diff --git a/README.md b/README.md index dc77777..2bb28d0 100644 --- a/README.md +++ b/README.md @@ -85,10 +85,10 @@ This widget displays the departure times of a selected station. The data for thi ### Setup -A Station-ID is required to set up the widget. To get the Station-ID, you can run the Script directly in the Scriptable App. -After you confirm the prompt with the "yes" button, a list of stations will be displayed. Click at the desired station on "Copy ID to clipboard". The Station-ID is copied to the clipboard. Alternativ, you can use the method descriped below to get the Station-ID. +A Station-ID is required to set up the widget. To get the Station-ID, you can run the Script directly in the Scriptable App to use the Setup Wizard. +The wizard searches for stations near to you (this requires your location). -Add the Station-ID and the needed Walking Minutes to the Station, separated by a ";", to the Widget Parameter like this: +Add the generated config to the Widget Parameter like this: ![VRR-Monitor Widget setup](https://raw.githubusercontent.com/ThisIsBenny/iOS-Widgets/main/VRR-Monitor/setup.jpeg) @@ -99,5 +99,4 @@ The Station-ID can be searched with this URL: Put the name of the station behind the "query=" in the URL and open the URL in your Browser. Example: `https://abfahrtsmonitor.vrr.de/backend/api/stations/search?query=Düsseldorf HBF` -### Roadmap -* Add Transport-Line filter option +Add the Station-ID and the needed Walking Minutes to the Station, separated by a ";", to the Widget Parameter. diff --git a/VRR-Monitor/VRR-Monitor.js b/VRR-Monitor/VRR-Monitor.js index 1e9a45c..41a9e89 100644 --- a/VRR-Monitor/VRR-Monitor.js +++ b/VRR-Monitor/VRR-Monitor.js @@ -1,7 +1,16 @@ // Variables used by Scriptable. // These must be at the very top of the file. Do not edit. // icon-color: deep-green; icon-glyph: bus-alt; -// Version 1.0.0 + +/************** +Version 1.1.0 + +Changelog: + v1.1.0: + - Line filter support added + - Setup Wizard enhanced + +**************/ let transportTypes = [ { @@ -42,6 +51,12 @@ let transportTypes = [ ] //////////////////////////////////////////////////////////////////////////////// +// Wizard +let wizardStationId, wizardLines +let linesTable = new UITable() +linesTable.showSeparators = true + +//Color let backColor; //Widget background color let backColor2; //Widget background color let textColor; //Widget text color @@ -76,6 +91,8 @@ async function fetchStationdata(Id, linesFilter, distance, transportCodes) { let res = await req.loadJSON() return {departureData: res['departureData'], stationName: res['stationName']} } catch (e) { + console.log(req.response) + console.log(e) throw e } }; @@ -87,7 +104,13 @@ async function findNextStations(latitude, longitude) { return res['suggestions'] }; -function populateTable(table, stations) { +async function getLines(stationId) { + let req = new Request(`https://haltestellenmonitor.vrr.de/backend/api/lines/${stationId}/search`) + + return await req.loadJSON() +}; + +function populateStationTable(table, stations) { table.removeAllRows() for (i = 0; i < stations.length; i++) { let station = stations[i] @@ -95,23 +118,37 @@ function populateTable(table, stations) { let nameCell = row.addText(station.value) nameCell.leftAligned() - nameCell.widthWeight = 70 - let buttonCell = row.addButton('Copy ID'); - buttonCell.rightAligned() - buttonCell.widthWeight = 20 - buttonCell.onTap = () => { - Pasteboard.copy(station.data); - - let alert = new Alert(); - alert.message = `The Station ID '${station.data}' was copied to the clipboard`; - alert.presentSheet() + row.onSelect = (number) => { + wizardStationId = stations[number].data } table.addRow(row) } } +function populateLinesTable() { + linesTable.removeAllRows() + + for (i = 0; i < wizardLines.length; i++) { + let row = new UITableRow() + row.dismissOnSelect = false + + let selectedCell = row.addText((wizardLines[i].selected)? "✓" : "") + selectedCell.widthWeight = 5 + + let textCell = row.addText(wizardLines[i].name) + textCell.widthWeight = 70 + + row.onSelect = (number) => { + wizardLines[number].selected = !wizardLines[number].selected + populateLinesTable() + linesTable.reload() + } + linesTable.addRow(row) + } +} + let widgetInputRAW = args.widgetParameter; let widgetInput = null; @@ -119,20 +156,58 @@ if (widgetInputRAW !== null) { widgetInput = widgetInputRAW.toString().split(";"); } else { if(!config.runsInWidget) { - let prompt = new Alert() - prompt.message = 'Do you like to find Station IDs from Stations next to you?' - let okAction = prompt.addAction('Yes') + let prompt1 = new Alert() + prompt1.message = 'Do you like to use the Setup Wizard to get the widget parameters?' + prompt1.addAction('Yes') + prompt1.addCancelAction('No') - let cancelAction = prompt.addCancelAction('No') - let decision = await prompt.presentAlert() - if (decision === 0) { + if ((await prompt1.presentAlert()) === 0) { let l = await Location.current() let stations = await findNextStations(l.latitude, l.longitude) let table = new UITable() table.showSeparators = true - populateTable(table, stations) + populateStationTable(table, stations) await QuickLook.present(table) + + let prompt2 = new Alert() + prompt2.message = 'How many minutes do you need to go to the station?' + prompt2.addTextField('Minutes') + prompt2.addAction('Weiter') + + await prompt2.presentAlert() + + let widgetParameter = `${wizardStationId};${prompt2.textFieldValue(0)}` + + let prompt3 = new Alert() + prompt3.message = 'Do you want to display only specific lines (including direction)?' + prompt3.addAction('Yes') + prompt3.addCancelAction('No, show all lines') + + if ((await prompt3.presentAlert()) === 0) { + wizardLines = await getLines(wizardStationId) + wizardLines = wizardLines.map((v) => { + v.selected = false + return v + }) + populateLinesTable() + await QuickLook.present(linesTable) + let linesConfig = wizardLines.filter(v => v.selected).map((v) => { + return { + data: `${v.network}:${v.line}:+:${v.directionCode}` + } + + }) + + widgetParameter = widgetParameter + ";" + JSON.stringify(linesConfig) + } + + Pasteboard.copy(widgetParameter); + let alert = new Alert(); + alert.message = `Config '${widgetParameter}' was copied to the clipboard. Please paste this config to the widget parameter.` + alert.addAction('Ok') + alert.present() } + return } throw new Error('No Station Code set!') } @@ -147,7 +222,7 @@ let selectedTransportTypesCodes = selectedTransportTypes.map(function(v){ return v.code }) -let { departureData: data, stationName } = await fetchStationdata(widgetInput[0], '', widgetInput[1], selectedTransportTypesCodes); +let { departureData: data, stationName } = await fetchStationdata(widgetInput[0], widgetInput[2] || '', widgetInput[1], selectedTransportTypesCodes); console.log(JSON.stringify(data, null, 2)) @@ -156,71 +231,65 @@ let widget = new ListWidget(); widget.setPadding(10, 10, 10, 10) -if (data) { - const gradient = new LinearGradient() - gradient.locations = [0, 1] - gradient.colors = [ - new Color(backColor), - new Color(backColor2) - ] - widget.backgroundGradient = gradient +const gradient = new LinearGradient() +gradient.locations = [0, 1] +gradient.colors = [ + new Color(backColor), + new Color(backColor2) +] +widget.backgroundGradient = gradient - let firstLineStack = widget.addStack() +let firstLineStack = widget.addStack() - let provider = firstLineStack.addText("🚏 " + stationName) - provider.font = Font.boldSystemFont(12) - provider.textColor = new Color(textColor) +let provider = firstLineStack.addText("🚏 " + stationName) +provider.font = Font.boldSystemFont(12) +provider.textColor = new Color(textColor) - // Last Update - firstLineStack.addSpacer() - let lastUpdateText = firstLineStack.addDate(new Date()) - lastUpdateText.font = Font.mediumSystemFont(10) - lastUpdateText.rightAlignText() - lastUpdateText.applyTimeStyle() - lastUpdateText.textColor = Color.lightGray() +// Last Update +firstLineStack.addSpacer() +let lastUpdateText = firstLineStack.addDate(new Date()) +lastUpdateText.font = Font.mediumSystemFont(10) +lastUpdateText.rightAlignText() +lastUpdateText.applyTimeStyle() +lastUpdateText.textColor = Color.lightGray() - widget.addSpacer(10) +widget.addSpacer(10) - let row = widget.addStack() - row.layoutHorizontally() - row.spacing = 15 +let row = widget.addStack() +row.layoutHorizontally() +row.spacing = 15 - let timeColumn = row.addStack() - timeColumn.layoutVertically(); +let timeColumn = row.addStack() +timeColumn.layoutVertically(); - let lineColumn = row.addStack() - lineColumn.layoutVertically() +let lineColumn = row.addStack() +lineColumn.layoutVertically() - let directionColumn = row.addStack() - directionColumn.layoutVertically() +let directionColumn = row.addStack() +directionColumn.layoutVertically() - data.forEach(function(l) { +data.forEach(function(l) { - let timeText = timeColumn.addText(`${l.hour}:${l.minute}`) - timeText.font = Font.mediumSystemFont(12) - timeText.textColor = new Color(textColor) - timeText.leftAlignText() + let timeText = timeColumn.addText(`${l.hour}:${l.minute}`) + timeText.font = Font.mediumSystemFont(12) + timeText.textColor = new Color(textColor) + timeText.leftAlignText() - let lineText = lineColumn.addText(l.name) - lineText.font = Font.mediumSystemFont(12) - lineText.textColor = new Color(textColor) - lineText.leftAlignText() + let lineText = lineColumn.addText(l.name) + lineText.font = Font.mediumSystemFont(12) + lineText.textColor = new Color(textColor) + lineText.leftAlignText() - let directionText = directionColumn.addText(l.direction) - directionText.font = Font.mediumSystemFont(12) - directionText.textColor = new Color(textColor) - directionText.leftAlignText() - directionText.lineLimit = 1 + let directionText = directionColumn.addText(l.direction) + directionText.font = Font.mediumSystemFont(12) + directionText.textColor = new Color(textColor) + directionText.leftAlignText() + directionText.lineLimit = 1 - }) +}) - widget.addSpacer() - -} else { - let fallbackText = widget.addText("Es ist ein Fehler aufgetreten! Bitte prüfen Sie die Logs direkt in der App.") - fallbackText.font = Font.mediumSystemFont(12) - fallbackText.textColor = new Color(textColor) -} +widget.addSpacer() + if(!config.runsInWidget) { await widget.presentMedium()