Merge branch 'develop' into aleksandrs/6786_inactive_sessions_screen

# Conflicts:
#	Riot/Assets/en.lproj/Vector.strings
#	Riot/Generated/Strings.swift
#	RiotSwiftUI/Modules/UserSessions/Coordinator/UserSessionsFlowCoordinator.swift
#	RiotSwiftUI/Modules/UserSessions/UserSessionOverview/Test/Unit/UserSessionOverviewViewModelTests.swift
#	RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Coordinator/UserSessionsOverviewCoordinator.swift
#	RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Service/Mock/MockUserSessionsOverviewService.swift
#	RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/UserSessionsOverviewModels.swift
#	RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionListItemViewData.swift
This commit is contained in:
Aleksandrs Proskurins
2022-10-04 15:14:59 +03:00
88 changed files with 2246 additions and 415 deletions
@@ -18,6 +18,7 @@ import Foundation
/// View data for UserSessionListItem
struct UserSessionListItemViewData: Identifiable, Hashable {
var id: String {
sessionId
}
@@ -29,6 +30,6 @@ struct UserSessionListItemViewData: Identifiable, Hashable {
let sessionDetails: String
let deviceAvatarViewData: DeviceAvatarViewData
let sessionDetailsIcon: String?
}
@@ -18,13 +18,9 @@ import Foundation
struct UserSessionListItemViewDataFactory {
private static let userSessionNameFormatter = UserSessionNameFormatter()
private static let lastActivityDateFormatter = UserSessionLastActivityFormatter()
private static let inactiveSessionDateFormatter = InactiveUserSessionLastActivityFormatter()
func create(from session: UserSessionInfo) -> UserSessionListItemViewData {
let sessionName = UserSessionListItemViewDataFactory.userSessionNameFormatter.sessionName(deviceType: session.deviceType,
sessionDisplayName: session.name)
let sessionName = UserSessionNameFormatter.sessionName(deviceType: session.deviceType,
sessionDisplayName: session.name)
let sessionDetails = buildSessionDetails(isVerified: session.isVerified,
lastActivityDate: session.lastSeenTimestamp,
isActive: session.isActive)
@@ -47,7 +43,7 @@ struct UserSessionListItemViewDataFactory {
private func inactiveSessionDetails(lastActivityDate: TimeInterval?) -> String {
if let lastActivityDate = lastActivityDate {
let lastActivityDateString = Self.inactiveSessionDateFormatter.lastActivityDateString(from: lastActivityDate)
let lastActivityDateString = InactiveUserSessionLastActivityFormatter.lastActivityDateString(from: lastActivityDate)
return VectorL10n.userInactiveSessionItemWithDate(lastActivityDateString)
}
return VectorL10n.userInactiveSessionItem
@@ -61,7 +57,7 @@ struct UserSessionListItemViewDataFactory {
var lastActivityDateString: String?
if let lastActivityDate = lastActivityDate {
lastActivityDateString = Self.lastActivityDateFormatter.lastActivityDateString(from: lastActivityDate)
lastActivityDateString = UserSessionLastActivityFormatter.lastActivityDateString(from: lastActivityDate)
}
if let lastActivityDateString = lastActivityDateString, lastActivityDateString.isEmpty == false {
@@ -23,11 +23,13 @@ struct UserSessionsOverview: View {
var body: some View {
ScrollView {
securityRecommendationsSection
if hasSecurityRecommendations {
securityRecommendationsSection
}
currentSessionsSection
if viewModel.viewState.otherSessionsViewData.isEmpty == false {
if !viewModel.viewState.otherSessionsViewData.isEmpty {
otherSessionsSection
}
}
@@ -40,41 +42,39 @@ struct UserSessionsOverview: View {
}
}
@ViewBuilder
private var securityRecommendationsSection: some View {
if hasSecurityRecommendations {
SwiftUI.Section {
if !viewModel.viewState.unverifiedSessionsViewData.isEmpty {
SecurityRecommendationCard(style: .unverified,
sessionCount: viewModel.viewState.unverifiedSessionsViewData.count) {
viewModel.send(viewAction: .viewAllUnverifiedSessions)
}
SwiftUI.Section {
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)
}
}
} header: {
VStack(alignment: .leading) {
Text(VectorL10n.userSessionsOverviewSecurityRecommendationsSectionTitle)
.textCase(.uppercase)
.font(theme.fonts.footnote)
.foregroundColor(theme.colors.secondaryContent)
.padding(.bottom, 8.0)
Text(VectorL10n.userSessionsOverviewSecurityRecommendationsSectionInfo)
.font(theme.fonts.footnote)
.foregroundColor(theme.colors.secondaryContent)
.padding(.bottom, 12.0)
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.top, 24)
}
.padding(.horizontal, 16)
if !viewModel.viewState.inactiveSessionsViewData.isEmpty {
SecurityRecommendationCard(style: .inactive,
sessionCount: viewModel.viewState.inactiveSessionsViewData.count) {
viewModel.send(viewAction: .viewAllInactiveSessions)
}
}
} header: {
VStack(alignment: .leading) {
Text(VectorL10n.userSessionsOverviewSecurityRecommendationsSectionTitle)
.textCase(.uppercase)
.font(theme.fonts.footnote)
.foregroundColor(theme.colors.secondaryContent)
.padding(.bottom, 8.0)
Text(VectorL10n.userSessionsOverviewSecurityRecommendationsSectionInfo)
.font(theme.fonts.footnote)
.foregroundColor(theme.colors.secondaryContent)
.padding(.bottom, 12.0)
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.top, 24)
}
.padding(.horizontal, 16)
.accessibilityIdentifier("userSessionsOverviewSecurityRecommendationsSection")
}
var hasSecurityRecommendations: Bool {
@@ -102,10 +102,9 @@ struct UserSessionsOverview: View {
.padding(.horizontal, 16)
}
}
private var otherSessionsSection: some View {
SwiftUI.Section {
// Device list
LazyVStack(spacing: 0) {
ForEach(viewModel.viewState.otherSessionsViewData) { viewData in
UserSessionListItem(viewData: viewData, onBackgroundTap: { sessionId in
@@ -131,6 +130,7 @@ struct UserSessionsOverview: View {
.padding(.horizontal, 16.0)
.padding(.top, 24.0)
}
.accessibilityIdentifier("userSessionsOverviewOtherSection")
}
}