-
-
Save CyberBatMan2077/8ac39f169066a4a20320ee4572e1eafa to your computer and use it in GitHub Desktop.
iOS Scriptable Widget
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
// The part of cutting background pic | |
// and set it as widget background was created by Max Zeryck @mzeryck | |
// The part of setting date and greeting message was created by bjayers | |
// GitHub Gist URL: https://gist.github.com/bjayers/28be68a96c2257da16a0f5f4f9283798 | |
// These two functions were combined by CyberBatMan2077 and submitted in a fork from bjayers | |
// ------------------------------------------------------------------------------------------ | |
// The padding-top spacing parameter moves the text down by a set amount. | |
// The text color parameter should be a hex value. | |
// And the sentence you would like to show should follow the color parameter | |
// E.g: 50|#923632|May the force be with you | |
// All parameters are required and separated with "|" | |
// Parameters allow different settings for multiple widget instances. | |
// Widgets are unique based on the name of the script. | |
const filename = Script.name() + ".jpg" | |
const files = FileManager.local() | |
const path = files.joinPath(files.documentsDirectory(), filename) | |
let widgetHello = new ListWidget(); | |
var today = new Date(); | |
var widgetInputRAW = args.widgetParameter; | |
try { | |
widgetInputRAW.toString(); | |
} catch(e) { | |
widgetInputRAW = "50|#923632|"; | |
} | |
var widgetInput = widgetInputRAW.toString(); | |
var inputArr = widgetInput.split("|"); | |
var spacing = parseInt(inputArr[0]); | |
// Long-form days and months | |
var days = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday']; | |
var months = ['January','February','March','April','May','June','July','August','September','October','November','December']; | |
// Greetings arrays per time period. | |
var greetingsMorning = [ | |
'Good morning.' | |
]; | |
var greetingsAfternoon = [ | |
'Good afternoon.' | |
]; | |
var greetingsEvening = [ | |
'Good evening.' | |
]; | |
var greetingsNight = [ | |
'Bedtime.' | |
]; | |
var greetingsLateNight = [ | |
'Go to sleep!' | |
]; | |
// Holiday customization | |
var holidaysByKey = { | |
// month,week,day: datetext | |
"11,4,4": "Happy Thanksgiving!" | |
} | |
var holidaysByDate = { | |
// month,date: greeting | |
"1,1": "Happy " + (today.getFullYear()).toString() + "!", | |
"10,31": "Happy Halloween!", | |
"12,25": "Merry Christmas!" | |
} | |
var holidayKey = (today.getMonth() + 1).toString() + "," + (Math.ceil(today.getDate() / 7)).toString() + "," + (today.getDay()).toString(); | |
var holidayKeyDate = (today.getMonth() + 1).toString() + "," + (today.getDate()).toString(); | |
// Date Calculations | |
var weekday = days[ today.getDay() ]; | |
var month = months[ today.getMonth() ]; | |
var date = today.getDate(); | |
var hour = today.getHours(); | |
// Append ordinal suffix to date | |
// Generate date string | |
var datefull = weekday + ", " + month + " " + ordinalSuffix(date); | |
// Generate user define text string | |
var usertextfull = inputArr[2] | |
// Support for multiple greetings per time period | |
let themeColor = new Color(inputArr[1].toString()); | |
var greeting = new String("Howdy.") | |
if (hour < 5 && hour >= 1) { // 1am - 5am | |
greeting = greetingsLateNight[randomGreeting(greetingsLateNight)]; | |
} else if (hour >= 23 || hour < 1) { // 11pm - 1am | |
greeting = greetingsNight[randomGreeting(greetingsNight)]; | |
} else if (hour < 12) { // Before noon (5am - 12pm) | |
greeting = greetingsMorning[randomGreeting(greetingsMorning)]; | |
} else if (hour >= 12 && hour <= 17) { // 12pm - 5pm | |
greeting = greetingsAfternoon[randomGreeting(greetingsAfternoon)]; | |
} else if (hour > 17 && hour < 23) { // 5pm - 11pm | |
greeting = greetingsEvening[randomGreeting(greetingsEvening)]; | |
} | |
// Overwrite greeting if calculated holiday | |
if (holidaysByKey[holidayKey]) { | |
greeting = holidaysByKey[holidayKey]; | |
} | |
// Overwrite all greetings if specific holiday | |
if (holidaysByDate[holidayKeyDate]) { | |
greeting = holidaysByDate[holidayKeyDate]; | |
} | |
if (config.runsInWidget) { | |
let widget = new ListWidget() | |
widget.backgroundImage = files.readImage(path) | |
// You can your own code here to add additional items to the "invisible" background of the widget. | |
/* --------------- */ | |
/* Assemble Widget */ | |
/* --------------- */ | |
//Top spacing | |
widgetHello.addSpacer(parseInt(spacing)); | |
// Greeting label | |
let hello = widgetHello.addText(greeting); | |
hello.font = Font.boldSystemFont(42); | |
hello.textColor = themeColor; | |
// Date label | |
let datetext = widgetHello.addText(datefull); | |
datetext.font = Font.regularSystemFont(16); | |
datetext.textColor = themeColor; | |
// User define text | |
widgetHello.addText(" ") | |
let usertext = widgetHello.addText(usertextfull); | |
usertext.font = Font.boldSystemFont(25); | |
usertext.textColor = themeColor; | |
// Bottom Spacer | |
widgetHello.addSpacer(); | |
widgetHello.setPadding(15, 7, 10, 0) | |
widgetHello.backgroundImage = widget.backgroundImage | |
Script.setWidget(widgetHello) | |
Script.complete() | |
/* | |
* The code below this comment is used to set up the invisible widget. | |
* =================================================================== | |
*/ | |
} else { | |
// Determine if user has taken the screenshot. | |
var message | |
message = "Before you start, go to your home screen and enter wiggle mode. Scroll to the empty page on the far right and take a screenshot." | |
let exitOptions = ["Continue","Exit to Take Screenshot"] | |
let shouldExit = await generateAlert(message,exitOptions) | |
if (shouldExit) return | |
// Get screenshot and determine phone size. | |
let img = await Photos.fromLibrary() | |
let height = img.size.height | |
let phone = phoneSizes()[height] | |
if (!phone) { | |
message = "It looks like you selected an image that isn't an iPhone screenshot, or your iPhone is not supported. Try again with a different image." | |
await generateAlert(message,["OK"]) | |
return | |
} | |
// Prompt for widget size and position. | |
message = "What size of widget are you creating?" | |
let sizes = ["Small","Medium","Large"] | |
let size = await generateAlert(message,sizes) | |
let widgetSize = sizes[size] | |
message = "What position will it be in?" | |
message += (height == 1136 ? " (Note that your device only supports two rows of widgets, so the middle and bottom options are the same.)" : "") | |
// Determine image crop based on phone size. | |
let crop = { w: "", h: "", x: "", y: "" } | |
if (widgetSize == "Small") { | |
crop.w = phone.small | |
crop.h = phone.small | |
let positions = ["Top left","Top right","Middle left","Middle right","Bottom left","Bottom right"] | |
let position = await generateAlert(message,positions) | |
// Convert the two words into two keys for the phone size dictionary. | |
let keys = positions[position].toLowerCase().split(' ') | |
crop.y = phone[keys[0]] | |
crop.x = phone[keys[1]] | |
} else if (widgetSize == "Medium") { | |
crop.w = phone.medium | |
crop.h = phone.small | |
// Medium and large widgets have a fixed x-value. | |
crop.x = phone.left | |
let positions = ["Top","Middle","Bottom"] | |
let position = await generateAlert(message,positions) | |
let key = positions[position].toLowerCase() | |
crop.y = phone[key] | |
} else if(widgetSize == "Large") { | |
crop.w = phone.medium | |
crop.h = phone.large | |
crop.x = phone.left | |
let positions = ["Top","Bottom"] | |
let position = await generateAlert(message,positions) | |
// Large widgets at the bottom have the "middle" y-value. | |
crop.y = position ? phone.middle : phone.top | |
} | |
// Crop image and finalize the widget. | |
let imgCrop = cropImage(img, new Rect(crop.x,crop.y,crop.w,crop.h)) | |
message = "All set" | |
const finishConfirm = ["OK"] | |
const finishConfirmBox = await generateAlert(message, finishConfirm) | |
files.writeImage(path,imgCrop) | |
Script.complete() | |
} | |
// Generate an alert with the provided array of options. | |
async function generateAlert(message,options) { | |
let alert = new Alert() | |
alert.message = message | |
for (const option of options) { | |
alert.addAction(option) | |
} | |
let response = await alert.presentAlert() | |
return response | |
} | |
// Crop an image into the specified rect. | |
function cropImage(img,rect) { | |
let draw = new DrawContext() | |
draw.size = new Size(rect.width, rect.height) | |
draw.drawImageAtPoint(img,new Point(-rect.x, -rect.y)) | |
return draw.getImage() | |
} | |
// Pixel sizes and positions for widgets on all supported phones. | |
function phoneSizes() { | |
let phones = { | |
"2688": { | |
"small": 507, | |
"medium": 1080, | |
"large": 1137, | |
"left": 81, | |
"right": 654, | |
"top": 228, | |
"middle": 858, | |
"bottom": 1488 | |
}, | |
"1792": { | |
"small": 338, | |
"medium": 720, | |
"large": 758, | |
"left": 54, | |
"right": 436, | |
"top": 160, | |
"middle": 580, | |
"bottom": 1000 | |
}, | |
"2436": { | |
"small": 465, | |
"medium": 987, | |
"large": 1035, | |
"left": 69, | |
"right": 591, | |
"top": 213, | |
"middle": 783, | |
"bottom": 1353 | |
}, | |
"2208": { | |
"small": 471, | |
"medium": 1044, | |
"large": 1071, | |
"left": 99, | |
"right": 672, | |
"top": 114, | |
"middle": 696, | |
"bottom": 1278 | |
}, | |
"1334": { | |
"small": 296, | |
"medium": 642, | |
"large": 648, | |
"left": 54, | |
"right": 400, | |
"top": 60, | |
"middle": 412, | |
"bottom": 764 | |
}, | |
"1136": { | |
"small": 282, | |
"medium": 584, | |
"large": 622, | |
"left": 30, | |
"right": 332, | |
"top": 59, | |
"middle": 399, | |
"bottom": 399 | |
} | |
} | |
return phones | |
} | |
function ordinalSuffix(input) { | |
if (input % 10 == 1 && date != 11) { | |
return input.toString() + "st"; | |
} else if (input % 10 == 2 && date != 12) { | |
return input.toString() + "nd"; | |
} else if (input % 10 == 3 && date != 13) { | |
return input.toString() + "rd"; | |
} else { | |
return input.toString() + "th"; | |
} | |
} | |
function randomGreeting(greetingArray) { | |
return Math.floor(Math.random() * greetingArray.length); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment