${menuItem.title}
@@ -1479,10 +1659,23 @@ class DmYY {
previewWebView.present();
}
+ initSFSymbol() {
+ const named = SFSymbol.named;
+ SFSymbol.named = (str) => {
+ const current = named(str);
+ if (!current) {
+ console.log(`图标异常,请在文中搜索并替换图标:${str}`);
+ return named('photo');
+ }
+ return current;
+ };
+ return SFSymbol;
+ }
+
_init(widgetFamily = config.widgetFamily) {
+ this.initSFSymbol();
// 组件大小:small,medium,large
this.widgetFamily = widgetFamily;
- this.SETTING_KEY = this.md5(Script.name());
//用于配置所有的组件相关设置
// 文件管理器
@@ -1596,7 +1789,7 @@ class DmYY {
name,
type,
title: name,
- onClick: func.bind(this),
+ onClick: func?.bind(this),
};
if (typeof icon === 'string') {
@@ -1631,150 +1824,7 @@ class DmYY {
* @param {string} str 要加密成md5的数据
*/
// prettier-ignore
- md5(str) {
- function d(n, t) {
- var r = (65535 & n) + (65535 & t);
- return (((n >> 16) + (t >> 16) + (r >> 16)) << 16) | (65535 & r);
- }
-
- function f(n, t, r, e, o, u) {
- return d(((c = d(d(t, n), d(e, u))) << (f = o)) | (c >>> (32 - f)), r);
- var c, f;
- }
-
- function l(n, t, r, e, o, u, c) {
- return f(
- (t & r) | (~t & e), n, t, o, u, c);
- }
-
- function v(n, t, r, e, o, u, c) {
- return f(
- (t & e) | (r & ~e), n, t, o, u, c);
- }
-
- function g(n, t, r, e, o, u, c) {return f(t ^ r ^ e, n, t, o, u, c);}
-
- function m(n, t, r, e, o, u, c) {return f(r ^ (t | ~e), n, t, o, u, c);}
-
- function i(n, t) {
- var r, e, o, u;
- (n[t >> 5] |= 128 << t % 32), (n[14 + (((t + 64) >>> 9) << 4)] = t);
- for (var c = 1732584193, f = -271733879, i = -1732584194, a = 271733878, h = 0; h <
- n.length; h += 16) (c = l(
- (r = c), (e = f), (o = i), (u = a), n[h], 7, -680876936)), (a = l(
- a, c, f, i, n[h + 1], 12, -389564586)), (i = l(
- i, a, c, f, n[h + 2], 17, 606105819)), (f = l(
- f, i, a, c, n[h + 3], 22, -1044525330)), (c = l(
- c, f, i, a, n[h + 4], 7, -176418897)), (a = l(
- a, c, f, i, n[h + 5], 12, 1200080426)), (i = l(
- i, a, c, f, n[h + 6], 17, -1473231341)), (f = l(
- f, i, a, c, n[h + 7], 22, -45705983)), (c = l(
- c, f, i, a, n[h + 8], 7, 1770035416)), (a = l(
- a, c, f, i, n[h + 9], 12, -1958414417)), (i = l(
- i, a, c, f, n[h + 10], 17, -42063)), (f = l(
- f, i, a, c, n[h + 11], 22, -1990404162)), (c = l(
- c, f, i, a, n[h + 12], 7, 1804603682)), (a = l(
- a, c, f, i, n[h + 13], 12, -40341101)), (i = l(
- i, a, c, f, n[h + 14], 17, -1502002290)), (c = v(
- c, (f = l(f, i, a, c, n[h + 15], 22, 1236535329)), i, a, n[h + 1], 5,
- -165796510,
- )), (a = v(a, c, f, i, n[h + 6], 9, -1069501632)), (i = v(
- i, a, c, f, n[h + 11], 14, 643717713)), (f = v(
- f, i, a, c, n[h], 20, -373897302)), (c = v(
- c, f, i, a, n[h + 5], 5, -701558691)), (a = v(
- a, c, f, i, n[h + 10], 9, 38016083)), (i = v(
- i, a, c, f, n[h + 15], 14, -660478335)), (f = v(
- f, i, a, c, n[h + 4], 20, -405537848)), (c = v(
- c, f, i, a, n[h + 9], 5, 568446438)), (a = v(
- a, c, f, i, n[h + 14], 9, -1019803690)), (i = v(
- i, a, c, f, n[h + 3], 14, -187363961)), (f = v(
- f, i, a, c, n[h + 8], 20, 1163531501)), (c = v(
- c, f, i, a, n[h + 13], 5, -1444681467)), (a = v(
- a, c, f, i, n[h + 2], 9, -51403784)), (i = v(
- i, a, c, f, n[h + 7], 14, 1735328473)), (c = g(
- c, (f = v(f, i, a, c, n[h + 12], 20, -1926607734)), i, a, n[h + 5], 4,
- -378558,
- )), (a = g(a, c, f, i, n[h + 8], 11, -2022574463)), (i = g(
- i, a, c, f, n[h + 11], 16, 1839030562)), (f = g(
- f, i, a, c, n[h + 14], 23, -35309556)), (c = g(
- c, f, i, a, n[h + 1], 4, -1530992060)), (a = g(
- a, c, f, i, n[h + 4], 11, 1272893353)), (i = g(
- i, a, c, f, n[h + 7], 16, -155497632)), (f = g(
- f, i, a, c, n[h + 10], 23, -1094730640)), (c = g(
- c, f, i, a, n[h + 13], 4, 681279174)), (a = g(
- a, c, f, i, n[h], 11, -358537222)), (i = g(
- i, a, c, f, n[h + 3], 16, -722521979)), (f = g(
- f, i, a, c, n[h + 6], 23, 76029189)), (c = g(
- c, f, i, a, n[h + 9], 4, -640364487)), (a = g(
- a, c, f, i, n[h + 12], 11, -421815835)), (i = g(
- i, a, c, f, n[h + 15], 16, 530742520)), (c = m(
- c, (f = g(f, i, a, c, n[h + 2], 23, -995338651)), i, a, n[h], 6,
- -198630844,
- )), (a = m(a, c, f, i, n[h + 7], 10, 1126891415)), (i = m(
- i, a, c, f, n[h + 14], 15, -1416354905)), (f = m(
- f, i, a, c, n[h + 5], 21, -57434055)), (c = m(
- c, f, i, a, n[h + 12], 6, 1700485571)), (a = m(
- a, c, f, i, n[h + 3], 10, -1894986606)), (i = m(
- i, a, c, f, n[h + 10], 15, -1051523)), (f = m(
- f, i, a, c, n[h + 1], 21, -2054922799)), (c = m(
- c, f, i, a, n[h + 8], 6, 1873313359)), (a = m(
- a, c, f, i, n[h + 15], 10, -30611744)), (i = m(
- i, a, c, f, n[h + 6], 15, -1560198380)), (f = m(
- f, i, a, c, n[h + 13], 21, 1309151649)), (c = m(
- c, f, i, a, n[h + 4], 6, -145523070)), (a = m(
- a, c, f, i, n[h + 11], 10, -1120210379)), (i = m(
- i, a, c, f, n[h + 2], 15, 718787259)), (f = m(
- f, i, a, c, n[h + 9], 21, -343485551)), (c = d(c, r)), (f = d(
- f, e)), (i = d(i, o)), (a = d(a, u));
- return [c, f, i, a];
- }
-
- function a(n) {
- for (var t = '', r = 32 * n.length, e = 0; e <
- r; e += 8) t += String.fromCharCode((n[e >> 5] >>> e % 32) & 255);
- return t;
- }
-
- function h(n) {
- var t = [];
- for (t[(n.length >> 2) - 1] = void 0, e = 0; e <
- t.length; e += 1) t[e] = 0;
- for (var r = 8 * n.length, e = 0; e < r; e += 8) t[e >> 5] |= (255 &
- n.charCodeAt(e / 8)) << e % 32;
- return t;
- }
-
- function e(n) {
- for (var t, r = '0123456789abcdef', e = '', o = 0; o <
- n.length; o += 1) (t = n.charCodeAt(o)), (e += r.charAt((t >>> 4) & 15) +
- r.charAt(15 & t));
- return e;
- }
-
- function r(n) {return unescape(encodeURIComponent(n));}
-
- function o(n) {
- return a(i(h((t = r(n))), 8 * t.length));
- var t;
- }
-
- function u(n, t) {
- return (function(n, t) {
- var r, e, o = h(n), u = [], c = [];
- for (u[15] = c[15] = void 0, 16 < o.length &&
- (o = i(o, 8 * n.length)), r = 0; r < 16; r += 1) (u[r] = 909522486 ^
- o[r]), (c[r] = 1549556828 ^ o[r]);
- return ((e = i(u.concat(h(t)), 512 + 8 * t.length)), a(
- i(c.concat(e), 640)));
- })(r(n), r(t));
- }
-
- function t(n, t, r) {
- return t ? (r ? u(t, n) : e(u(t, n))) : r ? o(n) : e(o(n));
- }
-
- return t(str);
- }
+ md5(str){function d(n,t){var r=(65535&n)+(65535&t);return(((n>>16)+(t>>16)+(r>>16))<<16)|(65535&r)}function f(n,t,r,e,o,u){return d(((c=d(d(t,n),d(e,u)))<<(f=o))|(c>>>(32-f)),r);var c,f}function l(n,t,r,e,o,u,c){return f((t&r)|(~t&e),n,t,o,u,c)}function v(n,t,r,e,o,u,c){return f((t&e)|(r&~e),n,t,o,u,c)}function g(n,t,r,e,o,u,c){return f(t^r^e,n,t,o,u,c)}function m(n,t,r,e,o,u,c){return f(r^(t|~e),n,t,o,u,c)}function i(n,t){var r,e,o,u;(n[t>>5]|=128<
>>9)<<4)]=t);for(var c=1732584193,f=-271733879,i=-1732584194,a=271733878,h=0;h>5]>>>e%32)&255);return t}function h(n){var t=[];for(t[(n.length>>2)-1]=void 0,e=0;e>5]|=(255&n.charCodeAt(e/8))<>>4)&15)+r.charAt(15&t));return e}function r(n){return unescape(encodeURIComponent(n))}function o(n){return a(i(h((t=r(n))),8*t.length));var t}function u(n,t){return(function(n,t){var r,e,o=h(n),u=[],c=[];for(u[15]=c[15]=void 0,16 {
if (w) return w[`present${fnc}`]();
};
- const preview = [];
+ const preview = [],
+ lockView = [];
if (M.renderSmall) {
preview.push({
url: `https://raw.githubusercontent.com/dompling/Scriptable/master/images/small.png`,
@@ -2129,11 +2180,56 @@ const Runing = async (Widget, default_args = '', isDebug = true, extra) => {
});
}
+ if (M.renderAccessoryInline) {
+ lockView.push({
+ icon: {
+ color: '#4676EE',
+ name: 'list.triangle',
+ },
+ title: '锁屏列表',
+ val: 'accessoryInline',
+ name: 'accessoryInline',
+ dismissOnSelect: true,
+ onClick,
+ });
+ }
+
+ if (M.renderAccessoryRectangular) {
+ lockView.push({
+ icon: {
+ color: '#4676EE',
+ name: 'arrow.rectanglepath',
+ },
+ title: '锁屏 2x',
+ val: 'accessoryRectangular',
+ name: 'accessoryRectangular',
+ dismissOnSelect: true,
+ onClick,
+ });
+ }
+
+ if (M.renderAccessoryCircular) {
+ lockView.push({
+ icon: {
+ color: '#4676EE',
+ name: 'circle.circle',
+ },
+ title: '锁屏 1x',
+ val: 'accessoryCircular',
+ name: 'accessoryCircular',
+ dismissOnSelect: true,
+ onClick,
+ });
+ }
+
const menuConfig = [
- { title: '预览组件', menu: preview },
- { title: '组件配置', menu: actions },
+ ...(preview ? [{ title: '预览组件', menu: preview }] : []),
+ ...(lockView.length ? [{ title: '锁屏组件', menu: lockView }] : []),
...M['_menuActions'],
];
+
+ if (actions.length) menuConfig.push({ title: '组件配置', menu: actions });
+
await M.renderAppView(menuConfig, true);
}
}
diff --git a/Scripts/Oild.js b/Scripts/Oild.js
index b8b5d20..f2303cd 100644
--- a/Scripts/Oild.js
+++ b/Scripts/Oild.js
@@ -1,10 +1,10 @@
// Variables used by Scriptable.
// These must be at the very top of the file. Do not edit.
-// icon-color: deep-gray; icon-glyph: car;
+// icon-color: deep-gray; icon-glyph: oil;
// 添加require,是为了vscode中可以正确引入包,以获得自动补全等功能
if (typeof require === 'undefined') require = importModule;
-const {DmYY, Runing} = require('./DmYY');
+const { DmYY, Runing } = require('./DmYY');
const enumConfig = {
89: '汽油',
@@ -14,6 +14,43 @@ const enumConfig = {
0: '柴油',
};
+const provinces = [
+ '北京',
+ '天津',
+ '上海',
+ '重庆',
+ '河北',
+ '山西',
+ '辽宁',
+ '吉林',
+ '黑龙江',
+ '江苏',
+ '浙江',
+ '安徽',
+ '福建',
+ '江西',
+ '山东',
+ '河南',
+ '湖北',
+ '湖南',
+ '广东',
+ '海南',
+ '四川',
+ '贵州',
+ '云南',
+ '陕西',
+ '甘肃',
+ '青海',
+ '台湾',
+ '内蒙古',
+ '广西',
+ '西藏',
+ '宁夏',
+ '新疆',
+ '香港',
+ '澳门',
+];
+
const squareColor = '#8165AC';
const processColor = [`#7517F8`, `#E323FF`];
const processBarColor = [`#4da1ff`, `#4dffdf`];
@@ -23,21 +60,36 @@ const processBarBgColor = '#5A5A89';
class Widget extends DmYY {
constructor(arg) {
super(arg);
- config.runsInApp &&
- this.registerAction(
- '油价设置',
- () => {
- return this.setAlertInput('油价设置', '设置类型,多个英文逗号分割', {
- oilNumber: '92,95,89,0',
- });
- },
- {name: 'paperplane', color: '#722ed1'},
- );
this.en = 'oilWidget';
this.name = '油价';
- config.runsInApp && this.registerAction('基础设置', this.setWidgetConfig);
- this.cacheName = this.md5(`dataSource_${this.en}`);
- this.oilNumber = `${this.settings.oilNumber || '92'}`.split(',');
+ if (config.runsInApp) {
+ this.registerAction(
+ '油价设置',
+ () => {
+ return this.setAlertInput('油价设置', '设置类型,多个英文逗号分割', {
+ oilNumber: '92,95,89,0',
+ });
+ },
+ { name: 'oilcan', color: '#E64C57' }
+ );
+
+ this.registerAction({
+ icon: { name: 'location.circle', color: '#8BE39D' },
+ type: 'switch',
+ title: '自动定位',
+ val: 'location',
+ });
+
+ this.registerAction({
+ icon: { name: 'mappin.and.ellipse.circle', color: '#5BBFF6' },
+ type: 'select',
+ title: '油价省份',
+ val: 'province',
+ placeholder: '地区',
+ options: provinces,
+ });
+ this.registerAction('基础设置', this.setWidgetConfig);
+ }
}
dataSource = {
@@ -59,6 +111,23 @@ class Widget extends DmYY {
};
init = async () => {
+ try {
+ this.oilNumber = `${this.settings.oilNumber || '92'}`.split(',');
+ const oilNumber = [];
+ this.oilNumber.forEach((item) => {
+ if (item && ['92', '95', '89', '0'].includes(item)) {
+ oilNumber.push(item);
+ }
+ });
+ this.oilNumber = oilNumber;
+ if (!this.oilNumber.length)
+ return this.notify(this.name, '请设置油价型号:92,95,89,0');
+ } catch (error) {
+ return console.log('请设置正确的油价');
+ }
+ this.province = this.settings.province;
+ this.location = this.settings.location;
+
if (this.settings.dataSource) {
this.dataSource = this.settings.dataSource[0];
} else {
@@ -76,19 +145,27 @@ class Widget extends DmYY {
};
getOilPrice = async () => {
- const location = await Location.current();
- const locationText = await Location.reverseGeocode(
- location.latitude,
- location.longitude,
- );
- const {administrativeArea = ''} = locationText[0] || {};
- const filter = `(CITYNAME="${administrativeArea.replace('省', '')}")`;
+ if (this.location) {
+ const location = await Location.current();
+ const locationText = await Location.reverseGeocode(
+ location.latitude,
+ location.longitude
+ );
+ const { administrativeArea = '' } = locationText[0] || {};
+ this.province = administrativeArea.replace('省', '');
+ this.settings.province = this.province;
+ this.saveSettings(false);
+ }
+
+ if (!this.province) return this.notify(this.name, '请设置油价省份!!');
+ console.log(`当前省份:${this.province}`);
+ this.province = `(CITYNAME="${this.province}")`;
const time = Date.now();
const url = `https://datacenter-web.eastmoney.com/api/data/v1/get?reportName=RPTA_WEB_YJ_JH&columns=ALL&filter=${encodeURIComponent(
- filter,
+ this.province
)}&sortColumns=DIM_DATE&sortTypes=-1&pageNumber=1&pageSize=6&source=WEB&_=${time}`;
- const options = {url};
+ const options = { url };
const response = await this.$request.post(options);
console.log(response);
if (response.result) {
@@ -125,7 +202,8 @@ class Widget extends DmYY {
topLStack.addSpacer();
topLStack.bottomAlignContent();
const oilPrice = (this.dataSource[`V${this.oilNumber[0]}`] || '').toFixed(
- 2);
+ 2
+ );
const timer = (this.dataSource.DIM_DATE.split(' ')[0] || '').split('-');
const oilNumText = topLStack.addText(`${oilPrice}`);
oilNumText.textColor = this.widgetColor;
@@ -135,7 +213,7 @@ class Widget extends DmYY {
const oilStatus = this.dataSource[`ZDE${this.oilNumber[0]}`] > 0;
const oilZdeImage = SFSymbol.named(
- oilStatus ? 'arrow.up' : 'arrow.up',
+ oilStatus ? 'arrow.up' : 'arrow.up'
).image;
topStack.addSpacer();
const topRStack = topStack.addStack();
@@ -158,7 +236,8 @@ class Widget extends DmYY {
const bottomStack = w.addStack();
bottomStack.addSpacer();
const rightText = bottomStack.addText(
- `${this.oilNumber[0]}#${enumConfig[this.oilNumber[0]]}`);
+ `${this.oilNumber[0]}#${enumConfig[this.oilNumber[0]]}`
+ );
oilNumText.textColor = this.widgetColor;
rightText.font = Font.boldSystemFont(18);
rightText.textOpacity = 0.3;
@@ -168,7 +247,6 @@ class Widget extends DmYY {
};
rowData = (w, oilNumber) => {
-
const oilPrice = (this.dataSource[`V${oilNumber}`] || '').toFixed(2);
const oilZde = (this.dataSource[`ZDE${oilNumber}`] || '').toFixed(2);
const oilType = enumConfig[oilNumber] || '';
@@ -182,10 +260,11 @@ class Widget extends DmYY {
oilNumberStack.borderWidth = 4;
oilNumberStack.borderColor = new Color(squareColor);
oilNumberStack.centerAlignContent();
- this.provideText(
- `${oilNumber}`, oilNumberStack,
- {font: 'bold', size: 26, color: new Color(squareColor)},
- );
+ this.provideText(`${oilNumber}`, oilNumberStack, {
+ font: 'bold',
+ size: 26,
+ color: new Color(squareColor),
+ });
colStack.addSpacer(7);
@@ -193,17 +272,20 @@ class Widget extends DmYY {
oilInfoStack.size = new Size(65, colSize.height);
oilInfoStack.layoutVertically();
oilInfoStack.addSpacer();
- this.provideText(
- `#${oilType}`, oilInfoStack,
- {font: 'light', size: 12, color: this.widgetColor, opacity: 0.5},
- );
+ this.provideText(`#${oilType}`, oilInfoStack, {
+ font: 'light',
+ size: 12,
+ color: this.widgetColor,
+ opacity: 0.5,
+ });
oilInfoStack.addSpacer(2);
- this.provideText(
- `${oilPrice}`, oilInfoStack,
- {font: 'medium', size: 18, color: this.widgetColor},
- );
+ this.provideText(`${oilPrice}`, oilInfoStack, {
+ font: 'medium',
+ size: 18,
+ color: this.widgetColor,
+ });
oilInfoStack.addSpacer();
const processStack = colStack.addStack();
@@ -211,17 +293,16 @@ class Widget extends DmYY {
const processVerWidth = 10;
let maxCount = 0;
- const oilHistory = this.settings.dataSource.map(
- item => {
- const value = (item[`ZDE${oilNumber}`] /
- item[`QE${oilNumber}`]).toFixed(2) * 100;
- if (maxCount < value) maxCount = value;
- return value;
- });
+ const oilHistory = this.settings.dataSource.map((item) => {
+ const value =
+ (item[`ZDE${oilNumber}`] / item[`QE${oilNumber}`]).toFixed(2) * 100;
+ if (maxCount < value) maxCount = value;
+ return value;
+ });
maxCount = maxCount * 1.5;
- oilHistory.forEach(item => {
+ oilHistory.forEach((item) => {
const processItemStack = processStack.addStack();
processItemStack.size = new Size(processVerWidth, colSize.height);
processItemStack.cornerRadius = processVerWidth / 2;
@@ -232,7 +313,9 @@ class Widget extends DmYY {
const itemBarStack = processItemStack.addStack();
itemBarStack.cornerRadius = processItemStack.cornerRadius;
itemBarStack.size = new Size(
- processVerWidth, colSize.height * (Math.abs(item) / maxCount));
+ processVerWidth,
+ colSize.height * (Math.abs(item) / maxCount)
+ );
itemBarStack.backgroundGradient = this.gradient(processColor);
if (item < 0) processItemStack.addSpacer();
processStack.addSpacer();
@@ -251,13 +334,14 @@ class Widget extends DmYY {
const oilZdeValueStack = oilZdeStack.addStack();
oilZdeValueStack.centerAlignContent();
oilZdeValueStack.addSpacer();
- this.provideText(
- `${oilZde > 0 ? '+' : ''} ${oilZde}`, oilZdeValueStack,
- {font: 'light', size: 14, color: this.widgetColor},
- );
+ this.provideText(`${oilZde > 0 ? '+' : ''} ${oilZde}`, oilZdeValueStack, {
+ font: 'light',
+ size: 14,
+ color: this.widgetColor,
+ });
const oilZdeImage = SFSymbol.named(
- oilZde > 0 ? 'arrow.up' : 'arrow.down',
+ oilZde > 0 ? 'arrow.up' : 'arrow.down'
).image;
oilZdeValueStack.addSpacer(10);
@@ -282,7 +366,7 @@ class Widget extends DmYY {
const processBarStack = processBarBgStack.addStack();
const linear = new LinearGradient();
- linear.colors = processBarColor.map(item => new Color(item));
+ linear.colors = processBarColor.map((item) => new Color(item));
linear.locations = [0, 0.5];
linear.startPoint = new Point(0, 0);
linear.endPoint = new Point(1, 1);
@@ -290,7 +374,9 @@ class Widget extends DmYY {
processBarStack.backgroundGradient = linear;
processBarStack.cornerRadius = oilZdeSize.height / 2;
processBarStack.size = new Size(
- parseInt(oilZdeSize.width * oilZdeValue), oilZdeSize.height);
+ parseInt(oilZdeSize.width * oilZdeValue),
+ oilZdeSize.height
+ );
if (oilZde > 0) processBarBgStack.addSpacer();
};
@@ -303,9 +389,9 @@ class Widget extends DmYY {
stack.borderWidth = 1;
};
- gradient = (color, config = {locations: [0, 0.5]}) => {
+ gradient = (color, config = { locations: [0, 0.5] }) => {
const linear = new LinearGradient();
- linear.colors = color.map(item => new Color(item));
+ linear.colors = color.map((item) => new Color(item));
linear.locations = config.locations;
return linear;
};
diff --git a/Scripts/Spotify.js b/Scripts/Spotify.js
new file mode 100644
index 0000000..f1446b8
--- /dev/null
+++ b/Scripts/Spotify.js
@@ -0,0 +1,672 @@
+// Variables used by Scriptable.
+// These must be at the very top of the file. Do not edit.
+// icon-color: deep-blue; icon-glyph: dollar;
+
+// 添加require,是为了vscode中可以正确引入包,以获得自动补全等功能
+if (typeof require === "undefined") require = importModule;
+const { DmYY, Runing } = require("./DmYY");
+
+const logo = `https://open.spotifycdn.com/cdn/images/favicon.0f31d2ea.ico`;
+const fontFamily = "AmericanTypewriter-Bold";
+
+const api = {
+ me: `https://api.spotify.com/v1/me`,
+ accounts: `https://accounts.spotify.com/api/token`,
+ currentlyPlayingTrack: `https://api.spotify.com/v1/me/player/currently-playing`,
+ getTrack: `https://api.spotify.com/v1/tracks/11dFghVXANMlKmJXsNCbNl`,
+ palyState: `https://api.spotify.com/v1/me/player`,
+ playlists: `https://api.spotify.com/v1/me/playlists`,
+ following: `https://api.spotify.com/v1/me/following?type=artist`,
+};
+
+const scope = [
+ "ugc-image-upload",
+ "playlist-read-collaborative",
+ "playlist-modify-private",
+ "playlist-modify-public",
+ "playlist-read-private",
+ "user-read-playback-position",
+ "user-read-recently-played",
+ "user-top-read",
+ "user-modify-playback-state",
+ "user-read-currently-playing",
+ "user-read-playback-state",
+ "user-read-private",
+ "user-read-email",
+ "user-library-modify",
+ "user-library-read",
+ "user-follow-modify",
+ "user-follow-read",
+ "streaming",
+ "app-remote-control",
+];
+
+const webUri = `https://accounts.spotify.com/zh-CN/login?continue=${encodeURIComponent(
+ "https://developer.spotify.com/documentation/web-api/reference/get-current-users-profile"
+)}`;
+
+function generateRandomString(length) {
+ let text = "";
+ let possible =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+
+ for (let i = 0; i < length; i++) {
+ text += possible.charAt(Math.floor(Math.random() * possible.length));
+ }
+ return text;
+}
+
+function convertMillisecondsToHMS(milliseconds) {
+ // 计算总共有多少秒
+ let totalSeconds = Math.floor(milliseconds / 1000);
+
+ // 计算分钟数
+ let minutes = Math.floor(totalSeconds / 60);
+
+ // 剩余的秒数
+ let seconds = totalSeconds - minutes * 60;
+
+ if (minutes < 10) {
+ minutes = "0" + minutes;
+ }
+ if (seconds < 10) {
+ seconds = "0" + seconds;
+ }
+
+ // 组合时分秒
+ return minutes + ":" + seconds;
+}
+
+// @组件代码开始
+class Widget extends DmYY {
+ constructor(arg) {
+ super(arg);
+ this.en = "Spotify";
+ this.name = "声田音乐";
+ this.SETTING_KEY = this.md5(this.en);
+ this._init();
+ this.auth2 = args.queryParameters.code
+ ? args.queryParameters
+ : this.settings.auth2;
+
+ this.settings.auth2 = this.auth2;
+ this.saveSettings(false);
+
+ if (config.runsInApp) {
+ this.registerAction({
+ icon: {
+ name: "airplayaudio.circle.fill",
+ color: "#65D46E",
+ },
+ title: "登录",
+ val: "login",
+ name: "login",
+ dismissOnSelect: true,
+ onClick: () => {
+ return this.getWebToken();
+ },
+ });
+
+ this.registerAction({
+ icon: {
+ name: "music.note",
+ color: "#65D46E",
+ },
+ title: "客户端 ID",
+ val: "clientId",
+ name: "clientId",
+ type: "input",
+ dismissOnSelect: true,
+ });
+
+ this.registerAction("基础设置", this.setWidgetConfig);
+ }
+ }
+
+ baseUri = "";
+ accessToken = "";
+ dataSource = {
+ currentlyPlayingTrack: {},
+ playlists: {},
+ me: {},
+ following: {},
+ };
+
+ init = async () => {
+ await this.getAccessToken();
+ if (!this.settings.accessToken) return this.notify(this.name, "请登录!!");
+ this.accessToken = `${this.settings.accessToken.token_type} ${this.settings.accessToken.access_token}`;
+ this.dataSource.playlists = await this.getApiRes(api.playlists);
+ this.dataSource.following = await this.getApiRes(api.following);
+ this.dataSource.me = await this.getApiRes(api.me);
+ this.dataSource.currentlyPlayingTrack = await this.getApiRes(
+ api.currentlyPlayingTrack
+ );
+ };
+
+ getAccessToken = async () => {
+ const { accessToken } = this.settings;
+ if (accessToken) {
+ const diffTime = (new Date().getTime() - accessToken.time) / 1000;
+ if (diffTime > accessToken.expires_in) {
+ return this.refreshToken();
+ }
+ } else if (this.auth2) {
+ if (!this.auth2.code)
+ return this.notify(
+ this.name,
+ "请登录!!!",
+ "https://developer.spotify.com"
+ );
+ const { clientId, codeVerifier } = this.settings;
+
+ const options = {
+ code: this.auth2.code,
+ client_id: clientId,
+ code_verifier: codeVerifier,
+ grant_type: "authorization_code",
+ redirect_uri: "scriptable:///run/Spotify?openEditor=true",
+ };
+
+ const body = Object.entries(options)
+ .map((item) => `${item[0]}=${item[1]}`)
+ .join("&");
+
+ const response = await this.$request.post(api.accounts, {
+ headers: {
+ "Content-Type": "application/x-www-form-urlencoded",
+ },
+ body: body,
+ });
+
+ console.log(response);
+
+ if (!response.error) {
+ this.auth2 = null;
+ this.settings.auth2 = null;
+ this.settings.accessToken = {
+ ...this.settings.accessToken,
+ ...response,
+ time: new Date().getTime(),
+ };
+ console.log(
+ `获取 Token 成功,有效期 ${response.expires_in / (60 * 10)} 分钟`
+ );
+ this.saveSettings();
+ }
+ }
+ };
+
+ refreshToken = async () => {
+ const { accessToken, clientId } = this.settings;
+
+ const options = {
+ client_id: clientId,
+ grant_type: "refresh_token",
+ refresh_token: accessToken.refresh_token,
+ };
+
+ const body = Object.entries(options)
+ .map((item) => `${item[0]}=${item[1]}`)
+ .join("&");
+ const response = await this.$request.post(api.accounts, {
+ headers: {
+ "Content-Type": "application/x-www-form-urlencoded",
+ Authorization: this.accessToken,
+ },
+ body: body,
+ });
+ console.log("token 过期,更新");
+ console.log(response);
+ if (!response.error) {
+ this.auth2 = null;
+ this.settings.auth2 = null;
+ this.settings.accessToken = {
+ ...this.settings.accessToken,
+ ...response,
+ time: new Date().getTime(),
+ };
+ console.log(
+ `刷新 Token 成功,有效期 ${response.expires_in / (60 * 10)} 分钟`
+ );
+ this.saveSettings(false);
+ }
+ };
+
+ getWebToken = async () => {
+ const clientId = this.settings.clientId;
+ if (!clientId)
+ this.notify(
+ this.name,
+ "请到 Spotify 官网申请开发者账号创建 APP",
+ "https://developer.spotify.com"
+ );
+
+ this.settings.codeVerifier = generateRandomString(128);
+ this.saveSettings(false);
+
+ return WebView.loadURL(
+ `https://dompling.github.io/Spotify?clientId=${clientId}&codeVerifier=${
+ this.settings.codeVerifier
+ }&scope=${encodeURIComponent(scope.join(" "))}`
+ );
+ };
+
+ getApiRes = async (uri) => {
+ try {
+ const response = await this.$request.get(uri, {
+ headers: { Authorization: this.accessToken },
+ });
+ if (!response || response.error)
+ throw new Error(JSON.stringify(response));
+ return response;
+ } catch (error) {
+ console.log(error);
+ return {};
+ }
+ };
+
+ renderLarge = async (widget) => {
+ const { currentlyPlayingTrack, playlists, me, following } = this.dataSource;
+ if (currentlyPlayingTrack.is_playing) {
+ } else {
+ const containerStack = widget.addStack();
+ containerStack.layoutVertically();
+ const logoStack = containerStack.addStack();
+
+ logoStack.centerAlignContent();
+ logoStack.addSpacer();
+ const logoImage = await this.$request.get(logo, "IMG");
+ const logoImageWidget = logoStack.addImage(logoImage);
+ logoImageWidget.imageSize = new Size(20, 20);
+ logoImageWidget.centerAlignImage();
+
+ const meStack = containerStack.addStack();
+ meStack.centerAlignContent();
+
+ const avatarImage = await this.$request.get(
+ me.images[1]?.url || me.images[0]?.url,
+ "IMG"
+ );
+
+ const avatarStack = meStack.addImage(avatarImage);
+ avatarStack.imageSize = new Size(64, 64);
+ avatarStack.cornerRadius = avatarStack.imageSize.height / 2;
+
+ meStack.addSpacer(20);
+
+ const infoStack = meStack.addStack();
+ infoStack.layoutVertically();
+ this.provideText(me.display_name, infoStack, {
+ size: 16,
+ font: fontFamily,
+ });
+ infoStack.addSpacer(20);
+
+ this.provideText(me.email, infoStack, {
+ size: 12,
+ font: fontFamily,
+ });
+
+ containerStack.addSpacer(20);
+
+ const followStack = containerStack.addStack();
+ followStack.centerAlignContent();
+ this.provideText(`Following`, followStack, {
+ size: 16,
+ font: fontFamily,
+ });
+
+ followStack.addSpacer();
+
+ this.provideText(`${following.artists.total || 0}`, followStack, {
+ size: 16,
+ font: fontFamily,
+ });
+
+ containerStack.addSpacer(10);
+
+ const followingItemStack = containerStack.addStack();
+ followingItemStack.addSpacer();
+ const itemSize = new Size(48, 48);
+ for (let index = 0; index < following.artists.items.length; index++) {
+ if (index === 4) break;
+
+ const item = following.artists.items[index];
+ const itemImage = await this.$request.get(item.images[0].url, "IMG");
+ const itemImgStack = followingItemStack.addImage(itemImage);
+ itemImgStack.imageSize = itemSize;
+ itemImgStack.cornerRadius = itemSize.height / 2;
+ followingItemStack.addSpacer();
+ }
+
+ containerStack.addSpacer();
+
+ const playListStack = containerStack.addStack();
+
+ const listItems = playlists.items.reverse();
+ const bottomItems = [
+ listItems[0],
+ listItems[1],
+ listItems[2],
+ listItems[3],
+ ].filter((item) => !!item);
+
+ playListStack.addSpacer();
+
+ for (const index in bottomItems) {
+ const item = bottomItems[index];
+ const itemImage = await this.$request.get(item.images[0].url, "IMG");
+ const itemImageStack = playListStack.addImage(itemImage);
+ itemImageStack.cornerRadius = 6;
+ itemImageStack.imageSize = new Size(68, 68);
+ playListStack.addSpacer();
+ }
+
+ containerStack.addSpacer();
+ }
+ return widget;
+ };
+
+ renderMedium = async (widget) => {
+ const { currentlyPlayingTrack, playlists } = this.dataSource;
+ if (currentlyPlayingTrack.is_playing) {
+ const containerStack = widget.addStack();
+ const leftStack = containerStack.addStack();
+ leftStack.centerAlignContent();
+
+ const thumbImage = await this.$request.get(
+ currentlyPlayingTrack.item.album.images[0].url,
+ "IMG"
+ );
+ leftStack.addSpacer();
+ leftStack.size = new Size(140, 140);
+ const thumbImgStack = leftStack.addImage(thumbImage);
+ thumbImgStack.imageSize = leftStack.size;
+ thumbImgStack.cornerRadius = 12;
+ leftStack.addSpacer();
+
+ containerStack.addSpacer(20);
+
+ const rightStack = containerStack.addStack();
+ rightStack.layoutVertically();
+ rightStack.addSpacer();
+
+ const logoStack = rightStack.addStack();
+
+ logoStack.centerAlignContent();
+ logoStack.addSpacer();
+ const logoImage = await this.$request.get(logo, "IMG");
+ const logoImageWidget = logoStack.addImage(logoImage);
+ logoImageWidget.imageSize = new Size(20, 20);
+ logoImageWidget.centerAlignImage();
+
+ rightStack.addSpacer();
+
+ const nameStack = this.provideText(
+ currentlyPlayingTrack.item.name,
+ rightStack,
+ { size: 16, font: fontFamily }
+ );
+
+ nameStack.lineLimit = 1;
+ nameStack.minimumScaleFactor = 0.5;
+
+ rightStack.addSpacer();
+
+ const athorStack = this.provideText(
+ currentlyPlayingTrack.item.artists[0].name,
+ rightStack,
+ { size: 12, font: fontFamily }
+ );
+
+ athorStack.lineLimit = 1;
+ athorStack.minimumScaleFactor = 0.5;
+
+ rightStack.addSpacer();
+
+ const actionsStack = rightStack.addStack();
+
+ const preImage = SFSymbol.named("backward.end.fill").image;
+ const playImage = SFSymbol.named("pause.fill").image;
+ const nextImage = SFSymbol.named("forward.end.fill").image;
+
+ const iconSize = new Size(20, 20);
+ const preStack = actionsStack.addImage(preImage);
+ preStack.tintColor = this.widgetColor;
+ preStack.imageSize = iconSize;
+
+ actionsStack.addSpacer();
+
+ const playStack = actionsStack.addImage(playImage);
+ playStack.tintColor = this.widgetColor;
+ playStack.imageSize = iconSize;
+
+ actionsStack.addSpacer();
+
+ const nextStack = actionsStack.addImage(nextImage);
+ nextStack.tintColor = this.widgetColor;
+ nextStack.imageSize = iconSize;
+
+ rightStack.addSpacer();
+
+ containerStack.addSpacer();
+ } else {
+ const listItems = playlists.items.reverse();
+ const topItem = listItems[0];
+ const containerStack = widget.addStack();
+ containerStack.layoutVertically();
+ const topStack = containerStack.addStack();
+ topStack.centerAlignContent();
+
+ const topImg = await this.$request.get(topItem.images[0].url, "IMG");
+ const topImageStack = topStack.addImage(topImg);
+ topImageStack.cornerRadius = 6;
+ topImageStack.imageSize = new Size(50, 50);
+
+ topStack.addSpacer(20);
+
+ this.provideText(topItem.name, topStack, { font: fontFamily, size: 16 });
+
+ topStack.addSpacer();
+
+ const logoImage = await this.$request.get(logo, "IMG");
+ const logoImageWidget = topStack.addImage(logoImage);
+ logoImageWidget.imageSize = new Size(20, 20);
+
+ containerStack.addSpacer();
+
+ const bottomStack = containerStack.addStack();
+
+ const bottomItems = [
+ listItems[1],
+ listItems[2],
+ listItems[3],
+ listItems[4],
+ ].filter((item) => !!item);
+ for (const index in bottomItems) {
+ const item = bottomItems[index];
+ const itemImage = await this.$request.get(item.images[0].url, "IMG");
+ const itemImageStack = bottomStack.addImage(itemImage);
+ itemImageStack.cornerRadius = 6;
+ itemImageStack.imageSize = new Size(65, 65);
+ if (index !== bottomItems.length - 1) bottomStack.addSpacer();
+ }
+ }
+
+ return widget;
+ };
+
+ renderSmall = async (widget) => {
+ widget.setPadding(0, 0, 0, 0);
+ const { currentlyPlayingTrack, playlists } = this.dataSource;
+
+ if (currentlyPlayingTrack.is_playing) {
+ const iconSize = new Size(20, 20);
+
+ const containerStack = widget.addStack();
+ containerStack.setPadding(12, 12, 12, 12);
+ containerStack.layoutVertically();
+
+ const thumbImage = await this.$request.get(
+ currentlyPlayingTrack.item.album.images[0].url,
+ "IMG"
+ );
+ const opacityImg = await this.shadowImage(thumbImage, "#000", 0.3);
+ containerStack.backgroundImage = opacityImg;
+
+ const topStack = containerStack.addStack();
+ topStack.centerAlignContent();
+
+ const music = SFSymbol.named("timer.circle.fill").image;
+ const musicStack = topStack.addImage(music);
+ musicStack.tintColor = Color.white();
+ musicStack.imageSize = new Size(14, 14);
+
+ topStack.addSpacer(10);
+
+ this.provideText(
+ convertMillisecondsToHMS(currentlyPlayingTrack.item.duration_ms),
+ topStack,
+ { size: 12, font: fontFamily, color: Color.white() }
+ );
+
+ topStack.addSpacer();
+ const logoStack = topStack.addStack();
+ logoStack.centerAlignContent();
+
+ logoStack.addSpacer();
+ const logoImage = await this.$request.get(logo, "IMG");
+ const logoImageWidget = logoStack.addImage(logoImage);
+ logoImageWidget.imageSize = new Size(20, 20);
+ logoImageWidget.centerAlignImage();
+
+ containerStack.addSpacer();
+
+ const nameStack = this.provideText(
+ currentlyPlayingTrack.item.name,
+ containerStack,
+ { size: 16, font: fontFamily, color: Color.white() }
+ );
+
+ nameStack.lineLimit = 2;
+ containerStack.addSpacer();
+
+ const athorStack = this.provideText(
+ currentlyPlayingTrack.item.artists[0].name,
+ containerStack,
+ { size: 12, font: fontFamily, color: Color.white() }
+ );
+
+ athorStack.lineLimit = 1;
+ athorStack.minimumScaleFactor = 0.5;
+
+ containerStack.addSpacer();
+
+ const actionsStack = containerStack.addStack();
+
+ const preImage = SFSymbol.named("backward.end.fill").image;
+ const playImage = SFSymbol.named("pause.fill").image;
+ const nextImage = SFSymbol.named("forward.end.fill").image;
+
+ const preStack = actionsStack.addImage(preImage);
+ preStack.tintColor = Color.white();
+ preStack.imageSize = iconSize;
+
+ actionsStack.addSpacer();
+
+ const playStack = actionsStack.addImage(playImage);
+ playStack.tintColor = Color.white();
+ playStack.imageSize = iconSize;
+
+ actionsStack.addSpacer();
+
+ const nextStack = actionsStack.addImage(nextImage);
+ nextStack.tintColor = Color.white();
+ nextStack.imageSize = iconSize;
+ } else {
+ const listItems = playlists.items.reverse();
+ const topItem = listItems[0];
+
+ const containerStack = widget.addStack();
+ containerStack.setPadding(12, 12, 12, 12);
+ containerStack.layoutVertically();
+
+ const thumbImage = await this.$request.get(topItem.images[0].url, "IMG");
+ const opacityImg = await this.shadowImage(thumbImage, "#000", 0.3);
+ containerStack.backgroundImage = opacityImg;
+
+ const topStack = containerStack.addStack();
+ topStack.addSpacer();
+ const logoImage = await this.$request.get(logo, "IMG");
+ const logoImageWidget = topStack.addImage(logoImage);
+ logoImageWidget.imageSize = new Size(20, 20);
+
+ containerStack.addSpacer();
+
+ this.provideText(topItem.name, containerStack, {
+ font: fontFamily,
+ size: 16,
+ color: Color.white(),
+ });
+
+ containerStack.addSpacer();
+
+ const descStack = this.provideText(topItem.description, containerStack, {
+ font: fontFamily,
+ size: 12,
+ color: Color.white(),
+ });
+
+ descStack.lineLimit = 2;
+ descStack.minimumScaleFactor = 0.5;
+
+ containerStack.addSpacer();
+
+ const actionsStack = containerStack.addStack();
+ actionsStack.addSpacer();
+ actionsStack.centerAlignContent();
+
+ const heartImage = SFSymbol.named("heart.circle.fill").image;
+ const heartStack = actionsStack.addImage(heartImage);
+ heartStack.tintColor = Color.white();
+ heartStack.imageSize = new Size(20, 20);
+
+ actionsStack.addSpacer(5);
+
+ this.provideText(`${topItem.tracks.total}`, actionsStack, {
+ size: 14,
+ font: fontFamily,
+ color: Color.white(),
+ });
+ }
+
+ return widget;
+ };
+
+ renderAccessoryInline = async (widget) => {
+ return widget;
+ };
+
+ /**
+ * 渲染函数,函数名固定
+ * 可以根据 this.widgetFamily 来判断小组件尺寸,以返回不同大小的内容
+ */
+ async render() {
+ await this.init();
+ const widget = new ListWidget();
+ widget.useDefaultPadding();
+
+ await this.getWidgetBackgroundImage(widget);
+ if (this.widgetFamily === "small") await this.renderSmall(widget);
+ if (this.widgetFamily === "medium") await this.renderMedium(widget);
+ if (this.widgetFamily === "large") await this.renderLarge(widget);
+ if (this.widgetFamily == "accessoryInline")
+ await this.renderAccessoryInline(widget);
+
+ return widget;
+ }
+}
+
+// @组件代码结束
+await Runing(Widget, "", false); //远程开发环境
diff --git a/Scripts/VPNBoardPress.js b/Scripts/VPNBoardPress.js
index 13bd03b..f038939 100644
--- a/Scripts/VPNBoardPress.js
+++ b/Scripts/VPNBoardPress.js
@@ -482,8 +482,10 @@ completion(response);
Run = () => {
try {
if (config.runsInApp) {
- this.registerAction('默认账号', this.actionSettings);
- this.registerAction('清除账号', this.deletedVpn);
+ this.registerAction('默认账号', this.actionSettings, {
+ name: "text.badge.star",
+ color: "#a0d911",
+ });
this.registerAction('新增账号', async () => {
const account = await this.setAlertInput(
'添加账号', '添加账号数据,添加完成之后请去设置默认账号', {
@@ -502,6 +504,13 @@ completion(response);
this.settings.dataSource = this.settings.dataSource.filter(
item => item);
this.saveSettings();
+ },{
+ name: "text.badge.plus",
+ color: "#fadb14",
+ });
+ this.registerAction('清除账号', this.deletedVpn, {
+ name: "text.badge.xmark",
+ color: "#f5222d",
});
this.registerAction('基础设置', this.setWidgetConfig);
}
diff --git a/Scripts/VPNSubscription.js b/Scripts/VPNSubscription.js
index 285525b..fec9982 100644
--- a/Scripts/VPNSubscription.js
+++ b/Scripts/VPNSubscription.js
@@ -3,39 +3,40 @@
// icon-color: deep-gray; icon-glyph: paper-plane;
// 添加require,是为了vscode中可以正确引入包,以获得自动补全等功能
-if (typeof require === 'undefined') require = importModule;
-const {DmYY, Runing} = require('./DmYY');
+if (typeof require === "undefined") require = importModule;
+const { DmYY, Runing } = require("./DmYY");
// @组件代码开始
class Widget extends DmYY {
constructor(arg) {
super(arg);
- this.name = 'VPNSubscription';
- this.en = 'VPNSubscription';
+ this.name = "VPNSubscription";
+ this.en = "VPNSubscription";
this.CACHE_KEY = this.md5(`dataSouce_${this.en}`);
this.Run();
}
useBoxJS = false;
- today = '';
- logo = 'https://raw.githubusercontent.com/58xinian/icon/master/glados_animation.gif';
+ today = "";
+ logo =
+ "https://raw.githubusercontent.com/58xinian/icon/master/glados_animation.gif";
dataSource = {
- restData: '0',
- usedData: '0',
- totalData: '0',
- todayData: '0',
+ restData: "0",
+ usedData: "0",
+ totalData: "0",
+ todayData: "0",
isCheckIn: false,
};
account = {
- title: '',
- url: '',
+ title: "",
+ url: "",
};
- color1 = ['#ef0a6a', '#b6359c'];
- color2 = ['#ff54fa', '#fad126'];
- color3 = ['#28cfb3', '#72d7cc'];
+ color1 = ["#ef0a6a", "#b6359c"];
+ color2 = ["#ff54fa", "#fad126"];
+ color3 = ["#28cfb3", "#72d7cc"];
chartConfig = (data, color, value) => {
console.log(data);
@@ -49,7 +50,8 @@ class Widget extends DmYY {
"data": [${parseFloat(data[0])}],
"borderWidth": 0,
"backgroundColor": getGradientFillHelper('vertical', ${JSON.stringify(
- color[0])}),
+ color[0]
+ )}),
}
]
},
@@ -75,7 +77,8 @@ class Widget extends DmYY {
"data": [${parseFloat(data[1])}],
"borderWidth": 0,
"backgroundColor": getGradientFillHelper('vertical', ${JSON.stringify(
- color[1])}),
+ color[1]
+ )}),
}
]
},
@@ -108,7 +111,8 @@ class Widget extends DmYY {
"data": [${parseFloat(data[2])}],
"borderWidth": 0,
"backgroundColor": getGradientFillHelper('vertical', ${JSON.stringify(
- color[2])}),
+ color[2]
+ )}),
}
]
},
@@ -140,7 +144,7 @@ class Widget extends DmYY {
console.log(template1);
console.log(template2);
console.log(template3);
- return {template1, template2, template3};
+ return { template1, template2, template3 };
};
init = async () => {
@@ -162,13 +166,13 @@ class Widget extends DmYY {
async getdata(url) {
const req = new Request(url);
- req.method = 'GET';
+ req.method = "GET";
await req.load();
- let resp = req.response.headers['subscription-userinfo'];
+ let resp = req.response.headers["subscription-userinfo"];
resp = [
- (parseInt(resp.match(/upload=([0-9]+);?/)[1])).toFixed(2),
- (parseInt(resp.match(/download=([0-9]+);?/)[1])).toFixed(2),
- (parseInt(resp.match(/total=([0-9]+);?/)[1])).toFixed(2),
+ parseInt(resp.match(/upload=([0-9]+);?/)[1]).toFixed(2),
+ parseInt(resp.match(/download=([0-9]+);?/)[1]).toFixed(2),
+ parseInt(resp.match(/total=([0-9]+);?/)[1]).toFixed(2),
];
console.log(resp);
return resp;
@@ -176,35 +180,36 @@ class Widget extends DmYY {
gradient = (color) => {
const linear = new LinearGradient();
- linear.colors = color.map(item => new Color(item));
+ linear.colors = color.map((item) => new Color(item));
linear.locations = [0, 0.5];
return linear;
};
formatFileSize(fileSize) {
- if (fileSize < (1024 * 1024)) {
+ if (fileSize < 1024 * 1024) {
let temp = fileSize / 1024;
temp = temp.toFixed(2);
- return temp + 'KB';
- } else if (fileSize < (1024 * 1024 * 1024)) {
+ return temp + "KB";
+ } else if (fileSize < 1024 * 1024 * 1024) {
let temp = fileSize / (1024 * 1024);
temp = temp.toFixed(2);
- return temp + 'MB';
- } else if (fileSize < (1024 * 1024 * 1024 * 1024)) {
+ return temp + "MB";
+ } else if (fileSize < 1024 * 1024 * 1024 * 1024) {
let temp = fileSize / (1024 * 1024 * 1024);
temp = temp.toFixed(2);
- return temp + 'GB';
+ return temp + "GB";
} else {
let temp = fileSize / (1024 * 1024 * 1024 * 1024);
temp = temp.toFixed(2);
- return temp + 'TB';
+ return temp + "TB";
}
}
createChart = async (size, chart) => {
- const url = `https://quickchart.io/chart?w=${size.w}&h=${size.h}&f=png&c=${encodeURIComponent(
- chart)}`;
- return await this.$request.get(url, 'IMG');
+ const url = `https://quickchart.io/chart?w=${size.w}&h=${
+ size.h
+ }&f=png&c=${encodeURIComponent(chart)}`;
+ return await this.$request.get(url, "IMG");
};
setContent = async (w, size, viewSize) => {
@@ -212,16 +217,14 @@ class Widget extends DmYY {
const use = this.dataSource.usedData;
const today = this.dataSource.todayData;
const total = this.dataSource.totalData;
- const data1 = Math.floor(rest / total * 100);
- const data2 = Math.floor(use / total * 100);
+ const data1 = Math.floor((rest / total) * 100);
+ const data2 = Math.floor((use / total) * 100);
const data3 = Math.floor((today / total) * 100);
- const data = [
- data1 || 0, data2 || 0, data3 || 0,
- ];
- const {template1, template2, template3} = this.chartConfig(
- data,
- [this.color1, this.color2, this.color3],
- this.formatFileSize(this.dataSource.restData),
+ const data = [data1 || 0, data2 || 0, data3 || 0];
+ const { template1, template2, template3 } = this.chartConfig(
+ data,
+ [this.color1, this.color2, this.color3],
+ this.formatFileSize(this.dataSource.restData)
);
const stackContent = w.addStack();
@@ -237,7 +240,6 @@ class Widget extends DmYY {
const stackContent3 = stackContent2.addStack();
stackContent3.size = stackSize;
stackContent3.backgroundImage = await this.createChart(size, template3);
-
};
setLabelCell = async (stack, data) => {
@@ -250,7 +252,7 @@ class Widget extends DmYY {
stackIcon.cornerRadius = 8;
if (data.isImg) {
try {
- const icon = await this.$request.get(data.icon, 'IMG');
+ const icon = await this.$request.get(data.icon, "IMG");
stackIcon.addImage(icon);
} catch (e) {
console.log(e);
@@ -262,14 +264,14 @@ class Widget extends DmYY {
stackCell.addSpacer(5);
const stackTitle = stackCell.addStack();
- const title = {...this.textFormat.title};
+ const title = { ...this.textFormat.title };
title.color = this.widgetColor;
this.provideText(data.title, stackTitle, title);
stackCell.addSpacer(5);
const stackValue = stackCell.addStack();
- const value = {...this.textFormat.defaultText};
+ const value = { ...this.textFormat.defaultText };
value.color = this.widgetColor;
this.provideText(data.value, stackValue, title);
@@ -277,7 +279,7 @@ class Widget extends DmYY {
};
setFooterCell = (stack, data) => {
- const title = {...this.textFormat.title};
+ const title = { ...this.textFormat.title };
title.color = this.widgetColor;
title.size = 10;
@@ -298,7 +300,7 @@ class Widget extends DmYY {
this.provideText(data.value, stackText, title);
stackText.addSpacer();
- const desc = {...this.textFormat.defaultText};
+ const desc = { ...this.textFormat.defaultText };
desc.color = this.widgetColor;
desc.size = 8;
@@ -315,7 +317,9 @@ class Widget extends DmYY {
stackLeft.centerAlignContent();
try {
const imgIcon = await this.$request.get(
- this.account.icon || this.logo, 'IMG');
+ this.account.icon || this.logo,
+ "IMG"
+ );
const stackImgItem = stackLeft.addImage(imgIcon);
stackImgItem.imageSize = new Size(12, 12);
stackImgItem.cornerRadius = 4;
@@ -323,7 +327,7 @@ class Widget extends DmYY {
} catch (e) {
console.log(e);
}
- const title = {...this.textFormat.title};
+ const title = { ...this.textFormat.title };
title.color = this.widgetColor;
title.size = 12;
this.provideText(this.account.title, stackLeft, title);
@@ -331,18 +335,21 @@ class Widget extends DmYY {
const stackRight = stackHeader.addStack();
stackRight.centerAlignContent();
- const calendar = SFSymbol.named('waveform.path.badge.minus');
+ const calendar = SFSymbol.named("waveform.path.badge.minus");
const imgCalendar = stackRight.addImage(calendar.image);
imgCalendar.imageSize = new Size(12, 12);
- imgCalendar.tintColor = new Color('#00b800');
+ imgCalendar.tintColor = new Color("#00b800");
stackRight.addSpacer(5);
this.provideText(
- this.formatFileSize(this.dataSource.todayData), stackRight, title);
+ this.formatFileSize(this.dataSource.todayData),
+ stackRight,
+ title
+ );
w.addSpacer();
const stackContent = w.addStack();
stackContent.addSpacer();
- await this.setContent(stackContent, {w: 360, h: 360}, new Size(80, 80));
+ await this.setContent(stackContent, { w: 360, h: 360 }, new Size(80, 80));
stackContent.addSpacer();
w.addSpacer();
@@ -352,7 +359,7 @@ class Widget extends DmYY {
const stackFooterLeft = stackFooter.addStack();
this.setFooterCell(stackFooterLeft, {
value: this.formatFileSize(this.dataSource.restData),
- label: '剩余',
+ label: "剩余",
color: this.color1,
});
@@ -361,7 +368,7 @@ class Widget extends DmYY {
const stackFooterRight = stackFooter.addStack();
this.setFooterCell(stackFooterRight, {
value: this.formatFileSize(this.dataSource.usedData),
- label: '累计',
+ label: "累计",
color: this.color2,
});
@@ -371,48 +378,38 @@ class Widget extends DmYY {
renderMedium = async (w) => {
const stackBody = w.addStack();
const stackLeft = stackBody.addStack();
- await this.setContent(stackLeft, {w: 360, h: 360}, new Size(140, 140));
+ await this.setContent(stackLeft, { w: 360, h: 360 }, new Size(140, 140));
stackBody.addSpacer(10);
const stackRight = stackBody.addStack();
stackRight.layoutVertically();
- await this.setLabelCell(
- stackRight, {
- icon: this.account.icon || this.logo,
- title: this.account.title,
- value: ``,
- isImg: true,
- });
- await this.setLabelCell(
- stackRight,
- {
- icon: this.gradient(this.color3),
- title: '上传',
- value: this.formatFileSize(this.dataSource.todayData),
- },
- );
- await this.setLabelCell(
- stackRight,
- {
- icon: this.gradient(this.color2),
- title: '累计',
- value: this.formatFileSize(this.dataSource.usedData),
- },
- );
+ await this.setLabelCell(stackRight, {
+ icon: this.account.icon || this.logo,
+ title: this.account.title,
+ value: ``,
+ isImg: true,
+ });
+ await this.setLabelCell(stackRight, {
+ icon: this.gradient(this.color3),
+ title: "上传",
+ value: this.formatFileSize(this.dataSource.todayData),
+ });
+ await this.setLabelCell(stackRight, {
+ icon: this.gradient(this.color2),
+ title: "累计",
+ value: this.formatFileSize(this.dataSource.usedData),
+ });
- await this.setLabelCell(
- stackRight,
- {
- icon: this.gradient(this.color1),
- title: '剩余',
- value: this.formatFileSize(this.dataSource.restData),
- },
- );
+ await this.setLabelCell(stackRight, {
+ icon: this.gradient(this.color1),
+ title: "剩余",
+ value: this.formatFileSize(this.dataSource.restData),
+ });
return w;
};
renderLarge = async (w) => {
- w.addText('暂不支持');
+ w.addText("暂不支持");
return w;
};
@@ -424,9 +421,9 @@ class Widget extends DmYY {
await this.init();
const widget = new ListWidget();
await this.getWidgetBackgroundImage(widget);
- if (this.widgetFamily === 'medium') {
+ if (this.widgetFamily === "medium") {
return await this.renderMedium(widget);
- } else if (this.widgetFamily === 'large') {
+ } else if (this.widgetFamily === "large") {
return await this.renderLarge(widget);
} else {
return await this.renderSmall(widget);
@@ -436,33 +433,51 @@ class Widget extends DmYY {
Run = () => {
try {
if (config.runsInApp) {
- this.registerAction('默认订阅', this.actionSettings);
- this.registerAction('清除订阅', this.deletedVpn);
- this.registerAction('新增订阅', async () => {
+ this.registerAction("默认订阅", this.actionSettings, {
+ name: "text.badge.star",
+ color: "#a0d911",
+ });
+ this.registerAction("新增订阅", async () => {
const account = await this.setAlertInput(
- '添加订阅', '添加订阅数据,添加完成之后请去设置默认订阅', {
- title: '机场名',
- icon: '图标',
- url: '订阅地址',
- }, false);
+ "添加订阅",
+ "添加订阅数据,添加完成之后请去设置默认订阅",
+ {
+ title: "机场名",
+ icon: "图标",
+ url: "订阅地址",
+ },
+ false
+ );
if (!this.settings.dataSource) this.settings.dataSource = [];
if (!account) return;
if (account.title && account.url) {
this.settings.dataSource.push(account);
}
this.settings.dataSource = this.settings.dataSource.filter(
- item => item);
+ (item) => item
+ );
this.saveSettings();
+ },{
+ name: "text.badge.plus",
+ color: "#fadb14",
});
- this.registerAction('基础设置', this.setWidgetConfig);
+ this.registerAction("清除订阅", this.deletedVpn, {
+ name: "text.badge.xmark",
+ color: "#f5222d",
+ });
+ this.registerAction("基础设置", this.setWidgetConfig);
}
this.account = this.settings.account || this.account;
- this.CACHE_KEY += '_' + this.account.title;
- const index = typeof args.widgetParameter === 'string' ? parseInt(
- args.widgetParameter) : false;
- if (this.settings.dataSource && this.settings.dataSource[index] &&
- index !==
- false) {
+ this.CACHE_KEY += "_" + this.account.title;
+ const index =
+ typeof args.widgetParameter === "string"
+ ? parseInt(args.widgetParameter)
+ : false;
+ if (
+ this.settings.dataSource &&
+ this.settings.dataSource[index] &&
+ index !== false
+ ) {
this.account = this.settings.dataSource[index];
}
} catch (e) {
@@ -510,9 +525,8 @@ class Widget extends DmYY {
console.log(e);
}
}
-
}
// @组件代码结束
// await Runing(Widget, "", false); // 正式环境
-await Runing(Widget, '', false); //远程开发环境
+await Runing(Widget, "", false); //远程开发环境
diff --git a/Scripts/VpnBoard.js b/Scripts/VpnBoard.js
index 47401d3..d1b1afa 100644
--- a/Scripts/VpnBoard.js
+++ b/Scripts/VpnBoard.js
@@ -3,24 +3,24 @@
// icon-color: deep-gray; icon-glyph: paper-plane;
// 添加require,是为了vscode中可以正确引入包,以获得自动补全等功能
-if (typeof require === 'undefined') require = importModule;
-const {DmYY, Runing} = require('./DmYY');
+if (typeof require === "undefined") require = importModule;
+const { DmYY, Runing } = require("./DmYY");
// @组件代码开始
class Widget extends DmYY {
constructor(arg) {
super(arg);
- this.name = 'Vpn';
- this.en = 'vpnBoard';
+ this.name = "Vpn";
+ this.en = "vpnBoard";
this.CACHE_KEY = this.md5(`dataSouce_${this.en}`);
this.Run();
}
useBoxJS = false;
dataSource = {
- restData: '0',
- usedData: '0',
- todayUsed: '0',
+ restData: "0",
+ usedData: "0",
+ todayUsed: "0",
isCheckIn: false,
};
@@ -28,9 +28,9 @@ class Widget extends DmYY {
const color = `#${this.widgetColor.hex}`;
let template;
let path = this.FILE_MGR.documentsDirectory();
- path = path + '/VPNBoardTemplate.js';
+ path = path + "/VPNBoardTemplate.js";
if (this.FILE_MGR.fileExists(path)) {
- template = require('./VPNBoardTemplate');
+ template = require("./VPNBoardTemplate");
} else {
template = `
{
@@ -118,27 +118,27 @@ const template = \`${template}\`;
module.exports = template;`;
this.FILE_MGR.writeString(path, content);
}
- template = template.replaceAll('__COLOR__', `'${color}'`);
- template = template.replace('__LABELS__', `${JSON.stringify(labels)}`);
- template = template.replace('__TEXT__', `${JSON.stringify(text)}`);
- template = template.replace('__DATAS__', `${JSON.stringify(datas)}`);
+ template = template.replaceAll("__COLOR__", `'${color}'`);
+ template = template.replace("__LABELS__", `${JSON.stringify(labels)}`);
+ template = template.replace("__TEXT__", `${JSON.stringify(text)}`);
+ template = template.replace("__DATAS__", `${JSON.stringify(datas)}`);
return template;
};
account = {
- title: '',
- url: '',
- email: '',
- password: '',
+ title: "",
+ url: "",
+ email: "",
+ password: "",
};
range = {
- '11.1': {todayUsed: '30M'},
- '11.2': {todayUsed: '130M'},
- '11.3': {todayUsed: '300M'},
- '11.4': {todayUsed: '30M'},
- '11.5': {todayUsed: '2g'},
- '11.6': {todayUsed: '3G'},
+ 11.1: { todayUsed: "30M" },
+ 11.2: { todayUsed: "130M" },
+ 11.3: { todayUsed: "300M" },
+ 11.4: { todayUsed: "30M" },
+ 11.5: { todayUsed: "2g" },
+ 11.6: { todayUsed: "3G" },
};
max = 6;
@@ -153,7 +153,7 @@ module.exports = template;`;
}
const date = new Date();
const format = new DateFormatter();
- format.dateFormat = 'MM.dd';
+ format.dateFormat = "MM.dd";
const dateDay = format.string(date);
this.range[dateDay] = this.dataSource;
const rangeKey = Object.keys(this.range);
@@ -173,25 +173,28 @@ module.exports = template;`;
const table = {
url: this.account.url,
body: `email=${encodeURIComponent(
- this.account.email)}&passwd=${encodeURIComponent(
- this.account.password)}&remember_me=on&rumber-me=week`,
+ this.account.email
+ )}&passwd=${encodeURIComponent(
+ this.account.password
+ )}&remember_me=on&rumber-me=week`,
};
const request = new Request(table.url);
request.body = table.body;
- request.method = 'POST';
+ request.method = "POST";
const data = await request.loadString();
try {
if (
- JSON.parse(data).msg.match(
- /邮箱不存在|邮箱或者密码错误|Mail or password is incorrect/,
- )
+ JSON.parse(data).msg.match(
+ /邮箱不存在|邮箱或者密码错误|Mail or password is incorrect/
+ )
) {
- this.notify(this.name, '邮箱或者密码错误');
- console.log('登陆失败');
- this.cookie = request.response.cookies(
- item => `${item.name}=${item.value}`).join('; ');
+ this.notify(this.name, "邮箱或者密码错误");
+ console.log("登陆失败");
+ this.cookie = request.response
+ .cookies((item) => `${item.name}=${item.value}`)
+ .join("; ");
} else {
- console.log('登陆成功');
+ console.log("登陆成功");
}
} catch (e) {
console.log(e);
@@ -201,28 +204,27 @@ module.exports = template;`;
async checkin() {
const url = this.account.url;
let checkinPath =
- url.indexOf('auth/login') !== -1 ? 'user/checkin' : 'user/_checkin.php';
+ url.indexOf("auth/login") !== -1 ? "user/checkin" : "user/_checkin.php";
const checkinreqest = {
- url: url.replace(/(auth|user)\/login(.php)*/g, '') + checkinPath,
+ url: url.replace(/(auth|user)\/login(.php)*/g, "") + checkinPath,
headers: {
cookie: this.cookie,
},
};
- const data = await this.$request.post(checkinreqest, 'STRING');
+ const data = await this.$request.post(checkinreqest, "STRING");
if (data.match(/\"msg\"\:/)) {
- console.log('签到成功');
+ console.log("签到成功");
this.dataSource.isCheckIn = true;
} else {
- console.log('签到失败');
+ console.log("签到失败");
}
}
async dataResults() {
let url = this.account.url;
- const userPath = url.indexOf('auth/login') !== -1
- ? 'user'
- : 'user/index.php';
- url = url.replace(/(auth|user)\/login(.php)*/g, '') + userPath;
+ const userPath =
+ url.indexOf("auth/login") !== -1 ? "user" : "user/index.php";
+ url = url.replace(/(auth|user)\/login(.php)*/g, "") + userPath;
const webView = new WebView();
await webView.loadURL(url);
const js = `
@@ -239,21 +241,21 @@ if($('.progressbar').length){
completion(response);
`;
const response = await webView.evaluateJavaScript(js, true);
- this.dataSource = {...this.dataSource, ...response};
+ this.dataSource = { ...this.dataSource, ...response };
}
translateFlow(value) {
const unit = [
- {unit: 'T', value: 1024 * 1024},
- {unit: 'G', value: 1024},
- {unit: 'M', value: 1},
- {unit: 'K', value: 1 / 1024},
+ { unit: "T", value: 1024 * 1024 },
+ { unit: "G", value: 1024 },
+ { unit: "M", value: 1 },
+ { unit: "K", value: 1 / 1024 },
];
- const data = {unit: '', value: parseFloat(value)};
- unit.forEach(item => {
+ const data = { unit: "", value: parseFloat(value) };
+ unit.forEach((item) => {
if (value.indexOf(item.unit) > -1) {
data.unit = item.unit;
- data.value = Math.floor((parseFloat(value) * item.value) * 100) / 100;
+ data.value = Math.floor(parseFloat(value) * item.value * 100) / 100;
}
});
@@ -261,7 +263,9 @@ completion(response);
}
createChart = async (size) => {
- let labels = [], data = [], text = [];
+ let labels = [],
+ data = [],
+ text = [];
const rangeKey = Object.keys(this.range);
rangeKey.forEach((key) => {
labels.push(key);
@@ -270,31 +274,32 @@ completion(response);
data.push(valueUnit.value);
text.push(value);
});
- if (this.widgetSize === 'small') {
+ if (this.widgetSize === "small") {
labels = labels.slice(-3);
data = data.slice(-3);
}
console.log(data);
const chart = this.chartConfig(labels, data, text);
console.log(chart);
- const url = `https://quickchart.io/chart?w=${size.w}&h=${size.h}&f=png&c=${encodeURIComponent(
- chart)}`;
- return await this.$request.get(url, 'IMG');
+ const url = `https://quickchart.io/chart?w=${size.w}&h=${
+ size.h
+ }&f=png&c=${encodeURIComponent(chart)}`;
+ return await this.$request.get(url, "IMG");
};
createDivider(w) {
const drawContext = new DrawContext();
- drawContext.size = new Size(543, this.widgetSize === 'small' ? 4 : 2);
+ drawContext.size = new Size(543, this.widgetSize === "small" ? 4 : 2);
const path = new Path();
path.addLine(new Point(1000, 20));
drawContext.addPath(path);
- drawContext.setStrokeColor(new Color('#000', 1));
+ drawContext.setStrokeColor(new Color("#000", 1));
drawContext.setLineWidth(2);
drawContext.strokePath();
const stackLine = w.addStack();
stackLine.borderWidth = 1;
- stackLine.borderColor = new Color('#000', 0.4);
+ stackLine.borderColor = new Color("#000", 0.4);
stackLine.addImage(drawContext.getImage());
w.addSpacer(5);
}
@@ -304,14 +309,15 @@ completion(response);
header.centerAlignContent();
const left = header.addStack();
left.centerAlignContent();
- let icon = 'https://raw.githubusercontent.com/58xinian/icon/master/glados_animation.gif';
+ let icon =
+ "https://raw.githubusercontent.com/58xinian/icon/master/glados_animation.gif";
if (this.account.icon) icon = this.account.icon;
const stackIcon = left.addStack();
try {
- const imgIcon = await this.$request.get(icon, 'IMG');
+ const imgIcon = await this.$request.get(icon, "IMG");
const imgIconItem = stackIcon.addImage(imgIcon);
let iconSize = new Size(16, 16);
- if (this.widgetSize === 'small') iconSize = new Size(12, 12);
+ if (this.widgetSize === "small") iconSize = new Size(12, 12);
imgIconItem.imageSize = iconSize;
imgIconItem.cornerRadius = 4;
left.addSpacer(5);
@@ -319,7 +325,7 @@ completion(response);
console.log(e);
}
- const vpnName = {...this.textFormat.title};
+ const vpnName = { ...this.textFormat.title };
vpnName.size = size;
vpnName.color = this.widgetColor;
this.provideText(this.account.title, left, vpnName);
@@ -328,17 +334,21 @@ completion(response);
const right = header.addStack();
right.bottomAlignContent();
- const vpnFlow = {...this.textFormat.title};
- vpnFlow.color = new Color('#26c5bc');
+ const vpnFlow = { ...this.textFormat.title };
+ vpnFlow.color = new Color("#26c5bc");
vpnFlow.size = size;
- this.provideText(this.dataSource.isCheckIn ? '已签到' : '未签到', right, vpnFlow);
+ this.provideText(
+ this.dataSource.isCheckIn ? "已签到" : "未签到",
+ right,
+ vpnFlow
+ );
w.addSpacer();
- };
+ }
setLabel(w, data, size) {
const stackLabel = w.addStack();
- const textBattery = {...this.textFormat.battery};
+ const textBattery = { ...this.textFormat.battery };
textBattery.size = size.label;
textBattery.color = this.widgetColor;
this.provideText(data.label, stackLabel, textBattery);
@@ -355,20 +365,26 @@ completion(response);
footer.centerAlignContent();
this.setLabel(
- footer, {
- label: '剩余:',
- color: '#ff3e3e',
- value: this.dataSource.restData,
- unit: 'GB',
- }, size);
+ footer,
+ {
+ label: "剩余:",
+ color: "#ff3e3e",
+ value: this.dataSource.restData,
+ unit: "GB",
+ },
+ size
+ );
footer.addSpacer();
this.setLabel(
- footer, {
- label: '累计:',
- color: '#dc9e28',
- value: this.dataSource.usedData,
- unit: 'GB',
- }, size);
+ footer,
+ {
+ label: "累计:",
+ color: "#dc9e28",
+ value: this.dataSource.usedData,
+ unit: "GB",
+ },
+ size
+ );
}
setContent = async (w, size) => {
@@ -379,22 +395,22 @@ completion(response);
renderSmall = async (w) => {
await this.setHeader(w, 10);
- await this.setContent(w, {w: 195, h: 85});
+ await this.setContent(w, { w: 195, h: 85 });
this.createDivider(w);
- this.setFooter(w, {label: 6, value: 8});
+ this.setFooter(w, { label: 6, value: 8 });
return w;
};
renderMedium = async (w) => {
await this.setHeader(w, 16);
- await this.setContent(w, {w: 390, h: 85});
+ await this.setContent(w, { w: 390, h: 85 });
this.createDivider(w);
- this.setFooter(w, {label: 14, value: 18});
+ this.setFooter(w, { label: 14, value: 18 });
return w;
};
renderLarge = async (w) => {
- w.addText('暂不支持');
+ w.addText("暂不支持");
return w;
};
@@ -406,9 +422,9 @@ completion(response);
await this.init();
const widget = new ListWidget();
await this.getWidgetBackgroundImage(widget);
- if (this.widgetFamily === 'medium') {
+ if (this.widgetFamily === "medium") {
return await this.renderMedium(widget);
- } else if (this.widgetFamily === 'large') {
+ } else if (this.widgetFamily === "large") {
return await this.renderLarge(widget);
} else {
return await this.renderSmall(widget);
@@ -418,36 +434,62 @@ completion(response);
Run = () => {
try {
if (config.runsInApp) {
- this.registerAction('默认账号', this.actionSettings);
- this.registerAction('清除账号', this.deletedVpn);
- this.registerAction('新增账号', async () => {
- const account = await this.setAlertInput(
- '添加账号', '添加账号数据,添加完成之后请去设置默认账号', {
- title: '机场名',
- icon: '图标',
- url: '登陆地址',
- email: '邮箱账号',
- password: '密码',
- }, false);
- if (!this.settings.dataSource) this.settings.dataSource = [];
- if (!account) return;
- if (account.title && account.url && account.email &&
- account.password) {
- this.settings.dataSource.push(account);
+ this.registerAction("默认账号", this.actionSettings, {
+ name: "text.badge.star",
+ color: "#a0d911",
+ });
+ this.registerAction(
+ "新增账号",
+ async () => {
+ const account = await this.setAlertInput(
+ "添加账号",
+ "添加账号数据,添加完成之后请去设置默认账号",
+ {
+ title: "机场名",
+ icon: "图标",
+ url: "登陆地址",
+ email: "邮箱账号",
+ password: "密码",
+ },
+ false
+ );
+ if (!this.settings.dataSource) this.settings.dataSource = [];
+ if (!account) return;
+ if (
+ account.title &&
+ account.url &&
+ account.email &&
+ account.password
+ ) {
+ this.settings.dataSource.push(account);
+ }
+ this.settings.dataSource = this.settings.dataSource.filter(
+ (item) => item
+ );
+ this.saveSettings();
+ },
+ {
+ name: "text.badge.plus",
+ color: "#fadb14",
}
- this.settings.dataSource = this.settings.dataSource.filter(
- item => item);
- this.saveSettings();
+ );
+ this.registerAction("清除账号", this.deletedVpn, {
+ name: "text.badge.xmark",
+ color: "#f5222d",
});
- this.registerAction('基础设置', this.setWidgetConfig);
+ this.registerAction("基础设置", this.setWidgetConfig);
}
this.account = this.settings.account || this.account;
- this.CACHE_KEY += '_' + this.account.title;
- const index = typeof args.widgetParameter === 'string' ? parseInt(
- args.widgetParameter) : false;
- if (this.settings.dataSource && this.settings.dataSource[index] &&
- index !==
- false) {
+ this.CACHE_KEY += "_" + this.account.title;
+ const index =
+ typeof args.widgetParameter === "string"
+ ? parseInt(args.widgetParameter)
+ : false;
+ if (
+ this.settings.dataSource &&
+ this.settings.dataSource[index] &&
+ index !== false
+ ) {
this.account = this.settings.dataSource[index];
}
} catch (e) {
@@ -461,7 +503,9 @@ completion(response);
const dataSource = this.settings.dataSource || [];
dataSource.map((t, index) => {
const r = new UITableRow();
- r.addText(`parameter:${index} 机场名:${t.title} 账号:${t.email}`);
+ r.addText(
+ `parameter:${index} 机场名:${t.title} 账号:${t.email}`
+ );
r.onSelect = (n) => {
this.settings.account = t;
this.notify(t.title, `默认账号设置成功\n账号:${t.email}`);
@@ -495,9 +539,8 @@ completion(response);
console.log(e);
}
}
-
}
// @组件代码结束
// await Runing(Widget, "", false); // 正式环境
-await Runing(Widget, '', false); //远程开发环境
+await Runing(Widget, "", false); //远程开发环境
diff --git a/Scripts/birthday.js b/Scripts/birthday.js
index 2afa9f4..255acf8 100644
--- a/Scripts/birthday.js
+++ b/Scripts/birthday.js
@@ -5,34 +5,51 @@
// 添加require,是为了vscode中可以正确引入包,以获得自动补全等功能
if (typeof require === "undefined") require = importModule;
const { DmYY, Runing } = require("./DmYY");
-const mainTextSize = 13; // 倒数、农历、生日文字大小
-const now = new Date();
-const today = `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}`;
+let mainTextSize = 13; // 倒数、农历、生日文字大小
-const widthMode = Device.model() === "iPad" ? 110 : 400; // 中号组件图片尺寸
+let widthMode = 110; // 中号组件图片尺寸
-const heightMode = Device.model() === "iPad" ? 100 : 380; // 中号组件图片尺寸
+let heightMode = 100; // 中号组件图片尺寸
// @组件代码开始
class Widget extends DmYY {
constructor(arg) {
- super(arg, {
- lightBgColor: "#2581f2",
- darkBgColor: "#2581f2",
- darkColor: "#fff",
- lightColor: "#fff",
- });
+ super(arg);
this.en = "birthday";
this.name = "破壳日";
this.LEFT_IMG_KEY = `${this.cacheImage}/avatar`;
if (config.runsInApp) {
this.registerAction({
- icon: { name: "person.badge.plus", color: "#52c41a" },
- type: "img",
- title: "头像",
- name: "avatar",
- val: this.cacheImage,
+ title: "头像设置",
+ menu: [
+ {
+ icon: { name: "person.badge.plus", color: "#52c41a" },
+ type: "img",
+ title: "头像",
+ name: "avatar",
+ val: this.cacheImage,
+ },
+ {
+ icon: { name: "arrow.left.and.right", color: "#13c2c2" },
+ type: "input",
+ title: "头像宽度",
+ name: "avatarWidth",
+ },
+ {
+ icon: { name: "arrow.up.and.down", color: "#1890ff" },
+ type: "input",
+ title: "头像高度",
+ name: "avatarHeight",
+ },
+ ],
+ });
+
+ this.registerAction({
+ icon: { name: "a.square", color: "#eb2f96" },
+ type: "input",
+ title: "主文字大小",
+ name: "mainTextSize",
});
this.registerAction({
@@ -286,6 +303,10 @@ class Widget extends DmYY {
};
init = async () => {
+ widthMode = Number(this.settings.avatarWidth) || widthMode;
+ heightMode = Number(this.settings.avatarHeight) || heightMode;
+ mainTextSize = Number(this.settings.mainTextSize) || mainTextSize;
+
await this.FILE_MGR.fileExistsExtra(this.LEFT_IMG_KEY);
this.defaultData = {
username: this.settings.nickname || "", // 姓名
@@ -311,7 +332,6 @@ class Widget extends DmYY {
this.ajax(opt).then((res) => {
this.settings.ajax = res;
this.saveSettings(false);
-
});
} else {
this.settings.ajax = await this.ajax(opt);
@@ -319,8 +339,8 @@ class Widget extends DmYY {
this.saveSettings(false);
const response = this.settings.ajax;
- response.animalEmoji = `${this.getAnimalZodiacToEmoji(response.animal)}`;
- response.astro = `${this.getAstroToEmoji(response.constellation)}`;
+ response.animalEmoji = `${this.getAnimalZodiacToEmoji(response.sx)}`;
+ response.astro = `${this.getAstroToEmoji(response.xz)}`;
if (this.verifyTime(eday)) {
response.meetDay = this.getEdayNumber(eday);
@@ -343,7 +363,7 @@ class Widget extends DmYY {
.replace("月", "-")
.replace("日", "");
- const tmpBirth = this.getAge(this.defaultData.eday);
+ const tmpBirth = this.getAge(this.defaultData.time);
let ageYear = tmpBirth.year > 0 ? `${tmpBirth.year}岁` : "";
let ageMonth = tmpBirth.month > 0 ? `${tmpBirth.month}月` : "";
let ageDay = tmpBirth.day > 0 ? `${tmpBirth.day}天` : "1天";
@@ -379,7 +399,7 @@ class Widget extends DmYY {
if (dayImage) {
subWidget.addSpacer(2);
- let dayIcon = subWidget.addImage(dayImage.image);
+ let dayIcon = subWidget.addImage(SFSymbol.named(dayImage).image);
dayIcon.imageSize = new Size(mainTextSize + 1, mainTextSize + 1);
dayIcon.tintColor = new Color("#1ab6f8");
}
@@ -506,7 +526,7 @@ class Widget extends DmYY {
const userWidgetText = nameStack.addText(this.defaultData.username);
userWidgetText.textColor = this.widgetColor;
- userWidgetText.font = this.provideFont("italic", 22);
+ userWidgetText.font = this.provideFont("italic", mainTextSize + 10);
userWidgetText.shadowColor = new Color(this.defaultData.nicknameShadow);
userWidgetText.shadowOffset = new Point(3, 3);
userWidgetText.shadowRadius = 3;
@@ -514,7 +534,7 @@ class Widget extends DmYY {
nameStack.addSpacer(5);
this.provideText(`相遇${meetDay}天`, nameStack, {
font: "Party Let",
- size: 12,
+ size: mainTextSize,
opacity: 0.8,
});
@@ -528,8 +548,7 @@ class Widget extends DmYY {
icon: "hourglass",
color: "#1ab6f8",
title: "年龄",
- text: `${ageYear + ageMonth}`,
- dayImage: dayIcon,
+ text: `${ageYear + ageMonth} ${tmpBirth.day} 天`,
});
} else {
this.rowCell(rightStack, {
@@ -619,8 +638,7 @@ class Widget extends DmYY {
icon: "hourglass",
color: "#1ab6f8",
title: "年龄",
- text: ageYear + ageMonth,
- dayImage: dayIcon,
+ text: `${ageYear + ageMonth} ${tmpBirth.day} 天`,
});
} else {
this.rowCell(containerStack, {
diff --git a/Scripts/wsgw.js b/Scripts/wsgw.js
new file mode 100644
index 0000000..a8c1007
--- /dev/null
+++ b/Scripts/wsgw.js
@@ -0,0 +1,381 @@
+// Variables used by Scriptable.
+// These must be at the very top of the file. Do not edit.
+// icon-color: deep-gray; icon-glyph: setting;
+
+// 添加require,是为了vscode中可以正确引入包,以获得自动补全等功能
+if (typeof require === 'undefined') require = importModule;
+const { DmYY, Runing } = require('./DmYY');
+
+/**
+ * 重写修改自作者
+ * @channel https://t.me/yqc_123/
+ * @feedback https://t.me/NobyDa_Chat
+ * @author 小白脸|𝐎𝐍𝐙𝟑𝐕
+ *
+ * 添加重写:https://raw.githubusercontent.com/dompling/Script/master/wsgw/index.js
+ *
+ */
+
+const defaultData = {
+ user: '**',
+ left: {
+ dayElePq: [],
+ balance: 0,
+ arrearsOfFees: false,
+ },
+ right: {
+ previousBill: 0,
+ previousBillRate: 0,
+ thisYear: 0,
+ thisYearRate: 0,
+ },
+ update: '',
+};
+
+// @组件代码开始
+class Widget extends DmYY {
+ constructor(arg) {
+ super(arg);
+ this.en = 'wsgw';
+ this.name = '网上国网';
+ this.userNum = args.widgetParameter || 0;
+ if (config.runsInApp) {
+ this.registerAction({
+ icon: { name: 'photo.tv', color: '#5A74EF' },
+ type: 'color',
+ title: '左侧背景',
+ desc: '左侧背景色',
+ val: 'leftColor',
+ });
+ this.registerAction({
+ icon: { name: 'arrow.clockwise', color: '#1890ff' },
+ type: 'input',
+ title: '缓存时间',
+ desc: '默认3小时 (单位小时),填写方式数字',
+ placeholder: '3',
+ val: 'cacheTime',
+ });
+
+ this.registerAction({
+ icon: { name: 'character.cursor.ibeam', color: '#EC6240' },
+ type: 'input',
+ title: '文字缩放',
+ desc: '文字缩放比例,值为 0-1',
+ placeholder: '1',
+ val: 'scale',
+ });
+
+ this.registerAction('基础设置', this.setWidgetConfig);
+ }
+ }
+
+ date = new Date();
+ day = this.date.getTime();
+
+ dataSource = { ...defaultData };
+
+ init = async () => {
+ console.log(`当前用户下标:${this.userNum}`);
+ this.cacheTime = (this.settings.cacheTime || 3) * 3600000;
+ this.scale = parseFloat(this.settings.scale || '1');
+ if (
+ !this.settings.data ||
+ this.settings.cacheDay + this.cacheTime < this.day
+ ) {
+ console.log(`缓存失效,重新获取`);
+ await this.cacheData();
+ } else {
+ console.log(
+ `最后更新时间:${new Date(parseInt(this.settings.cacheDay)).toLocaleString()}`
+ );
+ console.log(
+ `缓存失效时间:${new Date(parseInt(this.settings.cacheDay) + this.cacheTime).toLocaleString()}`
+ );
+ this.dataSource = { ...this.settings.data[this.userNum] };
+ if (!this.dataSource.user) await this.cacheData();
+ console.log(this.dataSource);
+ }
+ };
+
+ cacheData = async () => {
+ try {
+ const response = await this.$request.get(
+ 'https://api.wsgw-rewrite.com/electricity/bill/all',
+ { timeoutInterval: 60 }
+ );
+ console.log(response);
+ this.settings.data = [];
+ response?.forEach((dataInfo) => {
+ const dataSource = {
+ user: '**',
+ left: {
+ dayElePq: [],
+ balance: 0,
+ arrearsOfFees: false,
+ },
+ right: {
+ previousBill: 0,
+ previousBillRate: 0,
+ thisYear: 0,
+ thisYearRate: 0,
+ },
+ update: '',
+ };
+
+ dataSource.user = dataInfo.userInfo.consName_dst.replaceAll('*', '');
+ dataSource.left.balance = parseFloat(dataInfo.eleBill.sumMoney);
+ dataSource.left.dayElePq = dataInfo.dayElecQuantity.sevenEleList
+ .filter((item) => item.dayElePq !== '-')
+ .map((item) => ({
+ label: item.day,
+ value: parseFloat(item.dayElePq),
+ }));
+
+ dataSource.left.arrearsOfFees = dataInfo.arrearsOfFees;
+
+ dataSource.right.previousBill = parseFloat(
+ this.last(dataInfo.monthElecQuantity?.mothEleList || [])
+ ?.monthEleCost || 0
+ );
+
+ const oldVal =
+ this.last(dataInfo.monthElecQuantity?.mothEleList || [], 2)
+ ?.monthEleCost || 1;
+
+ dataSource.right.previousBillRate =
+ ((dataSource.right.previousBill - oldVal) / oldVal) * 100;
+
+ dataSource.right.previousBillRate = parseFloat(
+ dataSource.right.previousBillRate.toFixed(2)
+ );
+
+ dataSource.right.thisYear = parseFloat(
+ dataInfo.monthElecQuantity?.dataInfo?.totalEleCost || 0
+ );
+
+ const lastYearVal = dataInfo.lastYearElecQuantity.dataInfo.totalEleCost;
+
+ dataSource.right.thisYearRate =
+ ((dataSource.right.thisYear - lastYearVal) / lastYearVal) * 100;
+
+ dataSource.right.thisYearRate = parseFloat(
+ dataSource.right.thisYearRate.toFixed(2)
+ );
+
+ dataSource.update = dataInfo.eleBill.date;
+ this.settings.data.push({ ...dataSource });
+ });
+ console.log(this.settings.data);
+ this.dataSource = { ...this.settings.data[this.userNum] };
+ this.settings.cacheDay = this.day;
+ this.saveSettings(false);
+ } catch (e) {
+ console.log(`接口数据异常:请检查 BoxJS 重写`);
+ console.log(e);
+ }
+ };
+
+ last = (data = [], index = 1) => {
+ return data[data.length - index];
+ };
+
+ renderImage = async (uri) => {
+ return this.$request.get(uri, 'IMG');
+ };
+
+ notSupport(w) {
+ const stack = w.addStack();
+ stack.addText('暂不支持');
+ return w;
+ }
+
+ barChart() {
+ return `
+ {
+ "type": "bar",
+ "data": {
+ "labels": ${JSON.stringify(this.dataSource.left.dayElePq.map((item) => item.label).reverse())},
+ "datasets": [
+ {
+ "label": "Sales",
+ "data": ${JSON.stringify(this.dataSource.left.dayElePq.map((item) => parseFloat(item.value)).reverse())},
+ "backgroundColor": "#fff",
+ "borderColor": "#fff",
+ "borderWidth": 1,
+ "borderRadius": {
+ "topLeft": 30,
+ "topRight": 30,
+ "bottomLeft": 30, // 只为柱状图底部设置圆角
+ "bottomRight": 30
+ },
+ "barPercentage": 0.8, // 控制柱子的宽度
+ "categoryPercentage": 0.4,
+ "borderSkipped": false // 应用自定义的圆角设置
+ }
+ ]
+ },
+ "options": {
+ "plugins": {
+ "legend": {
+ "display": false // 隐藏图例
+ },
+ "title": {
+ "display": false // 隐藏标题
+ }
+ },
+ "scales": {
+ "x": {
+ "display": false // 完全隐藏 X 轴
+ },
+ "y": {
+ "display": false // 完全隐藏 Y 轴
+ }
+ },
+ "layout": {
+ "padding": 0 // 移除图表周围的内边距
+ }
+ }
+}
+`;
+ }
+
+ createLeft = async (widget) => {
+ const fontStyle = {
+ color: new Color('#fff'),
+ size: 20 * this.scale,
+ opacity: 0.8,
+ };
+ const leftStack = widget.addStack();
+ leftStack.cornerRadius = 10;
+ leftStack.layoutVertically();
+ leftStack.backgroundColor = new Color(
+ this.settings.leftColor || '#5A74EF',
+ 0.8
+ );
+ leftStack.setPadding(10, 10, 10, 10);
+
+ const chartStack = leftStack.addStack();
+
+ const chartImage = await this.renderImage(
+ `https://quickchart.io/chart?v=4&w=800&h=400&f=png&c=${encodeURIComponent(this.barChart())}`
+ );
+ const chartImageStack = chartStack.addImage(chartImage);
+ chartImageStack.imageSize = new Size(120, 60);
+
+ leftStack.addSpacer();
+
+ this.provideText('余额', leftStack, fontStyle);
+
+ const todayStack = leftStack.addStack();
+ todayStack.centerAlignContent();
+ if (this.dataSource.left.arrearsOfFees)
+ fontStyle.color = new Color('#f65755');
+
+ fontStyle.size = 20 * this.scale;
+ this.provideText('¥ ', todayStack, fontStyle);
+
+ fontStyle.opacity = 1;
+ const todayUse = this.dataSource.left.balance;
+
+ this.provideText(` ${todayUse.toLocaleString()}`, todayStack, fontStyle);
+ };
+
+ createDot = (stack, color) => {
+ const dotStack = stack.addStack();
+ dotStack.setPadding(0, 0, 2, 0);
+ const dot = dotStack.addStack();
+
+ dot.size = new Size(10, 10);
+ dot.backgroundColor = new Color(color);
+ dot.cornerRadius = 10;
+ };
+
+ createCell = (widget, data = { title: '', num: 0, radio: 0 }) => {
+ const cellStack = widget.addStack();
+ cellStack.backgroundColor = new Color('#404045');
+ cellStack.setPadding(10, 10, 10, 10);
+ cellStack.cornerRadius = 10;
+ cellStack.layoutVertically();
+
+ const fontStyle = {
+ color: new Color('#fff'),
+ size: 14 * this.scale,
+ opacity: 0.6,
+ };
+ this.provideText(data.title, cellStack, fontStyle);
+
+ const dataStack = cellStack.addStack();
+ dataStack.bottomAlignContent();
+
+ fontStyle.size = 12 * this.scale;
+ this.provideText('¥ ', dataStack, fontStyle);
+
+ fontStyle.opacity = 1;
+ fontStyle.size = 20 * this.scale;
+ this.provideText(` ${data.num.toLocaleString()}`, dataStack, fontStyle);
+ dataStack.addSpacer();
+
+ const dotStack = dataStack.addStack();
+ this.createDot(dotStack, data.radio > 0 ? '#7EEF8F' : '#ED86A5');
+
+ fontStyle.size = 12 * this.scale;
+ this.provideText(
+ data.radio > 0 ? ` +${data.radio}%` : ` -${Math.abs(data.radio)}%`,
+ dataStack,
+ fontStyle
+ );
+ };
+
+ createRight = async (widget) => {
+ const rightStack = widget.addStack();
+ rightStack.layoutVertically();
+ this.createCell(rightStack, {
+ title: '上期费用',
+ num: this.dataSource.right.previousBill,
+ radio: this.dataSource.right.previousBillRate,
+ });
+ rightStack.addSpacer();
+ this.createCell(rightStack, {
+ title: '今年费用',
+ num: this.dataSource.right.thisYear,
+ radio: this.dataSource.right.thisYearRate,
+ });
+ };
+
+ renderSmall = async (w) => {
+ w.setPadding(10, 10, 10, 10);
+ await this.createLeft(w);
+ return w;
+ };
+
+ renderMedium = async (w) => {
+ w.setPadding(10, 10, 10, 10);
+ const containerStack = w.addStack();
+ containerStack.layoutHorizontally();
+ await this.createLeft(containerStack);
+ containerStack.addSpacer(10);
+ await this.createRight(containerStack);
+ return w;
+ };
+
+ /**
+ * 渲染函数,函数名固定
+ * 可以根据 this.widgetFamily 来判断小组件尺寸,以返回不同大小的内容
+ */
+ async render() {
+ await this.init();
+ const widget = new ListWidget();
+ widget.url = `com.wsgw.e.zsdl://platformapi/`;
+ await this.getWidgetBackgroundImage(widget);
+ if (this.widgetFamily === 'medium') {
+ return await this.renderMedium(widget);
+ } else if (this.widgetFamily === 'large') {
+ return await this.notSupport(widget);
+ } else {
+ return await this.renderSmall(widget);
+ }
+ }
+}
+
+// @组件代码结束
+await Runing(Widget, '0', false); //远程开发环境
diff --git a/install.json b/install.json
index 20b105a..a8b7d63 100644
--- a/install.json
+++ b/install.json
@@ -5,7 +5,7 @@
"repo": "https://github.com/dompling/Scriptable",
"apps": [
{
- "version": "1.1.0",
+ "version": "1.1.2",
"description": "DmYY组件库",
"scriptURL": "https://raw.githubusercontent.com/dompling/Scriptable/master/Scripts/DmYY.js",
"thumb": "https://img.icons8.com/clouds/344/settings.png",
@@ -13,6 +13,10 @@
"title": "DmYY",
"html": [
"更新说明
",
+ "v1.1.2",
+ "fix: 输入默认值问题",
+ "v1.1.1",
+ "feat: DmYY 判断有无 actions",
"v1.1.0",
"修复 boxjs 读取问题",
"v1.0.8",
@@ -422,7 +426,7 @@
]
},
{
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "获取当前省份油价",
"scriptURL": "https://raw.githubusercontent.com/dompling/Scriptable/master/Scripts/Oild.js",
"thumb": "https://img.icons8.com/clouds/344/engine-oil-level.png",
@@ -433,6 +437,12 @@
"name": "DmYY",
"scriptURL": "https://raw.githubusercontent.com/dompling/Scriptable/master/Scripts/DmYY.js"
}
+ ],
+ "html": [
+ "今日油价
",
+ "1.0.1
",
+ "增加自动定位设置
",
+ "增加省份选择
"
]
},
{
@@ -507,6 +517,26 @@
"scriptURL": "https://raw.githubusercontent.com/dompling/Scriptable/master/Scripts/DmYY.js"
}
]
+ },
+ {
+ "version": "1.0.2",
+ "description": "网上国网",
+ "scriptURL": "https://raw.githubusercontent.com/dompling/Scriptable/master/Scripts/wsgw.js",
+ "thumb": "https://is1-ssl.mzstatic.com/image/thumb/Purple116/v4/83/d8/8a/83d88a92-5a4d-7a2f-118c-80d795e7a9f6/AppIcon-0-0-1x_U007emarketing-0-5-0-0-sRGB-85-220.png/144x144.png",
+ "name": "wsgw",
+ "title": "网上国网",
+ "html": [
+ "网上国网
",
+ "1.填写账号密码BoxJS订阅",
+ "2.参考借用【@小白脸】大佬的重写和【@Yuheng0101】大佬的脚本",
+ "3.Surge 添加远程重写模块【网上国网重写】、其他的请自行使用 https://script.hub 转换"
+ ],
+ "depend": [
+ {
+ "name": "DmYY",
+ "scriptURL": "https://raw.githubusercontent.com/dompling/Scriptable/master/Scripts/DmYY.js"
+ }
+ ]
}
]
}
diff --git a/package.json b/package.json
index 409499c..7d7494d 100644
--- a/package.json
+++ b/package.json
@@ -11,6 +11,7 @@
],
"license": "ISC",
"devDependencies": {
- "@types/scriptable-ios": "^1.6.1"
+ "@types/scriptable-ios": "^1.6.1",
+ "prettier": "^3.3.3"
}
}
diff --git a/yarn.lock b/yarn.lock
index ebd5803..789a8f1 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6,3 +6,8 @@
version "1.6.1"
resolved "https://registry.npm.taobao.org/@types/scriptable-ios/download/@types/scriptable-ios-1.6.1.tgz#44766b47a0c0c9f92a3c1bf46214288cf3d926f4"
integrity sha1-RHZrR6DAyfkqPBv0YhQojPPZJvQ=
+
+prettier@^3.3.3:
+ version "3.3.3"
+ resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.3.tgz#30c54fe0be0d8d12e6ae61dbb10109ea00d53105"
+ integrity sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==