- Install and download the free Scriptable app on your iOS device.
- Inside the app, press the "Plus" icon to create a new script
- Paste the content of the JS file into the script
- Place a Scriptable widget on your home screen
Last active
December 6, 2022 22:45
-
-
Save mpociot/04ee7480399479a68237b43763bbc791 to your computer and use it in GitHub Desktop.
A Scriptable widget to show the upcoming Laracon talks
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
/****************************************************************************** | |
* Constants and Configurations | |
*****************************************************************************/ | |
// Font name and size | |
const FONT_NAME = 'Menlo'; | |
const FONT_SIZE = 10; | |
// Colors | |
const COLORS = { | |
bg0: '#29323c', | |
bg1: '#1c1c1c', | |
even: '#5BD2F0', | |
odd: '#9D90FF', | |
}; | |
// Fetch data and create widget | |
const data = fetchData(); | |
const widget = createWidget(data); | |
if (config.runsInApp) { | |
widget.presentMedium(); | |
} | |
Script.setWidget(widget); | |
Script.complete(); | |
/****************************************************************************** | |
* Main Functions (Widget and Data-Fetching) | |
*****************************************************************************/ | |
/** | |
* Main widget function. | |
* | |
* @param {} data The data for the widget to display | |
*/ | |
function createWidget(data) { | |
console.log(`Creating widget with data: ${JSON.stringify(data)}`); | |
const widget = new ListWidget(); | |
const bgColor = new LinearGradient(); | |
bgColor.colors = [new Color(COLORS.bg0), new Color(COLORS.bg1)]; | |
bgColor.locations = [0.0, 1.0]; | |
widget.backgroundGradient = bgColor; | |
widget.setPadding(10, 15, 15, 10); | |
const stack = widget.addStack(); | |
stack.layoutVertically(); | |
stack.spacing = 4; | |
stack.size = new Size(320, 0); | |
// Line 0 - Last Login | |
const timeFormatter = new DateFormatter(); | |
timeFormatter.locale = "en"; | |
timeFormatter.useNoDateStyle(); | |
timeFormatter.useShortTimeStyle(); | |
const lastLoginLine = stack.addText(`Last login: ${timeFormatter.string(new Date())} on ttys001`); | |
lastLoginLine.textColor = Color.white(); | |
lastLoginLine.textOpacity = 0.7; | |
lastLoginLine.font = new Font(FONT_NAME, FONT_SIZE); | |
// Line 1 - Input | |
const inputLine = stack.addText(`~ php artisan schedule:run`); | |
inputLine.textColor = Color.green(); | |
inputLine.font = new Font(FONT_NAME, FONT_SIZE); | |
const events = getUpcomingEvents(data.schedule); | |
events.map((event, i) => { | |
const nextEvent = stack.addText(formatEvent(event)); | |
nextEvent.textColor = new Color(i % 2 === 0 ? COLORS.even : COLORS.odd); | |
nextEvent.font = new Font(FONT_NAME, FONT_SIZE); | |
}); | |
if (events.length === 0) { | |
const nextEvent = stack.addText(`👋 See you at the next Laracon`); | |
nextEvent.textColor = new Color(COLORS.even); | |
nextEvent.font = new Font(FONT_NAME, FONT_SIZE); | |
} | |
return widget; | |
} | |
function formatEvent(event) { | |
let time = (new Date(event.date)).toLocaleString('en-US', { hour: 'numeric', minute: 'numeric', hour12: true }) | |
let description = `[${time}] ${event.emoji} – ${event.title}`; | |
return description; | |
} | |
function getUpcomingEvents(schedule) { | |
const now = new Date(); | |
return schedule.filter(event => { | |
// Add 60 minutes to event.date | |
const eventDate = new Date(event.date); | |
eventDate.setMinutes(eventDate.getMinutes() + 60); | |
return eventDate >= now; | |
}).slice(0, 6); | |
} | |
function fetchData() { | |
const schedule = [ | |
{ | |
time: '2:45 pm', | |
emoji: '🎉', | |
title: 'LARACON_INIT', | |
date: 1663159500000 | |
}, | |
{ | |
time: '3:00 pm', | |
emoji: '🗓', | |
title: 'Not Quite My Type', | |
speaker: 'Kai Sassnowski', | |
date: 1663160400000 | |
}, | |
{ | |
time: '3:40 pm', | |
emoji: '🗓', | |
title: 'Kubernetes and Laravel', | |
speaker: 'Bosun Egberinde', | |
date: 1663162800000 | |
}, | |
{ | |
time: '4:20 pm', | |
emoji: '🗓', | |
title: 'The future of Livewire', | |
speaker: 'Caleb Porzio', | |
date: 1663165200000 | |
}, | |
{ | |
time: '5:00 pm', | |
emoji: '☕️', | |
title: 'break', | |
date: 1663167600000 | |
}, | |
{ | |
time: '5:20 pm', | |
emoji: '⚡️', | |
title: 'Sustainable Self-Care', | |
speaker: 'Marje Holmstrom-Sabo', | |
date: 1663168800000 | |
}, | |
{ | |
time: '5:35 pm', | |
emoji: '⚡️', | |
title: "Let's Get Physical: Database Internals and You", | |
speaker: 'Tim Martin', | |
date: 1663169700000 | |
}, | |
{ | |
time: '5:50 pm', | |
emoji: '⚡️', | |
title: 'Deep Dive into Carbon', | |
speaker: 'Ralph J. Smit', | |
date: 1663170600000 | |
}, | |
{ | |
time: '6:05 pm', | |
emoji: '⚡️', | |
title: 'UI and Component testing with Cypress', | |
speaker: 'Marcel Pociot', | |
date: 1663171500000 | |
}, | |
{ | |
time: '6:20 pm', | |
emoji: '⚡️', | |
title: "The Hitchhiker's Guide to the Laravel Community", | |
speaker: 'Caneco', | |
date: 1663172400000 | |
}, | |
{ | |
time: '6:35 pm', | |
emoji: '🗓', | |
title: 'Abstracting too early', | |
speaker: 'Matt Stauffer', | |
date: 1663173300000 | |
}, | |
{ | |
time: '7:15 pm', | |
emoji: '☕️', | |
title: 'break', | |
date: 1663175700000 | |
}, | |
{ | |
time: '7:35 pm', | |
emoji: '🗓', | |
title: 'Laravel Update', | |
speaker: 'Taylor Otwell', | |
date: 1663176900000 | |
}, | |
{ | |
time: '8:35 pm', | |
emoji: '🗓', | |
title: 'Database Performance for Application Developers', | |
speaker: 'Aaron Francis', | |
date: 1663180500000 | |
}, | |
{ | |
time: '9:15 pm', | |
emoji: '🗓', | |
title: 'Christoph Dreams of Simple Code', | |
speaker: 'Christoph Rumpel', | |
date: 1663182900000 | |
}, | |
{ | |
time: '9:55 pm', | |
emoji: '☕️', | |
title: 'break', | |
date: 1663185300000 | |
}, | |
{ | |
time: '10:15 pm', | |
emoji: '⚡️', | |
title: "Is there any problem Git interactive rebase can't solve?", | |
speaker: 'Rissa Jackson', | |
date: 1663186500000 | |
}, | |
{ | |
time: '10:30 pm', | |
emoji: '⚡️', | |
title: 'Meaningful Mentorship', | |
speaker: 'Alex Six', | |
date: 1663187400000 | |
}, | |
{ | |
time: '10:45 pm', | |
emoji: '⚡️', | |
title: 'I shall say…err define this only once', | |
speaker: 'Freek Van der Herten', | |
date: 1663188300000 | |
}, | |
{ | |
time: '11:00 pm', | |
emoji: '⚡️', | |
title: "I can't believe it's not local!", | |
speaker: 'Chris Fidao', | |
date: 1663189200000 | |
}, | |
{ | |
time: '11:15 pm', | |
emoji: '⚡️', | |
title: 'Valid Variants of Validating Validation', | |
speaker: 'Luke Downing', | |
date: 1663190100000 | |
}, | |
{ | |
time: '11:30 pm', | |
emoji: '⚡️', | |
title: 'A Grab Bag of Useful Tips', | |
speaker: 'Colin DeCarlo', | |
date: 1663191000000 | |
}, | |
{ | |
time: '11:45 pm', | |
emoji: '⚡️', | |
title: 'Browsers are Magical Creatures', | |
speaker: 'Stephen Rees-Carter', | |
date: 1663191900000 | |
} | |
] | |
return { | |
schedule, | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment