Skip to content

Instantly share code, notes, and snippets.

View simonbs's full-sized avatar
🐼

Simon B. Støvring simonbs

🐼
View GitHub Profile
@simonbs
simonbs / Indie App Santa.js
Last active December 2, 2020 20:46
Indie App Santa
// 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 / UserDefault.swift
Last active March 3, 2024 11:38
Property wrapper that stores values in UserDefaults and works with SwiftUI and Combine.
/**
* 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
@simonbs
simonbs / childForStatusBarStyle.swift
Last active September 25, 2023 14:49
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.
// 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 / Today's Pollen Count.js
Last active July 17, 2022 17:35
Shows the current pollen counts. Pulls data from a Danish provider and only works in Denmark.
// Variables used by Scriptable.
// These must be at the very top of the file. Do not edit.
// icon-color: deep-green; icon-glyph: tree;
const STATION_VIBORG = "49"
const STATION_CPH = "48"
const IDS = {
BIRCH: "7",
MUGWORT: "31",
ALDER: "1",
ELM: "4",
@simonbs
simonbs / Tour de France Profile.js
Created July 13, 2021 14:37
Scriptable script showing a profile of the current Tour de France stage
// 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 / ToolbarController.swift
Created July 23, 2021 06:22
Enable/disable a toolbar item in a Catalyst app.
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 / Unleashed.js
Created October 13, 2021 06:36
Scriptable widget that counts down to Apple's Unleashed event on October 18th
// 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 / KeyboardAvoidingView.swift
Created January 24, 2022 21:29
Avoid undocked keyboard at bottom.
// Sample code made in response to this tweet:
// https://twitter.com/stroughtonsmith/status/1485719749673820163
final class MainView: UIView {
private let textView: UITextView = {
let this = UITextView()
this.translatesAutoresizingMaskIntoConstraints = false
this.text = "I'm a text view"
this.font = .preferredFont(forTextStyle: .body)
this.textColor = .label
@simonbs
simonbs / GitHub Sponsors Widget.js
Created January 31, 2022 15:19
Shows the total number of GitHub sponsors and the latest sponsors in a widget using the Scriptable app
// Variables used by Scriptable.
// These must be at the very top of the file. Do not edit.
// icon-color: brown; icon-glyph: hand-holding-usd;
// To use this script, you must create a personal access token on GitHub with the `read:org// scope.
// Follow the instructions on the link below to create your personal access token.
//
// https://github.com/settings/tokens
//
// Run the script when you ahve created your personal access token. It'll prompt you to enter the token and store it securely in the keychain on the device.
@simonbs
simonbs / Example.swift
Created April 5, 2022 19:14
Present a portrait-only UIViewController wrapped in UIViewControllerRepresentable from a SwiftUI view.
/**
* This file shows how we can tie all of the above together.
*/
import SwiftUI
// This view can have any orientation-
struct SettingsView: View {
@State private var isPortraitOnlyViewPresented = false