├── .gitignore ├── res ├── icon.png └── preview.png ├── src ├── setting.json ├── css │ ├── login.css │ ├── sidebar.css │ ├── app.css │ ├── color.css │ ├── setting.css │ ├── chatpan.css │ ├── sidelist.css │ └── style.css ├── preload.js ├── config.html ├── main.js └── renderer.js ├── package.json ├── README.md ├── manifest.json └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /res/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stapxs/Stapxs-QQ-Lite-Theme/HEAD/res/icon.png -------------------------------------------------------------------------------- /src/setting.json: -------------------------------------------------------------------------------- 1 | { 2 | "color": "0", 3 | "bg": "", 4 | "opacity": 5 5 | } -------------------------------------------------------------------------------- /res/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stapxs/Stapxs-QQ-Lite-Theme/HEAD/res/preview.png -------------------------------------------------------------------------------- /src/css/login.css: -------------------------------------------------------------------------------- 1 | #login { 2 | background-color: var(--color-card-1); 3 | } 4 | #login canvas { 5 | display: none; 6 | } 7 | #login div.operation > span { 8 | color: var(--color-main); 9 | } 10 | 11 | .qq-logo-icon { 12 | display: none; 13 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bcui-theme", 3 | "private": true, 4 | "version": "1.0.6", 5 | "description": "", 6 | "main": "index.js", 7 | "scripts": {}, 8 | "keywords": [], 9 | "author": "Staps Steve", 10 | "license": "MIT", 11 | "devDependencies": {} 12 | } 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 |

Border Card UI Theme

3 |

4 | 一个轻便简洁的 LiteLoaderQQNT 主题 5 |
6 |
7 | 这是一个来自 Stapxs QQ Lite 2.0 第三方客户端样式的迁移版 8 |

9 |

10 | 11 | ![view](res/preview.png) 12 | 13 | ## 版本支持 14 | - LiteLoaderQQNT >= 1.2.0 15 | - NTQQ Build >= 27254 16 | 17 | ## 使用方法 18 | ### 使用仓库版本 19 | ~~~ 20 | git clone https://github.com/Stapxs/Stapxs-QQ-Lite-Theme.git 21 | ~~~ 22 | - 克隆仓库、下载分支 zip 或从仓库 Releases 发布页下载 zip 23 | - 将 zip 解压移动到 ```LiteLoaderQQNT``` plugins 目录下 24 | - 重启 QQ 25 | 26 | ## 反馈问题 27 | 因为我在使用 macOS,所以本主题优先适配 macOS;如果在其他平台遇到了奇怪的布局错误(包括主题色未生效)等问题,欢迎提交 issue! 28 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://github.com/LiteLoaderQQNT/Plugin-Template/raw/main/manifest_schema.json", 3 | "manifest_version": 4, 4 | "type": "theme", 5 | "name": "Border Card UI Theme", 6 | "slug": "border-card-ui-theme", 7 | "description": "Stapxs QQ Lite 2.0 Electron 版 LiteLoaderQQNT 迁移主题。", 8 | "version": "1.0.6", 9 | "icon": "./res/icon.png", 10 | "thumb": "./res/icon.png", 11 | "authors": [ 12 | { 13 | "name": "stapxs", 14 | "link": "https://github.com/Stapxs" 15 | } 16 | ], 17 | "platform": ["win32", "linux", "darwin"], 18 | "injects": { 19 | "renderer": "./src/renderer.js", 20 | "main": "./src/main.js", 21 | "preload": "./src/preload.js" 22 | }, 23 | "repository": { 24 | "repo": "Stapxs/Stapxs-QQ-Lite-Theme", 25 | "branch": "main" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/preload.js: -------------------------------------------------------------------------------- 1 | const { contextBridge, ipcRenderer } = require('electron') 2 | 3 | contextBridge.exposeInMainWorld('bcui_theme', { 4 | rendererReady: () => ipcRenderer.send('LiteLoader.bcui_theme.rendererReady'), 5 | updateStyle: (callback) => ipcRenderer.on('LiteLoader.bcui_theme.updateStyle', callback), 6 | updateTheme: (config) => ipcRenderer.on('LiteLoader.bcui_theme.updateTheme', config), 7 | setSetting: (k, v) => ipcRenderer.send('LiteLoader.bcui_theme.setSetting', k, v), 8 | 9 | logToMain: (...args) => ipcRenderer.send('LiteLoader.bcui_theme.logToMain', ...args), 10 | logToError: (...args) => ipcRenderer.send('LiteLoader.bcui_theme.logToError', ...args), 11 | 12 | getVersion: () => ipcRenderer.invoke('LiteLoader.bcui_theme.getVersion'), 13 | getSetting: () => ipcRenderer.invoke('LiteLoader.bcui_theme.getSetting'), 14 | getSettingHTML: () => ipcRenderer.invoke('LiteLoader.bcui_theme.getSettingHTML'), 15 | chooseImage: () => ipcRenderer.send('LiteLoader.bcui_theme.chooseImage') 16 | }) 17 | -------------------------------------------------------------------------------- /src/config.html: -------------------------------------------------------------------------------- 1 |
外观
2 |
3 |
4 | 主题色 5 | 13 |
14 |
15 |
16 |
背景图片
17 |
18 |
19 |
20 | 21 | 22 |
23 |
24 |
25 | 背景图模糊 26 | 27 |
28 |
-------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 huan_kong 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/css/sidebar.css: -------------------------------------------------------------------------------- 1 | /* 侧边栏 */ 2 | .sidebar { 3 | background: transparent !important; 4 | } 5 | .sidebar > nav { 6 | background: transparent !important; 7 | } 8 | .qq-logo, 9 | .sidebar__avatar { 10 | display: none !important; 11 | } 12 | 13 | .sidebar__nav div.tab-item > div.is-active { 14 | background: var(--color-main) !important; 15 | opacity: 1 !important; 16 | } 17 | .sidebar__nav div.tab-item > div.is-active:hover { /* 去除鼠标悬停颜色 */ 18 | background: var(--color-main) !important; 19 | opacity: 1 !important; 20 | } 21 | .sidebar__nav div.tab-item > div.is-active + div.tab-item-img { 22 | filter: brightness(0) invert(1); 23 | } 24 | /* 隐藏 .sidebar__nav > div 超过第二个的元素 */ 25 | /* .sidebar__nav > div:nth-child(n+3) { 26 | display: none !important; 27 | } */ 28 | 29 | /* 通话 */ 30 | .avatar--phone i { 31 | color: var(--color-font) !important; 32 | } 33 | .phone_bg { 34 | width: calc(100% - 5px) !important; 35 | border-radius: 7px !important; 36 | } 37 | .av-call-status { 38 | border: 1px solid var(--color-card-2) !important; 39 | background: var(--color-card-1) !important; 40 | width: calc(100% - 40px) !important; 41 | margin: 10px 20px 0 20px; 42 | border-radius: 7px; 43 | } 44 | 45 | @media (prefers-color-scheme: dark) { 46 | .sidebar__nav div.tab-item > div.is-active + div.tab-item-img { 47 | filter: brightness(0); 48 | } 49 | } -------------------------------------------------------------------------------- /src/css/app.css: -------------------------------------------------------------------------------- 1 | .q-button { 2 | background: var(--color-main); 3 | color: var(--color-font-r); 4 | border: unset; 5 | } 6 | .q-button:hover { 7 | background: var(--color-main) !important; 8 | opacity: 0.8; 9 | } 10 | .q-button.loading { 11 | background: var(--color-main) !important; 12 | opacity: 0.5; 13 | } 14 | 15 | .q-context-menu { 16 | min-width: 150px; 17 | } 18 | .q-context-menu > a { 19 | flex-direction: row-reverse; 20 | display: flex; 21 | } 22 | .q-context-menu > div > a > div { /* 有二级菜单的项的图标就不要了 */ 23 | display: none; 24 | } 25 | .q-context-menu > a > div { /* 有二级菜单的项的图标就不要了 */ 26 | margin-right: 10px; 27 | } 28 | .q-context-menu > div > a > span, 29 | .q-context-menu > a > span { 30 | margin-right: 10px; 31 | } 32 | .q-context-menu > a:hover { 33 | background: var(--color-main); 34 | color: var(--color-font-r); 35 | } 36 | .q-context-menu > a > div { 37 | margin-right: 0; 38 | } 39 | 40 | .q-notification { 41 | background: var(--color-card-1) !important; 42 | } 43 | 44 | .q-input { 45 | border-bottom: 2px solid var(--color-main) !important; 46 | border-radius: 7px !important; 47 | height: 32px; 48 | } 49 | 50 | .q-switch.is-active:hover, 51 | .q-switch.is-active { 52 | background: var(--color-main); 53 | } 54 | 55 | .q-empty-page { 56 | background: transparent; 57 | box-shadow: unset; 58 | } 59 | 60 | .q-svg-icon:hover { 61 | color: var(--color-main) !important; 62 | } 63 | 64 | /* =================================================== */ 65 | 66 | .container > div.tab-container { 67 | margin-left: -16px; 68 | } 69 | -------------------------------------------------------------------------------- /src/css/color.css: -------------------------------------------------------------------------------- 1 | @media (prefers-color-scheme: light) { 2 | :root { 3 | /* 卡片颜色 */ 4 | --color-bg: #F8F9FA; 5 | --color-card: #FFFFFF; 6 | --color-card-1: #F1F3F5; 7 | --color-card-2: #e3e8ec; 8 | 9 | --color-bg-rgb: 248, 249, 250; 10 | --color-card-rgb: 255, 255, 255; 11 | --color-card-1-rgb: 241, 243, 245; 12 | --color-card-2-rgb: 227, 232, 236; 13 | 14 | /* 字体颜色 */ 15 | --color-font: #50534F; 16 | --color-font-1: #5c5f5a; 17 | --color-font-2: #7d817c; 18 | 19 | /* 字体颜色(反转) */ 20 | --color-font-r: var(--color-bg); 21 | --color-font-1-r: var(--color-card); 22 | 23 | /* 阴影颜色 */ 24 | --color-shader: #72727240; 25 | 26 | /* 主题色 */ 27 | --color-main: #606E7A; 28 | 29 | /* 内置主题色*/ 30 | --color-main-0: #606E7A; 31 | --color-main-1: #92aa8a; 32 | --color-main-2: #f0a1a8; 33 | --color-main-3: #8076a3; 34 | --color-main-4: #f9a633; 35 | --color-main-5: #50534f; 36 | } 37 | } 38 | 39 | @media (prefers-color-scheme: dark) { 40 | :root { 41 | /* 卡片颜色 */ 42 | --color-bg: #2D2D2D; 43 | --color-card: #3A3A3A; 44 | --color-card-1: #494949; 45 | --color-card-2: #5F5F5F; 46 | 47 | --color-bg-rgb: 45, 45, 45; 48 | --color-card-rgb: 58, 58, 58; 49 | --color-card-1-rgb: 73, 73, 73; 50 | --color-card-2-rgb: 95, 95, 95; 51 | 52 | /* 字体颜色 */ 53 | --color-font: #FFFFFF; 54 | --color-font-1: #CFCFCF; 55 | --color-font-2: #B0B0B0; 56 | 57 | /* 字体颜色(反转) */ 58 | --color-font-r: var(--color-bg); 59 | --color-font-1-r: var(--color-card); 60 | 61 | /* 阴影颜色 */ 62 | --color-shader: #1010109c; 63 | 64 | /* 主题色 */ 65 | --color-main: #c8e5ff; 66 | 67 | /* 内置主题色*/ 68 | --color-main-0: #c8e5ff; 69 | --color-main-1: #d4ffcf; 70 | --color-main-2: #ffafaa; 71 | --color-main-3: #cdb7ff; 72 | --color-main-4: #f9d27d; 73 | --color-main-5: #bcbfc7; 74 | } 75 | } -------------------------------------------------------------------------------- /src/css/setting.css: -------------------------------------------------------------------------------- 1 | .liteloader > div img { 2 | width: 20px; 3 | height: 20px; 4 | } 5 | 6 | /* 覆盖原始设置样式 */ 7 | .setting-item-title { 8 | color: var(--color-font); 9 | font-weight: var(--font-bold); 10 | font-size: min(var(--font_size_3),18px); 11 | line-height: min(var(--line_height_3),24px); 12 | margin: 0px 0px 8px 16px; 13 | } 14 | .chat-page { 15 | background-color: var(--color-card); 16 | border-top-left-radius: 8px; 17 | border-top-right-radius: 8px; 18 | border-bottom-right-radius: 8px; 19 | border-bottom-left-radius: 8px; 20 | margin-bottom: 24px; 21 | padding: 0px 16px; 22 | } 23 | .chat-page__item { 24 | align-items: center; 25 | display: flex; 26 | justify-content: space-between; 27 | padding: 12px 0px; 28 | } 29 | 30 | /* 附加设置样式 */ 31 | .chat-page__item div.tips { 32 | color: var(--color-font-2); 33 | margin-top: 4px; 34 | font-size: min(var(--font_size_2) ,16px); 35 | line-height: min(var(--line_height_2) ,22px); 36 | } 37 | .chat-page__item > select { 38 | border: 1px solid var(--color-card-2); 39 | height: 24px; 40 | width: 150px; 41 | } 42 | .chat-page__item button.ss-button { 43 | margin: 5px; 44 | font-weight: normal; 45 | font-size: 0.7rem; 46 | height: 24px; 47 | width: 100px; 48 | } 49 | .chat-page__item input[type="range"] { 50 | -webkit-appearance: none; 51 | background: var(--color-card-1); 52 | height: 5px; 53 | border-radius: 5px; 54 | } 55 | .chat-page__item input[type="range"]::-webkit-slider-thumb, 56 | .chat-page__item input[type="range"]::-moz-range-thumb { 57 | -webkit-appearance: none; 58 | width: 20px; 59 | height: 20px; 60 | background: var(--color-main); 61 | border-radius: 50%; 62 | cursor: pointer; 63 | } 64 | 65 | /* 设置页面顶栏 */ 66 | .main-card { 67 | display: flex; 68 | flex-direction: row; 69 | align-items: stretch; 70 | overflow: hidden; 71 | margin-top: -10px; 72 | } 73 | .main-card > div.bg-left { 74 | width: calc(100px + 10%); 75 | background: var(--color-main); 76 | margin: -200px 0 -200px -100px; 77 | transform: rotate(30deg); 78 | border: 10px solid var(--color-card-2); 79 | } 80 | .main-card > div.bg-right { 81 | width: calc(100px + 10%); 82 | background: var(--color-main); 83 | margin: -200px -100px -200px 0; 84 | transform: rotate(30deg); 85 | border: 10px solid var(--color-card-2); 86 | } 87 | .info-card { 88 | display: flex; 89 | flex-direction: column; 90 | align-items: center; 91 | flex: 1; 92 | } 93 | .info-card > svg { 94 | height: 3rem; 95 | fill: var(--color-main); 96 | } 97 | .info-card > span { 98 | display: block; 99 | } 100 | .info-card > span.title { 101 | font-size: 1.1rem; 102 | color: var(--color-main); 103 | margin-top: 10px; 104 | } 105 | .info-card > span.title > span { 106 | font-size: 0.8rem; 107 | color: var(--color-font-2); 108 | } 109 | .info-card > a { 110 | color: var(--color-font-r); 111 | background: var(--color-main); 112 | padding: 3px 15px; 113 | border-radius: 5rem; 114 | margin-top: 5px; 115 | font-size: 0.8rem; 116 | } 117 | .info-copy { 118 | margin-bottom: 40px; 119 | } 120 | .info-copy > span { 121 | width: 100%; 122 | display: block; 123 | text-align: center; 124 | font-size: 0.8rem; 125 | margin-top: 5px; 126 | color: var(--color-font-2); 127 | } -------------------------------------------------------------------------------- /src/css/chatpan.css: -------------------------------------------------------------------------------- 1 | .two-col-layout__main { 2 | box-shadow: -5px 0 4px -5px var(--color-shader); 3 | background-size: cover !important; 4 | background: var(--color-card); 5 | margin-left: 5px; 6 | } 7 | .aio { 8 | background: rgba(var(--color-card-rgb), 0.3); 9 | } 10 | .aio .chat-input-area { 11 | background: var(--color-card-1); 12 | border-radius: 7px; 13 | padding: 10px 0px; 14 | margin: 20px; 15 | z-index: 9; 16 | } 17 | .send-btn-wrap { 18 | background: var(--color-main) !important; 19 | } 20 | 21 | .chat-header { 22 | margin: 20px; 23 | border-radius: 7px; 24 | display: flex !important; 25 | align-items: center !important; 26 | padding: 0 20px !important; 27 | background: rgba(var(--color-card-1-rgb),.8); 28 | backdrop-filter: blur(50px); 29 | z-index: 10; 30 | box-shadow: 0 0 5px var(--color-shader); 31 | border: none !important; 32 | } 33 | body[q-platform="win32"] .chat-header, 34 | body[q-platform="linux"] .chat-header { 35 | margin-top: 30px !important; 36 | } 37 | body[q-platform="darwin"] .chat-header { 38 | max-height: 100px !important; 39 | } 40 | 41 | .group-chat { 42 | margin-top: -20px; 43 | height: calc(100% + 20px) !important; 44 | } 45 | 46 | /* 消息 */ 47 | .message-content__wrapper > div { 48 | background: var(--color-card-1) !important; 49 | } 50 | .message-content__wrapper >div.container--self { 51 | background: var(--color-main) !important; 52 | color: var(--color-font-r) !important; 53 | } 54 | .message-content__wrapper >div.container--self span { 55 | color: var(--color-font-r) !important; 56 | } 57 | .message-content__wrapper >div.container--self div.reply-element { 58 | border-color: var(--color-font-r); 59 | } 60 | .chat-msg-area__tip--bottom { 61 | transform: translateY(10px); 62 | margin-right: 25px !important; 63 | } 64 | .chat-msg-area__tip--top > div.q-notification { 65 | transform: translateY(120%); 66 | margin-right: 25px; 67 | } 68 | .babble { 69 | background: var(--color-card-1) !important; 70 | } 71 | 72 | /* 群/好友信息栏 */ 73 | .side-panel { 74 | margin-top: 10px; 75 | height: calc(100vh - 110px) !important; 76 | border-radius: 7px; 77 | box-shadow: 0 0 5px var(--color-shader); 78 | } 79 | .side-panel > div.panel-content > div { 80 | padding: 5px 10px !important; 81 | background: var(--color-card); 82 | border-radius: 7px; 83 | } 84 | .group-member { 85 | background: var(--color-card-1) !important; 86 | } 87 | .group-panel > div:last-child { 88 | background: var(--color-card-1); 89 | margin-bottom: 20px; 90 | /* margin-right: 20px; */ 91 | width: 220px; 92 | } 93 | .group-panel div.group-box { 94 | border-radius: 7px; 95 | overflow: hidden; 96 | } 97 | 98 | /* 附加面板 */ 99 | .expression-panel-inner { 100 | margin-bottom: 10px; 101 | } 102 | .expression-panel-inner > div { 103 | box-shadow: 0 0 5px var(--color-shader) !important; 104 | background: var(--color-card-1) !important; 105 | } 106 | 107 | .sticker-panel { 108 | height: 300px !important; 109 | } 110 | .sticker-panel > div:last-child > div:first-child { 111 | height: 250px !important; 112 | } 113 | .sticker-panel div.tabs-container-item-active:hover, 114 | .sticker-panel div.tabs-container-item-active { 115 | background: var(--color-main); 116 | } 117 | .sticker-list-item { 118 | border: 2px solid var(--color-card-2); 119 | border-radius: 7px; 120 | margin-top: 5px; 121 | padding: 2px; 122 | } 123 | 124 | /* 输入框 */ 125 | .aio .chat-input-area { 126 | background: var(--color-card-1); 127 | border-radius: 7px; 128 | margin: 20px; 129 | z-index: 9; 130 | } 131 | 132 | @media (prefers-color-scheme: dark) { 133 | .sticker-panel div.tabs-container-item-active svg, 134 | .message-content__wrapper > div.container--self svg { 135 | filter: brightness(0); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/css/sidelist.css: -------------------------------------------------------------------------------- 1 | /* 侧边列表 */ 2 | 3 | .tab-container { 4 | background: transparent !important; 5 | } 6 | 7 | 8 | .recent-contact { 9 | background: none !important; 10 | } 11 | .recent-contact .viewport-list__inner { 12 | display: flex; 13 | flex-direction: column; 14 | gap: 8px; 15 | padding: 8px; 16 | } 17 | 18 | .recent-contact-list div.viewport-list__inner > div.recent-contact-item { 19 | border-radius: 7px; 20 | } 21 | .recent-contact-list div.viewport-list__inner > div.recent-contact-item > div { 22 | padding: 10px 15px !important; 23 | } 24 | body[q-theme="dark"][is-simple-theme="true"] .recent-contact-list div.viewport-list__inner > div.recent-contact-item--selected .item__content, 25 | .recent-contact-list div.viewport-list__inner > div.recent-contact-item--selected .item__content { 26 | background: var(--color-main) !important; 27 | } 28 | body[q-theme="dark"][is-simple-theme="true"] .recent-contact-list div.viewport-list__inner > div.recent-contact-item--selected .item__content div, 29 | .recent-contact-list div.viewport-list__inner > div.recent-contact-item--selected .item__content i, 30 | .recent-contact-list div.viewport-list__inner > div.recent-contact-item--selected .item__content div { 31 | color: var(--color-font-r) !important; 32 | } 33 | 34 | .radio-tab__item--background { 35 | background: var(--color-main) !important; 36 | } 37 | .radio-tab__item--selected { 38 | color: var(--color-font-r) !important; 39 | } 40 | 41 | .list-toggler { 42 | padding-top: 90px; 43 | pointer-events: none; 44 | } 45 | .list-toggler > div { 46 | pointer-events: all; 47 | } 48 | .list-toggler::before { 49 | color: var(--color-main) !important; 50 | margin-bottom: 10px; 51 | position: relative; 52 | margin-left: 20px; 53 | margin-top: -60px; 54 | font-weight: bold; 55 | text-wrap: nowrap; 56 | content: '信息'; 57 | } 58 | .list-toggler > div { 59 | margin-left: -45px; 60 | } 61 | .recent-contact-list, .group-assistent-list { 62 | padding-right: 4px; 63 | } 64 | .recent-contact-list::-webkit-scrollbar, /* 消息列表滚动条 */ 65 | .group-assistent-list::-webkit-scrollbar { 66 | display: none !important; 67 | } 68 | 69 | .contact-top-bar { 70 | margin-bottom: -100px; 71 | margin-top: 30px; 72 | } 73 | 74 | .list-item:hover { 75 | background-color: rgba(var(--color-card-1) 0.1) !important; 76 | } 77 | .list-item__container > div.list-item__content { 78 | padding: 10px !important; 79 | } 80 | .recent-contact-item .avatar { 81 | outline: 2px solid var(--color-card-2); 82 | border-radius: 7px !important; 83 | height: 33px !important; 84 | width: 33px !important; 85 | } 86 | 87 | .contact, 88 | .q-collapse-item__header, 89 | .contact div.tab-header { 90 | background: transparent !important; 91 | } 92 | .contact > div:last-child { 93 | margin-top: 25px; 94 | } 95 | .contact > div:last-child > div:first-child { 96 | margin-top: 40px; 97 | } 98 | .contact > div:last-child::before { 99 | content: '联系人'; 100 | font-weight: bold; 101 | margin-left: 20px; 102 | color: var(--color-main); 103 | } 104 | 105 | .q-collapse-item__icon { 106 | background: var(--color-main); 107 | height: 40%; 108 | width: 5px; 109 | border-radius: 7px; 110 | } 111 | .q-collapse-item__icon > i { 112 | display: none; 113 | } 114 | 115 | .main-search > div:nth-child(2) > div { 116 | box-shadow: 0 0 5px var(--color-shader); 117 | height: calc(100% - 100px) !important; 118 | margin-top: 30px; 119 | margin-left: 5%; 120 | overflow: hidden; 121 | width: calc(95% - 5px); 122 | background: var(--color-card-1); 123 | border-radius: 7px; 124 | padding-top: 10px; 125 | } 126 | 127 | .network-tip { 128 | top: 100%; 129 | position: absolute; 130 | width: 95%; 131 | transform: translateY(calc(-100% - 10px)); 132 | z-index: 11; 133 | border-radius: 7px; 134 | box-shadow: 0 0 5px var(--color-shader); 135 | } 136 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const path = require('path') 3 | const { BrowserWindow, ipcMain, dialog } = require('electron') 4 | 5 | const pluginPath = LiteLoader.plugins['border-card-ui-theme'].path.plugin.replaceAll('\\', '/') 6 | const dataPath = LiteLoader.plugins['border-card-ui-theme'].path.data.replaceAll('\\', '/') 7 | const settingPath = path.join(dataPath, 'setting.json').replaceAll('\\', '/') 8 | 9 | const log = (...args) => { 10 | console.log('\x1b[36m[bcui-theme]\x1b[0m', ...args) 11 | } 12 | const error = (...args) => { 13 | console.log('\x1b[31m[bcui-theme]\x1b[0m', ...args) 14 | } 15 | 16 | // 获取当前有哪些css 17 | const cssPath = path.join(__dirname, 'css') 18 | // 寻找这个文件夹下所有的 .css 后缀文件(包括子文件夹) 19 | function getAllCssFiles(dirPath, arrayOfFiles) { 20 | const files = fs.readdirSync(dirPath) 21 | 22 | arrayOfFiles = arrayOfFiles || [] 23 | 24 | files.forEach((file) => { 25 | const filePath = path.join(dirPath, file) 26 | if (fs.statSync(filePath).isDirectory()) { 27 | arrayOfFiles = getAllCssFiles(filePath, arrayOfFiles) 28 | } else if (file.endsWith('.css')) { 29 | arrayOfFiles.push(filePath) 30 | } 31 | }) 32 | 33 | return arrayOfFiles 34 | } 35 | 36 | const cssFiles = getAllCssFiles(cssPath) 37 | 38 | /* 39 | 主线程方法 ============================================== 40 | */ 41 | 42 | // 更新样式 43 | function updateStyle(webContents) { 44 | cssFiles.forEach((filePath) => { 45 | const data = fs.readFileSync(filePath, 'utf-8') 46 | const id = filePath.substring(filePath.lastIndexOf('\\') + 1, filePath.lastIndexOf('.')) 47 | webContents.send('LiteLoader.bcui_theme.updateStyle', id, data) 48 | }) 49 | } 50 | 51 | // 获取设置 52 | function getSetting() { 53 | try { 54 | log('正在获取全量设置……') 55 | let rawdata = fs.readFileSync(settingPath) 56 | return JSON.parse(rawdata) 57 | } catch (err) { 58 | error('获取全量设置失败:', err.toString()) 59 | return null 60 | } 61 | } 62 | // 设置设置 63 | function setSetting(k, v) { 64 | try { 65 | if (!k || v === undefined) { 66 | throw Error('k 或 v 为空') 67 | } 68 | let data = fs.readFileSync(settingPath, 'utf8') 69 | let setting = JSON.parse(data) 70 | setting[k] = v 71 | const updatedData = JSON.stringify(setting, null, 4) 72 | fs.writeFileSync(settingPath, updatedData, 'utf8') 73 | log('保存设置:' + k + ' -> ' + v + ' 成功') 74 | 75 | const nowConfig = getSetting() 76 | const window = BrowserWindow.getAllWindows() 77 | window.forEach((win) => { 78 | win.webContents.send('LiteLoader.bcui_theme.updateTheme', nowConfig) 79 | }) 80 | } catch (err) { 81 | error('设置设置失败:', err.toString()) 82 | } 83 | } 84 | 85 | function chooseImage() { 86 | dialog.showOpenDialog({ 87 | properties: ['openFile'], 88 | filters: [ 89 | { name: 'Images', extensions: ['jpg', 'png', 'gif', 'webp'] }, 90 | { name: 'All Files', extensions: ['*'] }, 91 | ], 92 | }) 93 | .then((result) => { 94 | try { 95 | let imagePath = result.filePaths[0] 96 | if (!imagePath) { 97 | return 98 | } 99 | // 将文件复制到 dataPath,名称固定为 bg.* 100 | const fileName = path.basename(imagePath) 101 | const image = fs.readFileSync(imagePath) 102 | const ext = path.extname(imagePath) 103 | const bgPath = path.join(dataPath, 'bg' + ext) 104 | // 如果文件存在就删掉它 105 | if (fs.existsSync(bgPath)) { 106 | fs.unlinkSync(bgPath) 107 | } 108 | fs.writeFileSync(bgPath, image) 109 | setSetting('bg', 'url("local:///' + bgPath + '")') 110 | setSetting('bgName', fileName) 111 | } catch (err) { 112 | error('chooseImage error', err.toString()) 113 | } 114 | }) 115 | .catch((err) => { 116 | error('chooseImage, error', err.toString()) 117 | }) 118 | } 119 | 120 | /* 121 | 主线程 IPC 事件 ============================================== 122 | */ 123 | 124 | ipcMain.on('LiteLoader.bcui_theme.rendererReady', (event, message) => { 125 | const window = BrowserWindow.fromWebContents(event.sender) 126 | updateStyle(window.webContents) 127 | }) 128 | ipcMain.on('LiteLoader.bcui_theme.logToMain', (_, ...args) => { 129 | log('[renderer]', ...args) 130 | }) 131 | ipcMain.on('LiteLoader.bcui_theme.logToError', (_, ...args) => { 132 | error('[renderer]', ...args) 133 | }) 134 | 135 | ipcMain.handle('LiteLoader.bcui_theme.getVersion', async () => { 136 | const data = fs.readFileSync(`${pluginPath}/manifest.json`, 'utf-8') 137 | return await JSON.parse(data).version 138 | }) 139 | ipcMain.handle('LiteLoader.bcui_theme.getSetting', async () => { 140 | return await getSetting() 141 | }) 142 | ipcMain.on('LiteLoader.bcui_theme.setSetting', (_, k, v) => { 143 | setSetting(k, v) 144 | }) 145 | ipcMain.handle('LiteLoader.bcui_theme.getSettingHTML', async () => { 146 | return fs.readFileSync(`${pluginPath}/src/config.html`, 'utf-8') 147 | }) 148 | ipcMain.on('LiteLoader.bcui_theme.chooseImage', () => { 149 | chooseImage() 150 | }) 151 | 152 | /* 153 | 主线程事件 ============================================== 154 | */ 155 | 156 | module.exports.onBrowserWindowCreated = (window) => { 157 | log('设置目录:' + settingPath) 158 | try { 159 | // 创建设置文件 160 | // 判断 setting.json 是否存在,不存在则创建 161 | if (!fs.existsSync(settingPath)) { 162 | log('初始化设置 -> ' + settingPath) 163 | fs.mkdirSync(dataPath, { recursive: true }) 164 | fs.copyFileSync(`${pluginPath}/src/setting.json`, settingPath) 165 | } 166 | } catch(ex) { 167 | error('初始化设置失败:', ex.toString()) 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /src/renderer.js: -------------------------------------------------------------------------------- 1 | const log = (...args) => { 2 | console.log('[bcui-theme]', ...args) 3 | bcui_theme.logToMain(...args) 4 | } 5 | const error = (...args) => { 6 | console.error('[bcui-theme]', ...args) 7 | bcui_theme.logToError(...args) 8 | } 9 | 10 | /* 11 | 渲染线程 IPC 事件 ============================================== 12 | */ 13 | 14 | // 刷新样式 15 | bcui_theme.updateStyle( async (event, id, data) => { 16 | let style = document.querySelector(`style[id="${id}"]`) 17 | 18 | if (!style) { 19 | style = document.createElement('style') 20 | style.id = id 21 | document.head.appendChild(style) 22 | } 23 | 24 | style.textContent = data 25 | }) 26 | bcui_theme.updateTheme( async (event, config) => { 27 | updateTheme(config) 28 | }) 29 | 30 | function updateTheme(config) { 31 | log('更新主题:' + JSON.stringify(config)) 32 | try { 33 | if(config) { 34 | if(config.color != undefined) { 35 | document.documentElement.style.setProperty('--color-main', 'var(--color-main-' + config.color + ')') 36 | const meta = document.getElementsByName('theme-color')[0] 37 | if(meta) { 38 | meta.content = getComputedStyle(document.documentElement) 39 | .getPropertyValue('--color-main-' + config.color) 40 | } 41 | } 42 | if(config.bg != undefined && config.bg.indexOf('url("local:///') == 0) { 43 | if(document.getElementsByClassName('two-col-layout__main')[0]) 44 | document.getElementsByClassName('two-col-layout__main')[0].style 45 | .background = config.bg 46 | } else { 47 | if(document.getElementsByClassName('two-col-layout__main')[0]) 48 | document.getElementsByClassName('two-col-layout__main')[0].style 49 | .background = 'var(--color-card)' 50 | } 51 | if(config.opacity && typeof config.opacity == 'number') { 52 | const list = [ 53 | document.getElementsByClassName('aio')[0], 54 | document.getElementsByClassName('empty-aio')[0], 55 | ] 56 | list.forEach((item) => { 57 | if(item) 58 | item.style.backdropFilter = `blur(${config.opacity}px)` 59 | }) 60 | } 61 | } 62 | } catch (err) { 63 | error('更新主题失败:', err.toString() + '\n' + err.stack) 64 | 65 | } 66 | } 67 | 68 | // 渲染线程初始化完成 69 | log('渲染线程初始化完成') 70 | error('渲染线程初始化完成') 71 | bcui_theme.rendererReady() 72 | 73 | try { 74 | if (location.pathname === '/renderer/index.html') { 75 | if (location.hash === '#/blank') { 76 | navigation.addEventListener( 77 | 'navigatesuccess', 78 | () => { 79 | if (location.hash.includes('#/main') || location.hash.includes('#/chat')) { 80 | onMessageCreate() 81 | } 82 | }, 83 | { once: true }, 84 | ) 85 | } else if (location.hash.includes('#/main') || location.hash.includes('#/chat')) { 86 | onMessageCreate() 87 | } 88 | } 89 | } catch (err) { 90 | error('main, ERROR', err.toString()) 91 | } 92 | 93 | /* 94 | 渲染线程事件 ============================================== 95 | */ 96 | 97 | export const onSettingWindowCreated = (view) => { 98 | onSettingCreate(view) 99 | } 100 | 101 | const onMessageCreate = async () => { 102 | const configs = await bcui_theme.getSetting() 103 | updateTheme(configs) 104 | } 105 | 106 | // 创建设置页面 107 | const onSettingCreate = async (view) => { 108 | log('创建设置页面') 109 | const version = await bcui_theme.getVersion() 110 | // 创建顶图 111 | const topHtml = `
112 |
113 |
114 | 115 | 117 | 118 | 119 | Border Card UI 120 | for LiteLoaderQQNT 121 | 122 | 一个更加轻便简洁的 LiteLoaderQQNT 主题 123 | ${version} 124 |
125 |
126 |
127 |
Copyright (C) ${new Date().getFullYear()} Stapx Steve [林槐]
` 128 | const topView = document.createElement('div') 129 | topView.innerHTML = topHtml 130 | view.appendChild(topView) 131 | try { 132 | // 添加设置主体 133 | const settingHtml = await bcui_theme.getSettingHTML() 134 | const configs = await bcui_theme.getSetting() 135 | updateTheme(configs) 136 | const settingView = document.createElement('div') 137 | settingView.innerHTML = settingHtml 138 | // 设置元素和保存操作 139 | Object.keys(configs).forEach(key => { 140 | const value = configs[key] 141 | const dom = settingView.querySelector(`[name="bcui-${key}"]`) 142 | log('设置元素:' + key + ' : ' + dom.type) 143 | // 设置元素值 144 | switch (dom.type) { 145 | case 'submit': { 146 | break 147 | } 148 | default: { 149 | dom.value = value 150 | break 151 | } 152 | } 153 | // 保存操作 154 | switch (dom.type) { 155 | case 'range': 156 | case 'select-one': { 157 | dom.addEventListener('change', () => { 158 | try { 159 | bcui_theme.setSetting(key, Number(dom.value)) 160 | updateSettingPage(view) 161 | } catch (err) { 162 | error('设置设置失败:', err.toString()) 163 | } 164 | }) 165 | break 166 | } 167 | case 'submit': { 168 | dom.addEventListener('click', () => { 169 | try { 170 | if(key == 'bg') { 171 | bcui_theme.chooseImage() 172 | } 173 | if(key == 'bgName') { 174 | bcui_theme.setSetting('bg', '') 175 | bcui_theme.setSetting('bgName', '') 176 | } 177 | updateSettingPage(view) 178 | } catch (err) { 179 | error('设置设置失败:', err.toString()) 180 | } 181 | }) 182 | break 183 | } 184 | } 185 | }) 186 | 187 | view.appendChild(settingView) 188 | updateSettingPage(view) 189 | } catch (err) { 190 | error('创建设置页面失败:', err.toString()) 191 | } 192 | } 193 | 194 | async function updateSettingPage(view) { 195 | const configs = await bcui_theme.getSetting() 196 | const bgName = view.getElementsByClassName('bcui-bg-name')[0] 197 | if(configs.bgName && configs.bgName != '') { 198 | bgName.innerText = configs.bgName 199 | view.getElementsByClassName('bcui-bgName')[0].style.display = 'block' 200 | } else { 201 | bgName.style.display = 'none' 202 | view.getElementsByClassName('bcui-bgName')[0].style.display = 'none' 203 | } 204 | } -------------------------------------------------------------------------------- /src/css/style.css: -------------------------------------------------------------------------------- 1 | input { 2 | caret-color: var(--color-main); 3 | color: var(--color-font); 4 | } 5 | 6 | .ss-code { 7 | background: var(--color-main); 8 | color: var(--color-font-r); 9 | border-radius: 7px; 10 | padding: 3px 10px; 11 | margin: 0 5px; 12 | } 13 | 14 | .ss-card { 15 | background-color: var(--color-card);; 16 | box-shadow:0 0 5px transparent; 17 | transition: box-shadow .3s; 18 | color: var(--color-font); 19 | border-radius: 7px; 20 | min-height: 40px; 21 | min-width: 40px; 22 | padding: 20px; 23 | } 24 | .ss-card div[class="ss-card"] { 25 | min-height: 65px; 26 | padding: 0; 27 | } 28 | .ss-card div[class="ss-card"] header { 29 | padding: 20px 0 0 20px; 30 | } 31 | .ss-card div[class="ss-card"] > button > svg { 32 | margin-right: 20px; 33 | margin-top: -25px; 34 | } 35 | .ss-card:hover { 36 | box-shadow:0 0 5px var(--color-shader); 37 | } 38 | .ss-card header { 39 | color: var(--color-font); 40 | letter-spacing: 0.1rem; 41 | padding-bottom: 10px; 42 | font-size: 1.02rem; 43 | font-weight: 300; 44 | text-indent: 0; 45 | } 46 | .ss-card header div:first-child { 47 | background: var(--color-main); 48 | margin-right: 20px; 49 | border-radius: 5px; 50 | height: 25px; 51 | float: left; 52 | width: 5px; 53 | } 54 | .ss-card header > i:first-child { 55 | color: var(--color-main); 56 | display: inline-block; 57 | margin-right: 10px; 58 | text-align: center; 59 | font-size: 1.1rem; 60 | min-width: 20px; 61 | } 62 | 63 | .ss-button { 64 | background: var(--color-main); 65 | color: var(--color-font-r); 66 | border-radius: 7px; 67 | font-size: 0.95rem; 68 | font-weight: 600; 69 | height: 33px; 70 | border: 0; 71 | } 72 | .ss-button:hover { 73 | opacity: 0.95; 74 | } 75 | .ss-button:focus { 76 | outline: none; 77 | } 78 | .ss-button:active { 79 | opacity: 0.9; 80 | } 81 | .ss-button:disabled { 82 | opacity: 0.4; 83 | } 84 | 85 | .ss-input { 86 | background: var(--color-card-1); 87 | border-radius: 7px; 88 | padding: 0 10px; 89 | font-size: 15px; 90 | height: 35px; 91 | border: 0; 92 | } 93 | .ss-input:focus { 94 | outline: 2px solid var(--color-card-1); 95 | } 96 | 97 | .ss-pop { 98 | -webkit-box-shadow: 0 0 5px var(--color-shader); 99 | -moz-box-shadow: 0 0 5px var(--color-shader); 100 | box-shadow: 0 0 5px var(--color-shader); 101 | background: var(--color-bg); 102 | } 103 | .ss-pop div[class="arrow"]:before { 104 | border: none; 105 | } 106 | .ss-pop div[class="arrow"]:after { 107 | border: none; 108 | } 109 | .ss-pop div { 110 | color: var(--color-font); 111 | } 112 | 113 | .ss-radio { 114 | --radio-size: 32px; 115 | 116 | height: var(--radio-size); 117 | margin-bottom: 0; 118 | } 119 | .ss-radio:hover > div:nth-child(2) { 120 | padding: calc((var(--radio-size) / 4) + 1px); 121 | } 122 | .ss-radio > div:nth-child(2) { 123 | padding: calc((var(--radio-size) / 4) + 2px); 124 | border-radius: var(--radio-size); 125 | background: var(--color-main); 126 | height: var(--radio-size); 127 | width: var(--radio-size); 128 | transition: padding .1s; 129 | } 130 | .ss-radio > div:nth-child(2) > div { 131 | background: #fff; 132 | border-radius: 100%; 133 | width: 100%; 134 | height: 100%; 135 | } 136 | .ss-radio input { 137 | display: none; 138 | } 139 | .ss-radio input:checked ~ div:nth-child(2) { 140 | padding: calc(var(--radio-size) / 4); 141 | } 142 | 143 | .ss-checkbox { 144 | --checkbox-size: 13px; 145 | margin-bottom: 0; 146 | display: flex; 147 | align-items: center; 148 | } 149 | .ss-checkbox > input { 150 | display: none; 151 | } 152 | .ss-checkbox > div { 153 | border: 1px solid var(--color-font); 154 | border-radius: 30%; 155 | background: transparent; 156 | transition: background .3s, border .1s; 157 | height: var(--checkbox-size); 158 | width: var(--checkbox-size); 159 | } 160 | .ss-checkbox > input:checked ~ div { 161 | background: var(--color-bg); 162 | border: calc(var(--checkbox-size) / 3) solid var(--color-main); 163 | } 164 | .ss-checkbox > span { 165 | margin-left: 10px; 166 | font-size: 0.9rem; 167 | } 168 | .ss-checkbox.button { 169 | border: 2px solid var(--color-main); 170 | border-radius: 7px; 171 | background: transparent; 172 | padding: 10px 15px; 173 | } 174 | .ss-checkbox.button > div { 175 | border: 0 !important; 176 | max-width: 5px; 177 | border-radius: 5px; 178 | transform: scaleY(0); 179 | background: var(--color-main) !important; 180 | transition: transform .3s; 181 | } 182 | .ss-checkbox.button > input:checked ~ div { 183 | transform: scaleY(1); 184 | } 185 | 186 | .ss-switch { 187 | --switch-dot-border: 4px; 188 | --switch-dot-margin: 5px; 189 | --switch-height: 30px; 190 | min-width: 55px; 191 | margin-bottom: 0; 192 | } 193 | .ss-switch > div { 194 | border-radius: var(--switch-height); 195 | background: var(--color-card-1); 196 | height: var(--switch-height); 197 | transition: background .4s; 198 | width: 100%; 199 | } 200 | .ss-switch > div > div { 201 | transition: margin-left .3s cubic-bezier(0.85, 0, 0.12, 0.99), border .2s; 202 | border-radius: calc(var(--switch-height) - (var(--switch-dot-margin) * 2)); 203 | height: calc(var(--switch-height) - (var(--switch-dot-margin) * 2)); 204 | width: calc(var(--switch-height) - (var(--switch-dot-margin) * 2)); 205 | border: var(--switch-dot-border) solid #fff; 206 | box-shadow:0 0 5px var(--color-shader); 207 | margin-left: var(--switch-dot-margin); 208 | margin-top: var(--switch-dot-margin); 209 | background: var(--color-main); 210 | float: left; 211 | } 212 | .ss-switch input { 213 | display: none; 214 | } 215 | .ss-switch input:checked ~ div { 216 | background: var(--color-main); 217 | } 218 | .ss-switch input:checked ~ div > div { 219 | border: calc((var(--switch-height) - var(--switch-dot-margin) * 2) / 2 + 0.5px) solid #fff; 220 | margin-left: calc(100% - var(--switch-height) + var(--switch-dot-margin)); 221 | } 222 | 223 | .ss-code-input { 224 | flex-direction: initial; 225 | justify-content: center; 226 | padding-top: 30px; 227 | display: flex; 228 | } 229 | .ss-code-input input { 230 | background: var(--color-card-1); 231 | outline: 2px solid transparent; 232 | caret-color: transparent; 233 | transition: outline .3s; 234 | border-radius: 7px; 235 | text-align: center; 236 | font-size: 1.5rem; 237 | margin: 0 10px; 238 | height: 60px; 239 | width: 60px; 240 | border: 0; 241 | } 242 | .ss-code-input input:first-child { 243 | padding: 0; 244 | margin: 0; 245 | height: 0; 246 | width: 0; 247 | } 248 | .ss-code-input-selete { 249 | outline: 2px solid var(--color-main) !important; 250 | } 251 | .ss-code-input-err { 252 | outline: 2px solid #ef5f5f !important; 253 | } 254 | 255 | .ana-card { 256 | color: var(--color-font); 257 | text-align: center; 258 | font-size: 0.9rem; 259 | font-weight: 100; 260 | display: flex; 261 | height: 60px; 262 | } 263 | .ana-card div { 264 | background: var(--color-main); 265 | border-radius: 5px; 266 | height: 100%; 267 | width: 5px; 268 | } 269 | .ana-card span { 270 | width: 100%; 271 | } 272 | .ana-card-left { 273 | text-align: left; 274 | } 275 | 276 | footer > div:first-child { 277 | color: var(--color-font); 278 | margin-bottom: 20px; 279 | } 280 | footer > div:first-child > span { 281 | margin-left: 20px; 282 | font-size: 0.7rem; 283 | } 284 | footer > div:last-child { 285 | margin-bottom: 10px; 286 | text-align: center; 287 | margin-top: -10px; 288 | font-size: 0.7rem; 289 | } 290 | footer > div:last-child span a { 291 | color: var(--color-font-1); 292 | } 293 | footer header { 294 | color: var(--color-main); 295 | } 296 | footer header span { 297 | color: var(--color-font-1); 298 | font-size: 0.7rem; 299 | margin-left: 10px; 300 | } 301 | 302 | .cls-1 { 303 | fill: var(--color-card-1); 304 | } 305 | 306 | .bar-search { 307 | border: 0; 308 | height: 35px; 309 | font-size: 15px; 310 | margin-right: 0 !important; 311 | background: var(--color-card-1); 312 | } 313 | .bar-search:focus { 314 | background: var(--color-card-1); 315 | outline: none; 316 | 317 | -webkit-box-shadow:0 0 5px var(--color-shader); 318 | -moz-box-shadow:0 0 5px var(--color-shader); 319 | box-shadow:0 0 5px var(--color-shader); 320 | } 321 | 322 | .avatar { 323 | cursor: hand; 324 | overflow: hidden; 325 | --main-size: 33px; 326 | margin-right: 5px; 327 | width: var(--main-size); 328 | height: var(--main-size); 329 | border-radius: var(--main-size); 330 | background: var(--color-card-1); 331 | } 332 | .avatar img { 333 | width: var(--main-size); 334 | height: var(--main-size); 335 | } 336 | 337 | .user-name { 338 | display: none; 339 | } 340 | 341 | .scroll-top { 342 | border-top: 1px dashed var(--color-main); 343 | margin: 0 30px; 344 | } 345 | 346 | pre { 347 | background: transparent !important; 348 | overflow: visible !important; 349 | padding: 0 !important; 350 | } 351 | pre:before { 352 | display: none !important; 353 | } 354 | pre:after { 355 | display: none !important; 356 | } 357 | pre > code { 358 | font-family: 'Fira Code', monospace !important; 359 | padding: 1rem !important; 360 | } 361 | @supports (font-variation-settings: normal) { 362 | pre > code 363 | { 364 | font-family: 'Fira Code VF', monospace !important; 365 | } 366 | } 367 | pre[class*=language-]>code { 368 | border-left: 0px solid var(--color-main) !important; 369 | background-color: var(--color-card-2) !important; 370 | background-image: none !important; 371 | border-left: 10px solid #358ccb; 372 | background-origin: content-box; 373 | background-attachment: local; 374 | box-shadow: none !important; 375 | background-size: 3em 3em; 376 | margin-bottom: -75px; 377 | border-radius: 7px; 378 | position: relative; 379 | margin-top: -10px; 380 | z-index: 1; 381 | } 382 | code[class*=language-] { 383 | max-height: inherit; 384 | font-size: 0.8rem; 385 | height: inherit; 386 | padding: 0 1em; 387 | display: block; 388 | overflow: auto; 389 | } 390 | 391 | .about-text { 392 | padding: 20px; 393 | } 394 | .about-text i { 395 | color: var(--color-font-1); 396 | margin-bottom: 10px; 397 | font-style: normal; 398 | font-size: 0.9rem; 399 | font-weight: 400; 400 | text-indent: 2em; 401 | display: block; 402 | } 403 | .about-text a { 404 | color: var(--color-font); 405 | font-weight: bold; 406 | } 407 | .no-indent i { 408 | text-indent: 0; 409 | } 410 | 411 | ::-webkit-scrollbar-thumb { 412 | background: var(--color-main); 413 | border-radius: 6px; 414 | } 415 | ::-webkit-scrollbar { 416 | background-color:transparent; 417 | width:6px; 418 | } 419 | ::-webkit-scrollbar-button { 420 | display: none; 421 | } 422 | 423 | @media screen and (max-width: 992px) { 424 | .avatar { 425 | width: auto; 426 | height: auto; 427 | border-radius: 0; 428 | background: none; 429 | } 430 | .avatar img { 431 | display: none; 432 | } 433 | 434 | .bar-search { 435 | display: none !important; 436 | } 437 | 438 | .user-name { 439 | display: unset; 440 | cursor: pointer; 441 | color: var(--color-font-1); 442 | } 443 | .user-name:hover { 444 | color: var(--color-font); 445 | opacity: 0.7; 446 | } 447 | } 448 | 449 | .navbar-dark .navbar-brand { 450 | color: var(--color-font) !important; 451 | } 452 | 453 | .navbar-dark .navbar-nav .nav-link.active { 454 | color: var(--color-font) !important; 455 | } 456 | 457 | .navbar-dark .navbar-nav .nav-link { 458 | color: var(--color-font-1) !important; 459 | } 460 | .navbar-dark:hover .navbar-nav:hover .nav-link:hover { 461 | color: var(--color-font) !important; 462 | opacity: 0.7 !important; 463 | } --------------------------------------------------------------------------------