Cloud themes improvements

This commit is contained in:
Ilya Laktyushin 2019-08-29 05:31:34 +03:00
parent 4ac24e4369
commit f3db3a29b0
64 changed files with 3452 additions and 3048 deletions

View File

@ -8,6 +8,11 @@
<string>en</string> <string>en</string>
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
<string>${APP_NAME}</string> <string>${APP_NAME}</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict/>
<dict/>
</array>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string> <string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIcons</key> <key>CFBundleIcons</key>
@ -332,5 +337,29 @@
<false/> <false/>
<key>UIViewGroupOpacity</key> <key>UIViewGroupOpacity</key>
<false/> <false/>
<key>UTImportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>Telegram iOS Color Theme File</string>
<key>UTTypeIconFiles</key>
<array>
<string>BlueIcon@3x.png</string>
</array>
<key>UTTypeIdentifier</key>
<string>org.telegram.Telegram-iOS.theme</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>tgios-theme</string>
</array>
</dict>
</dict>
</array>
</dict> </dict>
</plist> </plist>

View File

@ -33,7 +33,5 @@
<string>merchant.privatbank.test.telergramios</string> <string>merchant.privatbank.test.telergramios</string>
<string>merchant.privatbank.prod.telergram</string> <string>merchant.privatbank.prod.telergram</string>
</array> </array>
<key>com.apple.developer.carplay-messaging</key>
<true/>
</dict> </dict>
</plist> </plist>

View File

@ -4660,19 +4660,27 @@ Any member of this group will be able to see messages in the channel.";
"Appearance.CreateTheme" = "Create New Theme"; "Appearance.CreateTheme" = "Create New Theme";
"Appearance.EditTheme" = "Edit Theme"; "Appearance.EditTheme" = "Edit Theme";
"Appearance.ShareTheme" = "Share";
"Appearance.RemoveTheme" = "Remove"; "Appearance.RemoveTheme" = "Remove";
"Appearance.CreateThemeInfo" = "A new theme template has been created from your current theme and added to your Saved Messages."; "Appearance.RemoveThemeConfirmation" = "Remove Theme";
"Conversation.Theme" = "Color Theme"; "Conversation.Theme" = "Color Theme";
"Conversation.ViewTheme" = "VIEW THEME"; "Conversation.ViewTheme" = "VIEW THEME";
"Message.Theme" = "Color Theme"; "Message.Theme" = "Color Theme";
"EditTheme.Title" = "Edit Theme"; "EditTheme.CreateTitle" = "Create Theme";
"EditTheme.Preview" = "PREVIEW"; "EditTheme.EditTitle" = "Edit Theme";
"EditTheme.Title" = "Title"; "EditTheme.Title" = "Theme Name";
"EditTheme.ShortLink" = "Short Link"; "EditTheme.ShortLink" = "link";
"EditTheme.ShortLinkInfo" = "Short Link"; "EditTheme.ShortLinkInfo" = "Short Link Info";
"EditTheme.Preview" = "CHAT PREVIEW";
"EditTheme.UploadNewTheme" = "Select a File...";
"EditTheme.UploadEditedTheme" = "Select Updated File...";
"EditTheme.UploadNewInfo" = "This theme will be based on your current theme and wallpaper. Otherwise, you can use a custom theme file if you already have one.";
"EditTheme.UploadEditedInfo" = "You can select a new file to update the theme. It will be updated for all users.";
"EditTheme.ThemeTemplateAlert" = "A copy of your theme template has been added to your Saved Messages.";
"EditTheme.FileReadError" = "Invalid theme file";
"Wallpaper.ErrorNotFound" = "Sorry, this chat background doesn't seem to exist."; "Wallpaper.ErrorNotFound" = "Sorry, this chat background doesn't seem to exist.";
"Theme.ErrorNotFound" = "Sorry, this color theme doesn't seem to exist."; "Theme.ErrorNotFound" = "Sorry, this color theme doesn't seem to exist.";

View File

@ -152,7 +152,7 @@ private final class BotCheckoutPasswordAlertContentNode: AlertContentNode {
self.textFieldNode.textField.textColor = theme.actionSheet.primaryTextColor self.textFieldNode.textField.textColor = theme.actionSheet.primaryTextColor
self.textFieldNode.textField.font = Font.regular(12.0) self.textFieldNode.textField.font = Font.regular(12.0)
self.textFieldNode.textField.typingAttributes = [NSAttributedString.Key.font: Font.regular(12.0)] self.textFieldNode.textField.typingAttributes = [NSAttributedString.Key.font: Font.regular(12.0)]
self.textFieldNode.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance self.textFieldNode.textField.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance
self.textFieldNode.textField.isSecureTextEntry = true self.textFieldNode.textField.isSecureTextEntry = true
self.textFieldNode.textField.tintColor = theme.list.itemAccentColor self.textFieldNode.textField.tintColor = theme.list.itemAccentColor

View File

@ -42,7 +42,7 @@ final class BotPaymentCardInputItemNode: BotPaymentItemNode, STPPaymentCardTextF
self.cardField.textColor = theme.list.itemPrimaryTextColor self.cardField.textColor = theme.list.itemPrimaryTextColor
self.cardField.textErrorColor = theme.list.itemDestructiveColor self.cardField.textErrorColor = theme.list.itemDestructiveColor
self.cardField.placeholderColor = theme.list.itemPlaceholderTextColor self.cardField.placeholderColor = theme.list.itemPlaceholderTextColor
self.cardField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance self.cardField.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance
} }
self.cardField.frame = CGRect(origin: CGPoint(x: 5.0, y: 0.0), size: CGSize(width: width - 10.0, height: 44.0)) self.cardField.frame = CGRect(origin: CGPoint(x: 5.0, y: 0.0), size: CGSize(width: width - 10.0, height: 44.0))

View File

@ -79,7 +79,7 @@ final class BotPaymentFieldItemNode: BotPaymentItemNode, UITextFieldDelegate {
self.titleNode.attributedText = NSAttributedString(string: self.title, font: titleFont, textColor: theme.list.itemPrimaryTextColor) self.titleNode.attributedText = NSAttributedString(string: self.title, font: titleFont, textColor: theme.list.itemPrimaryTextColor)
self.textField.textField.textColor = theme.list.itemPrimaryTextColor self.textField.textField.textColor = theme.list.itemPrimaryTextColor
self.textField.textField.attributedPlaceholder = NSAttributedString(string: placeholder, font: titleFont, textColor: theme.list.itemPlaceholderTextColor) self.textField.textField.attributedPlaceholder = NSAttributedString(string: placeholder, font: titleFont, textColor: theme.list.itemPlaceholderTextColor)
self.textField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance self.textField.textField.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance
self.textField.textField.tintColor = theme.list.itemAccentColor self.textField.textField.tintColor = theme.list.itemAccentColor
} }
@ -97,7 +97,7 @@ final class BotPaymentFieldItemNode: BotPaymentItemNode, UITextFieldDelegate {
if self.theme !== theme { if self.theme !== theme {
self.theme = theme self.theme = theme
self.titleNode.attributedText = NSAttributedString(string: self.title, font: titleFont, textColor: theme.list.itemPrimaryTextColor) self.titleNode.attributedText = NSAttributedString(string: self.title, font: titleFont, textColor: theme.list.itemPrimaryTextColor)
self.textField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance self.textField.textField.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance
self.textField.textField.tintColor = theme.list.itemAccentColor self.textField.textField.tintColor = theme.list.itemAccentColor
} }

View File

@ -321,7 +321,7 @@ class CreatePollOptionItemNode: ItemListRevealOptionsItemNode, ItemListItemNode,
strongSelf.textNode.attributedPlaceholderText = attributedPlaceholderText strongSelf.textNode.attributedPlaceholderText = attributedPlaceholderText
} }
strongSelf.textNode.keyboardAppearance = item.theme.chatList.searchBarKeyboardColor.keyboardAppearance strongSelf.textNode.keyboardAppearance = item.theme.rootController.keyboardColor.keyboardAppearance
strongSelf.textClippingNode.frame = CGRect(origin: CGPoint(x: revealOffset + leftInset, y: textTopInset), size: CGSize(width: params.width - leftInset - params.rightInset, height: textLayout.size.height)) strongSelf.textClippingNode.frame = CGRect(origin: CGPoint(x: revealOffset + leftInset, y: textTopInset), size: CGSize(width: params.width - leftInset - params.rightInset, height: textLayout.size.height))
strongSelf.textNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: params.width - leftInset - rightInset, height: textLayout.size.height + 1.0)) strongSelf.textNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: params.width - leftInset - rightInset, height: textLayout.size.height + 1.0))

View File

@ -93,7 +93,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
self.effectView = UIVisualEffectView() self.effectView = UIVisualEffectView()
if #available(iOS 9.0, *) { if #available(iOS 9.0, *) {
} else { } else {
if theme.chatList.searchBarKeyboardColor == .dark { if theme.rootController.keyboardColor == .dark {
self.effectView.effect = UIBlurEffect(style: .dark) self.effectView.effect = UIBlurEffect(style: .dark)
} else { } else {
self.effectView.effect = UIBlurEffect(style: .light) self.effectView.effect = UIBlurEffect(style: .light)

View File

@ -17,8 +17,8 @@ import OpenInExternalAppUI
private let deleteImage = generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Accessory Panels/MessageSelectionTrash"), color: .white) private let deleteImage = generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Accessory Panels/MessageSelectionTrash"), color: .white)
private let actionImage = generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Accessory Panels/MessageSelectionAction"), color: .white) private let actionImage = generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Accessory Panels/MessageSelectionAction"), color: .white)
private let backwardImage = UIImage(bundleImageName: "Media Gallery/BackwardButton") private let backwardImage = generateTintedImage(image: UIImage(bundleImageName: "Media Gallery/BackwardButton"), color: .white)
private let forwardImage = UIImage(bundleImageName: "Media Gallery/ForwardButton") private let forwardImage = generateTintedImage(image: UIImage(bundleImageName: "Media Gallery/ForwardButton"), color: .white)
private let pauseImage = generateTintedImage(image: UIImage(bundleImageName: "Media Gallery/PauseButton"), color: .white) private let pauseImage = generateTintedImage(image: UIImage(bundleImageName: "Media Gallery/PauseButton"), color: .white)
private let playImage = generateTintedImage(image: UIImage(bundleImageName: "Media Gallery/PlayButton"), color: .white) private let playImage = generateTintedImage(image: UIImage(bundleImageName: "Media Gallery/PlayButton"), color: .white)
@ -600,8 +600,13 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
self.actionButton.frame = CGRect(origin: CGPoint(x: leftInset, y: panelHeight - bottomInset - 44.0), size: CGSize(width: 44.0, height: 44.0)) self.actionButton.frame = CGRect(origin: CGPoint(x: leftInset, y: panelHeight - bottomInset - 44.0), size: CGSize(width: 44.0, height: 44.0))
self.deleteButton.frame = CGRect(origin: CGPoint(x: width - 44.0 - rightInset, y: panelHeight - bottomInset - 44.0), size: CGSize(width: 44.0, height: 44.0)) self.deleteButton.frame = CGRect(origin: CGPoint(x: width - 44.0 - rightInset, y: panelHeight - bottomInset - 44.0), size: CGSize(width: 44.0, height: 44.0))
self.backwardButton.frame = CGRect(origin: CGPoint(x: floor((width - 44.0) / 2.0) - 66.0, y: panelHeight - bottomInset - 44.0), size: CGSize(width: 44.0, height: 44.0)) if let image = self.backwardButton.image(for: .normal) {
self.forwardButton.frame = CGRect(origin: CGPoint(x: floor((width - 44.0) / 2.0) + 66.0, y: panelHeight - bottomInset - 44.0), size: CGSize(width: 44.0, height: 44.0)) self.backwardButton.frame = CGRect(origin: CGPoint(x: floor((width - image.size.width) / 2.0) - 66.0, y: panelHeight - bottomInset - 44.0 + 7.0), size: image.size)
}
if let image = self.forwardButton.image(for: .normal) {
self.forwardButton.frame = CGRect(origin: CGPoint(x: floor((width - image.size.width) / 2.0) + 66.0, y: panelHeight - bottomInset - 44.0 + 7.0), size: image.size)
}
self.playbackControlButton.frame = CGRect(origin: CGPoint(x: floor((width - 44.0) / 2.0), y: panelHeight - bottomInset - 44.0), size: CGSize(width: 44.0, height: 44.0)) self.playbackControlButton.frame = CGRect(origin: CGPoint(x: floor((width - 44.0) / 2.0), y: panelHeight - bottomInset - 44.0), size: CGSize(width: 44.0, height: 44.0))

View File

@ -473,7 +473,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
} }
} }
} }
seekable = value.duration >= 45.0 seekable = value.duration >= 30.0
} }
var fetching = false var fetching = false

View File

@ -672,7 +672,7 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo
if strongSelf.inputSeparator == nil { if strongSelf.inputSeparator == nil {
animateIn = true animateIn = true
} }
let keyboardAppearance = item.theme.chatList.searchBarKeyboardColor.keyboardAppearance let keyboardAppearance = item.theme.rootController.keyboardColor.keyboardAppearance
switch editingName { switch editingName {
case let .personName(firstName, lastName): case let .personName(firstName, lastName):
if strongSelf.inputSeparator == nil { if strongSelf.inputSeparator == nil {

View File

@ -251,7 +251,7 @@ public class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNod
strongSelf.textNode.attributedPlaceholderText = attributedPlaceholderText strongSelf.textNode.attributedPlaceholderText = attributedPlaceholderText
} }
strongSelf.textNode.keyboardAppearance = item.theme.chatList.searchBarKeyboardColor.keyboardAppearance strongSelf.textNode.keyboardAppearance = item.theme.rootController.keyboardColor.keyboardAppearance
strongSelf.textClippingNode.frame = CGRect(origin: CGPoint(x: leftInset, y: textTopInset), size: CGSize(width: params.width - leftInset - params.rightInset, height: textLayout.size.height)) strongSelf.textClippingNode.frame = CGRect(origin: CGPoint(x: leftInset, y: textTopInset), size: CGSize(width: params.width - leftInset - params.rightInset, height: textLayout.size.height))
strongSelf.textNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: params.width - leftInset - 16.0 - rightInset, height: textLayout.size.height + 1.0)) strongSelf.textNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: params.width - leftInset - 16.0 - rightInset, height: textLayout.size.height + 1.0))

View File

@ -13,6 +13,21 @@ public enum ItemListSingleLineInputItemType: Equatable {
case username case username
} }
public enum ItemListSingleLineInputClearType: Equatable {
case none
case always
case onFocus
var hasButton: Bool {
switch self {
case .none:
return false
case .always, .onFocus:
return true
}
}
}
public class ItemListSingleLineInputItem: ListViewItem, ItemListItem { public class ItemListSingleLineInputItem: ListViewItem, ItemListItem {
let theme: PresentationTheme let theme: PresentationTheme
let strings: PresentationStrings let strings: PresentationStrings
@ -22,7 +37,7 @@ public class ItemListSingleLineInputItem: ListViewItem, ItemListItem {
let type: ItemListSingleLineInputItemType let type: ItemListSingleLineInputItemType
let returnKeyType: UIReturnKeyType let returnKeyType: UIReturnKeyType
let spacing: CGFloat let spacing: CGFloat
let clearButton: Bool let clearType: ItemListSingleLineInputClearType
let enabled: Bool let enabled: Bool
public let sectionId: ItemListSectionId public let sectionId: ItemListSectionId
let action: () -> Void let action: () -> Void
@ -32,7 +47,7 @@ public class ItemListSingleLineInputItem: ListViewItem, ItemListItem {
let updatedFocus: ((Bool) -> Void)? let updatedFocus: ((Bool) -> Void)?
public let tag: ItemListItemTag? public let tag: ItemListItemTag?
public init(theme: PresentationTheme, strings: PresentationStrings, title: NSAttributedString, text: String, placeholder: String, type: ItemListSingleLineInputItemType = .regular(capitalization: true, autocorrection: true), returnKeyType: UIReturnKeyType = .`default`, spacing: CGFloat = 0.0, clearButton: Bool = false, enabled: Bool = true, tag: ItemListItemTag? = nil, sectionId: ItemListSectionId, textUpdated: @escaping (String) -> Void, shouldUpdateText: @escaping (String) -> Bool = { _ in return true }, processPaste: ((String) -> String)? = nil, updatedFocus: ((Bool) -> Void)? = nil, action: @escaping () -> Void) { public init(theme: PresentationTheme, strings: PresentationStrings, title: NSAttributedString, text: String, placeholder: String, type: ItemListSingleLineInputItemType = .regular(capitalization: true, autocorrection: true), returnKeyType: UIReturnKeyType = .`default`, spacing: CGFloat = 0.0, clearType: ItemListSingleLineInputClearType = .none, enabled: Bool = true, tag: ItemListItemTag? = nil, sectionId: ItemListSectionId, textUpdated: @escaping (String) -> Void, shouldUpdateText: @escaping (String) -> Bool = { _ in return true }, processPaste: ((String) -> String)? = nil, updatedFocus: ((Bool) -> Void)? = nil, action: @escaping () -> Void) {
self.theme = theme self.theme = theme
self.strings = strings self.strings = strings
self.title = title self.title = title
@ -41,7 +56,7 @@ public class ItemListSingleLineInputItem: ListViewItem, ItemListItem {
self.type = type self.type = type
self.returnKeyType = returnKeyType self.returnKeyType = returnKeyType
self.spacing = spacing self.spacing = spacing
self.clearButton = clearButton self.clearType = clearType
self.enabled = enabled self.enabled = enabled
self.tag = tag self.tag = tag
self.sectionId = sectionId self.sectionId = sectionId
@ -153,7 +168,7 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg
self.textNode.textField.font = Font.regular(17.0) self.textNode.textField.font = Font.regular(17.0)
if let item = self.item { if let item = self.item {
self.textNode.textField.textColor = item.theme.list.itemPrimaryTextColor self.textNode.textField.textColor = item.theme.list.itemPrimaryTextColor
self.textNode.textField.keyboardAppearance = item.theme.chatList.searchBarKeyboardColor.keyboardAppearance self.textNode.textField.keyboardAppearance = item.theme.rootController.keyboardColor.keyboardAppearance
self.textNode.textField.tintColor = item.theme.list.itemAccentColor self.textNode.textField.tintColor = item.theme.list.itemAccentColor
self.textNode.textField.accessibilityHint = item.placeholder self.textNode.textField.accessibilityHint = item.placeholder
} }
@ -180,7 +195,7 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg
let leftInset: CGFloat = 16.0 + params.leftInset let leftInset: CGFloat = 16.0 + params.leftInset
var rightInset: CGFloat = 16.0 + params.rightInset var rightInset: CGFloat = 16.0 + params.rightInset
if item.clearButton { if item.clearType.hasButton {
rightInset += 32.0 rightInset += 32.0
} }
@ -210,7 +225,7 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg
strongSelf.backgroundNode.backgroundColor = item.theme.list.itemBlocksBackgroundColor strongSelf.backgroundNode.backgroundColor = item.theme.list.itemBlocksBackgroundColor
strongSelf.textNode.textField.textColor = item.theme.list.itemPrimaryTextColor strongSelf.textNode.textField.textColor = item.theme.list.itemPrimaryTextColor
strongSelf.textNode.textField.keyboardAppearance = item.theme.chatList.searchBarKeyboardColor.keyboardAppearance strongSelf.textNode.textField.keyboardAppearance = item.theme.rootController.keyboardColor.keyboardAppearance
strongSelf.textNode.textField.tintColor = item.theme.list.itemAccentColor strongSelf.textNode.textField.tintColor = item.theme.list.itemAccentColor
} }
@ -290,9 +305,7 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg
strongSelf.clearIconNode.frame = CGRect(origin: CGPoint(x: params.width - params.rightInset - buttonSize.width + floor((buttonSize.width - image.size.width) / 2.0), y: floor((layout.contentSize.height - image.size.height) / 2.0)), size: image.size) strongSelf.clearIconNode.frame = CGRect(origin: CGPoint(x: params.width - params.rightInset - buttonSize.width + floor((buttonSize.width - image.size.width) / 2.0), y: floor((layout.contentSize.height - image.size.height) / 2.0)), size: image.size)
} }
strongSelf.clearIconNode.isHidden = !item.clearButton || item.text.isEmpty strongSelf.updateClearButtonVisibility()
strongSelf.clearButtonNode.isHidden = !item.clearButton || item.text.isEmpty
strongSelf.clearButtonNode.isAccessibilityElement = !strongSelf.clearButtonNode.isHidden
if strongSelf.backgroundNode.supernode == nil { if strongSelf.backgroundNode.supernode == nil {
strongSelf.insertSubnode(strongSelf.backgroundNode, at: 0) strongSelf.insertSubnode(strongSelf.backgroundNode, at: 0)
@ -334,6 +347,24 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg
} }
} }
private func updateClearButtonVisibility() {
guard let item = self.item else {
return
}
let isHidden: Bool
switch item.clearType {
case .none:
isHidden = true
case .always:
isHidden = item.text.isEmpty
case .onFocus:
isHidden = !self.textNode.textField.isFirstResponder || item.text.isEmpty
}
self.clearIconNode.isHidden = isHidden
self.clearButtonNode.isHidden = isHidden
self.clearButtonNode.isAccessibilityElement = isHidden
}
override public func animateInsertion(_ currentTimestamp: Double, duration: Double, short: Bool) { override public func animateInsertion(_ currentTimestamp: Double, duration: Double, short: Bool) {
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.4) self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.4)
} }
@ -392,10 +423,12 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg
@objc public func textFieldDidBeginEditing(_ textField: UITextField) { @objc public func textFieldDidBeginEditing(_ textField: UITextField) {
self.item?.updatedFocus?(true) self.item?.updatedFocus?(true)
self.updateClearButtonVisibility()
} }
@objc public func textFieldDidEndEditing(_ textField: UITextField) { @objc public func textFieldDidEndEditing(_ textField: UITextField) {
self.item?.updatedFocus?(false) self.item?.updatedFocus?(false)
self.updateClearButtonVisibility()
} }
public func animateError() { public func animateError() {

View File

@ -7,6 +7,7 @@
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
096C16E62317412A0047887D /* LegacyICloudFilePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 096C16E5231741290047887D /* LegacyICloudFilePicker.swift */; };
D03E3F6E2304C4840049C28B /* LegacyMediaPickerUI.h in Headers */ = {isa = PBXBuildFile; fileRef = D03E3F6C2304C4840049C28B /* LegacyMediaPickerUI.h */; settings = {ATTRIBUTES = (Public, ); }; }; D03E3F6E2304C4840049C28B /* LegacyMediaPickerUI.h in Headers */ = {isa = PBXBuildFile; fileRef = D03E3F6C2304C4840049C28B /* LegacyMediaPickerUI.h */; settings = {ATTRIBUTES = (Public, ); }; };
D03E3F802304C50E0049C28B /* LegacyMediaPickers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03E3F782304C50D0049C28B /* LegacyMediaPickers.swift */; }; D03E3F802304C50E0049C28B /* LegacyMediaPickers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03E3F782304C50D0049C28B /* LegacyMediaPickers.swift */; };
D03E3F812304C50E0049C28B /* LegacyImageProcessors.h in Headers */ = {isa = PBXBuildFile; fileRef = D03E3F792304C50D0049C28B /* LegacyImageProcessors.h */; settings = {ATTRIBUTES = (Public, ); }; }; D03E3F812304C50E0049C28B /* LegacyImageProcessors.h in Headers */ = {isa = PBXBuildFile; fileRef = D03E3F792304C50D0049C28B /* LegacyImageProcessors.h */; settings = {ATTRIBUTES = (Public, ); }; };
@ -32,6 +33,7 @@
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
096C16E5231741290047887D /* LegacyICloudFilePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegacyICloudFilePicker.swift; sourceTree = "<group>"; };
D03E3F692304C4840049C28B /* LegacyMediaPickerUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LegacyMediaPickerUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D03E3F692304C4840049C28B /* LegacyMediaPickerUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LegacyMediaPickerUI.framework; sourceTree = BUILT_PRODUCTS_DIR; };
D03E3F6C2304C4840049C28B /* LegacyMediaPickerUI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LegacyMediaPickerUI.h; sourceTree = "<group>"; }; D03E3F6C2304C4840049C28B /* LegacyMediaPickerUI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LegacyMediaPickerUI.h; sourceTree = "<group>"; };
D03E3F6D2304C4840049C28B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; D03E3F6D2304C4840049C28B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@ -111,6 +113,7 @@
D03E3F782304C50D0049C28B /* LegacyMediaPickers.swift */, D03E3F782304C50D0049C28B /* LegacyMediaPickers.swift */,
D03E3F7B2304C50D0049C28B /* LegacySuggestionContext.swift */, D03E3F7B2304C50D0049C28B /* LegacySuggestionContext.swift */,
D03E3F7F2304C50D0049C28B /* LegacyWallpaperPicker.swift */, D03E3F7F2304C50D0049C28B /* LegacyWallpaperPicker.swift */,
096C16E5231741290047887D /* LegacyICloudFilePicker.swift */,
D03E3F6C2304C4840049C28B /* LegacyMediaPickerUI.h */, D03E3F6C2304C4840049C28B /* LegacyMediaPickerUI.h */,
); );
path = Sources; path = Sources;
@ -219,6 +222,7 @@
files = ( files = (
D03E3F872304C50E0049C28B /* LegacyWallpaperPicker.swift in Sources */, D03E3F872304C50E0049C28B /* LegacyWallpaperPicker.swift in Sources */,
D03E3F842304C50E0049C28B /* LegacyImagePicker.swift in Sources */, D03E3F842304C50E0049C28B /* LegacyImagePicker.swift in Sources */,
096C16E62317412A0047887D /* LegacyICloudFilePicker.swift in Sources */,
D03E3F822304C50E0049C28B /* LegacyAttachmentMenu.swift in Sources */, D03E3F822304C50E0049C28B /* LegacyAttachmentMenu.swift in Sources */,
D03E3F852304C50E0049C28B /* LegacyImageProcessors.m in Sources */, D03E3F852304C50E0049C28B /* LegacyImageProcessors.m in Sources */,
D03E3F802304C50E0049C28B /* LegacyMediaPickers.swift in Sources */, D03E3F802304C50E0049C28B /* LegacyMediaPickers.swift in Sources */,

View File

@ -30,7 +30,21 @@ private final class LegacyICloudFileController: LegacyController, UIDocumentPick
} }
} }
func legacyICloudFileController(theme: PresentationTheme, completion: @escaping ([URL]) -> Void) -> ViewController { public enum LegacyICloudFilePickerMode {
case `default`
case `import`
var documentPickerMode: UIDocumentPickerMode {
switch self {
case .default:
return .open
case .import:
return .import
}
}
}
public func legacyICloudFilePicker(theme: PresentationTheme, mode: LegacyICloudFilePickerMode = .default, documentTypes: [String] = ["public.item"], completion: @escaping ([URL]) -> Void) -> ViewController {
var dismissImpl: (() -> Void)? var dismissImpl: (() -> Void)?
let legacyController = LegacyICloudFileController(presentation: .modal(animateIn: true), theme: theme, completion: { urls in let legacyController = LegacyICloudFileController(presentation: .modal(animateIn: true), theme: theme, completion: { urls in
dismissImpl?() dismissImpl?()
@ -38,25 +52,9 @@ func legacyICloudFileController(theme: PresentationTheme, completion: @escaping
}) })
legacyController.statusBar.statusBarStyle = .Black legacyController.statusBar.statusBarStyle = .Black
let documentTypes: [String] = [ let controller = UIDocumentPickerViewController(documentTypes: documentTypes, in: mode.documentPickerMode)
"public.item"
// "public.composite-content",
// "public.text",
// "public.image",
// "public.audio",
// "public.video",
// "public.movie",
// "public.font",
// "public.data",
// "org.telegram.Telegram.webp",
// "com.apple.iwork.pages.pages",
// "com.apple.iwork.numbers.numbers",
// "com.apple.iwork.keynote.key"
]
let controller = UIDocumentPickerViewController(documentTypes: documentTypes, in: .open)
controller.delegate = legacyController controller.delegate = legacyController
if #available(iOSApplicationExtension 11.0, iOS 11.0, *) { if #available(iOSApplicationExtension 11.0, iOS 11.0, *), case .default = mode {
controller.allowsMultipleSelection = true controller.allowsMultipleSelection = true
} }

View File

@ -82,7 +82,7 @@ final class PasscodeSetupControllerNode: ASDisplayNode {
passcodeType = .digits6 passcodeType = .digits6
} }
self.inputFieldNode = PasscodeEntryInputFieldNode(color: self.presentationData.theme.list.itemPrimaryTextColor, accentColor: self.presentationData.theme.list.itemAccentColor, fieldType: passcodeType, keyboardAppearance: self.presentationData.theme.chatList.searchBarKeyboardColor.keyboardAppearance) self.inputFieldNode = PasscodeEntryInputFieldNode(color: self.presentationData.theme.list.itemPrimaryTextColor, accentColor: self.presentationData.theme.list.itemAccentColor, fieldType: passcodeType, keyboardAppearance: self.presentationData.theme.rootController.keyboardColor.keyboardAppearance)
self.inputFieldBackgroundNode = ASImageNode() self.inputFieldBackgroundNode = ASImageNode()
self.inputFieldBackgroundNode.alpha = passcodeType == .alphanumeric ? 1.0 : 0.0 self.inputFieldBackgroundNode.alpha = passcodeType == .alphanumeric ? 1.0 : 0.0
self.inputFieldBackgroundNode.contentMode = .scaleToFill self.inputFieldBackgroundNode.contentMode = .scaleToFill

View File

@ -143,7 +143,7 @@ final class FormControllerTextInputItemNode: FormBlockItemNode<FormControllerTex
self.textField.textField.returnKeyType = item.returnKeyType self.textField.textField.returnKeyType = item.returnKeyType
} }
self.textField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance self.textField.textField.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance
self.textField.textField.tintColor = theme.list.itemAccentColor self.textField.textField.tintColor = theme.list.itemAccentColor
let attributedPlaceholder = NSAttributedString(string: item.placeholder, font: textFont, textColor: theme.list.itemPlaceholderTextColor) let attributedPlaceholder = NSAttributedString(string: item.placeholder, font: textFont, textColor: theme.list.itemPlaceholderTextColor)

View File

@ -46,7 +46,7 @@ final class SecureIdAuthPasswordOptionContentNode: ASDisplayNode, SecureIdAuthCo
self.inputField = TextFieldNode() self.inputField = TextFieldNode()
self.inputButtonNode = HighlightableButtonNode() self.inputButtonNode = HighlightableButtonNode()
self.inputActivityNode = ActivityIndicator(type: .custom(theme.list.itemAccentColor, 18.0, 1.5, false)) self.inputActivityNode = ActivityIndicator(type: .custom(theme.list.freeInputField.controlColor, 18.0, 1.5, false))
if let image = generateTintedImage(image: UIImage(bundleImageName: "Secure ID/PasswordHelpIcon"), color: theme.list.freeInputField.controlColor) { if let image = generateTintedImage(image: UIImage(bundleImageName: "Secure ID/PasswordHelpIcon"), color: theme.list.freeInputField.controlColor) {
self.inputButtonNode.setImage(image, for: []) self.inputButtonNode.setImage(image, for: [])
@ -59,7 +59,7 @@ final class SecureIdAuthPasswordOptionContentNode: ASDisplayNode, SecureIdAuthCo
self.inputField.textField.font = passwordFont self.inputField.textField.font = passwordFont
self.inputField.textField.textColor = theme.list.freeInputField.primaryColor self.inputField.textField.textColor = theme.list.freeInputField.primaryColor
self.inputField.textField.attributedPlaceholder = NSAttributedString(string: hint.isEmpty ? strings.LoginPassword_PasswordPlaceholder : hint, font: passwordFont, textColor: theme.list.freeInputField.placeholderColor) self.inputField.textField.attributedPlaceholder = NSAttributedString(string: hint.isEmpty ? strings.LoginPassword_PasswordPlaceholder : hint, font: passwordFont, textColor: theme.list.freeInputField.placeholderColor)
self.inputField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance self.inputField.textField.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance
self.inputField.textField.tintColor = theme.list.itemAccentColor self.inputField.textField.tintColor = theme.list.itemAccentColor
self.buttonNode = HighlightableButtonNode() self.buttonNode = HighlightableButtonNode()

View File

@ -126,8 +126,8 @@ final class SecureIdValueFormPhoneItemNode: FormBlockItemNode<SecureIdValueFormP
self.phoneInputNode.countryCodeField.textField.tintColor = theme.list.itemAccentColor self.phoneInputNode.countryCodeField.textField.tintColor = theme.list.itemAccentColor
self.phoneInputNode.numberField.textField.tintColor = theme.list.itemAccentColor self.phoneInputNode.numberField.textField.tintColor = theme.list.itemAccentColor
self.phoneInputNode.countryCodeField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance self.phoneInputNode.countryCodeField.textField.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance
self.phoneInputNode.numberField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance self.phoneInputNode.numberField.textField.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance
} }
self.item = item self.item = item

View File

@ -59,7 +59,7 @@ final class SetupTwoStepVerificationContentNode: ASDisplayNode, UITextFieldDeleg
self.inputNode.textField.font = Font.regular(22.0) self.inputNode.textField.font = Font.regular(22.0)
self.inputNode.textField.attributedPlaceholder = NSAttributedString(string: placeholder, font: Font.regular(22.0), textColor: theme.list.itemPlaceholderTextColor) self.inputNode.textField.attributedPlaceholder = NSAttributedString(string: placeholder, font: Font.regular(22.0), textColor: theme.list.itemPlaceholderTextColor)
self.inputNode.textField.textAlignment = .center self.inputNode.textField.textAlignment = .center
self.inputNode.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance self.inputNode.textField.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance
self.inputNode.textField.tintColor = theme.list.itemAccentColor self.inputNode.textField.tintColor = theme.list.itemAccentColor
switch inputType { switch inputType {
case .password: case .password:
@ -126,7 +126,7 @@ final class SetupTwoStepVerificationContentNode: ASDisplayNode, UITextFieldDeleg
func updatePresentationData(_ presentationData: PresentationData) { func updatePresentationData(_ presentationData: PresentationData) {
self.theme = presentationData.theme self.theme = presentationData.theme
self.inputNode.textField.keyboardAppearance = self.theme.chatList.searchBarKeyboardColor.keyboardAppearance self.inputNode.textField.keyboardAppearance = self.theme.rootController.keyboardColor.keyboardAppearance
self.inputSeparator.backgroundColor = self.theme.list.itemPlainSeparatorColor self.inputSeparator.backgroundColor = self.theme.list.itemPlainSeparatorColor
self.inputNode.textField.tintColor = self.theme.list.itemAccentColor self.inputNode.textField.tintColor = self.theme.list.itemAccentColor
} }

View File

@ -372,7 +372,7 @@ private enum ChannelAdminEntry: ItemListNodeEntry {
} }
return ItemListSectionHeaderItem(theme: theme, text: text, accessoryText: accessoryText, sectionId: self.section) return ItemListSectionHeaderItem(theme: theme, text: text, accessoryText: accessoryText, sectionId: self.section)
case let .rank(theme, strings, placeholder, text, enabled): case let .rank(theme, strings, placeholder, text, enabled):
return ItemListSingleLineInputItem(theme: theme, strings: strings, title: NSAttributedString(string: "", textColor: .black), text: text, placeholder: placeholder, type: .regular(capitalization: false, autocorrection: true), spacing: 0.0, clearButton: enabled, enabled: enabled, tag: ChannelAdminEntryTag.rank, sectionId: self.section, textUpdated: { updatedText in return ItemListSingleLineInputItem(theme: theme, strings: strings, title: NSAttributedString(string: "", textColor: .black), text: text, placeholder: placeholder, type: .regular(capitalization: false, autocorrection: true), spacing: 0.0, clearType: enabled ? .always : .none, enabled: enabled, tag: ChannelAdminEntryTag.rank, sectionId: self.section, textUpdated: { updatedText in
arguments.updateRank(text, updatedText) arguments.updateRank(text, updatedText)
}, shouldUpdateText: { text in }, shouldUpdateText: { text in
if text.containsEmoji { if text.containsEmoji {

View File

@ -845,7 +845,7 @@ public func channelInfoController(context: AccountContext, peerId: PeerId) -> Vi
} }
}, openStats: { }, openStats: {
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
var urlSignal = channelStatsUrl(postbox: context.account.postbox, network: context.account.network, peerId: peerId, params: "", darkTheme: presentationData.theme.chatList.searchBarKeyboardColor.keyboardAppearance == .dark) var urlSignal = channelStatsUrl(postbox: context.account.postbox, network: context.account.network, peerId: peerId, params: "", darkTheme: presentationData.theme.rootController.keyboardColor.keyboardAppearance == .dark)
var cancelImpl: (() -> Void)? var cancelImpl: (() -> Void)?
let progressSignal = Signal<Never, NoError> { subscriber in let progressSignal = Signal<Never, NoError> { subscriber in

View File

@ -80,7 +80,7 @@ private final class ChannelOwnershipTransferPasswordFieldNode: ASDisplayNode, UI
self.textInputNode.textField.textColor = self.theme.list.itemPrimaryTextColor self.textInputNode.textField.textColor = self.theme.list.itemPrimaryTextColor
self.textInputNode.textField.isSecureTextEntry = true self.textInputNode.textField.isSecureTextEntry = true
self.textInputNode.textField.returnKeyType = .done self.textInputNode.textField.returnKeyType = .done
self.textInputNode.textField.keyboardAppearance = self.theme.chatList.searchBarKeyboardColor.keyboardAppearance self.textInputNode.textField.keyboardAppearance = self.theme.rootController.keyboardColor.keyboardAppearance
self.textInputNode.clipsToBounds = true self.textInputNode.clipsToBounds = true
self.textInputNode.textField.delegate = self self.textInputNode.textField.delegate = self
self.textInputNode.textField.addTarget(self, action: #selector(self.textFieldTextChanged(_:)), for: .editingChanged) self.textInputNode.textField.addTarget(self, action: #selector(self.textFieldTextChanged(_:)), for: .editingChanged)
@ -92,7 +92,7 @@ private final class ChannelOwnershipTransferPasswordFieldNode: ASDisplayNode, UI
self.theme = theme self.theme = theme
self.backgroundNode.image = generateStretchableFilledCircleImage(diameter: 16.0, color: theme.actionSheet.inputHollowBackgroundColor, strokeColor: theme.actionSheet.inputBorderColor, strokeWidth: UIScreenPixel) self.backgroundNode.image = generateStretchableFilledCircleImage(diameter: 16.0, color: theme.actionSheet.inputHollowBackgroundColor, strokeColor: theme.actionSheet.inputBorderColor, strokeWidth: UIScreenPixel)
self.textInputNode.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance self.textInputNode.textField.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance
self.textInputNode.textField.textColor = theme.list.itemPrimaryTextColor self.textInputNode.textField.textColor = theme.list.itemPrimaryTextColor
self.textInputNode.textField.typingAttributes = [NSAttributedString.Key.font: Font.regular(14.0), NSAttributedString.Key.foregroundColor: theme.actionSheet.inputTextColor] self.textInputNode.textField.typingAttributes = [NSAttributedString.Key.font: Font.regular(14.0), NSAttributedString.Key.foregroundColor: theme.actionSheet.inputTextColor]
self.textInputNode.textField.tintColor = theme.list.itemAccentColor self.textInputNode.textField.tintColor = theme.list.itemAccentColor

View File

@ -90,7 +90,7 @@ final class ChannelStatsControllerNode: ViewControllerTracingNode, WKNavigationD
} }
} }
} }
self.refreshDisposable.set((channelStatsUrl(postbox: self.context.account.postbox, network: self.context.account.network, peerId: self.peerId, params: params, darkTheme: self.presentationData.theme.chatList.searchBarKeyboardColor.keyboardAppearance == .dark) self.refreshDisposable.set((channelStatsUrl(postbox: self.context.account.postbox, network: self.context.account.network, peerId: self.peerId, params: params, darkTheme: self.presentationData.theme.rootController.keyboardColor.keyboardAppearance == .dark)
|> deliverOnMainQueue).start(next: { [weak self] url in |> deliverOnMainQueue).start(next: { [weak self] url in
guard let strongSelf = self else { guard let strongSelf = self else {
return return

View File

@ -287,7 +287,7 @@ private enum ChannelVisibilityEntry: ItemListNodeEntry {
} }
}, tag: ChannelVisibilityEntryTag.privateLink) }, tag: ChannelVisibilityEntryTag.privateLink)
case let .editablePublicLink(theme, strings, placeholder, currentText): case let .editablePublicLink(theme, strings, placeholder, currentText):
return ItemListSingleLineInputItem(theme: theme, strings: strings, title: NSAttributedString(string: "t.me/", textColor: theme.list.itemPrimaryTextColor), text: currentText, placeholder: placeholder, type: .regular(capitalization: false, autocorrection: false), clearButton: true, tag: ChannelVisibilityEntryTag.publicLink, sectionId: self.section, textUpdated: { updatedText in return ItemListSingleLineInputItem(theme: theme, strings: strings, title: NSAttributedString(string: "t.me/", textColor: theme.list.itemPrimaryTextColor), text: currentText, placeholder: placeholder, type: .regular(capitalization: false, autocorrection: false), clearType: .always, tag: ChannelVisibilityEntryTag.publicLink, sectionId: self.section, textUpdated: { updatedText in
arguments.updatePublicLinkText(currentText, updatedText) arguments.updatePublicLinkText(currentText, updatedText)
}, updatedFocus: { focus in }, updatedFocus: { focus in
if focus { if focus {

View File

@ -209,7 +209,7 @@ private enum GroupStickerPackEntry: ItemListNodeEntry {
func item(_ arguments: GroupStickerPackSetupControllerArguments) -> ListViewItem { func item(_ arguments: GroupStickerPackSetupControllerArguments) -> ListViewItem {
switch self { switch self {
case let .search(theme, strings, prefix, placeholder, value): case let .search(theme, strings, prefix, placeholder, value):
return ItemListSingleLineInputItem(theme: theme, strings: strings, title: NSAttributedString(string: prefix, textColor: theme.list.itemPrimaryTextColor), text: value, placeholder: placeholder, type: .regular(capitalization: false, autocorrection: false), spacing: 0.0, clearButton: true, tag: nil, sectionId: self.section, textUpdated: { value in return ItemListSingleLineInputItem(theme: theme, strings: strings, title: NSAttributedString(string: prefix, textColor: theme.list.itemPrimaryTextColor), text: value, placeholder: placeholder, type: .regular(capitalization: false, autocorrection: false), spacing: 0.0, clearType: .always, tag: nil, sectionId: self.section, textUpdated: { value in
arguments.updateSearchText(value) arguments.updateSearchText(value)
}, processPaste: { text in }, processPaste: { text in
if let url = (URL(string: text) ?? URL(string: "http://" + text)), url.host == "t.me" || url.host == "telegram.me" { if let url = (URL(string: text) ?? URL(string: "http://" + text)), url.host == "t.me" || url.host == "telegram.me" {

View File

@ -183,7 +183,7 @@ class UserInfoEditingPhoneItemNode: ItemListRevealOptionsItemNode, ItemListItemN
if let item = self.item { if let item = self.item {
self.phoneNode.numberField?.textField.textColor = item.theme.list.itemPrimaryTextColor self.phoneNode.numberField?.textField.textColor = item.theme.list.itemPrimaryTextColor
self.phoneNode.numberField?.textField.keyboardAppearance = item.theme.chatList.searchBarKeyboardColor.keyboardAppearance self.phoneNode.numberField?.textField.keyboardAppearance = item.theme.rootController.keyboardColor.keyboardAppearance
self.phoneNode.numberField?.textField.tintColor = item.theme.list.itemAccentColor self.phoneNode.numberField?.textField.tintColor = item.theme.list.itemAccentColor
} }
} }
@ -233,7 +233,7 @@ class UserInfoEditingPhoneItemNode: ItemListRevealOptionsItemNode, ItemListItemN
strongSelf.labelSeparatorNode.backgroundColor = itemSeparatorColor strongSelf.labelSeparatorNode.backgroundColor = itemSeparatorColor
strongSelf.phoneNode.numberField?.textField.textColor = updatedTheme.list.itemPrimaryTextColor strongSelf.phoneNode.numberField?.textField.textColor = updatedTheme.list.itemPrimaryTextColor
strongSelf.phoneNode.numberField?.textField.keyboardAppearance = updatedTheme.chatList.searchBarKeyboardColor.keyboardAppearance strongSelf.phoneNode.numberField?.textField.keyboardAppearance = updatedTheme.rootController.keyboardColor.keyboardAppearance
strongSelf.phoneNode.numberField?.textField.tintColor = item.theme.list.itemAccentColor strongSelf.phoneNode.numberField?.textField.tintColor = item.theme.list.itemAccentColor
strongSelf.clearButton.setImage(generateClearIcon(color: updatedTheme.list.inputClearButtonColor), for: []) strongSelf.clearButton.setImage(generateClearIcon(color: updatedTheme.list.inputClearButtonColor), for: [])

View File

@ -161,7 +161,7 @@ public final class SearchBarNodeTheme: Equatable {
self.inputIcon = theme.rootController.navigationSearchBar.inputIconColor self.inputIcon = theme.rootController.navigationSearchBar.inputIconColor
self.inputClear = theme.rootController.navigationSearchBar.inputClearButtonColor self.inputClear = theme.rootController.navigationSearchBar.inputClearButtonColor
self.accent = theme.rootController.navigationSearchBar.accentColor self.accent = theme.rootController.navigationSearchBar.accentColor
self.keyboard = theme.chatList.searchBarKeyboardColor self.keyboard = theme.rootController.keyboardColor
} }
public static func ==(lhs: SearchBarNodeTheme, rhs: SearchBarNodeTheme) -> Bool { public static func ==(lhs: SearchBarNodeTheme, rhs: SearchBarNodeTheme) -> Bool {

View File

@ -127,10 +127,10 @@ final class ChangePhoneNumberControllerNode: ASDisplayNode {
self.phoneInputNode = PhoneInputNode(fontSize: 17.0) self.phoneInputNode = PhoneInputNode(fontSize: 17.0)
self.phoneInputNode.countryCodeField.textField.textColor = self.presentationData.theme.list.itemPrimaryTextColor self.phoneInputNode.countryCodeField.textField.textColor = self.presentationData.theme.list.itemPrimaryTextColor
self.phoneInputNode.countryCodeField.textField.keyboardAppearance = self.presentationData.theme.chatList.searchBarKeyboardColor.keyboardAppearance self.phoneInputNode.countryCodeField.textField.keyboardAppearance = self.presentationData.theme.rootController.keyboardColor.keyboardAppearance
self.phoneInputNode.countryCodeField.textField.tintColor = self.presentationData.theme.list.itemAccentColor self.phoneInputNode.countryCodeField.textField.tintColor = self.presentationData.theme.list.itemAccentColor
self.phoneInputNode.numberField.textField.textColor = self.presentationData.theme.list.itemPrimaryTextColor self.phoneInputNode.numberField.textField.textColor = self.presentationData.theme.list.itemPrimaryTextColor
self.phoneInputNode.numberField.textField.keyboardAppearance = self.presentationData.theme.chatList.searchBarKeyboardColor.keyboardAppearance self.phoneInputNode.numberField.textField.keyboardAppearance = self.presentationData.theme.rootController.keyboardColor.keyboardAppearance
self.phoneInputNode.numberField.textField.tintColor = self.presentationData.theme.list.itemAccentColor self.phoneInputNode.numberField.textField.tintColor = self.presentationData.theme.list.itemAccentColor
super.init() super.init()

View File

@ -234,7 +234,7 @@ final class TabBarAccountSwitchControllerNode: ViewControllerTracingNode {
self.effectView = UIVisualEffectView() self.effectView = UIVisualEffectView()
if #available(iOS 9.0, *) { if #available(iOS 9.0, *) {
} else { } else {
if presentationData.theme.chatList.searchBarKeyboardColor == .dark { if presentationData.theme.rootController.keyboardColor == .dark {
self.effectView.effect = UIBlurEffect(style: .dark) self.effectView.effect = UIBlurEffect(style: .dark)
} else { } else {
self.effectView.effect = UIBlurEffect(style: .light) self.effectView.effect = UIBlurEffect(style: .light)
@ -244,7 +244,7 @@ final class TabBarAccountSwitchControllerNode: ViewControllerTracingNode {
self.dimNode = ASDisplayNode() self.dimNode = ASDisplayNode()
self.dimNode.alpha = 1.0 self.dimNode.alpha = 1.0
if presentationData.theme.chatList.searchBarKeyboardColor == .light { if presentationData.theme.rootController.keyboardColor == .light {
self.dimNode.backgroundColor = UIColor(white: 0.0, alpha: 0.04) self.dimNode.backgroundColor = UIColor(white: 0.0, alpha: 0.04)
} else { } else {
self.dimNode.backgroundColor = presentationData.theme.chatList.backgroundColor.withAlphaComponent(0.2) self.dimNode.backgroundColor = presentationData.theme.chatList.backgroundColor.withAlphaComponent(0.2)
@ -287,7 +287,7 @@ final class TabBarAccountSwitchControllerNode: ViewControllerTracingNode {
func animateIn() { func animateIn() {
UIView.animate(withDuration: 0.3, animations: { UIView.animate(withDuration: 0.3, animations: {
if #available(iOS 9.0, *) { if #available(iOS 9.0, *) {
if self.presentationData.theme.chatList.searchBarKeyboardColor == .dark { if self.presentationData.theme.rootController.keyboardColor == .dark {
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) { if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
self.effectView.effect = UIBlurEffect(style: .regular) self.effectView.effect = UIBlurEffect(style: .regular)
if self.effectView.subviews.count == 2 { if self.effectView.subviews.count == 2 {
@ -310,7 +310,7 @@ final class TabBarAccountSwitchControllerNode: ViewControllerTracingNode {
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
if strongSelf.presentationData.theme.chatList.searchBarKeyboardColor == .dark { if strongSelf.presentationData.theme.rootController.keyboardColor == .dark {
if strongSelf.effectView.subviews.count == 2 { if strongSelf.effectView.subviews.count == 2 {
strongSelf.effectView.subviews[1].isHidden = true strongSelf.effectView.subviews[1].isHidden = true
} }

View File

@ -8,70 +8,79 @@ import TelegramPresentationData
import TelegramUIPreferences import TelegramUIPreferences
import ItemListUI import ItemListUI
import AlertUI import AlertUI
import LegacyMediaPickerUI
import AccountContext import AccountContext
private final class EditThemeControllerArguments { private final class EditThemeControllerArguments {
let context: AccountContext let context: AccountContext
let updateState: ((EditThemeControllerState) -> EditThemeControllerState) -> Void let updateState: ((EditThemeControllerState) -> EditThemeControllerState) -> Void
let openFile: () -> Void
init(context: AccountContext, updateState: @escaping ((EditThemeControllerState) -> EditThemeControllerState) -> Void) { init(context: AccountContext, updateState: @escaping ((EditThemeControllerState) -> EditThemeControllerState) -> Void, openFile: @escaping () -> Void) {
self.context = context self.context = context
self.updateState = updateState self.updateState = updateState
self.openFile = openFile
}
}
private enum EditThemeEntryTag: ItemListItemTag {
case title
func isEqual(to other: ItemListItemTag) -> Bool {
if let other = other as? EditThemeEntryTag, self == other {
return true
} else {
return false
}
} }
} }
private enum EditThemeControllerSection: Int32 { private enum EditThemeControllerSection: Int32 {
case chatPreview
case info case info
case chatPreview
} }
private enum EditThemeControllerEntry: ItemListNodeEntry { private enum EditThemeControllerEntry: ItemListNodeEntry {
case chatPreviewHeader(PresentationTheme, String) case title(PresentationTheme, PresentationStrings, String, String, Bool)
case chatPreview(PresentationTheme, PresentationTheme, TelegramWallpaper, PresentationFontSize, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder)
case title(PresentationTheme, PresentationStrings, String, String)
case slug(PresentationTheme, PresentationStrings, String, String, Bool) case slug(PresentationTheme, PresentationStrings, String, String, Bool)
case slugInfo(PresentationTheme, String) case slugInfo(PresentationTheme, String)
case chatPreviewHeader(PresentationTheme, String)
case chatPreview(PresentationTheme, PresentationTheme, TelegramWallpaper, PresentationFontSize, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder)
case uploadTheme(PresentationTheme, String)
case uploadInfo(PresentationTheme, String)
var section: ItemListSectionId { var section: ItemListSectionId {
switch self { switch self {
case .chatPreviewHeader, .chatPreview:
return EditThemeControllerSection.chatPreview.rawValue
case .title, .slug, .slugInfo: case .title, .slug, .slugInfo:
return EditThemeControllerSection.info.rawValue return EditThemeControllerSection.info.rawValue
case .chatPreviewHeader, .chatPreview, .uploadTheme, .uploadInfo:
return EditThemeControllerSection.chatPreview.rawValue
} }
} }
var stableId: Int32 { var stableId: Int32 {
switch self { switch self {
case .chatPreviewHeader:
return 0
case .chatPreview:
return 1
case .title: case .title:
return 2 return 0
case .slug: case .slug:
return 3 return 1
case .slugInfo: case .slugInfo:
return 2
case .chatPreviewHeader:
return 3
case .chatPreview:
return 4 return 4
case .uploadTheme:
return 5
case .uploadInfo:
return 6
} }
} }
static func ==(lhs: EditThemeControllerEntry, rhs: EditThemeControllerEntry) -> Bool { static func ==(lhs: EditThemeControllerEntry, rhs: EditThemeControllerEntry) -> Bool {
switch lhs { switch lhs {
case let .chatPreviewHeader(lhsTheme, lhsText): case let .title(lhsTheme, lhsStrings, lhsTitle, lhsValue, lhsDone):
if case let .chatPreviewHeader(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { if case let .title(rhsTheme, rhsStrings, rhsTitle, rhsValue, rhsDone) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsTitle == rhsTitle, lhsValue == rhsValue, lhsDone == rhsDone {
return true
} else {
return false
}
case let .chatPreview(lhsTheme, lhsComponentTheme, lhsWallpaper, lhsFontSize, lhsStrings, lhsTimeFormat, lhsNameOrder):
if case let .chatPreview(rhsTheme, rhsComponentTheme, rhsWallpaper, rhsFontSize, rhsStrings, rhsTimeFormat, rhsNameOrder) = rhs, lhsComponentTheme === rhsComponentTheme, lhsTheme === rhsTheme, lhsWallpaper == rhsWallpaper, lhsFontSize == rhsFontSize, lhsStrings === rhsStrings, lhsTimeFormat == rhsTimeFormat, lhsNameOrder == rhsNameOrder {
return true
} else {
return false
}
case let .title(lhsTheme, lhsStrings, lhsTitle, lhsValue):
if case let .title(rhsTheme, rhsStrings, rhsTitle, rhsValue) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsTitle == rhsTitle, lhsValue == rhsValue {
return true return true
} else { } else {
return false return false
@ -88,6 +97,30 @@ private enum EditThemeControllerEntry: ItemListNodeEntry {
} else { } else {
return false return false
} }
case let .chatPreviewHeader(lhsTheme, lhsText):
if case let .chatPreviewHeader(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true
} else {
return false
}
case let .chatPreview(lhsTheme, lhsComponentTheme, lhsWallpaper, lhsFontSize, lhsStrings, lhsTimeFormat, lhsNameOrder):
if case let .chatPreview(rhsTheme, rhsComponentTheme, rhsWallpaper, rhsFontSize, rhsStrings, rhsTimeFormat, rhsNameOrder) = rhs, lhsComponentTheme === rhsComponentTheme, lhsTheme === rhsTheme, lhsWallpaper == rhsWallpaper, lhsFontSize == rhsFontSize, lhsStrings === rhsStrings, lhsTimeFormat == rhsTimeFormat, lhsNameOrder == rhsNameOrder {
return true
} else {
return false
}
case let .uploadTheme(lhsTheme, lhsText):
if case let .uploadTheme(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true
} else {
return false
}
case let .uploadInfo(lhsTheme, lhsText):
if case let .uploadInfo(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true
} else {
return false
}
} }
} }
@ -97,67 +130,109 @@ private enum EditThemeControllerEntry: ItemListNodeEntry {
func item(_ arguments: EditThemeControllerArguments) -> ListViewItem { func item(_ arguments: EditThemeControllerArguments) -> ListViewItem {
switch self { switch self {
case let .chatPreviewHeader(theme, text): case let .title(theme, strings, title, text, done):
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section) return ItemListSingleLineInputItem(theme: theme, strings: strings, title: NSAttributedString(), text: text, placeholder: title, type: .regular(capitalization: true, autocorrection: false), returnKeyType: done ? .done : .next, clearType: .onFocus, tag: EditThemeEntryTag.title, sectionId: self.section, textUpdated: { value in
case let .chatPreview(theme, componentTheme, wallpaper, fontSize, strings, dateTimeFormat, nameDisplayOrder):
return ThemeSettingsChatPreviewItem(context: arguments.context, theme: theme, componentTheme: componentTheme, strings: strings, sectionId: self.section, fontSize: fontSize, wallpaper: wallpaper, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder)
case let .title(theme, strings, title, text):
return ItemListSingleLineInputItem(theme: theme, strings: strings, title: NSAttributedString(), text: text, placeholder: title, sectionId: self.section, textUpdated: { value in
arguments.updateState { current in arguments.updateState { current in
var state = current var state = current
state.title = value state.title = value
return state return state
} }
}, action: {}) }, action: {
})
case let .slug(theme, strings, title, text, enabled): case let .slug(theme, strings, title, text, enabled):
return ItemListSingleLineInputItem(theme: theme, strings: strings, title: NSAttributedString(string: "t.me/addtheme/", textColor: theme.list.itemPrimaryTextColor), text: text, placeholder: title, type: .username, enabled: enabled, sectionId: self.section, textUpdated: { value in return ItemListSingleLineInputItem(theme: theme, strings: strings, title: NSAttributedString(string: "t.me/addtheme/", textColor: theme.list.itemPrimaryTextColor), text: text, placeholder: title, type: .username, clearType: .onFocus, enabled: enabled, sectionId: self.section, textUpdated: { value in
arguments.updateState { current in arguments.updateState { current in
var state = current var state = current
state.slug = value state.slug = value
return state return state
} }
}, action: {}) }, action: {
})
case let .slugInfo(theme, text): case let .slugInfo(theme, text):
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section) return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
case let .chatPreviewHeader(theme, text):
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
case let .chatPreview(theme, componentTheme, wallpaper, fontSize, strings, dateTimeFormat, nameDisplayOrder):
return ThemeSettingsChatPreviewItem(context: arguments.context, theme: theme, componentTheme: componentTheme, strings: strings, sectionId: self.section, fontSize: fontSize, wallpaper: wallpaper, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder)
case let .uploadTheme(theme, text):
return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
arguments.openFile()
})
case let .uploadInfo(theme, text):
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
} }
} }
} }
private struct EditThemeControllerState: Equatable { public enum EditThemeControllerMode: Equatable {
var title: String case create
var slug: String case edit(PresentationCloudTheme)
var isComplete: Bool {
if self.title.isEmpty || self.slug.isEmpty {
return false
}
return true
}
} }
private func EditThemeControllerEntries(presentationData: PresentationData, theme: PresentationTheme?, state: EditThemeControllerState) -> [EditThemeControllerEntry] { private struct EditThemeControllerState: Equatable {
var mode: EditThemeControllerMode
var title: String
var slug: String
var previewTheme: PresentationTheme
var updatedTheme: PresentationTheme?
var updating: Bool
}
private func editThemeControllerEntries(presentationData: PresentationData, state: EditThemeControllerState) -> [EditThemeControllerEntry] {
var entries: [EditThemeControllerEntry] = [] var entries: [EditThemeControllerEntry] = []
if let theme = theme { var isCreate = false
entries.append(.chatPreviewHeader(presentationData.theme, presentationData.strings.EditTheme_Preview.uppercased())) if case .create = state.mode {
entries.append(.chatPreview(presentationData.theme, theme, theme.chat.defaultWallpaper, presentationData.fontSize, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder)) isCreate = true
}
entries.append(.title(presentationData.theme, presentationData.strings, presentationData.strings.EditTheme_Title, state.title, isCreate))
if case .edit = state.mode {
entries.append(.slug(presentationData.theme, presentationData.strings, presentationData.strings.EditTheme_ShortLink, state.slug, true))
entries.append(.slugInfo(presentationData.theme, presentationData.strings.EditTheme_ShortLinkInfo))
} }
entries.append(.title(presentationData.theme, presentationData.strings, presentationData.strings.EditTheme_Title, state.title)) entries.append(.chatPreviewHeader(presentationData.theme, presentationData.strings.EditTheme_Preview.uppercased()))
entries.append(.slug(presentationData.theme, presentationData.strings, presentationData.strings.EditTheme_ShortLink, state.slug, true)) entries.append(.chatPreview(presentationData.theme, state.previewTheme, state.previewTheme.chat.defaultWallpaper, presentationData.fontSize, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder))
entries.append(.slugInfo(presentationData.theme, presentationData.strings.EditTheme_ShortLinkInfo))
let uploadText: String
let uploadInfo: String
switch state.mode {
case .create:
uploadText = presentationData.strings.EditTheme_UploadNewTheme
uploadInfo = presentationData.strings.EditTheme_UploadNewInfo
case let .edit(theme):
if let _ = theme.theme.file {
uploadText = presentationData.strings.EditTheme_UploadEditedTheme
uploadInfo = presentationData.strings.EditTheme_UploadEditedInfo
} else {
uploadText = presentationData.strings.EditTheme_UploadNewTheme
uploadInfo = presentationData.strings.EditTheme_UploadNewInfo
}
}
entries.append(.uploadTheme(presentationData.theme, uploadText))
entries.append(.uploadInfo(presentationData.theme, uploadInfo))
return entries return entries
} }
public enum EditThemeControllerMode { public func editThemeController(context: AccountContext, mode: EditThemeControllerMode, navigateToChat: ((PeerId) -> Void)? = nil) -> ViewController {
case createNew let initialState: EditThemeControllerState
case createForExisting(TelegramTheme) switch mode {
case edit(TelegramTheme) case .create:
} let presentationData = context.sharedContext.currentPresentationData.with { $0 }
initialState = EditThemeControllerState(mode: mode, title: "", slug: "", previewTheme: presentationData.theme.withUpdated(name: "", author: nil, defaultWallpaper: presentationData.chatWallpaper), updatedTheme: nil, updating: false)
public func editThemeController(context: AccountContext, theme: TelegramTheme) -> ViewController { case let .edit(theme):
let initialState = EditThemeControllerState(title: theme.title, slug: theme.slug) let previewTheme: PresentationTheme
if let file = theme.theme.file, let path = context.sharedContext.accountManager.mediaBox.completedResourcePath(file.resource), let data = try? Data(contentsOf: URL(fileURLWithPath: path)), let theme = makePresentationTheme(data: data, resolvedWallpaper: theme.resolvedWallpaper) {
previewTheme = theme
} else {
previewTheme = context.sharedContext.currentPresentationData.with { $0 }.theme
}
initialState = EditThemeControllerState(mode: mode, title: theme.theme.title, slug: theme.theme.slug, previewTheme: previewTheme, updatedTheme: nil, updating: false)
}
let statePromise = ValuePromise(initialState, ignoreRepeated: true) let statePromise = ValuePromise(initialState, ignoreRepeated: true)
let stateValue = Atomic(value: initialState) let stateValue = Atomic(value: initialState)
let updateState: ((EditThemeControllerState) -> EditThemeControllerState) -> Void = { f in let updateState: ((EditThemeControllerState) -> EditThemeControllerState) -> Void = { f in
@ -170,28 +245,153 @@ public func editThemeController(context: AccountContext, theme: TelegramTheme) -
let arguments = EditThemeControllerArguments(context: context, updateState: { f in let arguments = EditThemeControllerArguments(context: context, updateState: { f in
updateState(f) updateState(f)
}, openFile: {
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let controller = legacyICloudFilePicker(theme: presentationData.theme, mode: .import, documentTypes: ["org.telegram.Telegram-iOS.theme"], completion: { urls in
if let url = urls.first, let data = try? Data(contentsOf: url), let theme = makePresentationTheme(data: data) {
updateState { current in
var state = current
state.previewTheme = theme
state.updatedTheme = theme
return state
}
} else {
presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.EditTheme_FileReadError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
}
})
presentControllerImpl?(controller, nil)
}) })
var previewTheme: PresentationTheme?
if let file = theme.file, let path = context.sharedContext.accountManager.mediaBox.completedResourcePath(file.resource), let data = try? Data(contentsOf: URL(fileURLWithPath: path)), let theme = makePresentationTheme(data: data) {
previewTheme = theme
}
let signal = combineLatest(queue: .mainQueue(), context.sharedContext.presentationData, statePromise.get()) let signal = combineLatest(queue: .mainQueue(), context.sharedContext.presentationData, statePromise.get())
|> map { presentationData, state -> (ItemListControllerState, (ItemListNodeState<EditThemeControllerEntry>, EditThemeControllerEntry.ItemGenerationArguments)) in |> map { presentationData, state -> (ItemListControllerState, (ItemListNodeState<EditThemeControllerEntry>, EditThemeControllerEntry.ItemGenerationArguments)) in
let leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: { let leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: {
dismissImpl?() dismissImpl?()
}) })
let rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Done), style: .bold, enabled: state.isComplete, action: {
//let _ = (updateTheme(account: context.account, resource: resource, title: state.title, slug: state.slug) |> deliverOnMainQueue).start(completed: { var focusItemTag: ItemListItemTag?
// dismissImpl?() if case .create = state.mode {
//}) focusItemTag = EditThemeEntryTag.title
}) }
let rightNavigationButton: ItemListNavigationButton
if state.updating {
rightNavigationButton = ItemListNavigationButton(content: .none, style: .activity, enabled: true, action: {})
} else {
let isComplete: Bool
if case .create = mode {
isComplete = !state.title.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines).isEmpty
} else {
isComplete = !state.title.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines).isEmpty && !state.slug.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines).isEmpty
}
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.EditTheme_Title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false) rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Done), style: .bold, enabled: isComplete, action: {
let listState = ItemListNodeState(entries: EditThemeControllerEntries(presentationData: presentationData, theme: previewTheme, state: state), style: .blocks, emptyStateItem: nil, animateChanges: false) arguments.updateState { current in
var state = current
return (controllerState, (listState, arguments)) state.updating = true
return state
}
let saveThemeTemplateFile: (String, LocalFileMediaResource, @escaping () -> Void) -> Void = { title, resource, completion in
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: resource.fileId), partialReference: nil, resource: resource, previewRepresentations: [], immediateThumbnailData: nil, mimeType: "application/x-tgtheme-ios", size: nil, attributes: [.FileName(fileName: "\(title).tgios-theme")])
let message = EnqueueMessage.message(text: "", attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil)
let _ = enqueueMessages(account: context.account, peerId: context.account.peerId, messages: [message]).start()
if let navigateToChat = navigateToChat {
presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.EditTheme_ThemeTemplateAlert, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Settings_SavedMessages, action: {
completion()
navigateToChat(context.account.peerId)
}), TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {
completion()
})], actionLayout: .vertical), nil)
} else {
completion()
}
}
let theme: PresentationTheme?
let custom: Bool
if let updatedTheme = state.updatedTheme {
theme = updatedTheme.withUpdated(name: state.title, author: "", defaultWallpaper: nil)
custom = true
} else {
if case let .edit(info) = mode, let _ = info.theme.file {
theme = nil
custom = true
} else {
theme = state.previewTheme.withUpdated(name: state.title, author: "", defaultWallpaper: nil)
custom = false
}
}
let themeResource: LocalFileMediaResource?
if let theme = theme, let themeString = encodePresentationTheme(theme), let themeData = themeString.data(using: .utf8) {
let resource = LocalFileMediaResource(fileId: arc4random64())
context.account.postbox.mediaBox.storeResourceData(resource.id, data: themeData)
context.sharedContext.accountManager.mediaBox.storeResourceData(resource.id, data: themeData)
themeResource = resource
} else {
themeResource = nil
}
switch mode {
case .create:
if let themeResource = themeResource {
let _ = (createTheme(account: context.account, resource: themeResource, title: state.title)
|> deliverOnMainQueue).start(error: { error in
arguments.updateState { current in
var state = current
state.updating = false
return state
}
}, completed: {
if !custom {
saveThemeTemplateFile(state.title, themeResource, {
dismissImpl?()
})
} else {
dismissImpl?()
}
})
}
case let .edit(theme):
let _ = (updateTheme(account: context.account, theme: theme.theme, title: state.title, slug: state.slug, resource: themeResource)
|> deliverOnMainQueue).start(error: { error in
arguments.updateState { current in
var state = current
state.updating = false
return state
}
}, completed: {
if let themeResource = themeResource, !custom {
saveThemeTemplateFile(state.title, themeResource, {
dismissImpl?()
})
} else {
dismissImpl?()
}
})
}
})
}
let title: String
switch mode {
case .create:
title = presentationData.strings.EditTheme_CreateTitle
case let .edit(theme):
if theme.theme.file == nil {
title = presentationData.strings.EditTheme_CreateTitle
} else {
title = presentationData.strings.EditTheme_EditTitle
}
}
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
let listState = ItemListNodeState(entries: editThemeControllerEntries(presentationData: presentationData, state: state), style: .blocks, focusItemTag: focusItemTag, emptyStateItem: nil, animateChanges: false)
return (controllerState, (listState, arguments))
} }
let controller = ItemListController(context: context, state: signal) let controller = ItemListController(context: context, state: signal)
@ -202,6 +402,7 @@ public func editThemeController(context: AccountContext, theme: TelegramTheme) -
controller?.present(c, in: .window(.root), with: a) controller?.present(c, in: .window(.root), with: a)
} }
dismissImpl = { [weak controller] in dismissImpl = { [weak controller] in
controller?.view.endEditing(true)
let _ = controller?.dismiss() let _ = controller?.dismiss()
} }
return controller return controller

View File

@ -116,7 +116,7 @@ public final class ThemePreviewController: ViewController {
|> take(1) |> take(1)
|> map { theme in |> map { theme in
if let theme = theme { if let theme = theme {
return .cloud(theme) return .cloud(PresentationCloudTheme(theme: theme, resolvedWallpaper: nil))
} else { } else {
return nil return nil
} }

View File

@ -8,6 +8,7 @@ import TelegramPresentationData
import TelegramUIPreferences import TelegramUIPreferences
import ItemListUI import ItemListUI
import AlertUI import AlertUI
import ShareController
import AccountContext import AccountContext
func themeDisplayName(strings: PresentationStrings, reference: PresentationThemeReference) -> String { func themeDisplayName(strings: PresentationStrings, reference: PresentationThemeReference) -> String {
@ -27,7 +28,7 @@ func themeDisplayName(strings: PresentationStrings, reference: PresentationTheme
case let .local(theme): case let .local(theme):
name = theme.title name = theme.title
case let .cloud(theme): case let .cloud(theme):
name = theme.title name = theme.theme.title
} }
return name return name
} }
@ -372,6 +373,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The
var pushControllerImpl: ((ViewController) -> Void)? var pushControllerImpl: ((ViewController) -> Void)?
var presentControllerImpl: ((ViewController, Any?) -> Void)? var presentControllerImpl: ((ViewController, Any?) -> Void)?
var getNavigationControllerImpl: (() -> NavigationController?)?
var selectThemeImpl: ((PresentationThemeReference) -> Void)? var selectThemeImpl: ((PresentationThemeReference) -> Void)?
var moreImpl: (() -> Void)? var moreImpl: (() -> Void)?
@ -463,34 +465,44 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme) let actionSheet = ActionSheetController(presentationTheme: presentationData.theme)
var items: [ActionSheetItem] = [] var items: [ActionSheetItem] = []
items.append(ActionSheetTextItem(title: theme.title)) items.append(ActionSheetTextItem(title: theme.theme.title))
items.append(ActionSheetButtonItem(title: presentationData.strings.Appearance_EditTheme, color: .accent, action: { [weak actionSheet] in if theme.theme.isCreator {
items.append(ActionSheetButtonItem(title: presentationData.strings.Appearance_EditTheme, color: .accent, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
let controller = editThemeController(context: context, mode: .edit(theme), navigateToChat: { peerId in
if let navigationController = getNavigationControllerImpl?() {
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peerId)))
}
})
presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
}))
}
items.append(ActionSheetButtonItem(title: presentationData.strings.Appearance_ShareTheme, color: .accent, action: { [weak actionSheet] in
actionSheet?.dismissAnimated() actionSheet?.dismissAnimated()
let controller = ShareController(context: context, subject: .url("https://t.me/addtheme/\(theme.theme.slug)"), preferredAction: .default)
let controller = editThemeController(context: context, theme: theme) presentControllerImpl?(controller, nil)
presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
})) }))
items.append(ActionSheetButtonItem(title: presentationData.strings.Appearance_RemoveTheme, color: .destructive, action: { [weak actionSheet] in items.append(ActionSheetButtonItem(title: presentationData.strings.Appearance_RemoveTheme, color: .destructive, action: { [weak actionSheet] in
actionSheet?.dismissAnimated() actionSheet?.dismissAnimated()
let _ = (cloudThemes.get() // let _ = (cloudThemes.get()
|> take(1) // |> take(1)
|> deliverOnMainQueue).start(next: { themes in // |> deliverOnMainQueue).start(next: { themes in
if isCurrent, let themeIndex = themes.firstIndex(where: { $0.id == theme.id }) { // if isCurrent, let themeIndex = themes.firstIndex(where: { $0.id == theme.id }) {
let newTheme: PresentationThemeReference // let newTheme: PresentationThemeReference
if themeIndex > 0 { // if themeIndex > 0 {
newTheme = .cloud(themes[themeIndex - 1]) // newTheme = .cloud(themes[themeIndex - 1])
} else { // } else {
newTheme = .builtin(.nightAccent) // newTheme = .builtin(.nightAccent)
} // }
selectThemeImpl?(newTheme) // selectThemeImpl?(newTheme)
} // }
//
let updatedThemes = themes.filter { $0.id != theme.id } // let updatedThemes = themes.filter { $0.id != theme.id }
cloudThemes.set(.single(updatedThemes) |> then(updatedCloudThemes)) // cloudThemes.set(.single(updatedThemes) |> then(updatedCloudThemes))
//
let _ = (deleteTheme(account: context.account, theme: theme)).start() // let _ = (deleteTheme(account: context.account, theme: theme)).start()
}) // })
})) }))
actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [ actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, color: .accent, action: { [weak actionSheet] in ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, color: .accent, action: { [weak actionSheet] in
@ -524,7 +536,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The
}) })
let defaultThemes: [PresentationThemeReference] = [.builtin(.dayClassic), .builtin(.day), .builtin(.night), .builtin(.nightAccent)] let defaultThemes: [PresentationThemeReference] = [.builtin(.dayClassic), .builtin(.day), .builtin(.night), .builtin(.nightAccent)]
let cloudThemes: [PresentationThemeReference] = cloudThemes.map { .cloud($0) } let cloudThemes: [PresentationThemeReference] = cloudThemes.map { .cloud(PresentationCloudTheme(theme: $0, resolvedWallpaper: nil)) }
var availableThemes = defaultThemes var availableThemes = defaultThemes
if !defaultThemes.contains(settings.theme) && !cloudThemes.contains(settings.theme) { if !defaultThemes.contains(settings.theme) && !cloudThemes.contains(settings.theme) {
@ -544,37 +556,27 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The
(controller?.navigationController as? NavigationController)?.pushViewController(c) (controller?.navigationController as? NavigationController)?.pushViewController(c)
} }
presentControllerImpl = { [weak controller] c, a in presentControllerImpl = { [weak controller] c, a in
controller?.present(c, in: .window(.root), with: a) controller?.present(c, in: .window(.root), with: a, blockInteraction: true)
}
getNavigationControllerImpl = { [weak controller] in
return controller?.navigationController as? NavigationController
} }
selectThemeImpl = { theme in selectThemeImpl = { theme in
arguments.selectTheme(theme) arguments.selectTheme(theme)
} }
moreImpl = { [weak controller] in moreImpl = {
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme) let actionSheet = ActionSheetController(presentationTheme: presentationData.theme)
var items: [ActionSheetItem] = [] var items: [ActionSheetItem] = []
items.append(ActionSheetButtonItem(title: presentationData.strings.Appearance_CreateTheme, color: .accent, action: { [weak actionSheet] in items.append(ActionSheetButtonItem(title: presentationData.strings.Appearance_CreateTheme, color: .accent, action: { [weak actionSheet] in
actionSheet?.dismissAnimated() actionSheet?.dismissAnimated()
var randomId: Int64 = 0
arc4random_buf(&randomId, 8)
let path = NSTemporaryDirectory() + "\(randomId)"
guard let string = encodePresentationTheme(presentationData.theme), let _ = try? string.write(toFile: path, atomically: true, encoding: .utf8) else { let controller = editThemeController(context: context, mode: .create, navigateToChat: { peerId in
return if let navigationController = getNavigationControllerImpl?() {
} context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peerId)))
let id = arc4random64()
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: LocalFileReferenceMediaResource(localFilePath: path, randomId: id), previewRepresentations: [], immediateThumbnailData: nil, mimeType: "application/x-tgtheme-ios", size: nil, attributes: [.FileName(fileName: "\(presentationData.theme.name.string).tgios-theme")])
let message = EnqueueMessage.message(text: "", attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil)
let _ = enqueueMessages(account: context.account, peerId: context.account.peerId, messages: [message]).start()
presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.Appearance_CreateThemeInfo, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Settings_SavedMessages, action: {
if let controller = controller, let navigationController = controller.navigationController as? NavigationController {
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(context.account.peerId)))
} }
}), TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})], actionLayout: .vertical), nil) })
presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
})) }))
actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [ actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, color: .accent, action: { [weak actionSheet] in ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, color: .accent, action: { [weak actionSheet] in

View File

@ -60,7 +60,7 @@ private func themeIconImage(context: AccountContext, theme: PresentationThemeRef
if case let .local(theme) = theme { if case let .local(theme) = theme {
resource = theme.resource resource = theme.resource
} else if case let .cloud(theme) = theme { } else if case let .cloud(theme) = theme {
resource = theme.file?.resource resource = theme.theme.file?.resource
} }
if let resource = resource { if let resource = resource {
signal = telegramThemeData(account: context.account, accountManager: context.sharedContext.accountManager, resource: resource, synchronousLoad: false) signal = telegramThemeData(account: context.account, accountManager: context.sharedContext.accountManager, resource: resource, synchronousLoad: false)

View File

@ -104,7 +104,7 @@ final class WallpaperColorPanelNode: ASDisplayNode, UITextFieldDelegate {
self.textFieldNode.textField.font = Font.regular(17.0) self.textFieldNode.textField.font = Font.regular(17.0)
self.textFieldNode.textField.textColor = self.theme.chat.inputPanel.inputTextColor self.textFieldNode.textField.textColor = self.theme.chat.inputPanel.inputTextColor
self.textFieldNode.textField.keyboardAppearance = self.theme.chat.inputPanel.keyboardColor.keyboardAppearance self.textFieldNode.textField.keyboardAppearance = self.theme.rootController.keyboardColor.keyboardAppearance
self.textFieldNode.textField.autocorrectionType = .no self.textFieldNode.textField.autocorrectionType = .no
self.textFieldNode.textField.autocapitalizationType = .allCharacters self.textFieldNode.textField.autocapitalizationType = .allCharacters
self.textFieldNode.textField.keyboardType = .asciiCapable self.textFieldNode.textField.keyboardType = .asciiCapable
@ -123,7 +123,7 @@ final class WallpaperColorPanelNode: ASDisplayNode, UITextFieldDelegate {
self.textBackgroundNode.image = textInputBackgroundImage(fieldColor: self.theme.chat.inputPanel.inputBackgroundColor, strokeColor: self.theme.chat.inputPanel.inputStrokeColor, diameter: 33.0) self.textBackgroundNode.image = textInputBackgroundImage(fieldColor: self.theme.chat.inputPanel.inputBackgroundColor, strokeColor: self.theme.chat.inputPanel.inputStrokeColor, diameter: 33.0)
self.textFieldNode.textField.textColor = self.theme.chat.inputPanel.inputTextColor self.textFieldNode.textField.textColor = self.theme.chat.inputPanel.inputTextColor
self.textFieldNode.textField.keyboardAppearance = self.theme.chat.inputPanel.keyboardColor.keyboardAppearance self.textFieldNode.textField.keyboardAppearance = self.theme.rootController.keyboardColor.keyboardAppearance
self.textFieldNode.textField.tintColor = self.theme.list.itemAccentColor self.textFieldNode.textField.tintColor = self.theme.list.itemAccentColor
} }

View File

@ -92,7 +92,7 @@ private enum UsernameSetupEntry: ItemListNodeEntry {
func item(_ arguments: UsernameSetupControllerArguments) -> ListViewItem { func item(_ arguments: UsernameSetupControllerArguments) -> ListViewItem {
switch self { switch self {
case let .editablePublicLink(theme, strings, prefix, currentText, text): case let .editablePublicLink(theme, strings, prefix, currentText, text):
return ItemListSingleLineInputItem(theme: theme, strings: strings, title: NSAttributedString(string: prefix, textColor: theme.list.itemPrimaryTextColor), text: text, placeholder: "", type: .username, spacing: 10.0, clearButton: true, tag: UsernameEntryTag.username, sectionId: self.section, textUpdated: { updatedText in return ItemListSingleLineInputItem(theme: theme, strings: strings, title: NSAttributedString(string: prefix, textColor: theme.list.itemPrimaryTextColor), text: text, placeholder: "", type: .username, spacing: 10.0, clearType: .always, tag: UsernameEntryTag.username, sectionId: self.section, textUpdated: { updatedText in
arguments.updatePublicLinkText(currentText, updatedText) arguments.updatePublicLinkText(currentText, updatedText)
}, action: { }, action: {
}) })

View File

@ -50,7 +50,7 @@ final class ShareInputFieldNodeTheme: Equatable {
extension ShareInputFieldNodeTheme { extension ShareInputFieldNodeTheme {
convenience init(presentationTheme theme: PresentationTheme) { convenience init(presentationTheme theme: PresentationTheme) {
self.init(backgroundColor: theme.actionSheet.inputBackgroundColor, textColor: theme.actionSheet.inputTextColor, placeholderColor: theme.actionSheet.inputPlaceholderColor, clearButtonColor: theme.actionSheet.inputClearButtonColor, accentColor: theme.actionSheet.controlAccentColor, keyboard: theme.chatList.searchBarKeyboardColor) self.init(backgroundColor: theme.actionSheet.inputBackgroundColor, textColor: theme.actionSheet.inputTextColor, placeholderColor: theme.actionSheet.inputPlaceholderColor, clearButtonColor: theme.actionSheet.inputClearButtonColor, accentColor: theme.actionSheet.controlAccentColor, keyboard: theme.rootController.keyboardColor)
} }
} }

View File

@ -48,7 +48,7 @@ final class ShareSearchBarNode: ASDisplayNode, UITextFieldDelegate {
self.textInputNode.hitTestSlop = UIEdgeInsets(top: -5.0, left: -5.0, bottom: -5.0, right: -5.0) self.textInputNode.hitTestSlop = UIEdgeInsets(top: -5.0, left: -5.0, bottom: -5.0, right: -5.0)
self.textInputNode.textField.keyboardAppearance = keyboardAppearance self.textInputNode.textField.keyboardAppearance = keyboardAppearance
self.textInputNode.textField.attributedPlaceholder = NSAttributedString(string: placeholder, font: Font.regular(16.0), textColor: theme.actionSheet.inputPlaceholderColor) self.textInputNode.textField.attributedPlaceholder = NSAttributedString(string: placeholder, font: Font.regular(16.0), textColor: theme.actionSheet.inputPlaceholderColor)
self.textInputNode.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance self.textInputNode.textField.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance
self.textInputNode.textField.tintColor = theme.actionSheet.controlAccentColor self.textInputNode.textField.tintColor = theme.actionSheet.controlAccentColor
super.init() super.init()

View File

@ -130,6 +130,7 @@ private var declaredEncodables: Void = {
declareEncodable(CachedStickerQueryResult.self, f: { CachedStickerQueryResult(decoder: $0) }) declareEncodable(CachedStickerQueryResult.self, f: { CachedStickerQueryResult(decoder: $0) })
declareEncodable(TelegramWallpaper.self, f: { TelegramWallpaper(decoder: $0) }) declareEncodable(TelegramWallpaper.self, f: { TelegramWallpaper(decoder: $0) })
declareEncodable(TelegramTheme.self, f: { TelegramTheme(decoder: $0) }) declareEncodable(TelegramTheme.self, f: { TelegramTheme(decoder: $0) })
declareEncodable(ThemeSettings.self, f: { ThemeSettings(decoder: $0) })
declareEncodable(SynchronizeMarkAllUnseenPersonalMessagesOperation.self, f: { SynchronizeMarkAllUnseenPersonalMessagesOperation(decoder: $0) }) declareEncodable(SynchronizeMarkAllUnseenPersonalMessagesOperation.self, f: { SynchronizeMarkAllUnseenPersonalMessagesOperation(decoder: $0) })
declareEncodable(SynchronizeAppLogEventsOperation.self, f: { SynchronizeAppLogEventsOperation(decoder: $0) }) declareEncodable(SynchronizeAppLogEventsOperation.self, f: { SynchronizeAppLogEventsOperation(decoder: $0) })
declareEncodable(CachedRecentPeers.self, f: { CachedRecentPeers(decoder: $0) }) declareEncodable(CachedRecentPeers.self, f: { CachedRecentPeers(decoder: $0) })

View File

@ -268,6 +268,7 @@ private enum SharedDataKeyValues: Int32 {
case localizationSettings = 3 case localizationSettings = 3
case proxySettings = 4 case proxySettings = 4
case autodownloadSettings = 5 case autodownloadSettings = 5
case themeSettings = 6
} }
public struct SharedDataKeys { public struct SharedDataKeys {
@ -300,6 +301,12 @@ public struct SharedDataKeys {
key.setInt32(0, value: SharedDataKeyValues.autodownloadSettings.rawValue) key.setInt32(0, value: SharedDataKeyValues.autodownloadSettings.rawValue)
return key return key
}() }()
public static let themeSettings: ValueBoxKey = {
let key = ValueBoxKey(length: 4)
key.setInt32(0, value: SharedDataKeyValues.themeSettings.rawValue)
return key
}()
} }
public func applicationSpecificItemCacheCollectionId(_ value: Int8) -> Int8 { public func applicationSpecificItemCacheCollectionId(_ value: Int8) -> Int8 {

View File

@ -140,12 +140,12 @@ private func saveUnsaveTheme(account: Account, theme: TelegramTheme, unsave: Boo
} }
} }
public func installTheme(account: Account, theme: TelegramTheme) -> Signal<Void, NoError> { private func installTheme(account: Account, theme: TelegramTheme) -> Signal<Never, NoError> {
return account.network.request(Api.functions.account.installTheme(format: themeFormat, theme: Api.InputTheme.inputTheme(id: theme.id, accessHash: theme.accessHash))) return account.network.request(Api.functions.account.installTheme(format: themeFormat, theme: Api.InputTheme.inputTheme(id: theme.id, accessHash: theme.accessHash)))
|> `catch` { _ -> Signal<Api.Bool, NoError> in |> `catch` { _ -> Signal<Api.Bool, NoError> in
return .complete() return .complete()
} }
|> mapToSignal { _ -> Signal<Void, NoError> in |> mapToSignal { _ -> Signal<Never, NoError> in
return .complete() return .complete()
} }
} }
@ -233,7 +233,11 @@ public func createTheme(account: Account, resource: MediaResource, title: String
|> mapError { _ in return CreateThemeError.generic } |> mapError { _ in return CreateThemeError.generic }
|> mapToSignal { apiTheme -> Signal<CreateThemeResult, CreateThemeError> in |> mapToSignal { apiTheme -> Signal<CreateThemeResult, CreateThemeError> in
if let theme = TelegramTheme(apiTheme: apiTheme) { if let theme = TelegramTheme(apiTheme: apiTheme) {
return .single(.result(theme)) return account.postbox.transaction { transaction -> CreateThemeResult in
return .result(theme)
}
|> introduceError(CreateThemeError.self)
} else { } else {
return .fail(.generic) return .fail(.generic)
} }
@ -299,3 +303,50 @@ public func updateTheme(account: Account, theme: TelegramTheme, title: String?,
} }
} }
} }
public final class ThemeSettings: PreferencesEntry, Equatable {
public let currentTheme: TelegramTheme?
public init(currentTheme: TelegramTheme?) {
self.currentTheme = currentTheme
}
public init(decoder: PostboxDecoder) {
self.currentTheme = decoder.decodeObjectForKey("t", decoder: { TelegramTheme(decoder: $0) }) as? TelegramTheme
}
public func encode(_ encoder: PostboxEncoder) {
if let currentTheme = currentTheme {
encoder.encodeObject(currentTheme, forKey: "t")
} else {
encoder.encodeNil(forKey: "t")
}
}
public func isEqual(to: PreferencesEntry) -> Bool {
if let to = to as? ThemeSettings {
return self == to
} else {
return false
}
}
public static func ==(lhs: ThemeSettings, rhs: ThemeSettings) -> Bool {
return lhs.currentTheme == rhs.currentTheme
}
}
public func applyTheme(accountManager: AccountManager, account: Account, theme: TelegramTheme?) -> Signal<Never, NoError> {
return accountManager.transaction { transaction -> Signal<Never, NoError> in
transaction.updateSharedData(SharedDataKeys.themeSettings, { _ in
return ThemeSettings(currentTheme: theme)
})
if let theme = theme {
return installTheme(account: account, theme: theme)
} else {
return .complete()
}
}
|> switchToLatest
}

View File

@ -113,7 +113,8 @@ private func makeDarkPresentationTheme(accentColor: UIColor, baseColor: Presenta
statusBarStyle: .white, statusBarStyle: .white,
tabBar: rootTabBar, tabBar: rootTabBar,
navigationBar: rootNavigationBar, navigationBar: rootNavigationBar,
navigationSearchBar: navigationSearchBar navigationSearchBar: navigationSearchBar,
keyboardColor: .dark
) )
let switchColors = PresentationThemeSwitch( let switchColors = PresentationThemeSwitch(
@ -138,7 +139,7 @@ private func makeDarkPresentationTheme(accentColor: UIColor, baseColor: Presenta
itemHighlightedBackgroundColor: UIColor(rgb: 0x313135), itemHighlightedBackgroundColor: UIColor(rgb: 0x313135),
itemBlocksSeparatorColor: UIColor(rgb: 0x3d3d40), itemBlocksSeparatorColor: UIColor(rgb: 0x3d3d40),
itemPlainSeparatorColor: UIColor(rgb: 0x3d3d40), itemPlainSeparatorColor: UIColor(rgb: 0x3d3d40),
disclosureArrowColor: UIColor(rgb: 0x5a5a5e), disclosureArrowColor: UIColor(rgb: 0xffffff, alpha: 0.28),
sectionHeaderTextColor: UIColor(rgb: 0x8d8e93), sectionHeaderTextColor: UIColor(rgb: 0x8d8e93),
freeTextColor: UIColor(rgb: 0x8d8e93), freeTextColor: UIColor(rgb: 0x8d8e93),
freeTextErrorColor: UIColor(rgb: 0xcf3030), freeTextErrorColor: UIColor(rgb: 0xcf3030),
@ -200,7 +201,6 @@ private func makeDarkPresentationTheme(accentColor: UIColor, baseColor: Presenta
regularSearchBarColor: UIColor(rgb: 0x272728), regularSearchBarColor: UIColor(rgb: 0x272728),
sectionHeaderFillColor: UIColor(rgb: 0x1c1c1d), sectionHeaderFillColor: UIColor(rgb: 0x1c1c1d),
sectionHeaderTextColor: UIColor(rgb: 0xffffff), sectionHeaderTextColor: UIColor(rgb: 0xffffff),
searchBarKeyboardColor: .dark,
verifiedIconFillColor: accentColor, verifiedIconFillColor: accentColor,
verifiedIconForegroundColor: badgeTextColor, verifiedIconForegroundColor: badgeTextColor,
secretIconColor: secretColor, secretIconColor: secretColor,
@ -258,7 +258,6 @@ private func makeDarkPresentationTheme(accentColor: UIColor, baseColor: Presenta
primaryTextColor: .white, primaryTextColor: .white,
secondaryTextColor: UIColor(rgb: 0xffffff, alpha: 0.5), secondaryTextColor: UIColor(rgb: 0xffffff, alpha: 0.5),
mediaRecordingDotColor: destructiveColor, mediaRecordingDotColor: destructiveColor,
keyboardColor: .dark,
mediaRecordingControl: inputPanelMediaRecordingControl mediaRecordingControl: inputPanelMediaRecordingControl
) )

View File

@ -81,7 +81,8 @@ private func makeDarkPresentationTheme(accentColor: UIColor, baseColor: Presenta
statusBarStyle: .white, statusBarStyle: .white,
tabBar: rootTabBar, tabBar: rootTabBar,
navigationBar: rootNavigationBar, navigationBar: rootNavigationBar,
navigationSearchBar: navigationSearchBar navigationSearchBar: navigationSearchBar,
keyboardColor: .dark
) )
let switchColors = PresentationThemeSwitch( let switchColors = PresentationThemeSwitch(
@ -168,7 +169,6 @@ private func makeDarkPresentationTheme(accentColor: UIColor, baseColor: Presenta
regularSearchBarColor: accentColor.withMultiplied(hue: 1.029, saturation: 0.609, brightness: 0.12), regularSearchBarColor: accentColor.withMultiplied(hue: 1.029, saturation: 0.609, brightness: 0.12),
sectionHeaderFillColor: mainBackgroundColor, sectionHeaderFillColor: mainBackgroundColor,
sectionHeaderTextColor: mainSecondaryTextColor.withAlphaComponent(0.5), sectionHeaderTextColor: mainSecondaryTextColor.withAlphaComponent(0.5),
searchBarKeyboardColor: .dark,
verifiedIconFillColor: accentColor, verifiedIconFillColor: accentColor,
verifiedIconForegroundColor: .white, verifiedIconForegroundColor: .white,
secretIconColor: secretColor, secretIconColor: secretColor,
@ -228,7 +228,6 @@ private func makeDarkPresentationTheme(accentColor: UIColor, baseColor: Presenta
primaryTextColor: UIColor(rgb: 0xffffff), primaryTextColor: UIColor(rgb: 0xffffff),
secondaryTextColor: UIColor(rgb: 0xffffff, alpha: 0.5), secondaryTextColor: UIColor(rgb: 0xffffff, alpha: 0.5),
mediaRecordingDotColor: accentColor, mediaRecordingDotColor: accentColor,
keyboardColor: .dark,
mediaRecordingControl: inputPanelMediaRecordingControl mediaRecordingControl: inputPanelMediaRecordingControl
) )

View File

@ -93,7 +93,8 @@ private func makeDefaultDayPresentationTheme(accentColor: UIColor, serviceBackgr
statusBarStyle: .black, statusBarStyle: .black,
tabBar: rootTabBar, tabBar: rootTabBar,
navigationBar: rootNavigationBar, navigationBar: rootNavigationBar,
navigationSearchBar: navigationSearchBar navigationSearchBar: navigationSearchBar,
keyboardColor: .light
) )
let switchColors = PresentationThemeSwitch( let switchColors = PresentationThemeSwitch(
@ -180,7 +181,6 @@ private func makeDefaultDayPresentationTheme(accentColor: UIColor, serviceBackgr
regularSearchBarColor: UIColor(rgb: 0xe9e9e9), regularSearchBarColor: UIColor(rgb: 0xe9e9e9),
sectionHeaderFillColor: UIColor(rgb: 0xf7f7f7), sectionHeaderFillColor: UIColor(rgb: 0xf7f7f7),
sectionHeaderTextColor: UIColor(rgb: 0x8e8e93), sectionHeaderTextColor: UIColor(rgb: 0x8e8e93),
searchBarKeyboardColor: .light,
verifiedIconFillColor: accentColor, verifiedIconFillColor: accentColor,
verifiedIconForegroundColor: .white, verifiedIconForegroundColor: .white,
secretIconColor: secretColor, secretIconColor: secretColor,
@ -264,7 +264,6 @@ private func makeDefaultDayPresentationTheme(accentColor: UIColor, serviceBackgr
primaryTextColor: .black, primaryTextColor: .black,
secondaryTextColor: UIColor(rgb: 0x8e8e93), secondaryTextColor: UIColor(rgb: 0x8e8e93),
mediaRecordingDotColor: UIColor(rgb: 0xed2521), mediaRecordingDotColor: UIColor(rgb: 0xed2521),
keyboardColor: .light,
mediaRecordingControl: inputPanelMediaRecordingControl mediaRecordingControl: inputPanelMediaRecordingControl
) )

View File

@ -30,7 +30,7 @@ public func makePresentationTheme(mediaBox: MediaBox, themeReference: Presentati
theme = makeDefaultPresentationTheme(reference: .dayClassic, accentColor: nil, serviceBackgroundColor: serviceBackgroundColor, baseColor: baseColor, preview: preview) theme = makeDefaultPresentationTheme(reference: .dayClassic, accentColor: nil, serviceBackgroundColor: serviceBackgroundColor, baseColor: baseColor, preview: preview)
} }
case let .cloud(info): case let .cloud(info):
if let file = info.file, let path = mediaBox.completedResourcePath(file.resource), let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead), let loadedTheme = makePresentationTheme(data: data) { if let file = info.theme.file, let path = mediaBox.completedResourcePath(file.resource), let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead), let loadedTheme = makePresentationTheme(data: data, resolvedWallpaper: info.resolvedWallpaper) {
theme = loadedTheme theme = loadedTheme
} else { } else {
theme = makeDefaultPresentationTheme(reference: .dayClassic, accentColor: nil, serviceBackgroundColor: serviceBackgroundColor, baseColor: baseColor, preview: preview) theme = makeDefaultPresentationTheme(reference: .dayClassic, accentColor: nil, serviceBackgroundColor: serviceBackgroundColor, baseColor: baseColor, preview: preview)

View File

@ -140,12 +140,14 @@ public final class PresentationThemeRootController {
public let tabBar: PresentationThemeRootTabBar public let tabBar: PresentationThemeRootTabBar
public let navigationBar: PresentationThemeRootNavigationBar public let navigationBar: PresentationThemeRootNavigationBar
public let navigationSearchBar: PresentationThemeNavigationSearchBar public let navigationSearchBar: PresentationThemeNavigationSearchBar
public let keyboardColor: PresentationThemeKeyboardColor
public init(statusBarStyle: PresentationThemeStatusBarStyle, tabBar: PresentationThemeRootTabBar, navigationBar: PresentationThemeRootNavigationBar, navigationSearchBar: PresentationThemeNavigationSearchBar) { public init(statusBarStyle: PresentationThemeStatusBarStyle, tabBar: PresentationThemeRootTabBar, navigationBar: PresentationThemeRootNavigationBar, navigationSearchBar: PresentationThemeNavigationSearchBar, keyboardColor: PresentationThemeKeyboardColor) {
self.statusBarStyle = statusBarStyle self.statusBarStyle = statusBarStyle
self.tabBar = tabBar self.tabBar = tabBar
self.navigationBar = navigationBar self.navigationBar = navigationBar
self.navigationSearchBar = navigationSearchBar self.navigationSearchBar = navigationSearchBar
self.keyboardColor = keyboardColor
} }
} }
@ -397,7 +399,6 @@ public final class PresentationThemeChatList {
public let regularSearchBarColor: UIColor public let regularSearchBarColor: UIColor
public let sectionHeaderFillColor: UIColor public let sectionHeaderFillColor: UIColor
public let sectionHeaderTextColor: UIColor public let sectionHeaderTextColor: UIColor
public let searchBarKeyboardColor: PresentationThemeKeyboardColor
public let verifiedIconFillColor: UIColor public let verifiedIconFillColor: UIColor
public let verifiedIconForegroundColor: UIColor public let verifiedIconForegroundColor: UIColor
public let secretIconColor: UIColor public let secretIconColor: UIColor
@ -405,7 +406,7 @@ public final class PresentationThemeChatList {
public let unpinnedArchiveAvatarColor: PresentationThemeArchiveAvatarColors public let unpinnedArchiveAvatarColor: PresentationThemeArchiveAvatarColors
public let onlineDotColor: UIColor public let onlineDotColor: UIColor
init(backgroundColor: UIColor, itemSeparatorColor: UIColor, itemBackgroundColor: UIColor, pinnedItemBackgroundColor: UIColor, itemHighlightedBackgroundColor: UIColor, itemSelectedBackgroundColor: UIColor, titleColor: UIColor, secretTitleColor: UIColor, dateTextColor: UIColor, authorNameColor: UIColor, messageTextColor: UIColor, messageDraftTextColor: UIColor, checkmarkColor: UIColor, pendingIndicatorColor: UIColor, failedFillColor: UIColor, failedForegroundColor: UIColor, muteIconColor: UIColor, unreadBadgeActiveBackgroundColor: UIColor, unreadBadgeActiveTextColor: UIColor, unreadBadgeInactiveBackgroundColor: UIColor, unreadBadgeInactiveTextColor: UIColor, pinnedBadgeColor: UIColor, pinnedSearchBarColor: UIColor, regularSearchBarColor: UIColor, sectionHeaderFillColor: UIColor, sectionHeaderTextColor: UIColor, searchBarKeyboardColor: PresentationThemeKeyboardColor, verifiedIconFillColor: UIColor, verifiedIconForegroundColor: UIColor, secretIconColor: UIColor, pinnedArchiveAvatarColor: PresentationThemeArchiveAvatarColors, unpinnedArchiveAvatarColor: PresentationThemeArchiveAvatarColors, onlineDotColor: UIColor) { init(backgroundColor: UIColor, itemSeparatorColor: UIColor, itemBackgroundColor: UIColor, pinnedItemBackgroundColor: UIColor, itemHighlightedBackgroundColor: UIColor, itemSelectedBackgroundColor: UIColor, titleColor: UIColor, secretTitleColor: UIColor, dateTextColor: UIColor, authorNameColor: UIColor, messageTextColor: UIColor, messageDraftTextColor: UIColor, checkmarkColor: UIColor, pendingIndicatorColor: UIColor, failedFillColor: UIColor, failedForegroundColor: UIColor, muteIconColor: UIColor, unreadBadgeActiveBackgroundColor: UIColor, unreadBadgeActiveTextColor: UIColor, unreadBadgeInactiveBackgroundColor: UIColor, unreadBadgeInactiveTextColor: UIColor, pinnedBadgeColor: UIColor, pinnedSearchBarColor: UIColor, regularSearchBarColor: UIColor, sectionHeaderFillColor: UIColor, sectionHeaderTextColor: UIColor, verifiedIconFillColor: UIColor, verifiedIconForegroundColor: UIColor, secretIconColor: UIColor, pinnedArchiveAvatarColor: PresentationThemeArchiveAvatarColors, unpinnedArchiveAvatarColor: PresentationThemeArchiveAvatarColors, onlineDotColor: UIColor) {
self.backgroundColor = backgroundColor self.backgroundColor = backgroundColor
self.itemSeparatorColor = itemSeparatorColor self.itemSeparatorColor = itemSeparatorColor
self.itemBackgroundColor = itemBackgroundColor self.itemBackgroundColor = itemBackgroundColor
@ -432,7 +433,6 @@ public final class PresentationThemeChatList {
self.regularSearchBarColor = regularSearchBarColor self.regularSearchBarColor = regularSearchBarColor
self.sectionHeaderFillColor = sectionHeaderFillColor self.sectionHeaderFillColor = sectionHeaderFillColor
self.sectionHeaderTextColor = sectionHeaderTextColor self.sectionHeaderTextColor = sectionHeaderTextColor
self.searchBarKeyboardColor = searchBarKeyboardColor
self.verifiedIconFillColor = verifiedIconFillColor self.verifiedIconFillColor = verifiedIconFillColor
self.verifiedIconForegroundColor = verifiedIconForegroundColor self.verifiedIconForegroundColor = verifiedIconForegroundColor
self.secretIconColor = secretIconColor self.secretIconColor = secretIconColor
@ -715,10 +715,9 @@ public final class PresentationThemeChatInputPanel {
public let primaryTextColor: UIColor public let primaryTextColor: UIColor
public let secondaryTextColor: UIColor public let secondaryTextColor: UIColor
public let mediaRecordingDotColor: UIColor public let mediaRecordingDotColor: UIColor
public let keyboardColor: PresentationThemeKeyboardColor
public let mediaRecordingControl: PresentationThemeChatInputPanelMediaRecordingControl public let mediaRecordingControl: PresentationThemeChatInputPanelMediaRecordingControl
public init(panelBackgroundColor: UIColor, panelSeparatorColor: UIColor, panelControlAccentColor: UIColor, panelControlColor: UIColor, panelControlDisabledColor: UIColor, panelControlDestructiveColor: UIColor, inputBackgroundColor: UIColor, inputStrokeColor: UIColor, inputPlaceholderColor: UIColor, inputTextColor: UIColor, inputControlColor: UIColor, actionControlFillColor: UIColor, actionControlForegroundColor: UIColor, primaryTextColor: UIColor, secondaryTextColor: UIColor, mediaRecordingDotColor: UIColor, keyboardColor: PresentationThemeKeyboardColor, mediaRecordingControl: PresentationThemeChatInputPanelMediaRecordingControl) { public init(panelBackgroundColor: UIColor, panelSeparatorColor: UIColor, panelControlAccentColor: UIColor, panelControlColor: UIColor, panelControlDisabledColor: UIColor, panelControlDestructiveColor: UIColor, inputBackgroundColor: UIColor, inputStrokeColor: UIColor, inputPlaceholderColor: UIColor, inputTextColor: UIColor, inputControlColor: UIColor, actionControlFillColor: UIColor, actionControlForegroundColor: UIColor, primaryTextColor: UIColor, secondaryTextColor: UIColor, mediaRecordingDotColor: UIColor, mediaRecordingControl: PresentationThemeChatInputPanelMediaRecordingControl) {
self.panelBackgroundColor = panelBackgroundColor self.panelBackgroundColor = panelBackgroundColor
self.panelSeparatorColor = panelSeparatorColor self.panelSeparatorColor = panelSeparatorColor
self.panelControlAccentColor = panelControlAccentColor self.panelControlAccentColor = panelControlAccentColor
@ -735,7 +734,6 @@ public final class PresentationThemeChatInputPanel {
self.primaryTextColor = primaryTextColor self.primaryTextColor = primaryTextColor
self.secondaryTextColor = secondaryTextColor self.secondaryTextColor = secondaryTextColor
self.mediaRecordingDotColor = mediaRecordingDotColor self.mediaRecordingDotColor = mediaRecordingDotColor
self.keyboardColor = keyboardColor
self.mediaRecordingControl = mediaRecordingControl self.mediaRecordingControl = mediaRecordingControl
} }
} }
@ -822,6 +820,10 @@ public final class PresentationThemeChat {
self.inputButtonPanel = inputButtonPanel self.inputButtonPanel = inputButtonPanel
self.historyNavigation = historyNavigation self.historyNavigation = historyNavigation
} }
public func withUpdatedDefaultWallpaper(_ defaultWallpaper: TelegramWallpaper?) -> PresentationThemeChat {
return PresentationThemeChat(defaultWallpaper: defaultWallpaper ?? self.defaultWallpaper, message: self.message, serviceMessage: self.serviceMessage, inputPanel: self.inputPanel, inputMediaPanel: self.inputMediaPanel, inputButtonPanel: self.inputButtonPanel, historyNavigation: self.historyNavigation)
}
} }
public enum PresentationThemeExpandedNotificationBackgroundType: Int32 { public enum PresentationThemeExpandedNotificationBackgroundType: Int32 {
@ -974,4 +976,21 @@ public final class PresentationTheme: Equatable {
public static func ==(lhs: PresentationTheme, rhs: PresentationTheme) -> Bool { public static func ==(lhs: PresentationTheme, rhs: PresentationTheme) -> Bool {
return lhs === rhs return lhs === rhs
} }
public func withUpdated(name: String?, author: String?, defaultWallpaper: TelegramWallpaper?) -> PresentationTheme {
var defaultWallpaper = defaultWallpaper
if let wallpaper = defaultWallpaper {
switch wallpaper {
case .image:
defaultWallpaper = nil
case let .file(file):
if file.isPattern {
defaultWallpaper = nil
}
default:
break
}
}
return PresentationTheme(name: name.flatMap(PresentationThemeName.custom) ?? .custom(self.name.string), author: author ?? self.author, referenceTheme: self.referenceTheme, overallDarkAppearance: self.overallDarkAppearance, baseColor: nil, intro: self.intro, passcode: self.passcode, rootController: self.rootController, list: self.list, chatList: self.chatList, chat: self.chat.withUpdatedDefaultWallpaper(defaultWallpaper), actionSheet: self.actionSheet, contextMenu: self.contextMenu, inAppNotification: self.inAppNotification)
}
} }

View File

@ -1,5 +1,6 @@
import Foundation import Foundation
import UIKit import UIKit
import Postbox
import TelegramCore import TelegramCore
import TelegramUIPreferences import TelegramUIPreferences
@ -35,7 +36,7 @@ extension TelegramWallpaper: Codable {
if let color = UIColor(hexString: value) { if let color = UIColor(hexString: value) {
self = .color(Int32(bitPattern: color.rgb)) self = .color(Int32(bitPattern: color.rgb))
} else { } else {
throw PresentationThemeDecodingError.generic self = .file(id: 0, accessHash: 0, isCreator: false, isDefault: false, isPattern: false, isDark: false, slug: value, file: TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: LocalFileMediaResource(fileId: 0), previewRepresentations: [], immediateThumbnailData: nil, mimeType: "", size: nil, attributes: []), settings: WallpaperSettings(blur: false, motion: false, color: nil, intensity: nil))
} }
} }
} else { } else {
@ -50,6 +51,8 @@ extension TelegramWallpaper: Codable {
try container.encode("builtin") try container.encode("builtin")
case let .color(value): case let .color(value):
try container.encode(String(format: "%06x", value)) try container.encode(String(format: "%06x", value))
case let .file(file):
try container.encode(file.slug)
default: default:
break break
} }
@ -354,6 +357,7 @@ extension PresentationThemeRootController: Codable {
case tabBar case tabBar
case navBar case navBar
case searchBar case searchBar
case keyboard
} }
public convenience init(from decoder: Decoder) throws { public convenience init(from decoder: Decoder) throws {
@ -361,7 +365,8 @@ extension PresentationThemeRootController: Codable {
self.init(statusBarStyle: try values.decode(PresentationThemeStatusBarStyle.self, forKey: .statusBar), self.init(statusBarStyle: try values.decode(PresentationThemeStatusBarStyle.self, forKey: .statusBar),
tabBar: try values.decode(PresentationThemeRootTabBar.self, forKey: .tabBar), tabBar: try values.decode(PresentationThemeRootTabBar.self, forKey: .tabBar),
navigationBar: try values.decode(PresentationThemeRootNavigationBar.self, forKey: .navBar), navigationBar: try values.decode(PresentationThemeRootNavigationBar.self, forKey: .navBar),
navigationSearchBar: try values.decode(PresentationThemeNavigationSearchBar.self, forKey: .searchBar)) navigationSearchBar: try values.decode(PresentationThemeNavigationSearchBar.self, forKey: .searchBar),
keyboardColor: try values.decode(PresentationThemeKeyboardColor.self, forKey: .keyboard))
} }
public func encode(to encoder: Encoder) throws { public func encode(to encoder: Encoder) throws {
@ -370,6 +375,7 @@ extension PresentationThemeRootController: Codable {
try values.encode(self.tabBar, forKey: .tabBar) try values.encode(self.tabBar, forKey: .tabBar)
try values.encode(self.navigationBar, forKey: .navBar) try values.encode(self.navigationBar, forKey: .navBar)
try values.encode(self.navigationSearchBar, forKey: .searchBar) try values.encode(self.navigationSearchBar, forKey: .searchBar)
try values.encode(self.keyboardColor, forKey: .keyboard)
} }
} }
@ -721,7 +727,6 @@ extension PresentationThemeChatList: Codable {
case regularSearchBar case regularSearchBar
case sectionHeaderBg case sectionHeaderBg
case sectionHeaderText case sectionHeaderText
case searchBarKeyboard
case verifiedIconBg case verifiedIconBg
case verifiedIconFg case verifiedIconFg
case secretIcon case secretIcon
@ -758,7 +763,6 @@ extension PresentationThemeChatList: Codable {
regularSearchBarColor: try decodeColor(values, .regularSearchBar), regularSearchBarColor: try decodeColor(values, .regularSearchBar),
sectionHeaderFillColor: try decodeColor(values, .sectionHeaderBg), sectionHeaderFillColor: try decodeColor(values, .sectionHeaderBg),
sectionHeaderTextColor: try decodeColor(values, .sectionHeaderText), sectionHeaderTextColor: try decodeColor(values, .sectionHeaderText),
searchBarKeyboardColor: try values.decode(PresentationThemeKeyboardColor.self, forKey: .searchBarKeyboard),
verifiedIconFillColor: try decodeColor(values, .verifiedIconBg), verifiedIconFillColor: try decodeColor(values, .verifiedIconBg),
verifiedIconForegroundColor: try decodeColor(values, .verifiedIconFg), verifiedIconForegroundColor: try decodeColor(values, .verifiedIconFg),
secretIconColor: try decodeColor(values, .secretIcon), secretIconColor: try decodeColor(values, .secretIcon),
@ -795,7 +799,6 @@ extension PresentationThemeChatList: Codable {
try encodeColor(&values, self.regularSearchBarColor, .regularSearchBar) try encodeColor(&values, self.regularSearchBarColor, .regularSearchBar)
try encodeColor(&values, self.sectionHeaderFillColor, .sectionHeaderBg) try encodeColor(&values, self.sectionHeaderFillColor, .sectionHeaderBg)
try encodeColor(&values, self.sectionHeaderTextColor, .sectionHeaderText) try encodeColor(&values, self.sectionHeaderTextColor, .sectionHeaderText)
try values.encode(self.searchBarKeyboardColor, forKey: .searchBarKeyboard)
try encodeColor(&values, self.verifiedIconFillColor, .verifiedIconBg) try encodeColor(&values, self.verifiedIconFillColor, .verifiedIconBg)
try encodeColor(&values, self.verifiedIconForegroundColor, .verifiedIconFg) try encodeColor(&values, self.verifiedIconForegroundColor, .verifiedIconFg)
try encodeColor(&values, self.secretIconColor, .secretIcon) try encodeColor(&values, self.secretIconColor, .secretIcon)
@ -1143,7 +1146,6 @@ extension PresentationThemeChatInputPanel: Codable {
case primaryText case primaryText
case secondaryText case secondaryText
case mediaRecordDot case mediaRecordDot
case keyboard
case mediaRecordControl case mediaRecordControl
} }
@ -1165,7 +1167,6 @@ extension PresentationThemeChatInputPanel: Codable {
primaryTextColor: try decodeColor(values, .primaryText), primaryTextColor: try decodeColor(values, .primaryText),
secondaryTextColor: try decodeColor(values, .secondaryText), secondaryTextColor: try decodeColor(values, .secondaryText),
mediaRecordingDotColor: try decodeColor(values, .mediaRecordDot), mediaRecordingDotColor: try decodeColor(values, .mediaRecordDot),
keyboardColor: try values.decode(PresentationThemeKeyboardColor.self, forKey: .keyboard),
mediaRecordingControl: try values.decode(PresentationThemeChatInputPanelMediaRecordingControl.self, forKey: .mediaRecordControl)) mediaRecordingControl: try values.decode(PresentationThemeChatInputPanelMediaRecordingControl.self, forKey: .mediaRecordControl))
} }
@ -1187,7 +1188,6 @@ extension PresentationThemeChatInputPanel: Codable {
try encodeColor(&values, self.primaryTextColor, .primaryText) try encodeColor(&values, self.primaryTextColor, .primaryText)
try encodeColor(&values, self.secondaryTextColor, .secondaryText) try encodeColor(&values, self.secondaryTextColor, .secondaryText)
try encodeColor(&values, self.mediaRecordingDotColor, .mediaRecordDot) try encodeColor(&values, self.mediaRecordingDotColor, .mediaRecordDot)
try values.encode(self.keyboardColor, forKey: .keyboard)
try values.encode(self.mediaRecordingControl, forKey: .mediaRecordControl) try values.encode(self.mediaRecordingControl, forKey: .mediaRecordControl)
} }
} }
@ -1313,7 +1313,15 @@ extension PresentationThemeChat: Codable {
public convenience init(from decoder: Decoder) throws { public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self) let values = try decoder.container(keyedBy: CodingKeys.self)
self.init(defaultWallpaper: try values.decode(TelegramWallpaper.self, forKey: .defaultWallpaper),
var wallpaper = try values.decode(TelegramWallpaper.self, forKey: .defaultWallpaper)
if let decoder = decoder as? PresentationThemeDecoding {
if case .file = wallpaper, let resolvedWallpaper = decoder.resolvedWallpaper {
wallpaper = resolvedWallpaper
}
}
self.init(defaultWallpaper: wallpaper,
message: try values.decode(PresentationThemeChatMessage.self, forKey: .message), message: try values.decode(PresentationThemeChatMessage.self, forKey: .message),
serviceMessage: try values.decode(PresentationThemeServiceMessage.self, forKey: .serviceMessage), serviceMessage: try values.decode(PresentationThemeServiceMessage.self, forKey: .serviceMessage),
inputPanel: try values.decode(PresentationThemeChatInputPanel.self, forKey: .inputPanel), inputPanel: try values.decode(PresentationThemeChatInputPanel.self, forKey: .inputPanel),

View File

@ -1,4 +1,5 @@
import Foundation import Foundation
import TelegramCore
public func encodePresentationTheme(_ theme: PresentationTheme) -> String? { public func encodePresentationTheme(_ theme: PresentationTheme) -> String? {
let encoding = PresentationThemeEncoding() let encoding = PresentationThemeEncoding()
@ -321,7 +322,7 @@ private class PresentationThemeDecodingLevel {
} }
} }
public func makePresentationTheme(data: Data) -> PresentationTheme? { public func makePresentationTheme(data: Data, resolvedWallpaper: TelegramWallpaper? = nil) -> PresentationTheme? {
guard let string = String(data: data, encoding: .utf8) else { guard let string = String(data: data, encoding: .utf8) else {
return nil return nil
} }
@ -378,6 +379,7 @@ public func makePresentationTheme(data: Data) -> PresentationTheme? {
} }
let decoder = PresentationThemeDecoding(referencing: topLevel.data) let decoder = PresentationThemeDecoding(referencing: topLevel.data)
decoder.resolvedWallpaper = resolvedWallpaper
if let value = try? decoder.unbox(topLevel.data, as: PresentationTheme.self) { if let value = try? decoder.unbox(topLevel.data, as: PresentationTheme.self) {
return value return value
} }
@ -392,10 +394,11 @@ class PresentationThemeDecoding: Decoder {
public var userInfo: [CodingUserInfoKey : Any] { public var userInfo: [CodingUserInfoKey : Any] {
return [:] return [:]
} }
var referenceTheme: PresentationTheme? var referenceTheme: PresentationTheme?
var serviceBackgroundColor: UIColor? var serviceBackgroundColor: UIColor?
var resolvedWallpaper: TelegramWallpaper?
private var _referenceCoding: PresentationThemeEncoding? private var _referenceCoding: PresentationThemeEncoding?
fileprivate var referenceCoding: PresentationThemeEncoding? { fileprivate var referenceCoding: PresentationThemeEncoding? {
if let referenceCoding = self._referenceCoding { if let referenceCoding = self._referenceCoding {

View File

@ -136,7 +136,7 @@ final class AuthorizedApplicationContext {
self.notificationController = NotificationContainerController(context: context) self.notificationController = NotificationContainerController(context: context)
self.mainWindow.previewThemeAccentColor = presentationData.theme.rootController.navigationBar.accentTextColor self.mainWindow.previewThemeAccentColor = presentationData.theme.rootController.navigationBar.accentTextColor
self.mainWindow.previewThemeDarkBlur = presentationData.theme.chatList.searchBarKeyboardColor == .dark self.mainWindow.previewThemeDarkBlur = presentationData.theme.rootController.keyboardColor == .dark
self.mainWindow.setupVolumeControlStatusBarGraphics(presentationData.volumeControlStatusBarIcons.images) self.mainWindow.setupVolumeControlStatusBarGraphics(presentationData.volumeControlStatusBarIcons.images)
self.rootController = TelegramRootController(context: context) self.rootController = TelegramRootController(context: context)
@ -740,7 +740,7 @@ final class AuthorizedApplicationContext {
if let strongSelf = self { if let strongSelf = self {
if previousTheme.swap(presentationData.theme) !== presentationData.theme { if previousTheme.swap(presentationData.theme) !== presentationData.theme {
strongSelf.mainWindow.previewThemeAccentColor = presentationData.theme.rootController.navigationBar.accentTextColor strongSelf.mainWindow.previewThemeAccentColor = presentationData.theme.rootController.navigationBar.accentTextColor
strongSelf.mainWindow.previewThemeDarkBlur = presentationData.theme.chatList.searchBarKeyboardColor == .dark strongSelf.mainWindow.previewThemeDarkBlur = presentationData.theme.rootController.keyboardColor == .dark
strongSelf.lockedCoveringView.updateTheme(presentationData.theme) strongSelf.lockedCoveringView.updateTheme(presentationData.theme)
strongSelf.rootController.updateTheme(NavigationControllerTheme(presentationTheme: presentationData.theme)) strongSelf.rootController.updateTheme(NavigationControllerTheme(presentationTheme: presentationData.theme))
} }

View File

@ -120,7 +120,7 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
#endif #endif
self.codeField.textField.returnKeyType = .done self.codeField.textField.returnKeyType = .done
self.codeField.textField.textColor = self.theme.list.itemPrimaryTextColor self.codeField.textField.textColor = self.theme.list.itemPrimaryTextColor
self.codeField.textField.keyboardAppearance = self.theme.chatList.searchBarKeyboardColor.keyboardAppearance self.codeField.textField.keyboardAppearance = self.theme.rootController.keyboardColor.keyboardAppearance
self.codeField.textField.disableAutomaticKeyboardHandling = [.forward, .backward] self.codeField.textField.disableAutomaticKeyboardHandling = [.forward, .backward]
self.codeField.textField.tintColor = self.theme.list.itemAccentColor self.codeField.textField.tintColor = self.theme.list.itemAccentColor

View File

@ -70,7 +70,7 @@ final class AuthorizationSequencePasswordEntryControllerNode: ASDisplayNode, UIT
self.codeField.textField.textAlignment = .natural self.codeField.textField.textAlignment = .natural
self.codeField.textField.isSecureTextEntry = true self.codeField.textField.isSecureTextEntry = true
self.codeField.textField.returnKeyType = .done self.codeField.textField.returnKeyType = .done
self.codeField.textField.keyboardAppearance = self.theme.chatList.searchBarKeyboardColor.keyboardAppearance self.codeField.textField.keyboardAppearance = self.theme.rootController.keyboardColor.keyboardAppearance
self.codeField.textField.disableAutomaticKeyboardHandling = [.forward, .backward] self.codeField.textField.disableAutomaticKeyboardHandling = [.forward, .backward]
self.codeField.textField.tintColor = self.theme.list.itemAccentColor self.codeField.textField.tintColor = self.theme.list.itemAccentColor

View File

@ -58,7 +58,7 @@ final class AuthorizationSequencePasswordRecoveryControllerNode: ASDisplayNode,
self.codeField.textField.textAlignment = .center self.codeField.textField.textAlignment = .center
self.codeField.textField.attributedPlaceholder = NSAttributedString(string: self.strings.TwoStepAuth_RecoveryCode, font: Font.regular(20.0), textColor: self.theme.list.itemPlaceholderTextColor) self.codeField.textField.attributedPlaceholder = NSAttributedString(string: self.strings.TwoStepAuth_RecoveryCode, font: Font.regular(20.0), textColor: self.theme.list.itemPlaceholderTextColor)
self.codeField.textField.returnKeyType = .done self.codeField.textField.returnKeyType = .done
self.codeField.textField.keyboardAppearance = self.theme.chatList.searchBarKeyboardColor.keyboardAppearance self.codeField.textField.keyboardAppearance = self.theme.rootController.keyboardColor.keyboardAppearance
self.codeField.textField.disableAutomaticKeyboardHandling = [.forward, .backward] self.codeField.textField.disableAutomaticKeyboardHandling = [.forward, .backward]
self.codeField.textField.tintColor = self.theme.list.itemAccentColor self.codeField.textField.tintColor = self.theme.list.itemAccentColor

View File

@ -103,8 +103,8 @@ private final class PhoneAndCountryNode: ASDisplayNode {
self.addSubnode(self.countryButton) self.addSubnode(self.countryButton)
self.addSubnode(self.phoneInputNode) self.addSubnode(self.phoneInputNode)
self.phoneInputNode.countryCodeField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance self.phoneInputNode.countryCodeField.textField.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance
self.phoneInputNode.numberField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance self.phoneInputNode.numberField.textField.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance
self.phoneInputNode.countryCodeField.textField.textColor = theme.list.itemPrimaryTextColor self.phoneInputNode.countryCodeField.textField.textColor = theme.list.itemPrimaryTextColor
self.phoneInputNode.numberField.textField.textColor = theme.list.itemPrimaryTextColor self.phoneInputNode.numberField.textField.textColor = theme.list.itemPrimaryTextColor
self.phoneInputNode.countryCodeField.textField.tintColor = theme.list.itemAccentColor self.phoneInputNode.countryCodeField.textField.tintColor = theme.list.itemAccentColor

View File

@ -108,7 +108,7 @@ final class AuthorizationSequenceSignUpControllerNode: ASDisplayNode, UITextFiel
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) { if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
self.firstNameField.textField.textContentType = .givenName self.firstNameField.textField.textContentType = .givenName
} }
self.firstNameField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance self.firstNameField.textField.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance
self.firstNameField.textField.tintColor = theme.list.itemAccentColor self.firstNameField.textField.tintColor = theme.list.itemAccentColor
self.lastNameField = TextFieldNode() self.lastNameField = TextFieldNode()
@ -122,7 +122,7 @@ final class AuthorizationSequenceSignUpControllerNode: ASDisplayNode, UITextFiel
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) { if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
self.lastNameField.textField.textContentType = .familyName self.lastNameField.textField.textContentType = .familyName
} }
self.lastNameField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance self.lastNameField.textField.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance
self.lastNameField.textField.tintColor = theme.list.itemAccentColor self.lastNameField.textField.tintColor = theme.list.itemAccentColor
self.currentPhotoNode = ASImageNode() self.currentPhotoNode = ASImageNode()

View File

@ -2769,7 +2769,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
} }
self.chatDisplayNode.updateTypingActivity = { [weak self] value in self.chatDisplayNode.updateTypingActivity = { [weak self] value in
if let strongSelf = self, strongSelf.presentationInterfaceState.interfaceState.editMessage == nil { if let strongSelf = self, strongSelf.presentationInterfaceState.interfaceState.editMessage == nil && !strongSelf.presentationInterfaceState.isScheduledMessages {
if value { if value {
strongSelf.typingActivityPromise.set(Signal<Bool, NoError>.single(true) strongSelf.typingActivityPromise.set(Signal<Bool, NoError>.single(true)
|> then( |> then(
@ -5155,7 +5155,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
ActionSheetButtonItem(title: self.presentationData.strings.Conversation_FileICloudDrive, action: { [weak self, weak actionSheet] in ActionSheetButtonItem(title: self.presentationData.strings.Conversation_FileICloudDrive, action: { [weak self, weak actionSheet] in
actionSheet?.dismissAnimated() actionSheet?.dismissAnimated()
if let strongSelf = self { if let strongSelf = self {
strongSelf.present(legacyICloudFileController(theme: strongSelf.presentationData.theme, completion: { urls in strongSelf.present(legacyICloudFilePicker(theme: strongSelf.presentationData.theme, completion: { urls in
if let strongSelf = self, !urls.isEmpty { if let strongSelf = self, !urls.isEmpty {
var signals: [Signal<ICloudFileDescription?, NoError>] = [] var signals: [Signal<ICloudFileDescription?, NoError>] = []
for url in urls { for url in urls {

View File

@ -186,7 +186,7 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
self.effectView = UIVisualEffectView() self.effectView = UIVisualEffectView()
if #available(iOS 9.0, *) { if #available(iOS 9.0, *) {
} else { } else {
if self.presentationData.theme.chatList.searchBarKeyboardColor == .dark { if self.presentationData.theme.rootController.keyboardColor == .dark {
self.effectView.effect = UIBlurEffect(style: .dark) self.effectView.effect = UIBlurEffect(style: .dark)
} else { } else {
self.effectView.effect = UIBlurEffect(style: .light) self.effectView.effect = UIBlurEffect(style: .light)
@ -310,7 +310,7 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
if #available(iOS 9.0, *) { if #available(iOS 9.0, *) {
} else { } else {
if self.presentationData.theme.chatList.searchBarKeyboardColor == .dark { if self.presentationData.theme.rootController.keyboardColor == .dark {
self.effectView.effect = UIBlurEffect(style: .dark) self.effectView.effect = UIBlurEffect(style: .dark)
} else { } else {
self.effectView.effect = UIBlurEffect(style: .light) self.effectView.effect = UIBlurEffect(style: .light)

View File

@ -502,7 +502,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
textColor = presentationInterfaceState.theme.chat.inputPanel.inputTextColor textColor = presentationInterfaceState.theme.chat.inputPanel.inputTextColor
tintColor = presentationInterfaceState.theme.list.itemAccentColor tintColor = presentationInterfaceState.theme.list.itemAccentColor
baseFontSize = max(17.0, presentationInterfaceState.fontSize.baseDisplaySize) baseFontSize = max(17.0, presentationInterfaceState.fontSize.baseDisplaySize)
keyboardAppearance = presentationInterfaceState.theme.chat.inputPanel.keyboardColor.keyboardAppearance keyboardAppearance = presentationInterfaceState.theme.rootController.keyboardColor.keyboardAppearance
} }
let paragraphStyle = NSMutableParagraphStyle() let paragraphStyle = NSMutableParagraphStyle()
@ -691,7 +691,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
} }
} }
let keyboardAppearance = interfaceState.theme.chat.inputPanel.keyboardColor.keyboardAppearance let keyboardAppearance = interfaceState.theme.rootController.keyboardColor.keyboardAppearance
if let textInputNode = self.textInputNode, textInputNode.keyboardAppearance != keyboardAppearance, textInputNode.isFirstResponder() { if let textInputNode = self.textInputNode, textInputNode.keyboardAppearance != keyboardAppearance, textInputNode.isFirstResponder() {
if textInputNode.isCurrentlyEmoji() { if textInputNode.isCurrentlyEmoji() {
textInputNode.initialPrimaryLanguage = "emoji" textInputNode.initialPrimaryLanguage = "emoji"

View File

@ -52,7 +52,7 @@ private final class ChatTextLinkEditInputFieldNode: ASDisplayNode, ASEditableTex
self.textInputNode.clipsToBounds = true self.textInputNode.clipsToBounds = true
self.textInputNode.hitTestSlop = UIEdgeInsets(top: -5.0, left: -5.0, bottom: -5.0, right: -5.0) self.textInputNode.hitTestSlop = UIEdgeInsets(top: -5.0, left: -5.0, bottom: -5.0, right: -5.0)
self.textInputNode.textContainerInset = UIEdgeInsets(top: self.inputInsets.top, left: 0.0, bottom: self.inputInsets.bottom, right: 0.0) self.textInputNode.textContainerInset = UIEdgeInsets(top: self.inputInsets.top, left: 0.0, bottom: self.inputInsets.bottom, right: 0.0)
self.textInputNode.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance self.textInputNode.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance
self.textInputNode.keyboardType = .URL self.textInputNode.keyboardType = .URL
self.textInputNode.autocapitalizationType = .none self.textInputNode.autocapitalizationType = .none
self.textInputNode.returnKeyType = .done self.textInputNode.returnKeyType = .done
@ -77,7 +77,7 @@ private final class ChatTextLinkEditInputFieldNode: ASDisplayNode, ASEditableTex
self.theme = theme self.theme = theme
self.backgroundNode.image = generateStretchableFilledCircleImage(diameter: 33.0, color: self.theme.actionSheet.inputHollowBackgroundColor, strokeColor: self.theme.actionSheet.inputBorderColor, strokeWidth: 1.0) self.backgroundNode.image = generateStretchableFilledCircleImage(diameter: 33.0, color: self.theme.actionSheet.inputHollowBackgroundColor, strokeColor: self.theme.actionSheet.inputBorderColor, strokeWidth: 1.0)
self.textInputNode.keyboardAppearance = self.theme.chatList.searchBarKeyboardColor.keyboardAppearance self.textInputNode.keyboardAppearance = self.theme.rootController.keyboardColor.keyboardAppearance
self.placeholderNode.attributedText = NSAttributedString(string: self.placeholderNode.attributedText?.string ?? "", font: Font.regular(17.0), textColor: self.theme.actionSheet.inputPlaceholderColor) self.placeholderNode.attributedText = NSAttributedString(string: self.placeholderNode.attributedText?.string ?? "", font: Font.regular(17.0), textColor: self.theme.actionSheet.inputPlaceholderColor)
self.textInputNode.tintColor = self.theme.actionSheet.controlAccentColor self.textInputNode.tintColor = self.theme.actionSheet.controlAccentColor
} }

View File

@ -67,7 +67,7 @@ final class ContactMultiselectionControllerNode: ASDisplayNode {
} }
self.contactListNode = ContactListNode(context: context, presentation: .single(.natural(options: options, includeChatList: includeChatList)), filters: filters, selectionState: ContactListNodeGroupSelectionState()) self.contactListNode = ContactListNode(context: context, presentation: .single(.natural(options: options, includeChatList: includeChatList)), filters: filters, selectionState: ContactListNodeGroupSelectionState())
self.tokenListNode = EditableTokenListNode(theme: EditableTokenListNodeTheme(backgroundColor: self.presentationData.theme.rootController.navigationBar.backgroundColor, separatorColor: self.presentationData.theme.rootController.navigationBar.separatorColor, placeholderTextColor: self.presentationData.theme.list.itemPlaceholderTextColor, primaryTextColor: self.presentationData.theme.list.itemPrimaryTextColor, selectedTextColor: self.presentationData.theme.list.itemAccentColor, accentColor: self.presentationData.theme.list.itemAccentColor, keyboardColor: self.presentationData.theme.chatList.searchBarKeyboardColor), placeholder: placeholder) self.tokenListNode = EditableTokenListNode(theme: EditableTokenListNodeTheme(backgroundColor: self.presentationData.theme.rootController.navigationBar.backgroundColor, separatorColor: self.presentationData.theme.rootController.navigationBar.separatorColor, placeholderTextColor: self.presentationData.theme.list.itemPlaceholderTextColor, primaryTextColor: self.presentationData.theme.list.itemPrimaryTextColor, selectedTextColor: self.presentationData.theme.list.itemAccentColor, accentColor: self.presentationData.theme.list.itemAccentColor, keyboardColor: self.presentationData.theme.rootController.keyboardColor), placeholder: placeholder)
super.init() super.init()

View File

@ -263,7 +263,7 @@ class PaneSearchBarNode: ASDisplayNode, UITextFieldDelegate {
self.iconNode.image = generateLoupeIcon(color: theme.chat.inputMediaPanel.stickersSearchControlColor) self.iconNode.image = generateLoupeIcon(color: theme.chat.inputMediaPanel.stickersSearchControlColor)
self.clearButton.setImage(generateClearIcon(color: theme.chat.inputMediaPanel.stickersSearchControlColor), for: []) self.clearButton.setImage(generateClearIcon(color: theme.chat.inputMediaPanel.stickersSearchControlColor), for: [])
self.cancelButton.setAttributedTitle(NSAttributedString(string: strings.Common_Cancel, font: Font.regular(17.0), textColor: theme.chat.inputPanel.panelControlAccentColor), for: []) self.cancelButton.setAttributedTitle(NSAttributedString(string: strings.Common_Cancel, font: Font.regular(17.0), textColor: theme.chat.inputPanel.panelControlAccentColor), for: [])
self.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance self.textField.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance
self.textField.tintColor = theme.list.itemAccentColor self.textField.tintColor = theme.list.itemAccentColor
if let (boundingSize, leftInset, rightInset) = self.validLayout { if let (boundingSize, leftInset, rightInset) = self.validLayout {

View File

@ -62,7 +62,6 @@
09FFBCD72281BB2D00C33B4B /* ChatTextLinkEditController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09FFBCD62281BB2D00C33B4B /* ChatTextLinkEditController.swift */; }; 09FFBCD72281BB2D00C33B4B /* ChatTextLinkEditController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09FFBCD62281BB2D00C33B4B /* ChatTextLinkEditController.swift */; };
D000CABC21F158AD0011B15D /* PrepareSecretThumbnailData.swift in Sources */ = {isa = PBXBuildFile; fileRef = D000CABB21F158AD0011B15D /* PrepareSecretThumbnailData.swift */; }; D000CABC21F158AD0011B15D /* PrepareSecretThumbnailData.swift in Sources */ = {isa = PBXBuildFile; fileRef = D000CABB21F158AD0011B15D /* PrepareSecretThumbnailData.swift */; };
D0068FA821760FA300D1B315 /* StoreDownloadedMedia.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0068FA721760FA300D1B315 /* StoreDownloadedMedia.swift */; }; D0068FA821760FA300D1B315 /* StoreDownloadedMedia.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0068FA721760FA300D1B315 /* StoreDownloadedMedia.swift */; };
D007019C2029E8F2006B9E34 /* LegacyICloudFileController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D007019B2029E8F2006B9E34 /* LegacyICloudFileController.swift */; };
D007019E2029EFDD006B9E34 /* ICloudResources.swift in Sources */ = {isa = PBXBuildFile; fileRef = D007019D2029EFDD006B9E34 /* ICloudResources.swift */; }; D007019E2029EFDD006B9E34 /* ICloudResources.swift in Sources */ = {isa = PBXBuildFile; fileRef = D007019D2029EFDD006B9E34 /* ICloudResources.swift */; };
D008178222B47464008A895F /* NotificationContentContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = D008178122B47464008A895F /* NotificationContentContext.swift */; }; D008178222B47464008A895F /* NotificationContentContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = D008178122B47464008A895F /* NotificationContentContext.swift */; };
D00817D022B47A14008A895F /* WakeupManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D00817B622B47A12008A895F /* WakeupManager.swift */; }; D00817D022B47A14008A895F /* WakeupManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D00817B622B47A12008A895F /* WakeupManager.swift */; };
@ -634,7 +633,6 @@
D002A0DA1E9C190700A81812 /* SoftwareVideoThumbnailLayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SoftwareVideoThumbnailLayer.swift; sourceTree = "<group>"; }; D002A0DA1E9C190700A81812 /* SoftwareVideoThumbnailLayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SoftwareVideoThumbnailLayer.swift; sourceTree = "<group>"; };
D002A0DC1E9CD52A00A81812 /* ChatMediaInputRecentGifsItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatMediaInputRecentGifsItem.swift; sourceTree = "<group>"; }; D002A0DC1E9CD52A00A81812 /* ChatMediaInputRecentGifsItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatMediaInputRecentGifsItem.swift; sourceTree = "<group>"; };
D0068FA721760FA300D1B315 /* StoreDownloadedMedia.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreDownloadedMedia.swift; sourceTree = "<group>"; }; D0068FA721760FA300D1B315 /* StoreDownloadedMedia.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreDownloadedMedia.swift; sourceTree = "<group>"; };
D007019B2029E8F2006B9E34 /* LegacyICloudFileController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegacyICloudFileController.swift; sourceTree = "<group>"; };
D007019D2029EFDD006B9E34 /* ICloudResources.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ICloudResources.swift; sourceTree = "<group>"; }; D007019D2029EFDD006B9E34 /* ICloudResources.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ICloudResources.swift; sourceTree = "<group>"; };
D008178122B47464008A895F /* NotificationContentContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationContentContext.swift; sourceTree = "<group>"; }; D008178122B47464008A895F /* NotificationContentContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationContentContext.swift; sourceTree = "<group>"; };
D00817B622B47A12008A895F /* WakeupManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WakeupManager.swift; sourceTree = "<group>"; }; D00817B622B47A12008A895F /* WakeupManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WakeupManager.swift; sourceTree = "<group>"; };
@ -1740,7 +1738,6 @@
children = ( children = (
D00E15251DDBD4E700ACF65C /* LegacyCamera.swift */, D00E15251DDBD4E700ACF65C /* LegacyCamera.swift */,
D06BB8811F58994B0084FC30 /* LegacyInstantVideoController.swift */, D06BB8811F58994B0084FC30 /* LegacyInstantVideoController.swift */,
D007019B2029E8F2006B9E34 /* LegacyICloudFileController.swift */,
D0380DAC204ED434000414AB /* LegacyLiveUploadInterface.swift */, D0380DAC204ED434000414AB /* LegacyLiveUploadInterface.swift */,
D0B21B1E22156D92003F741D /* LegacyCache.swift */, D0B21B1E22156D92003F741D /* LegacyCache.swift */,
); );
@ -3064,7 +3061,6 @@
090B48C82200BCA8005083FA /* WallpaperUploadManager.swift in Sources */, 090B48C82200BCA8005083FA /* WallpaperUploadManager.swift in Sources */,
09F2158D225CF5BC00AEDF6D /* Pasteboard.swift in Sources */, 09F2158D225CF5BC00AEDF6D /* Pasteboard.swift in Sources */,
D0C26D571FDF2388004ABF18 /* OpenChatMessage.swift in Sources */, D0C26D571FDF2388004ABF18 /* OpenChatMessage.swift in Sources */,
D007019C2029E8F2006B9E34 /* LegacyICloudFileController.swift in Sources */,
D000CABC21F158AD0011B15D /* PrepareSecretThumbnailData.swift in Sources */, D000CABC21F158AD0011B15D /* PrepareSecretThumbnailData.swift in Sources */,
D08BDF641FA37BEA009D08E1 /* ChatRecordingPreviewInputPanelNode.swift in Sources */, D08BDF641FA37BEA009D08E1 /* ChatRecordingPreviewInputPanelNode.swift in Sources */,
D0943B071FDEC529001522CC /* InstantVideoRadialStatusNode.swift in Sources */, D0943B071FDEC529001522CC /* InstantVideoRadialStatusNode.swift in Sources */,

View File

@ -56,10 +56,42 @@ public struct PresentationLocalTheme: PostboxCoding, Equatable {
} }
} }
public struct PresentationCloudTheme: PostboxCoding, Equatable {
public let theme: TelegramTheme
public let resolvedWallpaper: TelegramWallpaper?
public init(theme: TelegramTheme, resolvedWallpaper: TelegramWallpaper?) {
self.theme = theme
self.resolvedWallpaper = resolvedWallpaper
}
public init(decoder: PostboxDecoder) {
self.theme = decoder.decodeObjectForKey("theme", decoder: { TelegramTheme(decoder: $0) }) as! TelegramTheme
self.resolvedWallpaper = decoder.decodeObjectForKey("wallpaper", decoder: { TelegramWallpaper(decoder: $0) }) as? TelegramWallpaper
}
public func encode(_ encoder: PostboxEncoder) {
encoder.encodeObject(self.theme, forKey: "theme")
if let resolvedWallpaper = self.resolvedWallpaper {
encoder.encodeObject(resolvedWallpaper, forKey: "wallpaper")
}
}
public static func ==(lhs: PresentationCloudTheme, rhs: PresentationCloudTheme) -> Bool {
if lhs.theme != rhs.theme {
return false
}
if lhs.resolvedWallpaper != rhs.resolvedWallpaper {
return false
}
return true
}
}
public enum PresentationThemeReference: PostboxCoding, Equatable { public enum PresentationThemeReference: PostboxCoding, Equatable {
case builtin(PresentationBuiltinThemeReference) case builtin(PresentationBuiltinThemeReference)
case local(PresentationLocalTheme) case local(PresentationLocalTheme)
case cloud(TelegramTheme) case cloud(PresentationCloudTheme)
public init(decoder: PostboxDecoder) { public init(decoder: PostboxDecoder) {
switch decoder.decodeInt32ForKey("v", orElse: 0) { switch decoder.decodeInt32ForKey("v", orElse: 0) {
@ -68,7 +100,7 @@ public enum PresentationThemeReference: PostboxCoding, Equatable {
case 1: case 1:
self = .local(decoder.decodeObjectForKey("localTheme", decoder: { PresentationLocalTheme(decoder: $0) }) as! PresentationLocalTheme) self = .local(decoder.decodeObjectForKey("localTheme", decoder: { PresentationLocalTheme(decoder: $0) }) as! PresentationLocalTheme)
case 2: case 2:
self = .cloud(decoder.decodeObjectForKey("theme", decoder: { TelegramTheme(decoder: $0) }) as! TelegramTheme) self = .cloud(decoder.decodeObjectForKey("cloudTheme", decoder: { PresentationCloudTheme(decoder: $0) }) as! PresentationCloudTheme)
default: default:
assertionFailure() assertionFailure()
self = .builtin(.dayClassic) self = .builtin(.dayClassic)
@ -85,7 +117,7 @@ public enum PresentationThemeReference: PostboxCoding, Equatable {
encoder.encodeObject(theme, forKey: "localTheme") encoder.encodeObject(theme, forKey: "localTheme")
case let .cloud(theme): case let .cloud(theme):
encoder.encodeInt32(2, forKey: "v") encoder.encodeInt32(2, forKey: "v")
encoder.encodeObject(theme, forKey: "theme") encoder.encodeObject(theme, forKey: "cloudTheme")
} }
} }
@ -135,7 +167,7 @@ public enum PresentationThemeReference: PostboxCoding, Equatable {
id = themeId(for: theme.resource.fileId) id = themeId(for: theme.resource.fileId)
case let .cloud(theme): case let .cloud(theme):
namespace = 2 namespace = 2
id = themeId(for: theme.id) id = themeId(for: theme.theme.id)
} }
return (Int64(namespace) << 32) | Int64(bitPattern: UInt64(UInt32(bitPattern: id))) return (Int64(namespace) << 32) | Int64(bitPattern: UInt64(UInt32(bitPattern: id)))
@ -379,9 +411,12 @@ public struct PresentationThemeSettings: PreferencesEntry {
case let .local(theme): case let .local(theme):
resources.append(theme.resource.id) resources.append(theme.resource.id)
case let .cloud(theme): case let .cloud(theme):
if let file = theme.file { if let file = theme.theme.file {
resources.append(file.resource.id) resources.append(file.resource.id)
} }
if let chatWallpaper = theme.resolvedWallpaper {
resources.append(contentsOf: wallpaperResources(chatWallpaper))
}
} }
return resources return resources
} }