Skip to content

Instantly share code, notes, and snippets.

@SDuck4
Last active November 3, 2023 12:19
Show Gist options
  • Save SDuck4/a655230ec214083e432566a84e24c5f8 to your computer and use it in GitHub Desktop.
Save SDuck4/a655230ec214083e432566a84e24c5f8 to your computer and use it in GitHub Desktop.
Date Progress - Progress bar widget for days, weeks, months and years
/**
* Date Progress - Progress bar widget for days, weeks, months and years
* - This widget run by Scriptable(https://scriptable.app).
* - This widget is optimized for 4x2 size.
* - Author: SDuck (https://twitter.com/sduck4)
* - Source: https://gist.github.com/SDuck4/a655230ec214083e432566a84e24c5f8
*
* Parameters:
* - Each parameter is separated by `|`(vertical bar) and must be entered in the following order.
* - If you do not use the parameters, you can skip them.
*
* 1. Colors: Set colors of progress bars
* - Enter the color you want to set in hexcode format.
* - Each color is separated by `,`(comma).
* - You can enter 1~4 colors.
* - If the number of colors is smaller than 4, repeat the colors.
* - Ex 1. #3B82F6,#10B981,#FBBF24,#EF4444
* - Ex 2. #34D399
*
* 2. Labels: Set text for progress bar labels
* - Each label is separated by `,`(comma).
* - You can use the template string below.
* - ${dayOfMonth}: the day of the month. Ex. 1
* - ${dayOfMonthWithZero}: the day of the month with zero. Ex. 01
* - ${dayEn}: the days of the week in English. Ex. Sun, Mon, Tue, ...
* - ${dayKo}: the days of the week in Korean. Ex. 일, 월, 화, ...
* - ${weekOfYear}: the week number of the year. Ex. 42
* - ${weekOfYearWithZero}: the week number of the year with zero. Ex. 04
* - ${monthNum}: the month number. Ex. 11
* - ${monthNumWithZero}: the month number with zero. Ex. 06
* - ${monthEn}: the month name in English. Ex. Jan, Fab, Mar, ...
* - ${year}: the year number. Ex. 2021
* - Ex. ${dayEn},W${weekOfYearWithZero},${monthEn},${year}
*
* 3. The week starts on Sunday: Set the day of the week starts
* - If `true`, the week starts on Sunnday.
* - If `false`, the week starts on Monday.
* - Default value is `false`.
*/
const FONT_SIZE = 16;
const LINE_HEIGHT = 24;
const LABEL_WIDTH = 100;
const SPACER_SIZE = 10;
const BAR_WIDTH = 180;
const BAR_HEIGHT = 12;
const COLOR_LIGHT_GRAY = new Color('#E5E7EB', 1);
const COLOR_DARK_GRAY = new Color('#374151', 1);
const COLOR_BAR_BACKGROUND = Color.dynamic(COLOR_LIGHT_GRAY, COLOR_DARK_GRAY);
const COLOR_BAR_DEFAULT = new Color('#3B82F6', 1);
// Process parameters
const params = (args.widgetParameter + '').split('|');
// Parameter: Colors
let colors = [];
if (params[0] !== '' && params[0] !== 'null') {
colors = params[0].split(',').map(color => color.trim());
colors = colors.map(color => new Color(color, 1));
} else {
colors.push(COLOR_BAR_DEFAULT);
}
function getColors(index) {
return colors[index % colors.length];
}
// Parameter: The week starts on Sunday
let isWeekStartsOnSunday = false;
if (params.length > 2 && params[2].toLowerCase() === 'true') {
isWeekStartsOnSunday = true;
}
// Parameter: Labels
const now = new Date();
const labels = ['Day', 'Week', 'Month', 'Year'];
const calcWeekOfYear = (date) => {
const firstDayOfYear = new Date(date.getFullYear(), 0, 1);
const dayOfFirstDay = firstDayOfYear.getDay();
const firstWeekStart = new Date(date.getFullYear(), 0, firstDayOfYear.getDay() > 3 ? 8 - dayOfFirstDay : 1 - dayOfFirstDay);
const dateValue = isWeekStartsOnSunday ? date.valueOf() : date.valueOf() - 86400000;
const weekNum = Math.floor((dateValue - firstWeekStart.valueOf()) / 86400000 / 7) + 1;
return weekNum;
};
const labelsTemplate = {
dayOfMonth: date => {
return date.getDate();
},
dayOfMonthWithZero: date => {
const dayNum = date.getDate();
return dayNum < 10 ? '0' + dayNum : dayNum;
},
dayEn: date => {
return ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'][date.getDay()];
},
dayKo: date => {
return ['일', '월', '화', '수', '목', '금', '토'][date.getDay()];
},
weekOfYear: date => {
let weekNum = calcWeekOfYear(date);
if (weekNum === 0) {
weekNum = calcWeekOfYear(new Date(date.getFullYear(), 0, 0));
}
return weekNum;
},
weekOfYearWithZero: date => {
let weekNum = calcWeekOfYear(date);
if (weekNum === 0) {
weekNum = calcWeekOfYear(new Date(date.getFullYear(), 0, 0));
}
return weekNum < 10 ? '0' + weekNum : weekNum;
},
monthNum: date => {
return date.getMonth() + 1;
},
monthNumWithZero: date => {
const monthNum = date.getMonth() + 1;
return monthNum < 10 ? '0' + monthNum : monthNum;
},
monthEn: date => {
return ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'][date.getMonth()];
},
year: date => {
return date.getFullYear();
},
};
if (params.length > 1 && params[1] !== '') {
const paramLabels = params[1].split(',').map(label => label.trim());
const templateRegExp = /(\${[^{}]+})/;
for (let i = 0; i < paramLabels.length; i++) {
while (paramLabels[i].match(templateRegExp)) {
const template = paramLabels[i].match(templateRegExp)[0];
const templateKey = template.replace('${', '').replace('}', '');
const templateValue = labelsTemplate[templateKey](now);
paramLabels[i] = paramLabels[i].replace(template, templateValue);
}
labels[i] = paramLabels[i];
}
}
// Calculate date progress
function calcProgress(start, end, progress) {
return (progress - start) / (end - start);
}
const dayStart = new Date(now.getFullYear(), now.getMonth(), now.getDate());
const dayEnd = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1);
const dayProgress = calcProgress(dayStart, dayEnd, now);
let weekDay = now.getDay() === 0 ? 6 : now.getDay() - 1;
if (isWeekStartsOnSunday) {
weekDay = now.getDay();
}
const weekStart = new Date(now.getFullYear(), now.getMonth(), now.getDate() - weekDay);
const weekEnd = new Date(weekStart.getFullYear(), weekStart.getMonth(), weekStart.getDate() + 7);
const weekProgress = calcProgress(weekStart, weekEnd, now);
const monthStart = new Date(now.getFullYear(), now.getMonth(), 1);
const monthEnd = new Date(now.getFullYear(), now.getMonth() + 1, 1);
const monthProgress = calcProgress(monthStart, monthEnd, now);
const yearStart = new Date(now.getFullYear(), 0, 1);
const yearEnd = new Date(now.getFullYear() + 1, 0, 1);
const yearProgress = calcProgress(yearStart, yearEnd, now);
// Create Widget
const font = Font.systemFont(FONT_SIZE);
const widget = new ListWidget();
widget.spacing = SPACER_SIZE;
function addProgress(name, progress, color) {
const percent = Math.round(progress * 100);
const line = widget.addStack();
line.centerAlignContent();
const label = line.addStack();
label.size = new Size(LABEL_WIDTH, LINE_HEIGHT);
label.centerAlignContent();
const labelName = label.addText(name);
labelName.font = font;
label.addSpacer();
const labelPercent = label.addText(percent + '%');
labelPercent.font = font;
line.addSpacer(SPACER_SIZE);
const barBackground = line.addStack();
barBackground.size = new Size(BAR_WIDTH, BAR_HEIGHT);
barBackground.backgroundColor = COLOR_BAR_BACKGROUND;
barBackground.cornerRadius = BAR_HEIGHT / 2;
barBackground.topAlignContent();
barBackground.layoutVertically();
const barProgressWidth = BAR_WIDTH * progress;
const barProgress = barBackground.addStack();
barProgress.size = new Size(barProgressWidth, BAR_HEIGHT);
barProgress.backgroundColor = color;
barProgress.cornerRadius = BAR_HEIGHT / 2;
}
addProgress(labels[0], dayProgress, getColors(0));
addProgress(labels[1], weekProgress, getColors(1));
addProgress(labels[2], monthProgress, getColors(2));
addProgress(labels[3], yearProgress, getColors(3));
widget.presentMedium();
Script.setWidget(widget);
@SDuck4
Copy link
Author

SDuck4 commented Nov 3, 2023

Scriptable v1.7.13에서 백그라운드 컬러 문제가 해결되어 기존 버전으로 변경합니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment