// /* * Copyright (c) 2023 BWI GmbH * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import SwiftUI import UIKit protocol FeatureBannerDelegate { func didPressClose() func didPressShowDetails() } @objcMembers class FeatureBannerViewCell: UITableViewCell, FeatureBannerDelegate { private var parentViewController: UIViewController? private let hostingController = UIHostingController(rootView: nil) private var webViewController: WebViewViewController? private var username: String = "" override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) hostingController.view.backgroundColor = UIColor.clear } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } public func setupView(parent: UIViewController, rootView: Content) { self.parentViewController = parent hostingController.rootView = rootView let shouldControllerMove = hostingController.parent != parent if shouldControllerMove { removeController() parent.addChild(hostingController) } if !self.contentView.subviews.contains(hostingController.view) { self.contentView.addSubview(hostingController.view) self.contentView.vc_addSubViewMatchingParentSafeArea(hostingController.view) } if shouldControllerMove { hostingController.didMove(toParent: parent) } } func calculateHeight() -> CGFloat { hostingController.view.setNeedsLayout() hostingController.view.layoutIfNeeded() let result = hostingController.view.intrinsicContentSize.height return result } private func removeController() { hostingController.willMove(toParent: nil) hostingController.view.removeFromSuperview() hostingController.removeFromParent() parentViewController = nil } deinit { removeController() } // MARK: user interaction func hideTopBanner() { removeController() NotificationCenter.default.post(name: .bwiHideTopBanner, object: self, userInfo: ["type" : "feature_banner"]) } func didPressClose() { hideTopBanner() } func didPressShowDetails() { let migrationInfoView = MigrationInfoView(username: username, getUserName: nil).environmentObject(BWIThemeService.shared).interactiveDismissDisabled(true) let hostingViewController = UIHostingController(rootView: migrationInfoView) if hostingViewController.popoverPresentationController != nil { hostingViewController.modalPresentationStyle = .popover } hostingViewController.isModalInPresentation = true hostingController.parent?.present(hostingViewController, animated: true, completion: nil) } @objc func closeModal() { webViewController?.dismiss(animated: true) } func setUsername(username: String) { self.username = username } } struct FeatureBannerView: View { var delegate: FeatureBannerDelegate? let darkmodeBackground = UIColor(rgb:0x2394A7) let warningColor = UIColor(rgb:0xD51928) var backgroundColor: Color { if BWIBuildSettings.shared.BuMXMigrationInfoLevel >= 2 { ThemeService.shared().isCurrentThemeDark() ? Color(uiColor: warningColor) : Color(ThemeService.shared().theme.warningColor) } else { ThemeService.shared().isCurrentThemeDark() ? Color(uiColor: darkmodeBackground) : Color(ThemeService.shared().theme.tintColor) } } var body: some View { VStack(alignment: .center) { header advertisementText HStack(alignment: .center, spacing: 12) { remindMeLaterButton showMoreButton } } .padding(.horizontal, 12) .background(backgroundColor) .cornerRadius(12) .padding(16) } var header: some View { HStack() { Image(Asset.Images.newFeatures.name) // .renderingMode(.template) .foregroundColor(Color(ThemeService.shared().theme.backgroundColor)) .accessibilityHidden(true) Text(BWIL10n.bwiMobileDialogMBannerTitle) .font(.system(size: 20).bold()) .foregroundColor(Color(ThemeService.shared().theme.backgroundColor)) Spacer() } .padding(.top, 16) } var advertisementText: some View { VStack { VStack { if BWIBuildSettings.shared.isManagedViaMDM { Text(BWIL10n.bwiMobileDialogMdmBannerTextPrefix) + Text(BWIL10n.bwiMobileDialogMdmBannerTextBold) .bold() } else if BWIBuildSettings.shared.BuMXMigrationInfoLevel == 1 { Text(BWIL10n.bwiMobileDialogM1BannerTextPrefix) + Text(BWIL10n.bwiMobileDialogM1BannerTextBold) .bold() } else { Text(BWIL10n.bwiMobileDialogM2BannerTextPrefix) + Text(BWIL10n.bwiMobileDialogM2BannerTextBold) .bold() + Text(BWIL10n.bwiMobileDialogM2BannerTextSuffix) } } } .font(.system(size: 15)) .multilineTextAlignment(.leading) .lineLimit(nil) .fixedSize(horizontal: false, vertical: true) .foregroundColor(Color(ThemeService.shared().theme.backgroundColor)) } var closeButton: some View { HStack() { Spacer() Button { delegate?.didPressClose() } label: { Image(Asset.Images.closeButton.name) .renderingMode(.template) .foregroundColor(Color(ThemeService.shared().theme.backgroundColor)) .padding(10) } } } var showMoreButton: some View { Button { delegate?.didPressShowDetails() } label: { HStack() { Spacer() Text(BWIL10n.bwiMobileDialogMBannerButton2) .font(.system(size: 18)) .bold() .padding(10) .foregroundColor(ThemeService.shared().isCurrentThemeDark() ? Color(uiColor: darkmodeBackground) : Color.black) Spacer() } } .background(Color(ThemeService.shared().theme.backgroundColor)) .cornerRadius(12) .padding(.top, 10) .padding(.bottom, 25) } var remindMeLaterButton: some View { Button { delegate?.didPressClose() } label: { HStack() { Spacer() Text(BWIL10n.bwiMobileDialogMBannerButton1) .font(.system(size: 18)) .padding(10) .foregroundColor(Color(ThemeService.shared().theme.backgroundColor)) Spacer() } } .overlay(RoundedRectangle(cornerRadius: 12) .stroke(Color(ThemeService.shared().theme.backgroundColor), lineWidth: 2)) .padding(.top, 10) .padding(.bottom, 25) } }