Skip to content

Instantly share code, notes, and snippets.

@simonfrey
Last active January 13, 2021 08:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save simonfrey/3d5c111af0aa2dc05e98137b44f575bf to your computer and use it in GitHub Desktop.
Save simonfrey/3d5c111af0aa2dc05e98137b44f575bf to your computer and use it in GitHub Desktop.
Checkvist Due Tasks Widget (iOS Scriptable App)
//
// Scriptable widget for your checkvist due tasks
//
// Checkvist: https://checkvist.com/
// Scriptable: https://scriptable.app/
//
// See how it looks: https://simon-frey.com/files/checkvist_ios_scriptable_widget.png
//
// Settings
const username = '[YOUR EMAIL];
const openAPIToken = '[Open API Key from Profile]';
const backgroundColor = new Color("#FFF");
const textColor = new Color("#000");
const overdueTextColor = new Color("#e0485b");
//
//
// DO NOT EDIT BELLOW HERE
//
const now = new Date();
async function loadDueTasks() {
const host = 'https://checkvist.com';
const fmt = '.json';
const headers = {
'Authorization': 'Basic ' + btoa(username + ":" + openAPIToken),
}
// Get all lists
let allListsRequest = new Request(host + '/checklists' + fmt);
allListsRequest.headers = headers;
const allLists = await allListsRequest.loadJSON();
const activeLists = allLists.filter(list => {
return !list.archived
});
var tasks = [];
for (const list of activeLists) {
let singleListsTasksResquest = new Request(host + '/checklists/' + list.id + "/tasks" + fmt);
singleListsTasksResquest.headers = headers;
const singleListTasks = await singleListsTasksResquest.loadJSON();
const newTasks = singleListTasks.filter(task => {
if (task.status != 0) {
// Task is not open
return false
}
if (task.due == null) {
// Task has no due date
return false
}
if (task.due == "ASAP") {
// ASAP task
return true
}
return Date.parse(task.due) <= now;
})
if (newTasks.length == 0) {
continue
}
tasks = tasks.concat(newTasks);
};
tasks.sort(
function (a, b) {
let aDate = new Date();
if (a.due != "ASAP") {
aDate = Date.parse(a.due)
}
let bDate = new Date();
if (b.due != "ASAP") {
bDate = Date.parse(b.due)
}
return aDate-bDate
});
return tasks;
}
async function createWidget(tasks) {
let widget = new ListWidget()
widget.backgroundColor = backgroundColor;
if (tasks == undefined || tasks.length ==0){
let subtitle = widget.addText("Nothing due today")
subtitle.font = Font.mediumSystemFont(25);
subtitle.textColor = textColor;
subtitle.centerAlignText();
return widget
}
let fontSize = 13* (7/tasks.length);
if (fontSize > 15){
fontSize = 15;
}
tasks.forEach(task => {
let taskText = widget.addText("• "+task.content)
taskText.font = Font.mediumSystemFont(fontSize);
taskText.leftAlignText()
taskText.textColor = textColor;
if (task.due != "ASAP" && Date.parse(task.due) < now){
taskText.textColor = overdueTextColor;
}
});
return widget
}
const dueTasks = await loadDueTasks();
console.log("DUE: "+JSON.stringify(dueTasks))
const widget = await createWidget(dueTasks)
if (config.runsInWidget) {
Script.setWidget(widget)
} else {
widget.presentMedium()
}
Script.complete()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment