mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various fixes
This commit is contained in:
parent
3fee94d82b
commit
9f2e9407ef
@ -902,7 +902,7 @@ public protocol SharedAccountContext: AnyObject {
|
|||||||
|
|
||||||
func makeMediaPickerScreen(context: AccountContext, hasSearch: Bool, completion: @escaping (Any) -> Void) -> ViewController
|
func makeMediaPickerScreen(context: AccountContext, hasSearch: Bool, completion: @escaping (Any) -> Void) -> ViewController
|
||||||
|
|
||||||
func makeStoryMediaPickerScreen(context: AccountContext, getSourceRect: @escaping () -> CGRect, completion: @escaping (Any, UIView, CGRect, UIImage?, @escaping (Bool?) -> (UIView, CGRect)?, @escaping () -> Void) -> Void, dismissed: @escaping () -> Void) -> ViewController
|
func makeStoryMediaPickerScreen(context: AccountContext, getSourceRect: @escaping () -> CGRect, completion: @escaping (Any, UIView, CGRect, UIImage?, @escaping (Bool?) -> (UIView, CGRect)?, @escaping () -> Void) -> Void, dismissed: @escaping () -> Void, groupsPresented: @escaping () -> Void) -> ViewController
|
||||||
|
|
||||||
func makeProxySettingsController(sharedContext: SharedAccountContext, account: UnauthorizedAccount) -> ViewController
|
func makeProxySettingsController(sharedContext: SharedAccountContext, account: UnauthorizedAccount) -> ViewController
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ public struct VenueIconArguments: TransformImageCustomArguments {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func venueIcon(engine: TelegramEngine, type: String, flag: String? = nil, background: Bool) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> {
|
public func venueIcon(engine: TelegramEngine, type: String, flag: String? = nil, background: Bool) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> {
|
||||||
let isBuiltinIcon = ["", "home", "work"].contains(type)
|
let isBuiltinIcon = ["", "home", "work"].contains(type) || flag != nil
|
||||||
let data: Signal<Data?, NoError> = isBuiltinIcon ? .single(nil) : venueIconData(engine: engine, resource: VenueIconResource(type: type))
|
let data: Signal<Data?, NoError> = isBuiltinIcon ? .single(nil) : venueIconData(engine: engine, resource: VenueIconResource(type: type))
|
||||||
return data |> map { data in
|
return data |> map { data in
|
||||||
return { arguments in
|
return { arguments in
|
||||||
@ -164,7 +164,18 @@ public func venueIcon(engine: TelegramEngine, type: String, flag: String? = nil,
|
|||||||
c.fillEllipse(in: CGRect(origin: CGPoint(), size: arguments.drawingRect.size))
|
c.fillEllipse(in: CGRect(origin: CGPoint(), size: arguments.drawingRect.size))
|
||||||
}
|
}
|
||||||
let boundsSize = CGSize(width: arguments.drawingRect.size.width - 4.0 * 2.0, height: arguments.drawingRect.size.height - 4.0 * 2.0)
|
let boundsSize = CGSize(width: arguments.drawingRect.size.width - 4.0 * 2.0, height: arguments.drawingRect.size.height - 4.0 * 2.0)
|
||||||
if let image = iconImage, let cgImage = generateTintedImage(image: image, color: foregroundColor)?.cgImage {
|
if let flag {
|
||||||
|
let attributedString = NSAttributedString(string: flag, attributes: [NSAttributedString.Key.font: Font.regular(22.0), NSAttributedString.Key.foregroundColor: UIColor.white])
|
||||||
|
|
||||||
|
let line = CTLineCreateWithAttributedString(attributedString)
|
||||||
|
let lineBounds = CTLineGetBoundsWithOptions(line, .useGlyphPathBounds)
|
||||||
|
|
||||||
|
let bounds = CGRect(origin: .zero, size: boundsSize)
|
||||||
|
let lineOrigin = CGPoint(x: floorToScreenPixels((bounds.size.width - lineBounds.size.width) / 2.0), y: floorToScreenPixels((bounds.size.height - lineBounds.size.height) / 2.0))
|
||||||
|
|
||||||
|
c.translateBy(x: lineOrigin.x + 3.0, y: lineOrigin.y + 7.0)
|
||||||
|
CTLineDraw(line, c)
|
||||||
|
} else if let image = iconImage, let cgImage = generateTintedImage(image: image, color: foregroundColor)?.cgImage {
|
||||||
let fittedSize = image.size.aspectFitted(boundsSize)
|
let fittedSize = image.size.aspectFitted(boundsSize)
|
||||||
c.draw(cgImage, in: CGRect(origin: CGPoint(x: floor((arguments.drawingRect.width - fittedSize.width) / 2.0), y: floor((arguments.drawingRect.height - fittedSize.height) / 2.0)), size: fittedSize))
|
c.draw(cgImage, in: CGRect(origin: CGPoint(x: floor((arguments.drawingRect.width - fittedSize.width) / 2.0), y: floor((arguments.drawingRect.height - fittedSize.height) / 2.0)), size: fittedSize))
|
||||||
} else if isBuiltinIcon {
|
} else if isBuiltinIcon {
|
||||||
|
@ -268,22 +268,36 @@ final class LocationActionListItemNode: ListViewItemNode {
|
|||||||
var arguments: TransformImageCustomArguments?
|
var arguments: TransformImageCustomArguments?
|
||||||
if let updatedIcon = updatedIcon {
|
if let updatedIcon = updatedIcon {
|
||||||
switch updatedIcon {
|
switch updatedIcon {
|
||||||
case .location:
|
case .location:
|
||||||
strongSelf.iconNode.isHidden = false
|
strongSelf.iconNode.isHidden = false
|
||||||
strongSelf.venueIconNode.isHidden = true
|
strongSelf.venueIconNode.isHidden = true
|
||||||
strongSelf.iconNode.image = generateLocationIcon(theme: item.presentationData.theme)
|
strongSelf.iconNode.image = generateLocationIcon(theme: item.presentationData.theme)
|
||||||
case .liveLocation, .stopLiveLocation:
|
case .liveLocation, .stopLiveLocation:
|
||||||
strongSelf.iconNode.isHidden = false
|
strongSelf.iconNode.isHidden = false
|
||||||
strongSelf.venueIconNode.isHidden = true
|
strongSelf.venueIconNode.isHidden = true
|
||||||
strongSelf.iconNode.image = generateLiveLocationIcon(theme: item.presentationData.theme, stop: updatedIcon == .stopLiveLocation)
|
strongSelf.iconNode.image = generateLiveLocationIcon(theme: item.presentationData.theme, stop: updatedIcon == .stopLiveLocation)
|
||||||
case let .venue(venue):
|
case let .venue(venue):
|
||||||
strongSelf.iconNode.isHidden = true
|
strongSelf.iconNode.isHidden = true
|
||||||
strongSelf.venueIconNode.isHidden = false
|
strongSelf.venueIconNode.isHidden = false
|
||||||
strongSelf.venueIconNode.setSignal(venueIcon(engine: item.engine, type: venue.venue?.type ?? "", background: true))
|
|
||||||
|
|
||||||
if venue.venue?.id == "city" {
|
func flagEmoji(countryCode: String) -> String {
|
||||||
arguments = VenueIconArguments(defaultBackgroundColor: item.presentationData.theme.chat.inputPanel.actionControlFillColor, defaultForegroundColor: .white)
|
let base : UInt32 = 127397
|
||||||
|
var flagString = ""
|
||||||
|
for v in countryCode.uppercased().unicodeScalars {
|
||||||
|
flagString.unicodeScalars.append(UnicodeScalar(base + v.value)!)
|
||||||
}
|
}
|
||||||
|
return flagString
|
||||||
|
}
|
||||||
|
let type = venue.venue?.type
|
||||||
|
var flag: String?
|
||||||
|
if let venue = venue.venue, venue.provider == "city", let countryCode = venue.id {
|
||||||
|
flag = flagEmoji(countryCode: countryCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
if venue.venue?.provider == "city" {
|
||||||
|
arguments = VenueIconArguments(defaultBackgroundColor: item.presentationData.theme.chat.inputPanel.actionControlFillColor, defaultForegroundColor: .white)
|
||||||
|
}
|
||||||
|
strongSelf.venueIconNode.setSignal(venueIcon(engine: item.engine, type: type ?? "", flag: flag, background: true))
|
||||||
}
|
}
|
||||||
|
|
||||||
if updatedIcon == .stopLiveLocation {
|
if updatedIcon == .stopLiveLocation {
|
||||||
|
@ -150,7 +150,7 @@ private enum LocationPickerEntry: Comparable, Identifiable {
|
|||||||
case let .city(_, title, subtitle, _, _, _, coordinate, name, countryCode):
|
case let .city(_, title, subtitle, _, _, _, coordinate, name, countryCode):
|
||||||
let icon: LocationActionListItemIcon
|
let icon: LocationActionListItemIcon
|
||||||
if let name {
|
if let name {
|
||||||
icon = .venue(TelegramMediaMap(latitude: 0, longitude: 0, heading: nil, accuracyRadius: nil, geoPlace: nil, venue: MapVenue(title: name, address: "City", provider: nil, id: "city", type: "building/default"), liveBroadcastingTimeout: nil, liveProximityNotificationRadius: nil))
|
icon = .venue(TelegramMediaMap(latitude: 0, longitude: 0, heading: nil, accuracyRadius: nil, geoPlace: nil, venue: MapVenue(title: name, address: presentationData.strings.Location_TypeCity, provider: "city", id: countryCode, type: "building/default"), liveBroadcastingTimeout: nil, liveProximityNotificationRadius: nil))
|
||||||
} else {
|
} else {
|
||||||
icon = .location
|
icon = .location
|
||||||
}
|
}
|
||||||
@ -583,20 +583,28 @@ final class LocationPickerControllerNode: ViewControllerTracingNode, CLLocationM
|
|||||||
switch strongSelf.mode {
|
switch strongSelf.mode {
|
||||||
case .share:
|
case .share:
|
||||||
if source == .story {
|
if source == .story {
|
||||||
title = "Add This Location"
|
title = presentationData.strings.Location_AddThisLocation
|
||||||
} else {
|
} else {
|
||||||
title = presentationData.strings.Map_SendThisLocation
|
title = presentationData.strings.Map_SendThisLocation
|
||||||
}
|
}
|
||||||
case .pick:
|
case .pick:
|
||||||
title = presentationData.strings.Map_SetThisLocation
|
title = presentationData.strings.Map_SetThisLocation
|
||||||
}
|
}
|
||||||
entries.append(.location(presentationData.theme, title, address ?? presentationData.strings.Map_Locating, nil, nil, nil, coordinate, state.street, state.countryCode, true))
|
if source == .story {
|
||||||
|
if state.street != "" {
|
||||||
|
entries.append(.location(presentationData.theme, state.street ?? presentationData.strings.Map_Locating, state.isStreet ? presentationData.strings.Location_TypeStreet : presentationData.strings.Location_TypeLocation, nil, nil, nil, coordinate, state.street, nil, false))
|
||||||
|
} else if state.city != "" {
|
||||||
|
entries.append(.city(presentationData.theme, state.city ?? presentationData.strings.Map_Locating, presentationData.strings.Location_TypeCity, nil, nil, nil, coordinate, state.city, state.countryCode))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
entries.append(.location(presentationData.theme, title, address ?? presentationData.strings.Map_Locating, nil, nil, nil, coordinate, state.street, nil, true))
|
||||||
|
}
|
||||||
case .selecting:
|
case .selecting:
|
||||||
let title: String
|
let title: String
|
||||||
switch strongSelf.mode {
|
switch strongSelf.mode {
|
||||||
case .share:
|
case .share:
|
||||||
if source == .story {
|
if source == .story {
|
||||||
title = "Add This Location"
|
title = presentationData.strings.Location_AddThisLocation
|
||||||
} else {
|
} else {
|
||||||
title = presentationData.strings.Map_SendThisLocation
|
title = presentationData.strings.Map_SendThisLocation
|
||||||
}
|
}
|
||||||
|
@ -309,6 +309,9 @@ final class MediaPickerGridItemNode: GridItemNode {
|
|||||||
|
|
||||||
self.progressDisposable.set(nil)
|
self.progressDisposable.set(nil)
|
||||||
self.updateProgress(nil, animated: false)
|
self.updateProgress(nil, animated: false)
|
||||||
|
|
||||||
|
self.backgroundNode.image = nil
|
||||||
|
self.imageNode.contentMode = .scaleAspectFill
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.draftNode.supernode == nil {
|
if self.draftNode.supernode == nil {
|
||||||
@ -403,6 +406,7 @@ final class MediaPickerGridItemNode: GridItemNode {
|
|||||||
if asset.localIdentifier == self.currentAsset?.localIdentifier {
|
if asset.localIdentifier == self.currentAsset?.localIdentifier {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
self.backgroundNode.image = nil
|
||||||
|
|
||||||
self.progressDisposable.set(
|
self.progressDisposable.set(
|
||||||
(interaction.downloadManager.downloadProgress(identifier: asset.localIdentifier)
|
(interaction.downloadManager.downloadProgress(identifier: asset.localIdentifier)
|
||||||
|
@ -73,7 +73,7 @@ private struct MediaPickerGridTransaction {
|
|||||||
let scrollToItem: GridNodeScrollToItem?
|
let scrollToItem: GridNodeScrollToItem?
|
||||||
|
|
||||||
init(previousList: [MediaPickerGridEntry], list: [MediaPickerGridEntry], context: AccountContext, interaction: MediaPickerInteraction, theme: PresentationTheme, strings: PresentationStrings, scrollToItem: GridNodeScrollToItem?) {
|
init(previousList: [MediaPickerGridEntry], list: [MediaPickerGridEntry], context: AccountContext, interaction: MediaPickerInteraction, theme: PresentationTheme, strings: PresentationStrings, scrollToItem: GridNodeScrollToItem?) {
|
||||||
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: previousList, rightList: list)
|
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: previousList, rightList: list)
|
||||||
|
|
||||||
self.deletions = deleteIndices
|
self.deletions = deleteIndices
|
||||||
self.insertions = indicesAndItems.map { GridNodeInsertItem(index: $0.0, item: $0.1.item(context: context, interaction: interaction, theme: theme, strings: strings), previousIndex: $0.2) }
|
self.insertions = indicesAndItems.map { GridNodeInsertItem(index: $0.0, item: $0.1.item(context: context, interaction: interaction, theme: theme, strings: strings), previousIndex: $0.2) }
|
||||||
@ -81,6 +81,19 @@ private struct MediaPickerGridTransaction {
|
|||||||
|
|
||||||
self.scrollToItem = scrollToItem
|
self.scrollToItem = scrollToItem
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init(clearList: [MediaPickerGridEntry]) {
|
||||||
|
var deletions: [Int] = []
|
||||||
|
var i = 0
|
||||||
|
for _ in clearList {
|
||||||
|
deletions.append(i)
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
self.deletions = deletions
|
||||||
|
self.insertions = []
|
||||||
|
self.updates = []
|
||||||
|
self.scrollToItem = nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Month: Equatable {
|
struct Month: Equatable {
|
||||||
@ -585,6 +598,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fileprivate var resetOnUpdate = false
|
||||||
private func updateState(_ state: State) {
|
private func updateState(_ state: State) {
|
||||||
guard let controller = self.controller, let interaction = controller.interaction else {
|
guard let controller = self.controller, let interaction = controller.interaction else {
|
||||||
return
|
return
|
||||||
@ -659,6 +673,69 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
self.requestedCameraAccess = true
|
self.requestedCameraAccess = true
|
||||||
self.mediaAssetsContext.requestCameraAccess()
|
self.mediaAssetsContext.requestCameraAccess()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !controller.didSetupGroups {
|
||||||
|
controller.didSetupGroups = true
|
||||||
|
controller.groupsPromise.set(
|
||||||
|
combineLatest(
|
||||||
|
self.mediaAssetsContext.fetchAssetsCollections(.album),
|
||||||
|
self.mediaAssetsContext.fetchAssetsCollections(.smartAlbum)
|
||||||
|
)
|
||||||
|
|> map { albums, smartAlbums -> [MediaGroupItem] in
|
||||||
|
var collections: [PHAssetCollection] = []
|
||||||
|
smartAlbums.enumerateObjects { collection, _, _ in
|
||||||
|
if [.smartAlbumUserLibrary, .smartAlbumFavorites].contains(collection.assetCollectionSubtype) {
|
||||||
|
collections.append(collection)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
smartAlbums.enumerateObjects { collection, index, _ in
|
||||||
|
var supportedAlbums: [PHAssetCollectionSubtype] = [
|
||||||
|
.smartAlbumBursts,
|
||||||
|
.smartAlbumPanoramas,
|
||||||
|
.smartAlbumScreenshots,
|
||||||
|
.smartAlbumSelfPortraits,
|
||||||
|
.smartAlbumSlomoVideos,
|
||||||
|
.smartAlbumTimelapses,
|
||||||
|
.smartAlbumVideos,
|
||||||
|
.smartAlbumAllHidden
|
||||||
|
]
|
||||||
|
if #available(iOS 11, *) {
|
||||||
|
supportedAlbums.append(.smartAlbumAnimated)
|
||||||
|
supportedAlbums.append(.smartAlbumDepthEffect)
|
||||||
|
supportedAlbums.append(.smartAlbumLivePhotos)
|
||||||
|
}
|
||||||
|
if supportedAlbums.contains(collection.assetCollectionSubtype) {
|
||||||
|
let result = PHAsset.fetchAssets(in: collection, options: nil)
|
||||||
|
if result.count > 0 {
|
||||||
|
collections.append(collection)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
albums.enumerateObjects(options: [.reverse]) { collection, _, _ in
|
||||||
|
collections.append(collection)
|
||||||
|
}
|
||||||
|
|
||||||
|
var items: [MediaGroupItem] = []
|
||||||
|
for collection in collections {
|
||||||
|
let result = PHAsset.fetchAssets(in: collection, options: nil)
|
||||||
|
let firstItem: PHAsset?
|
||||||
|
if [.smartAlbumUserLibrary, .smartAlbumFavorites].contains(collection.assetCollectionSubtype) {
|
||||||
|
firstItem = result.lastObject
|
||||||
|
} else {
|
||||||
|
firstItem = result.firstObject
|
||||||
|
}
|
||||||
|
items.append(
|
||||||
|
MediaGroupItem(
|
||||||
|
collection: collection,
|
||||||
|
firstItem: firstItem,
|
||||||
|
count: result.count
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return items
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
} else if case .notDetermined = mediaAccess, !self.requestedMediaAccess {
|
} else if case .notDetermined = mediaAccess, !self.requestedMediaAccess {
|
||||||
self.requestedMediaAccess = true
|
self.requestedMediaAccess = true
|
||||||
self.mediaAssetsContext.requestMediaAccess()
|
self.mediaAssetsContext.requestMediaAccess()
|
||||||
@ -671,7 +748,16 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let previousEntries = self.currentEntries
|
|
||||||
|
|
||||||
|
var previousEntries = self.currentEntries
|
||||||
|
|
||||||
|
if self.resetOnUpdate {
|
||||||
|
self.enqueueTransaction(MediaPickerGridTransaction(clearList: previousEntries))
|
||||||
|
self.resetOnUpdate = false
|
||||||
|
previousEntries = []
|
||||||
|
}
|
||||||
|
|
||||||
self.currentEntries = entries
|
self.currentEntries = entries
|
||||||
|
|
||||||
var scrollToItem: GridNodeScrollToItem?
|
var scrollToItem: GridNodeScrollToItem?
|
||||||
@ -692,6 +778,10 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
self.updateNavigation(transition: .immediate)
|
self.updateNavigation(transition: .immediate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func resetItems() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private func updateSelectionState(animated: Bool = false) {
|
private func updateSelectionState(animated: Bool = false) {
|
||||||
self.gridNode.forEachItemNode { itemNode in
|
self.gridNode.forEachItemNode { itemNode in
|
||||||
if let itemNode = itemNode as? MediaPickerGridItemNode {
|
if let itemNode = itemNode as? MediaPickerGridItemNode {
|
||||||
@ -1541,7 +1631,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
|
|
||||||
self.titleView.action = { [weak self] in
|
self.titleView.action = { [weak self] in
|
||||||
if let self {
|
if let self {
|
||||||
self.openGroupsMenu()
|
self.presentGroupsMenu()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1720,77 +1810,20 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
self.controllerNode.closeGalleryController()
|
self.controllerNode.closeGalleryController()
|
||||||
}
|
}
|
||||||
|
|
||||||
public func openGroupsMenu() {
|
public var groupsPresented: () -> Void = {}
|
||||||
let updatedState = combineLatest(
|
|
||||||
queue: Queue.mainQueue(),
|
private var didSetupGroups = false
|
||||||
self.controllerNode.mediaAssetsContext.fetchAssetsCollections(.album),
|
private let groupsPromise = Promise<[MediaGroupItem]>()
|
||||||
self.controllerNode.mediaAssetsContext.fetchAssetsCollections(.smartAlbum)
|
|
||||||
)
|
public func presentGroupsMenu() {
|
||||||
let _ = (updatedState
|
self.groupsPresented()
|
||||||
|
|
||||||
|
let _ = (self.groupsPromise.get()
|
||||||
|> take(1)
|
|> take(1)
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] albums, smartAlbums in
|
|> deliverOnMainQueue).start(next: { [weak self] items in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var collections: [PHAssetCollection] = []
|
|
||||||
smartAlbums.enumerateObjects { collection, _, _ in
|
|
||||||
if [.smartAlbumUserLibrary, .smartAlbumFavorites].contains(collection.assetCollectionSubtype) {
|
|
||||||
collections.append(collection)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
smartAlbums.enumerateObjects { collection, index, _ in
|
|
||||||
var supportedAlbums: [PHAssetCollectionSubtype] = [
|
|
||||||
.smartAlbumBursts,
|
|
||||||
.smartAlbumPanoramas,
|
|
||||||
.smartAlbumScreenshots,
|
|
||||||
.smartAlbumSelfPortraits,
|
|
||||||
.smartAlbumSlomoVideos,
|
|
||||||
.smartAlbumTimelapses,
|
|
||||||
.smartAlbumVideos,
|
|
||||||
.smartAlbumAllHidden
|
|
||||||
]
|
|
||||||
if #available(iOS 11, *) {
|
|
||||||
supportedAlbums.append(.smartAlbumAnimated)
|
|
||||||
supportedAlbums.append(.smartAlbumDepthEffect)
|
|
||||||
supportedAlbums.append(.smartAlbumLivePhotos)
|
|
||||||
}
|
|
||||||
if supportedAlbums.contains(collection.assetCollectionSubtype) {
|
|
||||||
let result = PHAsset.fetchAssets(in: collection, options: nil)
|
|
||||||
if result.count > 0 {
|
|
||||||
collections.append(collection)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
albums.enumerateObjects(options: [.reverse]) { collection, _, _ in
|
|
||||||
collections.append(collection)
|
|
||||||
}
|
|
||||||
|
|
||||||
var items: [MediaGroupItem] = []
|
|
||||||
for collection in collections {
|
|
||||||
let result = PHAsset.fetchAssets(in: collection, options: nil)
|
|
||||||
let firstItem: PHAsset?
|
|
||||||
if [.smartAlbumUserLibrary, .smartAlbumFavorites].contains(collection.assetCollectionSubtype) {
|
|
||||||
firstItem = result.lastObject
|
|
||||||
} else {
|
|
||||||
firstItem = result.firstObject
|
|
||||||
}
|
|
||||||
// let iconSource: ContextMenuActionItemIconSource?
|
|
||||||
// if let firstItem {
|
|
||||||
// let targetSize = CGSize(width: 24.0, height: 24.0)
|
|
||||||
// iconSource = ContextMenuActionItemIconSource(size: CGSize(width: 24.0, height: 24.0), contentMode: .scaleAspectFill, cornerRadius: 6.0, signal: assetImage(asset: firstItem, targetSize: targetSize, exact: false))
|
|
||||||
// } else {
|
|
||||||
// iconSource = nil
|
|
||||||
// }
|
|
||||||
items.append(
|
|
||||||
MediaGroupItem(
|
|
||||||
collection: collection,
|
|
||||||
firstItem: firstItem,
|
|
||||||
count: result.count
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
var dismissImpl: (() -> Void)?
|
var dismissImpl: (() -> Void)?
|
||||||
let content: ContextControllerItemsContent = MediaGroupsContextMenuContent(
|
let content: ContextControllerItemsContent = MediaGroupsContextMenuContent(
|
||||||
context: self.context,
|
context: self.context,
|
||||||
@ -1799,6 +1832,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
self.controllerNode.resetOnUpdate = true
|
||||||
if collection.assetCollectionSubtype == .smartAlbumUserLibrary {
|
if collection.assetCollectionSubtype == .smartAlbumUserLibrary {
|
||||||
self.selectedCollection.set(.single(nil))
|
self.selectedCollection.set(.single(nil))
|
||||||
self.titleView.title = self.presentationData.strings.MediaPicker_Recents
|
self.titleView.title = self.presentationData.strings.MediaPicker_Recents
|
||||||
@ -1806,6 +1840,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
self.selectedCollection.set(.single(collection))
|
self.selectedCollection.set(.single(collection))
|
||||||
self.titleView.title = collection.localizedTitle ?? ""
|
self.titleView.title = collection.localizedTitle ?? ""
|
||||||
}
|
}
|
||||||
|
self.scrollToTop?()
|
||||||
dismissImpl?()
|
dismissImpl?()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -2461,7 +2496,8 @@ public func storyMediaPickerController(
|
|||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
getSourceRect: @escaping () -> CGRect,
|
getSourceRect: @escaping () -> CGRect,
|
||||||
completion: @escaping (Any, UIView, CGRect, UIImage?, @escaping (Bool?) -> (UIView, CGRect)?, @escaping () -> Void) -> Void,
|
completion: @escaping (Any, UIView, CGRect, UIImage?, @escaping (Bool?) -> (UIView, CGRect)?, @escaping () -> Void) -> Void,
|
||||||
dismissed: @escaping () -> Void
|
dismissed: @escaping () -> Void,
|
||||||
|
groupsPresented: @escaping () -> Void
|
||||||
) -> ViewController {
|
) -> ViewController {
|
||||||
let presentationData = context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: defaultDarkColorPresentationTheme)
|
let presentationData = context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: defaultDarkColorPresentationTheme)
|
||||||
let updatedPresentationData: (PresentationData, Signal<PresentationData, NoError>) = (presentationData, .single(presentationData))
|
let updatedPresentationData: (PresentationData, Signal<PresentationData, NoError>) = (presentationData, .single(presentationData))
|
||||||
@ -2472,6 +2508,7 @@ public func storyMediaPickerController(
|
|||||||
controller.getSourceRect = getSourceRect
|
controller.getSourceRect = getSourceRect
|
||||||
controller.requestController = { _, present in
|
controller.requestController = { _, present in
|
||||||
let mediaPickerController = MediaPickerScreen(context: context, updatedPresentationData: updatedPresentationData, peer: nil, threadTitle: nil, chatLocation: nil, bannedSendPhotos: nil, bannedSendVideos: nil, subject: .assets(nil, .story), mainButtonState: nil, mainButtonAction: nil)
|
let mediaPickerController = MediaPickerScreen(context: context, updatedPresentationData: updatedPresentationData, peer: nil, threadTitle: nil, chatLocation: nil, bannedSendPhotos: nil, bannedSendVideos: nil, subject: .assets(nil, .story), mainButtonState: nil, mainButtonAction: nil)
|
||||||
|
mediaPickerController.groupsPresented = groupsPresented
|
||||||
mediaPickerController.customSelection = { controller, result in
|
mediaPickerController.customSelection = { controller, result in
|
||||||
if let result = result as? MediaEditorDraft {
|
if let result = result as? MediaEditorDraft {
|
||||||
controller.updateHiddenMediaId(result.path)
|
controller.updateHiddenMediaId(result.path)
|
||||||
|
@ -47,6 +47,7 @@ final class MediaPickerTitleView: UIView {
|
|||||||
if self.segmentsHidden != oldValue {
|
if self.segmentsHidden != oldValue {
|
||||||
let transition = ContainedViewLayoutTransition.animated(duration: 0.21, curve: .easeInOut)
|
let transition = ContainedViewLayoutTransition.animated(duration: 0.21, curve: .easeInOut)
|
||||||
transition.updateAlpha(node: self.titleNode, alpha: self.segmentsHidden ? 1.0 : 0.0)
|
transition.updateAlpha(node: self.titleNode, alpha: self.segmentsHidden ? 1.0 : 0.0)
|
||||||
|
transition.updateAlpha(node: self.arrowNode, alpha: self.segmentsHidden ? 1.0 : 0.0)
|
||||||
transition.updateAlpha(node: self.segmentedControlNode, alpha: self.segmentsHidden ? 0.0 : 1.0)
|
transition.updateAlpha(node: self.segmentedControlNode, alpha: self.segmentsHidden ? 0.0 : 1.0)
|
||||||
self.segmentedControlNode.isUserInteractionEnabled = !self.segmentsHidden
|
self.segmentedControlNode.isUserInteractionEnabled = !self.segmentsHidden
|
||||||
}
|
}
|
||||||
|
@ -2577,6 +2577,8 @@ public class CameraScreen: ViewController {
|
|||||||
self.node.hasGallery = false
|
self.node.hasGallery = false
|
||||||
self.node.requestUpdateLayout(hasAppeared: self.node.hasAppeared, transition: .immediate)
|
self.node.requestUpdateLayout(hasAppeared: self.node.hasAppeared, transition: .immediate)
|
||||||
}
|
}
|
||||||
|
}, groupsPresented: {
|
||||||
|
stopCameraCapture()
|
||||||
})
|
})
|
||||||
self.galleryController = controller
|
self.galleryController = controller
|
||||||
}
|
}
|
||||||
|
@ -2068,6 +2068,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
self.isInteractingWithEntities = isInteracting
|
self.isInteractingWithEntities = isInteracting
|
||||||
if !isInteracting {
|
if !isInteracting {
|
||||||
self.controller?.isSavingAvailable = true
|
self.controller?.isSavingAvailable = true
|
||||||
|
self.hasAnyChanges = true
|
||||||
}
|
}
|
||||||
self.requestUpdate(transition: .easeInOut(duration: 0.2))
|
self.requestUpdate(transition: .easeInOut(duration: 0.2))
|
||||||
}
|
}
|
||||||
|
@ -1869,8 +1869,8 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
return mediaPickerController(context: context, hasSearch: hasSearch, completion: completion)
|
return mediaPickerController(context: context, hasSearch: hasSearch, completion: completion)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func makeStoryMediaPickerScreen(context: AccountContext, getSourceRect: @escaping () -> CGRect, completion: @escaping (Any, UIView, CGRect, UIImage?, @escaping (Bool?) -> (UIView, CGRect)?, @escaping () -> Void) -> Void, dismissed: @escaping () -> Void) -> ViewController {
|
public func makeStoryMediaPickerScreen(context: AccountContext, getSourceRect: @escaping () -> CGRect, completion: @escaping (Any, UIView, CGRect, UIImage?, @escaping (Bool?) -> (UIView, CGRect)?, @escaping () -> Void) -> Void, dismissed: @escaping () -> Void, groupsPresented: @escaping () -> Void) -> ViewController {
|
||||||
return storyMediaPickerController(context: context, getSourceRect: getSourceRect, completion: completion, dismissed: dismissed)
|
return storyMediaPickerController(context: context, getSourceRect: getSourceRect, completion: completion, dismissed: dismissed, groupsPresented: groupsPresented)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func makeProxySettingsController(sharedContext: SharedAccountContext, account: UnauthorizedAccount) -> ViewController {
|
public func makeProxySettingsController(sharedContext: SharedAccountContext, account: UnauthorizedAccount) -> ViewController {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user