diff --git a/Riot/Assets/de.lproj/Vector.strings b/Riot/Assets/de.lproj/Vector.strings index db34abd41..766ff9904 100644 --- a/Riot/Assets/de.lproj/Vector.strings +++ b/Riot/Assets/de.lproj/Vector.strings @@ -2571,7 +2571,6 @@ "user_inactive_session_item_with_date" = "Inaktiv seit 90+ Tagen (%@)"; "user_inactive_session_item" = "Inaktiv seit 90+ Tagen"; "user_other_session_unverified_sessions_header_subtitle" = "Für besonders sichere Kommunikation verifiziere deine Sitzungen oder melde dich von ihnen ab, falls du sie nicht mehr identifizieren kannst."; -"user_other_session_security_recommendation_title" = "Sicherheitsempfehlung"; "user_sessions_overview_link_device" = "Verbinde ein Gerät"; // MARK: User sessions management diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index 37bb74994..f1b90008b 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -2474,7 +2474,7 @@ To enable access, tap Settings> Location and select Always"; "user_session_rename_session_title" = "Renaming sessions"; "user_session_rename_session_description" = "Other users in direct messages and rooms that you join are able to view a full list of your sessions.\n\nThis provides them with confidence that they are really speaking to you, but it also means they can see the session name you enter here."; -"user_other_session_security_recommendation_title" = "Security recommendation"; +"user_other_session_security_recommendation_title" = "Other sessions"; "user_other_session_unverified_sessions_header_subtitle" = "Verify your sessions for enhanced secure messaging or sign out from those you don’t recognize or use anymore."; "user_other_session_current_session_details" = "Your current session"; "user_other_session_verified_sessions_header_subtitle" = "For best security, sign out from any session that you don’t recognize or use anymore."; diff --git a/Riot/Assets/et.lproj/Vector.strings b/Riot/Assets/et.lproj/Vector.strings index fd122e847..3797c222b 100644 --- a/Riot/Assets/et.lproj/Vector.strings +++ b/Riot/Assets/et.lproj/Vector.strings @@ -2545,7 +2545,6 @@ "user_other_session_verified_sessions_header_subtitle" = "Parima turvalisuse nimel logi välja neist sessioonidest, mida sa enam ei kasuta või ei tunne ära."; "user_other_session_current_session_details" = "Sinu praegune sessioon"; "user_other_session_unverified_sessions_header_subtitle" = "Turvalise sõnumvahetuse nimel verifitseeri kõik oma sessioonid ning logi neist välja, mida sa enam ei kasuta või ei tunne enam ära."; -"user_other_session_security_recommendation_title" = "Turvalisusega seotud soovitused"; "user_other_session_verified_additional_info" = "See sessioon on valmis turvaliseks sõnumivahetuseks."; "user_other_session_unverified_additional_info" = "Parima turvalisuse ja töökindluse nimel verifitseeri see sessioon või logi ta võrgust välja."; "user_session_verification_unknown_additional_info" = "Selle sessiooni olekut ei saa tuvastada enne kui oled ta verifitseerinud."; diff --git a/Riot/Assets/fr.lproj/Vector.strings b/Riot/Assets/fr.lproj/Vector.strings index 4f371613b..ed4a3820f 100644 --- a/Riot/Assets/fr.lproj/Vector.strings +++ b/Riot/Assets/fr.lproj/Vector.strings @@ -2542,7 +2542,6 @@ // First item is client name and second item is session display name "user_session_name" = "%@ : %@"; "user_other_session_unverified_sessions_header_subtitle" = "Vérifiez vos sessions pour renforcer la sécurité de votre messagerie, ou déconnectez celles que vous ne reconnaissez ou utilisez plus."; -"user_other_session_security_recommendation_title" = "Recommandations de sécurité"; "user_session_push_notifications_message" = "Lorsqu’activé, cette session recevra des notifications push."; "user_session_push_notifications" = "Notifications push"; "user_sessions_overview_current_session_section_title" = "Session courante"; diff --git a/Riot/Assets/hu.lproj/Vector.strings b/Riot/Assets/hu.lproj/Vector.strings index 78e52a6fd..f1f4e16ab 100644 --- a/Riot/Assets/hu.lproj/Vector.strings +++ b/Riot/Assets/hu.lproj/Vector.strings @@ -2565,7 +2565,6 @@ "user_other_session_verified_sessions_header_subtitle" = "A legjobb biztonság érdekében jelentkezz ki minden olyan munkamenetből, melyet már nem ismersz fel vagy nem használsz."; "user_other_session_current_session_details" = "Jelenlegi munkamenet"; "user_other_session_unverified_sessions_header_subtitle" = "Erősítse meg a munkameneteit a még biztonságosabb csevegéshez vagy jelentkezzen ki ezekből, ha nem ismeri fel vagy már nem használja őket."; -"user_other_session_security_recommendation_title" = "Biztonsági javaslat"; "user_session_push_notifications_message" = "Ha be van kapcsolva az eszközre Push értesítések lesznek küldve."; "user_session_push_notifications" = "Push értesítések"; "user_other_session_verified_additional_info" = "Ez a munkamenet beállítva a biztonságos üzenetküldéshez."; diff --git a/Riot/Assets/id.lproj/Vector.strings b/Riot/Assets/id.lproj/Vector.strings index 8894d91b4..a4ae14538 100644 --- a/Riot/Assets/id.lproj/Vector.strings +++ b/Riot/Assets/id.lproj/Vector.strings @@ -2752,7 +2752,6 @@ "user_inactive_session_item_with_date" = "Tidak aktif selama 90+ hari (%@)"; "user_inactive_session_item" = "Tidak aktif selama 90+ hari"; "user_other_session_unverified_sessions_header_subtitle" = "Verifikasi sesi Anda untuk perpesanan aman yang terbaik atau keluarkan sesi yang Anda tidak kenal atau gunakan lagi."; -"user_other_session_security_recommendation_title" = "Saran keamanan"; "user_sessions_overview_link_device" = "Tautkan sebuah perangkat"; // MARK: User sessions management diff --git a/Riot/Assets/it.lproj/Vector.strings b/Riot/Assets/it.lproj/Vector.strings index bc2e62e7c..b0ee26dc2 100644 --- a/Riot/Assets/it.lproj/Vector.strings +++ b/Riot/Assets/it.lproj/Vector.strings @@ -2525,7 +2525,6 @@ "user_inactive_session_item" = "Inattiva da 90+ giorni"; "user_inactive_session_item_with_date" = "Inattiva da 90+ giorni (%@)"; "user_other_session_unverified_sessions_header_subtitle" = "Verifica le tue sessioni per avere conversazioni più sicure o disconnetti quelle che non riconosci o che non usi più."; -"user_other_session_security_recommendation_title" = "Consiglio di sicurezza"; "user_sessions_overview_link_device" = "Collega un dispositivo"; // MARK: User sessions management diff --git a/Riot/Assets/nl.lproj/Vector.strings b/Riot/Assets/nl.lproj/Vector.strings index 0b3fd5868..5c02db6a0 100644 --- a/Riot/Assets/nl.lproj/Vector.strings +++ b/Riot/Assets/nl.lproj/Vector.strings @@ -2724,7 +2724,6 @@ "user_other_session_verified_sessions_header_subtitle" = "Voor de beste beveiliging log je uit bij elke sessie die je niet meer herkent of gebruikt."; "user_other_session_current_session_details" = "Jouw huidige sessie"; "user_other_session_unverified_sessions_header_subtitle" = "Verifieer je sessies voor verbeterde beveiligde berichtenuitwisseling of meld je af bij sessies die je niet meer herkent of gebruikt."; -"user_other_session_security_recommendation_title" = "Beveiligingsaanbeveling"; "user_session_push_notifications_message" = "Indien ingeschakeld, ontvangt deze sessie pushmeldingen."; "user_session_push_notifications" = "Pushmeldingen"; "user_other_session_verified_additional_info" = "Deze sessie is klaar voor beveiligde berichtenuitwisseling."; diff --git a/Riot/Assets/pt_BR.lproj/Vector.strings b/Riot/Assets/pt_BR.lproj/Vector.strings index 7e2cc90f2..3bf630208 100644 --- a/Riot/Assets/pt_BR.lproj/Vector.strings +++ b/Riot/Assets/pt_BR.lproj/Vector.strings @@ -2526,7 +2526,6 @@ "user_inactive_session_item_with_date" = "Inativa por 90+ dias (%@)"; "user_inactive_session_item" = "Inativa por 90+ dias"; "user_other_session_unverified_sessions_header_subtitle" = "Verifique suas sessões para mensageria de segurança melhorada ou faça signout daquelas que você não reconhece ou usa mais."; -"user_other_session_security_recommendation_title" = "Recomendação de segurança"; "user_sessions_overview_link_device" = "Linkar um dispositivo"; // MARK: User sessions management diff --git a/Riot/Assets/sk.lproj/Vector.strings b/Riot/Assets/sk.lproj/Vector.strings index 9f1cc6b65..8290307fa 100644 --- a/Riot/Assets/sk.lproj/Vector.strings +++ b/Riot/Assets/sk.lproj/Vector.strings @@ -2748,7 +2748,6 @@ "user_inactive_session_item_with_date" = "Neaktívna viac ako 90 dní (%@)"; "user_inactive_session_item" = "Neaktívna viac ako 90 dní"; "user_other_session_unverified_sessions_header_subtitle" = "Overte si relácie pre vylepšené bezpečné zasielanie správ alebo sa odhláste z tých, ktoré už nepoznáte alebo nepoužívate."; -"user_other_session_security_recommendation_title" = "Bezpečnostné odporúčania"; "user_sessions_overview_link_device" = "Prepojiť zariadenie"; // MARK: User sessions management diff --git a/Riot/Assets/sq.lproj/Vector.strings b/Riot/Assets/sq.lproj/Vector.strings index 8d6e3cbfd..24517ae23 100644 --- a/Riot/Assets/sq.lproj/Vector.strings +++ b/Riot/Assets/sq.lproj/Vector.strings @@ -2486,7 +2486,6 @@ "user_other_session_verified_sessions_header_subtitle" = "Për sigurinë më të mirë, dilni nga çfarëdo sesioni që nuk e njihni apo përdorni më."; "user_other_session_current_session_details" = "Sesioni juaj i tanishëm"; "user_other_session_unverified_sessions_header_subtitle" = "Verifikoni sesionet tuaj, për shkëmbim më të sigurt mesazhesh, ose dilni prej atyre që nuk i njihni, apo përdorni më."; -"user_other_session_security_recommendation_title" = "Rekomandim sigurie"; "user_session_push_notifications_message" = "Kur aktivizohet, ky sesion do të marrë njoftime push."; "user_session_push_notifications" = "Njoftime Push"; "user_other_session_verified_additional_info" = "Ky sesion është gati për shkëmbim të sigurt mesazhesh."; diff --git a/Riot/Assets/uk.lproj/Vector.strings b/Riot/Assets/uk.lproj/Vector.strings index a38d76c6f..f274a0dbe 100644 --- a/Riot/Assets/uk.lproj/Vector.strings +++ b/Riot/Assets/uk.lproj/Vector.strings @@ -2750,7 +2750,6 @@ "user_inactive_session_item_with_date" = "Неактивний понад 90 днів (%@)"; "user_inactive_session_item" = "Неактивний понад 90 днів"; "user_other_session_unverified_sessions_header_subtitle" = "Перевірте свої сеанси для посилення безпеки обміну повідомленнями або вийдіть з тих, які ви більше не розпізнаєте або не використовуєте."; -"user_other_session_security_recommendation_title" = "Поради з безпеки"; "user_sessions_overview_link_device" = "Пов'язати пристрій"; // MARK: User sessions management diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index 97c1ad7e6..2008451ea 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -8739,7 +8739,7 @@ public class VectorL10n: NSObject { public static var userOtherSessionPermanentlyUnverifiedAdditionalInfo: String { return VectorL10n.tr("Vector", "user_other_session_permanently_unverified_additional_info") } - /// Security recommendation + /// Other sessions public static var userOtherSessionSecurityRecommendationTitle: String { return VectorL10n.tr("Vector", "user_other_session_security_recommendation_title") } diff --git a/RiotSwiftUI/Modules/UserSessions/Common/View/DeviceAvatarView.swift b/RiotSwiftUI/Modules/UserSessions/Common/View/DeviceAvatarView.swift index 0e894961d..0352f35a4 100644 --- a/RiotSwiftUI/Modules/UserSessions/Common/View/DeviceAvatarView.swift +++ b/RiotSwiftUI/Modules/UserSessions/Common/View/DeviceAvatarView.swift @@ -23,6 +23,7 @@ struct DeviceAvatarView: View { var viewData: DeviceAvatarViewData var isSelected: Bool + var showVerificationBadge: Bool = true var avatarSize: CGFloat = 40 var badgeSize: CGFloat = 24 @@ -40,13 +41,14 @@ struct DeviceAvatarView: View { .background(isSelected ? theme.colors.primaryContent : theme.colors.system) .clipShape(Circle()) - // Verification badge - Image(viewData.verificationImageName) - .frame(maxWidth: CGFloat(badgeSize), maxHeight: CGFloat(badgeSize)) - .shapedBorder(color: theme.colors.system, borderWidth: 1, shape: Circle()) - .background(theme.colors.background) - .clipShape(Circle()) - .offset(x: 10, y: 8) + if showVerificationBadge { + Image(viewData.verificationImageName) + .frame(maxWidth: CGFloat(badgeSize), maxHeight: CGFloat(badgeSize)) + .shapedBorder(color: theme.colors.quinaryContent, borderWidth: 1, shape: Circle()) + .background(theme.colors.background) + .clipShape(Circle()) + .offset(x: 10, y: 8) + } } .frame(maxWidth: CGFloat(avatarSize), maxHeight: CGFloat(avatarSize)) } diff --git a/RiotSwiftUI/Modules/UserSessions/Common/View/SeparatorLine.swift b/RiotSwiftUI/Modules/UserSessions/Common/View/SeparatorLine.swift index 2f56761ef..22c24aa94 100644 --- a/RiotSwiftUI/Modules/UserSessions/Common/View/SeparatorLine.swift +++ b/RiotSwiftUI/Modules/UserSessions/Common/View/SeparatorLine.swift @@ -19,10 +19,12 @@ import SwiftUI struct SeparatorLine: View { @Environment(\.theme) private var theme: ThemeSwiftUI + var height: CGFloat = 1.0 + var body: some View { Rectangle() .fill(theme.colors.quinaryContent) .frame(maxWidth: .infinity) - .frame(height: 1.0) + .frame(height: height) } } diff --git a/RiotSwiftUI/Modules/UserSessions/Common/View/UserSessionCardView.swift b/RiotSwiftUI/Modules/UserSessions/Common/View/UserSessionCardView.swift index 9f6f6460f..a8a4aa351 100644 --- a/RiotSwiftUI/Modules/UserSessions/Common/View/UserSessionCardView.swift +++ b/RiotSwiftUI/Modules/UserSessions/Common/View/UserSessionCardView.swift @@ -30,14 +30,21 @@ struct UserSessionCardView: View { RoundedRectangle(cornerRadius: 8) } + enum DisplayMode { + case compact + case extended + } + let showLocationInformations: Bool + let displayMode: DisplayMode + private var showExtraInformations: Bool { - viewData.isCurrentSessionDisplayMode == false && (viewData.lastActivityDateString.isEmptyOrNil == false || ipText.isEmptyOrNil == false) + displayMode == .extended && (viewData.lastActivityDateString.isEmptyOrNil == false || ipText.isEmptyOrNil == false) } var body: some View { VStack(alignment: .center, spacing: 12) { - DeviceAvatarView(viewData: viewData.deviceAvatarViewData, isSelected: false) + DeviceAvatarView(viewData: viewData.deviceAvatarViewData, isSelected: false, showVerificationBadge: false) .accessibilityHidden(true) Text(viewData.sessionName) @@ -45,10 +52,16 @@ struct UserSessionCardView: View { .foregroundColor(theme.colors.primaryContent) .multilineTextAlignment(.center) - Label(viewData.verificationStatusText, image: viewData.verificationStatusImageName) - .font(theme.fonts.subheadline) - .foregroundColor(theme.colors[keyPath: viewData.verificationStatusColor]) - .multilineTextAlignment(.center) + Label { + Text(viewData.verificationStatusText) + .font(theme.fonts.subheadline) + .foregroundColor(theme.colors[keyPath: viewData.verificationStatusColor]) + .multilineTextAlignment(.center) + } icon: { + Image(viewData.verificationStatusImageName) + .resizable() + .frame(width: 16, height: 16) + } InlineTextButton(viewData.verificationStatusAdditionalInfoText, tappableText: VectorL10n.userSessionLearnMore, alwaysCallAction: false) { onLearnMoreAction?() @@ -93,18 +106,19 @@ struct UserSessionCardView: View { .accessibilityIdentifier("userSessionCardVerifyButton") } - if viewData.isCurrentSessionDisplayMode { + if viewData.isCurrentSessionDisplayMode, displayMode == .compact { Text(VectorL10n.userSessionViewDetails) .font(theme.fonts.body) .foregroundColor(theme.colors.accent) .accessibilityIdentifier("userSessionCardViewDetails") + .padding(.top, 8) } } .padding(24) .frame(maxWidth: .infinity) .background(theme.colors.background) .clipShape(backgroundShape) - .shapedBorder(color: theme.colors.quinaryContent, borderWidth: 1.0, shape: backgroundShape) + .shapedBorder(color: theme.colors.quinaryContent, borderWidth: 0.5, shape: backgroundShape) .onTapGesture { if viewData.isCurrentSessionDisplayMode { onViewDetailsAction?(viewData.sessionId) @@ -124,8 +138,9 @@ struct UserSessionCardViewPreview: View { @Environment(\.theme) var theme: ThemeSwiftUI let viewData: UserSessionCardViewData + let displayMode: UserSessionCardView.DisplayMode - init(isCurrent: Bool = false, verificationState: UserSessionInfo.VerificationState = .unverified) { + init(isCurrent: Bool = false, verificationState: UserSessionInfo.VerificationState = .unverified, displayMode: UserSessionCardView.DisplayMode = .extended) { let sessionInfo = UserSessionInfo(id: "alice", name: "iOS", deviceType: .mobile, @@ -143,11 +158,12 @@ struct UserSessionCardViewPreview: View { isActive: true, isCurrent: isCurrent) viewData = UserSessionCardViewData(sessionInfo: sessionInfo) + self.displayMode = displayMode } var body: some View { VStack { - UserSessionCardView(viewData: viewData, showLocationInformations: true) + UserSessionCardView(viewData: viewData, showLocationInformations: true, displayMode: displayMode) } .frame(maxWidth: .infinity) .background(theme.colors.system) @@ -158,7 +174,8 @@ struct UserSessionCardViewPreview: View { struct UserSessionCardView_Previews: PreviewProvider { static var previews: some View { Group { - UserSessionCardViewPreview(isCurrent: true).theme(.light).preferredColorScheme(.light) + UserSessionCardViewPreview(isCurrent: true, displayMode: .compact).theme(.light).preferredColorScheme(.light) + UserSessionCardViewPreview(isCurrent: true, displayMode: .extended).theme(.light).preferredColorScheme(.light) UserSessionCardViewPreview(isCurrent: true).theme(.dark).preferredColorScheme(.dark) UserSessionCardViewPreview().theme(.light).preferredColorScheme(.light) UserSessionCardViewPreview().theme(.dark).preferredColorScheme(.dark) diff --git a/RiotSwiftUI/Modules/UserSessions/UserOtherSessions/View/UserOtherSessions.swift b/RiotSwiftUI/Modules/UserSessions/UserOtherSessions/View/UserOtherSessions.swift index e0f71675c..41d79fe54 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserOtherSessions/View/UserOtherSessions.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserOtherSessions/View/UserOtherSessions.swift @@ -22,8 +22,8 @@ struct UserOtherSessions: View { @ObservedObject var viewModel: UserOtherSessionsViewModel.Context var body: some View { - VStack(spacing: 0) { - ScrollView { + ScrollView { + VStack(spacing: 0) { SwiftUI.Section { if viewModel.viewState.sessionItems.isEmpty { noItemsView() @@ -37,7 +37,7 @@ struct UserOtherSessions: View { viewModel.send(viewAction: .viewSessionInfo) } ) - .padding(.top) + .padding(.vertical, 24) } } if viewModel.isEditModeEnabled { @@ -100,7 +100,7 @@ struct UserOtherSessions: View { isSeparatorHidden: viewData == viewModel.viewState.sessionItems.last, isEditModeEnabled: viewModel.isEditModeEnabled, onBackgroundTap: { sessionId in viewModel.send(viewAction: .userOtherSessionSelected(sessionId: sessionId)) }, - onBackgroundLongPress: { _ in viewModel.isEditModeEnabled = true }) + onBackgroundLongPress: { _ in }) } } .background(theme.colors.background) diff --git a/RiotSwiftUI/Modules/UserSessions/UserOtherSessions/View/UserOtherSessionsHeaderView.swift b/RiotSwiftUI/Modules/UserSessions/UserOtherSessions/View/UserOtherSessionsHeaderView.swift index a815d7875..5555cc827 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserOtherSessions/View/UserOtherSessionsHeaderView.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserOtherSessions/View/UserOtherSessionsHeaderView.swift @@ -54,7 +54,6 @@ struct UserOtherSessionsHeaderView: View { } .font(theme.fonts.footnote) .foregroundColor(theme.colors.secondaryContent) - .padding(.bottom, 20.0) }) } .frame(maxWidth: .infinity, alignment: .leading) diff --git a/RiotSwiftUI/Modules/UserSessions/UserOtherSessions/View/UserOtherSessionsToolbar.swift b/RiotSwiftUI/Modules/UserSessions/UserOtherSessions/View/UserOtherSessionsToolbar.swift index b74606910..331ede0c3 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserOtherSessions/View/UserOtherSessionsToolbar.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserOtherSessions/View/UserOtherSessionsToolbar.swift @@ -107,5 +107,6 @@ struct UserOtherSessionsToolbar: ToolbarContent { .padding(.vertical, 12) } } + .accessibilityIdentifier("More") } } diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/View/UserSessionDetails.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/View/UserSessionDetails.swift index 8801c9ef0..215441892 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/View/UserSessionDetails.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/View/UserSessionDetails.swift @@ -54,6 +54,7 @@ struct UserSessionDetails: View { } } .listStyle(.grouped) + .listBackgroundColor(theme.colors.system) .navigationBarTitle(VectorL10n.userSessionDetailsTitle) } } diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/View/UserSessionOverview.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/View/UserSessionOverview.swift index 023952845..8f155814f 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/View/UserSessionOverview.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/View/UserSessionOverview.swift @@ -34,21 +34,24 @@ struct UserSessionOverview: View { onLearnMoreAction: { viewModel.send(viewAction: .viewSessionInfo) }, - showLocationInformations: viewModel.viewState.showLocationInfo + showLocationInformations: viewModel.viewState.showLocationInfo, + displayMode: .extended ) .padding(16) SwiftUI.Section { - UserSessionOverviewItem(title: VectorL10n.userSessionOverviewSessionDetailsButtonTitle, - showsChevron: true) { - viewModel.send(viewAction: .viewSessionDetails) - } - - if let enabled = viewModel.viewState.isPusherEnabled { - UserSessionOverviewToggleCell(title: VectorL10n.userSessionPushNotifications, - message: VectorL10n.userSessionPushNotificationsMessage, - isOn: enabled, isEnabled: viewModel.viewState.remotelyTogglingPushersAvailable) { - viewModel.send(viewAction: .togglePushNotifications) + VStack(spacing: 24) { + UserSessionOverviewItem(title: VectorL10n.userSessionOverviewSessionDetailsButtonTitle, + showsChevron: true) { + viewModel.send(viewAction: .viewSessionDetails) + } + + if let enabled = viewModel.viewState.isPusherEnabled { + UserSessionOverviewToggleCell(title: VectorL10n.userSessionPushNotifications, + message: VectorL10n.userSessionPushNotificationsMessage, + isOn: enabled, isEnabled: viewModel.viewState.remotelyTogglingPushersAvailable) { + viewModel.send(viewAction: .togglePushNotifications) + } } } } @@ -77,12 +80,10 @@ struct UserSessionOverview: View { } .accessibilityIdentifier(VectorL10n.manageSessionRename) - if viewModel.viewState.isCurrentSession == false { - Button { - viewModel.send(viewAction: .showLocationInfo) - } label: { - Label(showLocationInfo: viewModel.viewState.showLocationInfo) - } + Button { + viewModel.send(viewAction: .showLocationInfo) + } label: { + Label(showLocationInfo: viewModel.viewState.showLocationInfo) } } DestructiveButton { @@ -93,7 +94,7 @@ struct UserSessionOverview: View { .accessibilityIdentifier(VectorL10n.signOut) } label: { Image(systemName: "ellipsis") - .foregroundColor(theme.colors.secondaryContent) + .foregroundColor(theme.colors.accent) .padding(.horizontal, 4) .padding(.vertical, 12) } diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/View/UserSessionOverviewItem.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/View/UserSessionOverviewItem.swift index b54d23a99..580c9181f 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/View/UserSessionOverviewItem.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/View/UserSessionOverviewItem.swift @@ -36,10 +36,11 @@ struct UserSessionOverviewItem: View { .frame(maxWidth: .infinity, alignment: alignment) if showsChevron { - Image(Asset.Images.chevron.name) + Image(Asset.Images.disclosureIcon.name) + .foregroundColor(theme.colors.tertiaryContent) } } - .padding(.vertical, 15) + .padding(.vertical, 11) .padding(.horizontal, 16) SeparatorLine() } diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/View/UserSessionOverviewToggleCell.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/View/UserSessionOverviewToggleCell.swift index b6f79b58f..c162e930e 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/View/UserSessionOverviewToggleCell.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/View/UserSessionOverviewToggleCell.swift @@ -41,7 +41,7 @@ struct UserSessionOverviewToggleCell: View { } .disabled(!isEnabled) .allowsHitTesting(false) - .padding(.vertical, 10) + .padding(.vertical, 5.5) .padding(.horizontal, 16) .accessibilityIdentifier("UserSessionOverviewToggleCell") SeparatorLine() diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/SecurityRecommendationCard.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/SecurityRecommendationCard.swift index 090051154..e272c0563 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/SecurityRecommendationCard.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/SecurityRecommendationCard.swift @@ -30,12 +30,12 @@ struct SecurityRecommendationCard: View { let action: () -> Void var body: some View { - HStack(alignment: .top) { + HStack(alignment: .top, spacing: 16.0) { Image(iconName) VStack(alignment: .leading, spacing: 16.0) { VStack(alignment: .leading, spacing: 8.0) { Text(title) - .font(theme.fonts.calloutSB) + .font(theme.fonts.headline) .foregroundColor(theme.colors.primaryContent) Text(subtitle) @@ -43,20 +43,19 @@ struct SecurityRecommendationCard: View { .foregroundColor(theme.colors.secondaryContent) } - Button { - action() - } label: { - Text(buttonTitle) - .font(theme.fonts.body) - } - .foregroundColor(theme.colors.accent) + Text(buttonTitle) + .font(theme.fonts.body) + .foregroundColor(theme.colors.accent) } .frame(maxWidth: .infinity, alignment: .leading) } .padding(16) .background(theme.colors.background) .clipShape(backgroundShape) - .shapedBorder(color: theme.colors.quinaryContent, borderWidth: 1.0, shape: backgroundShape) + .shapedBorder(color: theme.colors.quinaryContent, borderWidth: 0.5, shape: backgroundShape) + .onTapGesture { + action() + } } private var backgroundShape: RoundedRectangle { diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionListItem.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionListItem.swift index f5d24c555..287b64003 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionListItem.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionListItem.swift @@ -43,13 +43,14 @@ struct UserSessionListItem: View { DeviceAvatarView(viewData: viewData.deviceAvatarViewData, isSelected: viewData.isSelected) VStack(alignment: .leading, spacing: 0) { Text(viewData.sessionName) - .font(theme.fonts.bodySB) + .lineLimit(1) + .font(theme.fonts.headline) .foregroundColor(theme.colors.primaryContent) .multilineTextAlignment(.leading) .padding(.top, 16) .padding(.bottom, 2) .padding(.trailing, 16) - HStack { + HStack(alignment: .top) { if let sessionDetailsIcon = viewData.sessionDetailsIcon { Image(sessionDetailsIcon) .padding(.leading, 2) @@ -67,7 +68,7 @@ struct UserSessionListItem: View { } .padding(.bottom, 16) .padding(.trailing, 16) - SeparatorLine() + SeparatorLine(height: 0.5) .isHidden(isSeparatorHidden) } .padding(.leading, 7) diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionsListViewAllView.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionsListViewAllView.swift index e3816314c..d472703b5 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionsListViewAllView.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionsListViewAllView.swift @@ -34,11 +34,11 @@ struct UserSessionsListViewAllView: View { .font(theme.fonts.body) .foregroundColor(theme.colors.accent) .frame(maxWidth: .infinity, alignment: .leading) - Image(Asset.Images.chevron.name) + Image(Asset.Images.disclosureIcon.name) + .foregroundColor(theme.colors.tertiaryContent) } .padding(.vertical, 15) .padding(.trailing, 20) - SeparatorLine() } .background(theme.colors.background) .padding(.leading, 72) diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionsOverview.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionsOverview.swift index c5ddce11d..9cfc89ca4 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionsOverview.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionsOverview.swift @@ -24,22 +24,19 @@ struct UserSessionsOverview: View { private let maxOtherSessionsToDisplay = 5 var body: some View { - VStack(alignment: .leading, spacing: 0) { - ScrollView { - if hasSecurityRecommendations { - securityRecommendationsSection - } - - currentSessionsSection - - if !viewModel.viewState.otherSessionsViewData.isEmpty { - otherSessionsSection - } + ScrollView { + if hasSecurityRecommendations { + securityRecommendationsSection + } + + currentSessionsSection + + if !viewModel.viewState.otherSessionsViewData.isEmpty { + otherSessionsSection } - .readableFrame() } .background(theme.colors.system.ignoresSafeArea()) - .frame(maxHeight: .infinity) + .frame(maxWidth: .infinity, maxHeight: .infinity) .navigationTitle(VectorL10n.userSessionsOverviewTitle) .navigationBarTitleDisplayMode(.inline) .activityIndicator(show: viewModel.viewState.showLoadingIndicator) @@ -51,17 +48,19 @@ struct UserSessionsOverview: View { private var securityRecommendationsSection: some View { SwiftUI.Section { - if !viewModel.viewState.unverifiedSessionsViewData.isEmpty { - SecurityRecommendationCard(style: .unverified, - sessionCount: viewModel.viewState.unverifiedSessionsViewData.count) { - viewModel.send(viewAction: .viewAllUnverifiedSessions) + VStack(spacing: 16) { + if !viewModel.viewState.unverifiedSessionsViewData.isEmpty { + SecurityRecommendationCard(style: .unverified, + sessionCount: viewModel.viewState.unverifiedSessionsViewData.count) { + viewModel.send(viewAction: .viewAllUnverifiedSessions) + } } - } - - if !viewModel.viewState.inactiveSessionsViewData.isEmpty { - SecurityRecommendationCard(style: .inactive, - sessionCount: viewModel.viewState.inactiveSessionsViewData.count) { - viewModel.send(viewAction: .viewAllInactiveSessions) + + if !viewModel.viewState.inactiveSessionsViewData.isEmpty { + SecurityRecommendationCard(style: .inactive, + sessionCount: viewModel.viewState.inactiveSessionsViewData.count) { + viewModel.send(viewAction: .viewAllInactiveSessions) + } } } } header: { @@ -75,10 +74,10 @@ struct UserSessionsOverview: View { Text(VectorL10n.userSessionsOverviewSecurityRecommendationsSectionInfo) .font(theme.fonts.footnote) .foregroundColor(theme.colors.secondaryContent) - .padding(.bottom, 12.0) } .frame(maxWidth: .infinity, alignment: .leading) .padding(.top, 24) + .padding(.bottom, 8.0) } .padding(.horizontal, 16) .accessibilityIdentifier("userSessionsOverviewSecurityRecommendationsSection") @@ -96,7 +95,7 @@ struct UserSessionsOverview: View { viewModel.send(viewAction: .verifyCurrentSession) }, onViewDetailsAction: { _ in viewModel.send(viewAction: .viewCurrentSessionDetails) - }, showLocationInformations: viewModel.viewState.showLocationInfo) + }, showLocationInformations: viewModel.viewState.showLocationInfo, displayMode: .compact) } header: { HStack(alignment: .firstTextBaseline) { Text(VectorL10n.userSessionsOverviewCurrentSessionSectionTitle) @@ -104,11 +103,11 @@ struct UserSessionsOverview: View { .font(theme.fonts.footnote) .foregroundColor(theme.colors.secondaryContent) .frame(maxWidth: .infinity, alignment: .leading) - .padding(.bottom, 12.0) .padding(.top, 24.0) currentSessionMenu } + .padding(.bottom, 8.0) } .padding(.horizontal, 16) } @@ -170,6 +169,7 @@ struct UserSessionsOverview: View { private var otherSessionsSection: some View { SwiftUI.Section { LazyVStack(spacing: 0) { + SeparatorLine(height: 0.5) ForEach(viewModel.viewState.otherSessionsViewData.prefix(maxOtherSessionsToDisplay)) { viewData in UserSessionListItem(viewData: viewData, showsLocationInfo: viewModel.viewState.showLocationInfo, @@ -181,6 +181,7 @@ struct UserSessionsOverview: View { viewModel.send(viewAction: .viewAllOtherSessions) } } + SeparatorLine(height: 0.5) } .background(theme.colors.background) } header: { @@ -198,11 +199,11 @@ struct UserSessionsOverview: View { Text(VectorL10n.userSessionsOverviewOtherSessionsSectionInfo) .font(theme.fonts.footnote) .foregroundColor(theme.colors.secondaryContent) - .padding(.bottom, 12.0) } .frame(maxWidth: .infinity, alignment: .leading) .padding(.horizontal, 16.0) .padding(.top, 24.0) + .padding(.bottom, 8.0) } .accessibilityIdentifier("userSessionsOverviewOtherSection") } diff --git a/changelog.d/pr-7180.change b/changelog.d/pr-7180.change new file mode 100644 index 000000000..80cb1db19 --- /dev/null +++ b/changelog.d/pr-7180.change @@ -0,0 +1 @@ +Updates on the UI/UX to conform the device manager to the design.