Skip to content
Snippets Groups Projects
Commit ea6f5d40 authored by Kateryna Kostiuk's avatar Kateryna Kostiuk
Browse files

UI/UX: simplify animation in conversation

Use a opacity transition when switching between search
results and conversations.

Change-Id: I3e1904401b6e741dbd2a7378cb4a8347f775dfe7
parent 9f42e61d
Branches
No related tags found
No related merge requests found
...@@ -130,7 +130,7 @@ struct SmartListView: View, StateEmittingView { ...@@ -130,7 +130,7 @@ struct SmartListView: View, StateEmittingView {
@ViewBuilder @ViewBuilder
private func backgroundCover() -> some View { private func backgroundCover() -> some View {
Color(UIColor.black).opacity(coverBackgroundOpacity) Color(UIColor.black).opacity(coverBackgroundOpacity)
.ignoresSafeArea(edges: [.top, .bottom]) .ignoresSafeArea()
.allowsHitTesting(true) .allowsHitTesting(true)
.onTapGesture { .onTapGesture {
toggleAccountList() toggleAccountList()
......
...@@ -29,16 +29,30 @@ struct SmartListContentView: View { ...@@ -29,16 +29,30 @@ struct SmartListContentView: View {
@Binding var isSearchBarActive: Bool @Binding var isSearchBarActive: Bool
@SwiftUI.State var currentSearchBarStatus: Bool = false @SwiftUI.State var currentSearchBarStatus: Bool = false
@SwiftUI.State var isShowingScanner: Bool = false @SwiftUI.State var isShowingScanner: Bool = false
@SwiftUI.State var isShowingTopView: Bool = true
var body: some View { var body: some View {
let conversationsView = ConversationsView(model: model, stateEmitter: stateEmitter)
return ZStack {
Group {
if isSearchBarActive {
// Use ScrollView instead of List to prevent memory leaks when using a conversation model inside ForEach. // Use ScrollView instead of List to prevent memory leaks when using a conversation model inside ForEach.
ScrollView { ScrollView {
VStack(alignment: .leading) { VStack(alignment: .leading) {
publicDirectorySearchView publicDirectorySearchView
.frame(maxWidth: .infinity, alignment: .leading) .frame(maxWidth: .infinity, alignment: .leading)
.contentShape(Rectangle()) .contentShape(Rectangle())
if !hideTopView { conversationsSearchHeaderView
.hideRowSeparator()
.frame(maxWidth: .infinity, alignment: .leading)
.contentShape(Rectangle())
conversationsView
}
.padding(.horizontal, 15)
}
} else {
ScrollView {
VStack(alignment: .leading) {
if mode == .smartList { if mode == .smartList {
smartListTopView smartListTopView
.frame(maxWidth: .infinity, alignment: .leading) .frame(maxWidth: .infinity, alignment: .leading)
...@@ -48,16 +62,18 @@ struct SmartListContentView: View { ...@@ -48,16 +62,18 @@ struct SmartListContentView: View {
.frame(maxWidth: .infinity, alignment: .leading) .frame(maxWidth: .infinity, alignment: .leading)
.contentShape(Rectangle()) .contentShape(Rectangle())
} }
} conversationsView
conversationsSearchHeaderView
.hideRowSeparator()
.frame(maxWidth: .infinity, alignment: .leading)
.contentShape(Rectangle())
ConversationsView(model: model, stateEmitter: stateEmitter)
} }
.padding(.horizontal, 15) .padding(.horizontal, 15)
} }
.transition(.opacity) }
}
.transition(AnyTransition.asymmetric(
insertion: .opacity,
removal: .opacity.animation(.easeOut(duration: 0))
))
}
.animation(.easeIn(duration: 0.3), value: isSearchBarActive)
.onAppear { [weak model] in .onAppear { [weak model] in
guard let model = model else { return } guard let model = model else { return }
// If there was an active search before presenting the conversation, the search results should remain the same upon returning to the page. Otherwise, flickering will occur. // If there was an active search before presenting the conversation, the search results should remain the same upon returning to the page. Otherwise, flickering will occur.
...@@ -67,17 +83,6 @@ struct SmartListContentView: View { ...@@ -67,17 +83,6 @@ struct SmartListContentView: View {
} }
hideTopView = false hideTopView = false
} }
.onChange(of: isSearchBarActive) { _ in
if isSearchBarActive {
isShowingTopView = false
} else {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
withAnimation {
isShowingTopView = !isSearchBarActive
}
}
}
}
.listStyle(.plain) .listStyle(.plain)
.hideRowSeparator() .hideRowSeparator()
.sheet(isPresented: $requestsModel.requestViewOpened) { .sheet(isPresented: $requestsModel.requestViewOpened) {
...@@ -97,24 +102,21 @@ struct SmartListContentView: View { ...@@ -97,24 +102,21 @@ struct SmartListContentView: View {
} }
@ViewBuilder private var smartListTopView: some View { @ViewBuilder private var smartListTopView: some View {
if isShowingTopView && (requestsModel.unreadRequests > 0 || model.connectionState == .none) { if requestsModel.unreadRequests > 0 || model.connectionState == .none {
VStack { VStack {
if model.connectionState == .none { if model.connectionState == .none {
networkSettingsButton() networkSettingsButton()
.transition(.opacity)
} }
if requestsModel.unreadRequests > 0 { if requestsModel.unreadRequests > 0 {
RequestsIndicatorView(model: requestsModel) RequestsIndicatorView(model: requestsModel)
.onTapGesture { [weak requestsModel] in .onTapGesture { [weak requestsModel] in
requestsModel?.presentRequests() requestsModel?.presentRequests()
} }
.transition(.opacity)
} }
} }
.padding(.bottom) .padding(.bottom)
.listRowInsets(EdgeInsets(top: 0, leading: 15, bottom: 5, trailing: 15)) .listRowInsets(EdgeInsets(top: 0, leading: 15, bottom: 5, trailing: 15))
.hideRowSeparator() .hideRowSeparator()
.transition(.opacity)
} }
} }
...@@ -157,17 +159,12 @@ struct SmartListContentView: View { ...@@ -157,17 +159,12 @@ struct SmartListContentView: View {
} }
@ViewBuilder private var newMessageTopView: some View { @ViewBuilder private var newMessageTopView: some View {
if !isSearchBarActive {
VStack { VStack {
if isShowingTopView {
newChatOptions newChatOptions
} }
}
.padding(.bottom) .padding(.bottom)
.listRowInsets(EdgeInsets(top: 0, leading: 15, bottom: 5, trailing: 15)) .listRowInsets(EdgeInsets(top: 0, leading: 15, bottom: 5, trailing: 15))
.hideRowSeparator() .hideRowSeparator()
.transition(.opacity)
}
} }
@ViewBuilder private var newChatOptions: some View { @ViewBuilder private var newChatOptions: some View {
...@@ -201,10 +198,8 @@ struct SmartListContentView: View { ...@@ -201,10 +198,8 @@ struct SmartListContentView: View {
@ViewBuilder private var conversationsSearchHeaderView: some View { @ViewBuilder private var conversationsSearchHeaderView: some View {
VStack(alignment: .leading) { VStack(alignment: .leading) {
if isSearchBarActive {
Spacer() Spacer()
.frame(height: 10) .frame(height: 10)
}
if !model.searchQuery.isEmpty { if !model.searchQuery.isEmpty {
Text(L10n.Smartlist.conversations) Text(L10n.Smartlist.conversations)
.fontWeight(.semibold) .fontWeight(.semibold)
...@@ -222,9 +217,8 @@ struct SmartListContentView: View { ...@@ -222,9 +217,8 @@ struct SmartListContentView: View {
} }
@ViewBuilder private var publicDirectorySearchView: some View { @ViewBuilder private var publicDirectorySearchView: some View {
if isSearchBarActive {
VStack(alignment: .leading) { VStack(alignment: .leading) {
if mode == .smartList && !model.isSipAccount() { if !model.isSipAccount() {
newChatOptions newChatOptions
.padding(.vertical, 10) .padding(.vertical, 10)
} }
...@@ -243,7 +237,6 @@ struct SmartListContentView: View { ...@@ -243,7 +237,6 @@ struct SmartListContentView: View {
} }
} }
} }
}
@ViewBuilder private var searchResultView: some View { @ViewBuilder private var searchResultView: some View {
switch model.searchStatus { switch model.searchStatus {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment