Skip to content

Instantly share code, notes, and snippets.

Avatar

Simon Støvring simonbs

View GitHub Profile
@simonbs
simonbs / Unleashed.js
Created Oct 13, 2021
Scriptable widget that counts down to Apple's Unleashed event on October 18th
View Unleashed.js
// Variables used by Scriptable.
// These must be at the very top of the file. Do not edit.
// icon-color: blue; icon-glyph: apple-alt;
const TITLE = ""
const DATE = "2021-10-18T17:00:00Z"
const BG_IMG_URL = "https://i.ibb.co/YQ09XTW/background.png"
const TITLE_IMG_URL = "https://i.ibb.co/qYH3Y9w/text.png"
const TITLE_IMG_SIZE = new Size(155, 25)
const LINK = "https://www.youtube.com/watch?v=exM1uajp--A"
@simonbs
simonbs / ToolbarController.swift
Created Jul 23, 2021
Enable/disable a toolbar item in a Catalyst app.
View ToolbarController.swift
final class ToolbarController, NSObject, NSToolbarDelegate {
var isBackButtonEnabled = false {
didSet {
if isBackButtonEnabled != oldValue {
reloadBackItem()
}
}
}
func toolbar(_ toolbar: NSToolbar, itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier, willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? {
@simonbs
simonbs / Tour de France Profile.js
Created Jul 13, 2021
Scriptable script showing a profile of the current Tour de France stage
View Tour de France Profile.js
// Variables used by Scriptable.
// These must be at the very top of the file. Do not edit.
// icon-color: yellow; icon-glyph: bicycle;
let stages = await loadStages()
let stage = findStage(stages)
if (stage == null) {
let widget = createTournamentOverWidget()
await widget.presentMedium()
} else {
let stageDetails = await loadStageDetails(stage.id)
@simonbs
simonbs / Today's Pollen Count.js
Created May 30, 2021
Shows the current pollen counts. Pulls data from a Danish provider and only works in Denmark.
View Today's Pollen Count.js
// Variables used by Scriptable.
// These must be at the very top of the file. Do not edit.
// icon-color: deep-green; icon-glyph: sun;
const STATION_VIBORG = "49"
const STATION_CPH = "48"
const GRASS_ID = "28"
const PREVIEW_WIDGET = false
// Pass your station ID here. See the constants above.
@simonbs
simonbs / childForStatusBarStyle.swift
Last active May 2, 2021
It seems that -childForStatusBarStyle: isn’t called on a UIViewController that is presented from a SwiftUI view using UIViewControllerRepresentable. Or am I doing something wrong? I came up with this *ugly* workaround that swizzles -childForStatusBarStyle: to return an associated object when present and uses the default implementation as fallback.
View childForStatusBarStyle.swift
// We'll store a UIViewController as an associated object and don't want to store a strong reference to it.
private final class WeakBoxedValue<T: AnyObject>: NSObject {
private(set) weak var value: T?
init(_ value: T?) {
self.value = value
}
}
// Use associated objects to a UIViewController that should determine the status bar appearance.
@simonbs
simonbs / UserDefault.swift
Last active Nov 24, 2021
Property wrapper that stores values in UserDefaults and works with SwiftUI and Combine.
View UserDefault.swift
/**
* I needed a property wrapper that fulfilled the following four requirements:
*
* 1. Values are stored in UserDefaults.
* 2. Properties using the property wrapper can be used with SwiftUI.
* 3. The property wrapper exposes a Publisher to be used with Combine.
* 4. The publisher is only called when the value is updated and not
* when_any_ value stored in UserDefaults is updated.
*
* First I tried using SwiftUI's builtin @AppStorage property wrapper
View Indie App Santa.js
// Variables used by Scriptable.
// These must be at the very top of the file. Do not edit.
// icon-color: red; icon-glyph: calendar-alt;
let data = await loadData()
let app = data.today[0]
let widget = null
if (config.runsInWidget) {
if (config.widgetFamily == "small") {
widget = await createSmallWidget(app)
} else {
@simonbs
simonbs / One More Thing.js
Last active Nov 4, 2020
Countdown to Apple's "One More Thing" event on November 10th, 2020
View One More Thing.js
// Variables used by Scriptable.
// These must be at the very top of the file. Do not edit.
// icon-color: deep-purple; icon-glyph: apple-alt;
const TITLE = "One More Thing"
const DATE = "2020-11-10T17:00:00Z"
const IMG_URL = "https://i.ibb.co/f2SN2Wb/bg.png"
let widget = await createWidget()
if (config.runsInWidget) {
Script.setWidget(widget)
@simonbs
simonbs / Animals of the Day.js
Created Nov 1, 2020
Shows an image of an animal
View Animals of the Day.js
// Variables used by Scriptable.
// These must be at the very top of the file. Do not edit.
// icon-color: purple; icon-glyph: paw;
let pandaURL = "https://c402277.ssl.cf1.rackcdn.com/photos/7749/images/story_full_width/HI_204718.jpg?1414503137"
let slothURL = "https://c402277.ssl.cf1.rackcdn.com/photos/6518/images/story_full_width/iStock_000011145477Large_mini_%281%29.jpg?1394632882"
let redPandaURL = "https://c402277.ssl.cf1.rackcdn.com/photos/8036/images/story_full_width/WEB_279173.jpg?1418412345"
let pandaImg = await getImage(pandaURL)
let slothImg = await getImage(slothURL)
let redPandaImg = await getImage(redPandaURL)
@simonbs
simonbs / Hi, Speed.js
Last active May 22, 2021
Greg Jowsiak's "Hi, Speed" widget recreated in Scriptable
View Hi, Speed.js
// This script recreates Greg Joswiak's widget that counts down to the "Hi, Speed" Apple Event on October 13th, 2020.
// You can see Greg's widget in this tweet:
// https://twitter.com/gregjoz/status/1313519797879988225
//
// You'll need this image for the background:
// https://i.imgur.com/t9Jr8kL.png
//
// I've stored the image at imgs/hispeed.png Scriptable's folder in iCloud Drive.
let widget = createWidget()