Merge branch 'release/20_0_0' into 'develop'
release/20_0_0 hotfix merge Co-authored-by: Hedden, Kyle Matthew <kyle.hedden@verizonwireless.com> Co-authored-by: Matt Bruce <matt.bruce@verizon.com> Co-authored-by: Subramaniam, Ramya <ramya.subramaniam@one.verizon.com> Co-authored-by: Bruce, Matt R <matt.bruce@one.verizon.com> See merge request https://gitlab.verizon.com/BPHV_MIPS/mvm_core_ui/-/merge_requests/1128
This commit is contained in:
commit
eb78d507d6
@ -364,8 +364,8 @@ extension Label {
|
|||||||
public static func boundingRect(forCharacterRange range: NSRange, in label: Label) -> CGRect {
|
public static func boundingRect(forCharacterRange range: NSRange, in label: Label) -> CGRect {
|
||||||
|
|
||||||
guard let abstractContainer = label.abstractTextContainer() else { return CGRect() }
|
guard let abstractContainer = label.abstractTextContainer() else { return CGRect() }
|
||||||
let textContainer = abstractContainer.0
|
let textContainer = abstractContainer.textContainer
|
||||||
let layoutManager = abstractContainer.1
|
let layoutManager = abstractContainer.layoutManager
|
||||||
|
|
||||||
var glyphRange = NSRange()
|
var glyphRange = NSRange()
|
||||||
|
|
||||||
@ -374,36 +374,6 @@ extension Label {
|
|||||||
|
|
||||||
return layoutManager.boundingRect(forGlyphRange: glyphRange, in: textContainer)
|
return layoutManager.boundingRect(forGlyphRange: glyphRange, in: textContainer)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
Provides a text container and layout manager of how the text would appear on screen.
|
|
||||||
They are used in tandem to derive low-level TextKit results of the label.
|
|
||||||
*/
|
|
||||||
public func abstractTextContainer() -> (NSTextContainer, NSLayoutManager, NSTextStorage)? {
|
|
||||||
|
|
||||||
// Must configure the attributed string to translate what would appear on screen to accurately analyze.
|
|
||||||
guard let attributedText = attributedText else { return nil }
|
|
||||||
|
|
||||||
let paragraph = NSMutableParagraphStyle()
|
|
||||||
paragraph.alignment = textAlignment
|
|
||||||
|
|
||||||
let stagedAttributedString = NSMutableAttributedString(attributedString: attributedText)
|
|
||||||
stagedAttributedString.addAttributes([NSAttributedString.Key.paragraphStyle: paragraph], range: NSRange(location: 0, length: attributedText.string.count))
|
|
||||||
|
|
||||||
let textStorage = NSTextStorage(attributedString: stagedAttributedString)
|
|
||||||
let layoutManager = NSLayoutManager()
|
|
||||||
let textContainer = NSTextContainer(size: .zero)
|
|
||||||
|
|
||||||
layoutManager.addTextContainer(textContainer)
|
|
||||||
textStorage.addLayoutManager(layoutManager)
|
|
||||||
|
|
||||||
textContainer.lineFragmentPadding = 0.0
|
|
||||||
textContainer.lineBreakMode = lineBreakMode
|
|
||||||
textContainer.maximumNumberOfLines = numberOfLines
|
|
||||||
textContainer.size = bounds.size
|
|
||||||
|
|
||||||
return (textContainer, layoutManager, textStorage)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Atomization
|
// MARK: - Atomization
|
||||||
|
|||||||
@ -307,6 +307,7 @@ open class Carousel: View {
|
|||||||
|
|
||||||
pagingView?.removeFromSuperview()
|
pagingView?.removeFromSuperview()
|
||||||
bottomPin?.isActive = false
|
bottomPin?.isActive = false
|
||||||
|
pagingView = nil
|
||||||
|
|
||||||
guard var pagingView = view else {
|
guard var pagingView = view else {
|
||||||
bottomPin = bottomAnchor.constraint(equalTo: collectionView.bottomAnchor)
|
bottomPin = bottomAnchor.constraint(equalTo: collectionView.bottomAnchor)
|
||||||
|
|||||||
@ -83,6 +83,9 @@ import Foundation
|
|||||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
if let defaultPageType = Self.defaultPageType() {
|
if let defaultPageType = Self.defaultPageType() {
|
||||||
pageType = try typeContainer.decodeIfPresent(String.self, forKey: .pageType) ?? defaultPageType
|
pageType = try typeContainer.decodeIfPresent(String.self, forKey: .pageType) ?? defaultPageType
|
||||||
|
if pageType.isEmpty {
|
||||||
|
pageType = defaultPageType
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
pageType = try typeContainer.decode(String.self, forKey: .pageType)
|
pageType = try typeContainer.decode(String.self, forKey: .pageType)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -52,18 +52,20 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController, Rotor
|
|||||||
bottomView.updateView(width)
|
bottomView.updateView(width)
|
||||||
showFooter(width)
|
showFooter(width)
|
||||||
}
|
}
|
||||||
tableView.reloadData()
|
tableView.visibleCells.forEach { cell in
|
||||||
|
(cell as? MVMCoreViewProtocol)?.updateView(width)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open override func updateUI(for molecules: [MoleculeModelProtocol]? = nil) {
|
open override func updateUI(for molecules: [MoleculeModelProtocol]? = nil) {
|
||||||
let isFirstRender = self.isFirstRender
|
|
||||||
super.updateUI(for: molecules)
|
super.updateUI(for: molecules)
|
||||||
|
|
||||||
guard molecules == nil else { return }
|
guard molecules == nil else { return }
|
||||||
|
|
||||||
createViewForTableHeader()
|
createViewForTableHeader()
|
||||||
createViewForTableFooter()
|
createViewForTableFooter()
|
||||||
// Reloading the table is handled in updateViews.
|
// Reloading the table is handled in updateViews, however, update views is on a separate rendering task than the current thread. The table render needs to be bound and settled to the new model before others put in additional update requests.
|
||||||
|
tableView.reloadData()
|
||||||
}
|
}
|
||||||
|
|
||||||
override open func viewDidLoad() {
|
override open func viewDidLoad() {
|
||||||
|
|||||||
@ -20,7 +20,7 @@ public class ReplaceableMoleculeBehaviorModel: PageBehaviorModelProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ReplaceableMoleculeBehavior: PageMoleculeTransformationBehavior, CoreLogging {
|
public class ReplaceableMoleculeBehavior: PageMoleculeTransformationBehavior, PageVisibilityBehavior, CoreLogging {
|
||||||
|
|
||||||
public var loggingPrefix: String {
|
public var loggingPrefix: String {
|
||||||
"\(self) \(ObjectIdentifier(self).hashValue) \(moleculeIds.prefix(3)) \(moleculeIds.count > 3 ? "+ \(moleculeIds.count - 3) more" : ""):\n"
|
"\(self) \(ObjectIdentifier(self).hashValue) \(moleculeIds.prefix(3)) \(moleculeIds.count > 3 ? "+ \(moleculeIds.count - 3) more" : ""):\n"
|
||||||
@ -30,6 +30,8 @@ public class ReplaceableMoleculeBehavior: PageMoleculeTransformationBehavior, Co
|
|||||||
String(describing: Self.self)
|
String(describing: Self.self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isPageShowing = false
|
||||||
|
var previouslyReplacedIds = Set<String>()
|
||||||
var moleculeIds: [String]
|
var moleculeIds: [String]
|
||||||
public var modulesToListenFor: [String]
|
public var modulesToListenFor: [String]
|
||||||
private var observingForResponses: NSObjectProtocol?
|
private var observingForResponses: NSObjectProtocol?
|
||||||
@ -75,7 +77,7 @@ public class ReplaceableMoleculeBehavior: PageMoleculeTransformationBehavior, Co
|
|||||||
return rootMolecule
|
return rootMolecule
|
||||||
}
|
}
|
||||||
debugLog("top replacing \(rootMolecule) with \(updatedMolecule)")
|
debugLog("top replacing \(rootMolecule) with \(updatedMolecule)")
|
||||||
logUpdated(molecule: updatedMolecule)
|
logUpdated(moleculeId: updatedMolecule.id)
|
||||||
changeList.append(updatedMolecule)
|
changeList.append(updatedMolecule)
|
||||||
return updatedMolecule
|
return updatedMolecule
|
||||||
}
|
}
|
||||||
@ -92,7 +94,7 @@ public class ReplaceableMoleculeBehavior: PageMoleculeTransformationBehavior, Co
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
debugLog("deep replacing \(replacedMolecule) with \(newMolecule)")
|
debugLog("deep replacing \(replacedMolecule) with \(newMolecule)")
|
||||||
logUpdated(molecule: newMolecule)
|
logUpdated(moleculeId: newMolecule.id)
|
||||||
changeList.append(newMolecule)
|
changeList.append(newMolecule)
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
@ -111,15 +113,29 @@ public class ReplaceableMoleculeBehavior: PageMoleculeTransformationBehavior, Co
|
|||||||
return hasReplacement ? updatedRootMolecules : nil
|
return hasReplacement ? updatedRootMolecules : nil
|
||||||
}
|
}
|
||||||
|
|
||||||
private func logUpdated(molecule: MoleculeModelProtocol) {
|
private func logUpdated(moleculeId: String) {
|
||||||
guard let module: [AnyHashable: Any] = delegateObject?.moleculeDelegate?.getModuleWithName(molecule.id),
|
guard let module: [AnyHashable: Any] = delegateObject?.moleculeDelegate?.getModuleWithName(moleculeId),
|
||||||
let viewController = delegateObject?.moleculeDelegate as? MVMCoreViewControllerProtocol else {
|
let viewController = delegateObject?.moleculeDelegate as? MVMCoreViewControllerProtocol else {
|
||||||
debugLog("Missing the originating module \(molecule.id) creating this molecule!")
|
debugLog("Missing the originating module \(moleculeId) creating this molecule!")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
previouslyReplacedIds.insert(moleculeId)
|
||||||
|
guard isPageShowing else { return } // Page has not been made visible yet. (Pulled and replaced from cache on load or background update.) Hold reporting until onPageShown.
|
||||||
MVMCoreUILoggingHandler.shared()?.defaultLogPageUpdate(forController: viewController, from: module)
|
MVMCoreUILoggingHandler.shared()?.defaultLogPageUpdate(forController: viewController, from: module)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func onPageShown(_ delegateObject: MVMCoreUIDelegateObject?) {
|
||||||
|
isPageShowing = true
|
||||||
|
debugLog("Page shown. Send molecule analytics for: \(previouslyReplacedIds)")
|
||||||
|
previouslyReplacedIds.forEach { id in
|
||||||
|
logUpdated(moleculeId: id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func onPageHidden(_ delegateObject: MVMCoreUIDelegateObject?) {
|
||||||
|
isPageShowing = false
|
||||||
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
debugLog("deinit")
|
debugLog("deinit")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,6 +22,9 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
// The bundle for this framework
|
// The bundle for this framework
|
||||||
+ (nullable NSBundle *)bundleForMVMCoreUI;
|
+ (nullable NSBundle *)bundleForMVMCoreUI;
|
||||||
|
|
||||||
|
/// The bundle for the VDS frameowrk. Handy for accessing VDS resources such as fonts.
|
||||||
|
+ (nullable NSBundle *)bundleForFonts;
|
||||||
|
|
||||||
// Returns the hardcoded string from the string file.
|
// Returns the hardcoded string from the string file.
|
||||||
+ (nullable NSString *)hardcodedStringWithKey:(nonnull NSString *)key;
|
+ (nullable NSString *)hardcodedStringWithKey:(nonnull NSString *)key;
|
||||||
|
|
||||||
|
|||||||
@ -22,6 +22,10 @@
|
|||||||
return [NSBundle bundleWithIdentifier:@"com.vzw.MVMCoreUI"];
|
return [NSBundle bundleWithIdentifier:@"com.vzw.MVMCoreUI"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (nullable NSBundle *)bundleForFonts {
|
||||||
|
return [NSBundle bundleWithIdentifier:@"com.vzw.vds"];
|
||||||
|
}
|
||||||
|
|
||||||
+ (nullable NSString *)hardcodedStringWithKey:(nonnull NSString *)key {
|
+ (nullable NSString *)hardcodedStringWithKey:(nonnull NSString *)key {
|
||||||
// Redirect key with relevant module.
|
// Redirect key with relevant module.
|
||||||
return [MVMCoreGetterUtility hardcodedStringWithKey:key bundle:[MVMCoreUIUtility bundleForMVMCoreUI]];
|
return [MVMCoreGetterUtility hardcodedStringWithKey:key bundle:[MVMCoreUIUtility bundleForMVMCoreUI]];
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user