Skip to content

Instantly share code, notes, and snippets.

@joshdholtz
Created May 9, 2021 01:13
Show Gist options
  • Save joshdholtz/33b9bf6018526018381468361d3d18f5 to your computer and use it in GitHub Desktop.
Save joshdholtz/33b9bf6018526018381468361d3d18f5 to your computer and use it in GitHub Desktop.
Official Indie Dev Monday Widget For Scriptable
/*
* 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