Skip to content

Commit

Permalink
feat(ios): platforms list
Browse files Browse the repository at this point in the history
  • Loading branch information
krystxf committed Nov 5, 2024
1 parent efd15d3 commit 0dd31e7
Show file tree
Hide file tree
Showing 8 changed files with 324 additions and 52 deletions.
56 changes: 56 additions & 0 deletions apps/mobile/metro-now/common/components/route-name.view.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// metro-now
// https://github.com/krystxf/metro-now

import SwiftUI

struct RouteNameIconView: View {
let label: String
let background: Color

var body: some View {
Text(label.uppercased())
.font(.system(size: 12, weight: .bold))
.foregroundStyle(.white)
.fixedSize(horizontal: true, vertical: true)
.frame(width: 26, height: 26)
.background(Rectangle().fill(background))
.clipShape(.rect(cornerRadius: 6))
}
}

#Preview {
RouteNameIconView(
label: "a",
background: .green
)

RouteNameIconView(
label: "b",
background: .yellow
)

RouteNameIconView(
label: "c",
background: .red
)

RouteNameIconView(
label: "28",
background: .purple
)

RouteNameIconView(
label: "99",
background: .black
)

RouteNameIconView(
label: "149",
background: .blue
)

RouteNameIconView(
label: "912",
background: .black
)
}
4 changes: 4 additions & 0 deletions apps/mobile/metro-now/common/utils/metro-line.utils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,7 @@ func getMetroLineColor(_ line: MetroLine?) -> Color? {
default: nil
}
}

func getMetroLineColor(_ line: String) -> Color? {
getMetroLineColor(MetroLine(rawValue: line.uppercased()))
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ struct StopDepartureListItemView: View {
let nextHeadsign: String?
let nextDeparture: Date?

let dateFormat = DateFormatter()

init(
color: Color?,
headsign: String,
Expand Down
38 changes: 14 additions & 24 deletions apps/mobile/metro-now/metro-now.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -40,24 +40,11 @@
/* End PBXFileReference section */

/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
2D9601C72CC812D6000EF3D5 /* Exceptions for "common" folder in "metro-now" target */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
components/countdown.view.swift,
"const/api-const.swift",
"managers/location-manager.swift",
"managers/network-manager.swift",
"types/api-types.swift",
"types/metro-line.swift",
"utils/metro-line.utils.swift",
utils/station.utils.swift,
);
target = 2D001BA72CC8099B00C6B4F8 /* metro-now */;
};
2D9601C92CC812EF000EF3D5 /* Exceptions for "common" folder in "metro-now Watch App" target */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
components/countdown.view.swift,
"components/route-name.view.swift",
"const/api-const.swift",
"managers/location-manager.swift",
"managers/network-manager.swift",
Expand All @@ -84,7 +71,6 @@
2D9601C12CC8126F000EF3D5 /* common */ = {
isa = PBXFileSystemSynchronizedRootGroup;
exceptions = (
2D9601C72CC812D6000EF3D5 /* Exceptions for "common" folder in "metro-now" target */,
2D9601C92CC812EF000EF3D5 /* Exceptions for "common" folder in "metro-now Watch App" target */,
);
path = common;
Expand Down Expand Up @@ -187,7 +173,7 @@
attributes = {
BuildIndependentTargetsInParallel = 1;
LastSwiftUpdateCheck = 1600;
LastUpgradeCheck = 1600;
LastUpgradeCheck = 1610;
TargetAttributes = {
2D001BA72CC8099B00C6B4F8 = {
CreatedOnToolsVersion = 16.0;
Expand Down Expand Up @@ -294,6 +280,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
Expand Down Expand Up @@ -355,6 +342,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
Expand All @@ -380,7 +368,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
CURRENT_PROJECT_VERSION = 30;
DEVELOPMENT_ASSET_PATHS = "\"metro-now Watch App/Preview Content\"";
DEVELOPMENT_TEAM = R6WU5ABNG2;
ENABLE_PREVIEWS = YES;
Expand All @@ -389,6 +377,7 @@
INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "";
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
INFOPLIST_KEY_WKCompanionAppBundleIdentifier = "com.krystof.metro-now";
INFOPLIST_KEY_WKRunsIndependentlyOfCompanionApp = YES;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand All @@ -411,7 +400,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
CURRENT_PROJECT_VERSION = 30;
DEVELOPMENT_ASSET_PATHS = "\"metro-now Watch App/Preview Content\"";
DEVELOPMENT_TEAM = R6WU5ABNG2;
ENABLE_PREVIEWS = YES;
Expand All @@ -420,6 +409,7 @@
INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "";
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
INFOPLIST_KEY_WKCompanionAppBundleIdentifier = "com.krystof.metro-now";
INFOPLIST_KEY_WKRunsIndependentlyOfCompanionApp = YES;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand All @@ -443,7 +433,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
CURRENT_PROJECT_VERSION = 30;
DEVELOPMENT_ASSET_PATHS = "\"metro-now/Preview Content\"";
DEVELOPMENT_TEAM = R6WU5ABNG2;
ENABLE_PREVIEWS = YES;
Expand All @@ -456,12 +446,12 @@
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
IPHONEOS_DEPLOYMENT_TARGET = 18;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
MARKETING_VERSION = 0.2;
PRODUCT_BUNDLE_IDENTIFIER = "com.krystof.metro-now";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
Expand All @@ -477,7 +467,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
CURRENT_PROJECT_VERSION = 30;
DEVELOPMENT_ASSET_PATHS = "\"metro-now/Preview Content\"";
DEVELOPMENT_TEAM = R6WU5ABNG2;
ENABLE_PREVIEWS = YES;
Expand All @@ -490,12 +480,12 @@
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
IPHONEOS_DEPLOYMENT_TARGET = 18;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
MARKETING_VERSION = 0.2;
PRODUCT_BUNDLE_IDENTIFIER = "com.krystof.metro-now";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
Expand Down
105 changes: 79 additions & 26 deletions apps/mobile/metro-now/metro-now/ContentView.swift
Original file line number Diff line number Diff line change
@@ -1,46 +1,99 @@
// metro-now
// https://github.com/krystxf/metro-now

import CoreLocation
import SwiftUI

import CoreLocation
import Foundation
struct ContentView: View {
@StateObject private var locationManager = LocationManager()
@State var stops: [ApiStop]? = nil
@State var departures: [ApiDeparture]? = nil
private let timer = Timer.publish(every: 2, on: .main, in: .common).autoconnect()

class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate {
private let locationManager = CLLocationManager()
var body: some View {
NavigationStack {
if let location = locationManager.location,
let stops,
let closestStop = findClosestStop(to: location, stops: stops)
{
ClosestStopPageView(
closestStop: closestStop,
departures: departures
)
.navigationTitle(closestStop.name)
} else {
ProgressView()
}
}
.onAppear {
getAllMetroStops()
}
.onReceive(timer) { _ in
getStopDepartures()
}
}

func findClosestStop(to location: CLLocation, stops: [ApiStop]) -> ApiStop? {
var closestStop: ApiStop?
var closestDistance: CLLocationDistance?

@Published var location: CLLocation?
for stop in stops {
let stopLocation = CLLocation(latitude: stop.avgLatitude, longitude: stop.avgLongitude)

let distance = location.distance(from: stopLocation)

guard closestDistance != nil else {
closestStop = stop
closestDistance = distance
continue
}

override init() {
super.init()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
if distance < closestDistance! {
closestStop = stop
closestDistance = distance
}
}

return closestStop
}

func locationManager(_: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.first {
func getAllMetroStops() {
NetworkManager.shared.getMetroStops { result in
DispatchQueue.main.async {
self.location = location
switch result {
case let .success(stops):

self.stops = stops

case let .failure(error):
print(error.localizedDescription)
}
}
}
}
}

struct ContentView: View {
@StateObject private var locationManager = LocationManager()
func getStopDepartures() {
guard
let location = locationManager.location,
let stops,
let closestStop = findClosestStop(to: location, stops: stops)
else {
return
}

var body: some View {
VStack {
if let location = locationManager.location {
Text("Latitude: \(location.coordinate.latitude)")
Text("Longitude: \(location.coordinate.longitude)")
} else {
Text("Fetching location...")
NetworkManager.shared
.getDepartures(stopIds: [closestStop.id], platformIds: []) { result in
DispatchQueue.main.async {
switch result {
case let .success(departures):

self.departures = departures

case let .failure(error):
print(error.localizedDescription)
}
}
}
}
.padding()
}
}

Expand Down
Loading

0 comments on commit 0dd31e7

Please sign in to comment.