mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-22 09:32:52 +02:00
Cleaned up various things, mostly removed unnecessary selfs, comments and bad formatting
This commit is contained in:
committed by
Stefan Ceriu
parent
c073dfd95d
commit
eac1401cc1
+8
-22
@@ -22,39 +22,24 @@ struct UserSessionsOverviewCoordinatorParameters {
|
||||
}
|
||||
|
||||
final class UserSessionsOverviewCoordinator: Coordinator, Presentable {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private let parameters: UserSessionsOverviewCoordinatorParameters
|
||||
private let userSessionsOverviewHostingController: UIViewController
|
||||
private var userSessionsOverviewViewModel: UserSessionsOverviewViewModelProtocol
|
||||
private let hostingViewController: UIViewController
|
||||
private var viewModel: UserSessionsOverviewViewModelProtocol
|
||||
private let service: UserSessionsOverviewService
|
||||
|
||||
private var indicatorPresenter: UserIndicatorTypePresenterProtocol
|
||||
private var loadingIndicator: UserIndicator?
|
||||
|
||||
// MARK: Public
|
||||
|
||||
// Must be used only internally
|
||||
var childCoordinators: [Coordinator] = []
|
||||
var completion: ((UserSessionsOverviewCoordinatorResult) -> Void)?
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(parameters: UserSessionsOverviewCoordinatorParameters) {
|
||||
self.parameters = parameters
|
||||
let service = UserSessionsOverviewService(mxSession: parameters.session)
|
||||
self.service = service
|
||||
let viewModel = UserSessionsOverviewViewModel(userSessionsOverviewService: service)
|
||||
let view = UserSessionsOverview(viewModel: viewModel.context)
|
||||
userSessionsOverviewViewModel = viewModel
|
||||
|
||||
let hostingViewController = VectorHostingController(rootView: view)
|
||||
|
||||
userSessionsOverviewHostingController = hostingViewController
|
||||
|
||||
service = UserSessionsOverviewService(mxSession: parameters.session)
|
||||
viewModel = UserSessionsOverviewViewModel(userSessionsOverviewService: service)
|
||||
hostingViewController = VectorHostingController(rootView: UserSessionsOverview(viewModel: viewModel.context))
|
||||
indicatorPresenter = UserIndicatorTypePresenter(presentingViewController: hostingViewController)
|
||||
}
|
||||
|
||||
@@ -62,9 +47,10 @@ final class UserSessionsOverviewCoordinator: Coordinator, Presentable {
|
||||
|
||||
func start() {
|
||||
MXLog.debug("[UserSessionsOverviewCoordinator] did start.")
|
||||
userSessionsOverviewViewModel.completion = { [weak self] result in
|
||||
viewModel.completion = { [weak self] result in
|
||||
guard let self = self else { return }
|
||||
MXLog.debug("[UserSessionsOverviewCoordinator] UserSessionsOverviewViewModel did complete with result: \(result).")
|
||||
|
||||
switch result {
|
||||
case .showAllUnverifiedSessions:
|
||||
self.showAllUnverifiedSessions()
|
||||
@@ -83,7 +69,7 @@ final class UserSessionsOverviewCoordinator: Coordinator, Presentable {
|
||||
}
|
||||
|
||||
func toPresentable() -> UIViewController {
|
||||
return self.userSessionsOverviewHostingController
|
||||
return hostingViewController
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
+15
-24
@@ -18,33 +18,25 @@ import Foundation
|
||||
import MatrixSDK
|
||||
|
||||
class UserSessionsOverviewService: UserSessionsOverviewServiceProtocol {
|
||||
|
||||
// MARK: - Constants
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private let mxSession: MXSession
|
||||
|
||||
// MARK: Public
|
||||
|
||||
private(set) var lastOverviewData: UserSessionsOverviewData
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(mxSession: MXSession) {
|
||||
self.mxSession = mxSession
|
||||
|
||||
self.lastOverviewData = UserSessionsOverviewData(currentSessionInfo: nil, unverifiedSessionsInfo: [], inactiveSessionsInfo: [], otherSessionsInfo: [])
|
||||
lastOverviewData = UserSessionsOverviewData(currentSessionInfo: nil,
|
||||
unverifiedSessionsInfo: [],
|
||||
inactiveSessionsInfo: [],
|
||||
otherSessionsInfo: [])
|
||||
|
||||
self.setupInitialOverviewData()
|
||||
setupInitialOverviewData()
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
func fetchUserSessionsOverviewData(completion: @escaping (Result<UserSessionsOverviewData, Error>) -> Void) {
|
||||
self.mxSession.matrixRestClient.devices { response in
|
||||
mxSession.matrixRestClient.devices { response in
|
||||
switch response {
|
||||
case .success(let devices):
|
||||
self.lastOverviewData = self.userSessionsOverviewData(from: devices)
|
||||
@@ -62,21 +54,20 @@ class UserSessionsOverviewService: UserSessionsOverviewServiceProtocol {
|
||||
// MARK: - Private
|
||||
|
||||
private func setupInitialOverviewData() {
|
||||
let currentSessionInfo = self.getCurrentUserSessionInfoFromCache()
|
||||
let currentSessionInfo = getCurrentUserSessionInfoFromCache()
|
||||
|
||||
self.lastOverviewData = UserSessionsOverviewData(currentSessionInfo: currentSessionInfo, unverifiedSessionsInfo: [], inactiveSessionsInfo: [], otherSessionsInfo: [])
|
||||
lastOverviewData = UserSessionsOverviewData(currentSessionInfo: currentSessionInfo, unverifiedSessionsInfo: [], inactiveSessionsInfo: [], otherSessionsInfo: [])
|
||||
}
|
||||
|
||||
private func getCurrentUserSessionInfoFromCache() -> UserSessionInfo? {
|
||||
guard let mainAccount = MXKAccountManager.shared().activeAccounts.first, let device = mainAccount.device else {
|
||||
return nil
|
||||
}
|
||||
return self.userSessionInfo(from: device)
|
||||
return userSessionInfo(from: device)
|
||||
}
|
||||
|
||||
private func userSessionInfo(from device: MXDevice) -> UserSessionInfo {
|
||||
|
||||
let deviceInfo = self.getDeviceInfo(for: device.deviceId)
|
||||
let deviceInfo = getDeviceInfo(for: device.deviceId)
|
||||
|
||||
let isSessionVerified = deviceInfo?.trustLevel.isVerified ?? false
|
||||
|
||||
@@ -95,20 +86,20 @@ class UserSessionsOverviewService: UserSessionsOverviewServiceProtocol {
|
||||
}
|
||||
|
||||
private func getDeviceInfo(for deviceId: String) -> MXDeviceInfo? {
|
||||
guard let userId = self.mxSession.myUserId else {
|
||||
guard let userId = mxSession.myUserId else {
|
||||
return nil
|
||||
}
|
||||
return self.mxSession.crypto.device(withDeviceId: deviceId, ofUser: userId)
|
||||
|
||||
return mxSession.crypto.device(withDeviceId: deviceId, ofUser: userId)
|
||||
}
|
||||
|
||||
private func userSessionsOverviewData(from devices: [MXDevice]) -> UserSessionsOverviewData {
|
||||
|
||||
let sortedDevices = devices.sorted { device1, device2 in
|
||||
device1.lastSeenTs > device2.lastSeenTs
|
||||
}
|
||||
|
||||
let allUserSessionInfo = sortedDevices.map { device in
|
||||
return self.userSessionInfo(from: device)
|
||||
return userSessionInfo(from: device)
|
||||
}
|
||||
|
||||
var currentSessionInfo: UserSessionInfo?
|
||||
@@ -118,7 +109,7 @@ class UserSessionsOverviewService: UserSessionsOverviewServiceProtocol {
|
||||
var otherSessionsInfo: [UserSessionInfo] = []
|
||||
|
||||
for userSessionInfo in allUserSessionInfo {
|
||||
if userSessionInfo.sessionId == self.mxSession.myDeviceId {
|
||||
if userSessionInfo.sessionId == mxSession.myDeviceId {
|
||||
currentSessionInfo = userSessionInfo
|
||||
} else {
|
||||
otherSessionsInfo.append(userSessionInfo)
|
||||
|
||||
+5
-3
@@ -17,11 +17,10 @@
|
||||
import Foundation
|
||||
|
||||
class MockUserSessionsOverviewService: UserSessionsOverviewServiceProtocol {
|
||||
|
||||
var lastOverviewData: UserSessionsOverviewData
|
||||
|
||||
func fetchUserSessionsOverviewData(completion: @escaping (Result<UserSessionsOverviewData, Error>) -> Void) {
|
||||
completion(.success(self.lastOverviewData))
|
||||
completion(.success(lastOverviewData))
|
||||
}
|
||||
|
||||
func getOtherSession(sessionId: String) -> UserSessionInfo? {
|
||||
@@ -41,6 +40,9 @@ class MockUserSessionsOverviewService: UserSessionsOverviewServiceProtocol {
|
||||
UserSessionInfo(sessionId: "3", sessionName: "Android", deviceType: .mobile, isVerified: false, lastSeenIP: "3.0.0.3", lastSeenTimestamp: (Date().timeIntervalSince1970 - 10))
|
||||
]
|
||||
|
||||
self.lastOverviewData = UserSessionsOverviewData(currentSessionInfo: currentSessionInfo, unverifiedSessionsInfo: unverifiedSessionsInfo, inactiveSessionsInfo: inactiveSessionsInfo, otherSessionsInfo: otherSessionsInfo)
|
||||
lastOverviewData = UserSessionsOverviewData(currentSessionInfo: currentSessionInfo,
|
||||
unverifiedSessionsInfo: unverifiedSessionsInfo,
|
||||
inactiveSessionsInfo: inactiveSessionsInfo,
|
||||
otherSessionsInfo: otherSessionsInfo)
|
||||
}
|
||||
}
|
||||
|
||||
-2
@@ -17,7 +17,6 @@
|
||||
import Foundation
|
||||
|
||||
struct UserSessionsOverviewData {
|
||||
|
||||
let currentSessionInfo: UserSessionInfo?
|
||||
let unverifiedSessionsInfo: [UserSessionInfo]
|
||||
let inactiveSessionsInfo: [UserSessionInfo]
|
||||
@@ -25,7 +24,6 @@ struct UserSessionsOverviewData {
|
||||
}
|
||||
|
||||
protocol UserSessionsOverviewServiceProtocol {
|
||||
|
||||
var lastOverviewData: UserSessionsOverviewData { get }
|
||||
|
||||
func fetchUserSessionsOverviewData(completion: @escaping (Result<UserSessionsOverviewData, Error>) -> Void) -> Void
|
||||
|
||||
-1
@@ -20,7 +20,6 @@ import Combine
|
||||
@testable import RiotSwiftUI
|
||||
|
||||
class UserSessionsOverviewViewModelTests: XCTestCase {
|
||||
|
||||
var service: MockUserSessionsOverviewService!
|
||||
var viewModel: UserSessionsOverviewViewModelProtocol!
|
||||
var context: UserSessionsOverviewViewModelType.Context!
|
||||
|
||||
+5
-6
@@ -36,14 +36,13 @@ enum UserSessionsOverviewViewModelResult {
|
||||
// MARK: View
|
||||
|
||||
struct UserSessionsOverviewViewState: BindableState {
|
||||
|
||||
var unverifiedSessionsViewData: [UserSessionListItemViewData]
|
||||
|
||||
var inactiveSessionsViewData: [UserSessionListItemViewData]
|
||||
|
||||
var currentSessionViewData: UserSessionCardViewData?
|
||||
|
||||
var otherSessionsViewData: [UserSessionListItemViewData]
|
||||
var unverifiedSessionsViewData = [UserSessionListItemViewData]()
|
||||
|
||||
var inactiveSessionsViewData = [UserSessionListItemViewData]()
|
||||
|
||||
var otherSessionsViewData = [UserSessionListItemViewData]()
|
||||
|
||||
var showLoadingIndicator: Bool = false
|
||||
}
|
||||
|
||||
+23
-45
@@ -21,91 +21,63 @@ typealias UserSessionsOverviewViewModelType = StateStoreViewModel<UserSessionsOv
|
||||
UserSessionsOverviewViewAction>
|
||||
|
||||
class UserSessionsOverviewViewModel: UserSessionsOverviewViewModelType, UserSessionsOverviewViewModelProtocol {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private let userSessionsOverviewService: UserSessionsOverviewServiceProtocol
|
||||
|
||||
// MARK: Public
|
||||
|
||||
var completion: ((UserSessionsOverviewViewModelResult) -> Void)?
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(userSessionsOverviewService: UserSessionsOverviewServiceProtocol) {
|
||||
self.userSessionsOverviewService = userSessionsOverviewService
|
||||
|
||||
let initialViewState = UserSessionsOverviewViewState(unverifiedSessionsViewData: [], inactiveSessionsViewData: [], currentSessionViewData: nil, otherSessionsViewData: [])
|
||||
super.init(initialViewState: .init())
|
||||
|
||||
super.init(initialViewState: initialViewState)
|
||||
|
||||
self.updateViewState(with: userSessionsOverviewService.lastOverviewData)
|
||||
updateViewState(with: userSessionsOverviewService.lastOverviewData)
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
|
||||
override func process(viewAction: UserSessionsOverviewViewAction) {
|
||||
switch viewAction {
|
||||
case .viewAppeared:
|
||||
self.loadData()
|
||||
loadData()
|
||||
case .verifyCurrentSession:
|
||||
self.completion?(.verifyCurrentSession)
|
||||
completion?(.verifyCurrentSession)
|
||||
case .viewCurrentSessionDetails:
|
||||
guard let currentSessionInfo = userSessionsOverviewService.lastOverviewData.currentSessionInfo else {
|
||||
assertionFailure("currentSessionInfo should be present")
|
||||
return
|
||||
return
|
||||
}
|
||||
self.completion?(.showCurrentSessionOverview(sessionInfo: currentSessionInfo))
|
||||
completion?(.showCurrentSessionOverview(sessionInfo: currentSessionInfo))
|
||||
case .viewAllUnverifiedSessions:
|
||||
self.completion?(.showAllUnverifiedSessions)
|
||||
completion?(.showAllUnverifiedSessions)
|
||||
case .viewAllInactiveSessions:
|
||||
self.completion?(.showAllInactiveSessions)
|
||||
completion?(.showAllInactiveSessions)
|
||||
case .viewAllOtherSessions:
|
||||
self.completion?(.showAllOtherSessions)
|
||||
completion?(.showAllOtherSessions)
|
||||
case .tapUserSession(let sessionId):
|
||||
guard let sessionInfo = userSessionsOverviewService.getOtherSession(sessionId: sessionId) else {
|
||||
assertionFailure("missing session info")
|
||||
return
|
||||
}
|
||||
self.completion?(.showUserSessionOverview(sessionInfo: sessionInfo))
|
||||
completion?(.showUserSessionOverview(sessionInfo: sessionInfo))
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func updateViewState(with userSessionsViewData: UserSessionsOverviewData) {
|
||||
|
||||
let unverifiedSessionsViewData = self.userSessionListItemViewDataList(from: userSessionsViewData.unverifiedSessionsInfo)
|
||||
let inactiveSessionsViewData = self.userSessionListItemViewDataList(from: userSessionsViewData.inactiveSessionsInfo)
|
||||
|
||||
var currentSessionViewData: UserSessionCardViewData?
|
||||
|
||||
let otherSessionsViewData = self.userSessionListItemViewDataList(from: userSessionsViewData.otherSessionsInfo)
|
||||
|
||||
state.unverifiedSessionsViewData = userSessionsViewData.unverifiedSessionsInfo.asViewData()
|
||||
state.inactiveSessionsViewData = userSessionsViewData.inactiveSessionsInfo.asViewData()
|
||||
state.otherSessionsViewData = userSessionsViewData.otherSessionsInfo.asViewData()
|
||||
|
||||
if let currentSessionInfo = userSessionsViewData.currentSessionInfo {
|
||||
currentSessionViewData = UserSessionCardViewData(userSessionInfo: currentSessionInfo, isCurrentSessionDisplayMode: true)
|
||||
}
|
||||
|
||||
self.state.unverifiedSessionsViewData = unverifiedSessionsViewData
|
||||
self.state.inactiveSessionsViewData = inactiveSessionsViewData
|
||||
self.state.currentSessionViewData = currentSessionViewData
|
||||
self.state.otherSessionsViewData = otherSessionsViewData
|
||||
}
|
||||
|
||||
private func userSessionListItemViewDataList(from userSessionInfoList: [UserSessionInfo]) -> [UserSessionListItemViewData] {
|
||||
return userSessionInfoList.map {
|
||||
return UserSessionListItemViewData(userSessionInfo: $0)
|
||||
state.currentSessionViewData = UserSessionCardViewData(userSessionInfo: currentSessionInfo, isCurrentSessionDisplayMode: true)
|
||||
}
|
||||
}
|
||||
|
||||
private func loadData() {
|
||||
state.showLoadingIndicator = true
|
||||
|
||||
self.state.showLoadingIndicator = true
|
||||
|
||||
self.userSessionsOverviewService.fetchUserSessionsOverviewData { [weak self] result in
|
||||
userSessionsOverviewService.fetchUserSessionsOverviewData { [weak self] result in
|
||||
guard let self = self else {
|
||||
return
|
||||
}
|
||||
@@ -122,3 +94,9 @@ class UserSessionsOverviewViewModel: UserSessionsOverviewViewModelType, UserSess
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension Collection where Element == UserSessionInfo {
|
||||
func asViewData() -> [UserSessionListItemViewData] {
|
||||
map { UserSessionListItemViewData(userSessionInfo: $0) }
|
||||
}
|
||||
}
|
||||
|
||||
-1
@@ -17,7 +17,6 @@
|
||||
import Foundation
|
||||
|
||||
protocol UserSessionsOverviewViewModelProtocol {
|
||||
|
||||
var completion: ((UserSessionsOverviewViewModelResult) -> Void)? { get set }
|
||||
|
||||
var context: UserSessionsOverviewViewModelType.Context { get }
|
||||
|
||||
+3
-14
@@ -17,9 +17,6 @@
|
||||
import SwiftUI
|
||||
|
||||
struct UserSessionListItem: View {
|
||||
|
||||
// MARK: - Constants
|
||||
|
||||
private enum LayoutConstants {
|
||||
static let horizontalPadding: CGFloat = 15
|
||||
static let verticalPadding: CGFloat = 16
|
||||
@@ -27,23 +24,16 @@ struct UserSessionListItem: View {
|
||||
static let avatarRightMargin: CGFloat = 18
|
||||
}
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
@Environment(\.theme) private var theme: ThemeSwiftUI
|
||||
|
||||
// MARK: Public
|
||||
|
||||
let viewData: UserSessionListItemViewData
|
||||
|
||||
var onBackgroundTap: ((String) -> (Void))? = nil
|
||||
|
||||
// MARK: - Body
|
||||
|
||||
var body: some View {
|
||||
Button(action: { onBackgroundTap?(self.viewData.sessionId)
|
||||
}) {
|
||||
Button {
|
||||
onBackgroundTap?(viewData.sessionId)
|
||||
} label: {
|
||||
VStack(alignment: .leading, spacing: LayoutConstants.verticalPadding) {
|
||||
HStack(spacing: LayoutConstants.avatarRightMargin) {
|
||||
DeviceAvatarView(viewData: viewData.deviceAvatarViewData)
|
||||
@@ -74,7 +64,6 @@ struct UserSessionListItem: View {
|
||||
}
|
||||
|
||||
struct UserSessionListPreview: View {
|
||||
|
||||
let userSessionsOverviewService: UserSessionsOverviewServiceProtocol = MockUserSessionsOverviewService()
|
||||
|
||||
var body: some View {
|
||||
|
||||
+4
-13
@@ -18,14 +18,9 @@ import Foundation
|
||||
|
||||
/// View data for UserSessionListItem
|
||||
struct UserSessionListItemViewData: Identifiable {
|
||||
|
||||
// MARK: - Constants
|
||||
|
||||
private static let userSessionNameFormatter = UserSessionNameFormatter()
|
||||
private static let lastActivityDateFormatter = UserSessionLastActivityFormatter()
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
|
||||
var id: String {
|
||||
return sessionId
|
||||
}
|
||||
@@ -38,8 +33,6 @@ struct UserSessionListItemViewData: Identifiable {
|
||||
|
||||
let deviceAvatarViewData: DeviceAvatarViewData
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(sessionId: String,
|
||||
sessionDisplayName: String?,
|
||||
deviceType: DeviceType,
|
||||
@@ -47,15 +40,14 @@ struct UserSessionListItemViewData: Identifiable {
|
||||
lastActivityDate: TimeInterval?) {
|
||||
|
||||
self.sessionId = sessionId
|
||||
self.sessionName = Self.userSessionNameFormatter.sessionName(deviceType: deviceType, sessionDisplayName: sessionDisplayName)
|
||||
self.sessionDetails = Self.buildSessionDetails(isVerified: isVerified, lastActivityDate: lastActivityDate)
|
||||
self.deviceAvatarViewData = DeviceAvatarViewData(deviceType: deviceType, isVerified: isVerified)
|
||||
sessionName = Self.userSessionNameFormatter.sessionName(deviceType: deviceType, sessionDisplayName: sessionDisplayName)
|
||||
sessionDetails = Self.buildSessionDetails(isVerified: isVerified, lastActivityDate: lastActivityDate)
|
||||
deviceAvatarViewData = DeviceAvatarViewData(deviceType: deviceType, isVerified: isVerified)
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private static func buildSessionDetails(isVerified: Bool, lastActivityDate: TimeInterval?) -> String {
|
||||
|
||||
let sessionDetailsString: String
|
||||
|
||||
let sessionStatusText = isVerified ? VectorL10n.userSessionVerifiedShort : VectorL10n.userSessionUnverifiedShort
|
||||
@@ -77,7 +69,6 @@ struct UserSessionListItemViewData: Identifiable {
|
||||
}
|
||||
|
||||
extension UserSessionListItemViewData {
|
||||
|
||||
init(userSessionInfo: UserSessionInfo) {
|
||||
self.init(sessionId: userSessionInfo.sessionId, sessionDisplayName: userSessionInfo.sessionName, deviceType: userSessionInfo.deviceType, isVerified: userSessionInfo.isVerified, lastActivityDate: userSessionInfo.lastSeenTimestamp)
|
||||
}
|
||||
|
||||
+1
-8
@@ -17,11 +17,6 @@
|
||||
import SwiftUI
|
||||
|
||||
struct UserSessionsOverview: View {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
@Environment(\.theme) private var theme: ThemeSwiftUI
|
||||
|
||||
@ViewBuilder
|
||||
@@ -52,7 +47,6 @@ struct UserSessionsOverview: View {
|
||||
|
||||
var body: some View {
|
||||
ScrollView {
|
||||
|
||||
// Security recommendations section
|
||||
if viewModel.viewState.unverifiedSessionsViewData.isEmpty == false || viewModel.viewState.inactiveSessionsViewData.isEmpty == false {
|
||||
|
||||
@@ -64,7 +58,7 @@ struct UserSessionsOverview: View {
|
||||
|
||||
// Other sessions section
|
||||
if viewModel.viewState.otherSessionsViewData.isEmpty == false {
|
||||
self.otherSessionsSection
|
||||
otherSessionsSection
|
||||
}
|
||||
}
|
||||
.background(theme.colors.system.ignoresSafeArea())
|
||||
@@ -77,7 +71,6 @@ struct UserSessionsOverview: View {
|
||||
}
|
||||
|
||||
private var otherSessionsSection: some View {
|
||||
|
||||
SwiftUI.Section {
|
||||
// Device list
|
||||
LazyVStack(spacing: 0) {
|
||||
|
||||
Reference in New Issue
Block a user