Last active
March 28, 2021 16:56
-
-
Save timokoola/a44268ee25bc7b22cc9e7c850d17b72c to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| // Variables used by Scriptable. | |
| // These must be at the very top of the file. Do not edit. | |
| // icon-color: cyan; icon-glyph: bus; | |
| let [argsStop, topColorStr, bottomColorStr, textColorStr] = cleanParameters( | |
| args?.widgetParameter | |
| ); | |
| let topColor = new Color(topColorStr); | |
| let bottomColor = new Color(bottomColorStr); | |
| let textColor = new Color(textColorStr); | |
| let busStopQuery = JSON.stringify({ | |
| query: `{ stop(id: "${argsStop}") { gtfsId name url code stoptimesWithoutPatterns(numberOfDepartures: 15) { scheduledDeparture realtimeDeparture departureDelay realtime realtimeState serviceDay headsign trip { routeShortName tripHeadsign directionId route { type } } } } }`, | |
| }); | |
| let items = await getDigiTransit(busStopQuery); | |
| // Base parts are from the Scriptable example "random Scriptable API" | |
| let widget = await createWidget(items); | |
| if (config.runsInWidget) { | |
| // The script runs inside a widget, so we pass our instance of ListWidget to be shown inside the widget on the Home Screen. | |
| Script.setWidget(widget); | |
| } else { | |
| // The script runs inside the app, so we preview the widget. | |
| widget.presentMedium(); | |
| } | |
| // Calling Script.complete() signals to Scriptable that the script have finished running. | |
| // This can speed up the execution, in particular when running the script from Shortcuts or using Siri. | |
| Script.complete(); | |
| function cleanParameters(params) { | |
| let split_ = params?.split(";") ?? ""; | |
| let defaultStop = (split_?.[0] ?? "") !== "" ? split_?.[0] : "HSL:1020131"; | |
| let defaultTop = (split_?.[1] ?? "") !== "" ? split_?.[1] : "#489FB5"; | |
| let defaultBottom = (split_?.[2] ?? "") !== "" ? split_?.[2] : "#16697A"; | |
| let defaultText = (split_?.[3] ?? "") !== "" ? split_?.[3] : "#FFFFFF"; | |
| if (!defaultStop.startsWith("HSL:")) { | |
| defaultStop = "HSL:1020131"; | |
| } | |
| return [defaultStop, defaultTop, defaultBottom, defaultText]; | |
| } | |
| async function getDigiTransit(query) { | |
| let url = "https://api.digitransit.fi/routing/v1/routers/hsl/index/graphql"; | |
| let r = new Request(url); | |
| r.method = "POST"; | |
| r.headers = { "Content-Type": "application/json" }; | |
| r.body = query; | |
| return await r.loadJSON(); | |
| } | |
| // modeled after the example | |
| async function createWidget(stops) { | |
| let currentStop = stops.data.stop; | |
| // API seems to return a bad url for stop time tables | |
| let linkUrl = `https://reittiopas.hsl.fi/pysakit/${currentStop.gtfsId}`; | |
| let title = `${currentStop.code} ${currentStop.name}`; | |
| let widget = new ListWidget(); | |
| // Add background gradient | |
| let gradient = new LinearGradient(); | |
| gradient.locations = [0, 1]; | |
| gradient.colors = [topColor, bottomColor]; | |
| widget.backgroundGradient = gradient; | |
| // Show title | |
| let titleStack = widget.addStack(); | |
| let titleElement = titleStack.addText(title); | |
| titleElement.textColor = textColor; | |
| titleElement.font = Font.title3(); | |
| widget.addSpacer(6); | |
| let df = new DateFormatter(); | |
| df.useNoDateStyle(); | |
| df.useShortTimeStyle(); | |
| let rows = config.widgetFamily === "large" ? 15 : 4; | |
| for ( | |
| let i = 0; | |
| i < currentStop.stoptimesWithoutPatterns.length && i < rows; | |
| i++ | |
| ) { | |
| let item = currentStop.stoptimesWithoutPatterns[i]; | |
| let itemDate = new Date( | |
| item.serviceDay * 1000 + item.realtimeDeparture * 1000 | |
| ); | |
| let departureStack = widget.addStack(); | |
| departureStack.url = linkUrl; | |
| let shortName = `${item.trip.routeShortName}`; | |
| let routeElement = departureStack.addText(shortName.padEnd(6, " ")); | |
| routeElement.font = new Font("Menlo", 13); | |
| routeElement.textColor = textColor; | |
| let spacer = 2; | |
| if (config.widgetFamily !== "small") { | |
| departureStack.addSpacer(spacer); | |
| let headSignElement = departureStack.addText(`${item.trip.tripHeadsign}`); | |
| headSignElement.font = Font.systemFont(13); | |
| headSignElement.textColor = textColor; | |
| } else { | |
| departureStack.addSpacer(spacer); | |
| let headSignElement = departureStack.addText( | |
| `${item.trip.tripHeadsign.substring(0, 5)}` | |
| ); | |
| headSignElement.font = Font.systemFont(13); | |
| headSignElement.textColor = textColor; | |
| } | |
| departureStack.addSpacer(); | |
| let timeElement = departureStack.addText(`${df.string(itemDate)}`); | |
| timeElement.font = new Font("Menlo", 13); | |
| timeElement.textColor = textColor; | |
| } | |
| widget.addSpacer(20); | |
| // UI presented in Siri and Shortcuts is non-interactive, so we only show the footer when not running the script from Siri. | |
| if (!config.runsWithSiri) { | |
| widget.addSpacer(8); | |
| // Add button to open documentation | |
| let linkSymbol = SFSymbol.named("arrow.up.forward"); | |
| let footerStack = widget.addStack(); | |
| let linkStack = footerStack.addStack(); | |
| linkStack.centerAlignContent(); | |
| linkStack.url = linkUrl; | |
| let linkElement = linkStack.addText("See all departures"); | |
| linkElement.font = Font.systemFont(13); | |
| linkElement.textColor = textColor; | |
| linkStack.addSpacer(3); | |
| let linkSymbolElement = linkStack.addImage(linkSymbol.image); | |
| linkSymbolElement.imageSize = new Size(11, 11); | |
| linkSymbolElement.tintColor = textColor; | |
| linkSymbolElement.imageOpacity = 0.6; | |
| footerStack.addSpacer(); | |
| // Add link to Find bikes now | |
| let docsSymbol = SFSymbol.named("bus"); | |
| let docsElement = footerStack.addImage(docsSymbol.image); | |
| docsElement.imageSize = new Size(20, 20); | |
| docsElement.tintColor = textColor; | |
| docsElement.imageOpacity = 0.8; | |
| docsElement.url = linkUrl; | |
| } | |
| return widget; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment