aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIván Ávalos <avalos@disroot.org>2022-02-06 03:48:54 -0600
committerIván Ávalos <avalos@disroot.org>2022-02-06 03:48:54 -0600
commita2387a76bb3b343862baa57e3fe28ed893f6cbda (patch)
treece4fc6c18491dd808274e5ec819b6030aeca570b
parent3913ab898f2c2ecc3b638eca4681957b1cf74330 (diff)
downloadetbsa-trackermap-mobile-a2387a76bb3b343862baa57e3fe28ed893f6cbda.tar.gz
etbsa-trackermap-mobile-a2387a76bb3b343862baa57e3fe28ed893f6cbda.tar.bz2
etbsa-trackermap-mobile-a2387a76bb3b343862baa57e3fe28ed893f6cbda.zip
Implemented details view with details tab
-rw-r--r--iosApp/iosApp.xcodeproj/project.pbxproj20
-rw-r--r--iosApp/iosApp/Details/Commands/UnitCommandsView.swift28
-rw-r--r--iosApp/iosApp/Details/DetailsView.swift82
-rw-r--r--iosApp/iosApp/Details/DetailsViewModel.swift31
-rw-r--r--iosApp/iosApp/Details/Information/UnitInformationView.swift104
-rw-r--r--iosApp/iosApp/Details/Reports/UnitReportsView.swift27
-rw-r--r--iosApp/iosApp/Devices/DevicesView.swift45
-rw-r--r--iosApp/iosApp/Localizable.strings13
8 files changed, 332 insertions, 18 deletions
diff --git a/iosApp/iosApp.xcodeproj/project.pbxproj b/iosApp/iosApp.xcodeproj/project.pbxproj
index 821ffb6..7faf845 100644
--- a/iosApp/iosApp.xcodeproj/project.pbxproj
+++ b/iosApp/iosApp.xcodeproj/project.pbxproj
@@ -28,6 +28,11 @@
E38F242027A27B550069FC45 /* LoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E38F241F27A27B550069FC45 /* LoadingView.swift */; };
E396281D27AF5723005D070E /* WhirlyGlobe.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = E396281B27AF56BA005D070E /* WhirlyGlobe.xcframework */; };
E396281E27AF5723005D070E /* WhirlyGlobe.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = E396281B27AF56BA005D070E /* WhirlyGlobe.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ E396282027AF59F2005D070E /* DetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E396281F27AF59F2005D070E /* DetailsView.swift */; };
+ E396282227AF66A3005D070E /* DetailsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E396282127AF66A3005D070E /* DetailsViewModel.swift */; };
+ E396282427AFBD3D005D070E /* UnitInformationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E396282327AFBD3D005D070E /* UnitInformationView.swift */; };
+ E396282627AFBD4E005D070E /* UnitReportsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E396282527AFBD4E005D070E /* UnitReportsView.swift */; };
+ E396282827AFBD72005D070E /* UnitCommandsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E396282727AFBD72005D070E /* UnitCommandsView.swift */; };
E39ABC4327A4E88C00965D05 /* UnitsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39ABC4227A4E88C00965D05 /* UnitsViewModel.swift */; };
E39ABC4627A4EBD500965D05 /* DevicesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39ABC4527A4EBD500965D05 /* DevicesView.swift */; };
E39ABC4827A4EDEC00965D05 /* DeviceRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39ABC4727A4EDEC00965D05 /* DeviceRow.swift */; };
@@ -70,6 +75,11 @@
E38F241D27A270D50069FC45 /* UnitsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnitsView.swift; sourceTree = "<group>"; };
E38F241F27A27B550069FC45 /* LoadingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingView.swift; sourceTree = "<group>"; };
E396281B27AF56BA005D070E /* WhirlyGlobe.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = WhirlyGlobe.xcframework; sourceTree = "<group>"; };
+ E396281F27AF59F2005D070E /* DetailsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailsView.swift; sourceTree = "<group>"; };
+ E396282127AF66A3005D070E /* DetailsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailsViewModel.swift; sourceTree = "<group>"; };
+ E396282327AFBD3D005D070E /* UnitInformationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnitInformationView.swift; sourceTree = "<group>"; };
+ E396282527AFBD4E005D070E /* UnitReportsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnitReportsView.swift; sourceTree = "<group>"; };
+ E396282727AFBD72005D070E /* UnitCommandsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnitCommandsView.swift; sourceTree = "<group>"; };
E39ABC4227A4E88C00965D05 /* UnitsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnitsViewModel.swift; sourceTree = "<group>"; };
E39ABC4527A4EBD500965D05 /* DevicesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DevicesView.swift; sourceTree = "<group>"; };
E39ABC4727A4EDEC00965D05 /* DeviceRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceRow.swift; sourceTree = "<group>"; };
@@ -157,6 +167,8 @@
E35A078727AB619700F24D71 /* Reports */,
E35A078627AB619000F24D71 /* Information */,
E35A078527AB618700F24D71 /* Commands */,
+ E396281F27AF59F2005D070E /* DetailsView.swift */,
+ E396282127AF66A3005D070E /* DetailsViewModel.swift */,
);
path = Details;
sourceTree = "<group>";
@@ -164,6 +176,7 @@
E35A078527AB618700F24D71 /* Commands */ = {
isa = PBXGroup;
children = (
+ E396282727AFBD72005D070E /* UnitCommandsView.swift */,
);
path = Commands;
sourceTree = "<group>";
@@ -171,6 +184,7 @@
E35A078627AB619000F24D71 /* Information */ = {
isa = PBXGroup;
children = (
+ E396282327AFBD3D005D070E /* UnitInformationView.swift */,
);
path = Information;
sourceTree = "<group>";
@@ -178,6 +192,7 @@
E35A078727AB619700F24D71 /* Reports */ = {
isa = PBXGroup;
children = (
+ E396282527AFBD4E005D070E /* UnitReportsView.swift */,
);
path = Reports;
sourceTree = "<group>";
@@ -326,12 +341,17 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ E396282627AFBD4E005D070E /* UnitReportsView.swift in Sources */,
E33A237127A7553500DD647F /* MapView.swift in Sources */,
+ E396282027AF59F2005D070E /* DetailsView.swift in Sources */,
E38F241727A242C70069FC45 /* Resolver.swift in Sources */,
E33A236027A4FD2C00DD647F /* UnitMapView.swift in Sources */,
+ E396282427AFBD3D005D070E /* UnitInformationView.swift in Sources */,
E33A236727A64E4500DD647F /* MarkerTransformations.swift in Sources */,
E38F241527A242870069FC45 /* Inject.swift in Sources */,
E39ABC4827A4EDEC00965D05 /* DeviceRow.swift in Sources */,
+ E396282227AF66A3005D070E /* DetailsViewModel.swift in Sources */,
+ E396282827AFBD72005D070E /* UnitCommandsView.swift in Sources */,
E38F241C27A26DD70069FC45 /* RootViewModel.swift in Sources */,
E36DF77B27AB740C003C561C /* MapViewController.swift in Sources */,
E33A237327A7581A00DD647F /* Utils.swift in Sources */,
diff --git a/iosApp/iosApp/Details/Commands/UnitCommandsView.swift b/iosApp/iosApp/Details/Commands/UnitCommandsView.swift
new file mode 100644
index 0000000..fade29b
--- /dev/null
+++ b/iosApp/iosApp/Details/Commands/UnitCommandsView.swift
@@ -0,0 +1,28 @@
+/**
+ * TrackerMap
+ * Copyright (C) 2021-2022 Iván Ávalos <avalos@disroot.org>, Henoch Ojeda <imhenoch@protonmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import SwiftUI
+import shared
+
+struct UnitCommandsView: View {
+ var unit: UnitInformation
+
+ var body: some View {
+
+ Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
+ }
+}
diff --git a/iosApp/iosApp/Details/DetailsView.swift b/iosApp/iosApp/Details/DetailsView.swift
new file mode 100644
index 0000000..8e2a6b5
--- /dev/null
+++ b/iosApp/iosApp/Details/DetailsView.swift
@@ -0,0 +1,82 @@
+/**
+ * TrackerMap
+ * Copyright (C) 2021-2022 Iván Ávalos <avalos@disroot.org>, Henoch Ojeda <imhenoch@protonmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import SwiftUI
+import shared
+
+struct DetailsView: View {
+ @ObservedObject var detailsViewModel = DetailsViewModel()
+
+ @Binding var isPresented: Bool
+ @State var action: DeviceRow.Action
+ var id: Int32
+
+ init(isPresented: Binding<Bool>, action: DeviceRow.Action, forId id: Int32) {
+ self._isPresented = isPresented
+ self.action = action
+ self.id = id
+ detailsViewModel.fetchUnit(id: id)
+ }
+
+ var body: some View {
+ NavigationView {
+ VStack {
+ if let unit = detailsViewModel.unit {
+ switch action {
+ case .details:
+ UnitInformationView(unit: unit)
+ case .reports:
+ UnitReportsView(unit: unit)
+ case .commands:
+ UnitCommandsView(unit: unit)
+ }
+ } else {
+ LoadingView()
+ }
+ }
+ .navigationBarTitleView(
+ Picker(selection: $action) {
+ Text("details").tag(DeviceRow.Action.details)
+ Text("reports").tag(DeviceRow.Action.reports)
+ Text("commands").tag(DeviceRow.Action.commands)
+ } label: {
+ EmptyView()
+ }.pickerStyle(SegmentedPickerStyle())
+ )
+ .navigationTitle(detailsViewModel.unit?.device.name ?? NSLocalizedString("loading", comment: ""))
+ .navigationBarTitleDisplayMode(.large)
+ .toolbar {
+ ToolbarItem(placement: .navigationBarLeading) {
+ if let category = detailsViewModel.unit?.device.category {
+ let type = Marker.companion
+ .categoryToMarkerType(category: category)
+ Image(MarkerTransformations.markerTypeToImageName(markerType: type))
+ } else {
+ EmptyView()
+ }
+ }
+ ToolbarItem(placement: .navigationBarTrailing) {
+ Button {
+ isPresented = false
+ } label: {
+ Text("done").bold()
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/iosApp/iosApp/Details/DetailsViewModel.swift b/iosApp/iosApp/Details/DetailsViewModel.swift
new file mode 100644
index 0000000..ce9165c
--- /dev/null
+++ b/iosApp/iosApp/Details/DetailsViewModel.swift
@@ -0,0 +1,31 @@
+/**
+ * TrackerMap
+ * Copyright (C) 2021-2022 Iván Ávalos <avalos@disroot.org>, Henoch Ojeda <imhenoch@protonmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import Foundation
+import shared
+
+class DetailsViewModel: ObservableObject {
+ @Inject var unitsController: UnitsController
+
+ @Published var unit: UnitInformation?
+
+ func fetchUnit(id: Int32) {
+ unitsController.getUnit(deviceId: id) { unit, _ in
+ self.unit = unit
+ }
+ }
+}
diff --git a/iosApp/iosApp/Details/Information/UnitInformationView.swift b/iosApp/iosApp/Details/Information/UnitInformationView.swift
new file mode 100644
index 0000000..3a52b84
--- /dev/null
+++ b/iosApp/iosApp/Details/Information/UnitInformationView.swift
@@ -0,0 +1,104 @@
+/**
+ * TrackerMap
+ * Copyright (C) 2021-2022 Iván Ávalos <avalos@disroot.org>, Henoch Ojeda <imhenoch@protonmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import SwiftUI
+import shared
+
+struct UnitInformationView: View {
+ var unit: UnitInformation
+
+ var body: some View {
+ List {
+ // MARK: - Contact
+ if let contact = unit.device.contact {
+ HStack {
+ Text("contact")
+ Spacer()
+ Text(contact).foregroundColor(.secondaryLabel)
+ }
+ }
+ // MARK: - Unique ID
+ if let uniqueId = unit.device.uniqueId {
+ HStack {
+ Text("unique-id")
+ Spacer()
+ Text(uniqueId).foregroundColor(.secondaryLabel)
+ }
+ }
+ // MARK: - Date time
+ if let datetime = unit.position?.fixTime {
+ HStack {
+ Text("datetime")
+ Spacer()
+ Text(Formatter.companion.formatDate(str: datetime))
+ .foregroundColor(.secondaryLabel)
+ }
+ }
+ // MARK: - Latitude
+ if let latitude = unit.position?.latitude {
+ HStack {
+ Text("latitude")
+ Spacer()
+ Text("\(latitude)").foregroundColor(.secondaryLabel)
+ }
+ }
+ // MARK: - Longitude
+ if let longitude = unit.position?.longitude {
+ HStack {
+ Text("longitude")
+ Spacer()
+ Text("\(longitude)").foregroundColor(.secondaryLabel)
+ }
+ }
+ // MARK: - Speed
+ if let speed = unit.position?.speed {
+ HStack {
+ Text("speed")
+ Spacer()
+ Text(Formatter.companion.formatSpeed(
+ speed: Double(truncating: speed), unit: .kmh))
+ .foregroundColor(.secondaryLabel)
+ }
+ }
+ // MARK: - Address
+ if let address = unit.position?.address {
+ HStack {
+ Text("address")
+ Spacer()
+ Text(address).foregroundColor(.secondaryLabel)
+ }
+ }
+ // MARK: - Hours
+ if let hours = unit.getHourmeter() {
+ HStack {
+ Text("hourmeter")
+ Spacer()
+ Text(Formatter.companion.formatHours(millis: Int64(truncating: hours)))
+ .foregroundColor(.secondaryLabel)
+ }
+ }
+ // MARK: - Protocol
+ if let protocol_ = unit.position?.protocol {
+ HStack {
+ Text("protocol")
+ Spacer()
+ Text(protocol_).foregroundColor(.secondaryLabel)
+ }
+ }
+ }
+ }
+}
diff --git a/iosApp/iosApp/Details/Reports/UnitReportsView.swift b/iosApp/iosApp/Details/Reports/UnitReportsView.swift
new file mode 100644
index 0000000..3e01e00
--- /dev/null
+++ b/iosApp/iosApp/Details/Reports/UnitReportsView.swift
@@ -0,0 +1,27 @@
+/**
+ * TrackerMap
+ * Copyright (C) 2021-2022 Iván Ávalos <avalos@disroot.org>, Henoch Ojeda <imhenoch@protonmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import SwiftUI
+import shared
+
+struct UnitReportsView: View {
+ var unit: UnitInformation
+
+ var body: some View {
+ Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
+ }
+}
diff --git a/iosApp/iosApp/Devices/DevicesView.swift b/iosApp/iosApp/Devices/DevicesView.swift
index e971ac6..d3a361e 100644
--- a/iosApp/iosApp/Devices/DevicesView.swift
+++ b/iosApp/iosApp/Devices/DevicesView.swift
@@ -19,26 +19,35 @@ import SwiftUI
struct DevicesView: View {
@StateObject var unitsViewModel: UnitsViewModel
+ @State var shouldShowView = false
+ @State var action: DeviceRow.Action = .details
+ @State var id: Int32?
var body: some View {
- List(unitsViewModel.units, id: \.device.id) { unit in
- DeviceRow(unit: unit, callback: { action in
- switch action {
- case .details:
- print ("Selected details of \(unit.device.name)")
- case .reports:
- print ("Selected reports of \(unit.device.name)")
- case .commands:
- print ("Selected commands of \(unit.device.name)")
- }
- })
- .onTapGesture {
- unitsViewModel.searchQuery = ""
- unitsViewModel.isEditing = false
- unitsViewModel.unitsDisplayMode = .map
- unitsViewModel.selectedUnit = unit
- UIApplication.shared.endEditing()
- }
+ VStack {
+ List(unitsViewModel.units, id: \.device.id) { unit in
+ DeviceRow(unit: unit, callback: { action in
+ self.action = action
+ id = unit.device.id
+ shouldShowView = true
+ })
+ .onTapGesture {
+ unitsViewModel.searchQuery = ""
+ unitsViewModel.isEditing = false
+ unitsViewModel.unitsDisplayMode = .map
+ unitsViewModel.selectedUnit = unit
+ UIApplication.shared.endEditing()
+ }
+ }
+ }
+ .sheet(isPresented: $shouldShowView) {
+ print("Dismissed")
+ } content: {
+ if let id = id {
+ DetailsView(isPresented: $shouldShowView,
+ action: action,
+ forId: id)
+ }
}
}
}
diff --git a/iosApp/iosApp/Localizable.strings b/iosApp/iosApp/Localizable.strings
index 049518f..9013574 100644
--- a/iosApp/iosApp/Localizable.strings
+++ b/iosApp/iosApp/Localizable.strings
@@ -18,6 +18,9 @@
"app-name" = "TrackerMap";
"app-server-url" = "https://etbsa.net/api";
+"loading" = "Loading";
+"done" = "Done";
+
"username" = "Username";
"password" = "Password";
"server-url" = "Server URL";
@@ -35,3 +38,13 @@
"map-layer" = "Map layer";
"openstreetmap" = "OpenStreetMap";
"satellite" = "Satellite";
+
+"contact" = "Contact";
+"unique-id" = "Unique ID";
+"datetime" = "Datetime";
+"latitude" = "Latitude";
+"longitude" = "Longitude";
+"speed" = "Speed";
+"address" = "Address";
+"hourmeter" = "Hourmeter";
+"protocol" = "Protocol";