1 contributor
178 lines | 6.373kb
//
//  ControlView.swift
//  USB Meter
//
//  Created by Bogdan Timofte on 09/03/2020.
//  Copyright © 2020 Bogdan Timofte. All rights reserved.
//

import SwiftUI

struct ControlView: View {
    
    @EnvironmentObject private var meter: Meter
    var compactLayout: Bool = false
    var availableSize: CGSize? = nil
    var showsHeader: Bool = true

    var body: some View {
        VStack(alignment: .leading, spacing: 14) {
            if showsHeader {
                HStack {
                    Text("Controls")
                        .font(.headline)
                    Spacer()
                    Text(meter.reportsCurrentScreenIndex ? "Device Screen" : "Page Controls")
                        .font(.caption.weight(.semibold))
                        .foregroundColor(.secondary)
                }
            }

            if compactLayout {
                if usesExpandedCompactLayout {
                    Spacer(minLength: 0)

                    VStack(spacing: 12) {
                        HStack(spacing: 12) {
                            controlButton(
                                title: "Prev",
                                symbol: "chevron.left",
                                tint: .indigo,
                                action: { meter.previousScreen() }
                            )

                            currentScreenCard
                                .frame(maxWidth: .infinity, minHeight: 112)
                                .padding(.horizontal, 14)
                                .meterCard(tint: meter.color, fillOpacity: 0.06, strokeOpacity: 0.10)
                        }

                        HStack(spacing: 12) {
                            controlButton(
                                title: "Rotate",
                                symbol: "rotate.right.fill",
                                tint: .orange,
                                action: { meter.rotateScreen() }
                            )

                            controlButton(
                                title: "Next",
                                symbol: "chevron.right",
                                tint: .indigo,
                                action: { meter.nextScreen() }
                            )
                        }
                    }

                    Spacer(minLength: 0)
                } else {
                    HStack(spacing: 10) {
                        controlButton(
                            title: "Prev",
                            symbol: "chevron.left",
                            tint: .indigo,
                            action: { meter.previousScreen() }
                        )

                        currentScreenCard
                            .frame(maxWidth: .infinity, minHeight: 82)
                            .padding(.horizontal, 10)
                            .meterCard(tint: meter.color, fillOpacity: 0.06, strokeOpacity: 0.10)

                        controlButton(
                            title: "Rotate",
                            symbol: "rotate.right.fill",
                            tint: .orange,
                            action: { meter.rotateScreen() }
                        )

                        controlButton(
                            title: "Next",
                            symbol: "chevron.right",
                            tint: .indigo,
                            action: { meter.nextScreen() }
                        )
                    }
                }
            } else {
                HStack(spacing: 12) {
                    controlButton(
                        title: "Prev",
                        symbol: "chevron.left",
                        tint: .indigo,
                        action: { meter.previousScreen() }
                    )

                    currentScreenCard
                    .frame(maxWidth: .infinity, minHeight: 92)
                    .padding(.horizontal, 12)
                    .meterCard(tint: meter.color, fillOpacity: 0.06, strokeOpacity: 0.10)

                    controlButton(
                        title: "Next",
                        symbol: "chevron.right",
                        tint: .indigo,
                        action: { meter.nextScreen() }
                    )
                }

                controlButton(
                    title: "Rotate Screen",
                    symbol: "rotate.right.fill",
                    tint: .orange,
                    compact: false,
                    action: { meter.rotateScreen() }
                )
            }
        }
        .frame(maxWidth: .infinity, maxHeight: compactLayout ? .infinity : nil, alignment: .topLeading)
    }

    @ViewBuilder
    private var currentScreenCard: some View {
        if meter.reportsCurrentScreenIndex {
            Text(meter.currentScreenDescription)
                .font((usesExpandedCompactLayout ? Font.title3 : .subheadline).weight(.semibold))
                .multilineTextAlignment(.center)
        } else {
            VStack {
                Image(systemName: "questionmark.square.dashed")
                    .font(.system(size: usesExpandedCompactLayout ? 30 : 24, weight: .semibold))
                    .foregroundColor(.secondary)
            }
        }
    }

    private var usesExpandedCompactLayout: Bool {
        compactLayout && (availableSize?.height ?? 0) >= 520
    }

    private func controlButton(
        title: String,
        symbol: String,
        tint: Color,
        compact: Bool = true,
        action: @escaping () -> Void
    ) -> some View {
        Button(action: action) {
            VStack(spacing: 10) {
                Image(systemName: symbol)
                    .font(.system(size: compact ? 18 : 20, weight: .semibold))
                Text(title)
                    .font(.footnote.weight(.semibold))
                    .multilineTextAlignment(.center)
            }
            .foregroundColor(tint)
            .frame(maxWidth: .infinity, minHeight: compact ? (usesExpandedCompactLayout ? 112 : 92) : 68)
            .padding(.horizontal, 8)
            .meterCard(tint: tint, fillOpacity: 0.10, strokeOpacity: 0.14)
        }
        .buttonStyle(.plain)
    }
}

struct ControlView_Previews: PreviewProvider {
    static var previews: some View {
        ControlView()
    }
}