ios: improve new and existing chat interactions - new chat sheet, one hand ui, info views action buttons; new modes of contact deletion (keep conversation, only delete conversation) (#4427)

* ios: added delete contacts, one hand ui, and contact action buttons

* remove unused, rework info buttons wip

* ios: moved existing buttons to new chat sheet

* ios: add basic list of contacts to new chat sheet

* ios: add deleted chats section to new chat sheet

* group chat info navigation

* fix spacing of group info buttons

* remove comment

* unify spacing logic across info views

* info button alerts wip

* calls alerts wip

* call buttons alerts

* fix call button to correctly update on preference change while in view

* refactor

* fix alert ids

* contact list wip

* more contact list actions

* open chat wip

* fix contact list elements clickability

* ios: search functionality on new chat sheet

* ios: white bg for search box on new chat sheet

* ios: don't show empty list when pasted contact is not known

* ios: add search and nav title to deleted chats

* navigation links wip

* fix refreshable

* ios: empty states for lists

* ios: hide contact cards from chat list

* ios: make search bar icon sizes consistent

* ios: fix deleted conversation dissapearing from chat list on back

* fix pending invitation cleanup in chat sheet

* rename search label from open to search

* make cleanup alert work on sheet and on dismiss

* dismiss all sheets after creation of groups

* fix double toolbar on group invite members

* fix double toolbar on group link invitation screen

* dismiss all on group creation error

* comment

* show alert in dismissAllSheets completion

* fix sheet dismissal on known group

* rework contact list with buttons (fixes dark mode)

* fix dark mode on new chat view

* fix search dark mode

* increase search padding

* improve new chat title and info button placing

* info view background

* improve create group title placement

* refactor

* fix delete dialogue in light mode

* change icon

* archivebox on contact list

---------

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
This commit is contained in:
Diogo
2024-08-05 15:58:24 +04:00
committed by GitHub
co-authored by spaced4ndy Evgeny Poberezkin
parent b2b1519aea
commit 55331289d3
23 changed files with 1726 additions and 423 deletions
+32 -12
View File
@@ -101,7 +101,7 @@ public enum ChatCommand {
case apiConnectPlan(userId: Int64, connReq: String)
case apiConnect(userId: Int64, incognito: Bool, connReq: String)
case apiConnectContactViaAddress(userId: Int64, incognito: Bool, contactId: Int64)
case apiDeleteChat(type: ChatType, id: Int64, notify: Bool?)
case apiDeleteChat(type: ChatType, id: Int64, chatDeleteMode: ChatDeleteMode)
case apiClearChat(type: ChatType, id: Int64)
case apiListContacts(userId: Int64)
case apiUpdateProfile(userId: Int64, profile: Profile)
@@ -266,11 +266,7 @@ public enum ChatCommand {
case let .apiConnectPlan(userId, connReq): return "/_connect plan \(userId) \(connReq)"
case let .apiConnect(userId, incognito, connReq): return "/_connect \(userId) incognito=\(onOff(incognito)) \(connReq)"
case let .apiConnectContactViaAddress(userId, incognito, contactId): return "/_connect contact \(userId) incognito=\(onOff(incognito)) \(contactId)"
case let .apiDeleteChat(type, id, notify): if let notify = notify {
return "/_delete \(ref(type, id)) notify=\(onOff(notify))"
} else {
return "/_delete \(ref(type, id))"
}
case let .apiDeleteChat(type, id, chatDeleteMode): return "/_delete \(ref(type, id)) \(chatDeleteMode.cmdString)"
case let .apiClearChat(type, id): return "/_clear chat \(ref(type, id))"
case let .apiListContacts(userId): return "/_contacts \(userId)"
case let .apiUpdateProfile(userId, profile): return "/_profile \(userId) \(encodeJSON(profile))"
@@ -505,10 +501,6 @@ public enum ChatCommand {
return nil
}
private func onOff(_ b: Bool) -> String {
b ? "on" : "off"
}
private func onOffParam(_ param: String, _ b: Bool?) -> String {
if let b = b {
return " \(param)=\(onOff(b))"
@@ -521,6 +513,10 @@ public enum ChatCommand {
}
}
private func onOff(_ b: Bool) -> String {
b ? "on" : "off"
}
public struct APIResponse: Decodable {
var resp: ChatResponse
}
@@ -1048,6 +1044,27 @@ public func chatError(_ chatResponse: ChatResponse) -> ChatErrorType? {
}
}
public enum ChatDeleteMode: Codable {
case full(notify: Bool)
case entity(notify: Bool)
case messages
var cmdString: String {
switch self {
case let .full(notify): "full notify=\(onOff(notify))"
case let .entity(notify): "entity notify=\(onOff(notify))"
case .messages: "messages"
}
}
public var isEntity: Bool {
switch self {
case .entity: return true
default: return false
}
}
}
public enum ConnectionPlan: Decodable, Hashable {
case invitationLink(invitationLinkPlan: InvitationLinkPlan)
case contactAddress(contactAddressPlan: ContactAddressPlan)
@@ -2141,7 +2158,8 @@ public struct AppSettings: Codable, Equatable, Hashable {
public var uiDarkColorScheme: String? = nil
public var uiCurrentThemeIds: [String: String]? = nil
public var uiThemes: [ThemeOverrides]? = nil
public var oneHandUI: Bool? = nil
public func prepareForExport() -> AppSettings {
var empty = AppSettings()
let def = AppSettings.defaults
@@ -2171,6 +2189,7 @@ public struct AppSettings: Codable, Equatable, Hashable {
if uiDarkColorScheme != def.uiDarkColorScheme { empty.uiDarkColorScheme = uiDarkColorScheme }
if uiCurrentThemeIds != def.uiCurrentThemeIds { empty.uiCurrentThemeIds = uiCurrentThemeIds }
if uiThemes != def.uiThemes { empty.uiThemes = uiThemes }
if oneHandUI != def.oneHandUI { empty.oneHandUI = oneHandUI }
return empty
}
@@ -2201,7 +2220,8 @@ public struct AppSettings: Codable, Equatable, Hashable {
uiColorScheme: DefaultTheme.SYSTEM_THEME_NAME,
uiDarkColorScheme: DefaultTheme.SIMPLEX.themeName,
uiCurrentThemeIds: nil as [String: String]?,
uiThemes: nil as [ThemeOverrides]?
uiThemes: nil as [ThemeOverrides]?,
oneHandUI: false
)
}
}
+35 -2
View File
@@ -1289,6 +1289,15 @@ public enum ChatInfo: Identifiable, Decodable, NamedChat, Hashable {
}
}
}
public var chatDeleted: Bool {
get {
switch self {
case let .direct(contact): return contact.chatDeleted
default: return false
}
}
}
public var sendMsgEnabled: Bool {
get {
@@ -1401,6 +1410,27 @@ public enum ChatInfo: Identifiable, Decodable, NamedChat, Hashable {
}
}
public enum ShowEnableCallsAlert: Hashable {
case userEnable
case askContact
case other
}
public var showEnableCallsAlert: ShowEnableCallsAlert {
switch self {
case let .direct(contact):
if contact.mergedPreferences.calls.userPreference.preference.allow == .no {
return .userEnable
} else if contact.mergedPreferences.calls.contactPreference.allow == .no {
return .askContact
} else {
return .other
}
default:
return .other
}
}
public var ntfsEnabled: Bool {
self.chatSettings?.enableNtfs == .all
}
@@ -1508,7 +1538,8 @@ public struct Contact: Identifiable, Decodable, NamedChat, Hashable {
var contactGroupMemberId: Int64?
var contactGrpInvSent: Bool
public var uiThemes: ThemeModeOverrides?
public var chatDeleted: Bool
public var id: ChatId { get { "@\(contactId)" } }
public var apiId: Int64 { get { contactId } }
public var ready: Bool { get { activeConn?.connStatus == .ready } }
@@ -1575,13 +1606,15 @@ public struct Contact: Identifiable, Decodable, NamedChat, Hashable {
mergedPreferences: ContactUserPreferences.sampleData,
createdAt: .now,
updatedAt: .now,
contactGrpInvSent: false
contactGrpInvSent: false,
chatDeleted: false
)
}
public enum ContactStatus: String, Decodable, Hashable {
case active = "active"
case deleted = "deleted"
case deletedByUser = "deletedByUser"
}
public struct ContactRef: Decodable, Equatable, Hashable {