mirror of
https://github.com/vector-im/element-ios.git
synced 2024-09-28 15:22:39 +00:00
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:
parent
ef5365ab24
commit
545b641e53
30 changed files with 195 additions and 51 deletions
8
.gitignore
vendored
8
.gitignore
vendored
|
@ -30,8 +30,14 @@ vendor/
|
|||
Pods/
|
||||
|
||||
## 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
|
||||
*.xcworkspace
|
||||
*.xcworkspace/*
|
||||
!Riot.xcworkspace/xcshareddata
|
||||
Riot.xcworkspace/xcshareddata/*
|
||||
!Riot.xcworkspace/xcshareddata/swiftpm/
|
||||
Riot.xcworkspace/xcshareddata/swiftpm/*
|
||||
!Riot.xcworkspace/xcshareddata/swiftpm/Package.resolved
|
||||
|
||||
# Fastlane
|
||||
fastlane/report.xml
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1200"
|
||||
version = "1.3">
|
||||
version = "1.7">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES"
|
||||
|
|
50
Riot.xcworkspace/xcshareddata/swiftpm/Package.resolved
Normal file
50
Riot.xcworkspace/xcshareddata/swiftpm/Package.resolved
Normal 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
|
||||
}
|
91
Riot/Managers/Theme/ElementUIColorsResolved.swift
Normal file
91
Riot/Managers/Theme/ElementUIColorsResolved.swift
Normal 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()
|
||||
}
|
||||
}
|
|
@ -22,30 +22,10 @@ import DesignTokens
|
|||
@objc public protocol ThemeV2 {
|
||||
|
||||
/// Colors object
|
||||
var colors: ElementUIColors { get }
|
||||
var colors: ElementUIColorsResolved { get }
|
||||
|
||||
/// Fonts object
|
||||
var fonts: ElementUIFonts { get }
|
||||
|
||||
/// 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
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -182,7 +182,7 @@ class DarkTheme: NSObject, Theme {
|
|||
}
|
||||
|
||||
// MARK: - Theme v2
|
||||
var colors = UIColor.element
|
||||
var colors = UIColor.elementDark
|
||||
|
||||
var fonts = UIFont.element
|
||||
|
||||
|
|
|
@ -186,7 +186,7 @@ class DefaultTheme: NSObject, Theme {
|
|||
}
|
||||
|
||||
// MARK: - Theme v2
|
||||
var colors = UIColor.element
|
||||
var colors = UIColor.elementLight
|
||||
|
||||
var fonts = UIFont.element
|
||||
}
|
||||
|
|
|
@ -127,6 +127,9 @@ class VectorHostingController: UIHostingController<AnyView> {
|
|||
}
|
||||
|
||||
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 {
|
||||
theme.applyStyle(onNavigationBar: navigationBar, withModernScrollEdgeAppearance: enableNavigationBarScrollEdgeAppearance)
|
||||
}
|
||||
|
|
|
@ -65,9 +65,12 @@ fileprivate extension Color {
|
|||
///
|
||||
/// SceneKit works in a colorspace with a linear gamma, which is why this conversion is necessary.
|
||||
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
|
||||
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
|
||||
else { return nil }
|
||||
|
||||
|
|
|
@ -59,3 +59,9 @@ struct EffectsView: UIViewRepresentable {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct EffectsView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
EffectsView(effect: .confetti)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,11 +36,14 @@ public protocol ThemeSwiftUIType {
|
|||
/// may contain more design components in future, like icons, audio files etc.
|
||||
}
|
||||
|
||||
#warning("Temporary missing colors")
|
||||
public extension ElementColors {
|
||||
var quarterlyContent: Color { quaternaryContent }
|
||||
var navigation: Color { system }
|
||||
var tile: Color { system }
|
||||
// MARK: - Legacy
|
||||
var legacyTile: Color {
|
||||
let dynamicColor = UIColor { $0.userInterfaceStyle == .light ? .elementLight.tile : .elementDark.tile }
|
||||
return Color(dynamicColor)
|
||||
}
|
||||
|
||||
// TODO: Generate in DesignTokens repo.
|
||||
var namesAndAvatars: [Color] {
|
||||
[
|
||||
globalAzure,
|
||||
|
|
|
@ -50,7 +50,7 @@ struct BorderedInputFieldStyle: TextFieldStyle {
|
|||
if (theme.identifier == ThemeIdentifier.dark) {
|
||||
return (isEnabled ? theme.colors.primaryContent : theme.colors.tertiaryContent)
|
||||
} else {
|
||||
return (isEnabled ? theme.colors.primaryContent : theme.colors.quarterlyContent)
|
||||
return (isEnabled ? theme.colors.primaryContent : theme.colors.quaternaryContent)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ struct ClearViewModifier: ViewModifier {
|
|||
}) {
|
||||
Image(systemName: "xmark.circle.fill")
|
||||
.renderingMode(.template)
|
||||
.foregroundColor(theme.colors.quarterlyContent)
|
||||
.foregroundColor(theme.colors.quaternaryContent)
|
||||
}
|
||||
.padding(.top, alignment == .top ? 8 : 0)
|
||||
.padding(.bottom, alignment == .bottom ? 8 : 0)
|
||||
|
|
|
@ -56,7 +56,7 @@ struct MultilineTextField: View {
|
|||
return theme.colors.accent
|
||||
}
|
||||
|
||||
return theme.colors.quarterlyContent
|
||||
return theme.colors.quaternaryContent
|
||||
}
|
||||
|
||||
private var borderWidth: CGFloat {
|
||||
|
|
|
@ -55,7 +55,7 @@ struct OptionButton: View {
|
|||
}
|
||||
}
|
||||
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))
|
||||
.background(theme.colors.quinaryContent)
|
||||
|
|
|
@ -38,7 +38,7 @@ struct SearchBar: View {
|
|||
}
|
||||
.padding(8)
|
||||
.padding(.horizontal, 25)
|
||||
.background(theme.colors.navigation)
|
||||
.background(theme.colors.system)
|
||||
.cornerRadius(8)
|
||||
.padding(.leading)
|
||||
.padding(.trailing, isEditing ? 8 : 16)
|
||||
|
@ -46,7 +46,7 @@ struct SearchBar: View {
|
|||
HStack {
|
||||
Image(systemName: "magnifyingglass")
|
||||
.renderingMode(.template)
|
||||
.foregroundColor(theme.colors.quarterlyContent)
|
||||
.foregroundColor(theme.colors.quaternaryContent)
|
||||
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
|
||||
|
||||
if isEditing && !text.isEmpty {
|
||||
|
@ -55,7 +55,7 @@ struct SearchBar: View {
|
|||
}) {
|
||||
Image(systemName: "multiply.circle.fill")
|
||||
.renderingMode(.template)
|
||||
.foregroundColor(theme.colors.quarterlyContent)
|
||||
.foregroundColor(theme.colors.quaternaryContent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ struct SecondaryActionButtonStyle_Previews: PreviewProvider {
|
|||
Text("Custom")
|
||||
.foregroundColor(theme.colors.secondaryContent)
|
||||
}
|
||||
.buttonStyle(SecondaryActionButtonStyle(customColor: theme.colors.quarterlyContent))
|
||||
.buttonStyle(SecondaryActionButtonStyle(customColor: theme.colors.quaternaryContent))
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ struct WaitOverlay: ViewModifier {
|
|||
}
|
||||
.padding(12)
|
||||
.background(RoundedRectangle(cornerRadius: 8, style: .continuous)
|
||||
.fill(theme.colors.navigation.opacity(0.9)))
|
||||
.fill(theme.colors.system.opacity(0.9)))
|
||||
}
|
||||
.edgesIgnoringSafeArea(.all)
|
||||
.transition(.opacity)
|
||||
|
|
|
@ -47,7 +47,7 @@ struct OnboardingSplashScreenPageIndicator: View {
|
|||
ForEach(0..<pageCount) { index in
|
||||
Circle()
|
||||
.frame(width: 8, height: 8)
|
||||
.foregroundColor(index == pageIndex ? .accentColor : theme.colors.quarterlyContent)
|
||||
.foregroundColor(index == pageIndex ? .accentColor : theme.colors.quaternaryContent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ struct RoomAccessTypeChooserRow: View {
|
|||
Spacer()
|
||||
Image(systemName: isSelected ? "checkmark.circle.fill" : "circle")
|
||||
.renderingMode(.template)
|
||||
.foregroundColor(isSelected ? theme.colors.accent : theme.colors.quarterlyContent)
|
||||
.foregroundColor(isSelected ? theme.colors.accent : theme.colors.quaternaryContent)
|
||||
}
|
||||
if let badgeText = badgeText {
|
||||
Text(badgeText)
|
||||
|
|
|
@ -37,7 +37,7 @@ struct RoomRestrictedAccessSpaceChooserSelector: View {
|
|||
Button(VectorL10n.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)
|
||||
.disabled(viewModel.viewState.loading)
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ struct RoomRestrictedAccessSpaceChooserSelector: View {
|
|||
Button(VectorL10n.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)
|
||||
.disabled(viewModel.viewState.selectedItemIds.isEmpty || viewModel.viewState.loading)
|
||||
}
|
||||
|
|
|
@ -89,10 +89,10 @@ struct TimelinePollAnswerOptionButton: View {
|
|||
|
||||
var progressViewAccentColor: Color {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ struct FormInputFieldStyle: TextFieldStyle {
|
|||
|
||||
private var textColor: Color {
|
||||
if !isEnabled {
|
||||
return theme.colors.quarterlyContent
|
||||
return theme.colors.quaternaryContent
|
||||
}
|
||||
return theme.colors.primaryContent
|
||||
}
|
||||
|
|
|
@ -144,7 +144,7 @@ struct MatrixItemChooser: View {
|
|||
}
|
||||
.padding(.vertical, 4)
|
||||
.padding(.horizontal)
|
||||
.background(theme.colors.tile)
|
||||
.background(theme.colors.legacyTile)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ struct MatrixItemChooserSectionHeader: View {
|
|||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding(.vertical, 8)
|
||||
.padding(.horizontal)
|
||||
.background(theme.colors.navigation)
|
||||
.background(theme.colors.system)
|
||||
.cornerRadius(8)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ struct SpaceSettings: View {
|
|||
.padding(.bottom, 32)
|
||||
}
|
||||
}
|
||||
.background(theme.colors.navigation.ignoresSafeArea())
|
||||
.background(theme.colors.system.ignoresSafeArea())
|
||||
.waitOverlay(show: viewModel.viewState.isLoading, allowUserInteraction: false)
|
||||
.ignoresSafeArea(.container, edges: .bottom)
|
||||
.frame(maxHeight: .infinity)
|
||||
|
|
|
@ -67,7 +67,7 @@ struct SpaceSettingsOptionListItem: View {
|
|||
Image(systemName: "chevron.right")
|
||||
.renderingMode(.template)
|
||||
.font(.system(size: 16, weight: .regular))
|
||||
.foregroundColor(theme.colors.quarterlyContent)
|
||||
.foregroundColor(theme.colors.quaternaryContent)
|
||||
}
|
||||
.opacity(isEnabled ? 1 : 0.5)
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ targets:
|
|||
|
||||
dependencies:
|
||||
- target: RiotSwiftUI
|
||||
- package: DesignKit
|
||||
|
||||
settings:
|
||||
base:
|
||||
|
|
1
changelog.d/6276.change
Normal file
1
changelog.d/6276.change
Normal file
|
@ -0,0 +1 @@
|
|||
DesignKit: Replace the local DesignKit target with the shared Swift package from ElementX.
|
|
@ -41,7 +41,7 @@ include:
|
|||
packages:
|
||||
DesignKit:
|
||||
url: https://github.com/vector-im/element-x-ios
|
||||
branch: doug/designkit
|
||||
branch: develop
|
||||
Mapbox:
|
||||
url: https://github.com/maplibre/maplibre-gl-native-distribution
|
||||
minVersion: 5.12.2
|
||||
|
|
Loading…
Reference in a new issue