mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-16 19:30:29 +00:00
Various UI fixes
This commit is contained in:
parent
9bf4297c60
commit
ebc595a62f
22
Images.xcassets/Settings/MenuIcons/EditProfile.imageset/Contents.json
vendored
Normal file
22
Images.xcassets/Settings/MenuIcons/EditProfile.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "EditProfile@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "EditProfile@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
Images.xcassets/Settings/MenuIcons/EditProfile.imageset/EditProfile@2x.png
vendored
Normal file
BIN
Images.xcassets/Settings/MenuIcons/EditProfile.imageset/EditProfile@2x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 666 B |
BIN
Images.xcassets/Settings/MenuIcons/EditProfile.imageset/EditProfile@3x.png
vendored
Normal file
BIN
Images.xcassets/Settings/MenuIcons/EditProfile.imageset/EditProfile@3x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 954 B |
@ -71,6 +71,7 @@ func faqSearchableItems(context: AccountContext) -> Signal<[SettingsSearchableIt
|
||||
return cachedFaqInstantPage(context: context)
|
||||
|> map { resolvedUrl -> [SettingsSearchableItem] in
|
||||
var results: [SettingsSearchableItem] = []
|
||||
var nextIndex: Int = 1
|
||||
if case let .instantView(webPage, _) = resolvedUrl {
|
||||
if case let .Loaded(content) = webPage.content, let instantPage = content.instantPage {
|
||||
var processingQuestions = false
|
||||
@ -83,14 +84,15 @@ func faqSearchableItems(context: AccountContext) -> Signal<[SettingsSearchableIt
|
||||
if results.isEmpty {
|
||||
processingQuestions = true
|
||||
}
|
||||
case let .anchor(anchor):
|
||||
currentAnchor = anchor
|
||||
case let .header(text):
|
||||
if let anchor = currentAnchor {
|
||||
results.append(SettingsSearchableItem(id: .faq(results.count + 1), title: text.plainText, alternate: [], icon: .faq, breadcrumbs: [strings.SettingsSearch_FAQ], present: { context, _, present in
|
||||
present(.push, InstantPageController(context: context, webPage: webPage, sourcePeerType: .channel, anchor: anchor))
|
||||
}))
|
||||
}
|
||||
// case let .anchor(anchor):
|
||||
// currentAnchor = anchor
|
||||
// case let .header(text):
|
||||
// if let anchor = currentAnchor {
|
||||
// results.append(SettingsSearchableItem(id: .faq(nextIndex), title: text.plainText, alternate: [], icon: .faq, breadcrumbs: [strings.SettingsSearch_FAQ], present: { context, _, present in
|
||||
// present(.push, InstantPageController(context: context, webPage: webPage, sourcePeerType: .channel, anchor: anchor))
|
||||
// }))
|
||||
// nextIndex += 1
|
||||
// }
|
||||
default:
|
||||
break
|
||||
}
|
||||
@ -107,9 +109,20 @@ func faqSearchableItems(context: AccountContext) -> Signal<[SettingsSearchableIt
|
||||
for item in items {
|
||||
if case let .text(itemText, _) = item, case let .url(text, url, _) = itemText {
|
||||
let (_, anchor) = extractAnchor(string: url)
|
||||
results.append(SettingsSearchableItem(id: .faq(results.count + 1), title: text.plainText, alternate: [], icon: .faq, breadcrumbs: [strings.SettingsSearch_FAQ, currentSection], present: { context, _, present in
|
||||
var index = nextIndex
|
||||
if anchor?.contains("delete-my-account") ?? false {
|
||||
index = 0
|
||||
} else {
|
||||
nextIndex += 1
|
||||
}
|
||||
let item = SettingsSearchableItem(id: .faq(index), title: text.plainText, alternate: [], icon: .faq, breadcrumbs: [strings.SettingsSearch_FAQ, currentSection], present: { context, _, present in
|
||||
present(.push, InstantPageController(context: context, webPage: webPage, sourcePeerType: .channel, anchor: anchor))
|
||||
}))
|
||||
})
|
||||
if index == 0 {
|
||||
results.insert(item, at: 0)
|
||||
} else {
|
||||
results.append(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -352,7 +352,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
}
|
||||
durationNode.defaultDuration = telegramFile.duration.flatMap(Double.init)
|
||||
|
||||
let streamVideo = automaticDownload && isMediaStreamable(message: item.message, media: telegramFile)
|
||||
let streamVideo = automaticDownload && isMediaStreamable(message: item.message, media: telegramFile) && telegramFile.id?.namespace != Namespaces.Media.LocalFile
|
||||
if let videoNode = strongSelf.videoNode {
|
||||
videoNode.layer.allowsGroupOpacity = true
|
||||
videoNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.5, delay: 0.2, removeOnCompletion: false, completion: { [weak videoNode] _ in
|
||||
@ -500,6 +500,15 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
var isBuffering: Bool?
|
||||
if let message = self.item?.message, let media = self.media, let size = media.size, (isMediaStreamable(message: message, media: media) || size <= 256 * 1024) && (self.automaticDownload ?? false) {
|
||||
if let playerStatus = self.playerStatus, case .buffering = playerStatus.status {
|
||||
isBuffering = true
|
||||
} else {
|
||||
isBuffering = false
|
||||
}
|
||||
}
|
||||
|
||||
var progressRequired = false
|
||||
if case let .fetchStatus(fetchStatus) = status.mediaStatus {
|
||||
if case .Local = fetchStatus {
|
||||
@ -511,6 +520,8 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
} else {
|
||||
progressRequired = true
|
||||
}
|
||||
} else if isBuffering ?? false {
|
||||
progressRequired = true
|
||||
}
|
||||
|
||||
if progressRequired {
|
||||
@ -530,15 +541,6 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
var isBuffering: Bool?
|
||||
if let message = self.item?.message, let media = self.media, let size = media.size, (isMediaStreamable(message: message, media: media) || size <= 256 * 1024) && (self.automaticDownload ?? false) {
|
||||
if let playerStatus = self.playerStatus, case .buffering = playerStatus.status {
|
||||
isBuffering = true
|
||||
} else {
|
||||
isBuffering = false
|
||||
}
|
||||
}
|
||||
|
||||
var state: RadialStatusNodeState
|
||||
switch status.mediaStatus {
|
||||
case var .fetchStatus(fetchStatus):
|
||||
@ -550,7 +552,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
case let .Fetching(_, progress):
|
||||
if let isBuffering = isBuffering {
|
||||
if isBuffering {
|
||||
state = .progress(color: bubbleTheme.mediaOverlayControlForegroundColor, lineWidth: nil, value: nil, cancelEnabled: false)
|
||||
state = .progress(color: bubbleTheme.mediaOverlayControlForegroundColor, lineWidth: nil, value: nil, cancelEnabled: true)
|
||||
} else {
|
||||
state = .none
|
||||
}
|
||||
@ -573,7 +575,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
}
|
||||
default:
|
||||
if isBuffering ?? false {
|
||||
state = .progress(color: bubbleTheme.mediaOverlayControlForegroundColor, lineWidth: nil, value: nil, cancelEnabled: false)
|
||||
state = .progress(color: bubbleTheme.mediaOverlayControlForegroundColor, lineWidth: nil, value: nil, cancelEnabled: true)
|
||||
} else {
|
||||
state = .none
|
||||
}
|
||||
|
||||
@ -178,8 +178,8 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode {
|
||||
let point = recognizer.location(in: self.imageNode.view)
|
||||
if let fetchStatus = self.fetchStatus, case .Local = fetchStatus {
|
||||
var videoContentMatch = true
|
||||
if let content = self.videoContent, case let .message(id, _, _) = content.nativeId {
|
||||
videoContentMatch = self.message?.id == id
|
||||
if let content = self.videoContent, case let .message(id, _, mediaId) = content.nativeId {
|
||||
videoContentMatch = self.message?.id == id && self.media?.id == mediaId
|
||||
}
|
||||
self.activateLocalContent((self.automaticPlayback ?? false) && videoContentMatch ? .automaticPlayback : .default)
|
||||
} else {
|
||||
@ -698,9 +698,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode {
|
||||
} else if let image = media as? TelegramMediaWebFile {
|
||||
strongSelf.fetchDisposable.set(chatMessageWebFileInteractiveFetched(account: context.account, image: image).start())
|
||||
} else if let file = media as? TelegramMediaFile {
|
||||
if automaticPlayback || !file.isAnimated {
|
||||
let fetchSignal = messageMediaFileInteractiveFetched(context: context, message: message, file: file, userInitiated: false)
|
||||
if !file.isAnimated {
|
||||
let visibilityAwareFetchSignal = strongSelf.visibilityPromise.get()
|
||||
|> mapToSignal { visibility -> Signal<Void, NoError> in
|
||||
switch visibility {
|
||||
@ -714,10 +712,6 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
strongSelf.fetchDisposable.set(visibilityAwareFetchSignal.start())
|
||||
} else {
|
||||
strongSelf.fetchDisposable.set(fetchSignal.start())
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if case .prefetch = automaticDownload, message.id.namespace != Namespaces.Message.SecretIncoming {
|
||||
if let file = media as? TelegramMediaFile {
|
||||
@ -927,7 +921,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode {
|
||||
if wideLayout {
|
||||
if let size = file.size {
|
||||
let sizeString = "\(dataSizeString(Int(Float(size) * progress), forceDecimal: true, decimalSeparator: decimalSeparator)) / \(dataSizeString(size, forceDecimal: true, decimalSeparator: decimalSeparator))"
|
||||
if file.isAnimated && !automaticDownload {
|
||||
if file.isAnimated && (!automaticDownload || !automaticPlayback) {
|
||||
badgeContent = .mediaDownload(backgroundColor: bubbleTheme.mediaDateAndStatusFillColor, foregroundColor: bubbleTheme.mediaDateAndStatusTextColor, duration: "GIF " + sizeString, size: nil, muted: false, active: false)
|
||||
}
|
||||
else if let duration = file.duration, !message.flags.contains(.Unsent) {
|
||||
@ -1031,7 +1025,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode {
|
||||
case .Remote:
|
||||
state = .download(bubbleTheme.mediaOverlayControlForegroundColor)
|
||||
if let file = self.media as? TelegramMediaFile {
|
||||
if file.isAnimated && !automaticDownload {
|
||||
if file.isAnimated && (!automaticDownload || !automaticPlayback) {
|
||||
let string = "GIF " + dataSizeString(file.size ?? 0, decimalSeparator: decimalSeparator)
|
||||
badgeContent = .mediaDownload(backgroundColor: bubbleTheme.mediaDateAndStatusFillColor, foregroundColor: bubbleTheme.mediaDateAndStatusTextColor, duration: string, size: nil, muted: false, active: false)
|
||||
} else {
|
||||
|
||||
@ -267,7 +267,7 @@ final class GridMessageItemNode: GridItemNode {
|
||||
badgeContent = .text(inset: 0.0, backgroundColor: mediaBadgeBackgroundColor, foregroundColor: mediaBadgeTextColor, text: NSAttributedString(string: durationString))
|
||||
}
|
||||
|
||||
strongSelf.mediaBadgeNode.update(theme: item.theme, content: badgeContent, mediaDownloadState: mediaDownloadState, alignment: .right, animated: false)
|
||||
strongSelf.mediaBadgeNode.update(theme: item.theme, content: badgeContent, mediaDownloadState: mediaDownloadState, alignment: .right, animated: false, badgeAnimated: false)
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
@ -338,23 +338,29 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
shouldUpdateVisibleItems = true
|
||||
self.updateNavigationBar()
|
||||
}
|
||||
var didSetScrollOffset = false
|
||||
if resetOffset {
|
||||
var contentOffset = CGPoint(x: 0.0, y: -self.scrollNode.view.contentInset.top)
|
||||
if let state = self.initialState {
|
||||
self.setupScrollOffsetOnLayout = false
|
||||
didSetScrollOffset = true
|
||||
contentOffset = CGPoint(x: 0.0, y: CGFloat(state.contentOffset))
|
||||
}
|
||||
else if let anchor = self.initialAnchor, !anchor.isEmpty {
|
||||
if let items = self.currentLayout?.items {
|
||||
self.setupScrollOffsetOnLayout = false
|
||||
didSetScrollOffset = true
|
||||
if let (item, lineOffset, _, _) = self.findAnchorItem(anchor, items: items) {
|
||||
contentOffset = CGPoint(x: 0.0, y: item.frame.minY + lineOffset - self.scrollNode.view.contentInset.top)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.setupScrollOffsetOnLayout = false
|
||||
didSetScrollOffset = true
|
||||
}
|
||||
self.scrollNode.view.contentOffset = contentOffset
|
||||
if didSetScrollOffset {
|
||||
self.previousContentOffset = contentOffset
|
||||
self.updateNavigationBar()
|
||||
self.setupScrollOffsetOnLayout = false
|
||||
}
|
||||
}
|
||||
if shouldUpdateVisibleItems {
|
||||
self.updateVisibleItems(visibleBounds: self.scrollNode.view.bounds)
|
||||
@ -668,7 +674,9 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
}
|
||||
|
||||
let delta: CGFloat
|
||||
if let previousContentOffset = self.previousContentOffset {
|
||||
if self.setupScrollOffsetOnLayout {
|
||||
delta = 0.0
|
||||
} else if let previousContentOffset = self.previousContentOffset {
|
||||
delta = contentOffset.y - previousContentOffset.y
|
||||
} else {
|
||||
delta = 0.0
|
||||
@ -700,6 +708,10 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
navigationBarFrame.size.height = max(minBarHeight, min(maxBarHeight, navigationBarFrame.size.height))
|
||||
}
|
||||
|
||||
if self.setupScrollOffsetOnLayout {
|
||||
navigationBarFrame.size.height = maxBarHeight
|
||||
}
|
||||
|
||||
let transitionFactor = (navigationBarFrame.size.height - minBarHeight) / (maxBarHeight - minBarHeight)
|
||||
|
||||
if containerLayout.safeInsets.top.isZero {
|
||||
|
||||
@ -92,7 +92,7 @@ class ItemListActionItemNode: ListViewItemNode, ItemListItemNode {
|
||||
private var item: ItemListActionItem?
|
||||
|
||||
var tag: ItemListItemTag? {
|
||||
return self.item?.tag
|
||||
return self.item?.tag as? ItemListItemTag
|
||||
}
|
||||
|
||||
init() {
|
||||
|
||||
@ -5,14 +5,6 @@ import Postbox
|
||||
import TelegramCore
|
||||
import LegacyComponents
|
||||
|
||||
private final class LogoutOptionsItemIcons {
|
||||
static let addAccount = UIImage(bundleImageName: "Settings/MenuIcons/AddAccount")?.precomposed()
|
||||
static let setPasscode = UIImage(bundleImageName: "Settings/MenuIcons/SetPasscode")?.precomposed()
|
||||
static let clearCache = UIImage(bundleImageName: "Settings/MenuIcons/ClearCache")?.precomposed()
|
||||
static let changePhoneNumber = UIImage(bundleImageName: "Settings/MenuIcons/ChangePhoneNumber")?.precomposed()
|
||||
static let contactSupport = UIImage(bundleImageName: "Settings/MenuIcons/Support")?.precomposed()
|
||||
}
|
||||
|
||||
private struct LogoutOptionsItemArguments {
|
||||
let addAccount: () -> Void
|
||||
let setPasscode: () -> Void
|
||||
@ -76,23 +68,23 @@ private enum LogoutOptionsEntry: ItemListNodeEntry, Equatable {
|
||||
case let .alternativeHeader(theme, title):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: title, sectionId: self.section)
|
||||
case let .addAccount(theme, title, text):
|
||||
return ItemListDisclosureItem(theme: theme, icon: LogoutOptionsItemIcons.addAccount, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
return ItemListDisclosureItem(theme: theme, icon: PresentationResourcesSettings.addAccount, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
arguments.addAccount()
|
||||
})
|
||||
case let .setPasscode(theme, title, text):
|
||||
return ItemListDisclosureItem(theme: theme, icon: LogoutOptionsItemIcons.setPasscode, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
return ItemListDisclosureItem(theme: theme, icon: PresentationResourcesSettings.setPasscode, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
arguments.setPasscode()
|
||||
})
|
||||
case let .clearCache(theme, title, text):
|
||||
return ItemListDisclosureItem(theme: theme, icon: LogoutOptionsItemIcons.clearCache, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
return ItemListDisclosureItem(theme: theme, icon: PresentationResourcesSettings.clearCache, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
arguments.clearCache()
|
||||
})
|
||||
case let .changePhoneNumber(theme, title, text):
|
||||
return ItemListDisclosureItem(theme: theme, icon: LogoutOptionsItemIcons.changePhoneNumber, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
return ItemListDisclosureItem(theme: theme, icon: PresentationResourcesSettings.changePhoneNumber, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
arguments.changePhoneNumber()
|
||||
})
|
||||
case let .contactSupport(theme, title, text):
|
||||
return ItemListDisclosureItem(theme: theme, icon: LogoutOptionsItemIcons.contactSupport, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
return ItemListDisclosureItem(theme: theme, icon: PresentationResourcesSettings.support, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
arguments.contactSupport()
|
||||
})
|
||||
case let .logout(theme, title):
|
||||
|
||||
@ -312,7 +312,6 @@ private func chatMessageVideoDatas(postbox: Postbox, fileReference: FileMediaRef
|
||||
|> mapToSignal { maybeData -> Signal<(Data?, (Data, String)?, Bool), NoError> in
|
||||
if maybeData.complete {
|
||||
let loadedData: Data? = try? Data(contentsOf: URL(fileURLWithPath: maybeData.path), options: [])
|
||||
|
||||
return .single((nil, loadedData == nil ? nil : (loadedData!, maybeData.path), true))
|
||||
} else {
|
||||
let thumbnail: Signal<Data?, NoError>
|
||||
|
||||
@ -2,6 +2,7 @@ import Foundation
|
||||
import Display
|
||||
|
||||
struct PresentationResourcesSettings {
|
||||
static let editProfile = UIImage(bundleImageName: "Settings/MenuIcons/EditProfile")?.precomposed()
|
||||
static let proxy = UIImage(bundleImageName: "Settings/MenuIcons/Proxy")?.precomposed()
|
||||
static let savedMessages = UIImage(bundleImageName: "Settings/MenuIcons/SavedMessages")?.precomposed()
|
||||
static let recentCalls = UIImage(bundleImageName: "Settings/MenuIcons/RecentCalls")?.precomposed()
|
||||
@ -18,4 +19,9 @@ struct PresentationResourcesSettings {
|
||||
|
||||
static let support = UIImage(bundleImageName: "Settings/MenuIcons/Support")?.precomposed()
|
||||
static let faq = UIImage(bundleImageName: "Settings/MenuIcons/Faq")?.precomposed()
|
||||
|
||||
static let addAccount = UIImage(bundleImageName: "Settings/MenuIcons/AddAccount")?.precomposed()
|
||||
static let setPasscode = UIImage(bundleImageName: "Settings/MenuIcons/SetPasscode")?.precomposed()
|
||||
static let clearCache = UIImage(bundleImageName: "Settings/MenuIcons/ClearCache")?.precomposed()
|
||||
static let changePhoneNumber = UIImage(bundleImageName: "Settings/MenuIcons/ChangePhoneNumber")?.precomposed()
|
||||
}
|
||||
|
||||
@ -598,7 +598,6 @@ func selectivePrivacySettingsController(context: AccountContext, kind: Selective
|
||||
let actionsDisposable = DisposableSet()
|
||||
|
||||
let updateSettingsDisposable = MetaDisposable()
|
||||
actionsDisposable.add(updateSettingsDisposable)
|
||||
|
||||
let arguments = SelectivePrivacySettingsControllerArguments(context: context, updateType: { type in
|
||||
updateState {
|
||||
@ -721,9 +720,8 @@ func selectivePrivacySettingsController(context: AccountContext, kind: Selective
|
||||
actionsDisposable.dispose()
|
||||
}
|
||||
|
||||
let controller = ItemListController(context: context, state: signal)
|
||||
controller.didDisappear = { [weak controller] _ in
|
||||
if let controller = controller, controller.navigationController?.viewControllers.firstIndex(of: controller) == nil {
|
||||
|
||||
let update: (Bool) -> Void = { save in
|
||||
var wasSaving = false
|
||||
var settings: SelectivePrivacySettings?
|
||||
var callP2PSettings: SelectivePrivacySettings?
|
||||
@ -787,6 +785,17 @@ func selectivePrivacySettingsController(context: AccountContext, kind: Selective
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let controller = ItemListController(context: context, state: signal)
|
||||
controller.willDisappear = { [weak controller] _ in
|
||||
if let controller = controller, controller.navigationController?.viewControllers.firstIndex(of: controller) == nil {
|
||||
update(false)
|
||||
}
|
||||
}
|
||||
controller.didDisappear = { [weak controller] _ in
|
||||
if let controller = controller, controller.navigationController?.viewControllers.firstIndex(of: controller) == nil {
|
||||
update(true)
|
||||
}
|
||||
}
|
||||
|
||||
pushControllerImpl = { [weak controller] c in
|
||||
|
||||
@ -1078,7 +1078,7 @@ public func settingsController(context: AccountContext, accountManager: AccountM
|
||||
presentControllerImpl?(v, a)
|
||||
}, pushController: { v in
|
||||
pushControllerImpl?(v)
|
||||
}, getNavigationController: getNavigationControllerImpl)
|
||||
}, getNavigationController: getNavigationControllerImpl, exceptionsList: notifyExceptions.get())
|
||||
|
||||
let (hasPassport, hasWatchApp) = hasPassportAndWatch
|
||||
let listState = ItemListNodeState(entries: settingsEntries(account: context.account, presentationData: presentationData, state: state, view: view, proxySettings: proxySettings, notifyExceptions: preferencesAndExceptions.1, notificationsAuthorizationStatus: preferencesAndExceptions.2, notificationsWarningSuppressed: preferencesAndExceptions.3, unreadTrendingStickerPacks: unreadTrendingStickerPacks, archivedPacks: featuredAndArchived.1, hasPassport: hasPassport, hasWatchApp: hasWatchApp, accountsAndPeers: accountsAndPeers.1, inAppNotificationSettings: inAppNotificationSettings), style: .blocks, searchItem: searchItem, initialScrollToItem: ListViewScrollToItem(index: 0, position: .top(-navigationBarSearchContentHeight), animated: false, curve: .Default(duration: 0.0), directionHint: .Up))
|
||||
|
||||
@ -19,6 +19,8 @@ extension NavigationBarSearchContentNode: ItemListControllerSearchNavigationCont
|
||||
extension SettingsSearchableItemIcon {
|
||||
func image() -> UIImage? {
|
||||
switch self {
|
||||
case .profile:
|
||||
return PresentationResourcesSettings.editProfile
|
||||
case .proxy:
|
||||
return PresentationResourcesSettings.proxy
|
||||
case .savedMessages:
|
||||
@ -58,12 +60,13 @@ final class SettingsSearchItem: ItemListControllerSearch {
|
||||
let presentController: (ViewController, Any?) -> Void
|
||||
let pushController: (ViewController) -> Void
|
||||
let getNavigationController: (() -> NavigationController?)?
|
||||
let exceptionsList: Signal<NotificationExceptionsList?, NoError>
|
||||
|
||||
private var updateActivity: ((Bool) -> Void)?
|
||||
private var activity: ValuePromise<Bool> = ValuePromise(ignoreRepeated: false)
|
||||
private let activityDisposable = MetaDisposable()
|
||||
|
||||
init(context: AccountContext, theme: PresentationTheme, placeholder: String, activated: Bool, updateActivated: @escaping (Bool) -> Void, presentController: @escaping (ViewController, Any?) -> Void, pushController: @escaping (ViewController) -> Void, getNavigationController: (() -> NavigationController?)?) {
|
||||
init(context: AccountContext, theme: PresentationTheme, placeholder: String, activated: Bool, updateActivated: @escaping (Bool) -> Void, presentController: @escaping (ViewController, Any?) -> Void, pushController: @escaping (ViewController) -> Void, getNavigationController: (() -> NavigationController?)?, exceptionsList: Signal<NotificationExceptionsList?, NoError>) {
|
||||
self.context = context
|
||||
self.theme = theme
|
||||
self.placeholder = placeholder
|
||||
@ -72,6 +75,7 @@ final class SettingsSearchItem: ItemListControllerSearch {
|
||||
self.presentController = presentController
|
||||
self.pushController = pushController
|
||||
self.getNavigationController = getNavigationController
|
||||
self.exceptionsList = exceptionsList
|
||||
self.activityDisposable.set((activity.get() |> mapToSignal { value -> Signal<Bool, NoError> in
|
||||
if value {
|
||||
return .single(value) |> delay(0.2, queue: Queue.mainQueue())
|
||||
@ -135,7 +139,7 @@ final class SettingsSearchItem: ItemListControllerSearch {
|
||||
pushController(c)
|
||||
}, presentController: { c, a in
|
||||
presentController(c, a)
|
||||
}, getNavigationController: self.getNavigationController)
|
||||
}, getNavigationController: self.getNavigationController, exceptionsList: self.exceptionsList)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -217,7 +221,7 @@ private final class SettingsSearchContainerNode: SearchDisplayControllerContentN
|
||||
|
||||
private let themeAndStringsPromise: Promise<(PresentationTheme, PresentationStrings)>
|
||||
|
||||
init(context: AccountContext, listState: LocalizationListState, openResult: @escaping (SettingsSearchableItem) -> Void) {
|
||||
init(context: AccountContext, openResult: @escaping (SettingsSearchableItem) -> Void, exceptionsList: Signal<NotificationExceptionsList?, NoError>) {
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
self.themeAndStringsPromise = Promise((self.presentationData.theme, self.presentationData.strings))
|
||||
@ -235,14 +239,20 @@ private final class SettingsSearchContainerNode: SearchDisplayControllerContentN
|
||||
self.addSubnode(self.dimNode)
|
||||
self.addSubnode(self.listNode)
|
||||
|
||||
let queryAndFoundItems = combineLatest(settingsSearchableItems(context: context), faqSearchableItems(context: context))
|
||||
let queryAndFoundItems = combineLatest(settingsSearchableItems(context: context, exceptionsList: exceptionsList), faqSearchableItems(context: context))
|
||||
|> mapToSignal { searchableItems, faqSearchableItems -> Signal<(String, [SettingsSearchableItem])?, NoError> in
|
||||
return self.searchQuery.get()
|
||||
|> mapToSignal { query -> Signal<(String, [SettingsSearchableItem])?, NoError> in
|
||||
if let query = query, !query.isEmpty {
|
||||
let result = searchSettingsItems(items: searchableItems, query: query)
|
||||
let results = searchSettingsItems(items: searchableItems, query: query)
|
||||
let faqResults = searchSettingsItems(items: faqSearchableItems, query: query)
|
||||
return .single((query, result + faqResults))
|
||||
let finalResults: [SettingsSearchableItem]
|
||||
if faqResults.first?.id == .faq(0) {
|
||||
finalResults = faqResults + results
|
||||
} else {
|
||||
finalResults = results + faqResults
|
||||
}
|
||||
return .single((query, finalResults))
|
||||
} else {
|
||||
return .single(nil)
|
||||
}
|
||||
@ -404,16 +414,18 @@ private final class SettingsSearchItemNode: ItemListControllerSearchNode {
|
||||
let pushController: (ViewController) -> Void
|
||||
let presentController: (ViewController, Any?) -> Void
|
||||
let getNavigationController: (() -> NavigationController?)?
|
||||
let exceptionsList: Signal<NotificationExceptionsList?, NoError>
|
||||
|
||||
var cancel: () -> Void
|
||||
|
||||
init(context: AccountContext, cancel: @escaping () -> Void, updateActivity: @escaping(Bool) -> Void, pushController: @escaping (ViewController) -> Void, presentController: @escaping (ViewController, Any?) -> Void, getNavigationController: (() -> NavigationController?)?) {
|
||||
init(context: AccountContext, cancel: @escaping () -> Void, updateActivity: @escaping(Bool) -> Void, pushController: @escaping (ViewController) -> Void, presentController: @escaping (ViewController, Any?) -> Void, getNavigationController: (() -> NavigationController?)?, exceptionsList: Signal<NotificationExceptionsList?, NoError>) {
|
||||
self.context = context
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
self.cancel = cancel
|
||||
self.pushController = pushController
|
||||
self.presentController = presentController
|
||||
self.getNavigationController = getNavigationController
|
||||
self.cancel = cancel
|
||||
self.exceptionsList = exceptionsList
|
||||
|
||||
super.init()
|
||||
}
|
||||
@ -428,7 +440,7 @@ private final class SettingsSearchItemNode: ItemListControllerSearchNode {
|
||||
return
|
||||
}
|
||||
|
||||
self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, contentNode: SettingsSearchContainerNode(context: self.context, listState: LocalizationListState.defaultSettings, openResult: { [weak self] result in
|
||||
self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, contentNode: SettingsSearchContainerNode(context: self.context, openResult: { [weak self] result in
|
||||
if let strongSelf = self {
|
||||
result.present(strongSelf.context, strongSelf.getNavigationController?(), { [weak self] mode, controller in
|
||||
if let strongSelf = self {
|
||||
@ -445,7 +457,7 @@ private final class SettingsSearchItemNode: ItemListControllerSearchNode {
|
||||
}
|
||||
})
|
||||
}
|
||||
}), cancel: { [weak self] in
|
||||
}, exceptionsList: self.exceptionsList), cancel: { [weak self] in
|
||||
self?.cancel()
|
||||
})
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@ import TelegramCore
|
||||
private let maximumNumberOfAccounts = 3
|
||||
|
||||
enum SettingsSearchableItemIcon {
|
||||
case profile
|
||||
case proxy
|
||||
case savedMessages
|
||||
case calls
|
||||
@ -55,7 +56,7 @@ struct SettingsSearchableItem {
|
||||
}
|
||||
|
||||
private func profileSearchableItems(context: AccountContext, canAddAccount: Bool) -> [SettingsSearchableItem] {
|
||||
let icon: SettingsSearchableItemIcon = .calls
|
||||
let icon: SettingsSearchableItemIcon = .profile
|
||||
let strings = context.sharedContext.currentPresentationData.with { $0 }.strings
|
||||
|
||||
let presentProfileSettings: (AccountContext, @escaping (SettingsSearchableItemPresentation, ViewController) -> Void, EditSettingsEntryTag?) -> Void = { context, present, itemTag in
|
||||
@ -155,12 +156,12 @@ private func stickerSearchableItems(context: AccountContext) -> [SettingsSearcha
|
||||
]
|
||||
}
|
||||
|
||||
private func notificationSearchableItems(context: AccountContext, notifyExceptions: Signal<NotificationExceptionsList?, NoError>) -> [SettingsSearchableItem] {
|
||||
private func notificationSearchableItems(context: AccountContext, exceptionsList: NotificationExceptionsList?) -> [SettingsSearchableItem] {
|
||||
let icon: SettingsSearchableItemIcon = .notifications
|
||||
let strings = context.sharedContext.currentPresentationData.with { $0 }.strings
|
||||
|
||||
let presentNotificationSettings: (AccountContext, (SettingsSearchableItemPresentation, ViewController) -> Void, NotificationsAndSoundsEntryTag?) -> Void = { context, present, itemTag in
|
||||
present(.push, notificationsAndSoundsController(context: context, exceptionsList: nil, focusOnItemTag: itemTag))
|
||||
present(.push, notificationsAndSoundsController(context: context, exceptionsList: exceptionsList, focusOnItemTag: itemTag))
|
||||
}
|
||||
|
||||
return [
|
||||
@ -475,7 +476,7 @@ private func appearanceSearchableItems(context: AccountContext) -> [SettingsSear
|
||||
]
|
||||
}
|
||||
|
||||
func settingsSearchableItems(context: AccountContext) -> Signal<[SettingsSearchableItem], NoError> {
|
||||
func settingsSearchableItems(context: AccountContext, exceptionsList: Signal<NotificationExceptionsList?, NoError>) -> Signal<[SettingsSearchableItem], NoError> {
|
||||
let watchAppInstalled = (context.watchManager?.watchAppInstalled ?? .single(false))
|
||||
|> take(1)
|
||||
let canAddAccount = activeAccountsAndPeers(context: context)
|
||||
@ -483,8 +484,8 @@ func settingsSearchableItems(context: AccountContext) -> Signal<[SettingsSearcha
|
||||
|> map { accountsAndPeers -> Bool in
|
||||
return accountsAndPeers.1.count + 1 < maximumNumberOfAccounts
|
||||
}
|
||||
return combineLatest(watchAppInstalled, canAddAccount)
|
||||
|> map { watchAppInstalled, canAddAccount in
|
||||
return combineLatest(watchAppInstalled, canAddAccount, exceptionsList)
|
||||
|> map { watchAppInstalled, canAddAccount, exceptionsList in
|
||||
let strings = context.sharedContext.currentPresentationData.with { $0 }.strings
|
||||
|
||||
var allItems: [SettingsSearchableItem] = []
|
||||
@ -503,7 +504,7 @@ func settingsSearchableItems(context: AccountContext) -> Signal<[SettingsSearcha
|
||||
let stickerItems = stickerSearchableItems(context: context)
|
||||
allItems.append(contentsOf: stickerItems)
|
||||
|
||||
let notificationItems = notificationSearchableItems(context: context, notifyExceptions: .complete())
|
||||
let notificationItems = notificationSearchableItems(context: context, exceptionsList: exceptionsList)
|
||||
allItems.append(contentsOf: notificationItems)
|
||||
|
||||
let privacyItems = privacySearchableItems(context: context)
|
||||
@ -535,13 +536,25 @@ func settingsSearchableItems(context: AccountContext) -> Signal<[SettingsSearcha
|
||||
})
|
||||
allItems.append(passport)
|
||||
|
||||
let support = SettingsSearchableItem(id: .support(0), title: strings.Settings_Support, alternate: ["Support"], icon: .support, breadcrumbs: [], present: { context, _, present in
|
||||
//return .push(ChatController(context: context, chatLocation: .peer(context.account.peerId)))
|
||||
let support = SettingsSearchableItem(id: .support(0), title: strings.Settings_Support, alternate: [], icon: .support, breadcrumbs: [], present: { context, _, present in
|
||||
let _ = (supportPeerId(account: context.account)
|
||||
|> deliverOnMainQueue).start(next: { peerId in
|
||||
if let peerId = peerId {
|
||||
present(.push, ChatController(context: context, chatLocation: .peer(peerId)))
|
||||
}
|
||||
})
|
||||
})
|
||||
allItems.append(support)
|
||||
|
||||
let faq = SettingsSearchableItem(id: .faq(0), title: strings.Settings_FAQ, alternate: [], icon: .faq, breadcrumbs: [], present: { context, _, present in
|
||||
//return .push(ChatController(context: context, chatLocation: .peer(context.account.peerId)))
|
||||
let faq = SettingsSearchableItem(id: .faq(0), title: strings.Settings_FAQ, alternate: [], icon: .faq, breadcrumbs: [], present: { context, navigationController, present in
|
||||
|
||||
let _ = (cachedFaqInstantPage(context: context)
|
||||
|> deliverOnMainQueue).start(next: { resolvedUrl in
|
||||
openResolvedUrl(resolvedUrl, context: context, navigationController: navigationController, openPeer: { peer, navigation in
|
||||
}, present: { controller, arguments in
|
||||
present(.push, controller)
|
||||
}, dismissInput: {})
|
||||
})
|
||||
})
|
||||
allItems.append(faq)
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@ private final class SoftwareVideoThumbnailLayerNullAction: NSObject, CAAction {
|
||||
}
|
||||
|
||||
final class SoftwareVideoThumbnailLayer: CALayer {
|
||||
var disposable: Disposable?
|
||||
var disposable = MetaDisposable()
|
||||
|
||||
var ready: (() -> Void)? {
|
||||
didSet {
|
||||
@ -28,8 +28,7 @@ final class SoftwareVideoThumbnailLayer: CALayer {
|
||||
self.masksToBounds = true
|
||||
|
||||
if let dimensions = fileReference.media.dimensions {
|
||||
self.disposable = (mediaGridMessageVideo(postbox: account.postbox, videoReference: fileReference)
|
||||
|> deliverOn(Queue.concurrentDefaultQueue())).start(next: { [weak self] transform in
|
||||
self.disposable.set((mediaGridMessageVideo(postbox: account.postbox, videoReference: fileReference)).start(next: { [weak self] transform in
|
||||
var boundingSize = dimensions.aspectFilled(CGSize(width: 93.0, height: 93.0))
|
||||
let imageSize = boundingSize
|
||||
boundingSize.width = min(200.0, boundingSize.width)
|
||||
@ -42,7 +41,7 @@ final class SoftwareVideoThumbnailLayer: CALayer {
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,7 +50,7 @@ final class SoftwareVideoThumbnailLayer: CALayer {
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.disposable?.dispose()
|
||||
self.disposable.dispose()
|
||||
}
|
||||
|
||||
override func action(forKey event: String) -> CAAction? {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user