App polish part 3 (#1135)

- Add an animation to long press on messages.
- Make emojis bigger on the reactions picker screen.
- Remove quote menu action.
- Fix emoji picker handle overlapping focused search field.
- Update launch, splash and onboarding screens.
- Use elevation tokens in Forms.
- Move the cancel button on the Start Chat flow.
This commit is contained in:
Doug
2023-06-22 14:37:47 +01:00
committed by GitHub
parent e65a2d2431
commit f2312f6f70
47 changed files with 2054 additions and 5570 deletions
@@ -0,0 +1,96 @@
//
// Copyright 2023 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
struct LongPressWithFeedback: ViewModifier {
let action: () -> Void
@State private var isLongPressing = false
private let feedbackGenerator = UIImpactFeedbackGenerator(style: .heavy)
func body(content: Content) -> some View {
content
.scaleEffect(x: isLongPressing ? 0.93 : 1,
y: isLongPressing ? 0.93 : 1)
.animation(isLongPressing ? .spring(response: 0.8).delay(0.2) : .spring(response: 0.2),
value: isLongPressing)
.onLongPressGesture(minimumDuration: 0.25) {
action()
feedbackGenerator.impactOccurred()
} onPressingChanged: { isPressing in
isLongPressing = isPressing
if isPressing {
feedbackGenerator.prepare()
}
}
}
}
extension View {
func longPressWithFeedback(action: @escaping () -> Void) -> some View {
modifier(LongPressWithFeedback(action: action))
}
}
struct FakeContextMenu_Previews: PreviewProvider {
static var previews: some View { Preview() }
struct Preview: View {
private let viewModel = RoomScreenViewModel.mock
@State private var isPresentingSheet = false
var body: some View {
NavigationStack {
ScrollView {
VStack(alignment: .leading) {
mockBubble("This is a message from somebody with a couple of lines of text.")
.longPressWithFeedback { isPresentingSheet = true }
mockBubble("Short message")
.longPressWithFeedback { isPresentingSheet = true }
mockBubble("How are you today? The sun is shining here and its very hot ☀️☀️☀️")
.longPressWithFeedback { isPresentingSheet = true }
mockBubble("I'm a fake!")
.contextMenu {
Button("Copy") { }
Button("Reply") { }
Button("Remove") { }
}
}
.padding()
}
.navigationTitle("Work chat")
.navigationBarTitleDisplayMode(.inline)
}
.sheet(isPresented: $isPresentingSheet) {
Text("Long pressed!")
.presentationDetents([.medium])
}
.environmentObject(viewModel.context)
}
func mockBubble(_ body: String) -> some View {
Text(body)
.padding(.horizontal, 12)
.padding(.vertical, 4)
.background(Color.compound._bgBubbleOutgoing, in: RoundedRectangle(cornerRadius: 12))
.onTapGesture { /* Fix long press gesture blocking the scroll view */ }
}
}
}
@@ -21,8 +21,6 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
@EnvironmentObject private var context: RoomScreenViewModel.Context
@Environment(\.timelineGroupStyle) private var timelineGroupStyle
private let feedbackGenerator = UIImpactFeedbackGenerator(style: .heavy)
let timelineItem: EventBasedTimelineItemProtocol
@ViewBuilder let content: () -> Content
@@ -116,13 +114,8 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
}
// We need a tap gesture before this long one so that it doesn't
// steal away the gestures from the scroll view
.onLongPressGesture(minimumDuration: 0.25) {
.longPressWithFeedback {
context.send(viewAction: .timelineItemMenu(itemID: timelineItem.id))
feedbackGenerator.impactOccurred()
} onPressingChanged: { pressing in
if pressing {
feedbackGenerator.prepare()
}
}
.padding(.top, messageBubbleTopPadding)
}
@@ -33,7 +33,6 @@ struct TimelineItemMenuActions {
enum TimelineItemMenuAction: Identifiable, Hashable {
case copy
case edit
case quote
case copyPermalink
case redact
case reply
@@ -182,10 +181,6 @@ public struct TimelineItemMenu: View {
Button { send(action) } label: {
MenuLabel(title: L10n.actionEdit, systemImageName: "pencil.line")
}
case .quote:
Button { send(action) } label: {
MenuLabel(title: L10n.actionQuote, systemImageName: "quote.bubble")
}
case .copyPermalink:
Button { send(action) } label: {
MenuLabel(title: L10n.actionCopyLinkToMessage, systemImageName: "link")