mirror of
https://github.com/lux-tel/session-ios.git
synced 2026-10-30 20:38:32 +00:00
# Conflicts: # Session/Conversations/ConversationVC+Interaction.swift # Session/Conversations/ConversationVC.swift # Session/Conversations/Settings/ThreadSettingsViewModel.swift # Session/Home/GlobalSearch/GlobalSearchViewController.swift # Session/Meta/AppDelegate.swift # SessionMessagingKit/Open Groups/OpenGroupManager.swift # SessionMessagingKit/Sending & Receiving/MessageReceiver.swift # SessionMessagingKit/Utilities/MessageWrapper.swift
263 lines
11 KiB
Swift
263 lines
11 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: [PRO] 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() ?? 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(),
|
|
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() ?? 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 {
|
|
/// This will made a decision based on the current state of the profile data, it's up to the parent screen to observer changes and trigger
|
|
/// a UI refresh to update this state
|
|
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:
|
|
return dependencies[singleton: .sessionProManager].currentUserIsCurrentlyPro
|
|
|
|
case .some(let profile):
|
|
return dependencies[singleton: .sessionProManager]
|
|
.profileFeatures(for: profile)
|
|
.contains(.animatedAvatar)
|
|
}
|
|
}
|
|
}
|
|
|
|
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]
|
|
)
|
|
}
|
|
}
|
|
}
|