release notes wallpaper

This commit is contained in:
kate-signal 2026-05-12 18:11:45 -04:00 committed by GitHub
parent 59b1d17ac3
commit 589d37d607
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 101 additions and 44 deletions

View File

@ -161,10 +161,20 @@ public class CVComponentThreadDetails: CVComponentBase, CVRootComponent {
let groupInfoWrapper = ManualLayoutViewWithLayer(name: "groupWrapper")
// Blurred background for when there's wallpaper,
// Unique background for release notes channel,
// blurred background for when there's wallpaper,
// frame with rounded corners otherwise.
let cornerRadius: CGFloat = 40
if conversationStyle.hasWallpaper {
if thread.isReleaseNotesThread {
if Theme.isDarkThemeEnabled {
groupInfoWrapper.backgroundColor = UIColor(rgbHex: 0x2F3240, alpha: 1)
} else {
groupInfoWrapper.backgroundColor = UIColor(rgbHex: 0xF6F7FF, alpha: 1)
}
groupInfoWrapper.layer.cornerRadius = cornerRadius
groupInfoWrapper.layer.borderWidth = 2
groupInfoWrapper.layer.borderColor = UIColor.Signal.tertiaryFill.cgColor
} else if conversationStyle.hasWallpaper {
let wallpaperBlurView = componentView.ensureWallpaperBlurView()
configureWallpaperBlurView(
wallpaperBlurView: wallpaperBlurView,

View File

@ -721,20 +721,19 @@ extension ConversationViewController: CVLoadCoordinatorDelegate {
) -> ConversationStyle {
let hasWallpaper: Bool
let shouldDimWallpaperInDarkMode: Bool
let isWallpaperPhoto: Bool
switch wallpaperViewBuilder {
case .customPhoto(_, let shouldDimInDarkMode):
hasWallpaper = true
shouldDimWallpaperInDarkMode = shouldDimInDarkMode
isWallpaperPhoto = true
case .colorOrGradient(_, let shouldDimInDarkMode):
hasWallpaper = true
shouldDimWallpaperInDarkMode = shouldDimInDarkMode
isWallpaperPhoto = false
case .releaseNotes:
hasWallpaper = true
shouldDimWallpaperInDarkMode = false
case .none:
hasWallpaper = false
shouldDimWallpaperInDarkMode = false
isWallpaperPhoto = false
}
return ConversationStyle(
type: type,
@ -742,7 +741,6 @@ extension ConversationViewController: CVLoadCoordinatorDelegate {
viewWidth: viewWidth,
hasWallpaper: hasWallpaper,
shouldDimWallpaperInDarkMode: shouldDimWallpaperInDarkMode,
isWallpaperPhoto: isWallpaperPhoto,
chatColor: chatColor,
)
}

View File

@ -519,7 +519,6 @@ public class CVLoader: NSObject {
viewWidth: containerView.width,
hasWallpaper: false,
shouldDimWallpaperInDarkMode: false,
isWallpaperPhoto: false,
chatColor: chatColor,
)
let coreState = CVCoreState(
@ -645,7 +644,6 @@ public class CVLoader: NSObject {
viewWidth: mockViewWidth,
hasWallpaper: false,
shouldDimWallpaperInDarkMode: false,
isWallpaperPhoto: false,
chatColor: chatColor,
)
let coreState = CVCoreState(

View File

@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "official_wallpaper_reduced.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

View File

@ -228,7 +228,6 @@ class EditHistoryTableSheetViewController: OWSTableSheetViewController {
viewWidth: viewWidth,
hasWallpaper: false,
shouldDimWallpaperInDarkMode: false,
isWallpaperPhoto: false,
chatColor: DependenciesBridge.shared.chatColorSettingStore.resolvedChatColor(
for: thread,
tx: tx,

View File

@ -137,7 +137,6 @@ class AudioCell: MediaTileListModeCell {
viewWidth: contentView.bounds.width,
hasWallpaper: false,
shouldDimWallpaperInDarkMode: false,
isWallpaperPhoto: false,
chatColor: ChatColorSettingStore.Constants.defaultColor.colorSetting,
)
let coreState = CVCoreState(conversationStyle: conversationStyle, mediaCache: audioItem.mediaCache)

View File

@ -124,7 +124,6 @@ class MediaGalleryFileCell: MediaTileListModeCell {
viewWidth: contentView.bounds.width,
hasWallpaper: false,
shouldDimWallpaperInDarkMode: false,
isWallpaperPhoto: false,
chatColor: ChatColorSettingStore.Constants.defaultColor.colorSetting,
)
let coreState = CVCoreState(conversationStyle: conversationStyle, mediaCache: fileItem.mediaCache)

View File

@ -300,7 +300,6 @@ class MemberLabelViewController: OWSViewController, UITextFieldDelegate {
viewWidth: view.width - 44, // stack view padding
hasWallpaper: false,
shouldDimWallpaperInDarkMode: false,
isWallpaperPhoto: false,
chatColor: PaletteChatColor.ultramarine.colorSetting,
)

View File

@ -229,7 +229,6 @@ class MessageDetailViewController: OWSTableViewController2 {
viewWidth: view.width - (cellOuterInsets.totalWidth + (Self.cellHInnerMargin * 2)),
hasWallpaper: false,
shouldDimWallpaperInDarkMode: false,
isWallpaperPhoto: false,
chatColor: DependenciesBridge.shared.chatColorSettingStore.resolvedChatColor(
for: thread,
tx: transaction,

View File

@ -221,7 +221,6 @@ class PinnedMessagesDetailsViewController: OWSViewController, DatabaseChangeDele
viewWidth: view.safeAreaLayoutGuide.layoutFrame.width,
hasWallpaper: false,
shouldDimWallpaperInDarkMode: false,
isWallpaperPhoto: false,
chatColor: DependenciesBridge.shared.chatColorSettingStore.resolvedChatColor(
for: threadViewModel.threadRecord,
tx: tx,
@ -255,7 +254,6 @@ class PinnedMessagesDetailsViewController: OWSViewController, DatabaseChangeDele
viewWidth: view.safeAreaLayoutGuide.layoutFrame.width - Self.goToMessageButtonSize,
hasWallpaper: false,
shouldDimWallpaperInDarkMode: false,
isWallpaperPhoto: false,
chatColor: DependenciesBridge.shared.chatColorSettingStore.resolvedChatColor(
for: thread,
tx: tx,

View File

@ -887,7 +887,9 @@ extension ConversationSettingsViewController: ConversationHeaderDelegate {
func buildMainHeader() -> UIView {
let options: ConversationHeaderBuilder.Options
if isTerminatedGroup || thread.isReleaseNotesThread {
if thread.isReleaseNotesThread {
options = [.mute, .search, .noBackground]
} else if isTerminatedGroup {
options = [.mute, .search]
} else if callRecords.isEmpty {
options = [.videoCall, .audioCall, .mute, .search, .renderLocalUserAsNoteToSelf]
@ -920,7 +922,7 @@ extension ConversationSettingsViewController: ConversationHeaderDelegate {
}
var canTapThreadName: Bool {
!thread.isGroupThread && !thread.isNoteToSelf
!thread.isGroupThread && !thread.isNoteToSelf && !thread.isReleaseNotesThread
}
func didTapThreadName() {

View File

@ -35,6 +35,8 @@ class ConversationSettingsViewController: OWSTableViewController2, BadgeCollecti
let callRecords: [CallRecord]
var memberLabelCoordinator: MemberLabelCoordinator?
let backgroundContainer = CVBackgroundContainer()
var thread: TSThread {
threadViewModel.threadRecord
}
@ -177,6 +179,20 @@ class ConversationSettingsViewController: OWSTableViewController2, BadgeCollecti
reloadThreadAndUpdateContent()
updateNavigationBar()
if thread.isReleaseNotesThread {
// Makes tableView clear so the wallpaper can show through.
backgroundStyle = .clear
if Theme.isDarkThemeEnabled {
overrideCellBackgroundColor = UIColor(rgbHex: 0x424757, alpha: 1)
}
let backgroundContainer = self.backgroundContainer
view.insertSubview(backgroundContainer, belowSubview: tableView)
backgroundContainer.autoPinEdgesToSuperviewEdges()
backgroundContainer.set(wallpaperView: WallpaperViewBuilder.releaseNotes.build())
}
}
func updateNavigationBar() {

View File

@ -401,6 +401,8 @@ private class MiniPreviewView: UIView {
shouldDimWallpaperInDarkMode = shouldDimInDarkMode
case .customPhoto(_, let shouldDimInDarkMode):
shouldDimWallpaperInDarkMode = shouldDimInDarkMode
case .releaseNotes:
shouldDimWallpaperInDarkMode = false
}
} else {
stackViewContainer = UIView()

View File

@ -152,7 +152,6 @@ class MockConversationView: UIView {
viewWidth: viewWidth,
hasWallpaper: hasWallpaper,
shouldDimWallpaperInDarkMode: shouldDimWallpaperInDarkMode,
isWallpaperPhoto: false,
chatColor: chatColor,
)
let threadAssociatedData = ThreadAssociatedData.fetchOrDefault(for: thread, transaction: transaction)

View File

@ -22,7 +22,6 @@ class ConversationViewTest: SignalBaseTest {
viewWidth: 100,
hasWallpaper: false,
shouldDimWallpaperInDarkMode: false,
isWallpaperPhoto: false,
chatColor: ChatColorSettingStore.Constants.defaultColor.colorSetting,
)
let style2 = ConversationStyle(
@ -31,7 +30,6 @@ class ConversationViewTest: SignalBaseTest {
viewWidth: 100,
hasWallpaper: false,
shouldDimWallpaperInDarkMode: false,
isWallpaperPhoto: false,
chatColor: ChatColorSettingStore.Constants.defaultColor.colorSetting,
)
let style3 = ConversationStyle(
@ -40,7 +38,6 @@ class ConversationViewTest: SignalBaseTest {
viewWidth: 101,
hasWallpaper: false,
shouldDimWallpaperInDarkMode: false,
isWallpaperPhoto: false,
chatColor: ChatColorSettingStore.Constants.defaultColor.colorSetting,
)
@ -61,7 +58,6 @@ class ConversationViewTest: SignalBaseTest {
viewWidth: 100,
hasWallpaper: false,
shouldDimWallpaperInDarkMode: false,
isWallpaperPhoto: false,
chatColor: ChatColorSettingStore.Constants.defaultColor.colorSetting,
)

View File

@ -241,6 +241,8 @@ public class BackupArchiveChatStyleArchiver: BackupArchiveProtoStreamWriter {
case .failure(let error):
return .failure(error)
}
case .releaseNotes:
protoWallpaper = nil
}
if let protoWallpaper {
@ -538,6 +540,7 @@ private extension Wallpaper {
enum BackupRepresentation {
case wallpaperPreset(BackupProto_ChatStyle.WallpaperPreset)
case photo
case releaseNotes
}
func asBackupProto() -> BackupRepresentation {
@ -567,6 +570,7 @@ private extension Wallpaper {
case .blueGradient: .wallpaperPreset(.gradientSky)
case .bisqueGradient: .wallpaperPreset(.gradientPeach)
case .photo: .photo
case .releaseNotes: .releaseNotes
}
}
}

View File

@ -23,7 +23,7 @@ extension Wallpaper {
}
switch self {
case .photo:
case .photo, .releaseNotes:
return nil
// Solid
case .blush:
@ -451,6 +451,7 @@ extension Wallpaper {
case .bisqueGradient: return .tangerine
// Custom
case .photo: return nil
case .releaseNotes: return nil
}
}
}

View File

@ -34,5 +34,8 @@ public enum Wallpaper: String, CaseIterable {
// Custom
case photo
public static var defaultWallpapers: [Wallpaper] { allCases.filter { $0 != .photo } }
// Release Notes
case releaseNotes
public static var defaultWallpapers: [Wallpaper] { allCases.filter { $0 != .photo && $0 != .releaseNotes } }
}

View File

@ -37,7 +37,6 @@ public struct ConversationStyle {
public let hasWallpaper: Bool
// Determines blur effect for incoming message bubbles.
public let shouldDimWallpaperInDarkMode: Bool
public let isWallpaperPhoto: Bool
public let isStandaloneRenderItem: Bool
@ -114,7 +113,6 @@ public struct ConversationStyle {
viewWidth: CGFloat,
hasWallpaper: Bool,
shouldDimWallpaperInDarkMode: Bool,
isWallpaperPhoto: Bool,
chatColor: ColorOrGradientSetting,
isStandaloneRenderItem: Bool = false,
) {
@ -124,7 +122,6 @@ public struct ConversationStyle {
self.primaryTextColor = Theme.primaryTextColor
self.hasWallpaper = hasWallpaper
self.shouldDimWallpaperInDarkMode = shouldDimWallpaperInDarkMode
self.isWallpaperPhoto = isWallpaperPhoto
self.chatColorSetting = chatColor
self.chatColorValue = chatColor.asValue
@ -397,7 +394,6 @@ extension ConversationStyle: Equatable {
lhs.isDarkThemeEnabled == rhs.isDarkThemeEnabled &&
lhs.hasWallpaper == rhs.hasWallpaper &&
lhs.shouldDimWallpaperInDarkMode == rhs.shouldDimWallpaperInDarkMode &&
lhs.isWallpaperPhoto == rhs.isWallpaperPhoto &&
lhs.maxMessageWidth == rhs.maxMessageWidth &&
lhs.maxMediaMessageWidth == rhs.maxMediaMessageWidth &&
lhs.textInsets == rhs.textInsets &&
@ -419,7 +415,6 @@ extension ConversationStyle: CustomDebugStringConvertible {
"dynamicBodyTypePointSize: \(dynamicBodyTypePointSize), " +
"isDarkThemeEnabled: \(isDarkThemeEnabled), " +
"hasWallpaper: \(hasWallpaper), " +
"isWallpaperPhoto: \(isWallpaperPhoto), " +
"maxMessageWidth: \(maxMessageWidth), " +
"maxMediaMessageWidth: \(maxMediaMessageWidth), " +
"textInsets: \(textInsets), " +

View File

@ -94,6 +94,8 @@ open class OWSTableViewController2: OWSViewController, OWSNavigationChildControl
presentingViewController != nil || traitCollection.userInterfaceLevel == .elevated
}
public var overrideCellBackgroundColor: UIColor?
private static let cellIdentifier = "cellIdentifier"
override public init() {
@ -1026,10 +1028,11 @@ extension OWSTableViewController2: UITableViewDataSource, UITableViewDelegate {
}
public var cellBackgroundColor: UIColor {
Self.cellBackgroundColor(
isUsingPresentedStyle: isUsingPresentedStyle,
forceDarkMode: forceDarkMode,
)
overrideCellBackgroundColor ??
Self.cellBackgroundColor(
isUsingPresentedStyle: isUsingPresentedStyle,
forceDarkMode: forceDarkMode,
)
}
public static func cellBackgroundColor(

View File

@ -11,19 +11,25 @@ extension Wallpaper {
public static func viewBuilder(for thread: TSThread? = nil, tx: DBReadTransaction) -> WallpaperViewBuilder? {
AssertIsOnMainThread()
let wallpaperStore = DependenciesBridge.shared.wallpaperStore
guard
let resolvedWallpaper = wallpaperStore.fetchWallpaperForRendering(
for: thread?.uniqueId,
tx: tx,
)
else {
return nil
let wallpaper: Wallpaper
if let thread, thread.isReleaseNotesThread {
wallpaper = .releaseNotes
} else {
guard
let resolvedWallpaper = wallpaperStore.fetchWallpaperForRendering(
for: thread?.uniqueId,
tx: tx,
)
else {
return nil
}
wallpaper = resolvedWallpaper
}
return viewBuilder(
for: resolvedWallpaper,
for: wallpaper,
customPhoto: {
WallpaperStore.fetchResolvedValue(
for: thread,
@ -51,6 +57,8 @@ extension Wallpaper {
return .customPhoto(customPhoto, shouldDimInDarkMode: shouldDimInDarkTheme)
} else if let colorOrGradientSetting = wallpaper.asColorOrGradientSetting {
return .colorOrGradient(colorOrGradientSetting, shouldDimInDarkMode: shouldDimInDarkTheme)
} else if case .releaseNotes = wallpaper {
return .releaseNotes
} else {
owsFailDebug("Couldn't create wallpaper view builder.")
return nil
@ -63,6 +71,7 @@ extension Wallpaper {
public enum WallpaperViewBuilder {
case colorOrGradient(ColorOrGradientSetting, shouldDimInDarkMode: Bool)
case customPhoto(UIImage, shouldDimInDarkMode: Bool)
case releaseNotes
public func build() -> WallpaperView {
switch self {
@ -77,6 +86,8 @@ public enum WallpaperViewBuilder {
)),
shouldDimInDarkTheme: shouldDimInDarkMode,
)
case .releaseNotes:
return WallpaperView(mode: .releaseNotesView, shouldDimInDarkTheme: false)
}
}
}
@ -87,6 +98,7 @@ public class WallpaperView {
fileprivate enum Mode {
case colorView(UIView)
case imageView(UIImage)
case releaseNotesView
}
public private(set) var contentView: UIView?
@ -133,7 +145,17 @@ public class WallpaperView {
dimmingView.backgroundColor = .ows_blackAlpha20
self.dimmingView = dimmingView
}
return imageView
case .releaseNotesView:
let image = UIImage(named: "official_wallpaper_reduced")
let imageView = UIImageView(image: image)
if Theme.isDarkThemeEnabled {
imageView.tintColor = UIColor(rgbHex: 0x272C3C)
imageView.backgroundColor = UIColor(rgbHex: 0x353A49)
} else {
imageView.tintColor = UIColor(rgbHex: 0xE3E4E9)
imageView.backgroundColor = UIColor(rgbHex: 0xE8EAF8).withAlphaComponent(0.4)
}
return imageView
}
}()