ios: translucent bars in chat view (#4641)

* extend reverse list; disable clipping

* wallpaper - ignore safe area

* minor

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
This commit is contained in:
Arturs Krumins
2024-08-09 19:23:57 +03:00
committed by GitHub
parent bef1597fa1
commit cf7a16e857
4 changed files with 103 additions and 65 deletions
+68 -63
View File
@@ -47,65 +47,70 @@ struct ChatView: View {
@State private var showDeleteSelectedMessages: Bool = false
@State private var allowToDeleteSelectedMessagesForAll: Bool = false
@AppStorage(DEFAULT_TOOLBAR_MATERIAL) private var toolbarMaterial = ToolbarMaterial.bar.rawValue
var body: some View {
if #available(iOS 16.0, *) {
let v = viewBody
.scrollDismissesKeyboard(.immediately)
.keyboardPadding()
if (searchMode) {
v.toolbarBackground(.thinMaterial, for: .navigationBar)
} else {
v.toolbarBackground(.visible, for: .navigationBar)
}
viewBody
.scrollDismissesKeyboard(.immediately)
.keyboardPadding()
.toolbarBackground(.hidden, for: .navigationBar)
} else {
viewBody
}
}
@ViewBuilder
private var viewBody: some View {
let cInfo = chat.chatInfo
return VStack(spacing: 0) {
if searchMode {
searchToolbar()
ZStack {
let wallpaperImage = theme.wallpaper.type.image
let wallpaperType = theme.wallpaper.type
let backgroundColor = theme.wallpaper.background ?? wallpaperType.defaultBackgroundColor(theme.base, theme.colors.background)
let tintColor = theme.wallpaper.tint ?? wallpaperType.defaultTintColor(theme.base)
Color.clear.ignoresSafeArea(.all)
.if(wallpaperImage != nil) { view in
view.modifier(
ChatViewBackground(image: wallpaperImage!, imageType: wallpaperType, background: backgroundColor, tint: tintColor)
)
}
VStack(spacing: 0) {
ZStack(alignment: .bottomTrailing) {
chatItemsList()
floatingButtons(counts: floatingButtonModel.unreadChatItemCounts)
}
connectingText()
if selectedChatItems == nil {
ComposeView(
chat: chat,
composeState: $composeState,
keyboardVisible: $keyboardVisible
)
.disabled(!cInfo.sendMsgEnabled)
} else {
SelectedItemsBottomToolbar(
chatItems: ItemsModel.shared.reversedChatItems,
selectedChatItems: $selectedChatItems,
chatInfo: chat.chatInfo,
deleteItems: { forAll in
allowToDeleteSelectedMessagesForAll = forAll
showDeleteSelectedMessages = true
},
moderateItems: {
if case let .group(groupInfo) = chat.chatInfo {
showModerateSelectedMessagesAlert(groupInfo)
}
}
)
}
}
}
.safeAreaInset(edge: .top) {
VStack(spacing: .zero) {
if searchMode { searchToolbar() }
Divider()
}
ZStack(alignment: .bottomTrailing) {
let wallpaperImage = theme.wallpaper.type.image
let wallpaperType = theme.wallpaper.type
let backgroundColor = theme.wallpaper.background ?? wallpaperType.defaultBackgroundColor(theme.base, theme.colors.background)
let tintColor = theme.wallpaper.tint ?? wallpaperType.defaultTintColor(theme.base)
chatItemsList()
.if(wallpaperImage != nil) { view in
view.modifier(
ChatViewBackground(image: wallpaperImage!, imageType: wallpaperType, background: backgroundColor, tint: tintColor)
)
}
floatingButtons(counts: floatingButtonModel.unreadChatItemCounts)
}
connectingText()
if selectedChatItems == nil {
ComposeView(
chat: chat,
composeState: $composeState,
keyboardVisible: $keyboardVisible
)
.disabled(!cInfo.sendMsgEnabled)
} else {
SelectedItemsBottomToolbar(
chatItems: ItemsModel.shared.reversedChatItems,
selectedChatItems: $selectedChatItems,
chatInfo: chat.chatInfo,
deleteItems: { forAll in
allowToDeleteSelectedMessagesForAll = forAll
showDeleteSelectedMessages = true
},
moderateItems: {
if case let .group(groupInfo) = chat.chatInfo {
showModerateSelectedMessagesAlert(groupInfo)
}
}
)
}
.background(ToolbarMaterial.material(toolbarMaterial))
}
.navigationTitle(cInfo.chatViewName)
.background(theme.colors.background)
@@ -352,7 +357,6 @@ struct ChatView: View {
}
.padding(.horizontal)
.padding(.vertical, 8)
.background(.thinMaterial)
}
private func voiceWithoutFrame(_ ci: ChatItem) -> Bool {
@@ -397,20 +401,21 @@ struct ChatView: View {
} loadPage: {
loadChatItems(cInfo)
}
.onTapGesture { hideKeyboard() }
.onChange(of: searchText) { _ in
loadChat(chat: chat, search: searchText)
}
.onChange(of: chatModel.chatId) { chatId in
if let chatId, let c = chatModel.getChat(chatId) {
chat = c
showChatInfoSheet = false
loadChat(chat: c)
}
}
.onChange(of: im.reversedChatItems) { _ in
floatingButtonModel.chatItemsChanged()
.padding(.vertical, -InvertedTableView.inset)
.onTapGesture { hideKeyboard() }
.onChange(of: searchText) { _ in
loadChat(chat: chat, search: searchText)
}
.onChange(of: chatModel.chatId) { chatId in
if let chatId, let c = chatModel.getChat(chatId) {
chat = c
showChatInfoSheet = false
loadChat(chat: c)
}
}
.onChange(of: im.reversedChatItems) { _ in
floatingButtonModel.chatItemsChanged()
}
}
}
@@ -281,6 +281,7 @@ struct ComposeView: View {
@State private var stopPlayback: Bool = false
@AppStorage(DEFAULT_PRIVACY_SAVE_LAST_DRAFT) private var saveLastDraft = true
@AppStorage(DEFAULT_TOOLBAR_MATERIAL) private var toolbarMaterial = ToolbarMaterial.bar.rawValue
var body: some View {
VStack(spacing: 0) {
@@ -381,7 +382,7 @@ struct ComposeView: View {
}
}
}
.background(.thinMaterial)
.background(ToolbarMaterial.material(toolbarMaterial))
.onChange(of: composeState.message) { msg in
if composeState.linkPreviewAllowed {
if msg.count > 0 {
@@ -53,6 +53,7 @@ struct ReverseList<Item: Identifiable & Hashable & Sendable, Content: View>: UIV
super.init(style: .plain)
// 1. Style
tableView = InvertedTableView()
tableView.separatorStyle = .none
tableView.transform = .verticalFlip
tableView.backgroundColor = .clear
@@ -132,6 +133,11 @@ struct ReverseList<Item: Identifiable & Hashable & Sendable, Content: View>: UIV
NotificationCenter.default.post(name: .chatViewWillBeginScrolling, object: nil)
}
override func viewDidAppear(_ animated: Bool) {
tableView.clipsToBounds = false
parent?.viewIfLoaded?.clipsToBounds = false
}
/// Scrolls up
func scrollToNextPage() {
tableView.setContentOffset(
@@ -272,3 +278,29 @@ func withConditionalAnimation<Result>(
try body()
}
}
class InvertedTableView: UITableView {
static let inset = CGFloat(100)
static let insets = UIEdgeInsets(
top: inset,
left: .zero,
bottom: inset,
right: .zero
)
override var contentInsetAdjustmentBehavior: UIScrollView.ContentInsetAdjustmentBehavior {
get { .never }
set { }
}
override var contentInset: UIEdgeInsets {
get { Self.insets }
set { }
}
override var adjustedContentInset: UIEdgeInsets {
Self.insets
}
}
@@ -81,7 +81,7 @@ struct ChatViewBackground: ViewModifier {
case WallpaperType.empty: ()
}
}
)
).ignoresSafeArea(.all)
}
}