Skip to content

Instantly share code, notes, and snippets.

@SDuck4
Last active November 3, 2023 12:19
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • 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 Jan 26, 2021

Date Progress - 일, 주, 월, 년 진행도를 보여주는 위젯

DateProgress3

파라미터

  • 각 파라미터는 |(세로선)으로 구분하며, 다음 순서로 입력합니다.
  • 만약 파라미터를 사용하지 않으면 생략해도 됩니다.
  1. 색상: 진행 바 색상을 설정합니다.

    • 설정할 색상을 헥스코드 형식으로 입력합니다.
    • 각 색상은 ,(컴마)로 구분합니다.
    • 1~4개의 색상을 설정할 수 있습니다.
    • 색상의 개수가 4보다 작으면, 색상을 반복합니다.
    • Ex 1. #3B82F6,#10B981,#FBBF24,#EF4444
    • Ex 2. #34D399
  2. 라벨: 진행 바 라벨의 텍스트를 설정합니다.

    • 각 라벨은 ,(컴마)로 구분합니다.
    • 다음 템플릿 문자열을 사용할 수 있습니다.
      • ${dayOfMonth}: 월의 일자. Ex. 1
      • ${dayOfMonthWithZero}: 월의 일자를 0과 함께 출력. Ex. 01
      • ${dayEn}: 요일의 영문 약자. Ex. Sun, Mon, Tue, ...
      • ${dayKo}: 요일의 국문 약자. Ex. 일, 월, 화, ...
      • ${weekOfYear}: 연도의 주차 수. Ex. 42
      • ${weekOfYearWithZero}: 연도의 주차 수를 0과 함께 출력. Ex. 04
      • ${monthNum}: 월 숫자. Ex. 11
      • ${monthNumWithZero}: 월 숫자를 0과 함께 출력. Ex. 06
      • ${monthEn}: 월의 영문 약자. Ex. Jan, Fab, Mar, ...
      • ${year}: 연도 숫자. Ex. 2021
    • Ex. ${dayKo}요일,${weekOfYear}주차,${monthNum}월,${year}년
  3. 일주일이 일요일에 시작: 일주일의 시작 요일을 설정합니다.

    • 만약 true이면, 일주일이 일요일에 시작합니다.
    • 만약 false이면, 일주일이 월요일에 시작합니다.
    • 기본 값은 false 입니다.

@SDuck4
Copy link
Author

SDuck4 commented Nov 2, 2023

Scriptable v1.7.12에서 백그라운드 컬러를 출력하지 않는 오류가 있어 임시로 테두리를 사용해 진행 바 색상을 출력합니다.

@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