mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-08 19:10:53 +00:00
Cloud themes improvements
This commit is contained in:
parent
4ac24e4369
commit
f3db3a29b0
@ -8,6 +8,11 @@
|
||||
<string>en</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>${APP_NAME}</string>
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
<array>
|
||||
<dict/>
|
||||
<dict/>
|
||||
</array>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIcons</key>
|
||||
@ -332,5 +337,29 @@
|
||||
<false/>
|
||||
<key>UIViewGroupOpacity</key>
|
||||
<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>
|
||||
</plist>
|
||||
|
@ -33,7 +33,5 @@
|
||||
<string>merchant.privatbank.test.telergramios</string>
|
||||
<string>merchant.privatbank.prod.telergram</string>
|
||||
</array>
|
||||
<key>com.apple.developer.carplay-messaging</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -4660,19 +4660,27 @@ Any member of this group will be able to see messages in the channel.";
|
||||
|
||||
"Appearance.CreateTheme" = "Create New Theme";
|
||||
"Appearance.EditTheme" = "Edit Theme";
|
||||
"Appearance.ShareTheme" = "Share";
|
||||
"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.ViewTheme" = "VIEW THEME";
|
||||
|
||||
"Message.Theme" = "Color Theme";
|
||||
|
||||
"EditTheme.Title" = "Edit Theme";
|
||||
"EditTheme.Preview" = "PREVIEW";
|
||||
"EditTheme.Title" = "Title";
|
||||
"EditTheme.ShortLink" = "Short Link";
|
||||
"EditTheme.ShortLinkInfo" = "Short Link";
|
||||
"EditTheme.CreateTitle" = "Create Theme";
|
||||
"EditTheme.EditTitle" = "Edit Theme";
|
||||
"EditTheme.Title" = "Theme Name";
|
||||
"EditTheme.ShortLink" = "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.";
|
||||
"Theme.ErrorNotFound" = "Sorry, this color theme doesn't seem to exist.";
|
||||
|
@ -152,7 +152,7 @@ private final class BotCheckoutPasswordAlertContentNode: AlertContentNode {
|
||||
self.textFieldNode.textField.textColor = theme.actionSheet.primaryTextColor
|
||||
self.textFieldNode.textField.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.tintColor = theme.list.itemAccentColor
|
||||
|
||||
|
@ -42,7 +42,7 @@ final class BotPaymentCardInputItemNode: BotPaymentItemNode, STPPaymentCardTextF
|
||||
self.cardField.textColor = theme.list.itemPrimaryTextColor
|
||||
self.cardField.textErrorColor = theme.list.itemDestructiveColor
|
||||
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))
|
||||
|
@ -79,7 +79,7 @@ final class BotPaymentFieldItemNode: BotPaymentItemNode, UITextFieldDelegate {
|
||||
self.titleNode.attributedText = NSAttributedString(string: self.title, font: titleFont, 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.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
self.textField.textField.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance
|
||||
self.textField.textField.tintColor = theme.list.itemAccentColor
|
||||
}
|
||||
|
||||
@ -97,7 +97,7 @@ final class BotPaymentFieldItemNode: BotPaymentItemNode, UITextFieldDelegate {
|
||||
if self.theme !== theme {
|
||||
self.theme = theme
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -321,7 +321,7 @@ class CreatePollOptionItemNode: ItemListRevealOptionsItemNode, ItemListItemNode,
|
||||
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.textNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: params.width - leftInset - rightInset, height: textLayout.size.height + 1.0))
|
||||
|
@ -93,7 +93,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
||||
self.effectView = UIVisualEffectView()
|
||||
if #available(iOS 9.0, *) {
|
||||
} else {
|
||||
if theme.chatList.searchBarKeyboardColor == .dark {
|
||||
if theme.rootController.keyboardColor == .dark {
|
||||
self.effectView.effect = UIBlurEffect(style: .dark)
|
||||
} else {
|
||||
self.effectView.effect = UIBlurEffect(style: .light)
|
||||
|
@ -17,8 +17,8 @@ import OpenInExternalAppUI
|
||||
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 backwardImage = UIImage(bundleImageName: "Media Gallery/BackwardButton")
|
||||
private let forwardImage = UIImage(bundleImageName: "Media Gallery/ForwardButton")
|
||||
private let backwardImage = generateTintedImage(image: UIImage(bundleImageName: "Media Gallery/BackwardButton"), color: .white)
|
||||
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 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.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))
|
||||
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))
|
||||
if let image = self.backwardButton.image(for: .normal) {
|
||||
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))
|
||||
|
||||
|
@ -473,7 +473,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
}
|
||||
}
|
||||
}
|
||||
seekable = value.duration >= 45.0
|
||||
seekable = value.duration >= 30.0
|
||||
}
|
||||
|
||||
var fetching = false
|
||||
|
@ -672,7 +672,7 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo
|
||||
if strongSelf.inputSeparator == nil {
|
||||
animateIn = true
|
||||
}
|
||||
let keyboardAppearance = item.theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
let keyboardAppearance = item.theme.rootController.keyboardColor.keyboardAppearance
|
||||
switch editingName {
|
||||
case let .personName(firstName, lastName):
|
||||
if strongSelf.inputSeparator == nil {
|
||||
|
@ -251,7 +251,7 @@ public class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNod
|
||||
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.textNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: params.width - leftInset - 16.0 - rightInset, height: textLayout.size.height + 1.0))
|
||||
|
@ -13,6 +13,21 @@ public enum ItemListSingleLineInputItemType: Equatable {
|
||||
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 {
|
||||
let theme: PresentationTheme
|
||||
let strings: PresentationStrings
|
||||
@ -22,7 +37,7 @@ public class ItemListSingleLineInputItem: ListViewItem, ItemListItem {
|
||||
let type: ItemListSingleLineInputItemType
|
||||
let returnKeyType: UIReturnKeyType
|
||||
let spacing: CGFloat
|
||||
let clearButton: Bool
|
||||
let clearType: ItemListSingleLineInputClearType
|
||||
let enabled: Bool
|
||||
public let sectionId: ItemListSectionId
|
||||
let action: () -> Void
|
||||
@ -32,7 +47,7 @@ public class ItemListSingleLineInputItem: ListViewItem, ItemListItem {
|
||||
let updatedFocus: ((Bool) -> Void)?
|
||||
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.strings = strings
|
||||
self.title = title
|
||||
@ -41,7 +56,7 @@ public class ItemListSingleLineInputItem: ListViewItem, ItemListItem {
|
||||
self.type = type
|
||||
self.returnKeyType = returnKeyType
|
||||
self.spacing = spacing
|
||||
self.clearButton = clearButton
|
||||
self.clearType = clearType
|
||||
self.enabled = enabled
|
||||
self.tag = tag
|
||||
self.sectionId = sectionId
|
||||
@ -153,7 +168,7 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg
|
||||
self.textNode.textField.font = Font.regular(17.0)
|
||||
if let item = self.item {
|
||||
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.accessibilityHint = item.placeholder
|
||||
}
|
||||
@ -180,7 +195,7 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg
|
||||
let leftInset: CGFloat = 16.0 + params.leftInset
|
||||
var rightInset: CGFloat = 16.0 + params.rightInset
|
||||
|
||||
if item.clearButton {
|
||||
if item.clearType.hasButton {
|
||||
rightInset += 32.0
|
||||
}
|
||||
|
||||
@ -210,7 +225,7 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg
|
||||
strongSelf.backgroundNode.backgroundColor = item.theme.list.itemBlocksBackgroundColor
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@ -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.isHidden = !item.clearButton || item.text.isEmpty
|
||||
strongSelf.clearButtonNode.isHidden = !item.clearButton || item.text.isEmpty
|
||||
strongSelf.clearButtonNode.isAccessibilityElement = !strongSelf.clearButtonNode.isHidden
|
||||
strongSelf.updateClearButtonVisibility()
|
||||
|
||||
if strongSelf.backgroundNode.supernode == nil {
|
||||
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) {
|
||||
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) {
|
||||
self.item?.updatedFocus?(true)
|
||||
self.updateClearButtonVisibility()
|
||||
}
|
||||
|
||||
@objc public func textFieldDidEndEditing(_ textField: UITextField) {
|
||||
self.item?.updatedFocus?(false)
|
||||
self.updateClearButtonVisibility()
|
||||
}
|
||||
|
||||
public func animateError() {
|
||||
|
@ -7,6 +7,7 @@
|
||||
objects = {
|
||||
|
||||
/* 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, ); }; };
|
||||
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, ); }; };
|
||||
@ -32,6 +33,7 @@
|
||||
/* End PBXBuildFile 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; };
|
||||
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>"; };
|
||||
@ -111,6 +113,7 @@
|
||||
D03E3F782304C50D0049C28B /* LegacyMediaPickers.swift */,
|
||||
D03E3F7B2304C50D0049C28B /* LegacySuggestionContext.swift */,
|
||||
D03E3F7F2304C50D0049C28B /* LegacyWallpaperPicker.swift */,
|
||||
096C16E5231741290047887D /* LegacyICloudFilePicker.swift */,
|
||||
D03E3F6C2304C4840049C28B /* LegacyMediaPickerUI.h */,
|
||||
);
|
||||
path = Sources;
|
||||
@ -219,6 +222,7 @@
|
||||
files = (
|
||||
D03E3F872304C50E0049C28B /* LegacyWallpaperPicker.swift in Sources */,
|
||||
D03E3F842304C50E0049C28B /* LegacyImagePicker.swift in Sources */,
|
||||
096C16E62317412A0047887D /* LegacyICloudFilePicker.swift in Sources */,
|
||||
D03E3F822304C50E0049C28B /* LegacyAttachmentMenu.swift in Sources */,
|
||||
D03E3F852304C50E0049C28B /* LegacyImageProcessors.m in Sources */,
|
||||
D03E3F802304C50E0049C28B /* LegacyMediaPickers.swift in Sources */,
|
||||
|
@ -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)?
|
||||
let legacyController = LegacyICloudFileController(presentation: .modal(animateIn: true), theme: theme, completion: { urls in
|
||||
dismissImpl?()
|
||||
@ -38,25 +52,9 @@ func legacyICloudFileController(theme: PresentationTheme, completion: @escaping
|
||||
})
|
||||
legacyController.statusBar.statusBarStyle = .Black
|
||||
|
||||
let documentTypes: [String] = [
|
||||
"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)
|
||||
let controller = UIDocumentPickerViewController(documentTypes: documentTypes, in: mode.documentPickerMode)
|
||||
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
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ final class PasscodeSetupControllerNode: ASDisplayNode {
|
||||
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.alpha = passcodeType == .alphanumeric ? 1.0 : 0.0
|
||||
self.inputFieldBackgroundNode.contentMode = .scaleToFill
|
||||
|
@ -143,7 +143,7 @@ final class FormControllerTextInputItemNode: FormBlockItemNode<FormControllerTex
|
||||
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
|
||||
|
||||
let attributedPlaceholder = NSAttributedString(string: item.placeholder, font: textFont, textColor: theme.list.itemPlaceholderTextColor)
|
||||
|
@ -46,7 +46,7 @@ final class SecureIdAuthPasswordOptionContentNode: ASDisplayNode, SecureIdAuthCo
|
||||
self.inputField = TextFieldNode()
|
||||
|
||||
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) {
|
||||
self.inputButtonNode.setImage(image, for: [])
|
||||
@ -59,7 +59,7 @@ final class SecureIdAuthPasswordOptionContentNode: ASDisplayNode, SecureIdAuthCo
|
||||
self.inputField.textField.font = passwordFont
|
||||
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.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
self.inputField.textField.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance
|
||||
self.inputField.textField.tintColor = theme.list.itemAccentColor
|
||||
|
||||
self.buttonNode = HighlightableButtonNode()
|
||||
|
@ -126,8 +126,8 @@ final class SecureIdValueFormPhoneItemNode: FormBlockItemNode<SecureIdValueFormP
|
||||
self.phoneInputNode.countryCodeField.textField.tintColor = theme.list.itemAccentColor
|
||||
self.phoneInputNode.numberField.textField.tintColor = theme.list.itemAccentColor
|
||||
|
||||
self.phoneInputNode.countryCodeField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
self.phoneInputNode.numberField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
self.phoneInputNode.countryCodeField.textField.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance
|
||||
self.phoneInputNode.numberField.textField.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance
|
||||
}
|
||||
|
||||
self.item = item
|
||||
|
@ -59,7 +59,7 @@ final class SetupTwoStepVerificationContentNode: ASDisplayNode, UITextFieldDeleg
|
||||
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.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
|
||||
switch inputType {
|
||||
case .password:
|
||||
@ -126,7 +126,7 @@ final class SetupTwoStepVerificationContentNode: ASDisplayNode, UITextFieldDeleg
|
||||
|
||||
func updatePresentationData(_ presentationData: PresentationData) {
|
||||
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.inputNode.textField.tintColor = self.theme.list.itemAccentColor
|
||||
}
|
||||
|
@ -372,7 +372,7 @@ private enum ChannelAdminEntry: ItemListNodeEntry {
|
||||
}
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, accessoryText: accessoryText, sectionId: self.section)
|
||||
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)
|
||||
}, shouldUpdateText: { text in
|
||||
if text.containsEmoji {
|
||||
|
@ -845,7 +845,7 @@ public func channelInfoController(context: AccountContext, peerId: PeerId) -> Vi
|
||||
}
|
||||
}, openStats: {
|
||||
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)?
|
||||
let progressSignal = Signal<Never, NoError> { subscriber in
|
||||
|
@ -80,7 +80,7 @@ private final class ChannelOwnershipTransferPasswordFieldNode: ASDisplayNode, UI
|
||||
self.textInputNode.textField.textColor = self.theme.list.itemPrimaryTextColor
|
||||
self.textInputNode.textField.isSecureTextEntry = true
|
||||
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.textField.delegate = self
|
||||
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.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.typingAttributes = [NSAttributedString.Key.font: Font.regular(14.0), NSAttributedString.Key.foregroundColor: theme.actionSheet.inputTextColor]
|
||||
self.textInputNode.textField.tintColor = theme.list.itemAccentColor
|
||||
|
@ -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
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
|
@ -287,7 +287,7 @@ private enum ChannelVisibilityEntry: ItemListNodeEntry {
|
||||
}
|
||||
}, tag: ChannelVisibilityEntryTag.privateLink)
|
||||
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)
|
||||
}, updatedFocus: { focus in
|
||||
if focus {
|
||||
|
@ -209,7 +209,7 @@ private enum GroupStickerPackEntry: ItemListNodeEntry {
|
||||
func item(_ arguments: GroupStickerPackSetupControllerArguments) -> ListViewItem {
|
||||
switch self {
|
||||
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)
|
||||
}, processPaste: { text in
|
||||
if let url = (URL(string: text) ?? URL(string: "http://" + text)), url.host == "t.me" || url.host == "telegram.me" {
|
||||
|
@ -183,7 +183,7 @@ class UserInfoEditingPhoneItemNode: ItemListRevealOptionsItemNode, ItemListItemN
|
||||
|
||||
if let item = self.item {
|
||||
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
|
||||
}
|
||||
}
|
||||
@ -233,7 +233,7 @@ class UserInfoEditingPhoneItemNode: ItemListRevealOptionsItemNode, ItemListItemN
|
||||
strongSelf.labelSeparatorNode.backgroundColor = itemSeparatorColor
|
||||
|
||||
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.clearButton.setImage(generateClearIcon(color: updatedTheme.list.inputClearButtonColor), for: [])
|
||||
|
@ -161,7 +161,7 @@ public final class SearchBarNodeTheme: Equatable {
|
||||
self.inputIcon = theme.rootController.navigationSearchBar.inputIconColor
|
||||
self.inputClear = theme.rootController.navigationSearchBar.inputClearButtonColor
|
||||
self.accent = theme.rootController.navigationSearchBar.accentColor
|
||||
self.keyboard = theme.chatList.searchBarKeyboardColor
|
||||
self.keyboard = theme.rootController.keyboardColor
|
||||
}
|
||||
|
||||
public static func ==(lhs: SearchBarNodeTheme, rhs: SearchBarNodeTheme) -> Bool {
|
||||
|
@ -127,10 +127,10 @@ final class ChangePhoneNumberControllerNode: ASDisplayNode {
|
||||
|
||||
self.phoneInputNode = PhoneInputNode(fontSize: 17.0)
|
||||
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.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
|
||||
|
||||
super.init()
|
||||
|
@ -234,7 +234,7 @@ final class TabBarAccountSwitchControllerNode: ViewControllerTracingNode {
|
||||
self.effectView = UIVisualEffectView()
|
||||
if #available(iOS 9.0, *) {
|
||||
} else {
|
||||
if presentationData.theme.chatList.searchBarKeyboardColor == .dark {
|
||||
if presentationData.theme.rootController.keyboardColor == .dark {
|
||||
self.effectView.effect = UIBlurEffect(style: .dark)
|
||||
} else {
|
||||
self.effectView.effect = UIBlurEffect(style: .light)
|
||||
@ -244,7 +244,7 @@ final class TabBarAccountSwitchControllerNode: ViewControllerTracingNode {
|
||||
|
||||
self.dimNode = ASDisplayNode()
|
||||
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)
|
||||
} else {
|
||||
self.dimNode.backgroundColor = presentationData.theme.chatList.backgroundColor.withAlphaComponent(0.2)
|
||||
@ -287,7 +287,7 @@ final class TabBarAccountSwitchControllerNode: ViewControllerTracingNode {
|
||||
func animateIn() {
|
||||
UIView.animate(withDuration: 0.3, animations: {
|
||||
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, *) {
|
||||
self.effectView.effect = UIBlurEffect(style: .regular)
|
||||
if self.effectView.subviews.count == 2 {
|
||||
@ -310,7 +310,7 @@ final class TabBarAccountSwitchControllerNode: ViewControllerTracingNode {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if strongSelf.presentationData.theme.chatList.searchBarKeyboardColor == .dark {
|
||||
if strongSelf.presentationData.theme.rootController.keyboardColor == .dark {
|
||||
if strongSelf.effectView.subviews.count == 2 {
|
||||
strongSelf.effectView.subviews[1].isHidden = true
|
||||
}
|
||||
|
@ -8,70 +8,79 @@ import TelegramPresentationData
|
||||
import TelegramUIPreferences
|
||||
import ItemListUI
|
||||
import AlertUI
|
||||
import LegacyMediaPickerUI
|
||||
import AccountContext
|
||||
|
||||
private final class EditThemeControllerArguments {
|
||||
let context: AccountContext
|
||||
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.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 {
|
||||
case chatPreview
|
||||
case info
|
||||
case chatPreview
|
||||
}
|
||||
|
||||
private enum EditThemeControllerEntry: ItemListNodeEntry {
|
||||
case chatPreviewHeader(PresentationTheme, String)
|
||||
case chatPreview(PresentationTheme, PresentationTheme, TelegramWallpaper, PresentationFontSize, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder)
|
||||
case title(PresentationTheme, PresentationStrings, String, String)
|
||||
case title(PresentationTheme, PresentationStrings, String, String, Bool)
|
||||
case slug(PresentationTheme, PresentationStrings, String, String, Bool)
|
||||
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 {
|
||||
switch self {
|
||||
case .chatPreviewHeader, .chatPreview:
|
||||
return EditThemeControllerSection.chatPreview.rawValue
|
||||
case .title, .slug, .slugInfo:
|
||||
return EditThemeControllerSection.info.rawValue
|
||||
case .chatPreviewHeader, .chatPreview, .uploadTheme, .uploadInfo:
|
||||
return EditThemeControllerSection.chatPreview.rawValue
|
||||
}
|
||||
}
|
||||
|
||||
var stableId: Int32 {
|
||||
switch self {
|
||||
case .chatPreviewHeader:
|
||||
return 0
|
||||
case .chatPreview:
|
||||
return 1
|
||||
case .title:
|
||||
return 2
|
||||
return 0
|
||||
case .slug:
|
||||
return 3
|
||||
return 1
|
||||
case .slugInfo:
|
||||
return 2
|
||||
case .chatPreviewHeader:
|
||||
return 3
|
||||
case .chatPreview:
|
||||
return 4
|
||||
case .uploadTheme:
|
||||
return 5
|
||||
case .uploadInfo:
|
||||
return 6
|
||||
}
|
||||
}
|
||||
|
||||
static func ==(lhs: EditThemeControllerEntry, rhs: EditThemeControllerEntry) -> Bool {
|
||||
switch lhs {
|
||||
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 .title(lhsTheme, lhsStrings, lhsTitle, lhsValue):
|
||||
if case let .title(rhsTheme, rhsStrings, rhsTitle, rhsValue) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsTitle == rhsTitle, lhsValue == rhsValue {
|
||||
case let .title(lhsTheme, lhsStrings, lhsTitle, lhsValue, lhsDone):
|
||||
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
|
||||
@ -88,6 +97,30 @@ private enum EditThemeControllerEntry: ItemListNodeEntry {
|
||||
} else {
|
||||
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 {
|
||||
switch self {
|
||||
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 .title(theme, strings, title, text):
|
||||
return ItemListSingleLineInputItem(theme: theme, strings: strings, title: NSAttributedString(), text: text, placeholder: title, sectionId: self.section, textUpdated: { value in
|
||||
case let .title(theme, strings, title, text, done):
|
||||
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
|
||||
arguments.updateState { current in
|
||||
var state = current
|
||||
state.title = value
|
||||
return state
|
||||
}
|
||||
}, action: {})
|
||||
}, action: {
|
||||
|
||||
})
|
||||
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
|
||||
var state = current
|
||||
state.slug = value
|
||||
return state
|
||||
}
|
||||
}, action: {})
|
||||
}, action: {
|
||||
|
||||
})
|
||||
case let .slugInfo(theme, text):
|
||||
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 {
|
||||
var title: String
|
||||
var slug: String
|
||||
|
||||
var isComplete: Bool {
|
||||
if self.title.isEmpty || self.slug.isEmpty {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
public enum EditThemeControllerMode: Equatable {
|
||||
case create
|
||||
case edit(PresentationCloudTheme)
|
||||
}
|
||||
|
||||
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] = []
|
||||
|
||||
if let theme = theme {
|
||||
entries.append(.chatPreviewHeader(presentationData.theme, presentationData.strings.EditTheme_Preview.uppercased()))
|
||||
entries.append(.chatPreview(presentationData.theme, theme, theme.chat.defaultWallpaper, presentationData.fontSize, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder))
|
||||
var isCreate = false
|
||||
if case .create = state.mode {
|
||||
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(.slug(presentationData.theme, presentationData.strings, presentationData.strings.EditTheme_ShortLink, state.slug, true))
|
||||
entries.append(.slugInfo(presentationData.theme, presentationData.strings.EditTheme_ShortLinkInfo))
|
||||
entries.append(.chatPreviewHeader(presentationData.theme, presentationData.strings.EditTheme_Preview.uppercased()))
|
||||
entries.append(.chatPreview(presentationData.theme, state.previewTheme, state.previewTheme.chat.defaultWallpaper, presentationData.fontSize, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder))
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
public enum EditThemeControllerMode {
|
||||
case createNew
|
||||
case createForExisting(TelegramTheme)
|
||||
case edit(TelegramTheme)
|
||||
}
|
||||
|
||||
public func editThemeController(context: AccountContext, theme: TelegramTheme) -> ViewController {
|
||||
let initialState = EditThemeControllerState(title: theme.title, slug: theme.slug)
|
||||
public func editThemeController(context: AccountContext, mode: EditThemeControllerMode, navigateToChat: ((PeerId) -> Void)? = nil) -> ViewController {
|
||||
let initialState: EditThemeControllerState
|
||||
switch mode {
|
||||
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)
|
||||
case let .edit(theme):
|
||||
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 stateValue = Atomic(value: initialState)
|
||||
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
|
||||
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())
|
||||
|> map { presentationData, state -> (ItemListControllerState, (ItemListNodeState<EditThemeControllerEntry>, EditThemeControllerEntry.ItemGenerationArguments)) in
|
||||
let leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: {
|
||||
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: {
|
||||
// dismissImpl?()
|
||||
//})
|
||||
})
|
||||
|> map { presentationData, state -> (ItemListControllerState, (ItemListNodeState<EditThemeControllerEntry>, EditThemeControllerEntry.ItemGenerationArguments)) in
|
||||
let leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: {
|
||||
dismissImpl?()
|
||||
})
|
||||
|
||||
var focusItemTag: ItemListItemTag?
|
||||
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)
|
||||
let listState = ItemListNodeState(entries: EditThemeControllerEntries(presentationData: presentationData, theme: previewTheme, state: state), style: .blocks, emptyStateItem: nil, animateChanges: false)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Done), style: .bold, enabled: isComplete, action: {
|
||||
arguments.updateState { current in
|
||||
var state = current
|
||||
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)
|
||||
@ -202,6 +402,7 @@ public func editThemeController(context: AccountContext, theme: TelegramTheme) -
|
||||
controller?.present(c, in: .window(.root), with: a)
|
||||
}
|
||||
dismissImpl = { [weak controller] in
|
||||
controller?.view.endEditing(true)
|
||||
let _ = controller?.dismiss()
|
||||
}
|
||||
return controller
|
||||
|
@ -116,7 +116,7 @@ public final class ThemePreviewController: ViewController {
|
||||
|> take(1)
|
||||
|> map { theme in
|
||||
if let theme = theme {
|
||||
return .cloud(theme)
|
||||
return .cloud(PresentationCloudTheme(theme: theme, resolvedWallpaper: nil))
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import TelegramPresentationData
|
||||
import TelegramUIPreferences
|
||||
import ItemListUI
|
||||
import AlertUI
|
||||
import ShareController
|
||||
import AccountContext
|
||||
|
||||
func themeDisplayName(strings: PresentationStrings, reference: PresentationThemeReference) -> String {
|
||||
@ -27,7 +28,7 @@ func themeDisplayName(strings: PresentationStrings, reference: PresentationTheme
|
||||
case let .local(theme):
|
||||
name = theme.title
|
||||
case let .cloud(theme):
|
||||
name = theme.title
|
||||
name = theme.theme.title
|
||||
}
|
||||
return name
|
||||
}
|
||||
@ -372,6 +373,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The
|
||||
|
||||
var pushControllerImpl: ((ViewController) -> Void)?
|
||||
var presentControllerImpl: ((ViewController, Any?) -> Void)?
|
||||
var getNavigationControllerImpl: (() -> NavigationController?)?
|
||||
|
||||
var selectThemeImpl: ((PresentationThemeReference) -> Void)?
|
||||
var moreImpl: (() -> Void)?
|
||||
@ -463,34 +465,44 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
var items: [ActionSheetItem] = []
|
||||
items.append(ActionSheetTextItem(title: theme.title))
|
||||
items.append(ActionSheetButtonItem(title: presentationData.strings.Appearance_EditTheme, color: .accent, action: { [weak actionSheet] in
|
||||
items.append(ActionSheetTextItem(title: theme.theme.title))
|
||||
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()
|
||||
|
||||
let controller = editThemeController(context: context, theme: theme)
|
||||
presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
||||
let controller = ShareController(context: context, subject: .url("https://t.me/addtheme/\(theme.theme.slug)"), preferredAction: .default)
|
||||
presentControllerImpl?(controller, nil)
|
||||
}))
|
||||
items.append(ActionSheetButtonItem(title: presentationData.strings.Appearance_RemoveTheme, color: .destructive, action: { [weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
|
||||
let _ = (cloudThemes.get()
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(next: { themes in
|
||||
if isCurrent, let themeIndex = themes.firstIndex(where: { $0.id == theme.id }) {
|
||||
let newTheme: PresentationThemeReference
|
||||
if themeIndex > 0 {
|
||||
newTheme = .cloud(themes[themeIndex - 1])
|
||||
} else {
|
||||
newTheme = .builtin(.nightAccent)
|
||||
}
|
||||
selectThemeImpl?(newTheme)
|
||||
}
|
||||
|
||||
let updatedThemes = themes.filter { $0.id != theme.id }
|
||||
cloudThemes.set(.single(updatedThemes) |> then(updatedCloudThemes))
|
||||
|
||||
let _ = (deleteTheme(account: context.account, theme: theme)).start()
|
||||
})
|
||||
// let _ = (cloudThemes.get()
|
||||
// |> take(1)
|
||||
// |> deliverOnMainQueue).start(next: { themes in
|
||||
// if isCurrent, let themeIndex = themes.firstIndex(where: { $0.id == theme.id }) {
|
||||
// let newTheme: PresentationThemeReference
|
||||
// if themeIndex > 0 {
|
||||
// newTheme = .cloud(themes[themeIndex - 1])
|
||||
// } else {
|
||||
// newTheme = .builtin(.nightAccent)
|
||||
// }
|
||||
// selectThemeImpl?(newTheme)
|
||||
// }
|
||||
//
|
||||
// let updatedThemes = themes.filter { $0.id != theme.id }
|
||||
// cloudThemes.set(.single(updatedThemes) |> then(updatedCloudThemes))
|
||||
//
|
||||
// let _ = (deleteTheme(account: context.account, theme: theme)).start()
|
||||
// })
|
||||
}))
|
||||
actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
|
||||
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 cloudThemes: [PresentationThemeReference] = cloudThemes.map { .cloud($0) }
|
||||
let cloudThemes: [PresentationThemeReference] = cloudThemes.map { .cloud(PresentationCloudTheme(theme: $0, resolvedWallpaper: nil)) }
|
||||
|
||||
var availableThemes = defaultThemes
|
||||
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)
|
||||
}
|
||||
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
|
||||
arguments.selectTheme(theme)
|
||||
}
|
||||
moreImpl = { [weak controller] in
|
||||
moreImpl = {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
var items: [ActionSheetItem] = []
|
||||
items.append(ActionSheetButtonItem(title: presentationData.strings.Appearance_CreateTheme, color: .accent, action: { [weak actionSheet] in
|
||||
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 {
|
||||
return
|
||||
}
|
||||
|
||||
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)))
|
||||
let controller = editThemeController(context: context, mode: .create, navigateToChat: { peerId in
|
||||
if let navigationController = getNavigationControllerImpl?() {
|
||||
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(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: [
|
||||
ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, color: .accent, action: { [weak actionSheet] in
|
||||
|
@ -60,7 +60,7 @@ private func themeIconImage(context: AccountContext, theme: PresentationThemeRef
|
||||
if case let .local(theme) = theme {
|
||||
resource = theme.resource
|
||||
} else if case let .cloud(theme) = theme {
|
||||
resource = theme.file?.resource
|
||||
resource = theme.theme.file?.resource
|
||||
}
|
||||
if let resource = resource {
|
||||
signal = telegramThemeData(account: context.account, accountManager: context.sharedContext.accountManager, resource: resource, synchronousLoad: false)
|
||||
|
@ -104,7 +104,7 @@ final class WallpaperColorPanelNode: ASDisplayNode, UITextFieldDelegate {
|
||||
|
||||
self.textFieldNode.textField.font = Font.regular(17.0)
|
||||
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.autocapitalizationType = .allCharacters
|
||||
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.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
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,7 @@ private enum UsernameSetupEntry: ItemListNodeEntry {
|
||||
func item(_ arguments: UsernameSetupControllerArguments) -> ListViewItem {
|
||||
switch self {
|
||||
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)
|
||||
}, action: {
|
||||
})
|
||||
|
@ -50,7 +50,7 @@ final class ShareInputFieldNodeTheme: Equatable {
|
||||
|
||||
extension ShareInputFieldNodeTheme {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.textField.keyboardAppearance = keyboardAppearance
|
||||
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
|
||||
|
||||
super.init()
|
||||
|
@ -130,6 +130,7 @@ private var declaredEncodables: Void = {
|
||||
declareEncodable(CachedStickerQueryResult.self, f: { CachedStickerQueryResult(decoder: $0) })
|
||||
declareEncodable(TelegramWallpaper.self, f: { TelegramWallpaper(decoder: $0) })
|
||||
declareEncodable(TelegramTheme.self, f: { TelegramTheme(decoder: $0) })
|
||||
declareEncodable(ThemeSettings.self, f: { ThemeSettings(decoder: $0) })
|
||||
declareEncodable(SynchronizeMarkAllUnseenPersonalMessagesOperation.self, f: { SynchronizeMarkAllUnseenPersonalMessagesOperation(decoder: $0) })
|
||||
declareEncodable(SynchronizeAppLogEventsOperation.self, f: { SynchronizeAppLogEventsOperation(decoder: $0) })
|
||||
declareEncodable(CachedRecentPeers.self, f: { CachedRecentPeers(decoder: $0) })
|
||||
|
@ -268,6 +268,7 @@ private enum SharedDataKeyValues: Int32 {
|
||||
case localizationSettings = 3
|
||||
case proxySettings = 4
|
||||
case autodownloadSettings = 5
|
||||
case themeSettings = 6
|
||||
}
|
||||
|
||||
public struct SharedDataKeys {
|
||||
@ -300,6 +301,12 @@ public struct SharedDataKeys {
|
||||
key.setInt32(0, value: SharedDataKeyValues.autodownloadSettings.rawValue)
|
||||
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 {
|
||||
|
@ -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)))
|
||||
|> `catch` { _ -> Signal<Api.Bool, NoError> in
|
||||
return .complete()
|
||||
}
|
||||
|> mapToSignal { _ -> Signal<Void, NoError> in
|
||||
|> mapToSignal { _ -> Signal<Never, NoError> in
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
@ -233,7 +233,11 @@ public func createTheme(account: Account, resource: MediaResource, title: String
|
||||
|> mapError { _ in return CreateThemeError.generic }
|
||||
|> mapToSignal { apiTheme -> Signal<CreateThemeResult, CreateThemeError> in
|
||||
if let theme = TelegramTheme(apiTheme: apiTheme) {
|
||||
return .single(.result(theme))
|
||||
return account.postbox.transaction { transaction -> CreateThemeResult in
|
||||
|
||||
return .result(theme)
|
||||
}
|
||||
|> introduceError(CreateThemeError.self)
|
||||
} else {
|
||||
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
|
||||
}
|
||||
|
@ -113,7 +113,8 @@ private func makeDarkPresentationTheme(accentColor: UIColor, baseColor: Presenta
|
||||
statusBarStyle: .white,
|
||||
tabBar: rootTabBar,
|
||||
navigationBar: rootNavigationBar,
|
||||
navigationSearchBar: navigationSearchBar
|
||||
navigationSearchBar: navigationSearchBar,
|
||||
keyboardColor: .dark
|
||||
)
|
||||
|
||||
let switchColors = PresentationThemeSwitch(
|
||||
@ -138,7 +139,7 @@ private func makeDarkPresentationTheme(accentColor: UIColor, baseColor: Presenta
|
||||
itemHighlightedBackgroundColor: UIColor(rgb: 0x313135),
|
||||
itemBlocksSeparatorColor: UIColor(rgb: 0x3d3d40),
|
||||
itemPlainSeparatorColor: UIColor(rgb: 0x3d3d40),
|
||||
disclosureArrowColor: UIColor(rgb: 0x5a5a5e),
|
||||
disclosureArrowColor: UIColor(rgb: 0xffffff, alpha: 0.28),
|
||||
sectionHeaderTextColor: UIColor(rgb: 0x8d8e93),
|
||||
freeTextColor: UIColor(rgb: 0x8d8e93),
|
||||
freeTextErrorColor: UIColor(rgb: 0xcf3030),
|
||||
@ -200,7 +201,6 @@ private func makeDarkPresentationTheme(accentColor: UIColor, baseColor: Presenta
|
||||
regularSearchBarColor: UIColor(rgb: 0x272728),
|
||||
sectionHeaderFillColor: UIColor(rgb: 0x1c1c1d),
|
||||
sectionHeaderTextColor: UIColor(rgb: 0xffffff),
|
||||
searchBarKeyboardColor: .dark,
|
||||
verifiedIconFillColor: accentColor,
|
||||
verifiedIconForegroundColor: badgeTextColor,
|
||||
secretIconColor: secretColor,
|
||||
@ -258,7 +258,6 @@ private func makeDarkPresentationTheme(accentColor: UIColor, baseColor: Presenta
|
||||
primaryTextColor: .white,
|
||||
secondaryTextColor: UIColor(rgb: 0xffffff, alpha: 0.5),
|
||||
mediaRecordingDotColor: destructiveColor,
|
||||
keyboardColor: .dark,
|
||||
mediaRecordingControl: inputPanelMediaRecordingControl
|
||||
)
|
||||
|
||||
|
@ -81,7 +81,8 @@ private func makeDarkPresentationTheme(accentColor: UIColor, baseColor: Presenta
|
||||
statusBarStyle: .white,
|
||||
tabBar: rootTabBar,
|
||||
navigationBar: rootNavigationBar,
|
||||
navigationSearchBar: navigationSearchBar
|
||||
navigationSearchBar: navigationSearchBar,
|
||||
keyboardColor: .dark
|
||||
)
|
||||
|
||||
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),
|
||||
sectionHeaderFillColor: mainBackgroundColor,
|
||||
sectionHeaderTextColor: mainSecondaryTextColor.withAlphaComponent(0.5),
|
||||
searchBarKeyboardColor: .dark,
|
||||
verifiedIconFillColor: accentColor,
|
||||
verifiedIconForegroundColor: .white,
|
||||
secretIconColor: secretColor,
|
||||
@ -228,7 +228,6 @@ private func makeDarkPresentationTheme(accentColor: UIColor, baseColor: Presenta
|
||||
primaryTextColor: UIColor(rgb: 0xffffff),
|
||||
secondaryTextColor: UIColor(rgb: 0xffffff, alpha: 0.5),
|
||||
mediaRecordingDotColor: accentColor,
|
||||
keyboardColor: .dark,
|
||||
mediaRecordingControl: inputPanelMediaRecordingControl
|
||||
)
|
||||
|
||||
|
@ -93,7 +93,8 @@ private func makeDefaultDayPresentationTheme(accentColor: UIColor, serviceBackgr
|
||||
statusBarStyle: .black,
|
||||
tabBar: rootTabBar,
|
||||
navigationBar: rootNavigationBar,
|
||||
navigationSearchBar: navigationSearchBar
|
||||
navigationSearchBar: navigationSearchBar,
|
||||
keyboardColor: .light
|
||||
)
|
||||
|
||||
let switchColors = PresentationThemeSwitch(
|
||||
@ -180,7 +181,6 @@ private func makeDefaultDayPresentationTheme(accentColor: UIColor, serviceBackgr
|
||||
regularSearchBarColor: UIColor(rgb: 0xe9e9e9),
|
||||
sectionHeaderFillColor: UIColor(rgb: 0xf7f7f7),
|
||||
sectionHeaderTextColor: UIColor(rgb: 0x8e8e93),
|
||||
searchBarKeyboardColor: .light,
|
||||
verifiedIconFillColor: accentColor,
|
||||
verifiedIconForegroundColor: .white,
|
||||
secretIconColor: secretColor,
|
||||
@ -264,7 +264,6 @@ private func makeDefaultDayPresentationTheme(accentColor: UIColor, serviceBackgr
|
||||
primaryTextColor: .black,
|
||||
secondaryTextColor: UIColor(rgb: 0x8e8e93),
|
||||
mediaRecordingDotColor: UIColor(rgb: 0xed2521),
|
||||
keyboardColor: .light,
|
||||
mediaRecordingControl: inputPanelMediaRecordingControl
|
||||
)
|
||||
|
||||
|
@ -30,7 +30,7 @@ public func makePresentationTheme(mediaBox: MediaBox, themeReference: Presentati
|
||||
theme = makeDefaultPresentationTheme(reference: .dayClassic, accentColor: nil, serviceBackgroundColor: serviceBackgroundColor, baseColor: baseColor, preview: preview)
|
||||
}
|
||||
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
|
||||
} else {
|
||||
theme = makeDefaultPresentationTheme(reference: .dayClassic, accentColor: nil, serviceBackgroundColor: serviceBackgroundColor, baseColor: baseColor, preview: preview)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -140,12 +140,14 @@ public final class PresentationThemeRootController {
|
||||
public let tabBar: PresentationThemeRootTabBar
|
||||
public let navigationBar: PresentationThemeRootNavigationBar
|
||||
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.tabBar = tabBar
|
||||
self.navigationBar = navigationBar
|
||||
self.navigationSearchBar = navigationSearchBar
|
||||
self.keyboardColor = keyboardColor
|
||||
}
|
||||
}
|
||||
|
||||
@ -397,7 +399,6 @@ public final class PresentationThemeChatList {
|
||||
public let regularSearchBarColor: UIColor
|
||||
public let sectionHeaderFillColor: UIColor
|
||||
public let sectionHeaderTextColor: UIColor
|
||||
public let searchBarKeyboardColor: PresentationThemeKeyboardColor
|
||||
public let verifiedIconFillColor: UIColor
|
||||
public let verifiedIconForegroundColor: UIColor
|
||||
public let secretIconColor: UIColor
|
||||
@ -405,7 +406,7 @@ public final class PresentationThemeChatList {
|
||||
public let unpinnedArchiveAvatarColor: PresentationThemeArchiveAvatarColors
|
||||
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.itemSeparatorColor = itemSeparatorColor
|
||||
self.itemBackgroundColor = itemBackgroundColor
|
||||
@ -432,7 +433,6 @@ public final class PresentationThemeChatList {
|
||||
self.regularSearchBarColor = regularSearchBarColor
|
||||
self.sectionHeaderFillColor = sectionHeaderFillColor
|
||||
self.sectionHeaderTextColor = sectionHeaderTextColor
|
||||
self.searchBarKeyboardColor = searchBarKeyboardColor
|
||||
self.verifiedIconFillColor = verifiedIconFillColor
|
||||
self.verifiedIconForegroundColor = verifiedIconForegroundColor
|
||||
self.secretIconColor = secretIconColor
|
||||
@ -715,10 +715,9 @@ public final class PresentationThemeChatInputPanel {
|
||||
public let primaryTextColor: UIColor
|
||||
public let secondaryTextColor: UIColor
|
||||
public let mediaRecordingDotColor: UIColor
|
||||
public let keyboardColor: PresentationThemeKeyboardColor
|
||||
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.panelSeparatorColor = panelSeparatorColor
|
||||
self.panelControlAccentColor = panelControlAccentColor
|
||||
@ -735,7 +734,6 @@ public final class PresentationThemeChatInputPanel {
|
||||
self.primaryTextColor = primaryTextColor
|
||||
self.secondaryTextColor = secondaryTextColor
|
||||
self.mediaRecordingDotColor = mediaRecordingDotColor
|
||||
self.keyboardColor = keyboardColor
|
||||
self.mediaRecordingControl = mediaRecordingControl
|
||||
}
|
||||
}
|
||||
@ -822,6 +820,10 @@ public final class PresentationThemeChat {
|
||||
self.inputButtonPanel = inputButtonPanel
|
||||
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 {
|
||||
@ -974,4 +976,21 @@ public final class PresentationTheme: Equatable {
|
||||
public static func ==(lhs: PresentationTheme, rhs: PresentationTheme) -> Bool {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
import TelegramUIPreferences
|
||||
|
||||
@ -35,7 +36,7 @@ extension TelegramWallpaper: Codable {
|
||||
if let color = UIColor(hexString: value) {
|
||||
self = .color(Int32(bitPattern: color.rgb))
|
||||
} 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 {
|
||||
@ -50,6 +51,8 @@ extension TelegramWallpaper: Codable {
|
||||
try container.encode("builtin")
|
||||
case let .color(value):
|
||||
try container.encode(String(format: "%06x", value))
|
||||
case let .file(file):
|
||||
try container.encode(file.slug)
|
||||
default:
|
||||
break
|
||||
}
|
||||
@ -354,6 +357,7 @@ extension PresentationThemeRootController: Codable {
|
||||
case tabBar
|
||||
case navBar
|
||||
case searchBar
|
||||
case keyboard
|
||||
}
|
||||
|
||||
public convenience init(from decoder: Decoder) throws {
|
||||
@ -361,7 +365,8 @@ extension PresentationThemeRootController: Codable {
|
||||
self.init(statusBarStyle: try values.decode(PresentationThemeStatusBarStyle.self, forKey: .statusBar),
|
||||
tabBar: try values.decode(PresentationThemeRootTabBar.self, forKey: .tabBar),
|
||||
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 {
|
||||
@ -370,6 +375,7 @@ extension PresentationThemeRootController: Codable {
|
||||
try values.encode(self.tabBar, forKey: .tabBar)
|
||||
try values.encode(self.navigationBar, forKey: .navBar)
|
||||
try values.encode(self.navigationSearchBar, forKey: .searchBar)
|
||||
try values.encode(self.keyboardColor, forKey: .keyboard)
|
||||
}
|
||||
}
|
||||
|
||||
@ -721,7 +727,6 @@ extension PresentationThemeChatList: Codable {
|
||||
case regularSearchBar
|
||||
case sectionHeaderBg
|
||||
case sectionHeaderText
|
||||
case searchBarKeyboard
|
||||
case verifiedIconBg
|
||||
case verifiedIconFg
|
||||
case secretIcon
|
||||
@ -758,7 +763,6 @@ extension PresentationThemeChatList: Codable {
|
||||
regularSearchBarColor: try decodeColor(values, .regularSearchBar),
|
||||
sectionHeaderFillColor: try decodeColor(values, .sectionHeaderBg),
|
||||
sectionHeaderTextColor: try decodeColor(values, .sectionHeaderText),
|
||||
searchBarKeyboardColor: try values.decode(PresentationThemeKeyboardColor.self, forKey: .searchBarKeyboard),
|
||||
verifiedIconFillColor: try decodeColor(values, .verifiedIconBg),
|
||||
verifiedIconForegroundColor: try decodeColor(values, .verifiedIconFg),
|
||||
secretIconColor: try decodeColor(values, .secretIcon),
|
||||
@ -795,7 +799,6 @@ extension PresentationThemeChatList: Codable {
|
||||
try encodeColor(&values, self.regularSearchBarColor, .regularSearchBar)
|
||||
try encodeColor(&values, self.sectionHeaderFillColor, .sectionHeaderBg)
|
||||
try encodeColor(&values, self.sectionHeaderTextColor, .sectionHeaderText)
|
||||
try values.encode(self.searchBarKeyboardColor, forKey: .searchBarKeyboard)
|
||||
try encodeColor(&values, self.verifiedIconFillColor, .verifiedIconBg)
|
||||
try encodeColor(&values, self.verifiedIconForegroundColor, .verifiedIconFg)
|
||||
try encodeColor(&values, self.secretIconColor, .secretIcon)
|
||||
@ -1143,7 +1146,6 @@ extension PresentationThemeChatInputPanel: Codable {
|
||||
case primaryText
|
||||
case secondaryText
|
||||
case mediaRecordDot
|
||||
case keyboard
|
||||
case mediaRecordControl
|
||||
}
|
||||
|
||||
@ -1165,7 +1167,6 @@ extension PresentationThemeChatInputPanel: Codable {
|
||||
primaryTextColor: try decodeColor(values, .primaryText),
|
||||
secondaryTextColor: try decodeColor(values, .secondaryText),
|
||||
mediaRecordingDotColor: try decodeColor(values, .mediaRecordDot),
|
||||
keyboardColor: try values.decode(PresentationThemeKeyboardColor.self, forKey: .keyboard),
|
||||
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.secondaryTextColor, .secondaryText)
|
||||
try encodeColor(&values, self.mediaRecordingDotColor, .mediaRecordDot)
|
||||
try values.encode(self.keyboardColor, forKey: .keyboard)
|
||||
try values.encode(self.mediaRecordingControl, forKey: .mediaRecordControl)
|
||||
}
|
||||
}
|
||||
@ -1313,7 +1313,15 @@ extension PresentationThemeChat: Codable {
|
||||
|
||||
public convenience init(from decoder: Decoder) throws {
|
||||
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),
|
||||
serviceMessage: try values.decode(PresentationThemeServiceMessage.self, forKey: .serviceMessage),
|
||||
inputPanel: try values.decode(PresentationThemeChatInputPanel.self, forKey: .inputPanel),
|
||||
|
@ -1,4 +1,5 @@
|
||||
import Foundation
|
||||
import TelegramCore
|
||||
|
||||
public func encodePresentationTheme(_ theme: PresentationTheme) -> String? {
|
||||
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 {
|
||||
return nil
|
||||
}
|
||||
@ -378,6 +379,7 @@ public func makePresentationTheme(data: Data) -> PresentationTheme? {
|
||||
}
|
||||
|
||||
let decoder = PresentationThemeDecoding(referencing: topLevel.data)
|
||||
decoder.resolvedWallpaper = resolvedWallpaper
|
||||
if let value = try? decoder.unbox(topLevel.data, as: PresentationTheme.self) {
|
||||
return value
|
||||
}
|
||||
@ -392,10 +394,11 @@ class PresentationThemeDecoding: Decoder {
|
||||
public var userInfo: [CodingUserInfoKey : Any] {
|
||||
return [:]
|
||||
}
|
||||
|
||||
|
||||
var referenceTheme: PresentationTheme?
|
||||
var serviceBackgroundColor: UIColor?
|
||||
|
||||
var resolvedWallpaper: TelegramWallpaper?
|
||||
|
||||
private var _referenceCoding: PresentationThemeEncoding?
|
||||
fileprivate var referenceCoding: PresentationThemeEncoding? {
|
||||
if let referenceCoding = self._referenceCoding {
|
||||
|
@ -136,7 +136,7 @@ final class AuthorizedApplicationContext {
|
||||
self.notificationController = NotificationContainerController(context: context)
|
||||
|
||||
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.rootController = TelegramRootController(context: context)
|
||||
@ -740,7 +740,7 @@ final class AuthorizedApplicationContext {
|
||||
if let strongSelf = self {
|
||||
if previousTheme.swap(presentationData.theme) !== presentationData.theme {
|
||||
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.rootController.updateTheme(NavigationControllerTheme(presentationTheme: presentationData.theme))
|
||||
}
|
||||
|
@ -120,7 +120,7 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
|
||||
#endif
|
||||
self.codeField.textField.returnKeyType = .done
|
||||
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.tintColor = self.theme.list.itemAccentColor
|
||||
|
||||
|
@ -70,7 +70,7 @@ final class AuthorizationSequencePasswordEntryControllerNode: ASDisplayNode, UIT
|
||||
self.codeField.textField.textAlignment = .natural
|
||||
self.codeField.textField.isSecureTextEntry = true
|
||||
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.tintColor = self.theme.list.itemAccentColor
|
||||
|
||||
|
@ -58,7 +58,7 @@ final class AuthorizationSequencePasswordRecoveryControllerNode: ASDisplayNode,
|
||||
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.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.tintColor = self.theme.list.itemAccentColor
|
||||
|
||||
|
@ -103,8 +103,8 @@ private final class PhoneAndCountryNode: ASDisplayNode {
|
||||
self.addSubnode(self.countryButton)
|
||||
self.addSubnode(self.phoneInputNode)
|
||||
|
||||
self.phoneInputNode.countryCodeField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
self.phoneInputNode.numberField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
self.phoneInputNode.countryCodeField.textField.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance
|
||||
self.phoneInputNode.numberField.textField.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance
|
||||
self.phoneInputNode.countryCodeField.textField.textColor = theme.list.itemPrimaryTextColor
|
||||
self.phoneInputNode.numberField.textField.textColor = theme.list.itemPrimaryTextColor
|
||||
self.phoneInputNode.countryCodeField.textField.tintColor = theme.list.itemAccentColor
|
||||
|
@ -108,7 +108,7 @@ final class AuthorizationSequenceSignUpControllerNode: ASDisplayNode, UITextFiel
|
||||
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
||||
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.lastNameField = TextFieldNode()
|
||||
@ -122,7 +122,7 @@ final class AuthorizationSequenceSignUpControllerNode: ASDisplayNode, UITextFiel
|
||||
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
||||
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.currentPhotoNode = ASImageNode()
|
||||
|
@ -2769,7 +2769,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
}
|
||||
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 {
|
||||
strongSelf.typingActivityPromise.set(Signal<Bool, NoError>.single(true)
|
||||
|> 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
|
||||
actionSheet?.dismissAnimated()
|
||||
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 {
|
||||
var signals: [Signal<ICloudFileDescription?, NoError>] = []
|
||||
for url in urls {
|
||||
|
@ -186,7 +186,7 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
|
||||
self.effectView = UIVisualEffectView()
|
||||
if #available(iOS 9.0, *) {
|
||||
} else {
|
||||
if self.presentationData.theme.chatList.searchBarKeyboardColor == .dark {
|
||||
if self.presentationData.theme.rootController.keyboardColor == .dark {
|
||||
self.effectView.effect = UIBlurEffect(style: .dark)
|
||||
} else {
|
||||
self.effectView.effect = UIBlurEffect(style: .light)
|
||||
@ -310,7 +310,7 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
|
||||
|
||||
if #available(iOS 9.0, *) {
|
||||
} else {
|
||||
if self.presentationData.theme.chatList.searchBarKeyboardColor == .dark {
|
||||
if self.presentationData.theme.rootController.keyboardColor == .dark {
|
||||
self.effectView.effect = UIBlurEffect(style: .dark)
|
||||
} else {
|
||||
self.effectView.effect = UIBlurEffect(style: .light)
|
||||
|
@ -502,7 +502,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
||||
textColor = presentationInterfaceState.theme.chat.inputPanel.inputTextColor
|
||||
tintColor = presentationInterfaceState.theme.list.itemAccentColor
|
||||
baseFontSize = max(17.0, presentationInterfaceState.fontSize.baseDisplaySize)
|
||||
keyboardAppearance = presentationInterfaceState.theme.chat.inputPanel.keyboardColor.keyboardAppearance
|
||||
keyboardAppearance = presentationInterfaceState.theme.rootController.keyboardColor.keyboardAppearance
|
||||
}
|
||||
|
||||
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 textInputNode.isCurrentlyEmoji() {
|
||||
textInputNode.initialPrimaryLanguage = "emoji"
|
||||
|
@ -52,7 +52,7 @@ private final class ChatTextLinkEditInputFieldNode: ASDisplayNode, ASEditableTex
|
||||
self.textInputNode.clipsToBounds = true
|
||||
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.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
self.textInputNode.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance
|
||||
self.textInputNode.keyboardType = .URL
|
||||
self.textInputNode.autocapitalizationType = .none
|
||||
self.textInputNode.returnKeyType = .done
|
||||
@ -77,7 +77,7 @@ private final class ChatTextLinkEditInputFieldNode: ASDisplayNode, ASEditableTex
|
||||
self.theme = theme
|
||||
|
||||
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.textInputNode.tintColor = self.theme.actionSheet.controlAccentColor
|
||||
}
|
||||
|
@ -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.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()
|
||||
|
||||
|
@ -263,7 +263,7 @@ class PaneSearchBarNode: ASDisplayNode, UITextFieldDelegate {
|
||||
self.iconNode.image = generateLoupeIcon(color: theme.chat.inputMediaPanel.stickersSearchControlColor)
|
||||
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.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
self.textField.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance
|
||||
self.textField.tintColor = theme.list.itemAccentColor
|
||||
|
||||
if let (boundingSize, leftInset, rightInset) = self.validLayout {
|
||||
|
Binary file not shown.
@ -62,7 +62,6 @@
|
||||
09FFBCD72281BB2D00C33B4B /* ChatTextLinkEditController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09FFBCD62281BB2D00C33B4B /* ChatTextLinkEditController.swift */; };
|
||||
D000CABC21F158AD0011B15D /* PrepareSecretThumbnailData.swift in Sources */ = {isa = PBXBuildFile; fileRef = D000CABB21F158AD0011B15D /* PrepareSecretThumbnailData.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 */; };
|
||||
D008178222B47464008A895F /* NotificationContentContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = D008178122B47464008A895F /* NotificationContentContext.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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
@ -1740,7 +1738,6 @@
|
||||
children = (
|
||||
D00E15251DDBD4E700ACF65C /* LegacyCamera.swift */,
|
||||
D06BB8811F58994B0084FC30 /* LegacyInstantVideoController.swift */,
|
||||
D007019B2029E8F2006B9E34 /* LegacyICloudFileController.swift */,
|
||||
D0380DAC204ED434000414AB /* LegacyLiveUploadInterface.swift */,
|
||||
D0B21B1E22156D92003F741D /* LegacyCache.swift */,
|
||||
);
|
||||
@ -3064,7 +3061,6 @@
|
||||
090B48C82200BCA8005083FA /* WallpaperUploadManager.swift in Sources */,
|
||||
09F2158D225CF5BC00AEDF6D /* Pasteboard.swift in Sources */,
|
||||
D0C26D571FDF2388004ABF18 /* OpenChatMessage.swift in Sources */,
|
||||
D007019C2029E8F2006B9E34 /* LegacyICloudFileController.swift in Sources */,
|
||||
D000CABC21F158AD0011B15D /* PrepareSecretThumbnailData.swift in Sources */,
|
||||
D08BDF641FA37BEA009D08E1 /* ChatRecordingPreviewInputPanelNode.swift in Sources */,
|
||||
D0943B071FDEC529001522CC /* InstantVideoRadialStatusNode.swift in Sources */,
|
||||
|
@ -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 {
|
||||
case builtin(PresentationBuiltinThemeReference)
|
||||
case local(PresentationLocalTheme)
|
||||
case cloud(TelegramTheme)
|
||||
case cloud(PresentationCloudTheme)
|
||||
|
||||
public init(decoder: PostboxDecoder) {
|
||||
switch decoder.decodeInt32ForKey("v", orElse: 0) {
|
||||
@ -68,7 +100,7 @@ public enum PresentationThemeReference: PostboxCoding, Equatable {
|
||||
case 1:
|
||||
self = .local(decoder.decodeObjectForKey("localTheme", decoder: { PresentationLocalTheme(decoder: $0) }) as! PresentationLocalTheme)
|
||||
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:
|
||||
assertionFailure()
|
||||
self = .builtin(.dayClassic)
|
||||
@ -85,7 +117,7 @@ public enum PresentationThemeReference: PostboxCoding, Equatable {
|
||||
encoder.encodeObject(theme, forKey: "localTheme")
|
||||
case let .cloud(theme):
|
||||
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)
|
||||
case let .cloud(theme):
|
||||
namespace = 2
|
||||
id = themeId(for: theme.id)
|
||||
id = themeId(for: theme.theme.id)
|
||||
}
|
||||
|
||||
return (Int64(namespace) << 32) | Int64(bitPattern: UInt64(UInt32(bitPattern: id)))
|
||||
@ -379,9 +411,12 @@ public struct PresentationThemeSettings: PreferencesEntry {
|
||||
case let .local(theme):
|
||||
resources.append(theme.resource.id)
|
||||
case let .cloud(theme):
|
||||
if let file = theme.file {
|
||||
if let file = theme.theme.file {
|
||||
resources.append(file.resource.id)
|
||||
}
|
||||
if let chatWallpaper = theme.resolvedWallpaper {
|
||||
resources.append(contentsOf: wallpaperResources(chatWallpaper))
|
||||
}
|
||||
}
|
||||
return resources
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user