Skip to content

Commit

Permalink
PIA-1297: Update styles on the region selection flow
Browse files Browse the repository at this point in the history
  • Loading branch information
kp-laura-sempere committed Feb 9, 2024
1 parent de6172a commit ea8f8fe
Show file tree
Hide file tree
Showing 26 changed files with 459 additions and 65 deletions.
3 changes: 0 additions & 3 deletions PIA VPN-tvOS/Dashboard/UI/DashboardView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,6 @@ struct DashboardView: View {

}
.frame(width: viewWidth, height: viewHeight)
.background(Color.pia_background)


}
}

Expand Down
2 changes: 1 addition & 1 deletion PIA VPN-tvOS/Navigation/UI/TopNavigationView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ struct LeadingSegmentedNavigationView: View {
ForEach(viewModel.leadingSections, id: \.self) { section in
button(for: section)
.padding(6)

}
}
.background(Capsule().fill(Color.pia_surface_container_secondary).shadow(radius: 3))
}
.padding()
.onChange(of: focusedSection) { _, newValue in
viewModel.sectionDidUpdateFocus(to: newValue)
}
Expand Down
3 changes: 2 additions & 1 deletion PIA VPN-tvOS/PIA_VPN_tvOSApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ struct PIA_VPN_tvOSApp: App {
var body: some Scene {
WindowGroup {
RootContainerFactory.makeRootContainerView()
.preferredColorScheme(.dark)
.background(Color.pia_background)
.preferredColorScheme(.dark) //Sets the UI to Dark Mode
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,18 @@ class RegionsSelectionFactory {
}

static func makeRegionsContainerViewModel() -> RegionsContainerViewModel {
return RegionsContainerViewModel(onSearchSelectedAction: .navigate(router: AppRouterFactory.makeAppRouter(), destination: RegionsDestinations.search))
return RegionsContainerViewModel(favoritesUseCase: makeFavoriteRegionUseCase, onSearchSelectedAction: .navigate(router: AppRouterFactory.makeAppRouter(), destination: RegionsDestinations.search))
}


static func makeRegionsListViewModel(with filter: RegionsListFilter) -> RegionsListViewModel {
return RegionsListViewModel(filter: filter, listUseCase: makeRegionsListUseCase(),
favoriteUseCase: makeFavoriteRegionUseCase(), regionsFilterUseCase: makeRegionsFilterUseCase(),
favoriteUseCase: makeFavoriteRegionUseCase, regionsFilterUseCase: makeRegionsFilterUseCase(), regionsDisplayNameUseCase: RegionsDisplayNameUseCase(),
onServerSelectedRouterAction: .goBackToRoot(router: AppRouterFactory.makeAppRouter()))
}

static func makeRegionsFilterUseCase() -> RegionsFilterUseCaseType {
return RegionsFilterUseCase(serversUseCase: makeRegionsListUseCase(), favoritesUseCase: makeFavoriteRegionUseCase(), searchedRegionsAvailability: makeSearchedRegionsAvailability())
return RegionsFilterUseCase(serversUseCase: makeRegionsListUseCase(), favoritesUseCase: makeFavoriteRegionUseCase, searchedRegionsAvailability: makeSearchedRegionsAvailability())
}

static func makeSearchedRegionsAvailability() -> SearchedRegionsAvailabilityType {
Expand Down Expand Up @@ -64,8 +64,10 @@ class RegionsSelectionFactory {
return RegionsListUseCase(serverProvider: DashboardFactory.makeServerProvider(), clientPreferences: Client.preferences)
}

static func makeFavoriteRegionUseCase() -> FavoriteRegionUseCaseType {
/// FavoritesUseCase is the same instance across the whole app
/// in order to be able to publish updates to the favorites collection
static var makeFavoriteRegionUseCase: FavoriteRegionUseCaseType = {
return FavoriteRegionUseCase(keychain: KeychainFactory.makeKeychain())
}
}()

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import Foundation
import SwiftUI
import Combine

class RegionsContainerViewModel: ObservableObject {
enum RegionsNavigationItems: CaseIterable, Identifiable {
Expand All @@ -31,18 +32,22 @@ class RegionsContainerViewModel: ObservableObject {
}
}

@Published var sideMenuItems: [RegionsNavigationItems] = RegionsNavigationItems.allCases
@Published var sideMenuItems: [RegionsNavigationItems] = [.all, .search]

@Published var selectedSection: RegionsNavigationItems = .all

var searchButtonTitle: String {
L10n.Localizable.Region.Search.placeholder
L10n.Localizable.Regions.Search.Button.title
}

private let favoritesUseCase: FavoriteRegionUseCaseType
private let onSearchSelectedAction: AppRouter.Actions
private var cancellables = Set<AnyCancellable>()

init(onSearchSelectedAction: AppRouter.Actions) {
init(favoritesUseCase: FavoriteRegionUseCaseType, onSearchSelectedAction: AppRouter.Actions) {
self.favoritesUseCase = favoritesUseCase
self.onSearchSelectedAction = onSearchSelectedAction
subscribeToFavoritesUpdates()
}

func navigate(to route: RegionsNavigationItems) {
Expand All @@ -54,5 +59,20 @@ class RegionsContainerViewModel: ObservableObject {

}


}

// MARK: - Private

extension RegionsContainerViewModel {
private func subscribeToFavoritesUpdates() {
favoritesUseCase.favoriteIdentifiersPublisher
.receive(on: RunLoop.main)
.sink { newFavorites in
if newFavorites.isEmpty {
self.sideMenuItems = [.all, .search]
} else {
self.sideMenuItems = [.favorites, .all, .search]
}
}.store(in: &cancellables)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ class RegionsListViewModel: ObservableObject {
private let listUseCase: RegionsListUseCaseType
private let favoriteUseCase: FavoriteRegionUseCaseType
private let regionsFilterUseCase: RegionsFilterUseCaseType
private let regionsDisplayNameUseCase: RegionsDisplayNameUseCaseType

private let onServerSelectedRouterAction: AppRouter.Actions
internal var filter: RegionsListFilter

Expand All @@ -27,21 +29,31 @@ class RegionsListViewModel: ObservableObject {
private var cancellables = Set<AnyCancellable>()
internal var favoriteToggleError: Error? = nil

private var allServers: [ServerType] = []

init(filter: RegionsListFilter,
listUseCase: RegionsListUseCaseType,
favoriteUseCase: FavoriteRegionUseCaseType,
regionsFilterUseCase: RegionsFilterUseCaseType,
regionsDisplayNameUseCase: RegionsDisplayNameUseCaseType,
onServerSelectedRouterAction: AppRouter.Actions) {
self.filter = filter
self.listUseCase = listUseCase
self.favoriteUseCase = favoriteUseCase
self.regionsFilterUseCase = regionsFilterUseCase
self.regionsDisplayNameUseCase = regionsDisplayNameUseCase
self.onServerSelectedRouterAction = onServerSelectedRouterAction


allServers = listUseCase.getCurrentServers()
refreshRegionsList()
subscribeToSearchUpdates()
}

func getDisplayName(for server: ServerType) -> (title: String, subtitle: String) {
regionsDisplayNameUseCase.getDisplayName(for: server, amongst: allServers)
}


func didSelectRegionServer(_ server: ServerType) {
listUseCase.select(server: server)
onServerSelectedRouterAction()
Expand Down
54 changes: 16 additions & 38 deletions PIA VPN-tvOS/RegionsSelection/UI/RegionsContainerView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,54 +23,29 @@ struct RegionsContainerView: View {
} label: {
HStack {
Text(menuItem.text)
.font(.headline)
.padding(.leading, 26)
.padding(.vertical, 12)
.font(.system(size: 38, weight: .medium))
.foregroundColor(.pia_on_surface)
.padding(20)
Spacer()
}
.background(focusedFilter == menuItem ? Color.pia_surface_container_primary : Color.clear)
.cornerRadius(12)

}
.cornerRadius(4)
.buttonStyle(.plain)
.buttonStyle(.borderless)
.focused($focusedFilter, equals: menuItem)

}
}
}


var navigateToSearchScreenButton: some View {
Button {
viewModel.navigate(to: .search)
} label: {
HStack(alignment: .center) {
Spacer()
VStack {
Spacer()
Text(viewModel.searchButtonTitle)
.padding(.horizontal, 60)
.padding(.vertical, 18)
.background(Color.pia_primary)
.cornerRadius(8)
Spacer()
}.frame(height: 150)

Spacer()

}
.frame(height: 150)
.padding()

}
.buttonStyle(.bordered)
.buttonBorderShape(ButtonBorderShape.roundedRectangle)
}.listStyle(.plain)
}


var body: some View {
VStack(alignment: .trailing) {
HStack(alignment: .top) {
regionsFilterButtons
.frame(width: viewWidth * 0.23)
VStack {
switch viewModel.selectedSection {
case .favorites:
Expand All @@ -79,21 +54,24 @@ struct RegionsContainerView: View {
RegionsSelectionFactory.makeAllRegionsListView()
case .search:
VStack {
navigateToSearchScreenButton
SearchControllerButton(
buttonAction: {
viewModel.navigate(to: .search)
},
buttonTitle: viewModel.searchButtonTitle
)
RegionsSelectionFactory.makePreviouslySearchedRegionsListView()
.padding(.top, 40)
}

}
}.frame(width: viewWidth * 0.7)
}
}
.onChange(of: focusedFilter) { _, newValue in
guard let focusedMenuItem = newValue else { return }
viewModel.selectedSection = focusedMenuItem
}
}
.frame(width: viewWidth)
.background(Color.pia_background)
}
}

Expand Down
17 changes: 10 additions & 7 deletions PIA VPN-tvOS/RegionsSelection/UI/RegionsListItemButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@

import SwiftUI

struct RegionsListItemButton: View {
typealias ButtonAction = () -> Void
typealias ButtonAction = () -> Void

struct RegionsListItemButton: View {
let onRegionItemSelected: ButtonAction
@FocusState var buttonFocused: Bool

Expand Down Expand Up @@ -124,20 +124,23 @@ extension RegionsListItemButton {


var detailsView: some View {
VStack(alignment: .leading) {
VStack(alignment: .leading, spacing: 8) {
Text(title)
.font(.system(size: 31, weight: .medium))
.multilineTextAlignment(.leading)
.foregroundColor(buttonFocused ? Color.black : Color.pia_on_surface_container_secondary)
.foregroundColor(buttonFocused ? Color.pia_on_primary : Color.pia_on_surface_container_primary)
.minimumScaleFactor(0.6)
.fixedSize(horizontal: false, vertical: true)
.lineLimit(2, reservesSpace: true)
.lineLimit(1)

if let subtitle = subtitle {
Text(subtitle)
.font(.caption2)
.font(.system(size: 23, weight: .medium))
.italic()
.foregroundColor(buttonFocused ? Color.pia_on_primary : Color.pia_on_surface_container_primary)
.multilineTextAlignment(.leading)
.minimumScaleFactor(0.7)
.lineLimit(2)
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions PIA VPN-tvOS/RegionsSelection/UI/RegionsListView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,15 @@ struct RegionsListView: View {
viewModel.didSelectRegionServer(server)
},
iconName: "flag-\(server.country.lowercased())",
title: server.name,
// TODO: substitute here
title: viewModel.getDisplayName(for: server).title,
subtitle: viewModel.getDisplayName(for: server).subtitle,
favoriteIconName: viewModel.favoriteIconName(for: server),
contextMenuItem: contextMenuItem(for: server)
)

}
}
.padding(.top, 40)
}

}.onAppear {
Expand Down
49 changes: 49 additions & 0 deletions PIA VPN-tvOS/RegionsSelection/UI/SearchControllerButton.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//
// SearchControllerButton.swift
// PIA VPN-tvOS
//
// Created by Laura S on 2/8/24.
// Copyright © 2024 Private Internet Access Inc. All rights reserved.
//

import SwiftUI

struct SearchControllerButton: View {
let buttonAction: ButtonAction
let buttonTitle: String

@FocusState var focusedSearchButton: Bool

var body: some View {
Button {
buttonAction()
} label: {
HStack(alignment: .center) {
Spacer()
VStack {
Spacer()
Text(buttonTitle)
.font(.system(size: 38, weight: .medium))
.padding(.horizontal, 90)
.padding(.vertical, 8)
.foregroundColor(focusedSearchButton ? .pia_on_primary : .pia_on_surface)
.background(focusedSearchButton ? Color.pia_primary : Color.pia_surface_container_secondary)
.cornerRadius(8)
Spacer()
}
.frame(height: 66)

Spacer()

}
.frame(height: 150)
.overlay(
RoundedRectangle(cornerRadius: 20).stroke(Color.pia_outline, lineWidth: 2)
)

}
.focused($focusedSearchButton)
.buttonStyle(.borderless)
.buttonBorderShape(ButtonBorderShape.roundedRectangle)
}
}
Loading

0 comments on commit ea8f8fe

Please sign in to comment.