diff --git a/RiotSwiftUI/Modules/Common/Avatar/Model/Avatarable.swift b/RiotSwiftUI/Modules/Common/Avatar/Model/Avatarable.swift new file mode 100644 index 000000000..417e1e5ab --- /dev/null +++ b/RiotSwiftUI/Modules/Common/Avatar/Model/Avatarable.swift @@ -0,0 +1,34 @@ +// +// Copyright 2021 New Vector Ltd +// +// 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 Foundation + +/** + A protcol that any class or struct can conform to + so that it can easiy produce avatar data. + E.g. MXRoom, MxUser cna conform to this making it + easy to grab the avatar data for display. + */ +protocol Avatarable: AvatarInputType { } +extension Avatarable { + var avatarData: AvatarInput { + AvatarInput( + mxContentUri: mxContentUri, + matrixItemId: matrixItemId, + displayName: displayName + ) + } +} diff --git a/RiotSwiftUI/Modules/Template/SimpleProfileExample/Mock/TemplateMockUserService.swift b/RiotSwiftUI/Modules/Template/SimpleProfileExample/Mock/TemplateMockUserService.swift new file mode 100644 index 000000000..4bbf64b49 --- /dev/null +++ b/RiotSwiftUI/Modules/Template/SimpleProfileExample/Mock/TemplateMockUserService.swift @@ -0,0 +1,28 @@ +// +// Copyright 2021 New Vector Ltd +// +// 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 Foundation + +struct TemplateMockUserService: TemplateUserServiceType { + + static let example = TemplateMockUserService(userId: "123", displayName: "Alice", avatarUrl: "mx123@matrix.com", currentlyActive: true, lastActive: 123456) + + let userId: String + let displayName: String? + let avatarUrl: String? + let currentlyActive: Bool + let lastActive: UInt +} diff --git a/RiotSwiftUI/Modules/Template/SimpleProfileExample/Model/TemplateUserProfileViewState.swift b/RiotSwiftUI/Modules/Template/SimpleProfileExample/Model/TemplateUserProfileViewState.swift new file mode 100644 index 000000000..b5b308242 --- /dev/null +++ b/RiotSwiftUI/Modules/Template/SimpleProfileExample/Model/TemplateUserProfileViewState.swift @@ -0,0 +1,22 @@ +// +// Copyright 2021 New Vector Ltd +// +// 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 Foundation + +struct TemplateUserProfileViewState { + let avatar: AvatarInputType? + let displayName: String? +} diff --git a/RiotSwiftUI/Modules/Template/SimpleProfileExample/View/TemplateUserProfile.swift b/RiotSwiftUI/Modules/Template/SimpleProfileExample/View/TemplateUserProfile.swift new file mode 100644 index 000000000..3094158f3 --- /dev/null +++ b/RiotSwiftUI/Modules/Template/SimpleProfileExample/View/TemplateUserProfile.swift @@ -0,0 +1,50 @@ +// +// Copyright 2021 New Vector Ltd +// +// 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 + +@available(iOS 14.0, *) +struct TemplateUserProfile: View { + + @ObservedObject var viewModel: TemplateUserProfileViewModel + + var header: some View { + VStack { + if let avatar = viewModel.viewState.avatar { + HStack{ + Spacer() + AvatarImage(avatarData: avatar, size: .xxLarge) + Spacer() + } + } + Text(viewModel.viewState.displayName ?? "") + } + + } + var body: some View { + VectorForm { + header + } + } +} + +@available(iOS 14.0, *) +struct TemplateUserProfile_Previews: PreviewProvider { + static var previews: some View { + TemplateUserProfile(viewModel: TemplateUserProfileViewModel(userService: TemplateMockUserService.example)) + .addDependency(MockAvatarService.example) + } +} diff --git a/RiotSwiftUI/Modules/Template/SimpleProfileExample/ViewModel/TemplateUserProfileViewModel.swift b/RiotSwiftUI/Modules/Template/SimpleProfileExample/ViewModel/TemplateUserProfileViewModel.swift new file mode 100644 index 000000000..cfc0564a7 --- /dev/null +++ b/RiotSwiftUI/Modules/Template/SimpleProfileExample/ViewModel/TemplateUserProfileViewModel.swift @@ -0,0 +1,34 @@ +// +// Copyright 2021 New Vector Ltd +// +// 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 + +@available(iOS 14.0, *) +class TemplateUserProfileViewModel: ObservableObject { + + private let userService: TemplateUserServiceType + + @Published var viewState: TemplateUserProfileViewState + + private static func defaultState(userService: TemplateUserServiceType) -> TemplateUserProfileViewState { + return TemplateUserProfileViewState(avatar: userService.avatarData, displayName: userService.displayName) + } + + init(userService: TemplateUserServiceType, initialState: TemplateUserProfileViewState? = nil) { + self.userService = userService + self.viewState = initialState ?? Self.defaultState(userService: userService) + } +} diff --git a/RiotSwiftUI/Modules/Template/SimpleProfileExample/ViewModel/TemplateUserServiceType.swift b/RiotSwiftUI/Modules/Template/SimpleProfileExample/ViewModel/TemplateUserServiceType.swift new file mode 100644 index 000000000..87fb0e242 --- /dev/null +++ b/RiotSwiftUI/Modules/Template/SimpleProfileExample/ViewModel/TemplateUserServiceType.swift @@ -0,0 +1,34 @@ +// +// Copyright 2021 New Vector Ltd +// +// 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 Foundation + +protocol TemplateUserServiceType: Avatarable { + var userId: String { get } + var displayName: String? { get } + var avatarUrl: String? { get } + var currentlyActive: Bool { get } + var lastActive: UInt { get } +} + +extension TemplateUserServiceType { + var mxContentUri: String? { + avatarUrl + } + var matrixItemId: String { + userId + } +}