本文提及的存储库:oplist-beautification

前言

如你所见,本文是一个openlist的美化教程。鉴于截至本文完成时,openlist还只有beta版,大概能明白这个项目目前知名度不算太高(所以这篇文章恐怕成了第一篇openlist美化教程。事实上,即使是关于它的其他资料也很少)),因此先介绍一下它的本体。

openlist是什么?

openlist是在知名开源网盘列表程序alist在被出售给商业公司(趋势)后,其部分贡献者另起炉灶而诞生的一个项目。

alist-soldout

美化代码

废话太多…贴上代码!同alist,将代码填入 设置/全局/的相应位置

自定义内容(核心科技)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
<!-- v3 -->

<!-- 修正部分区域的透明 -->
<style>
.hope-ui-light,
.hope-ui-dark {
--hope-colors-background: transparent;
}
</style>

<script type="module">
// v3

// 提供用来监听代码控制的 url 变化的事件
(() => {
const wrapHistoryMethod = (type) => {
const orig = history[type];
return function (...args) {
const rv = orig.apply(this, args);
const event = new CustomEvent(type, { detail: args });
window.dispatchEvent(event);
return rv;
};
};
history.pushState = wrapHistoryMethod('pushState');
history.replaceState = wrapHistoryMethod('replaceState');
})();

class Beautifier {
/**
* Beautifier 类用于美化页面背景色
*
* 其提供了3个方法:
* - observe: 开始监听页面变化并美化背景色
* - disconnect: 停止监听页面变化
* - undo: 恢复页面背景色到默认状态
*
* 可以通过window.beautifier访问实例对象
*
*/
static ignoredSelectors = [
'.hope-tooltip',
'.hope-tooltip__arrow',
'.hope-checkbox__control',
'.hope-modal__overlay',
'button:not(.hope-menu__trigger)',
'svg'
];

static getSelector(mainSelector) {
return `${mainSelector} :not(${Beautifier.ignoredSelectors.join('):not(')})`;
}

static lightSelector = Beautifier.getSelector('.hope-ui-light');
static darkSelector = Beautifier.getSelector('.hope-ui-dark');

static lightBgColor = 'rgba(255, 255, 255, 0.8)';
static darkBgColor = 'rgb(32, 36, 37)';

static specificPrefix = 'rgba(132, 133, 141';

constructor() {
this.observer = null;
}

/**
* @param {'light'|'dark'} theme
*/
#rewriteBgColor(theme) {
let selector = theme === 'light' ? Beautifier.lightSelector : Beautifier.darkSelector;
let bgColor = theme === 'light' ? Beautifier.lightBgColor : Beautifier.darkBgColor;

document.querySelectorAll(selector).forEach(element => {
const computedStyle = getComputedStyle(element);

if (computedStyle.backgroundImage !== 'none') {
return;
}

if (computedStyle.backgroundColor !== 'rgba(0, 0, 0, 0)' &&
!computedStyle.backgroundColor.startsWith(Beautifier.specificPrefix)) {
element.style.backgroundColor = bgColor;
element.setAttribute('data-beautified', 'true');
}
});
}

#beautify() {
if (!location.pathname.startsWith('/@manage') && !location.pathname.startsWith('/@login')) {
this.#rewriteBgColor('light');
this.#rewriteBgColor('dark');
}
}

observe() {
this.observer = new MutationObserver(this.#beautify.bind(this));
this.observer.observe(document.getElementById('root'), {
childList: true,
subtree: true
});

this.#beautify();
}

disconnect() {
if (this.observer) {
this.observer.disconnect();
}
}

undo() {
this.disconnect();

document.body.querySelectorAll('[data-beautified]').forEach(element => {
element.style.backgroundColor = '';
element.removeAttribute('data-beautified');
});
}
}

const beautifier = new Beautifier();
window.beautifier = beautifier;

beautifier.observe();

// 一个愚蠢到有点无敌的修复机制,不过工作良好
(() => {
function fixLogin(pathname) {
if (pathname.startsWith('/@login')) {
beautifier.undo();
}
else {
beautifier.disconnect();
beautifier.observe();
}
}

['popstate', 'pushState', 'replaceState'].forEach(eventType => {
addEventListener(eventType, () => {
fixLogin(location.pathname);
});
});
})();
</script>

自定义头部(想用就用)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<!-- v1 -->

<!-- 引入自定义字体 -->
<link rel="stylesheet" href="https://s4.zstatic.net/ajax/libs/lxgw-wenkai-webfont/1.7.0/lxgwwenkai-regular.min.css">

<style>
/* 移除原生视频控件 */
video::-webkit-media-controls {
display: none;
}

/* 设置背景图片样式 */
body {
background-repeat: no-repeat;
background-size: cover;
background-attachment: fixed;
background-position: center;
}

/* 在此处的url()里修改背景图片地址 */
/* 加了个深色遮罩,爱护你的眼睛 */
body.hope-ui-dark {
background-color: rgb(32, 36, 37);
background-image: linear-gradient(rgba(32, 36, 37, 0.8), rgba(32, 36, 37, 0.8)), url('https://t.alcy.cc/moez');
}

/* 在此处的url()里修改背景图片地址 */
body.hope-ui-light {
background-image: url('https://t.alcy.cc/moez');
}

/* 统一站点公告的样式 */
.hope-ui-light .hope-c-PJLV-ikJQsXT-css {
background: rgba(255, 255, 255, 0.8) !important;
backdrop-filter: blur(0) !important;
}

.hope-ui-dark .hope-c-PJLV-ikJQsXT-css {
background: rgb(32, 36, 37) !important;
backdrop-filter: blur(0) !important;
}

/* 自定义字体 */
* {
font-family: "LXGW WenKai", sans-serif;
}
</style>

<!-- 看板娘 -->
<script>if (localStorage.getItem('modelId') === null) {
localStorage.setItem('modelId', '9'); // 设置默认模型ID
localStorage.setItem('modelTexturesId', '0'); // 设置默认皮肤ID
}
</script>
<script src="https://cdn.mmoe.work/live2d-widget/autoload.js"></script>

<script src="https://s4.zstatic.net/ajax/libs/js-polyfills/0.1.43/polyfill.min.js?features=String.prototype.replaceAll"></script>

通过cdn引入

只适用于只打算美化元素背景色,已有其他美化的读者

1
<script type="module" src="https://fastly.jsdelivr.net/gh/adogecheems/alist-beautification@latest/src/beautifier.js"></script>

效果

表现完美(我还专门跑去用openlist试了一下):

final-result

需要说明的部分

好吧,我得承认,openlist与原版项目alist目前是没有任何显而易见的区别的,特别是在前端方面。所以以前的alist美化代码,现在其实是可以在openlist上正常工作的。

那么这篇文章的意义是什么?

为什么我仍打算写这篇文章呢(是为了凑热度),是因为我提出的这种美化方案(一开始载于一劳永逸的alist美化方案)是基于动态observe原理的,具有较高的泛用性,在以后openlist的持续更新中会更为省心。

如果你使用过传统的alist美化代码,想必你遇到过版本一更新,美化的样式就出现一些扎眼的不协调部分的问题,这通常是类名发生变化导致的。而我确信这个美化方案即使在多次版本更新之后,仍然能保持良好的工作。

因此

我希望在新项目openlist诞生后,其主流的美化方式是这种新的方案,所以重新写了一篇文章来介绍。

最后的碎碎念

推荐在我的存储库获得后续代码优化,如果可以的话,就请点个star支持一下吧!