Fixup missing colours and use resolved colours in UIKit.

Fix the confetti colour when using DesignKit.
Pin swift packages.
Fix UI tests target.
This commit is contained in:
Doug 2022-05-27 20:42:44 +01:00 committed by Doug
parent ef5365ab24
commit 545b641e53
30 changed files with 195 additions and 51 deletions

8
.gitignore vendored
View file

@ -30,8 +30,14 @@ vendor/
Pods/ Pods/
## Ignore project files as we generate them with xcodegen (https://github.com/yonaskolb/XcodeGen) ## Ignore project files as we generate them with xcodegen (https://github.com/yonaskolb/XcodeGen)
# Plus ridiculous workaround to unignore the Package.resolved file for SwiftPM.
*.xcodeproj *.xcodeproj
*.xcworkspace *.xcworkspace/*
!Riot.xcworkspace/xcshareddata
Riot.xcworkspace/xcshareddata/*
!Riot.xcworkspace/xcshareddata/swiftpm/
Riot.xcworkspace/xcshareddata/swiftpm/*
!Riot.xcworkspace/xcshareddata/swiftpm/Package.resolved
# Fastlane # Fastlane
fastlane/report.xml fastlane/report.xml

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1200" LastUpgradeVersion = "1200"
version = "1.3"> version = "1.7">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
buildImplicitDependencies = "YES" buildImplicitDependencies = "YES"

View file

@ -0,0 +1,50 @@
{
"pins" : [
{
"identity" : "element-design-tokens",
"kind" : "remoteSourceControl",
"location" : "https://github.com/vector-im/element-design-tokens.git",
"state" : {
"revision" : "4aafdc25ca0e322c0de930d4ec86121f5503023e",
"version" : "0.0.1"
}
},
{
"identity" : "element-x-ios",
"kind" : "remoteSourceControl",
"location" : "https://github.com/vector-im/element-x-ios",
"state" : {
"branch" : "develop",
"revision" : "272fc5000bfe6e15a0f0ea669ef3088c7d163ce7"
}
},
{
"identity" : "maplibre-gl-native-distribution",
"kind" : "remoteSourceControl",
"location" : "https://github.com/maplibre/maplibre-gl-native-distribution",
"state" : {
"revision" : "d761956e81e74d8bdbfba31e0ec3a75616190658",
"version" : "5.12.2"
}
},
{
"identity" : "swift-collections",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-collections",
"state" : {
"revision" : "48254824bb4248676bf7ce56014ff57b142b77eb",
"version" : "1.0.2"
}
},
{
"identity" : "swiftui-introspect",
"kind" : "remoteSourceControl",
"location" : "https://github.com/siteline/SwiftUI-Introspect.git",
"state" : {
"revision" : "f2616860a41f9d9932da412a8978fec79c06fe24",
"version" : "0.1.4"
}
}
],
"version" : 2
}

View file

@ -0,0 +1,91 @@
//
// 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 UIKit
import DesignTokens
extension UIColor {
/// The colors from DesignKit, resolved for light mode only.
static let elementLight = ElementUIColorsResolved(dynamicColors: element, userInterfaceStyle: .light)
/// The colors from DesignKit, resolved for dark mode only.
static let elementDark = ElementUIColorsResolved(dynamicColors: element, userInterfaceStyle: .dark)
}
/// The dynamic colors from DesignKit, resolved to light or dark mode for use in the UIKit themes.
///
/// As Element doesn't (currently) update the app's `UIUserInterfaceStyle` when selecting
/// a custom theme, the dynamic colors provided by DesignKit need resolving for each theme to
/// prevent them from respecting the interface style and rendering in the wrong style.
@objcMembers public class ElementUIColorsResolved: NSObject {
// MARK: Compound
public let accent: UIColor
public let alert: UIColor
public let primaryContent: UIColor
public let secondaryContent: UIColor
public let tertiaryContent: UIColor
public let quaternaryContent: UIColor
public let quinaryContent: UIColor
public let system: UIColor
public let background: UIColor
public let namesAndAvatars: [UIColor]
// MARK: Legacy
public let quarterlyContent: UIColor
public let navigation: UIColor
public let tile: UIColor
public let separator: UIColor
// MARK: Setup
public init(dynamicColors: ElementUIColors, userInterfaceStyle: UIUserInterfaceStyle) {
let traitCollection = UITraitCollection(userInterfaceStyle: userInterfaceStyle)
self.accent = dynamicColors.accent.resolvedColor(with: traitCollection)
self.alert = dynamicColors.alert.resolvedColor(with: traitCollection)
self.primaryContent = dynamicColors.primaryContent.resolvedColor(with: traitCollection)
self.secondaryContent = dynamicColors.secondaryContent.resolvedColor(with: traitCollection)
self.tertiaryContent = dynamicColors.tertiaryContent.resolvedColor(with: traitCollection)
self.quaternaryContent = dynamicColors.quaternaryContent.resolvedColor(with: traitCollection)
self.quinaryContent = dynamicColors.quinaryContent.resolvedColor(with: traitCollection)
self.system = dynamicColors.system.resolvedColor(with: traitCollection)
self.background = dynamicColors.background.resolvedColor(with: traitCollection)
self.namesAndAvatars = [
dynamicColors.globalAzure.resolvedColor(with: traitCollection),
dynamicColors.globalGrape.resolvedColor(with: traitCollection),
dynamicColors.globalVerde.resolvedColor(with: traitCollection),
dynamicColors.globalPolly.resolvedColor(with: traitCollection),
dynamicColors.globalMelon.resolvedColor(with: traitCollection),
dynamicColors.globalAqua.resolvedColor(with: traitCollection),
dynamicColors.globalPrune.resolvedColor(with: traitCollection),
dynamicColors.globalKiwi.resolvedColor(with: traitCollection)
]
// Legacy colours
self.quarterlyContent = dynamicColors.quaternaryContent.resolvedColor(with: traitCollection)
self.navigation = dynamicColors.system.resolvedColor(with: traitCollection)
if userInterfaceStyle == .light {
self.tile = UIColor(rgb: 0xF3F8FD)
self.separator = dynamicColors.quinaryContent.resolvedColor(with: traitCollection)
} else {
self.tile = dynamicColors.quinaryContent.resolvedColor(with: traitCollection)
self.separator = dynamicColors.system.resolvedColor(with: traitCollection)
}
super.init()
}
}

View file

@ -22,30 +22,10 @@ import DesignTokens
@objc public protocol ThemeV2 { @objc public protocol ThemeV2 {
/// Colors object /// Colors object
var colors: ElementUIColors { get } var colors: ElementUIColorsResolved { get }
/// Fonts object /// Fonts object
var fonts: ElementUIFonts { get } var fonts: ElementUIFonts { get }
/// may contain more design components in future, like icons, audio files etc. /// may contain more design components in future, like icons, audio files etc.
} }
#warning("Temporary missing colors")
public extension ElementUIColors {
var quarterlyContent: UIColor { quaternaryContent }
var navigation: UIColor { system }
var tile: UIColor { system }
var separator: UIColor { system }
var namesAndAvatars: [UIColor] {
[
globalAzure,
globalGrape,
globalVerde,
globalPolly,
globalMelon,
globalAqua,
globalPrune,
globalKiwi
]
}
}

View file

@ -182,7 +182,7 @@ class DarkTheme: NSObject, Theme {
} }
// MARK: - Theme v2 // MARK: - Theme v2
var colors = UIColor.element var colors = UIColor.elementDark
var fonts = UIFont.element var fonts = UIFont.element

View file

@ -186,7 +186,7 @@ class DefaultTheme: NSObject, Theme {
} }
// MARK: - Theme v2 // MARK: - Theme v2
var colors = UIColor.element var colors = UIColor.elementLight
var fonts = UIFont.element var fonts = UIFont.element
} }

View file

@ -127,6 +127,9 @@ class VectorHostingController: UIHostingController<AnyView> {
} }
private func update(theme: Theme) { private func update(theme: Theme) {
// Ensure dynamic colors are shown correctly when the theme is the opposite appearance to the system.
overrideUserInterfaceStyle = theme.userInterfaceStyle
if let navigationBar = self.navigationController?.navigationBar { if let navigationBar = self.navigationController?.navigationBar {
theme.applyStyle(onNavigationBar: navigationBar, withModernScrollEdgeAppearance: enableNavigationBarScrollEdgeAppearance) theme.applyStyle(onNavigationBar: navigationBar, withModernScrollEdgeAppearance: enableNavigationBarScrollEdgeAppearance)
} }

View file

@ -65,9 +65,12 @@ fileprivate extension Color {
/// ///
/// SceneKit works in a colorspace with a linear gamma, which is why this conversion is necessary. /// SceneKit works in a colorspace with a linear gamma, which is why this conversion is necessary.
var floatComponents: [Float]? { var floatComponents: [Float]? {
// Get the CGColor from a UIColor as it is nil on Color when loaded from an asset catalog.
let cgColor = UIColor(self).cgColor
guard guard
let colorSpace = CGColorSpace(name: CGColorSpace.extendedLinearSRGB), let colorSpace = CGColorSpace(name: CGColorSpace.extendedLinearSRGB),
let linearColor = cgColor?.converted(to: colorSpace, intent: .defaultIntent, options: nil), let linearColor = cgColor.converted(to: colorSpace, intent: .defaultIntent, options: nil),
let components = linearColor.components let components = linearColor.components
else { return nil } else { return nil }

View file

@ -59,3 +59,9 @@ struct EffectsView: UIViewRepresentable {
} }
} }
} }
struct EffectsView_Previews: PreviewProvider {
static var previews: some View {
EffectsView(effect: .confetti)
}
}

View file

@ -36,11 +36,14 @@ public protocol ThemeSwiftUIType {
/// may contain more design components in future, like icons, audio files etc. /// may contain more design components in future, like icons, audio files etc.
} }
#warning("Temporary missing colors")
public extension ElementColors { public extension ElementColors {
var quarterlyContent: Color { quaternaryContent } // MARK: - Legacy
var navigation: Color { system } var legacyTile: Color {
var tile: Color { system } let dynamicColor = UIColor { $0.userInterfaceStyle == .light ? .elementLight.tile : .elementDark.tile }
return Color(dynamicColor)
}
// TODO: Generate in DesignTokens repo.
var namesAndAvatars: [Color] { var namesAndAvatars: [Color] {
[ [
globalAzure, globalAzure,

View file

@ -50,7 +50,7 @@ struct BorderedInputFieldStyle: TextFieldStyle {
if (theme.identifier == ThemeIdentifier.dark) { if (theme.identifier == ThemeIdentifier.dark) {
return (isEnabled ? theme.colors.primaryContent : theme.colors.tertiaryContent) return (isEnabled ? theme.colors.primaryContent : theme.colors.tertiaryContent)
} else { } else {
return (isEnabled ? theme.colors.primaryContent : theme.colors.quarterlyContent) return (isEnabled ? theme.colors.primaryContent : theme.colors.quaternaryContent)
} }
} }

View file

@ -47,7 +47,7 @@ struct ClearViewModifier: ViewModifier {
}) { }) {
Image(systemName: "xmark.circle.fill") Image(systemName: "xmark.circle.fill")
.renderingMode(.template) .renderingMode(.template)
.foregroundColor(theme.colors.quarterlyContent) .foregroundColor(theme.colors.quaternaryContent)
} }
.padding(.top, alignment == .top ? 8 : 0) .padding(.top, alignment == .top ? 8 : 0)
.padding(.bottom, alignment == .bottom ? 8 : 0) .padding(.bottom, alignment == .bottom ? 8 : 0)

View file

@ -56,7 +56,7 @@ struct MultilineTextField: View {
return theme.colors.accent return theme.colors.accent
} }
return theme.colors.quarterlyContent return theme.colors.quaternaryContent
} }
private var borderWidth: CGFloat { private var borderWidth: CGFloat {

View file

@ -55,7 +55,7 @@ struct OptionButton: View {
} }
} }
Spacer() Spacer()
Image(systemName: "chevron.right").font(.system(size: 16, weight: .regular)).foregroundColor(theme.colors.quarterlyContent) Image(systemName: "chevron.right").font(.system(size: 16, weight: .regular)).foregroundColor(theme.colors.quaternaryContent)
} }
.padding(EdgeInsets(top: 15, leading: 16, bottom: 15, trailing: 16)) .padding(EdgeInsets(top: 15, leading: 16, bottom: 15, trailing: 16))
.background(theme.colors.quinaryContent) .background(theme.colors.quinaryContent)

View file

@ -38,7 +38,7 @@ struct SearchBar: View {
} }
.padding(8) .padding(8)
.padding(.horizontal, 25) .padding(.horizontal, 25)
.background(theme.colors.navigation) .background(theme.colors.system)
.cornerRadius(8) .cornerRadius(8)
.padding(.leading) .padding(.leading)
.padding(.trailing, isEditing ? 8 : 16) .padding(.trailing, isEditing ? 8 : 16)
@ -46,7 +46,7 @@ struct SearchBar: View {
HStack { HStack {
Image(systemName: "magnifyingglass") Image(systemName: "magnifyingglass")
.renderingMode(.template) .renderingMode(.template)
.foregroundColor(theme.colors.quarterlyContent) .foregroundColor(theme.colors.quaternaryContent)
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading) .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
if isEditing && !text.isEmpty { if isEditing && !text.isEmpty {
@ -55,7 +55,7 @@ struct SearchBar: View {
}) { }) {
Image(systemName: "multiply.circle.fill") Image(systemName: "multiply.circle.fill")
.renderingMode(.template) .renderingMode(.template)
.foregroundColor(theme.colors.quarterlyContent) .foregroundColor(theme.colors.quaternaryContent)
} }
} }
} }

View file

@ -68,7 +68,7 @@ struct SecondaryActionButtonStyle_Previews: PreviewProvider {
Text("Custom") Text("Custom")
.foregroundColor(theme.colors.secondaryContent) .foregroundColor(theme.colors.secondaryContent)
} }
.buttonStyle(SecondaryActionButtonStyle(customColor: theme.colors.quarterlyContent)) .buttonStyle(SecondaryActionButtonStyle(customColor: theme.colors.quaternaryContent))
} }
.padding() .padding()
} }

View file

@ -89,7 +89,7 @@ struct WaitOverlay: ViewModifier {
} }
.padding(12) .padding(12)
.background(RoundedRectangle(cornerRadius: 8, style: .continuous) .background(RoundedRectangle(cornerRadius: 8, style: .continuous)
.fill(theme.colors.navigation.opacity(0.9))) .fill(theme.colors.system.opacity(0.9)))
} }
.edgesIgnoringSafeArea(.all) .edgesIgnoringSafeArea(.all)
.transition(.opacity) .transition(.opacity)

View file

@ -47,7 +47,7 @@ struct OnboardingSplashScreenPageIndicator: View {
ForEach(0..<pageCount) { index in ForEach(0..<pageCount) { index in
Circle() Circle()
.frame(width: 8, height: 8) .frame(width: 8, height: 8)
.foregroundColor(index == pageIndex ? .accentColor : theme.colors.quarterlyContent) .foregroundColor(index == pageIndex ? .accentColor : theme.colors.quaternaryContent)
} }
} }
} }

View file

@ -45,7 +45,7 @@ struct RoomAccessTypeChooserRow: View {
Spacer() Spacer()
Image(systemName: isSelected ? "checkmark.circle.fill" : "circle") Image(systemName: isSelected ? "checkmark.circle.fill" : "circle")
.renderingMode(.template) .renderingMode(.template)
.foregroundColor(isSelected ? theme.colors.accent : theme.colors.quarterlyContent) .foregroundColor(isSelected ? theme.colors.accent : theme.colors.quaternaryContent)
} }
if let badgeText = badgeText { if let badgeText = badgeText {
Text(badgeText) Text(badgeText)

View file

@ -37,7 +37,7 @@ struct RoomRestrictedAccessSpaceChooserSelector: View {
Button(VectorL10n.cancel) { Button(VectorL10n.cancel) {
viewModel.send(viewAction: .cancel) viewModel.send(viewAction: .cancel)
} }
.foregroundColor(viewModel.viewState.loading ? theme.colors.quarterlyContent : theme.colors.accent) .foregroundColor(viewModel.viewState.loading ? theme.colors.quaternaryContent : theme.colors.accent)
.opacity(viewModel.viewState.loading ? 0.7 : 1) .opacity(viewModel.viewState.loading ? 0.7 : 1)
.disabled(viewModel.viewState.loading) .disabled(viewModel.viewState.loading)
} }
@ -45,7 +45,7 @@ struct RoomRestrictedAccessSpaceChooserSelector: View {
Button(VectorL10n.done) { Button(VectorL10n.done) {
viewModel.send(viewAction: .done) viewModel.send(viewAction: .done)
} }
.foregroundColor(viewModel.viewState.selectedItemIds.isEmpty || viewModel.viewState.loading ? theme.colors.quarterlyContent : theme.colors.accent) .foregroundColor(viewModel.viewState.selectedItemIds.isEmpty || viewModel.viewState.loading ? theme.colors.quaternaryContent : theme.colors.accent)
.opacity(viewModel.viewState.selectedItemIds.isEmpty || viewModel.viewState.loading ? 0.7 : 1) .opacity(viewModel.viewState.selectedItemIds.isEmpty || viewModel.viewState.loading ? 0.7 : 1)
.disabled(viewModel.viewState.selectedItemIds.isEmpty || viewModel.viewState.loading) .disabled(viewModel.viewState.selectedItemIds.isEmpty || viewModel.viewState.loading)
} }

View file

@ -89,10 +89,10 @@ struct TimelinePollAnswerOptionButton: View {
var progressViewAccentColor: Color { var progressViewAccentColor: Color {
guard !poll.closed else { guard !poll.closed else {
return (answerOption.winner ? theme.colors.accent : theme.colors.quarterlyContent) return (answerOption.winner ? theme.colors.accent : theme.colors.quaternaryContent)
} }
return answerOption.selected ? theme.colors.accent : theme.colors.quarterlyContent return answerOption.selected ? theme.colors.accent : theme.colors.quaternaryContent
} }
} }

View file

@ -25,7 +25,7 @@ struct FormInputFieldStyle: TextFieldStyle {
private var textColor: Color { private var textColor: Color {
if !isEnabled { if !isEnabled {
return theme.colors.quarterlyContent return theme.colors.quaternaryContent
} }
return theme.colors.primaryContent return theme.colors.primaryContent
} }

View file

@ -144,7 +144,7 @@ struct MatrixItemChooser: View {
} }
.padding(.vertical, 4) .padding(.vertical, 4)
.padding(.horizontal) .padding(.horizontal)
.background(theme.colors.tile) .background(theme.colors.legacyTile)
} }
} }

View file

@ -52,7 +52,7 @@ struct MatrixItemChooserSectionHeader: View {
.frame(maxWidth: .infinity, alignment: .leading) .frame(maxWidth: .infinity, alignment: .leading)
.padding(.vertical, 8) .padding(.vertical, 8)
.padding(.horizontal) .padding(.horizontal)
.background(theme.colors.navigation) .background(theme.colors.system)
.cornerRadius(8) .cornerRadius(8)
} }
} }

View file

@ -39,7 +39,7 @@ struct SpaceSettings: View {
.padding(.bottom, 32) .padding(.bottom, 32)
} }
} }
.background(theme.colors.navigation.ignoresSafeArea()) .background(theme.colors.system.ignoresSafeArea())
.waitOverlay(show: viewModel.viewState.isLoading, allowUserInteraction: false) .waitOverlay(show: viewModel.viewState.isLoading, allowUserInteraction: false)
.ignoresSafeArea(.container, edges: .bottom) .ignoresSafeArea(.container, edges: .bottom)
.frame(maxHeight: .infinity) .frame(maxHeight: .infinity)

View file

@ -67,7 +67,7 @@ struct SpaceSettingsOptionListItem: View {
Image(systemName: "chevron.right") Image(systemName: "chevron.right")
.renderingMode(.template) .renderingMode(.template)
.font(.system(size: 16, weight: .regular)) .font(.system(size: 16, weight: .regular))
.foregroundColor(theme.colors.quarterlyContent) .foregroundColor(theme.colors.quaternaryContent)
} }
.opacity(isEnabled ? 1 : 0.5) .opacity(isEnabled ? 1 : 0.5)
} }

View file

@ -32,6 +32,7 @@ targets:
dependencies: dependencies:
- target: RiotSwiftUI - target: RiotSwiftUI
- package: DesignKit
settings: settings:
base: base:

1
changelog.d/6276.change Normal file
View file

@ -0,0 +1 @@
DesignKit: Replace the local DesignKit target with the shared Swift package from ElementX.

View file

@ -41,7 +41,7 @@ include:
packages: packages:
DesignKit: DesignKit:
url: https://github.com/vector-im/element-x-ios url: https://github.com/vector-im/element-x-ios
branch: doug/designkit branch: develop
Mapbox: Mapbox:
url: https://github.com/maplibre/maplibre-gl-native-distribution url: https://github.com/maplibre/maplibre-gl-native-distribution
minVersion: 5.12.2 minVersion: 5.12.2