Skip to content

Commit

Permalink
feat(watch): UI WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
krystxf committed Oct 20, 2024
1 parent 7bfb554 commit a4a627d
Show file tree
Hide file tree
Showing 8 changed files with 191 additions and 58 deletions.
51 changes: 12 additions & 39 deletions apps/mobile/metro-now-watch Watch App/ContentView.swift
Original file line number Diff line number Diff line change
@@ -1,51 +1,24 @@
//
// metro-now-watch
//
// Created by Kryštof Krátký on 19.05.2024.
//

import MapKit
import CoreLocation
import SwiftUI
import os

struct ContentView: View {
@StateObject private var locationModel = LocationModel()
@State var closestStation: MetroStationsGeoJSONFeature?
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
var stopManager = StopManager()

var body: some View {
NavigationView {
if let closestStation {
ScrollView { LazyVStack {
ForEach(closestStation.properties.platforms, id: \.self) { platform in

Label(
title: { Text(platform.direction) },
icon: { Image(systemName: getMetroLineIcon(platform.name)) }
)
}
}}

.navigationTitle(
closestStation.properties.name
)
}
}
StationDeparturesView(label: stopManager.closestStop?.name ?? "Loading...")

.onReceive(locationModel.$location) { location in
.task {
let stops = await getAllMetroStops()
print("Helloooooo")
stopManager.stops = stops
stopManager.closestStop = stops.first
// print(stops)

guard let location else {
print("Unknown location")
return
// print(locationModel.location)
}
print("User's location: \(location)")

let res = getClosestStationFromGeoJSON(location: location)

closestStation = res
}
.onAppear {
locationModel.checkLocationServicesEnabled()
}
.environmentObject(stopManager)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//
// MetroStopsManager.swift
// metro-now
//
// Created by Kryštof Krátký on 29.09.2024.
//

import SwiftUI

struct Stop: Codable {
var id: String
var name: String
var avgLatitude, avgLongitude: Double
var platforms: [Platform]
}

struct Platform: Codable {
var id: String
var name: String
var latitude, longitude: Double
var routes: [Route]
}

struct Route: Codable {
var id: String
var name: String
}

class StopManager: ObservableObject {
@Published var stops = [Stop]()
@Published var closestStop: Stop? = nil
}

func getAllMetroStops() async -> [Stop] {
let METRO_NOW_API = "http://localhost:3001"
print("Fetching data")
guard let url = URL(string: "http://localhost:3001/stop/all?metroOnly=true") else {
print("Invalid URL in getAllMetroStops")
return []
}
print("URL created")

do {
let (data, _) = try await URLSession.shared.data(from: url)
print("Fetched data")

let decodedResponse = try? JSONDecoder().decode([Stop].self, from: data)
guard let decodedResponse else {
print("Error parsing data")
return []
}

return decodedResponse
} catch {
print("Invalid data")
}

return []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import SwiftUI

struct DepartureDetailView: View {
let platformID: String

var body: some View {
VStack {
Label(
"Haje",
systemImage: "arrowshape.right.fill"
)
.font(.title2)
Text("1m 20s")
.font(.title2)
Text("Also to Kacerov in 1m 20s")
.font(.footnote)
}

.containerBackground(
.red.gradient,
for: .tabView
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import SwiftUI

struct DeparturesListView: View {
let platformID: String

var body: some View {
NavigationView {
List {
Text("A List Item")
Text("A Second List Item")
Text("A Third List Item")
Text("A List Item")
Text("A Second List Item")
Text("A Third List Item")
}
}

.containerBackground(
.red.gradient,
for: .tabView
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import SwiftUI

struct StationDepartureDetailView: View {
var body: some View {
TabView {
TabView {
DepartureDetailView(platformID: "unknown")
.tag(Optional(0))
DeparturesListView(platformID: "unknown")
.tag(Optional(1))
}
.tabViewStyle(.verticalPage(transitionStyle: .blur))

TabView {
DepartureDetailView(platformID: "unknown")
.tag(Optional(0))
DeparturesListView(platformID: "unknown")
.tag(Optional(1))
}
.tabViewStyle(.verticalPage(transitionStyle: .blur))
}
.tabViewStyle(.page)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import SwiftUI

struct StationDeparturesView: View {
var label: String

var body: some View {
NavigationStack {
ScrollView {
ForEach(0 ..< 2) { _ in
NavigationLink(value: 2) {
HStack {
VStack(alignment: .leading) {
Text("Háje")
Text("Also to Kačerov").font(.system(size: 12))
}
Spacer()
Text("20s")
}
}
.buttonStyle(.plain)
.frame(maxWidth: .infinity)
.padding(.vertical, 8)
.padding(.horizontal, 12)
.background(.red)
.clipShape(.rect(cornerRadius: 12))
}
}
.navigationTitle(label)
.navigationDestination(for: Int.self) { _ in
StationDepartureDetailView()
}
}
}
}
32 changes: 14 additions & 18 deletions apps/mobile/metro-now.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,6 @@
2DC63A082BF4C25B00A72C7F /* MapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DC63A072BF4C25B00A72C7F /* MapView.swift */; };
2DC63A242BF5266700A72C7F /* metroUtilsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DC63A232BF5266700A72C7F /* metroUtilsTests.swift */; };
2DC63A262BF5280F00A72C7F /* jsonUtilsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DC63A252BF5280F00A72C7F /* jsonUtilsTests.swift */; };
2DD3DEA92C07D319002233DE /* metro-stations.geojson in Resources */ = {isa = PBXBuildFile; fileRef = 2DD3DEA72C07D319002233DE /* metro-stations.geojson */; };
2DD3DEAA2C07D319002233DE /* metro-stations.geojson in Resources */ = {isa = PBXBuildFile; fileRef = 2DD3DEA72C07D319002233DE /* metro-stations.geojson */; };
2DD3DEAC2C07D319002233DE /* metro-routes.geojson in Resources */ = {isa = PBXBuildFile; fileRef = 2DD3DEA82C07D319002233DE /* metro-routes.geojson */; };
2DD3DEAD2C07D319002233DE /* metro-routes.geojson in Resources */ = {isa = PBXBuildFile; fileRef = 2DD3DEA82C07D319002233DE /* metro-routes.geojson */; };
2DD3DEB02C07EC22002233DE /* metro-stations.geojson in Resources */ = {isa = PBXBuildFile; fileRef = 2DD3DEA72C07D319002233DE /* metro-stations.geojson */; };
2DD3DEB32C07F737002233DE /* MediumWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DD3DEB22C07F737002233DE /* MediumWidgetView.swift */; };
2DD3DED22C080185002233DE /* SmallWidgetPlaceholderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DD3DED12C080185002233DE /* SmallWidgetPlaceholderView.swift */; };
2DD3DED42C080240002233DE /* MediumWidgetPlaceholderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DD3DED32C080240002233DE /* MediumWidgetPlaceholderView.swift */; };
Expand Down Expand Up @@ -136,8 +131,6 @@
2DC63A182BF50E8F00A72C7F /* metro-now-tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "metro-now-tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
2DC63A232BF5266700A72C7F /* metroUtilsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = metroUtilsTests.swift; sourceTree = "<group>"; };
2DC63A252BF5280F00A72C7F /* jsonUtilsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = jsonUtilsTests.swift; sourceTree = "<group>"; };
2DD3DEA72C07D319002233DE /* metro-stations.geojson */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "metro-stations.geojson"; path = "../../../data/metro-stations.geojson"; sourceTree = "<group>"; };
2DD3DEA82C07D319002233DE /* metro-routes.geojson */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "metro-routes.geojson"; path = "../../../data/metro-routes.geojson"; sourceTree = "<group>"; };
2DD3DEB22C07F737002233DE /* MediumWidgetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediumWidgetView.swift; sourceTree = "<group>"; };
2DD3DED12C080185002233DE /* SmallWidgetPlaceholderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SmallWidgetPlaceholderView.swift; sourceTree = "<group>"; };
2DD3DED32C080240002233DE /* MediumWidgetPlaceholderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediumWidgetPlaceholderView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -251,7 +244,9 @@
2D5BA5EA2C382FC30055F12A /* MapAnnotation */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (2D5BA5EB2C382FEA0055F12A /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = MapAnnotation; sourceTree = "<group>"; };
2D6C8CDD2C514882003E09A8 /* Countdown */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (2D6C8CE02C51488E003E09A8 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = Countdown; sourceTree = "<group>"; };
2D6C8CE12C5157FC003E09A8 /* StationDetailView */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (2D6C8CE22C515802003E09A8 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = StationDetailView; sourceTree = "<group>"; };
2D82A7902CA34D8E00AF13A8 /* pages */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = pages; sourceTree = "<group>"; };
2DD2EBBD2C5302B700E3ACF4 /* Vehicle */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (2DD2EBC42C5302D400E3ACF4 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, 2DD2EBC52C5302D400E3ACF4 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, 2DD2EBC62C5302D400E3ACF4 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = Vehicle; sourceTree = "<group>"; };
2DFBA9E82CA9CCFD00257C44 /* model */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = model; sourceTree = "<group>"; };
2DFD2F272C4DC296009C81CC /* API */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (2DFD2F2B2C4DC2EC009C81CC /* PBXFileSystemSynchronizedBuildFileExceptionSet */, 2DFD2F432C4DCC37009C81CC /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = API; sourceTree = "<group>"; };
/* End PBXFileSystemSynchronizedRootGroup section */

Expand Down Expand Up @@ -334,8 +329,6 @@
2D1B2C542BFAD93F007ED5EB /* Data */ = {
isa = PBXGroup;
children = (
2DD3DEA82C07D319002233DE /* metro-routes.geojson */,
2DD3DEA72C07D319002233DE /* metro-stations.geojson */,
2DF66D972BFD39B000B31FA2 /* test-coordinates.swift */,
);
path = Data;
Expand All @@ -354,6 +347,8 @@
2D4486842BFAA10A005C59CE /* metro-now-watch Watch App */ = {
isa = PBXGroup;
children = (
2DFBA9E82CA9CCFD00257C44 /* model */,
2D82A7902CA34D8E00AF13A8 /* pages */,
2D4486852BFAA10A005C59CE /* metro_now_watchApp.swift */,
2D4486872BFAA10A005C59CE /* ContentView.swift */,
2D4486892BFAA10B005C59CE /* Assets.xcassets */,
Expand Down Expand Up @@ -533,6 +528,10 @@
);
dependencies = (
);
fileSystemSynchronizedGroups = (
2D82A7902CA34D8E00AF13A8 /* pages */,
2DFBA9E82CA9CCFD00257C44 /* model */,
);
name = "metro-now-watch Watch App";
productName = "metro-now-watch Watch App";
productReference = 2D4486832BFAA10A005C59CE /* metro-now-watch Watch App.app */;
Expand Down Expand Up @@ -646,8 +645,6 @@
buildActionMask = 2147483647;
files = (
2D44868D2BFAA10B005C59CE /* Preview Assets.xcassets in Resources */,
2DD3DEAD2C07D319002233DE /* metro-routes.geojson in Resources */,
2DD3DEAA2C07D319002233DE /* metro-stations.geojson in Resources */,
2D44868A2BFAA10B005C59CE /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand All @@ -657,8 +654,6 @@
buildActionMask = 2147483647;
files = (
2DC639E32BF3CCBC00A72C7F /* Preview Assets.xcassets in Resources */,
2DD3DEAC2C07D319002233DE /* metro-routes.geojson in Resources */,
2DD3DEA92C07D319002233DE /* metro-stations.geojson in Resources */,
2DC639E02BF3CCBC00A72C7F /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand All @@ -674,7 +669,6 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
2DD3DEB02C07EC22002233DE /* metro-stations.geojson in Resources */,
2DF48A502C01F186002F754E /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -783,6 +777,7 @@
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_CFBundleDisplayName = "metro-now-watch";
INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "Find the nearest metro station";
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
INFOPLIST_KEY_WKCompanionAppBundleIdentifier = "com.krystof.metro-now";
LD_RUNPATH_SEARCH_PATHS = (
Expand Down Expand Up @@ -813,6 +808,7 @@
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_CFBundleDisplayName = "metro-now-watch";
INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "Find the nearest metro station";
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
INFOPLIST_KEY_WKCompanionAppBundleIdentifier = "com.krystof.metro-now";
LD_RUNPATH_SEARCH_PATHS = (
Expand Down Expand Up @@ -1078,12 +1074,12 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.krystof.metro-now.metro-now-widgets";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator watchos watchsimulator";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2,4";
TARGETED_DEVICE_FAMILY = "1,2";
WATCHOS_DEPLOYMENT_TARGET = 10.0;
};
name = Debug;
Expand All @@ -1110,12 +1106,12 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.krystof.metro-now.metro-now-widgets";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator watchos watchsimulator";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2,4";
TARGETED_DEVICE_FAMILY = "1,2";
WATCHOS_DEPLOYMENT_TARGET = 10.0;
};
name = Release;
Expand Down
2 changes: 1 addition & 1 deletion apps/mobile/metro-now/Core/Map/MapView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ struct MapView: View {
element.longitude > region.center.longitude - region.span.longitudeDelta,
element.longitude < region.center.longitude + region.span.longitudeDelta,
!METRO_LINES.contains(element.routes.first?.name ?? ""),
i < 100
i < 500
{
i += 1
return element
Expand Down

0 comments on commit a4a627d

Please sign in to comment.