mirror of
https://github.com/ThisIsBenny/iOS-Widgets.git
synced 2025-06-07 05:57:41 +00:00
Vodafone Widget v2 Beta 1
Signed-off-by: Benny Samir Hierl <bennysamir@posteo.de>
This commit is contained in:
parent
30f9564a06
commit
22357c4650
1 changed files with 267 additions and 134 deletions
|
@ -3,9 +3,16 @@
|
||||||
// icon-color: red; icon-glyph: broadcast-tower;
|
// icon-color: red; icon-glyph: broadcast-tower;
|
||||||
|
|
||||||
/**************
|
/**************
|
||||||
Version 1.2.4
|
Version 2.0.0
|
||||||
|
|
||||||
Changelog:
|
Changelog:
|
||||||
|
v2.0.0:
|
||||||
|
- Disable "Dark Mode Support"
|
||||||
|
- Medium Widget Support
|
||||||
|
- Switch between used and remaining volume
|
||||||
|
- Use MSISDN for Cache-Name
|
||||||
|
- Show amount for prepaid cards
|
||||||
|
- Show remaining days as progress-bar
|
||||||
v1.2.4:
|
v1.2.4:
|
||||||
- use color.dynamic
|
- use color.dynamic
|
||||||
v1.2.3:
|
v1.2.3:
|
||||||
|
@ -41,18 +48,28 @@ Credits:
|
||||||
**************/
|
**************/
|
||||||
|
|
||||||
// How many minutes should the cache be valid
|
// How many minutes should the cache be valid
|
||||||
let cacheMinutes = 60;
|
const cacheMinutes = 60
|
||||||
|
|
||||||
|
// Set to false if the widget should display always in red
|
||||||
|
const darkModeSupport = true
|
||||||
|
|
||||||
|
// Switch between remaining and used contingent. If you want show the used contingent, then change the value from true to false
|
||||||
|
const showRemainingContingent = true
|
||||||
|
|
||||||
|
// To disable the progressbar for the remaining days, you have to change the value from true to false
|
||||||
|
const showRemainingDaysAsProgressbar = true
|
||||||
|
|
||||||
// Please add additional values to these list, in case that your contract/tarif isn't supported by these default values.
|
// Please add additional values to these list, in case that your contract/tarif isn't supported by these default values.
|
||||||
const containerList = ['Daten', 'D_EU_DATA', 'C_DIY_Data_National']
|
const containerList = ['Daten', 'D_EU_DATA', 'C_DIY_Data_National']
|
||||||
const codeList = ['-1', '45500', '40100']
|
const codeList = ['-1', '-5' ,'45500', '40100']
|
||||||
|
|
||||||
|
// Dev Settings
|
||||||
|
const debug = false
|
||||||
|
config.widgetFamily = config.widgetFamily || 'small'
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
let widgetInputRAW = args.widgetParameter;
|
let widgetInputRAW = args.widgetParameter;
|
||||||
let widgetInput = null;
|
let widgetInput = null;
|
||||||
|
|
||||||
let user, pass, number
|
let user, pass, number
|
||||||
|
|
||||||
if (widgetInputRAW !== null) {
|
if (widgetInputRAW !== null) {
|
||||||
[user, pass, number] = widgetInputRAW.toString().split("|");
|
[user, pass, number] = widgetInputRAW.toString().split("|");
|
||||||
|
|
||||||
|
@ -64,56 +81,115 @@ if (widgetInputRAW !== null) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const backColor = Color.dynamic(new Color('D32D1F'), new Color('111111'));
|
const h = 5
|
||||||
const backColor2 = Color.dynamic(new Color('76150C'), new Color('222222'));
|
let width
|
||||||
const textColor = Color.dynamic(new Color('EDEDED'), new Color('EDEDED'));
|
if (config.widgetFamily === 'small') {
|
||||||
const fillColor = Color.dynamic(new Color('EDEDED'), new Color('EDEDED'));
|
width = 200
|
||||||
const strokeColor = Color.dynamic(new Color('B0B0B0'), new Color('121212'));
|
} else {
|
||||||
|
width = 400
|
||||||
const canvas = new DrawContext();
|
|
||||||
const canvSize = 200;
|
|
||||||
const canvTextSize = 36;
|
|
||||||
|
|
||||||
const canvWidth = 22;
|
|
||||||
const canvRadius = 80;
|
|
||||||
|
|
||||||
canvas.opaque = false
|
|
||||||
canvas.size = new Size(canvSize, canvSize);
|
|
||||||
canvas.respectScreenScale = true;
|
|
||||||
|
|
||||||
function sinDeg(deg) {
|
|
||||||
return Math.sin((deg * Math.PI) / 180);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function cosDeg(deg) {
|
let backColor = new Color('D32D1F')
|
||||||
return Math.cos((deg * Math.PI) / 180);
|
let backColor2 = new Color('93291E')
|
||||||
|
let textColor = new Color('EDEDED')
|
||||||
|
let fillColor = new Color('EDEDED')
|
||||||
|
let strokeColor = new Color('B0B0B0')
|
||||||
|
|
||||||
|
if (darkModeSupport) {
|
||||||
|
backColor = Color.dynamic(backColor, new Color('111111'))
|
||||||
|
backColor2 = Color.dynamic(backColor2, new Color('222222'))
|
||||||
|
textColor = Color.dynamic(textColor, new Color('EDEDED'))
|
||||||
|
fillColor = Color.dynamic(fillColor, new Color('EDEDED'))
|
||||||
|
strokeColor = Color.dynamic(strokeColor, new Color('121212'))
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawArc(ctr, rad, w, deg) {
|
function creatProgress(total, havegone) {
|
||||||
bgx = ctr.x - rad;
|
const context = new DrawContext()
|
||||||
bgy = ctr.y - rad;
|
context.size = new Size(width, h)
|
||||||
bgd = 2 * rad;
|
context.opaque = false
|
||||||
bgr = new Rect(bgx, bgy, bgd, bgd);
|
context.respectScreenScale = false
|
||||||
|
|
||||||
canvas.setFillColor(fillColor);
|
// Background Path
|
||||||
canvas.setStrokeColor(strokeColor);
|
context.setFillColor(fillColor)
|
||||||
canvas.setLineWidth(w);
|
const path = new Path()
|
||||||
canvas.strokeEllipse(bgr);
|
path.addRoundedRect(new Rect(0, 0, width, h), 3, 2)
|
||||||
|
context.addPath(path)
|
||||||
|
context.fillPath()
|
||||||
|
|
||||||
for (t = 0; t < deg; t++) {
|
// Progress Path
|
||||||
rect_x = ctr.x + rad * sinDeg(t) - w / 2;
|
context.setFillColor(strokeColor)
|
||||||
rect_y = ctr.y - rad * cosDeg(t) - w / 2;
|
const path1 = new Path()
|
||||||
rect_r = new Rect(rect_x, rect_y, w, w);
|
const path1width = (width * (havegone / total) > width) ? width : width * (havegone / total)
|
||||||
canvas.fillEllipse(rect_r);
|
path1.addRoundedRect(new Rect(0, 0, path1width, h), 3, 2)
|
||||||
|
context.addPath(path1)
|
||||||
|
context.fillPath()
|
||||||
|
return context.getImage()
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDiagram(percentage) {
|
||||||
|
function drawArc(ctr, rad, w, deg) {
|
||||||
|
bgx = ctr.x - rad
|
||||||
|
bgy = ctr.y - rad
|
||||||
|
bgd = 2 * rad
|
||||||
|
bgr = new Rect(bgx, bgy, bgd, bgd)
|
||||||
|
|
||||||
|
canvas.setFillColor(fillColor)
|
||||||
|
canvas.setStrokeColor(strokeColor)
|
||||||
|
canvas.setLineWidth(w)
|
||||||
|
canvas.strokeEllipse(bgr)
|
||||||
|
|
||||||
|
for (t = 0; t < deg; t++) {
|
||||||
|
rect_x = ctr.x + rad * sinDeg(t) - w / 2
|
||||||
|
rect_y = ctr.y - rad * cosDeg(t) - w / 2
|
||||||
|
rect_r = new Rect(rect_x, rect_y, w, w)
|
||||||
|
canvas.fillEllipse(rect_r)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
function sinDeg(deg) {
|
||||||
|
return Math.sin((deg * Math.PI) / 180)
|
||||||
|
}
|
||||||
|
|
||||||
|
function cosDeg(deg) {
|
||||||
|
return Math.cos((deg * Math.PI) / 180)
|
||||||
|
}
|
||||||
|
const canvas = new DrawContext()
|
||||||
|
const canvSize = 200
|
||||||
|
const canvTextSize = 36
|
||||||
|
|
||||||
|
const canvWidth = 10
|
||||||
|
const canvRadius = 80
|
||||||
|
|
||||||
|
canvas.opaque = false
|
||||||
|
canvas.size = new Size(canvSize, canvSize)
|
||||||
|
canvas.respectScreenScale = true
|
||||||
|
|
||||||
|
drawArc(
|
||||||
|
new Point(canvSize / 2, canvSize / 2),
|
||||||
|
canvRadius,
|
||||||
|
canvWidth,
|
||||||
|
Math.floor(percentage * 3.6)
|
||||||
|
)
|
||||||
|
|
||||||
|
const canvTextRect = new Rect(
|
||||||
|
0,
|
||||||
|
100 - canvTextSize / 2,
|
||||||
|
canvSize,
|
||||||
|
canvTextSize
|
||||||
|
)
|
||||||
|
canvas.setTextAlignedCenter()
|
||||||
|
canvas.setTextColor(textColor)
|
||||||
|
canvas.setFont(Font.boldSystemFont(canvTextSize))
|
||||||
|
canvas.drawTextInRect(`${percentage}%`, canvTextRect)
|
||||||
|
|
||||||
|
return canvas.getImage()
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTimeRemaining(endtime) {
|
function getTimeRemaining(endtime) {
|
||||||
const total = Date.parse(endtime) - Date.parse(new Date());
|
const total = Date.parse(endtime) - Date.parse(new Date())
|
||||||
const seconds = Math.floor((total / 1000) % 60);
|
const seconds = Math.floor((total / 1000) % 60)
|
||||||
const minutes = Math.floor((total / 1000 / 60) % 60);
|
const minutes = Math.floor((total / 1000 / 60) % 60)
|
||||||
const hours = Math.floor((total / (1000 * 60 * 60)) % 24);
|
const hours = Math.floor((total / (1000 * 60 * 60)) % 24)
|
||||||
const days = Math.floor(total / (1000 * 60 * 60 * 24));
|
const days = Math.floor(total / (1000 * 60 * 60 * 24))
|
||||||
|
|
||||||
return {
|
return {
|
||||||
total,
|
total,
|
||||||
|
@ -121,7 +197,7 @@ function getTimeRemaining(endtime) {
|
||||||
hours,
|
hours,
|
||||||
minutes,
|
minutes,
|
||||||
seconds
|
seconds
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getSessionCookiesViaNetworkLogin() {
|
async function getSessionCookiesViaNetworkLogin() {
|
||||||
|
@ -147,7 +223,7 @@ async function getSessionCookiesViaNetworkLogin() {
|
||||||
console.log("Login failed! Please check if Wifi is disabled.")
|
console.log("Login failed! Please check if Wifi is disabled.")
|
||||||
throw new Error(`Login failed with HTTP-Status-Code ${req.response.statusCode}`)
|
throw new Error(`Login failed with HTTP-Status-Code ${req.response.statusCode}`)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
async function getSessionCookiesViaMeinVodafoneLogin(u, p) {
|
async function getSessionCookiesViaMeinVodafoneLogin(u, p) {
|
||||||
let req;
|
let req;
|
||||||
|
@ -170,25 +246,25 @@ async function getSessionCookiesViaMeinVodafoneLogin(u, p) {
|
||||||
console.log("Login failed!")
|
console.log("Login failed!")
|
||||||
throw new Error(`Login failed with HTTP-Status-Code ${req.response.statusCode}`)
|
throw new Error(`Login failed with HTTP-Status-Code ${req.response.statusCode}`)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
async function getUsage(user, pass, number) {
|
async function getUsage(user, pass, number) {
|
||||||
let cookies, msisdn;
|
let cookies, msisdn
|
||||||
if (user && pass && number) {
|
if (user && pass && number) {
|
||||||
console.log("Login via MeinVodafone")
|
console.log("Login via MeinVodafone")
|
||||||
let { cookies: c } = await getSessionCookiesViaMeinVodafoneLogin(user, pass);
|
let { cookies: c } = await getSessionCookiesViaMeinVodafoneLogin(user, pass)
|
||||||
cookies = c;
|
cookies = c
|
||||||
msisdn = number;
|
msisdn = number
|
||||||
} else {
|
} else {
|
||||||
console.log("Login via Network")
|
console.log("Login via Network")
|
||||||
let { cookies: c, msisdn: m } = await getSessionCookiesViaNetworkLogin();
|
let { cookies: c, msisdn: m } = await getSessionCookiesViaNetworkLogin()
|
||||||
cookies = c;
|
cookies = c
|
||||||
msisdn = m;
|
msisdn = m
|
||||||
}
|
}
|
||||||
let CookieValues = cookies.map(function (v) {
|
let CookieValues = cookies.map(function (v) {
|
||||||
return v.name + "=" + v.value
|
return v.name + "=" + v.value
|
||||||
})
|
})
|
||||||
let req;
|
let req
|
||||||
req = new Request(`https://www.vodafone.de/api/enterprise-resources/core/bss/sub-nil/mobile/payment/service-usages/subscriptions/${msisdn}/unbilled-usage`)
|
req = new Request(`https://www.vodafone.de/api/enterprise-resources/core/bss/sub-nil/mobile/payment/service-usages/subscriptions/${msisdn}/unbilled-usage`)
|
||||||
req.headers = {
|
req.headers = {
|
||||||
'x-vf-api': '1499082775305',
|
'x-vf-api': '1499082775305',
|
||||||
|
@ -198,72 +274,91 @@ async function getUsage(user, pass, number) {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
let res = await req.loadJSON()
|
let res = await req.loadJSON()
|
||||||
|
if(!res['serviceUsageVBO'] || !res['serviceUsageVBO']['usageAccounts'] || !res['serviceUsageVBO']['usageAccounts'][0]) {
|
||||||
|
if (debug) {
|
||||||
|
console.log(JSON.stringify(res, null, 2))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
console.log("unbilled-usage loaded")
|
console.log("unbilled-usage loaded")
|
||||||
let datenContainer = res['serviceUsageVBO']['usageAccounts'][0]['usageGroup'].find(function (v) {
|
if (debug) {
|
||||||
|
console.log(JSON.stringify(res['serviceUsageVBO']['usageAccounts'][0], null, 2))
|
||||||
|
}
|
||||||
|
const marketCode = res['serviceUsageVBO']['usageAccounts'][0]['details']['marketCode']
|
||||||
|
const billDate = res['serviceUsageVBO']['usageAccounts'][0]['details']['billDate']
|
||||||
|
const amount = res['serviceUsageVBO']['usageAccounts'][0]['details']['amount']
|
||||||
|
|
||||||
|
let usage = []
|
||||||
|
|
||||||
|
// Get Main Container
|
||||||
|
let container = res['serviceUsageVBO']['usageAccounts'][0]['usageGroup'].filter(function (v) {
|
||||||
return containerList.includes(v.container)
|
return containerList.includes(v.container)
|
||||||
})
|
})
|
||||||
|
|
||||||
if (datenContainer === undefined) {
|
if (container.length === 0) {
|
||||||
const ErrorMsg = "Can't find usageGroup with supported Container: " + containerList.join(', ') + ".";
|
const ErrorMsg = "Can't find usageGroup with supported Container: " + containerList.join(', ') + ".";
|
||||||
console.log(ErrorMsg)
|
console.log(ErrorMsg)
|
||||||
|
|
||||||
const listOfContainerNamesInResponse = res['serviceUsageVBO']['usageAccounts'][0]['usageGroup'].map(function (v) {
|
const listOfContainerNamesInResponse = res['serviceUsageVBO']['usageAccounts'][0]['usageGroup'].map(function (v) {
|
||||||
return v.container;
|
return v.container
|
||||||
})
|
})
|
||||||
console.log("Please check the following list to find the correct container name for your case and adjust the list of container names at the beginnging: " + listOfContainerNamesInResponse.join(", "))
|
console.log("Please check the following list to find the correct container name for your case and adjust the list of container names at the beginnging: " + listOfContainerNamesInResponse.join(", "))
|
||||||
throw new Error(ErrorMsg)
|
throw new Error(ErrorMsg)
|
||||||
}
|
}
|
||||||
|
|
||||||
let datenvolumen;
|
|
||||||
if (datenContainer.usage.length == 1) {
|
|
||||||
datenvolumen = datenContainer.usage[0]
|
|
||||||
} else {
|
|
||||||
datenvolumen = datenContainer.usage.find(function (v) {
|
|
||||||
return codeList.includes(v.code)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (datenvolumen === undefined) {
|
for(let i = 0; i < container.length; i++) {
|
||||||
|
for (let j = 0; j < container[i]['usage'].length; j++) {
|
||||||
|
if (codeList.includes(container[i]['usage'][j]['code'])) {
|
||||||
|
usage.push(container[i]['usage'][j])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (usage.length === 0) {
|
||||||
const ErrorMsg = "Can't find Usage with supported Codes: " + codeList.join(', ') + ".";
|
const ErrorMsg = "Can't find Usage with supported Codes: " + codeList.join(', ') + ".";
|
||||||
console.log(ErrorMsg)
|
console.log(ErrorMsg)
|
||||||
|
|
||||||
const listOfCodeInResponse = datenContainer.usage.map(function (v) {
|
const listOfCodeInResponse = []
|
||||||
return `Code: "${v.code}" for "${v.description}"`;
|
for(let i = 0; i < container.length; i++) {
|
||||||
})
|
for (let j = 0; j < container[i]['usage'].length; j++) {
|
||||||
|
listOfCodeInResponse.push(`Code: "${container[i]['usage'][j].code}" for "${container[i]['usage'][j].description}"`)
|
||||||
|
}
|
||||||
|
}
|
||||||
console.log("Please check the following list to find the correct code for your case and adjust the list of codes at the beginnging: " + listOfCodeInResponse.join(", "))
|
console.log("Please check the following list to find the correct code for your case and adjust the list of codes at the beginnging: " + listOfCodeInResponse.join(", "))
|
||||||
throw new Error(ErrorMsg)
|
throw new Error(ErrorMsg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let endDate = usage[0].endDate
|
||||||
let endDate = datenvolumen.endDate;
|
|
||||||
if (endDate == null) {
|
if (endDate == null) {
|
||||||
endDate = res['serviceUsageVBO']['billDetails']['billCycleEndDate'] || null
|
endDate = res['serviceUsageVBO']['billDetails']['billCycleEndDate'] || null
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
total: datenvolumen.total,
|
billDate,
|
||||||
used: datenvolumen.used,
|
endDate,
|
||||||
remaining: datenvolumen.remaining,
|
amount,
|
||||||
endDate
|
marketCode,
|
||||||
|
usage
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("Loading usage data failed")
|
console.log("Loading usage data failed")
|
||||||
throw e
|
throw e
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
var today = new Date();
|
var today = new Date()
|
||||||
|
|
||||||
// Set up the file manager.
|
// Set up the file manager.
|
||||||
const files = FileManager.local()
|
const files = FileManager.local()
|
||||||
|
|
||||||
// Set up cache .
|
// Set up cache
|
||||||
const cachePath = files.joinPath(files.documentsDirectory(), "widget-vodafone")
|
const cacheNamePostfix = (number) ? number.substr(number.length - 4) : 'networkLogin'
|
||||||
|
const cachePath = files.joinPath(files.documentsDirectory(), "widget-vodafone-" + cacheNamePostfix)
|
||||||
const cacheExists = files.fileExists(cachePath)
|
const cacheExists = files.fileExists(cachePath)
|
||||||
const cacheDate = cacheExists ? files.modificationDate(cachePath) : 0
|
const cacheDate = cacheExists ? files.modificationDate(cachePath) : 0
|
||||||
|
|
||||||
// Get Data
|
// Get Data
|
||||||
let data;
|
let data
|
||||||
let lastUpdate
|
let lastUpdate
|
||||||
try {
|
try {
|
||||||
// If cache exists and it's been less than 30 minutes since last request, use cached data.
|
// If cache exists and it's been less than 30 minutes since last request, use cached data.
|
||||||
|
@ -301,7 +396,9 @@ let widget = new ListWidget();
|
||||||
widget.setPadding(10, 10, 10, 10)
|
widget.setPadding(10, 10, 10, 10)
|
||||||
|
|
||||||
if (data !== undefined) {
|
if (data !== undefined) {
|
||||||
console.log(data)
|
if(debug) {
|
||||||
|
console.log(JSON.stringify(data, null, 2))
|
||||||
|
}
|
||||||
const gradient = new LinearGradient()
|
const gradient = new LinearGradient()
|
||||||
gradient.locations = [0, 1]
|
gradient.locations = [0, 1]
|
||||||
gradient.colors = [
|
gradient.colors = [
|
||||||
|
@ -316,62 +413,93 @@ if (data !== undefined) {
|
||||||
provider.font = Font.mediumSystemFont(12)
|
provider.font = Font.mediumSystemFont(12)
|
||||||
provider.textColor = textColor
|
provider.textColor = textColor
|
||||||
|
|
||||||
|
if (data.marketCode === 'MMO') {
|
||||||
|
widget.addSpacer(2)
|
||||||
|
const amount = widget.addText(`Guthaben: ${data.amount.replace('.', ',')} €`)
|
||||||
|
amount.font = Font.systemFont(8)
|
||||||
|
amount.textColor = textColor
|
||||||
|
}
|
||||||
|
|
||||||
// Last Update
|
// Last Update
|
||||||
firstLineStack.addSpacer()
|
firstLineStack.addSpacer()
|
||||||
let lastUpdateText = firstLineStack.addDate(lastUpdate)
|
let lastUpdateText = firstLineStack.addDate(lastUpdate)
|
||||||
lastUpdateText.font = Font.mediumSystemFont(8)
|
lastUpdateText.font = Font.systemFont(8)
|
||||||
lastUpdateText.rightAlignText()
|
lastUpdateText.rightAlignText()
|
||||||
lastUpdateText.applyTimeStyle()
|
lastUpdateText.applyTimeStyle()
|
||||||
lastUpdateText.textColor = Color.lightGray()
|
lastUpdateText.textColor = Color.lightGray()
|
||||||
|
|
||||||
widget.addSpacer()
|
widget.addSpacer()
|
||||||
|
|
||||||
let remainingPercentage = (100 / data.total * data.remaining).toFixed(0);
|
const stack = widget.addStack()
|
||||||
|
stack.layoutHorizontally()
|
||||||
|
|
||||||
drawArc(
|
data.usage.slice(0, (config.widgetFamily === 'small' ? 1 : 2)).forEach((v) => {
|
||||||
new Point(canvSize / 2, canvSize / 2),
|
const column = stack.addStack()
|
||||||
canvRadius,
|
column.layoutVertically()
|
||||||
canvWidth,
|
column.centerAlignContent()
|
||||||
Math.floor(remainingPercentage * 3.6)
|
|
||||||
);
|
|
||||||
|
|
||||||
const canvTextRect = new Rect(
|
const percentage = (100 / v.total * (showRemainingContingent ? v.remaining : v.used)).toFixed(0);
|
||||||
0,
|
const imageStack = column.addStack()
|
||||||
100 - canvTextSize / 2,
|
imageStack.layoutHorizontally()
|
||||||
canvSize,
|
imageStack.addSpacer()
|
||||||
canvTextSize
|
imageStack.addImage(getDiagram(percentage));
|
||||||
);
|
imageStack.addSpacer()
|
||||||
canvas.setTextAlignedCenter();
|
column.addSpacer(2)
|
||||||
canvas.setTextColor(textColor);
|
|
||||||
canvas.setFont(Font.boldSystemFont(canvTextSize));
|
|
||||||
canvas.drawTextInRect(`${remainingPercentage}%`, canvTextRect);
|
|
||||||
|
|
||||||
const canvImage = canvas.getImage();
|
// Total Values
|
||||||
let image = widget.addImage(canvImage);
|
let totalValues;
|
||||||
image.centerAlignImage()
|
if (v.unitOfMeasure !== 'MB') {
|
||||||
|
totalValues = `${(showRemainingContingent ? v.remaining : v.used)} ${v.unitOfMeasure} von ${v.total} ${v.unitOfMeasure}`
|
||||||
|
} else if (parseInt(v.total) < 1000) {
|
||||||
|
totalValues = `${(showRemainingContingent ? v.remaining : v.used)} MB von ${v.total} MB`
|
||||||
|
} else {
|
||||||
|
let GB = ((showRemainingContingent ? v.remaining : v.used) / 1024).toFixed(2)
|
||||||
|
let totalGB = (v.total / 1024).toFixed(2)
|
||||||
|
totalValues = `${GB} GB von ${totalGB} GB`
|
||||||
|
}
|
||||||
|
textStack = column.addStack()
|
||||||
|
textStack.layoutHorizontally()
|
||||||
|
textStack.addSpacer()
|
||||||
|
let diagramText = textStack.addText(totalValues)
|
||||||
|
diagramText.font = Font.mediumSystemFont(11)
|
||||||
|
diagramText.lineLimit = 1
|
||||||
|
diagramText.centerAlignText()
|
||||||
|
diagramText.textColor = textColor
|
||||||
|
textStack.addSpacer()
|
||||||
|
|
||||||
|
nameStack = column.addStack()
|
||||||
|
nameStack.layoutHorizontally()
|
||||||
|
nameStack.addSpacer()
|
||||||
|
let diagramName = nameStack.addText(v.name.replace('Inland & EU', '').trim())
|
||||||
|
diagramName.font = Font.systemFont(10)
|
||||||
|
diagramName.lineLimit = 1
|
||||||
|
diagramName.centerAlignText()
|
||||||
|
diagramName.textColor = textColor
|
||||||
|
nameStack.addSpacer()
|
||||||
|
})
|
||||||
|
|
||||||
widget.addSpacer()
|
widget.addSpacer()
|
||||||
|
|
||||||
// Total Values
|
|
||||||
let totalValues;
|
|
||||||
if (parseInt(data.total) < 1000) {
|
|
||||||
totalValues = `${data.remaining} MB von ${data.total} MB`
|
|
||||||
} else {
|
|
||||||
let remainingGB = (data.remaining / 1024).toFixed(2)
|
|
||||||
let totalGB = (data.total / 1024).toFixed(0)
|
|
||||||
totalValues = `${remainingGB} GB von ${totalGB} GB`
|
|
||||||
}
|
|
||||||
let totalValuesText = widget.addText(totalValues)
|
|
||||||
totalValuesText.font = Font.mediumSystemFont(12)
|
|
||||||
totalValuesText.centerAlignText()
|
|
||||||
totalValuesText.textColor = textColor
|
|
||||||
|
|
||||||
// Remaining Days
|
// Remaining Days
|
||||||
if (data.endDate) {
|
if (data.endDate) {
|
||||||
widget.addSpacer(5)
|
widget.addSpacer(5)
|
||||||
let remainingDays = getTimeRemaining(data.endDate).days + 2
|
let remainingDays = getTimeRemaining(data.endDate).days + 2
|
||||||
|
if(data.billDate && showRemainingDaysAsProgressbar) {
|
||||||
|
const startDate = new Date(data.billDate)
|
||||||
|
const endDate = new Date(data.endDate)
|
||||||
|
const total = (endDate - startDate) / (1000 * 60 * 60 * 24)
|
||||||
|
|
||||||
|
const progressBarStack = widget.addStack()
|
||||||
|
progressBarStack.layoutHorizontally()
|
||||||
|
progressBarStack.addSpacer()
|
||||||
|
|
||||||
|
const progressBar = progressBarStack.addImage(creatProgress(total, total - remainingDays))
|
||||||
|
progressBarStack.addSpacer()
|
||||||
|
widget.addSpacer(4)
|
||||||
|
}
|
||||||
|
|
||||||
let remainingDaysText = widget.addText(`${remainingDays} Tage verbleibend`)
|
let remainingDaysText = widget.addText(`${remainingDays} Tage verbleibend`)
|
||||||
remainingDaysText.font = Font.mediumSystemFont(8)
|
remainingDaysText.font = Font.systemFont(8)
|
||||||
remainingDaysText.centerAlignText()
|
remainingDaysText.centerAlignText()
|
||||||
remainingDaysText.textColor = textColor
|
remainingDaysText.textColor = textColor
|
||||||
}
|
}
|
||||||
|
@ -383,7 +511,12 @@ if (data !== undefined) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!config.runsInWidget) {
|
if (!config.runsInWidget) {
|
||||||
await widget.presentSmall()
|
switch (config.widgetFamily) {
|
||||||
|
case 'small': await widget.presentSmall(); break;
|
||||||
|
case 'medium': await widget.presentMedium(); break;
|
||||||
|
case 'large': await widget.presentLarge(); break;
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Tell the system to show the widget.
|
// Tell the system to show the widget.
|
||||||
Script.setWidget(widget)
|
Script.setWidget(widget)
|
||||||
|
|
Loading…
Add table
Reference in a new issue