mirror of
https://github.com/lux-tel/session-ios.git
synced 2026-10-30 20:38:32 +00:00
266 lines
12 KiB
Swift
266 lines
12 KiB
Swift
// Copyright © 2023 Rangeproof Pty Ltd. All rights reserved.
|
|
|
|
import UIKit
|
|
import SessionUIKit
|
|
import SessionUtilitiesKit
|
|
|
|
public extension ProfilePictureView {
|
|
func update(
|
|
publicKey: String,
|
|
threadVariant: SessionThread.Variant,
|
|
displayPictureUrl: String?,
|
|
profile: Profile?,
|
|
profileIcon: Info.ProfileIcon = .none,
|
|
additionalProfile: Profile? = nil,
|
|
additionalProfileIcon: Info.ProfileIcon = .none,
|
|
using dependencies: Dependencies
|
|
) {
|
|
let (info, additionalInfo): (front: Info?, back: Info?) = Info.generateInfoFrom(
|
|
size: self.size,
|
|
publicKey: publicKey,
|
|
threadVariant: threadVariant,
|
|
displayPictureUrl: displayPictureUrl,
|
|
profile: profile,
|
|
profileIcon: profileIcon,
|
|
additionalProfile: additionalProfile,
|
|
additionalProfileIcon: additionalProfileIcon,
|
|
using: dependencies
|
|
)
|
|
|
|
guard let info: Info = info else { return }
|
|
|
|
update(info, additionalInfo: additionalInfo)
|
|
}
|
|
}
|
|
|
|
public extension ProfilePictureView.Info {
|
|
static func generateInfoFrom(
|
|
size: Size,
|
|
publicKey: String,
|
|
threadVariant: SessionThread.Variant,
|
|
displayPictureUrl: String?,
|
|
profile: Profile?,
|
|
profileIcon: ProfileIcon = .none,
|
|
additionalProfile: Profile? = nil,
|
|
additionalProfileIcon: ProfileIcon = .none,
|
|
using dependencies: Dependencies
|
|
) -> (front: ProfilePictureView.Info?, back: ProfilePictureView.Info?) {
|
|
let explicitPath: String? = try? dependencies[singleton: .displayPictureManager].path(
|
|
for: displayPictureUrl
|
|
)
|
|
let explicitPathFileExists: Bool = (explicitPath.map { dependencies[singleton: .fileManager].fileExists(atPath: $0) } ?? false)
|
|
|
|
switch (explicitPath, explicitPathFileExists, publicKey.isEmpty, threadVariant) {
|
|
// TODO: Deal with this case later when implement group related Pro features
|
|
case (.some(let path), true, _, .legacyGroup), (.some(let path), true, _, .group): fallthrough
|
|
case (.some(let path), true, _, .community):
|
|
/// If we are given an explicit `displayPictureUrl` then only use that
|
|
return (ProfilePictureView.Info(
|
|
source: .url(URL(fileURLWithPath: path)),
|
|
canAnimate: true,
|
|
icon: profileIcon
|
|
), nil)
|
|
|
|
case (.some(let path), true, _, _):
|
|
/// If we are given an explicit `displayPictureUrl` then only use that
|
|
return (
|
|
ProfilePictureView.Info(
|
|
source: .url(URL(fileURLWithPath: path)),
|
|
canAnimate: ProfilePictureView.canProfileAnimate(profile, using: dependencies),
|
|
icon: profileIcon
|
|
),
|
|
nil
|
|
)
|
|
|
|
case (_, _, _, .community):
|
|
return (
|
|
ProfilePictureView.Info(
|
|
source: {
|
|
switch size {
|
|
case .navigation, .message: return .image("SessionWhite16", #imageLiteral(resourceName: "SessionWhite16"))
|
|
case .list: return .image("SessionWhite24", #imageLiteral(resourceName: "SessionWhite24"))
|
|
case .hero, .modal, .expanded: return .image("SessionWhite40", #imageLiteral(resourceName: "SessionWhite40"))
|
|
}
|
|
}(),
|
|
canAnimate: true,
|
|
inset: {
|
|
let padding: CGFloat
|
|
|
|
switch size {
|
|
case .navigation, .message: padding = 7
|
|
case .list: padding = 12
|
|
case .hero: padding = 28
|
|
case .modal: padding = 24
|
|
case .expanded: padding = 50
|
|
}
|
|
|
|
return UIEdgeInsets(
|
|
top: padding,
|
|
left: padding,
|
|
bottom: padding,
|
|
right: padding
|
|
)
|
|
}(),
|
|
icon: profileIcon,
|
|
forcedBackgroundColor: .theme(.classicDark, color: .borderSeparator)
|
|
),
|
|
nil
|
|
)
|
|
|
|
case (_, _, true, _): return (nil, nil)
|
|
|
|
case (_, _, _, .legacyGroup), (_, _, _, .group):
|
|
let source: ImageDataManager.DataSource = {
|
|
guard
|
|
let path: String = try? dependencies[singleton: .displayPictureManager]
|
|
.path(for: profile?.displayPictureUrl),
|
|
dependencies[singleton: .fileManager].fileExists(atPath: path)
|
|
else {
|
|
return .placeholderIcon(
|
|
seed: (profile?.id ?? publicKey),
|
|
text: (profile?.displayName(for: threadVariant))
|
|
.defaulting(to: publicKey),
|
|
size: (additionalProfile != nil ?
|
|
size.multiImageSize :
|
|
size.viewSize
|
|
)
|
|
)
|
|
}
|
|
|
|
return ImageDataManager.DataSource.url(URL(fileURLWithPath: path))
|
|
}()
|
|
|
|
return (
|
|
ProfilePictureView.Info(
|
|
source: source,
|
|
canAnimate: ProfilePictureView.canProfileAnimate(profile, using: dependencies),
|
|
icon: profileIcon
|
|
),
|
|
additionalProfile
|
|
.map { other in
|
|
let source: ImageDataManager.DataSource = {
|
|
guard
|
|
let path: String = try? dependencies[singleton: .displayPictureManager]
|
|
.path(for: other.displayPictureUrl),
|
|
dependencies[singleton: .fileManager].fileExists(atPath: path)
|
|
else {
|
|
return .placeholderIcon(
|
|
seed: other.id,
|
|
text: other.displayName(for: threadVariant),
|
|
size: size.multiImageSize
|
|
)
|
|
}
|
|
|
|
return ImageDataManager.DataSource.url(URL(fileURLWithPath: path))
|
|
}()
|
|
|
|
return ProfilePictureView.Info(
|
|
source: source,
|
|
canAnimate: ProfilePictureView.canProfileAnimate(other, using: dependencies),
|
|
icon: additionalProfileIcon
|
|
)
|
|
}
|
|
.defaulting(
|
|
to: ProfilePictureView.Info(
|
|
source: .image("ic_user_round_fill", UIImage(named: "ic_user_round_fill")),
|
|
canAnimate: false,
|
|
renderingMode: .alwaysTemplate,
|
|
themeTintColor: .white,
|
|
inset: UIEdgeInsets(
|
|
top: 4,
|
|
left: 4,
|
|
bottom: -6,
|
|
right: 4
|
|
),
|
|
icon: additionalProfileIcon
|
|
)
|
|
)
|
|
)
|
|
|
|
case (_, _, _, .contact):
|
|
let source: ImageDataManager.DataSource = {
|
|
guard
|
|
let path: String = try? dependencies[singleton: .displayPictureManager]
|
|
.path(for: profile?.displayPictureUrl),
|
|
dependencies[singleton: .fileManager].fileExists(atPath: path)
|
|
else {
|
|
return .placeholderIcon(
|
|
seed: publicKey,
|
|
text: (profile?.displayName(for: threadVariant))
|
|
.defaulting(to: publicKey),
|
|
size: size.viewSize
|
|
)
|
|
}
|
|
|
|
return ImageDataManager.DataSource.url(URL(fileURLWithPath: path))
|
|
}()
|
|
|
|
return (
|
|
ProfilePictureView.Info(
|
|
source: source,
|
|
canAnimate: ProfilePictureView.canProfileAnimate(profile, using: dependencies),
|
|
icon: profileIcon),
|
|
nil
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
public extension ProfilePictureView {
|
|
// TODO: [PRO] Need to properly wire this up (it won't observe the changes, the parent screen will be responsible for updating the profile data and reloading the UI if the pro state changes)
|
|
static func canProfileAnimate(_ profile: Profile?, using dependencies: Dependencies) -> Bool {
|
|
guard dependencies[feature: .sessionProEnabled] else { return true }
|
|
|
|
switch profile {
|
|
case .none: return false
|
|
|
|
case .some(let profile) where profile.id == dependencies[cache: .general].sessionId.hexString:
|
|
if case .active = dependencies[singleton: .sessionProState].sessionProStateSubject.value {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
|
|
case .some(let profile):
|
|
return dependencies.mutate(cache: .libSession, { $0.validateProProof(for: profile) })
|
|
}
|
|
}
|
|
}
|
|
|
|
public extension ProfilePictureSwiftUI {
|
|
init?(
|
|
size: ProfilePictureView.Info.Size,
|
|
publicKey: String,
|
|
threadVariant: SessionThread.Variant,
|
|
displayPictureUrl: String?,
|
|
profile: Profile?,
|
|
profileIcon: ProfilePictureView.Info.ProfileIcon = .none,
|
|
additionalProfile: Profile? = nil,
|
|
additionalProfileIcon: ProfilePictureView.Info.ProfileIcon = .none,
|
|
using dependencies: Dependencies
|
|
) {
|
|
let (info, additionalInfo) = ProfilePictureView.Info.generateInfoFrom(
|
|
size: size,
|
|
publicKey: publicKey,
|
|
threadVariant: threadVariant,
|
|
displayPictureUrl: displayPictureUrl,
|
|
profile: profile,
|
|
profileIcon: profileIcon,
|
|
additionalProfile: additionalProfile,
|
|
additionalProfileIcon: additionalProfileIcon,
|
|
using: dependencies
|
|
)
|
|
|
|
switch info {
|
|
case .none: return nil
|
|
case .some(let info):
|
|
self.init(
|
|
size: size,
|
|
info: info,
|
|
additionalInfo: additionalInfo,
|
|
dataManager: dependencies[singleton: .imageDataManager]
|
|
)
|
|
}
|
|
}
|
|
}
|