ios: invert swipe actions in oneHandUI mode (#4596)

* add swipe label

* minor

* adjust font

* dynamic type

* limit use to oneHandUI

* icon size

* fix offset

* change font style

---------

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
This commit is contained in:
Arturs Krumins
2024-08-06 16:50:33 +03:00
committed by GitHub
parent 205cc835bf
commit e3ed7f68a2
3 changed files with 120 additions and 18 deletions
@@ -56,6 +56,8 @@ struct ChatListNavLink: View {
@State private var inProgress = false
@State private var progressByTimeout = false
@AppStorage(DEFAULT_ONE_HAND_UI) private var oneHandUI = false
var dynamicRowHeight: CGFloat { dynamicSizes[userFont]?.rowHeight ?? 80 }
var body: some View {
@@ -102,7 +104,7 @@ struct ChatListNavLink: View {
showSheetContent: { sheet = $0 }
)
} label: {
Label("Delete", systemImage: "trash")
deleteLabel
}
.tint(.red)
}
@@ -120,7 +122,7 @@ struct ChatListNavLink: View {
.swipeActions(edge: .leading, allowsFullSwipe: true) {
markReadButton()
toggleFavoriteButton()
ToggleNtfsButton(chat: chat)
toggleNtfsButton(chat: chat)
}
.swipeActions(edge: .trailing, allowsFullSwipe: true) {
if !chat.chatItems.isEmpty {
@@ -136,7 +138,7 @@ struct ChatListNavLink: View {
showSheetContent: { sheet = $0 }
)
} label: {
Label("Delete", systemImage: "trash")
deleteLabel
}
.tint(.red)
}
@@ -202,7 +204,7 @@ struct ChatListNavLink: View {
.swipeActions(edge: .leading, allowsFullSwipe: true) {
markReadButton()
toggleFavoriteButton()
ToggleNtfsButton(chat: chat)
toggleNtfsButton(chat: chat)
}
.swipeActions(edge: .trailing, allowsFullSwipe: true) {
if !chat.chatItems.isEmpty {
@@ -243,7 +245,7 @@ struct ChatListNavLink: View {
await MainActor.run { inProgress = false }
}
} label: {
Label("Join", systemImage: chat.chatInfo.incognito ? "theatermasks" : "ipad.and.arrow.forward")
SwipeLabel("Join", systemImage: chat.chatInfo.incognito ? "theatermasks" : "ipad.and.arrow.forward", inverted: oneHandUI)
}
.tint(chat.chatInfo.incognito ? .indigo : theme.colors.primary)
}
@@ -253,14 +255,14 @@ struct ChatListNavLink: View {
Button {
Task { await markChatRead(chat) }
} label: {
Label("Read", systemImage: "checkmark")
SwipeLabel("Read", systemImage: "checkmark", inverted: oneHandUI)
}
.tint(theme.colors.primary)
} else {
Button {
Task { await markChatUnread(chat) }
} label: {
Label("Unread", systemImage: "circlebadge.fill")
SwipeLabel("Unread", systemImage: "circlebadge.fill", inverted: oneHandUI)
}
.tint(theme.colors.primary)
}
@@ -272,24 +274,36 @@ struct ChatListNavLink: View {
Button {
toggleChatFavorite(chat, favorite: false)
} label: {
Label("Unfav.", systemImage: "star.slash")
SwipeLabel("Unfav.", systemImage: "star.slash.fill", inverted: oneHandUI)
}
.tint(.green)
} else {
Button {
toggleChatFavorite(chat, favorite: true)
} label: {
Label("Favorite", systemImage: "star.fill")
SwipeLabel("Favorite", systemImage: "star.fill", inverted: oneHandUI)
}
.tint(.green)
}
}
@ViewBuilder private func toggleNtfsButton(chat: Chat) -> some View {
Button {
toggleNotifications(chat, enableNtfs: !chat.chatInfo.ntfsEnabled)
} label: {
if chat.chatInfo.ntfsEnabled {
SwipeLabel("Mute", systemImage: "speaker.slash.fill", inverted: oneHandUI)
} else {
SwipeLabel("Unmute", systemImage: "speaker.wave.2.fill", inverted: oneHandUI)
}
}
}
private func clearChatButton() -> some View {
Button {
AlertManager.shared.showAlert(clearChatAlert())
} label: {
Label("Clear", systemImage: "gobackward")
SwipeLabel("Clear", systemImage: "gobackward", inverted: oneHandUI)
}
.tint(Color.orange)
}
@@ -298,7 +312,7 @@ struct ChatListNavLink: View {
Button {
AlertManager.shared.showAlert(clearNoteFolderAlert())
} label: {
Label("Clear", systemImage: "gobackward")
SwipeLabel("Clear", systemImage: "gobackward", inverted: oneHandUI)
}
.tint(Color.orange)
}
@@ -307,7 +321,7 @@ struct ChatListNavLink: View {
Button {
AlertManager.shared.showAlert(leaveGroupAlert(groupInfo))
} label: {
Label("Leave", systemImage: "rectangle.portrait.and.arrow.right")
SwipeLabel("Leave", systemImage: "rectangle.portrait.and.arrow.right.fill", inverted: oneHandUI)
}
.tint(Color.yellow)
}
@@ -316,7 +330,7 @@ struct ChatListNavLink: View {
Button {
AlertManager.shared.showAlert(deleteGroupAlert(groupInfo))
} label: {
Label("Delete", systemImage: "trash")
deleteLabel
}
.tint(.red)
}
@@ -326,18 +340,18 @@ struct ChatListNavLink: View {
.swipeActions(edge: .trailing, allowsFullSwipe: true) {
Button {
Task { await acceptContactRequest(incognito: false, contactRequest: contactRequest) }
} label: { Label("Accept", systemImage: "checkmark") }
} label: { SwipeLabel("Accept", systemImage: "checkmark", inverted: oneHandUI) }
.tint(theme.colors.primary)
Button {
Task { await acceptContactRequest(incognito: true, contactRequest: contactRequest) }
} label: {
Label("Accept incognito", systemImage: "theatermasks")
SwipeLabel("Accept incognito", systemImage: "theatermasks.fill", inverted: oneHandUI)
}
.tint(.indigo)
Button {
AlertManager.shared.showAlert(rejectContactRequestAlert(contactRequest))
} label: {
Label("Reject", systemImage: "multiply")
SwipeLabel("Reject", systemImage: "multiply.fill", inverted: oneHandUI)
}
.tint(.red)
}
@@ -358,14 +372,14 @@ struct ChatListNavLink: View {
AlertManager.shared.showAlertMsg(title: a.title, message: a.message)
})
} label: {
Label("Delete", systemImage: "trash")
deleteLabel
}
.tint(.red)
Button {
showContactConnectionInfo = true
} label: {
Label("Name", systemImage: "pencil")
SwipeLabel("Name", systemImage: "pencil", inverted: oneHandUI)
}
.tint(theme.colors.primary)
}
@@ -384,6 +398,10 @@ struct ChatListNavLink: View {
}
}
private var deleteLabel: some View {
SwipeLabel("Delete", systemImage: "trash.fill", inverted: oneHandUI)
}
private func deleteGroupAlert(_ groupInfo: GroupInfo) -> Alert {
Alert(
title: Text("Delete group?"),
@@ -0,0 +1,80 @@
//
// SwipeLabel.swift
// SimpleX (iOS)
//
// Created by Levitating Pineapple on 06/08/2024.
// Copyright © 2024 SimpleX Chat. All rights reserved.
//
import SwiftUI
struct SwipeLabel: View {
private let text: String
private let systemImage: String
private let inverted: Bool
init(_ text: String, systemImage: String, inverted: Bool) {
self.text = text
self.systemImage = systemImage
self.inverted = inverted
}
var body: some View {
if inverted {
Image(
uiImage: SwipeActionView(
systemName: systemImage,
text: text
).snapshot(inverted: inverted)
)
} else {
Label(text, systemImage: systemImage)
}
}
private class SwipeActionView: UIView {
private let imageView = UIImageView()
private let label = UILabel()
private let fontSize: CGFloat
init(systemName: String, text: String) {
fontSize = UIFontDescriptor.preferredFontDescriptor(withTextStyle: .subheadline).pointSize
super.init(frame: CGRect(x: 0, y: 0, width: 64, height: 32 + fontSize))
imageView.image = UIImage(systemName: systemName)
imageView.contentMode = .scaleAspectFit
label.text = NSLocalizedString(text, comment: "swipe action")
label.textAlignment = .center
label.font = UIFont.systemFont(ofSize: fontSize, weight: .medium)
addSubview(imageView)
addSubview(label)
}
override func layoutSubviews() {
imageView.frame = CGRect(
x: 20,
y: 0,
width: 24,
height: 24
)
label.frame = CGRect(
x: 0,
y: 32,
width: 64,
height: fontSize
)
}
@available(*, unavailable)
required init?(coder: NSCoder) { fatalError("not implemented") }
func snapshot(inverted: Bool) -> UIImage {
UIGraphicsImageRenderer(bounds: bounds).image { context in
if inverted {
context.cgContext.scaleBy(x: 1, y: -1)
context.cgContext.translateBy(x: 0, y: -bounds.height)
}
layer.render(in: context.cgContext)
}.withRenderingMode(.alwaysTemplate)
}
}
}
@@ -200,6 +200,7 @@
CE3097FB2C4C0C9F00180898 /* ErrorAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE3097FA2C4C0C9F00180898 /* ErrorAlert.swift */; };
CE38A29A2C3FCA54005ED185 /* ImageUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CBD2859295711D700EC2CF4 /* ImageUtils.swift */; };
CE38A29C2C3FCD72005ED185 /* SwiftyGif in Frameworks */ = {isa = PBXBuildFile; productRef = CE38A29B2C3FCD72005ED185 /* SwiftyGif */; };
CE75480A2C622630009579B7 /* SwipeLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE7548092C622630009579B7 /* SwipeLabel.swift */; };
CE984D4B2C36C5D500E3AEFF /* ChatItemClipShape.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE984D4A2C36C5D500E3AEFF /* ChatItemClipShape.swift */; };
CEDE70222C48FD9500233B1F /* SEChatState.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEDE70212C48FD9500233B1F /* SEChatState.swift */; };
CEE723AA2C3BD3D70009AE93 /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEE723A92C3BD3D70009AE93 /* ShareViewController.swift */; };
@@ -536,6 +537,7 @@
CE1EB0E32C459A660099D896 /* ShareAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareAPI.swift; sourceTree = "<group>"; };
CE2AD9CD2C452A4D00E844E3 /* ChatUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatUtils.swift; sourceTree = "<group>"; };
CE3097FA2C4C0C9F00180898 /* ErrorAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorAlert.swift; sourceTree = "<group>"; };
CE7548092C622630009579B7 /* SwipeLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwipeLabel.swift; sourceTree = "<group>"; };
CE984D4A2C36C5D500E3AEFF /* ChatItemClipShape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatItemClipShape.swift; sourceTree = "<group>"; };
CEDE70212C48FD9500233B1F /* SEChatState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SEChatState.swift; sourceTree = "<group>"; };
CEE723A72C3BD3D70009AE93 /* SimpleX SE.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "SimpleX SE.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -789,6 +791,7 @@
8C74C3ED2C1B942300039E77 /* ChatWallpaper.swift */,
8C9BC2642C240D5100875A27 /* ThemeModeEditor.swift */,
CE984D4A2C36C5D500E3AEFF /* ChatItemClipShape.swift */,
CE7548092C622630009579B7 /* SwipeLabel.swift */,
);
path = Helpers;
sourceTree = "<group>";
@@ -1443,6 +1446,7 @@
64D0C2C229FA57AB00B38D5F /* UserAddressLearnMore.swift in Sources */,
8CE848A32C5A0FA000D5C7C8 /* SelectableChatItemToolbars.swift in Sources */,
64466DCC29FFE3E800E3D48D /* MailView.swift in Sources */,
CE75480A2C622630009579B7 /* SwipeLabel.swift in Sources */,
5C971E2127AEBF8300C8A3CE /* ChatInfoImage.swift in Sources */,
5C55A921283CCCB700C4E99E /* IncomingCallView.swift in Sources */,
6454036F2822A9750090DDFF /* ComposeFileView.swift in Sources */,