Skip to content

Instantly share code, notes, and snippets.

@CyberBatMan2077
Forked from bjayers/home-hello.js
Last active October 1, 2020 15:15
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 CyberBatMan2077/8ac39f169066a4a20320ee4572e1eafa to your computer and use it in GitHub Desktop.
Save CyberBatMan2077/8ac39f169066a4a20320ee4572e1eafa to your computer and use it in GitHub Desktop.
iOS Scriptable Widget
// 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