263 lines
9.5 KiB
Swift
263 lines
9.5 KiB
Swift
//
|
|
// ServerPanelView.swift
|
|
// PrivadoVPN
|
|
//
|
|
// Created by Juraldinio on 1/31/21.
|
|
// Copyright © 2021 Privado LLC. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
import AppKit
|
|
|
|
protocol ServerPanelViewInput: AnyObject {
|
|
func hide()
|
|
func show(country: String, city: String, flag: String)
|
|
func useHandCursor(enable: Bool)
|
|
func countryCircle(isHighlited: Bool)
|
|
}
|
|
|
|
protocol ServerPanelViewOutput: AnyObject {
|
|
func viewIsReady()
|
|
func viewWillDisappear()
|
|
func serverSelectRequired()
|
|
}
|
|
|
|
final class ServerPanelView: View {
|
|
|
|
private enum Constants {
|
|
|
|
enum LocalizedString {
|
|
static let serverSelected = "serverlist.location.selected"
|
|
}
|
|
|
|
enum Image {
|
|
static let map = "map.serverlist"
|
|
static let arrow = "main-arrow"
|
|
}
|
|
|
|
enum Color {
|
|
static let line = NSColor(red: 25, green: 33, blue: 71)
|
|
static let header = NSColor(red: 61, green: 69, blue: 111)
|
|
static let country = NSColor.white
|
|
static let city = NSColor.white
|
|
static let background = NSColor(red: 21, green: 25, blue: 53)
|
|
}
|
|
|
|
enum Font {
|
|
|
|
// swiftlint:disable nesting
|
|
enum Name {
|
|
static let medium = PrivadoConstants.Font.medium
|
|
static let black = PrivadoConstants.Font.bold
|
|
static let light = PrivadoConstants.Font.light
|
|
}
|
|
|
|
enum Size {
|
|
static let header: CGFloat = 12.0
|
|
static let country: CGFloat = 12.0
|
|
static let city: CGFloat = 12.0
|
|
}
|
|
// swiftlint:enable nesting
|
|
}
|
|
|
|
enum Geometry {
|
|
|
|
static let height: CGFloat = 110
|
|
|
|
static let headerWidth: CGFloat = 110
|
|
static let headerHeight: CGFloat = 16
|
|
static let headerLeading: CGFloat = 22
|
|
|
|
static let lineHeight: CGFloat = 2
|
|
|
|
static let mapImageWidth: CGFloat = 113
|
|
static let mapImageHeight: CGFloat = 65
|
|
static let mapBetweenLine: CGFloat = 6
|
|
|
|
static let arrowImageWidth: CGFloat = 7
|
|
static let arrowImageHeight: CGFloat = 12
|
|
static let arrowBetweenMap: CGFloat = 14
|
|
static let arrowTrailing: CGFloat = 21
|
|
|
|
static let countryTrailingMap: CGFloat = 21
|
|
static let cityTrailingMap: CGFloat = 21
|
|
static let cityTop: CGFloat = 5.0
|
|
}
|
|
}
|
|
|
|
private let output: ServerPanelViewOutput
|
|
|
|
private var headerField: NSTextField?
|
|
private var countryField: NSTextField?
|
|
private var cityField: NSTextField?
|
|
private var arrowView: ImageView?
|
|
private var backView: View?
|
|
private var countryImageView: ImageView?
|
|
private var countryCircleImageView: ImageView?
|
|
|
|
// MARK: - Init
|
|
|
|
init(output: ServerPanelViewOutput) {
|
|
|
|
self.output = output
|
|
|
|
super.init(frame: .zero)
|
|
|
|
self.isHidden = true
|
|
self.translatesAutoresizingMaskIntoConstraints = false
|
|
|
|
self.createUI()
|
|
self.activateLayout()
|
|
|
|
self.target = self
|
|
self.action = #selector(self.onClick)
|
|
}
|
|
|
|
// MARK: - Lyfecycle
|
|
|
|
override func viewDidMoveToSuperview() {
|
|
super.viewDidMoveToSuperview()
|
|
|
|
if self.superview.isExist {
|
|
self.output.viewIsReady()
|
|
}
|
|
}
|
|
|
|
override func removeFromSuperview() {
|
|
self.output.viewWillDisappear()
|
|
super.removeFromSuperview()
|
|
}
|
|
|
|
// MARK: - on methods
|
|
|
|
@objc
|
|
private func onClick() {
|
|
self.output.serverSelectRequired()
|
|
}
|
|
|
|
// MARK: - Private
|
|
|
|
private func createUI() {
|
|
|
|
let backgroundView = View(frame: .zero)
|
|
backgroundView.translatesAutoresizingMaskIntoConstraints = false
|
|
backgroundView.viewBackgroundColor = NSColor(red: 105, green: 112, blue: 208)
|
|
backgroundView.layer?.cornerRadius = 8
|
|
self.backView = backgroundView
|
|
self.addSubview(backgroundView)
|
|
|
|
let headerFont = NSFont(name: PrivadoConstants.Font.bold, size: 11)
|
|
let headerField = self.initializeTextField(color: NSColor(red: 218, green: 219, blue: 243), font: headerFont, alignment: .left, backgroundExist: false)
|
|
headerField.backgroundColor = .clear
|
|
headerField.stringValue = NSLocalizedString(Constants.LocalizedString.serverSelected, comment: "")
|
|
self.headerField = headerField
|
|
backgroundView.addSubview(headerField)
|
|
|
|
let countryImageView = ImageView(frame: .zero)
|
|
countryImageView.translatesAutoresizingMaskIntoConstraints = false
|
|
self.countryImageView = countryImageView
|
|
backgroundView.addSubview(countryImageView)
|
|
|
|
let countryCircleView = ImageView(frame: .zero)
|
|
countryCircleView.translatesAutoresizingMaskIntoConstraints = false
|
|
if let image = NSImage(named: "country-circle-disconnected") {
|
|
countryCircleView.image = image
|
|
}
|
|
self.countryCircleImageView = countryCircleView
|
|
backgroundView.addSubview(countryCircleView)
|
|
|
|
let cityFont = NSFont(name: PrivadoConstants.Font.bold, size: 16)
|
|
let cityField = self.initializeTextField(color: .white, font: cityFont, alignment: .left, backgroundExist: false)
|
|
self.cityField = cityField
|
|
backgroundView.addSubview(cityField)
|
|
|
|
let countryFont = NSFont(name: PrivadoConstants.Font.semiBold, size: 13)
|
|
let countryField = self.initializeTextField(color: .white, font: countryFont, alignment: .left, backgroundExist: false)
|
|
self.countryField = countryField
|
|
backgroundView.addSubview(countryField)
|
|
|
|
let arrowView = self.initializeImageView(resource: Constants.Image.arrow)
|
|
self.arrowView = arrowView
|
|
backgroundView.addSubview(arrowView)
|
|
}
|
|
|
|
private func activateLayout() {
|
|
|
|
guard let headerField = self.headerField
|
|
, let backgroundView = self.backView
|
|
, let countyImageView = self.countryImageView
|
|
, let countryCircleView = self.countryCircleImageView
|
|
|
|
, let countryField = self.countryField
|
|
, let cityField = self.cityField
|
|
, let arrowView = self.arrowView else {
|
|
return
|
|
}
|
|
|
|
NSLayoutConstraint.activate([
|
|
self.heightAnchor.constraint(equalToConstant: Constants.Geometry.height),
|
|
//
|
|
backgroundView.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 20),
|
|
backgroundView.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20),
|
|
backgroundView.topAnchor.constraint(equalTo: self.topAnchor),
|
|
backgroundView.bottomAnchor.constraint(equalTo: self.bottomAnchor),
|
|
//
|
|
headerField.topAnchor.constraint(equalTo: backgroundView.topAnchor, constant: 20),
|
|
headerField.leadingAnchor.constraint(equalTo: backgroundView.leadingAnchor, constant: 20),
|
|
headerField.widthAnchor.constraint(equalToConstant: 133),
|
|
headerField.heightAnchor.constraint(equalToConstant: 13),
|
|
//
|
|
countryCircleView.heightAnchor.constraint(equalToConstant: 48),
|
|
countryCircleView.widthAnchor.constraint(equalToConstant: 48),
|
|
countryCircleView.leadingAnchor.constraint(equalTo: backgroundView.leadingAnchor, constant: 20),
|
|
countryCircleView.topAnchor.constraint(equalTo: headerField.bottomAnchor, constant: 13),
|
|
//
|
|
countyImageView.heightAnchor.constraint(equalToConstant: 30),
|
|
countyImageView.widthAnchor.constraint(equalToConstant: 30),
|
|
|
|
countyImageView.centerXAnchor.constraint(equalTo: countryCircleView.centerXAnchor),
|
|
countyImageView.centerYAnchor.constraint(equalTo: countryCircleView.centerYAnchor),
|
|
|
|
cityField.leadingAnchor.constraint(equalTo: countryCircleView.trailingAnchor, constant: 10),
|
|
cityField.topAnchor.constraint(equalTo: headerField.bottomAnchor, constant: 17),
|
|
|
|
countryField.leadingAnchor.constraint(equalTo: cityField.leadingAnchor),
|
|
countryField.topAnchor.constraint(equalTo: cityField.bottomAnchor, constant: 7),
|
|
|
|
arrowView.widthAnchor.constraint(equalToConstant: 22),
|
|
arrowView.heightAnchor.constraint(equalToConstant: 22),
|
|
arrowView.trailingAnchor.constraint(equalTo: backgroundView.trailingAnchor, constant: -20),
|
|
arrowView.bottomAnchor.constraint(equalTo: backgroundView.bottomAnchor, constant: -33)
|
|
])
|
|
|
|
}
|
|
}
|
|
|
|
// MARK: - ServerPanelViewInput
|
|
|
|
extension ServerPanelView: ServerPanelViewInput {
|
|
|
|
func hide() {
|
|
self.isHidden = true
|
|
}
|
|
|
|
func show(country: String, city: String, flag: String) {
|
|
|
|
self.countryField?.stringValue = country
|
|
self.cityField?.stringValue = city
|
|
self.countryImageView?.image = NSImage(named: flag)
|
|
|
|
self.isHidden = false
|
|
}
|
|
|
|
func useHandCursor(enable: Bool) {
|
|
self.useHandCursor = enable
|
|
self.arrowView?.isHidden = !enable
|
|
}
|
|
|
|
func countryCircle(isHighlited: Bool) {
|
|
self.countryCircleImageView?.image = isHighlited ? NSImage(named: "country-circle-connected") : NSImage(named: "country-circle-disconnected")
|
|
}
|
|
|
|
}
|