mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 12:07:55 +00:00
UX Update for user profile screen and room member details (#2822)
This commit is contained in:
@@ -63,6 +63,7 @@
|
||||
"action_leave_room" = "Leave room";
|
||||
"action_manage_account" = "Manage account";
|
||||
"action_manage_devices" = "Manage devices";
|
||||
"action_message" = "Message";
|
||||
"action_next" = "Next";
|
||||
"action_no" = "No";
|
||||
"action_not_now" = "Not now";
|
||||
|
||||
@@ -176,6 +176,14 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
private func presentCallScreen(roomID: String) async {
|
||||
guard let roomProxy = await userSession.clientProxy.roomForIdentifier(roomID) else {
|
||||
return
|
||||
}
|
||||
|
||||
actionsSubject.send(.presentCallScreen(roomProxy: roomProxy))
|
||||
}
|
||||
|
||||
private func handleRoomRoute(roomID: String, focussedEventID: String? = nil, animated: Bool) async {
|
||||
guard roomID == self.roomID else { fatalError("Navigation route doesn't belong to this room flow.") }
|
||||
|
||||
@@ -1064,6 +1072,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
stateMachine.tryEvent(.presentUserProfile(userID: userID))
|
||||
case .openDirectChat(let roomID):
|
||||
stateMachine.tryEvent(.startChildFlow(roomID: roomID, entryPoint: .room))
|
||||
case .startCall(let roomID):
|
||||
Task { await self.presentCallScreen(roomID: roomID) }
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
@@ -1087,6 +1097,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
switch action {
|
||||
case .openDirectChat(let roomID):
|
||||
stateMachine.tryEvent(.startChildFlow(roomID: roomID, entryPoint: .room))
|
||||
case .startCall(let roomID):
|
||||
Task { await self.presentCallScreen(roomID: roomID) }
|
||||
case .dismiss:
|
||||
break // Not supported when pushed.
|
||||
}
|
||||
@@ -1094,9 +1106,12 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
.store(in: &cancellables)
|
||||
|
||||
// Replace the RoomMemberDetailsScreen without any animation.
|
||||
navigationStackCoordinator.pop(animated: false)
|
||||
navigationStackCoordinator.push(coordinator, animated: false) { [weak self] in
|
||||
self?.stateMachine.tryEvent(.dismissUserProfile)
|
||||
// If this pop and push happens before the previous navigation is completed it might break screen presentation logic
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(500)) {
|
||||
self.navigationStackCoordinator.pop(animated: false)
|
||||
self.navigationStackCoordinator.push(coordinator, animated: false) { [weak self] in
|
||||
self?.stateMachine.tryEvent(.dismissUserProfile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -238,10 +238,10 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
stateMachine.processEvent(.showUserProfileScreen(userID: userID), userInfo: .init(animated: animated))
|
||||
case .genericCallLink(let url):
|
||||
navigationSplitCoordinator.setSheetCoordinator(GenericCallLinkCoordinator(parameters: .init(url: url)), animated: animated)
|
||||
case .oidcCallback:
|
||||
break
|
||||
case .settings, .chatBackupSettings:
|
||||
settingsFlowCoordinator.handleAppRoute(appRoute, animated: animated)
|
||||
case .oidcCallback:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -595,6 +595,14 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
navigationSplitCoordinator.setSheetCoordinator(callScreenCoordinator, animated: true)
|
||||
}
|
||||
|
||||
private func presentCallScreen(roomID: String) async {
|
||||
guard let roomProxy = await userSession.clientProxy.roomForIdentifier(roomID) else {
|
||||
return
|
||||
}
|
||||
|
||||
presentCallScreen(roomProxy: roomProxy)
|
||||
}
|
||||
|
||||
// MARK: Secure backup confirmation
|
||||
|
||||
private func presentSecureBackupLogoutConfirmationScreen() {
|
||||
@@ -706,6 +714,8 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
case .openDirectChat(let roomID):
|
||||
navigationSplitCoordinator.setSheetCoordinator(nil)
|
||||
stateMachine.processEvent(.selectRoom(roomID: roomID, entryPoint: .room))
|
||||
case .startCall(let roomID):
|
||||
Task { await self.presentCallScreen(roomID: roomID) }
|
||||
case .dismiss:
|
||||
navigationSplitCoordinator.setSheetCoordinator(nil)
|
||||
}
|
||||
|
||||
@@ -160,6 +160,8 @@ internal enum L10n {
|
||||
internal static var actionManageAccount: String { return L10n.tr("Localizable", "action_manage_account") }
|
||||
/// Manage devices
|
||||
internal static var actionManageDevices: String { return L10n.tr("Localizable", "action_manage_devices") }
|
||||
/// Message
|
||||
internal static var actionMessage: String { return L10n.tr("Localizable", "action_message") }
|
||||
/// Next
|
||||
internal static var actionNext: String { return L10n.tr("Localizable", "action_next") }
|
||||
/// No
|
||||
|
||||
@@ -22,19 +22,22 @@ struct FormActionButtonStyle: ButtonStyle {
|
||||
let title: String
|
||||
|
||||
func makeBody(configuration: Configuration) -> some View {
|
||||
VStack(spacing: 8) {
|
||||
VStack(spacing: 4) {
|
||||
configuration.label
|
||||
.buttonStyle(.plain)
|
||||
.foregroundColor(.compound.textPrimary)
|
||||
.scaledFrame(size: 54)
|
||||
.background {
|
||||
RoundedRectangle(cornerRadius: 16)
|
||||
.fill(configuration.isPressed ? Color.compound.bgSubtlePrimary : .compound.bgCanvasDefaultLevel1)
|
||||
}
|
||||
.foregroundColor(.compound.iconSecondary)
|
||||
.scaledFrame(size: 24)
|
||||
|
||||
Text(title)
|
||||
.foregroundColor(.compound.textSecondary)
|
||||
.font(.compound.bodyMD)
|
||||
.foregroundColor(.compound.textPrimary)
|
||||
.font(.compound.bodyLG)
|
||||
}
|
||||
.padding(.horizontal, 4)
|
||||
.padding(.vertical, 8)
|
||||
.frame(maxWidth: .infinity)
|
||||
.background {
|
||||
RoundedRectangle(cornerRadius: 14)
|
||||
.fill(configuration.isPressed ? Color.compound.bgSubtlePrimary : .compound.bgCanvasDefaultLevel1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,6 +106,10 @@ struct AvatarHeaderView<Footer: View>: View {
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .center)
|
||||
.listRowBackground(Color.clear)
|
||||
.listRowInsets(EdgeInsets(top: 11,
|
||||
leading: 0,
|
||||
bottom: 11,
|
||||
trailing: 0))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ struct RoomDetailsScreen: View {
|
||||
|
||||
@ViewBuilder
|
||||
private var headerSectionShortcuts: some View {
|
||||
HStack(spacing: 32) {
|
||||
HStack(spacing: 8) {
|
||||
ForEach(context.viewState.shortcuts, id: \.self) { shortcut in
|
||||
switch shortcut {
|
||||
case .mute:
|
||||
|
||||
+3
@@ -29,6 +29,7 @@ struct RoomMemberDetailsScreenCoordinatorParameters {
|
||||
enum RoomMemberDetailsScreenCoordinatorAction {
|
||||
case openUserProfile
|
||||
case openDirectChat(roomID: String)
|
||||
case startCall(roomID: String)
|
||||
}
|
||||
|
||||
final class RoomMemberDetailsScreenCoordinator: CoordinatorProtocol {
|
||||
@@ -59,6 +60,8 @@ final class RoomMemberDetailsScreenCoordinator: CoordinatorProtocol {
|
||||
actionsSubject.send(.openUserProfile)
|
||||
case .openDirectChat(let roomID):
|
||||
actionsSubject.send(.openDirectChat(roomID: roomID))
|
||||
case .startCall(let roomID):
|
||||
actionsSubject.send(.startCall(roomID: roomID))
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
@@ -19,6 +19,7 @@ import Foundation
|
||||
enum RoomMemberDetailsScreenViewModelAction {
|
||||
case openUserProfile
|
||||
case openDirectChat(roomID: String)
|
||||
case startCall(roomID: String)
|
||||
}
|
||||
|
||||
struct RoomMemberDetailsScreenViewState: BindableState {
|
||||
@@ -26,6 +27,7 @@ struct RoomMemberDetailsScreenViewState: BindableState {
|
||||
var memberDetails: RoomMemberDetails?
|
||||
var isOwnMemberDetails = false
|
||||
var isProcessingIgnoreRequest = false
|
||||
var dmRoomID: String?
|
||||
|
||||
var bindings: RoomMemberDetailsScreenViewStateBindings
|
||||
}
|
||||
@@ -83,6 +85,7 @@ enum RoomMemberDetailsScreenViewAction {
|
||||
case unignoreConfirmed
|
||||
case displayAvatar
|
||||
case openDirectChat
|
||||
case startCall(roomID: String)
|
||||
}
|
||||
|
||||
enum RoomMemberDetailsScreenError: Hashable {
|
||||
|
||||
+8
@@ -61,6 +61,12 @@ class RoomMemberDetailsScreenViewModel: RoomMemberDetailsScreenViewModelType, Ro
|
||||
roomMemberProxy = member
|
||||
state.memberDetails = RoomMemberDetails(withProxy: member)
|
||||
state.isOwnMemberDetails = member.userID == roomProxy.ownUserID
|
||||
switch await clientProxy.directRoomForUserID(member.userID) {
|
||||
case .success(let roomID):
|
||||
state.dmRoomID = roomID
|
||||
case .failure:
|
||||
break
|
||||
}
|
||||
case .failure(let error):
|
||||
MXLog.warning("Failed to find member: \(error)")
|
||||
actionsSubject.send(.openUserProfile)
|
||||
@@ -91,6 +97,8 @@ class RoomMemberDetailsScreenViewModel: RoomMemberDetailsScreenViewModelType, Ro
|
||||
Task { await displayFullScreenAvatar() }
|
||||
case .openDirectChat:
|
||||
Task { await openDirectChat() }
|
||||
case .startCall(let roomID):
|
||||
actionsSubject.send(.startCall(roomID: roomID))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+41
-22
@@ -25,7 +25,6 @@ struct RoomMemberDetailsScreen: View {
|
||||
headerSection
|
||||
|
||||
if context.viewState.memberDetails != nil, !context.viewState.isOwnMemberDetails {
|
||||
directChatSection
|
||||
blockUserSection
|
||||
}
|
||||
}
|
||||
@@ -39,6 +38,38 @@ struct RoomMemberDetailsScreen: View {
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
@ViewBuilder
|
||||
private var otherUserFooter: some View {
|
||||
HStack(spacing: 8) {
|
||||
if context.viewState.memberDetails != nil, !context.viewState.isOwnMemberDetails {
|
||||
Button {
|
||||
context.send(viewAction: .openDirectChat)
|
||||
} label: {
|
||||
CompoundIcon(\.chat)
|
||||
}
|
||||
.buttonStyle(FormActionButtonStyle(title: L10n.commonMessage))
|
||||
.accessibilityIdentifier(A11yIdentifiers.roomMemberDetailsScreen.directChat)
|
||||
}
|
||||
|
||||
if let roomID = context.viewState.dmRoomID {
|
||||
Button {
|
||||
context.send(viewAction: .startCall(roomID: roomID))
|
||||
} label: {
|
||||
CompoundIcon(\.videoCall)
|
||||
}
|
||||
.buttonStyle(FormActionButtonStyle(title: L10n.actionCall))
|
||||
}
|
||||
|
||||
if let permalink = context.viewState.memberDetails?.permalink {
|
||||
ShareLink(item: permalink) {
|
||||
CompoundIcon(\.shareIos)
|
||||
}
|
||||
.buttonStyle(FormActionButtonStyle(title: L10n.actionShare))
|
||||
}
|
||||
}
|
||||
.padding(.top, 32)
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var headerSection: some View {
|
||||
if let memberDetails = context.viewState.memberDetails {
|
||||
@@ -47,15 +78,7 @@ struct RoomMemberDetailsScreen: View {
|
||||
imageProvider: context.imageProvider) {
|
||||
context.send(viewAction: .displayAvatar)
|
||||
} footer: {
|
||||
if let permalink = memberDetails.permalink {
|
||||
HStack(spacing: 32) {
|
||||
ShareLink(item: permalink) {
|
||||
CompoundIcon(\.shareIos)
|
||||
}
|
||||
.buttonStyle(FormActionButtonStyle(title: L10n.actionShare))
|
||||
}
|
||||
.padding(.top, 32)
|
||||
}
|
||||
otherUserFooter
|
||||
}
|
||||
} else {
|
||||
AvatarHeaderView(user: UserProfileProxy(userID: context.viewState.userID),
|
||||
@@ -65,17 +88,6 @@ struct RoomMemberDetailsScreen: View {
|
||||
}
|
||||
}
|
||||
|
||||
private var directChatSection: some View {
|
||||
Section {
|
||||
ListRow(label: .default(title: L10n.commonDirectChat,
|
||||
icon: \.chat),
|
||||
kind: .button {
|
||||
context.send(viewAction: .openDirectChat)
|
||||
})
|
||||
.accessibilityIdentifier(A11yIdentifiers.roomMemberDetailsScreen.directChat)
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var blockUserSection: some View {
|
||||
if let memberDetails = context.viewState.memberDetails {
|
||||
@@ -134,9 +146,16 @@ struct RoomMemberDetailsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
let roomProxyMock = RoomProxyMock(with: .init(name: ""))
|
||||
roomProxyMock.getMemberUserIDReturnValue = .success(member)
|
||||
|
||||
let clientProxyMock = ClientProxyMock(.init())
|
||||
|
||||
// to avoid mock the call state for the account owner test case
|
||||
if member.userID != RoomMemberProxyMock.mockMe.userID {
|
||||
clientProxyMock.directRoomForUserIDReturnValue = .success("roomID")
|
||||
}
|
||||
|
||||
return RoomMemberDetailsScreenViewModel(userID: member.userID,
|
||||
roomProxy: roomProxyMock,
|
||||
clientProxy: ClientProxyMock(.init()),
|
||||
clientProxy: clientProxyMock,
|
||||
mediaProvider: MockMediaProvider(),
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||
analytics: ServiceLocator.shared.analytics)
|
||||
|
||||
@@ -28,6 +28,7 @@ struct UserProfileScreenCoordinatorParameters {
|
||||
|
||||
enum UserProfileScreenCoordinatorAction {
|
||||
case openDirectChat(roomID: String)
|
||||
case startCall(roomID: String)
|
||||
case dismiss
|
||||
}
|
||||
|
||||
@@ -57,6 +58,8 @@ final class UserProfileScreenCoordinator: CoordinatorProtocol {
|
||||
switch action {
|
||||
case .openDirectChat(let roomID):
|
||||
actionsSubject.send(.openDirectChat(roomID: roomID))
|
||||
case .startCall(let roomID):
|
||||
actionsSubject.send(.startCall(roomID: roomID))
|
||||
case .dismiss:
|
||||
actionsSubject.send(.dismiss)
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import Foundation
|
||||
|
||||
enum UserProfileScreenViewModelAction {
|
||||
case openDirectChat(roomID: String)
|
||||
case startCall(roomID: String)
|
||||
case dismiss
|
||||
}
|
||||
|
||||
@@ -28,6 +29,7 @@ struct UserProfileScreenViewState: BindableState {
|
||||
|
||||
var userProfile: UserProfileProxy?
|
||||
var permalink: URL?
|
||||
var dmRoomID: String?
|
||||
|
||||
var bindings: UserProfileScreenViewStateBindings
|
||||
}
|
||||
@@ -42,6 +44,7 @@ struct UserProfileScreenViewStateBindings {
|
||||
enum UserProfileScreenViewAction {
|
||||
case displayAvatar
|
||||
case openDirectChat
|
||||
case startCall(roomID: String)
|
||||
case dismiss
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,12 @@ class UserProfileScreenViewModel: UserProfileScreenViewModelType, UserProfileScr
|
||||
case .success(let userProfile):
|
||||
state.userProfile = userProfile
|
||||
state.permalink = (try? matrixToUserPermalink(userId: userID)).flatMap(URL.init(string:))
|
||||
switch await clientProxy.directRoomForUserID(userProfile.userID) {
|
||||
case .success(let roomID):
|
||||
state.dmRoomID = roomID
|
||||
case .failure:
|
||||
break
|
||||
}
|
||||
case .failure(let error):
|
||||
state.bindings.alertInfo = .init(id: .unknown)
|
||||
MXLog.error("Failed to find user profile: \(error)")
|
||||
@@ -81,6 +87,8 @@ class UserProfileScreenViewModel: UserProfileScreenViewModelType, UserProfileScr
|
||||
Task { await displayFullScreenAvatar() }
|
||||
case .openDirectChat:
|
||||
Task { await openDirectChat() }
|
||||
case .startCall(let roomID):
|
||||
actionsSubject.send(.startCall(roomID: roomID))
|
||||
case .dismiss:
|
||||
actionsSubject.send(.dismiss)
|
||||
}
|
||||
|
||||
@@ -23,10 +23,6 @@ struct UserProfileScreen: View {
|
||||
var body: some View {
|
||||
Form {
|
||||
headerSection
|
||||
|
||||
if context.viewState.userProfile != nil, !context.viewState.isOwnUser {
|
||||
directChatSection
|
||||
}
|
||||
}
|
||||
.compoundList()
|
||||
.navigationTitle(L10n.screenRoomMemberDetailsTitle)
|
||||
@@ -39,6 +35,38 @@ struct UserProfileScreen: View {
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
@ViewBuilder
|
||||
private var otherUserFooter: some View {
|
||||
HStack(spacing: 8) {
|
||||
if context.viewState.userProfile != nil, !context.viewState.isOwnUser {
|
||||
Button {
|
||||
context.send(viewAction: .openDirectChat)
|
||||
} label: {
|
||||
CompoundIcon(\.chat)
|
||||
}
|
||||
.buttonStyle(FormActionButtonStyle(title: L10n.commonMessage))
|
||||
.accessibilityIdentifier(A11yIdentifiers.roomMemberDetailsScreen.directChat)
|
||||
}
|
||||
|
||||
if let roomID = context.viewState.dmRoomID {
|
||||
Button {
|
||||
context.send(viewAction: .startCall(roomID: roomID))
|
||||
} label: {
|
||||
CompoundIcon(\.videoCall)
|
||||
}
|
||||
.buttonStyle(FormActionButtonStyle(title: L10n.actionCall))
|
||||
}
|
||||
|
||||
if let permalink = context.viewState.permalink {
|
||||
ShareLink(item: permalink) {
|
||||
CompoundIcon(\.shareIos)
|
||||
}
|
||||
.buttonStyle(FormActionButtonStyle(title: L10n.actionShare))
|
||||
}
|
||||
}
|
||||
.padding(.top, 32)
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var headerSection: some View {
|
||||
if let userProfile = context.viewState.userProfile {
|
||||
@@ -47,15 +75,7 @@ struct UserProfileScreen: View {
|
||||
imageProvider: context.imageProvider) {
|
||||
context.send(viewAction: .displayAvatar)
|
||||
} footer: {
|
||||
if let permalink = context.viewState.permalink {
|
||||
HStack(spacing: 32) {
|
||||
ShareLink(item: permalink) {
|
||||
CompoundIcon(\.shareIos)
|
||||
}
|
||||
.buttonStyle(FormActionButtonStyle(title: L10n.actionShare))
|
||||
}
|
||||
.padding(.top, 32)
|
||||
}
|
||||
otherUserFooter
|
||||
}
|
||||
} else {
|
||||
AvatarHeaderView(user: UserProfileProxy(userID: context.viewState.userID),
|
||||
@@ -65,17 +85,6 @@ struct UserProfileScreen: View {
|
||||
}
|
||||
}
|
||||
|
||||
private var directChatSection: some View {
|
||||
Section {
|
||||
ListRow(label: .default(title: L10n.commonDirectChat,
|
||||
icon: \.chat),
|
||||
kind: .button {
|
||||
context.send(viewAction: .openDirectChat)
|
||||
})
|
||||
.accessibilityIdentifier(A11yIdentifiers.roomMemberDetailsScreen.directChat)
|
||||
}
|
||||
}
|
||||
|
||||
@ToolbarContentBuilder
|
||||
private var toolbar: some ToolbarContent {
|
||||
if context.viewState.isPresentedModally {
|
||||
@@ -104,11 +113,15 @@ struct UserProfileScreen_Previews: PreviewProvider, TestablePreview {
|
||||
}
|
||||
|
||||
static func makeViewModel(userID: String) -> UserProfileScreenViewModel {
|
||||
UserProfileScreenViewModel(userID: userID,
|
||||
isPresentedModally: false,
|
||||
clientProxy: ClientProxyMock(.init()),
|
||||
mediaProvider: MockMediaProvider(),
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||
analytics: ServiceLocator.shared.analytics)
|
||||
let clientProxyMock = ClientProxyMock(.init())
|
||||
if userID != RoomMemberProxyMock.mockMe.userID {
|
||||
clientProxyMock.directRoomForUserIDReturnValue = .success("roomID")
|
||||
}
|
||||
return UserProfileScreenViewModel(userID: userID,
|
||||
isPresentedModally: false,
|
||||
clientProxy: clientProxyMock,
|
||||
mediaProvider: MockMediaProvider(),
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||
analytics: ServiceLocator.shared.analytics)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c2eddb648a0298d35c9ed697aefaf89ce609f58c0d3ba9fdb0b2c1cd892594fd
|
||||
size 123637
|
||||
oid sha256:a5b9f5e0db05f4beda9e4d7cd08c8a353a85c64a21988c6c9ec71956b4444eae
|
||||
size 124255
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c2eddb648a0298d35c9ed697aefaf89ce609f58c0d3ba9fdb0b2c1cd892594fd
|
||||
size 123637
|
||||
oid sha256:a5b9f5e0db05f4beda9e4d7cd08c8a353a85c64a21988c6c9ec71956b4444eae
|
||||
size 124255
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e02beede3f2a35a44b403435c8634d20cc9a120141dd7973f158c3c755914247
|
||||
size 73050
|
||||
oid sha256:8c04d77ffec96df07cbbe034347a267f56c832d1fccac0d8fde0c9a592525349
|
||||
size 73216
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e02beede3f2a35a44b403435c8634d20cc9a120141dd7973f158c3c755914247
|
||||
size 73050
|
||||
oid sha256:8c04d77ffec96df07cbbe034347a267f56c832d1fccac0d8fde0c9a592525349
|
||||
size 73216
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a70bb5fdd345057464613c8d8d915bb30aeaf340b709299270c100482b4bf4aa
|
||||
size 80297
|
||||
oid sha256:0fea52f76951ad2252887444caeb73ca9c8998275cdafca51e0aef97cdf745b9
|
||||
size 81212
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a70bb5fdd345057464613c8d8d915bb30aeaf340b709299270c100482b4bf4aa
|
||||
size 80297
|
||||
oid sha256:0fea52f76951ad2252887444caeb73ca9c8998275cdafca51e0aef97cdf745b9
|
||||
size 81212
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:cf3ba4bb678c7c5c3c5abbef122cf97eef5df819470812f501b76528beb12ddb
|
||||
size 35416
|
||||
oid sha256:b07080055d6ff55e0e2d326f9696d5bb05240702251a881052c63fd0595e102c
|
||||
size 36488
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:cf3ba4bb678c7c5c3c5abbef122cf97eef5df819470812f501b76528beb12ddb
|
||||
size 35416
|
||||
oid sha256:b07080055d6ff55e0e2d326f9696d5bb05240702251a881052c63fd0595e102c
|
||||
size 36488
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:99457e77405391a3be5b12d4513053bc22ee38146b0a026480206d622b5340cb
|
||||
size 232976
|
||||
oid sha256:993bde979b9cf5177f1b04069cd5dbb2058fb699f1dd531aa872d3b413cb810c
|
||||
size 243685
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8cf3d6d752e771fca995ad3d7283fbee60bfd7614d22097f033b3bf1f91ab78b
|
||||
size 233824
|
||||
oid sha256:edbb5601a3b3dd48ff43910cad90b1cabff8ea99392d5e406c2ea645801b4b98
|
||||
size 235619
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b31fa22226801415c912eba75810f02d40ac49a6fd1a4381d626ea1bb2bfee0c
|
||||
size 174497
|
||||
oid sha256:53f61afa3672b847e50aee527a24c1cdf45b7892fc1155f5fe35e19459a87ddf
|
||||
size 180791
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:75751372beb8547f0a22636a16f494c48f850e8e2de3e663e3bf8b3c99380265
|
||||
size 295815
|
||||
oid sha256:9308508c97fe4beb9dfede048f625ee56cac2d51dba45eb98770eb55439406bd
|
||||
size 301330
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:dd8485c8079834b2346e203f6ce396ca7c8704d353fb34d9453804d7d72a6a47
|
||||
size 278745
|
||||
oid sha256:05e5b40e37fd79e246442ac554d1c9524aa69d79c5aa3b3f0c38ae083b8aeb52
|
||||
size 282353
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:78a38dcd6b66c838c6c3ec33098a11bc064d2c33f4b296973ad7b9f65c55248a
|
||||
size 227514
|
||||
oid sha256:8a84cd11210a1a2ff6ee4b263b6234db0506fa1ddcbf65b313a2a23f4073460d
|
||||
size 238709
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:512606e0e6220ff71d4fce5441021e85f0f30c7ec7f1f29c584700113c8da9d1
|
||||
size 179884
|
||||
oid sha256:962394bd9d8afb3061818822d1745e43bf79e1cce148fe40ec851bc901afe3cf
|
||||
size 181482
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:64fce215cb9b466276f55f01c04c6a32f11c2108c09a96123a6e8ff573900936
|
||||
size 158911
|
||||
oid sha256:3b090ad72c576f703f002b6ae5cbb5b143f491a856eca9b4c02c9bd99b3f2809
|
||||
size 160547
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:51267cc2b70adcbbeb6c5df6d7560c9a49c58437cb04ab31d6fd05b7d3ad7bf9
|
||||
size 114025
|
||||
oid sha256:d1d6105a1c59caf5c6e7edca31faa51667feabde732ef7c9951d2c35937c74cb
|
||||
size 114559
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8f87d0ddaf6ae6b287f75a4963a749e6350c185b850188b52ff4ad7d50cefa77
|
||||
size 210205
|
||||
oid sha256:d70f72e041f7e569fd99f7e8a63e62bbb92a2aaedf03cdbd67a158d9fa885145
|
||||
size 222061
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:58018bea77f7b28dfa0bbfe6bf0b16398bd159af2bd245f3d483eb1e99c68007
|
||||
size 196330
|
||||
oid sha256:eec17eea97add9dec4b238f458905ad40dcdc6f4d302bc3aca6f1f424a30bd3e
|
||||
size 198643
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c7625aa1976b07cc0759f2431f6a44ada887f3927c816be128a45d14642c25da
|
||||
size 152736
|
||||
oid sha256:79a57e83b5432cd57652f444c96af0bff54ab20b8fbca663e38261237acc2f2c
|
||||
size 153273
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:bee936322c7945f72ab11e079e26c367fd782ed883a05ec8c33da82385522ba6
|
||||
size 119262
|
||||
oid sha256:b59dc444120d040baba15dc5322e00acf10c8afeba97fddbae2aea31a88ff7bf
|
||||
size 120302
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8ec35e3ebcd15298f7d4f7e196c593bb7e23f4574c84bcd4c6f12567f1748c9a
|
||||
size 124211
|
||||
oid sha256:e69ee9a2b3e21dce64a57d5664173480b49b49e7e70952ccfb8a74837e7e4297
|
||||
size 127058
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f3877939ae180b3a1aae3b972de0d22f0f8eb27e46b23250349873e4090d4a52
|
||||
size 139981
|
||||
oid sha256:00ae153e9298e2171ed34572aa11db1e82faca3a2654c7fd3f76c0cf8509369e
|
||||
size 143045
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8ff200cd13ec2dd401b87a29c8e052d2cbd117abd97580d9c4ea013c8bd53f9a
|
||||
size 122432
|
||||
oid sha256:08b1f2e462d2b3fee6ef422fae0552195efb849dab814174d506f98a7a71a9fb
|
||||
size 124405
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3405f914a5d00764b852d8c5fcbb34b1f0a01adc84e629e1e15892a22425476a
|
||||
size 138854
|
||||
oid sha256:f47d3d5d886babe9176b2e1641eedd4102525648fe2e04e33db7db587b31d8d9
|
||||
size 142258
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:654f4ed07206e3b447a9eddd8fdd3656f9c619261656a59abd40cc83d8ccbe93
|
||||
size 154414
|
||||
oid sha256:41d004bf2eead94cd40c0ffbb344bc5b471a5aa811a4164b3c5c7513acbb28ad
|
||||
size 158265
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0a1a9da6128d63577051c4e5f8038f289a663684cbfebaac2b2d0d8cb0c25a9f
|
||||
size 68084
|
||||
oid sha256:f6f8727b80f45320b3e11a836115a0ee7236a6cf709833b364718679c574cdc5
|
||||
size 68755
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c4d8f29bf227dad82d7205b0a1de7cde3ff43f23ea75dd5b3baded488f26e1b9
|
||||
size 75340
|
||||
oid sha256:2c0a42eccfde2736e4ba39ecd0f130a5eea4aa08b824f21eef4d2edc4246b3a0
|
||||
size 75605
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2953ae81a69f0adeb0445b15616e2bf5ff54dac822c3ed2010ae9b4804322b95
|
||||
size 87984
|
||||
oid sha256:e3962a70728c6f3c4fd976e3d7d83badfe618094a13fa5f824b93a0bd9836ad3
|
||||
size 88597
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:380f908b5ea794fcd00d8e2ed30cdbc4e3d8b252e41492e03b0326186e0f049e
|
||||
size 70245
|
||||
oid sha256:17b2d906a1f52c2729b3c0f08f0abba2d1aaa188661df2c559ff6256bf2a6714
|
||||
size 71214
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2c0e26cb0231c9abd1d57f4d38d899d93a7a8ab32259b1221991b8ac88b3bcc6
|
||||
size 87550
|
||||
oid sha256:9552cad4fffb2f1ab0855ecfaa7b1f4968cb83a4501961665cb62f3988fc7054
|
||||
size 90543
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:826249c063050e52da83c81e34d0cee9023c536298df7b4db59057ead3f01c23
|
||||
size 100501
|
||||
oid sha256:4404ca231f490c501c7f134a57757fa7822ceb1a627a50316de829e24c72b7dc
|
||||
size 103982
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e42a43a6820048238e353125067d7efc2c32c77dc5633a50a2060b468eceeefb
|
||||
size 102403
|
||||
oid sha256:ca1cdb9c0f157fe4869240c986f884eebd0b5205812734e07ee034f392a4ca17
|
||||
size 103673
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a1cf3ad4bcc2e661971a8019be778757b640a85bed8debf7b6d31003325f2e05
|
||||
size 112587
|
||||
oid sha256:468214e5bb420cc0536b2b913fc3d45c8fcf795b45a4238a9bd54b9d69036b5b
|
||||
size 116265
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7f9378f6ee8fe77ec5038cf87a77fad3261a79c1addb785e04db12b8a9b59003
|
||||
size 105673
|
||||
oid sha256:248b93a7d9532693c451c0f7ffe0597b580f143ff9cc5e5ed638416d51d1f8e6
|
||||
size 107933
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b9a78887dd1a44c5d39c92c4e474c9bab5c5a858768bb990300cc40d80501561
|
||||
size 121404
|
||||
oid sha256:624bf89fe59faf35f169a18c06cf8985eda4d332c61dacd294cdcafb3a635b1a
|
||||
size 125279
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:bcb33f529761684c7564df444d2808ea72a1e6eee290c349fce6bda2e239344d
|
||||
size 54899
|
||||
oid sha256:9a08d07335e8af83c60875a53eda8da7c2e06591cdbe00a2447841c04eec982d
|
||||
size 55310
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d555f65dd5a7296e1da5798ed7ff710b6bbd652b2dc801d1aa4decbe3a064ba3
|
||||
size 62749
|
||||
oid sha256:61eebfd560410b170993785e0aae41d0e1560e1d0ee6576aadc873329674b30e
|
||||
size 66231
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7c7715d26bb104bb82c18ccc6ea4d363e833fe91f84219ecee57f2b66ca857c7
|
||||
size 57234
|
||||
oid sha256:4b86bd4439129b9132ad9a317c775b7758171d9391017fad47bc7e42173d93b8
|
||||
size 58167
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d0d240b2ab4fbaaa18ea8817dcaf6ac33725cc2f73dea06c372336288bc04a0a
|
||||
size 69921
|
||||
oid sha256:759ff727547a456b9d1a11b980351afa0fc0e353a167f90855d03d5c4b676807
|
||||
size 75796
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
The UX of the profile of other users has been updated.
|
||||
Reference in New Issue
Block a user