Skip to content

Commit

Permalink
#181: Style the session verification banner to match Figma.
Browse files Browse the repository at this point in the history
  • Loading branch information
pixlwave committed Sep 14, 2022
1 parent b30712b commit d8cdedd
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 17 deletions.
88 changes: 88 additions & 0 deletions DesignKit/Sources/Buttons/ElementCapsuleButtonStyle.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import SwiftUI

public extension ButtonStyle where Self == ElementCapsuleButtonStyle {
/// A button style that uses a capsule shape with a regular appearance.
static var elementCapsule: ElementCapsuleButtonStyle {
ElementCapsuleButtonStyle(isProminent: false)
}

/// A button style that uses a capsule shape with a prominent appearance.
static var elementCapsuleProminent: ElementCapsuleButtonStyle {
ElementCapsuleButtonStyle(isProminent: true)
}
}

public struct ElementCapsuleButtonStyle: ButtonStyle {
let isProminent: Bool

public func makeBody(configuration: Configuration) -> some View {
configuration.label
.padding(7)
.frame(maxWidth: .infinity)
.font(.element.footnote)
.foregroundColor(fontColor)
.multilineTextAlignment(.center)
.background(background)
.opacity(configuration.isPressed ? 0.6 : 1)
}

@ViewBuilder
var background: some View {
if isProminent {
Capsule().foregroundColor(Color.element.accent)
} else {
ZStack {
Capsule().foregroundColor(Color.element.systemSecondaryBackground)
Capsule().stroke(Color.element.accent)
}
}
}

var fontColor: Color {
isProminent ? .element.systemPrimaryBackground : .element.systemPrimaryLabel
}
}

struct ElementCapsuleButtonStyle_Previews: PreviewProvider {
public static var states: some View {
VStack {
Button("Enabled") { /* preview */ }
.buttonStyle(.elementCapsuleProminent)

Button("Disabled") { /* preview */ }
.buttonStyle(.elementCapsuleProminent)
.disabled(true)

Button("Enabled") { /* preview */ }
.buttonStyle(.elementCapsule)

Button("Disabled") { /* preview */ }
.buttonStyle(.elementCapsule)
.disabled(true)
}
.padding()
}

public static var previews: some View {
states
.preferredColorScheme(.light)
states
.preferredColorScheme(.dark)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@

"room_timeline_replying_to" = "Replying to %@";

"session_verification_banner_title" = "Help keep your messages secure";
"session_verification_banner_message" = "Looks like you’re using a new device. Verify its you.";

// MARK: - Authentication

"authentication_login_title" = "Welcome back!";
Expand Down
4 changes: 4 additions & 0 deletions ElementX/Sources/Generated/Strings+Untranslated.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ extension ElementL10n {
public static let serverSelectionServerUrl = ElementL10n.tr("Untranslated", "server_selection_server_url")
/// Choose your server
public static let serverSelectionTitle = ElementL10n.tr("Untranslated", "server_selection_title")
/// Looks like you’re using a new device. Verify its you.
public static let sessionVerificationBannerMessage = ElementL10n.tr("Untranslated", "session_verification_banner_message")
/// Help keep your messages secure
public static let sessionVerificationBannerTitle = ElementL10n.tr("Untranslated", "session_verification_banner_title")
/// Timeline Style
public static let settingsTimelineStyle = ElementL10n.tr("Untranslated", "settings_timeline_style")
/// Untranslated
Expand Down
1 change: 1 addition & 0 deletions ElementX/Sources/Screens/HomeScreen/HomeScreenModels.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ enum HomeScreenViewAction {
case selectRoom(roomIdentifier: String)
case userMenu(action: HomeScreenViewUserMenuAction)
case verifySession
case skipSessionVerification
}

struct HomeScreenViewState: BindableState {
Expand Down
2 changes: 2 additions & 0 deletions ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
callback?(.userMenu(action: action))
case .verifySession:
callback?(.verifySession)
case .skipSessionVerification:
hideSessionVerificationBanner()
}
}

Expand Down
55 changes: 38 additions & 17 deletions ElementX/Sources/Screens/HomeScreen/View/HomeScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,13 @@ struct HomeScreen: View {
// MARK: Views

var body: some View {
VStack(spacing: 0.0) {
Group {
if context.viewState.isLoadingRooms {
VStack {
Text(ElementL10n.loading)
ProgressView()
}
} else {
if context.viewState.showSessionVerificationBanner {
HStack {
Text(ElementL10n.verificationVerifyDevice)
Spacer()
Button(ElementL10n.startVerification) {
context.send(viewAction: .verifySession)
}
}
.padding()
.background(Color.element.quaternaryContent)
.padding(.top, 1)
}

List {
Section(ElementL10n.rooms) {
ForEach(context.viewState.visibleRooms) { room in
Expand All @@ -59,13 +46,16 @@ struct HomeScreen: View {
}
.listStyle(.plain)
.searchable(text: $context.searchQuery)
.safeAreaInset(edge: .top) {
if context.viewState.showSessionVerificationBanner {
sessionVerificationBanner
.background(Color.element.systemPrimaryBackground, ignoresSafeAreaEdges: .all)
}
}
}

Spacer()
}
.transition(.slide)
.animation(.elementDefault, value: context.viewState.showSessionVerificationBanner)
.ignoresSafeArea(.all, edges: .bottom)
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Expand Down Expand Up @@ -119,6 +109,37 @@ struct HomeScreen: View {
return .empty
}
}

private var sessionVerificationBanner: some View {
VStack(alignment: .leading, spacing: 16) {
VStack(alignment: .leading, spacing: 2) {
Text(ElementL10n.sessionVerificationBannerTitle)
.font(.element.subheadline.bold())
.foregroundColor(.element.systemPrimaryLabel)
Text(ElementL10n.sessionVerificationBannerMessage)
.font(.element.footnote)
.foregroundColor(.element.systemSecondaryLabel.opacity(0.6))
}

HStack(spacing: 16) {
Button(ElementL10n.actionSkip) {
context.send(viewAction: .skipSessionVerification)
}
.frame(maxWidth: .infinity)
.buttonStyle(.elementCapsule)

Button(ElementL10n.continue) {
context.send(viewAction: .verifySession)
}
.frame(maxWidth: .infinity)
.buttonStyle(.elementCapsuleProminent)
}
}
.padding(16)
.background(Color(uiColor: .quaternarySystemFill)) // Figma has secondary background but with a different color???
.cornerRadius(14)
.padding(.horizontal, 16)
}

private func settings() {
context.send(viewAction: .userMenu(action: .settings))
Expand Down
1 change: 1 addition & 0 deletions changelog.d/181.change
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Style the session verification banner to match Figma.

0 comments on commit d8cdedd

Please sign in to comment.