Skip to content

Commit

Permalink
knocking request cell
Browse files Browse the repository at this point in the history
  • Loading branch information
Velin92 committed Nov 14, 2024
1 parent 2cb7fac commit 189c677
Show file tree
Hide file tree
Showing 24 changed files with 267 additions and 36 deletions.
62 changes: 37 additions & 25 deletions ElementX.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@
"common_audio" = "Audio";
"common_blocked_users" = "Blocked users";
"common_bubbles" = "Bubbles";
"common_call_invite" = "Call in progress (unsupported)";
"common_call_started" = "Call started";
"common_chat_backup" = "Chat backup";
"common_copyright" = "Copyright";
Expand Down Expand Up @@ -366,6 +365,7 @@
"screen_join_room_knock_message_description" = "Message (optional)";
"screen_join_room_knock_sent_description" = "You will receive an invite to join the room if your request is accepted.";
"screen_join_room_knock_sent_title" = "Request to join sent";
"screen_knock_requests_list_decline_and_ban_action_title" = "Decline and ban";
"screen_pinned_timeline_empty_state_description" = "Press on a message and choose “%1$@” to include here.";
"screen_pinned_timeline_empty_state_headline" = "Pin important messages so that they can be easily discovered";
"screen_reset_encryption_password_error" = "An unknown error happened. Please check your account password is correct and try again.";
Expand Down
4 changes: 2 additions & 2 deletions ElementX/Sources/Generated/Strings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,6 @@ internal enum L10n {
internal static var commonBlockedUsers: String { return L10n.tr("Localizable", "common_blocked_users") }
/// Bubbles
internal static var commonBubbles: String { return L10n.tr("Localizable", "common_bubbles") }
/// Call in progress (unsupported)
internal static var commonCallInvite: String { return L10n.tr("Localizable", "common_call_invite") }
/// Call started
internal static var commonCallStarted: String { return L10n.tr("Localizable", "common_call_started") }
/// Chat backup
Expand Down Expand Up @@ -1290,6 +1288,8 @@ internal enum L10n {
}
/// Are you sure you want to turn off key storage and delete it?
internal static var screenKeyBackupDisableTitle: String { return L10n.tr("Localizable", "screen_key_backup_disable_title") }
/// Decline and ban
internal static var screenKnockRequestsListDeclineAndBanActionTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_decline_and_ban_action_title") }
/// This account has been deactivated.
internal static var screenLoginErrorDeactivatedAccount: String { return L10n.tr("Localizable", "screen_login_error_deactivated_account") }
/// Incorrect username and/or password
Expand Down
11 changes: 7 additions & 4 deletions ElementX/Sources/Other/Avatars.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,9 @@ enum UserAvatarSizeOnScreen {
case editUserDetails
case suggestions
case blockedUsers
case knockingUsersStack
case knockingUser
case knockingUsersBannerStack
case knockingUserBanner
case knockingUserList

var value: CGFloat {
switch self {
Expand Down Expand Up @@ -103,10 +104,12 @@ enum UserAvatarSizeOnScreen {
return 96
case .dmDetails:
return 75
case .knockingUsersStack:
case .knockingUsersBannerStack:
return 28
case .knockingUser:
case .knockingUserBanner:
return 32
case .knockingUserList:
return 52
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions ElementX/Sources/Other/SwiftUI/Views/StackedAvatarsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,13 @@ struct StackedAvatarsView_Previews: PreviewProvider, TestablePreview {
StackedAvatarsView(overlap: 16,
lineWidth: 2,
avatars: avatars,
avatarSize: .user(on: .knockingUsersStack),
avatarSize: .user(on: .knockingUsersBannerStack),
mediaProvider: MediaProviderMock())
StackedAvatarsView(overlap: 16,
lineWidth: 2,
shouldStackFromLast: true,
avatars: avatars,
avatarSize: .user(on: .knockingUsersStack),
avatarSize: .user(on: .knockingUsersBannerStack),
mediaProvider: MediaProviderMock())
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
//
// Copyright 2024 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only
// Please see LICENSE in the repository root for full details.
//

//
// Copyright 2022-2024 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only
// Please see LICENSE in the repository root for full details.
//

import Compound
import SwiftUI

struct KnockRequestCellInfo {
let userID: String
let displayName: String?
let avatarUrl: URL?
let timestamp: String?
let reason: String?
}

struct KnockRequestCell: View {
let cellInfo: KnockRequestCellInfo
let onAccept: (String) -> Void
let onDecline: (String) -> Void
let onDeclineAndBan: (String) -> Void
var mediaProvider: MediaProviderProtocol?

var body: some View {
VStack(spacing: 0) {
HStack(alignment: .top, spacing: 16) {
LoadableAvatarImage(url: cellInfo.avatarUrl,
name: cellInfo.displayName,
contentID: cellInfo.userID,
avatarSize: .user(on: .knockingUserList),
mediaProvider: mediaProvider)
VStack(alignment: .leading, spacing: 12) {
VStack(alignment: .leading, spacing: 0) {
HStack(alignment: .top, spacing: 0) {
Text(cellInfo.displayName ?? cellInfo.userID)
.font(.compound.bodyLGSemibold)
.foregroundStyle(.compound.textPrimary)
.frame(maxWidth: .infinity, alignment: .leading)
if let timestamp = cellInfo.timestamp {
Text(timestamp)
.font(.compound.bodySM)
.foregroundStyle(.compound.textSecondary)
}
}
if cellInfo.displayName != nil {
Text(cellInfo.userID)
.font(.compound.bodyMD)
.foregroundStyle(.compound.textSecondary)
}
}
if let reason = cellInfo.reason {
DisclosableText(text: reason)
}
actions
}
}
.padding(16)
Divider()
}
}

@ViewBuilder
private var actions: some View {
HStack(spacing: 16) {
Button(L10n.actionDecline) {
onDecline(cellInfo.userID)
}
.buttonStyle(.compound(.secondary))
Button(L10n.actionAccept) {
onAccept(cellInfo.userID)
}
.buttonStyle(.compound(.primary))
}
Button(L10n.screenKnockRequestsListDeclineAndBanActionTitle, role: .destructive) {
onDeclineAndBan(cellInfo.userID)
}
.buttonStyle(.compound(.plain))
.frame(maxWidth: .infinity)
.padding(.top, 12)
.padding(.bottom, 4)
}
}

private struct DisclosableText: View {
let text: String
@State private var collapsedHeight = CGFloat.zero
@State private var expandedHeight = CGFloat.zero
@State private var isExpanded = false

var body: some View {
HStack(alignment: .top, spacing: 4) {
Text(text)
.multilineTextAlignment(.leading)
.lineLimit(isExpanded ? nil : 3)
.font(.compound.bodyMD)
.foregroundStyle(.compound.textPrimary)
.frame(maxWidth: .infinity, alignment: .leading)
.onGeometryChange(for: CGFloat.self) { geometry in
geometry.size.height
} action: { newValue in
if !isExpanded {
collapsedHeight = newValue
}
}
.background {
Text(text)
.multilineTextAlignment(.leading)
.font(.compound.bodyMD)
.foregroundStyle(.compound.textPrimary)
.fixedSize(horizontal: false, vertical: true)
.onGeometryChange(for: CGFloat.self) { geometry in
geometry.size.height
} action: { newValue in
expandedHeight = newValue
}
.hidden()
}
Button {
withAnimation {
isExpanded.toggle()
}
} label: {
CompoundIcon(\.chevronDown, size: .medium, relativeTo: .compound.bodyMD)
}
.rotationEffect(.degrees(isExpanded ? 180 : 0))
.foregroundStyle(.compound.iconTertiary)
.opacity(collapsedHeight < expandedHeight ? 1 : 0)
.disabled(collapsedHeight >= expandedHeight)
}
}
}

struct KnockRequestCell_Previews: PreviewProvider, TestablePreview {
// swiftlint:disable:next line_length
static let aliceWithLongReason = KnockRequestCellInfo(userID: "@alice:matrix.org", displayName: "Alice", avatarUrl: nil, timestamp: "20 Nov 2024", reason: "Hello would like to join this room, also this is a very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long reason")

static let aliceWithShortReason = KnockRequestCellInfo(userID: "@alice:matrix.org", displayName: "Alice", avatarUrl: nil, timestamp: "20 Nov 2024", reason: "Hello, I am Alice and would like to join this room, please")

static let aliceWithNoReason = KnockRequestCellInfo(userID: "@alice:matrix.org", displayName: "Alice", avatarUrl: nil, timestamp: "20 Nov 2024", reason: nil)

static let aliceWithNoName = KnockRequestCellInfo(userID: "@alice:matrix.org", displayName: nil, avatarUrl: nil, timestamp: "20 Nov 2024", reason: nil)

static var previews: some View {
KnockRequestCell(cellInfo: aliceWithLongReason, onAccept: { _ in }, onDecline: { _ in }, onDeclineAndBan: { _ in })
.previewDisplayName("Long reason")
KnockRequestCell(cellInfo: aliceWithShortReason, onAccept: { _ in }, onDecline: { _ in }, onDeclineAndBan: { _ in })
.previewDisplayName("Short reason")
KnockRequestCell(cellInfo: aliceWithNoReason, onAccept: { _ in }, onDecline: { _ in }, onDeclineAndBan: { _ in })
.previewDisplayName("No reason")
KnockRequestCell(cellInfo: aliceWithNoName, onAccept: { _ in }, onDecline: { _ in }, onDeclineAndBan: { _ in })
.previewDisplayName("No name")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ private struct SingleKnockRequestBannerContent: View {
LoadableAvatarImage(url: request.avatarURL,
name: request.displayName,
contentID: request.userID,
avatarSize: .user(on: .knockingUser), mediaProvider: mediaProvider)
avatarSize: .user(on: .knockingUserBanner), mediaProvider: mediaProvider)
VStack(spacing: 0) {
HStack(alignment: .top, spacing: 0) {
Text(L10n.screenRoomSingleKnockRequestTitle(request.displayName ?? request.userID))
Expand Down Expand Up @@ -129,7 +129,7 @@ private struct MultipleKnockRequestsBannerContent: View {
var body: some View {
VStack(spacing: 14) {
HStack(spacing: 10) {
StackedAvatarsView(overlap: 16, lineWidth: 2, shouldStackFromLast: true, avatars: avatars, avatarSize: .user(on: .knockingUsersStack), mediaProvider: mediaProvider)
StackedAvatarsView(overlap: 16, lineWidth: 2, shouldStackFromLast: true, avatars: avatars, avatarSize: .user(on: .knockingUsersBannerStack), mediaProvider: mediaProvider)
HStack(alignment: .top, spacing: 0) {
Text(multipleKnockRequestsTitle)
.lineLimit(2)
Expand Down
6 changes: 6 additions & 0 deletions PreviewTests/Sources/GeneratedPreviewTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,12 @@ extension PreviewTests {
}
}

func test_knockRequestCell() {
for preview in KnockRequestCell_Previews._allPreviews {
assertSnapshots(matching: preview)
}
}

func test_knockRequestsBannerView() {
for preview in KnockRequestsBannerView_Previews._allPreviews {
assertSnapshots(matching: preview)
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 189c677

Please sign in to comment.