Created
May 9, 2021 01:13
-
-
Save joshdholtz/33b9bf6018526018381468361d3d18f5 to your computer and use it in GitHub Desktop.
Official Indie Dev Monday Widget For Scriptable
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* This is the offical Scriptable widget for Indie Dev Monday | |
* | |
* Indie Dev Monday (https://indiedevmonday.com) is a weekly newsletter | |
* spotlighting indie developers | |
* | |
* This script includes: | |
* | |
* Latest issue widget (no parameter) | |
* - shows latest issue | |
* - works in small, medium, and large | |
* - tapping opens latest issues | |
* | |
* Random indie dev widget ("indie" has text parameter) | |
* - shows a random indie that has already been spotlighted | |
* - tapping opens that indie's issue | |
* | |
*/ | |
let indies = await loadIndies() | |
let issues = (await loadIssues())["items"] | |
let widget = null | |
if (config.runsInWidget) { | |
if (config.widgetFamily == "small") { | |
widget = await createSmallWidget(indies, issues) | |
} else { | |
widget = await createMediumWidget(indies, issues) | |
} | |
Script.setWidget(widget) | |
Script.complete() | |
} else if (config.runsWithSiri) { | |
let widget = await createMediumWidget(indies, issues) | |
await widget.presentMedium() | |
Script.complete() | |
} else { | |
await presentMenu(indies, issues) | |
} | |
async function presentMenu(indies, issues) { | |
let alert = new Alert() | |
alert.title = issues[0].title | |
alert.message = | |
alert.addAction("View Small Widget") | |
alert.addAction("View Medium Widget") | |
alert.addAction("View Large Widget") | |
alert.addAction("Open Website") | |
alert.addCancelAction("Cancel") | |
let idx = await alert.presentSheet() | |
if (idx == 0) { | |
let widget = await createSmallWidget(indies, issues) | |
await widget.presentSmall() | |
} else if (idx == 1) { | |
let widget = await createMediumWidget(indies, issues) | |
await widget.presentMedium() | |
} else if (idx == 2) { | |
let widget = await createMediumWidget(indies, issues) | |
await widget.presentLarge() | |
} else if (idx == 3) { | |
Safari.open(issues[0].url) | |
} | |
} | |
async function createSmallWidget(indies, issues) { | |
let style = args.widgetParameter | |
if (style === "indie") { | |
return createSmallWidgetIndie(indies, issues) | |
} else { | |
return createSmallWidgetIssue(indies, issues) | |
} | |
} | |
async function createSmallWidgetIndie(indies, issues) { | |
let indie = indies[Math.floor(Math.random()*indies.length)]; | |
// Widget | |
let w = new ListWidget() | |
w.backgroundColor = new Color("#ac3929") | |
w.url = "https://indiedevmonday.com/issue-" + indie.issue | |
w.refreshAfterDate = new Date(Date.now() + (3600 * 4 * 1000)) // i think 4 hours | |
console.log(w.refreshAfterDate) | |
w.setPadding(10, 10, 10, 10) | |
let wissue = w.addText(indie.full_name) | |
wissue.font = Font.boldRoundedSystemFont(16) | |
wissue.textColor = Color.white() | |
wissue.lineLimit = 2 | |
wissue.centerAlignText() | |
wissue.minimumScaleFactor = 0.2 | |
w.addSpacer(8) | |
let urlSlug = "https://indiedevmonday.com/assets/images/indies/" + indie.slug + ".png" | |
let img = await loadImage(urlSlug) | |
let personImg = w.addImage(img) | |
personImg.centerAlignImage() | |
w.addSpacer() | |
let wtitle = w.addText("Indie Dev Monday") | |
wtitle.font = Font.lightRoundedSystemFont(10) | |
wtitle.textColor = Color.white() | |
wtitle.lineLimit = 1 | |
wtitle.centerAlignText() | |
wtitle.minimumScaleFactor = 0.2 | |
return w | |
} | |
async function createSmallWidgetIssue(indies, issues) { | |
// Indie and issue data | |
let indie = indies[0] | |
let issue = issues[0] | |
let title = issue.title | |
let issueNumber = issue.url.split('-')[1] | |
let indiesInIssue = indies.filter(function(indie) { | |
return indie.issue === issueNumber | |
}) | |
let indieNames = indiesInIssue.map(function(indie) { | |
return indie.name | |
}) | |
title = indieNames.slice(0, -1).join(',')+' and '+indieNames.slice(-1); | |
// Widget | |
let w = new ListWidget() | |
w.backgroundColor = new Color("#ac3929") | |
w.url = "https://indiedevmonday.com/issue-" + indie.issue | |
//w.refreshAfterDate = end | |
w.setPadding(15, 15, 15, 15) | |
// Issue number and logo | |
let hstack = w.addStack() | |
hstack.layoutHorizontally() | |
hstack.bottomAlignContent() | |
let wissue = hstack.addText("#" + issueNumber) | |
wissue.font = Font.boldRoundedSystemFont(18) | |
wissue.textColor = Color.white() | |
wissue.lineLimit = 2 | |
wissue.centerAlignText() | |
wissue.minimumScaleFactor = 0.2 | |
hstack.addSpacer() | |
let imglogo = await loadLogo() | |
let wimg = hstack.addImage(imglogo) | |
wimg.imageSize = new Size(30, 30) | |
wimg.cornerRadius = 12 | |
w.addSpacer(8) | |
// Title | |
let wtitle = w.addText(title) | |
wtitle.font = Font.boldRoundedSystemFont(22) | |
wtitle.lineLimit = 2 | |
w.addSpacer() | |
// date | |
let wdate = w.addDate(getIssueDate(issue)) | |
wdate.font = Font.lightRoundedSystemFont(14) | |
return w | |
} | |
async function createMediumWidget(indies, issues) { | |
// Indie and issue data | |
let indie = indies[0] | |
let issue = issues[0] | |
let title = issue.title | |
let issueNumber = issue.url.split('-')[1] | |
let indiesInIssue = indies.filter(function(indie) { | |
return indie.issue === issueNumber | |
}) | |
let indieNames = indiesInIssue.map(function(indie) { | |
return indie.name | |
}) | |
if (indieNames.length > 0) { | |
title = indieNames.slice(0, -1).join(',')+' and '+indieNames.slice(-1); | |
} | |
// Widget | |
let w = new ListWidget() | |
w.backgroundColor = new Color("#ac3929") | |
w.url = "https://indiedevmonday.com/issue-" + indie.issue | |
//w.refreshAfterDate = end | |
w.setPadding(15, 15, 15, 15) | |
// Issue number and logo | |
let hstack = w.addStack() | |
hstack.layoutHorizontally() | |
hstack.bottomAlignContent() | |
let wissue = hstack.addText("#" + issueNumber) | |
wissue.font = Font.boldRoundedSystemFont(18) | |
wissue.textColor = Color.white() | |
wissue.lineLimit = 2 | |
wissue.centerAlignText() | |
wissue.minimumScaleFactor = 0.2 | |
hstack.addSpacer(5) | |
let wdate = hstack.addDate(getIssueDate(issue)) | |
wdate.font = Font.lightRoundedSystemFont(14) | |
hstack.addSpacer() | |
let imglogo = await loadLogo() | |
let wimg = hstack.addImage(imglogo) | |
wimg.imageSize = new Size(30, 30) | |
wimg.cornerRadius = 12 | |
w.addSpacer(8) | |
// Title | |
let wtitle = w.addText(title) | |
wtitle.font = Font.boldRoundedSystemFont(22) | |
wtitle.lineLimit = 2 | |
w.addSpacer(12) | |
let hstack2 = w.addStack() | |
hstack2.layoutHorizontally() | |
hstack2.addSpacer() | |
hstack2.addSpacer(8) | |
for (indie of indiesInIssue) { | |
let urlSlug = "https://indiedevmonday.com/assets/images/indies/" + indie.slug + ".png" | |
let img = await loadImage(urlSlug) | |
hstack2.addImage(img) | |
hstack2.addSpacer(8) | |
} | |
hstack2.addSpacer() | |
w.addSpacer() | |
return w | |
} | |
function getIssueDate(issue) { | |
let date = issue["date_published"] | |
let formatter = new DateFormatter() | |
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ" | |
return formatter.date(date) | |
} | |
async function loadIndies() { | |
let url = "https://indiedevmonday.com/indies.json" | |
let req = new Request(url) | |
return req.loadJSON() | |
} | |
async function loadIssues() { | |
let url = "https://indiedevmonday.com/feed.json" | |
let req = new Request(url) | |
return req.loadJSON() | |
} | |
async function loadLogo() { | |
let url = "https://indiedevmonday.com/assets/images/logo_trans.png" | |
return await loadImage(url) | |
} | |
async function loadImage(url) { | |
let req = new Request(url) | |
return req.loadImage() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment