efront 4.14.0 → 4.14.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,35 @@
1
+ - zh-CN: 未知错误!
2
+ en: Unknown error!
3
+
4
+ - zh-CN: 文件系统
5
+ en: file system
6
+
7
+ - zh-CN: 网络
8
+ en: network
9
+
10
+ - zh-CN: 无法访问$1
11
+ en: Unable to access $1
12
+
13
+ - zh-CN: Cookie解析异常!
14
+ en: Cookie parsing exception!
15
+
16
+ - zh-CN: 数据无法解析!
17
+ en: Data cannot be parsed!
18
+
19
+ - zh-CN: 无法连接可加密的服务器!
20
+ en: Unable to connect to an encrypted server!
21
+
22
+ - zh-CN: 无可用的数据源
23
+ en: No available data source
24
+
25
+ - zh-CN: 通道不存在!
26
+ en: The channel does not exist!
27
+
28
+ - zh-CN: 服务器忙!
29
+ en: The server is busy!
30
+
1
31
  - zh-CN: $1不是有效的色彩信息
2
- en: $1 is not a valid color
32
+ en: $1 is not a valid color
3
33
 
4
34
  - zh-CN: 加载失败
5
35
  en: Loading failed
@@ -143,16 +143,22 @@ function cross_(jsonp, digest = noop, method, url, headers) {
143
143
  var onerror1 = function (e) {
144
144
  if (!~requests.indexOf(_xhr)) return;
145
145
  removeFromList(requests, _xhr);
146
- errored = e || "未知错误!";
146
+ errored = e || i18n`未知错误!`;
147
147
  if (typeof errored === 'string') {
148
148
  errored = createResponse(e, xhr.status);
149
149
  }
150
150
  flush();
151
151
  digest();
152
152
  };
153
+ var getErrorSystem = function () {
154
+ if (!/^(\w+\:|\/\/)/.test(url) && /^file\:/i.test(location.href) || /^file\:/i.test(url)) return i18n`文件系统`;
155
+ if (navigator.onLine) return i18n`网络`;
156
+ return i18n`服务器`;
157
+ };
158
+
153
159
  var onerror = async function (e) {
154
160
  if (e.type === 'error') {
155
- e = createResponse("无法访问服务器!");
161
+ e = createResponse(i18n`无法访问${getErrorSystem()}`);
156
162
  }
157
163
  headers = extend({}, _headers);
158
164
  for (var r of reforms) {
@@ -212,7 +218,7 @@ function cross_(jsonp, digest = noop, method, url, headers) {
212
218
  if (isencrypt) cookie = encode62.safedecode(cookie, xhr.encrypt);
213
219
  }
214
220
  catch (e) {
215
- onerror({ status: xhr.status, response: "Cookie解析异常!", toString: toResponse });
221
+ onerror({ status: xhr.status, response: i18n`Cookie解析异常!`, toString: toResponse });
216
222
  return;
217
223
  }
218
224
  cookie_.addCookie(cookie, originDomain);
@@ -233,13 +239,13 @@ function cross_(jsonp, digest = noop, method, url, headers) {
233
239
  xhr.responseText = xhr.response;
234
240
  }
235
241
  catch (e) {
236
- return onerror("数据无法解析!")
242
+ return onerror(i18n`数据无法解析!`);
237
243
  }
238
244
  };
239
245
  switch (xhr.status) {
240
246
  case 0:
241
247
  if (!xhr.response) {
242
- onerror("无法访问服务器");
248
+ onerror(i18n`无法访问${getErrorSystem()}`);
243
249
  break;
244
250
  }
245
251
  case 200:
@@ -493,7 +499,7 @@ function addReform(r) {
493
499
  function getCode() {
494
500
  return new Promise((ok, oh) => {
495
501
  this('get', base + "!").then((xhr) => { return ok(encode62.timedecode(xhr.response || xhr.responseText)) }, () => {
496
- return oh('无法连接可加密的服务器!');
502
+ return oh(i18n`无法连接可加密的服务器!`);
497
503
  });
498
504
  });
499
505
  }
@@ -816,7 +816,9 @@ var data = {
816
816
  }
817
817
  },
818
818
  fromAll(refs, params, parse) {
819
- return this.createResponse(Promise.all(refs.map(r => this.from(r, params, parse))).then(datas => {
819
+ return this.createResponse(Promise.all(refs.map(r => this.from(r, params, parse).loading_promise.catch(e => []))).then(datas => {
820
+ datas = datas.filter(a => !!a);
821
+ if (!datas.length) throw new Error(i18n`无可用的数据源`);
820
822
  return datas.concat.apply([], datas);
821
823
  }));
822
824
  },
@@ -488,14 +488,28 @@ var Method = function () {
488
488
  return body;
489
489
  }
490
490
  var vlist = [], mlist = [macros], clist = [], base = '';
491
+ var killneg = function (v, n) {
492
+ if (n === "-") {
493
+ if (/^\-/.test(v)) {
494
+ v = v.slice(1);
495
+ }
496
+ else {
497
+ v = n + v;
498
+ }
499
+ }
500
+ return v;
501
+ };
491
502
  var calcvars = function (v) {
492
503
  var decode = /^['"`]/.test(v) ? strings.decode : a => a;
493
- return v.replace(/@[^\s\{\}\(\)\[\]\:\+\*\/,;\!\>\$\=\&\%\#\@'"`\?\.\/\|~#]+|@\{[^\}@]*\}/g, function (m) {
504
+ return v.replace(/(^\-)?(@[^\s\{\}\(\)\[\]\:\+\*\/,;\!\>\$\=\&\%\#\@'"`\?\.\/\|~#]+|@\{[^\}@]*\})/g, function (_, n, m) {
494
505
  var value = getFromScopeList(m, vlist, m);
495
506
  value = decode(value);
507
+ value = killneg(value, n);
496
508
  return value;
497
- }).replace(/(^|\s|[\]\)\(\[\-\+\*\/,;])(?:var\s*\(([\s\S]*?)\)|(--\S+))/g, function (m, q, a, b) {
498
- return q + getFromScopeList(b || a.trim(), vlist, m.slice(q.length));
509
+ }).replace(/(^|\s|[\]\)\(\[\+\*\/,;]|^\-)(?:var\s*\(([\s\S]*?)\)|(--\S+))/g, function (m, q, a, b) {
510
+ var v = getFromScopeList(b || a.trim(), vlist, m.slice(q.length));
511
+ v = killneg(v, q);
512
+ return v;
499
513
  });
500
514
  };
501
515
  var initvars = function (vars) {
@@ -86,6 +86,7 @@ assert(素馨(`a{a:extract(2,3,2)}`), `a{a:3;}`);
86
86
  assert(素馨(`a{a:extract(2 3,2)}`), `a{a:3;}`);
87
87
  assert(素馨(`value: range(10px, 30px, 10);`, '', true), `value:10px 20px 30px;`);
88
88
  assert(素馨(`value: range(4);`, '', true), `value:1 2 3 4;`);
89
+ assert(素馨(`@a:-1;b{a:-@a}`, '', true), `b{a:1;}`);
89
90
  assert(scanner2(`-0.2em .3em -0.2em 0`, new 素馨.素心)[0].text, '-0.2em');
90
91
  assert(scanner2(`-0.2em .3em -0.2em 0`, new 素馨.素心)[0].isdigit, true);
91
92
  assert(scanner2(`-0.2em .3em -0.2em 0`, new 素馨.素心)[2].text, ".3em");
@@ -1,4 +1,5 @@
1
1
  var activeDevice, ratio = 1;
2
+ var strokeColor = '#096';
2
3
  function line(buffer, style, lineWidth = window.devicePixelRatio || 1) {
3
4
  var canvas = this;
4
5
  var context = canvas.getContext("2d");
@@ -27,7 +28,7 @@ function line(buffer, style, lineWidth = window.devicePixelRatio || 1) {
27
28
  var [x, y] = buffer[cx];
28
29
  context.lineTo(x * width, y * height);
29
30
  }
30
- context.strokeStyle = style || "#00bd7bd4";
31
+ context.strokeStyle = style || strokeColor;
31
32
  context.lineWidth = lineWidth;
32
33
  context.stroke();
33
34
  }
@@ -69,7 +70,7 @@ function draw(buffer) {
69
70
  if (canvas.height !== canvas.offsetHeight * devicePixelRatio) canvas.height = canvas.offsetHeight * devicePixelRatio;
70
71
  context.clearRect(0, 0, canvas.width, canvas.height);
71
72
  context.beginPath();
72
- context.strokeStyle = "#00bd7bd4";
73
+ context.strokeStyle = strokeColor;
73
74
  context.lineWidth = window.devicePixelRatio || 1;
74
75
  var max = 2;
75
76
  var v = (this.volume >= 0 ? this.volume : 1) * buffer.length - .5;
@@ -91,7 +92,7 @@ function draw(buffer) {
91
92
  }
92
93
  });
93
94
  context.lineWidth = 1;
94
- context.strokeStyle = "#00bd7bd4";
95
+ context.strokeStyle = strokeColor;
95
96
  context.stroke();
96
97
  if (this === activeDevice) {
97
98
  context.beginPath();
@@ -9,7 +9,8 @@ var isSameSong = function (m1, m2) {
9
9
  m1.hash && m1.hash === m2.hash || // 酷狗
10
10
  m1.id && m1.id === m2.id || // 网易云 千千静听
11
11
  m1.rid && m1.rid === m2.rid || // 酷我
12
- m1.mid && m1.mid === m2.mid; // 酷我
12
+ m1.mid && m1.mid === m2.mid ||// 酷我
13
+ m1.url && m1.url === m2.url;
13
14
  };
14
15
 
15
16
  function addMethod(name, func) {
@@ -6,8 +6,6 @@
6
6
  right: 0;
7
7
  max-width: 460px;
8
8
  box-shadow: 0 0 20px -6px rgba(0, 0, 0, .6);
9
- margin-bottom: 10px;
10
- overflow: visible;
11
9
  background: #131416;
12
10
  margin-top: 0;
13
11
  transition: margin .2s ease-out;
@@ -5,21 +5,18 @@
5
5
  </div>
6
6
  <div class="track"></div>
7
7
  <div class="avatar" ng-style="{'background-image': info.avatarUrl,transform:currentRotate}"></div>
8
- <div class="info">
9
- <div class="time">
10
- <span ng-bind="currentTime"></span>&nbsp;/&nbsp;
11
- <span ng-bind="totalTime"></span>
12
- </div>
13
- <div class="song">
14
- <span class="name" ng-bind=getSongName()></span>
15
- <span class="spliter" ng-if="getSongName()&&getSingerName()">&nbsp;-&nbsp;</span>
16
- <span class="singer" ng-bind=getSingerName()></span>
17
- </div>
8
+ <btn class="play"></btn>
9
+ <div class="time">
10
+ <span ng-bind="currentTime"></span>
18
11
  </div>
12
+ <div class="total">
13
+ <span ng-bind="totalTime"></span>
14
+ </div>
15
+ <div class="song" ng-bind=getSongName()></div>
16
+ <div class="singer" ng-bind=getSingerName()></div>
19
17
  <btn class="prev" ng-click=play(index-1)></btn>
20
- <btn class="play" ng-click="playing?pause():play()"></btn>
21
18
  <btn class="next" ng-click=play(index+1)></btn>
22
- <sbtn class="list"></sbtn>
19
+ <!-- <sbtn class="list"></sbtn> -->
23
20
  <krc elementid=krcpad></krc>
24
21
  <canvas elementid="dance"></canvas>
25
- <div class="avatar" ng-click="effectPage()"></div>
22
+ <div class="avatar" ng-click="playing?pause():play()" ng-click="effectPage()"></div>
@@ -37,6 +37,7 @@ var patchMusicInfo = async function (info) {
37
37
  info.songName = info.songname;
38
38
  break;
39
39
  case "kugo":
40
+ default:
40
41
  if (info.hash) {
41
42
  res = await data.from("song-info", info);
42
43
  krc = await data.from("search-krc", res);
@@ -208,8 +209,12 @@ var $scope = {
208
209
  var { sin, cos } = Math;
209
210
  var { currentTheta } = $scope;
210
211
  if (player.offsetHeight <= calcPixel(80)) {
211
- var centerx = 44 / width, centery = .5;
212
- var start = 11 * ratio | 0, end = 77 * ratio | 0;
212
+ var avatar = player.querySelector(".avatar");
213
+ var { clientTop, clientWidth, offsetLeft } = avatar;
214
+ var offsetWidth = clientWidth;
215
+ offsetLeft += clientTop;
216
+ var centerx = (offsetWidth / 2 + offsetLeft) / width, centery = .5;
217
+ var start = offsetLeft * ratio | 0, end = (offsetLeft + offsetWidth) * ratio | 0;
213
218
  var cost = cos(currentTheta);
214
219
  var sint = sin(currentTheta);
215
220
  for (var cx = start, dx = end; cx < dx; cx++) {
@@ -431,6 +436,13 @@ var createControls = function () {
431
436
  };
432
437
 
433
438
  var player = function (player) {
439
+ var savatar = player.querySelector('canvas');
440
+ var switchPlayList = function () {
441
+ if (onclick.preventClick) return;
442
+ onclick.preventClick = true;
443
+ if (playList.parentNode) remove(playList);
444
+ else popup(playList, savatar);
445
+ }
434
446
  render(player, $scope);
435
447
  player.play = function (hash) {
436
448
  $scope.play(hash);
@@ -439,5 +451,17 @@ var player = function (player) {
439
451
  $scope.pause();
440
452
  };
441
453
  appendChild.before(document.body, player);
454
+ on("contextmenu")(player, e => e.preventDefault());
455
+ on("click.self")(player, function (a) {
456
+ if ($scope.playing) $scope.pause();
457
+ else $scope.play();
458
+ });
459
+ var timeout = 0;
460
+ on("pointerdown")(player, function () {
461
+ timeout = setTimeout(switchPlayList, 600);
462
+ });
463
+ on("pointerup")(player, function () {
464
+ clearTimeout(timeout);
465
+ })
442
466
  return player;
443
467
  }(createControls());
@@ -1,19 +1,8 @@
1
- .song {
2
- color: #fff;
3
- }
4
-
5
- .singer {
6
- color: #ccc;
7
- }
8
-
9
- .time {
10
- position: absolute;
11
- right: 8px;
12
- bottom: 4px;
13
- text-align: right;
14
- }
1
+ @avatar-left: 36px;
2
+ @avatar-top: -12px;
3
+ @avatar-size: 72px;
15
4
 
16
- @main-color: #2c7bb5;
5
+ @main-color: #021c;
17
6
 
18
7
  &.pause .play:before {
19
8
  content: "";
@@ -26,20 +15,22 @@
26
15
  vertical-align: middle;
27
16
  }
28
17
 
18
+ krc {
19
+ pointer-events: none;
20
+ }
21
+
29
22
  &.play .play:before {
30
- content: "";
31
- display: inline-block;
23
+ display: none;
32
24
  border: .4em solid;
33
25
  vertical-align: middle;
34
26
  }
35
27
 
36
- .avatar,
37
- &:after {
28
+ .avatar {
38
29
  border-radius: 50%;
39
- width: 72px;
40
- height: 72px;
41
- top: -12px;
42
- left: 8px;
30
+ width: @avatar-size;
31
+ height: @avatar-size;
32
+ top: @avatar-top;
33
+ left: @avatar-left;
43
34
  position: absolute;
44
35
  background-size: cover;
45
36
  border: 3px solid #000;
@@ -99,11 +90,25 @@
99
90
  overflow: hidden;
100
91
  z-index: -1;
101
92
 
93
+ &:before {
94
+ content: "";
95
+ left: @avatar-left+@border-width + 72px;
96
+ position: absolute;
97
+ min-width: 100px;
98
+ width: auto;
99
+ height: auto;
100
+ border-radius: 60px 0 0 0;
101
+ right: 0;
102
+ top: 0;
103
+ bottom: 0;
104
+ background-color: @main-color;
105
+ }
106
+
107
+ @blank-size : @avatar-size;
108
+ @border-width : 40px;
109
+ @border-size: @blank-size / 2 + @border-width;
110
+
102
111
  &:after {
103
- @size : 10000px;
104
- @blank-size : 70px;
105
- @margin-y: @size + 35px;
106
- @margin-x: @size + 35px;
107
112
  box-sizing: content-box;
108
113
  content: "";
109
114
  display: block;
@@ -111,19 +116,20 @@
111
116
  position: absolute;
112
117
  width: @blank-size;
113
118
  height: @blank-size;
114
- border: @size solid #000;
115
- margin: -@margin-x -@margin-y;
116
- top: 24px;
117
- left: 44px;
119
+ border: @border-width solid #000;
120
+ margin: -@border-size;
121
+ top: 12px-@avatar-top;
122
+ left: @avatar-left + @blank-size/2;
118
123
  }
119
124
 
120
125
  &:after {
121
- border-radius: 50%;
126
+ border-radius: @border-size;
122
127
  }
123
128
  }
124
129
 
125
130
  &>div.progress {
126
131
  z-index: 1;
132
+ pointer-events: none;
127
133
 
128
134
  >.track:after,
129
135
  >.avatar {
@@ -132,13 +138,13 @@
132
138
  }
133
139
 
134
140
  >.track {
135
- background: @main-color;
136
141
  opacity: .7;
137
142
  transition: height .3s, opacity .3s;
138
- top: 12px;
143
+ top: -@avatar-top;
139
144
  }
140
145
 
141
146
  >.avatar {
147
+ border-color: lighten(@main-color, 100%);
142
148
  opacity: 1;
143
149
  top: 0;
144
150
  }
@@ -148,7 +154,7 @@
148
154
  overflow : hidden;
149
155
  padding : 0;
150
156
  height : 72px;
151
- margin-top: -12px;
157
+ margin-top: @avatar-top;
152
158
  }
153
159
 
154
160
  & {
@@ -159,7 +165,7 @@
159
165
  user-select: none;
160
166
  position: fixed;
161
167
  bottom: 0;
162
- color: #fff;
168
+ color: #ccc;
163
169
  left: 0;
164
170
  right: 0;
165
171
  padding: 0 0 0 78px;
@@ -169,47 +175,80 @@
169
175
 
170
176
  >btn,
171
177
  >sbtn {
178
+ @btn-width: 42px;
172
179
  text-align: center;
173
180
  line-height: 60px;
174
- width: 50px;
181
+ width: @btn-width;
175
182
  height: 60px;
176
183
  vertical-align: top;
177
- position: relative;
184
+ position: absolute;
178
185
  background: transparent;
186
+ z-index: 2;
179
187
 
180
- &.info,
181
- &.prev,
182
- &.list,
183
- &.next,
184
188
  &.play {
185
- z-index: 2;
189
+ top: @avatar-top/2;
190
+ pointer-events: none;
191
+ left: @avatar-left+16px;
186
192
  }
193
+
194
+ &.next {
195
+ right: 0;
196
+ }
197
+
198
+ &.prev {
199
+ top: 0;
200
+ left: @avatar-left - @btn-width+6px;
201
+ }
202
+
187
203
  }
188
204
 
189
- >.info {
190
- width: 100%;
191
- margin-right: -200px;
205
+ .time {
206
+ left: 6px;
207
+ text-align: center;
208
+ top: 46px;
209
+ color: #fff9;
192
210
  line-height: 1;
193
- text-align: left;
194
- padding: 46px 5px 0 5px;
195
211
  z-index: 2;
196
- position: relative;
197
- font-size: 8px;
212
+ font-size: 12px;
213
+ }
198
214
 
199
- .spliter {
200
- .singer;
201
- }
215
+ .total {
216
+ z-index: 2;
217
+ right: 6px;
218
+ top: 46px;
219
+ color: #fff9;
220
+ line-height: 1;
221
+ font-size: 12px;
222
+ }
223
+
224
+ .singer {
225
+ color: #fffc;
226
+ font-size: 8px;
227
+ display: block;
228
+ top: 46px;
229
+ z-index: 2;
230
+ left: @avatar-left+@avatar-size;
231
+ right: 60px;
232
+ }
202
233
 
203
234
 
204
- >div {
205
- text-overflow: ellipsis;
206
- white-space: nowrap;
207
- overflow: hidden;
208
- }
235
+ .song {
236
+ left: @avatar-left + @avatar-size + 6px;
237
+ line-height: 1;
238
+ top: 22px;
239
+ font-size: 16px;
240
+ right: 60px;
241
+ z-index: 2;
209
242
  }
210
243
 
244
+
211
245
  >div {
212
- display: inline-block;
246
+ text-align: left;
247
+ overflow: hidden;
248
+ text-overflow: ellipsis;
249
+ white-space: nowrap;
250
+ position: absolute;
251
+ pointer-events: none;
213
252
  height: 60px;
214
253
  }
215
254
  }
@@ -218,10 +257,16 @@
218
257
  height: 100%;
219
258
  z-index: 10;
220
259
  opacity: 1;
260
+ @ptop: -@avatar-top;
221
261
 
222
262
  >div.progress>.track {
223
263
  height: 3px;
224
264
  opacity: 1;
265
+ top: @ptop;
266
+
267
+ &:after {
268
+ top: 24px - @avatar-top - @ptop;
269
+ }
225
270
  }
226
271
 
227
272
  >.track {
@@ -247,7 +292,7 @@
247
292
  font-size: 8px;
248
293
  text-align: left;
249
294
  line-height: 16px;
250
- padding-left: 84px;
295
+ padding-left: @avatar-left+@avatar-size+4px;
251
296
 
252
297
  .active,
253
298
  .active+.after {
@@ -273,10 +318,6 @@
273
318
  font-size: 16px;
274
319
  }
275
320
 
276
- &:not(.play):not(.page)>.background {
277
- opacity: 0;
278
- transition: opacity .4s ease;
279
- }
280
321
 
281
322
  &>.background {
282
323
  background-color: #999;
@@ -399,32 +440,35 @@
399
440
  pointer-events: none;
400
441
 
401
442
  &+.avatar {
443
+ pointer-events: all;
402
444
  border-color: transparent;
403
- z-index: 1;
445
+ z-index: 2;
446
+ }
447
+ }
448
+
449
+ & {
450
+ text-align: right;
451
+
452
+ >.track {
453
+ height: 60px;
454
+ margin-top: 0;
455
+ border-top: 0 solid #666;
456
+ transition: margin-top .2s ease-out, border-top .2s ease-out, height .2s ease-out;
404
457
  }
405
458
  }
406
459
 
407
- // & {
408
- // >.track {
409
- // height: 60px;
410
- // margin-top: 0;
411
- // border-top: 0 solid #666;
412
- // transition: margin-top .2s ease-out, border-top .2s ease-out, height .2s ease-out;
413
- // }
414
- // }
415
-
416
- // &.effect {
417
- // opacity: 1;
418
-
419
- // >.track {
420
- // height: 420px;
421
- // margin-top: -360px;
422
- // border-top: 360px solid #666;
423
- // }
424
- // }
460
+ &.effect {
461
+ opacity: 1;
462
+
463
+ >.track {
464
+ height: 420px;
465
+ margin-top: -360px;
466
+ border-top: 360px solid #666;
467
+ }
468
+ }
425
469
 
426
470
  &:not(.page)>canvas {
427
- top: -12px;
471
+ top: @avatar-top;
428
472
  }
429
473
 
430
474
  &.dragging {