feat: layout changes and copy to clipboard (MESSENGER-7564)

This commit is contained in:
Jan Niklas Grabowski
2025-09-18 18:10:53 +02:00
parent bed94efd52
commit 4d9a8a4d85
9 changed files with 182 additions and 74 deletions

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 2.8 MiB

View File

@@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "Bild_Dialog_1.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}

View File

@@ -773,3 +773,5 @@
"bwi_mobile_dialog_m_more2_text_3" = "Mit deinen Anmeldedaten einloggen";
"bwi_mobile_dialog_m_more_button" = "Neue App herunterladen";
"bwi_mobile_dialog_m_more_success" = "Benutzername kopiert";
"bwi_a11y_close_button" = "Ansicht schließen";

View File

@@ -685,3 +685,6 @@
"bwi_mobile_dialog_m_more2_text_3" = "Log in with your credentials";
"bwi_mobile_dialog_m_more_button" = "Download new app";
"bwi_mobile_dialog_m_more_success" = "user name copied";
"bwi_a11y_close_button" = "Close window";

View File

@@ -131,6 +131,10 @@ public class BWIL10n: NSObject {
public static var bumAutheticationTitle: String {
return BWIL10n.tr("Bwi", "bum_authetication_title")
}
/// Ansicht schließen
public static var bwiA11yCloseButton: String {
return BWIL10n.tr("Bwi", "bwi_a11y_close_button")
}
/// Barrierefreiheitserklärung
public static var bwiAccessibilityDeclarationButtonTitle: String {
return BWIL10n.tr("Bwi", "bwi_accessibility_declaration_button_title")

View File

@@ -63,6 +63,7 @@ internal class Asset: NSObject {
internal static let introduceFederation2Light = ImageAsset(name: "introduce_federation_2_light")
internal static let introduceFederation3 = ImageAsset(name: "introduce_federation_3")
internal static let mediaFileUnavailable = ImageAsset(name: "media_file_unavailable")
internal static let migrationDetail1 = ImageAsset(name: "migration_detail_1")
internal static let newFeatures = ImageAsset(name: "new_features")
internal static let qr = ImageAsset(name: "qr")
internal static let qrcodeViewfinder = ImageAsset(name: "qrcode_viewfinder")

View File

@@ -621,10 +621,15 @@ class AllChatsViewController: HomeViewController {
}
// bwi: feature banner cell
if sectionType == .featureBanner {
var username = ""
if let mainSession = self.mainSession {
username = mainSession.myUser.displayname
}
guard let cell = tableView.dequeueReusableCell(withIdentifier: "featureBanner", for: indexPath) as? FeatureBannerViewCell<FeatureBannerView> else {
return UITableViewCell()
}
cell.selectionStyle = .none
cell.setUsername(username: username)
cell.setupView(parent: self, rootView: FeatureBannerView(delegate: cell))
featureBannerViewHeight = cell.calculateHeight()
return cell

View File

@@ -28,6 +28,7 @@ protocol FeatureBannerDelegate {
private var parentViewController: UIViewController?
private let hostingController = UIHostingController<Content?>(rootView: nil)
private var webViewController: WebViewViewController?
private var username: String = ""
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
@@ -90,20 +91,27 @@ protocol FeatureBannerDelegate {
}
func didPressShowDetails() {
let migrationInfoView = MigrationInfoView().interactiveDismissDisabled(true)
let migrationInfoView = MigrationInfoView(username: username).interactiveDismissDisabled(true)
let hostingViewController = UIHostingController(rootView: migrationInfoView)
hostingViewController.modalPresentationStyle = .popover
if hostingViewController.popoverPresentationController != nil {
hostingViewController.modalPresentationStyle = .popover
}
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)
var body: some View {
VStack(alignment: .center) {
@@ -116,7 +124,7 @@ struct FeatureBannerView: View {
}
}
.padding(.horizontal, 12)
.background(Color(ThemeService.shared().theme.tintColor))
.background(ThemeService.shared().isCurrentThemeDark() ? Color(uiColor: darkmodeBackground) : Color(ThemeService.shared().theme.tintColor))
.cornerRadius(12)
.padding(16)
}
@@ -126,6 +134,7 @@ struct FeatureBannerView: View {
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))
@@ -171,7 +180,7 @@ struct FeatureBannerView: View {
.font(.system(size: 18))
.bold()
.padding(10)
.foregroundColor(ThemeService.shared().isCurrentThemeDark() ? Color(ThemeService.shared().theme.tintColor) : Color.black)
.foregroundColor(ThemeService.shared().isCurrentThemeDark() ? Color(uiColor: darkmodeBackground) : Color.black)
Spacer()
}
}

View File

@@ -22,16 +22,18 @@ struct MigrationInfoView: View {
@Environment(\.dismiss) var dismissView
@State private var selectedTab = 1
let username: String
var body: some View {
TabView(selection: $selectedTab) {
MigrationInfoViewOne()
.tag(1)
MigrationInfoViewTwo()
MigrationInfoViewTwo(username: username)
.tag(2)
}
.tabViewStyle(.page)
.indexViewStyle(.page(backgroundDisplayMode: .always))
//.background(Color.white.ignoresSafeArea())
.background(Color.white.ignoresSafeArea())
.onAppear() {
FeatureBannerVisibilityService().markAsRead()
NotificationCenter.default.post(name: .bwiMarkTopBannerAsRead, object: self, userInfo: ["type" : "feature_banner"])
@@ -50,6 +52,7 @@ struct MigrationInfoView: View {
.foregroundColor(Color(ThemeService.shared().theme.tintColor))
.padding(20)
}
.accessibilityLabel(BWIL10n.bwiA11yCloseButton)
}
Spacer()
HStack() {
@@ -62,8 +65,8 @@ struct MigrationInfoView: View {
.resizable()
.frame(width: 24, height: 24)
.foregroundStyle(Color(ThemeService.shared().theme.tintColor))
.padding(EdgeInsets(top: 20, leading: 30, bottom: 10, trailing: 30))
}
.padding(EdgeInsets(top: 20, leading: 30, bottom: 10, trailing: 30))
.opacity(selectedTab == 1 ? 0 : 1)
Spacer()
@@ -77,8 +80,8 @@ struct MigrationInfoView: View {
.resizable()
.frame(width: 24, height: 24)
.foregroundStyle(Color(ThemeService.shared().theme.tintColor))
.padding(EdgeInsets(top: 20, leading: 30, bottom: 10, trailing: 30))
}
.padding(EdgeInsets(top: 20, leading: 30, bottom: 10, trailing: 30))
.opacity(selectedTab == 2 ? 0 : 1)
}
}
@@ -92,43 +95,44 @@ struct MigrationInfoViewOne: View {
var body: some View {
GeometryReader { geo in
ScrollView(.vertical) {
VStack(alignment: .center, spacing: 30) {
Spacer()
header
VStack(alignment: .center, spacing: 20) {
Image("migration_detail_1")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(height: geo.size.height * 0.35, alignment: .bottom)
.frame(maxWidth: geo.size.width - 60)
.padding(EdgeInsets(top: 56, leading: 30, bottom: 0, trailing: 30))
.accessibilityHidden(true)
infoText
.frame(width: geo.size.width)
Spacer()
}
.frame(width: geo.size.width, height: geo.size.height)
.frame(minHeight: geo.size.height)
.frame(width: geo.size.width)
}
}
}
var header: some View {
VStack(spacing: 50) {
Image("bumx_logo")
.resizable()
.frame(width: 150, height: 150)
.clipShape(.rect(cornerRadius: 26))
.overlay(
RoundedRectangle(cornerRadius: 26)
.stroke(.gray, lineWidth: 0.4)
)
Text(BWIL10n.bwiMobileDialogMMoreTitle)
.font(.title)
.bold()
.frame(width: geo.size.width, height: geo.size.height)
}
}
var infoText: some View {
VStack(alignment: .leading) {
Text(BWIL10n.bwiMobileDialogM1MoreText1) +
Text(BWIL10n.bwiMobileDialogM1MoreText2).bold() +
Text(BWIL10n.bwiMobileDialogMMoreTitle)
.font(.title)
.bold()
.foregroundColor(Color.black)
.lineLimit(nil)
.fixedSize(horizontal: false, vertical: true)
.padding(.bottom, 20)
Text(BWIL10n.bwiMobileDialogM1MoreText1)
.foregroundColor(Color.black) +
Text(BWIL10n.bwiMobileDialogM1MoreText2).bold()
.foregroundColor(Color.black) +
Text(BWIL10n.bwiMobileDialogM1MoreText3)
.foregroundColor(Color.black)
VStack(alignment: .leading) {
HStack(alignment: .top) {
Text("")
@@ -148,79 +152,114 @@ struct MigrationInfoViewOne: View {
}
}
.multilineTextAlignment(.leading)
.foregroundColor(Color.black)
.padding(.leading, 16)
}
.lineLimit(nil)
.fixedSize(horizontal: false, vertical: true)
.padding(EdgeInsets(top: 0, leading: 30, bottom: 0, trailing: 30))
.padding(EdgeInsets(top: 10, leading: 30, bottom: 0, trailing: 30))
.accessibilityElement(children: .ignore)
.accessibilityLabel(
BWIL10n.bwiMobileDialogMMoreTitle + ". " +
BWIL10n.bwiMobileDialogM1MoreText1 +
BWIL10n.bwiMobileDialogM1MoreText2 +
BWIL10n.bwiMobileDialogM1MoreText3 + ", " +
BWIL10n.bwiMobileDialogM1MoreTextBullet1 + ", " +
BWIL10n.bwiMobileDialogM1MoreTextBullet2 + ", " +
BWIL10n.bwiMobileDialogM1MoreTextBullet3 + ", " +
BWIL10n.bwiMobileDialogM1MoreTextBullet4)
}
}
// MARK: Migraion Info View two
struct MigrationInfoViewTwo: View {
let username: String
@State var showSuccessToast: Bool = false
var body: some View {
GeometryReader { geo in
ScrollView(.vertical) {
VStack(alignment: .center, spacing: 30) {
Spacer()
header
VStack(alignment: .center, spacing: 20) {
VStack() {
Image("bumx_logo")
.resizable()
.frame(width: 200, height: 200)
.clipShape(.rect(cornerRadius: 36))
.overlay(
RoundedRectangle(cornerRadius: 36)
.stroke(.gray, lineWidth: 0.4)
)
.accessibilityHidden(true)
}
.frame(height: geo.size.height * 0.35, alignment: .center)
.padding(EdgeInsets(top: 56, leading: 30, bottom: 10, trailing: 30))
instructionsList
successToast
Spacer()
downloadNewAppButton
}
.frame(width: geo.size.width, height: geo.size.height)
.frame(minHeight: geo.size.height)
.frame(width: geo.size.width)
}
}
}
var header: some View {
VStack(spacing: 50) {
Image("bumx_logo")
.resizable()
.frame(width: 150, height: 150)
.clipShape(.rect(cornerRadius: 26))
.overlay(
RoundedRectangle(cornerRadius: 26)
.stroke(.gray, lineWidth: 0.4)
)
Text(BWIL10n.bwiMobileDialogMMore2Title)
.font(.title)
.bold()
.frame(width: geo.size.width, height: geo.size.height)
}
}
var instructionsList: some View {
VStack(alignment: .leading, spacing: 10) {
HStack() {
Text("1.")
Button(action: {
}, label: {
Text(BWIL10n.bwiMobileDialogMMore2Text1)
.underline()
Image(systemName: "square.on.square")
.resizable()
.frame(width: 15, height: 15)
})
VStack() {
VStack(alignment: .center) {
Text(BWIL10n.bwiMobileDialogMMore2Title)
.font(.title)
.bold()
.foregroundColor(Color.black)
.padding(.bottom, 20)
}
HStack() {
Text("2.")
Text(BWIL10n.bwiMobileDialogMMore2Text2)
}
HStack() {
Text("3.")
Text(BWIL10n.bwiMobileDialogMMore2Text3)
VStack(alignment: .leading) {
HStack() {
Text("1.")
Button(action: {
UIPasteboard.general.string = username
guard !showSuccessToast else { return }
withAnimation {
showSuccessToast = true
}
DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
withAnimation {
showSuccessToast = false
}
}
}, label: {
Text(BWIL10n.bwiMobileDialogMMore2Text1)
.underline()
Image(systemName: "square.on.square")
.resizable()
.frame(width: 15, height: 15)
})
}
.foregroundColor(Color.black)
HStack() {
Text("2.")
Text(BWIL10n.bwiMobileDialogMMore2Text2)
}
.padding(.bottom, 1)
.foregroundColor(Color.black)
HStack() {
Text("3.")
Text(BWIL10n.bwiMobileDialogMMore2Text3)
}
.foregroundColor(Color.black)
}
}
.lineLimit(nil)
.fixedSize(horizontal: false, vertical: true)
.padding(EdgeInsets(top: 10, leading: 30, bottom: 0, trailing: 30))
}
var downloadNewAppButton: some View {
@@ -240,4 +279,20 @@ struct MigrationInfoViewTwo: View {
})
.padding(.bottom, 100)
}
var successToast: some View {
HStack() {
Image(systemName: "checkmark")
.resizable()
.frame(width: 15, height: 15)
.accessibilityHidden(true)
Text(BWIL10n.bwiMobileDialogMMoreSuccess)
}
.foregroundColor(.white)
.padding(10)
.background(Color.black)
.clipShape(RoundedRectangle(cornerRadius: 10))
.opacity(showSuccessToast ? 1 : 0)
.transition(.opacity)
}
}