Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LekaApp - implement connecitonbutton behavior #446

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,30 @@
// SPDX-License-Identifier: Apache-2.0

import DesignKit
import RobotKit
import SwiftUI

struct RobotConnectionIndicator: View {

@EnvironmentObject var robotVM: RobotViewModel
@EnvironmentObject var metrics: UIMetrics
// Animation

@StateObject var robotViewModel: ConnectedRobotInformationViewModel = ConnectedRobotInformationViewModel()

@State private var isAnimated: Bool = false
@State private var diameter: CGFloat = 0

var body: some View {
ZStack {
Circle()
.fill(
robotVM.robotIsConnected
robotViewModel.isConnected
? DesignKitAsset.Colors.lekaGreen.swiftUIColor : DesignKitAsset.Colors.lekaDarkGray.swiftUIColor
)
.opacity(0.4)

Image(
uiImage:
robotVM.robotIsConnected
robotViewModel.isConnected
? DesignKitAsset.Images.robotConnected.image : DesignKitAsset.Images.robotDisconnected.image
)
.resizable()
Expand All @@ -34,7 +36,7 @@ struct RobotConnectionIndicator: View {

Circle()
.stroke(
robotVM.robotIsConnected
robotViewModel.isConnected
? DesignKitAsset.Colors.lekaGreen.swiftUIColor
: DesignKitAsset.Colors.lekaDarkGray.swiftUIColor,
lineWidth: 4
Expand All @@ -50,7 +52,7 @@ struct RobotConnectionIndicator: View {
.animation(
Animation.easeInOut(duration: 1.5).delay(5).repeatForever(autoreverses: false), value: diameter
)
.opacity(robotVM.robotIsConnected ? 1 : 0.0)
.opacity(robotViewModel.isConnected ? 1 : 0.0)
)
.overlay(
alignment: .topTrailing,
Expand All @@ -65,7 +67,7 @@ struct RobotConnectionIndicator: View {
}

@ViewBuilder private var badgeView: some View {
if !robotVM.robotIsConnected {
if !robotViewModel.isConnected {
Image(systemName: "exclamationmark.circle.fill")
.symbolRenderingMode(.palette)
.foregroundStyle(.white, .red)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@
// SPDX-License-Identifier: Apache-2.0

import DesignKit
import RobotKit
import SwiftUI

struct GoToRobotConnectButton: View {

@EnvironmentObject var robotVM: RobotViewModel
@EnvironmentObject var metrics: UIMetrics
@EnvironmentObject var navigationVM: NavigationViewModel

@StateObject var robotViewModel: ConnectedRobotInformationViewModel = ConnectedRobotInformationViewModel()

var body: some View {
Button {
navigationVM.showRobotPicker.toggle()
Expand All @@ -31,26 +33,49 @@ struct GoToRobotConnectButton: View {

@ViewBuilder
private var buttonContent: some View {
if robotVM.robotIsConnected {
if robotViewModel.isConnected {
VStack(alignment: .leading, spacing: 4) {
Text("Connecté à")
Text(robotVM.currentlyConnectedRobotName)
Text(robotViewModel.name)
.font(metrics.reg16)
HStack(spacing: 4) {
RobotBatteryIndicator(
level: $robotVM.robotChargeLevel,
charging: $robotVM.robotIsCharging)
Text(robotVM.robotOSVersion)
.foregroundColor(DesignKitAsset.Colors.lekaDarkGray.swiftUIColor)
}
robotCharginStatusAndBattery
}
.font(metrics.reg12)
.foregroundColor(DesignKitAsset.Colors.lekaDarkBlue.swiftUIColor)
} else {
Text("Connectez vous à votre LEKA.")
Text("Connectez-vous à votre Leka")
.font(metrics.reg16)
.multilineTextAlignment(.leading)
.foregroundColor(DesignKitAsset.Colors.lekaDarkBlue.swiftUIColor)
}
}

private var robotCharginStatusAndBattery: some View {
HStack(spacing: 5) {
Text(verbatim: "LekaOS v\(robotViewModel.osVersion)")
.foregroundColor(.gray)

if robotViewModel.isCharging {
Image(systemName: "bolt.circle.fill")
.foregroundColor(.blue)
} else {
Image(systemName: "bolt.slash.circle")
.foregroundColor(.gray.opacity(0.6))
}

let battery = BatteryViewModel(level: robotViewModel.battery)
Image(systemName: battery.name)
.foregroundColor(battery.color)
Text(verbatim: "\(battery.level)%")
.foregroundColor(.gray)
.monospacedDigit()
}
}

}

#Preview {
GoToRobotConnectButton()
.environmentObject(UIMetrics())
.environmentObject(NavigationViewModel())
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// SPDX-License-Identifier: Apache-2.0

import Combine
import RobotKit
import SwiftUI

struct ConnectedRobotInformationView: View {
Expand Down
41 changes: 41 additions & 0 deletions Modules/RobotKit/Sources/UI/ViewModels/BatteryViewModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Leka - iOS Monorepo
// Copyright 2023 APF France handicap
// SPDX-License-Identifier: Apache-2.0

import BLEKit
import SwiftUI

public struct BatteryViewModel: Equatable {

public let level: Int
public let name: String
public let color: Color

public init(level: Int) {
self.level = level
switch level {
case 0..<10:
self.name = "battery.0"
self.color = .red
case 10..<25:
self.name = "battery.25"
self.color = .red
case 25..<45:
self.name = "battery.25"
self.color = .orange
case 45..<70:
self.name = "battery.50"
self.color = .yellow
case 70..<95:
self.name = "battery.75"
self.color = .green
case 95...100:
self.name = "battery.100"
self.color = .green
default:
self.name = "battery.0"
self.color = .gray
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,39 @@
// SPDX-License-Identifier: Apache-2.0

import Combine
import RobotKit
import SwiftUI

class ConnectedRobotInformationViewModel: ObservableObject {
public class ConnectedRobotInformationViewModel: ObservableObject {

@Published var name: String = "(n/a)"
@Published var serialNumber: String = "(n/a)"
@Published var osVersion: String = "(n/a)"
@Published public var isConnected: Bool = false {
didSet {
self.isNotConnected = !isConnected
}
}

@Published public var isNotConnected: Bool = true

@Published public var name: String = "(n/a)"
@Published public var serialNumber: String = "(n/a)"
@Published public var osVersion: String = "(n/a)"

@Published var battery: Int = 0
@Published var isCharging: Bool = false
@Published public var battery: Int = 0
@Published public var isCharging: Bool = false

let robot = Robot.shared

private var cancellables: Set<AnyCancellable> = []

init() {
public init() {
getRobotInformation()
}

private func getRobotInformation() {
robot.isConnected
.receive(on: DispatchQueue.main)
.sink { isConnected in
guard !isConnected else { return }
self.isConnected = isConnected
guard self.isNotConnected else { return }
self.name = "(not connected)"
self.serialNumber = ""
self.osVersion = ""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,6 @@ import SwiftUI

public struct RobotDiscoveryViewModel: Identifiable {

public struct Battery: Equatable {
let value: Int
let name: String
let color: Color
}

public enum Status: CaseIterable {
case connected
case unselected
Expand All @@ -24,7 +18,7 @@ public struct RobotDiscoveryViewModel: Identifiable {
public let status: Status
public let isCharging: Bool
public let osVersion: String
public let battery: Battery
public let battery: BatteryViewModel

init(
name: String, battery: Int, isCharging: Bool, osVersion: String, status: Status = .unselected
Expand All @@ -34,7 +28,7 @@ public struct RobotDiscoveryViewModel: Identifiable {
self.status = status
self.isCharging = isCharging
self.osVersion = "LekaOS \(osVersion)"
self.battery = computeBatteryImage(for: battery)
self.battery = BatteryViewModel(level: battery)
}

init(discovery: RobotDiscoveryModel, status: Status = .unselected) {
Expand All @@ -43,7 +37,7 @@ public struct RobotDiscoveryViewModel: Identifiable {
self.status = status
self.isCharging = discovery.isCharging
self.osVersion = "LekaOS \(discovery.osVersion)"
self.battery = computeBatteryImage(for: discovery.battery)
self.battery = BatteryViewModel(level: discovery.battery)
}

}
Expand All @@ -57,20 +51,3 @@ extension RobotDiscoveryViewModel: Equatable {
}

}

private func computeBatteryImage(for value: Int) -> RobotDiscoveryViewModel.Battery {
switch value {
case 0..<10:
RobotDiscoveryViewModel.Battery(value: value, name: "battery.0", color: .red)
case 10..<25:
RobotDiscoveryViewModel.Battery(value: value, name: "battery.25", color: .red)
case 25..<45:
RobotDiscoveryViewModel.Battery(value: value, name: "battery.25", color: .orange)
case 45..<70:
RobotDiscoveryViewModel.Battery(value: value, name: "battery.50", color: .yellow)
case 70..<95:
RobotDiscoveryViewModel.Battery(value: value, name: "battery.75", color: .green)
default:
RobotDiscoveryViewModel.Battery(value: value, name: "battery.100", color: .green)
}
}
2 changes: 1 addition & 1 deletion Modules/RobotKit/Sources/UI/Views/RobotDiscoveryView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ struct RobotDiscoveryView: View {
HStack(spacing: 5) {
Image(systemName: discovery.battery.name)
.foregroundColor(discovery.battery.color)
Text("\(discovery.battery.value)%")
Text("\(discovery.battery.level)%")
.foregroundColor(.gray)
}
}
Expand Down