Merge branch 'master-ghc8107' into master-android
This commit is contained in:
commit
c4d7e5307c
@ -671,18 +671,18 @@ private func connectionErrorAlert(_ r: ChatResponse) -> Alert {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func apiDeleteChat(type: ChatType, id: Int64) async throws {
|
func apiDeleteChat(type: ChatType, id: Int64, notify: Bool? = nil) async throws {
|
||||||
let r = await chatSendCmd(.apiDeleteChat(type: type, id: id), bgTask: false)
|
let r = await chatSendCmd(.apiDeleteChat(type: type, id: id, notify: notify), bgTask: false)
|
||||||
if case .direct = type, case .contactDeleted = r { return }
|
if case .direct = type, case .contactDeleted = r { return }
|
||||||
if case .contactConnection = type, case .contactConnectionDeleted = r { return }
|
if case .contactConnection = type, case .contactConnectionDeleted = r { return }
|
||||||
if case .group = type, case .groupDeletedUser = r { return }
|
if case .group = type, case .groupDeletedUser = r { return }
|
||||||
throw r
|
throw r
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteChat(_ chat: Chat) async {
|
func deleteChat(_ chat: Chat, notify: Bool? = nil) async {
|
||||||
do {
|
do {
|
||||||
let cInfo = chat.chatInfo
|
let cInfo = chat.chatInfo
|
||||||
try await apiDeleteChat(type: cInfo.chatType, id: cInfo.apiId)
|
try await apiDeleteChat(type: cInfo.chatType, id: cInfo.apiId, notify: notify)
|
||||||
DispatchQueue.main.async { ChatModel.shared.removeChat(cInfo.id) }
|
DispatchQueue.main.async { ChatModel.shared.removeChat(cInfo.id) }
|
||||||
} catch let error {
|
} catch let error {
|
||||||
logger.error("deleteChat apiDeleteChat error: \(responseError(error))")
|
logger.error("deleteChat apiDeleteChat error: \(responseError(error))")
|
||||||
|
@ -99,12 +99,12 @@ struct ChatInfoView: View {
|
|||||||
@Binding var connectionCode: String?
|
@Binding var connectionCode: String?
|
||||||
@FocusState private var aliasTextFieldFocused: Bool
|
@FocusState private var aliasTextFieldFocused: Bool
|
||||||
@State private var alert: ChatInfoViewAlert? = nil
|
@State private var alert: ChatInfoViewAlert? = nil
|
||||||
|
@State private var showDeleteContactActionSheet = false
|
||||||
@State private var sendReceipts = SendReceipts.userDefault(true)
|
@State private var sendReceipts = SendReceipts.userDefault(true)
|
||||||
@State private var sendReceiptsUserDefault = true
|
@State private var sendReceiptsUserDefault = true
|
||||||
@AppStorage(DEFAULT_DEVELOPER_TOOLS) private var developerTools = false
|
@AppStorage(DEFAULT_DEVELOPER_TOOLS) private var developerTools = false
|
||||||
|
|
||||||
enum ChatInfoViewAlert: Identifiable {
|
enum ChatInfoViewAlert: Identifiable {
|
||||||
case deleteContactAlert
|
|
||||||
case clearChatAlert
|
case clearChatAlert
|
||||||
case networkStatusAlert
|
case networkStatusAlert
|
||||||
case switchAddressAlert
|
case switchAddressAlert
|
||||||
@ -114,7 +114,6 @@ struct ChatInfoView: View {
|
|||||||
|
|
||||||
var id: String {
|
var id: String {
|
||||||
switch self {
|
switch self {
|
||||||
case .deleteContactAlert: return "deleteContactAlert"
|
|
||||||
case .clearChatAlert: return "clearChatAlert"
|
case .clearChatAlert: return "clearChatAlert"
|
||||||
case .networkStatusAlert: return "networkStatusAlert"
|
case .networkStatusAlert: return "networkStatusAlert"
|
||||||
case .switchAddressAlert: return "switchAddressAlert"
|
case .switchAddressAlert: return "switchAddressAlert"
|
||||||
@ -233,7 +232,6 @@ struct ChatInfoView: View {
|
|||||||
}
|
}
|
||||||
.alert(item: $alert) { alertItem in
|
.alert(item: $alert) { alertItem in
|
||||||
switch(alertItem) {
|
switch(alertItem) {
|
||||||
case .deleteContactAlert: return deleteContactAlert()
|
|
||||||
case .clearChatAlert: return clearChatAlert()
|
case .clearChatAlert: return clearChatAlert()
|
||||||
case .networkStatusAlert: return networkStatusAlert()
|
case .networkStatusAlert: return networkStatusAlert()
|
||||||
case .switchAddressAlert: return switchAddressAlert(switchContactAddress)
|
case .switchAddressAlert: return switchAddressAlert(switchContactAddress)
|
||||||
@ -242,6 +240,26 @@ struct ChatInfoView: View {
|
|||||||
case let .error(title, error): return mkAlert(title: title, message: error)
|
case let .error(title, error): return mkAlert(title: title, message: error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.actionSheet(isPresented: $showDeleteContactActionSheet) {
|
||||||
|
if contact.ready && contact.active {
|
||||||
|
ActionSheet(
|
||||||
|
title: Text("Delete contact?\nThis cannot be undone!"),
|
||||||
|
buttons: [
|
||||||
|
.destructive(Text("Delete and notify contact")) { deleteContact(notify: true) },
|
||||||
|
.destructive(Text("Delete")) { deleteContact(notify: false) },
|
||||||
|
.cancel()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
ActionSheet(
|
||||||
|
title: Text("Delete contact?\nThis cannot be undone!"),
|
||||||
|
buttons: [
|
||||||
|
.destructive(Text("Delete")) { deleteContact() },
|
||||||
|
.cancel()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func contactInfoHeader() -> some View {
|
private func contactInfoHeader() -> some View {
|
||||||
@ -414,7 +432,7 @@ struct ChatInfoView: View {
|
|||||||
|
|
||||||
private func deleteContactButton() -> some View {
|
private func deleteContactButton() -> some View {
|
||||||
Button(role: .destructive) {
|
Button(role: .destructive) {
|
||||||
alert = .deleteContactAlert
|
showDeleteContactActionSheet = true
|
||||||
} label: {
|
} label: {
|
||||||
Label("Delete contact", systemImage: "trash")
|
Label("Delete contact", systemImage: "trash")
|
||||||
.foregroundColor(Color.red)
|
.foregroundColor(Color.red)
|
||||||
@ -430,14 +448,10 @@ struct ChatInfoView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func deleteContactAlert() -> Alert {
|
private func deleteContact(notify: Bool? = nil) {
|
||||||
Alert(
|
|
||||||
title: Text("Delete contact?"),
|
|
||||||
message: Text("Contact and all messages will be deleted - this cannot be undone!"),
|
|
||||||
primaryButton: .destructive(Text("Delete")) {
|
|
||||||
Task {
|
Task {
|
||||||
do {
|
do {
|
||||||
try await apiDeleteChat(type: chat.chatInfo.chatType, id: chat.chatInfo.apiId)
|
try await apiDeleteChat(type: chat.chatInfo.chatType, id: chat.chatInfo.apiId, notify: notify)
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
dismiss()
|
dismiss()
|
||||||
chatModel.chatId = nil
|
chatModel.chatId = nil
|
||||||
@ -451,9 +465,6 @@ struct ChatInfoView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
secondaryButton: .cancel()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func clearChatAlert() -> Alert {
|
private func clearChatAlert() -> Alert {
|
||||||
|
@ -32,6 +32,7 @@ struct ChatListNavLink: View {
|
|||||||
@State private var showJoinGroupDialog = false
|
@State private var showJoinGroupDialog = false
|
||||||
@State private var showContactConnectionInfo = false
|
@State private var showContactConnectionInfo = false
|
||||||
@State private var showInvalidJSON = false
|
@State private var showInvalidJSON = false
|
||||||
|
@State private var showDeleteContactActionSheet = false
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
switch chat.chatInfo {
|
switch chat.chatInfo {
|
||||||
@ -64,17 +65,37 @@ struct ChatListNavLink: View {
|
|||||||
clearChatButton()
|
clearChatButton()
|
||||||
}
|
}
|
||||||
Button {
|
Button {
|
||||||
AlertManager.shared.showAlert(
|
if contact.ready || !contact.active {
|
||||||
contact.ready || !contact.active
|
showDeleteContactActionSheet = true
|
||||||
? deleteContactAlert(chat.chatInfo)
|
} else {
|
||||||
: deletePendingContactAlert(chat, contact)
|
AlertManager.shared.showAlert(deletePendingContactAlert(chat, contact))
|
||||||
)
|
}
|
||||||
} label: {
|
} label: {
|
||||||
Label("Delete", systemImage: "trash")
|
Label("Delete", systemImage: "trash")
|
||||||
}
|
}
|
||||||
.tint(.red)
|
.tint(.red)
|
||||||
}
|
}
|
||||||
.frame(height: rowHeights[dynamicTypeSize])
|
.frame(height: rowHeights[dynamicTypeSize])
|
||||||
|
.actionSheet(isPresented: $showDeleteContactActionSheet) {
|
||||||
|
if contact.ready && contact.active {
|
||||||
|
ActionSheet(
|
||||||
|
title: Text("Delete contact?\nThis cannot be undone!"),
|
||||||
|
buttons: [
|
||||||
|
.destructive(Text("Delete and notify contact")) { Task { await deleteChat(chat, notify: true) } },
|
||||||
|
.destructive(Text("Delete")) { Task { await deleteChat(chat, notify: false) } },
|
||||||
|
.cancel()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
ActionSheet(
|
||||||
|
title: Text("Delete contact?\nThis cannot be undone!"),
|
||||||
|
buttons: [
|
||||||
|
.destructive(Text("Delete")) { Task { await deleteChat(chat) } },
|
||||||
|
.cancel()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder private func groupNavLink(_ groupInfo: GroupInfo) -> some View {
|
@ViewBuilder private func groupNavLink(_ groupInfo: GroupInfo) -> some View {
|
||||||
@ -269,17 +290,6 @@ struct ChatListNavLink: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func deleteContactAlert(_ chatInfo: ChatInfo) -> Alert {
|
|
||||||
Alert(
|
|
||||||
title: Text("Delete contact?"),
|
|
||||||
message: Text("Contact and all messages will be deleted - this cannot be undone!"),
|
|
||||||
primaryButton: .destructive(Text("Delete")) {
|
|
||||||
Task { await deleteChat(chat) }
|
|
||||||
},
|
|
||||||
secondaryButton: .cancel()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func deleteGroupAlert(_ groupInfo: GroupInfo) -> Alert {
|
private func deleteGroupAlert(_ groupInfo: GroupInfo) -> Alert {
|
||||||
Alert(
|
Alert(
|
||||||
title: Text("Delete group?"),
|
title: Text("Delete group?"),
|
||||||
|
@ -356,7 +356,7 @@ struct SimplexLockView: View {
|
|||||||
var id: Self { self }
|
var id: Self { self }
|
||||||
}
|
}
|
||||||
|
|
||||||
let laDelays: [Int] = [10, 30, 60, 180, 0]
|
let laDelays: [Int] = [10, 30, 60, 180, 600, 0]
|
||||||
|
|
||||||
func laDelayText(_ t: Int) -> LocalizedStringKey {
|
func laDelayText(_ t: Int) -> LocalizedStringKey {
|
||||||
let m = t / 60
|
let m = t / 60
|
||||||
@ -378,6 +378,7 @@ struct SimplexLockView: View {
|
|||||||
Text(mode.text)
|
Text(mode.text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.frame(height: 36)
|
||||||
if performLA {
|
if performLA {
|
||||||
Picker("Lock after", selection: $laLockDelay) {
|
Picker("Lock after", selection: $laLockDelay) {
|
||||||
let delays = laDelays.contains(laLockDelay) ? laDelays : [laLockDelay] + laDelays
|
let delays = laDelays.contains(laLockDelay) ? laDelays : [laLockDelay] + laDelays
|
||||||
@ -385,6 +386,7 @@ struct SimplexLockView: View {
|
|||||||
Text(laDelayText(t))
|
Text(laDelayText(t))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.frame(height: 36)
|
||||||
if showChangePassword && laMode == .passcode {
|
if showChangePassword && laMode == .passcode {
|
||||||
Button("Change passcode") {
|
Button("Change passcode") {
|
||||||
changeLAPassword()
|
changeLAPassword()
|
||||||
|
@ -89,7 +89,7 @@ public enum ChatCommand {
|
|||||||
case apiSetConnectionIncognito(connId: Int64, incognito: Bool)
|
case apiSetConnectionIncognito(connId: Int64, incognito: Bool)
|
||||||
case apiConnectPlan(userId: Int64, connReq: String)
|
case apiConnectPlan(userId: Int64, connReq: String)
|
||||||
case apiConnect(userId: Int64, incognito: Bool, connReq: String)
|
case apiConnect(userId: Int64, incognito: Bool, connReq: String)
|
||||||
case apiDeleteChat(type: ChatType, id: Int64)
|
case apiDeleteChat(type: ChatType, id: Int64, notify: Bool?)
|
||||||
case apiClearChat(type: ChatType, id: Int64)
|
case apiClearChat(type: ChatType, id: Int64)
|
||||||
case apiListContacts(userId: Int64)
|
case apiListContacts(userId: Int64)
|
||||||
case apiUpdateProfile(userId: Int64, profile: Profile)
|
case apiUpdateProfile(userId: Int64, profile: Profile)
|
||||||
@ -224,7 +224,11 @@ public enum ChatCommand {
|
|||||||
case let .apiSetConnectionIncognito(connId, incognito): return "/_set incognito :\(connId) \(onOff(incognito))"
|
case let .apiSetConnectionIncognito(connId, incognito): return "/_set incognito :\(connId) \(onOff(incognito))"
|
||||||
case let .apiConnectPlan(userId, connReq): return "/_connect plan \(userId) \(connReq)"
|
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 .apiConnect(userId, incognito, connReq): return "/_connect \(userId) incognito=\(onOff(incognito)) \(connReq)"
|
||||||
case let .apiDeleteChat(type, id): return "/_delete \(ref(type, id))"
|
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 .apiClearChat(type, id): return "/_clear chat \(ref(type, id))"
|
case let .apiClearChat(type, id): return "/_clear chat \(ref(type, id))"
|
||||||
case let .apiListContacts(userId): return "/_contacts \(userId)"
|
case let .apiListContacts(userId): return "/_contacts \(userId)"
|
||||||
case let .apiUpdateProfile(userId, profile): return "/_profile \(userId) \(encodeJSON(profile))"
|
case let .apiUpdateProfile(userId, profile): return "/_profile \(userId) \(encodeJSON(profile))"
|
||||||
|
@ -904,8 +904,8 @@ object ChatController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun apiDeleteChat(type: ChatType, id: Long): Boolean {
|
suspend fun apiDeleteChat(type: ChatType, id: Long, notify: Boolean? = null): Boolean {
|
||||||
val r = sendCmd(CC.ApiDeleteChat(type, id))
|
val r = sendCmd(CC.ApiDeleteChat(type, id, notify))
|
||||||
when {
|
when {
|
||||||
r is CR.ContactDeleted && type == ChatType.Direct -> return true
|
r is CR.ContactDeleted && type == ChatType.Direct -> return true
|
||||||
r is CR.ContactConnectionDeleted && type == ChatType.ContactConnection -> return true
|
r is CR.ContactConnectionDeleted && type == ChatType.ContactConnection -> return true
|
||||||
@ -1924,7 +1924,7 @@ sealed class CC {
|
|||||||
class ApiSetConnectionIncognito(val connId: Long, val incognito: Boolean): CC()
|
class ApiSetConnectionIncognito(val connId: Long, val incognito: Boolean): CC()
|
||||||
class APIConnectPlan(val userId: Long, val connReq: String): CC()
|
class APIConnectPlan(val userId: Long, val connReq: String): CC()
|
||||||
class APIConnect(val userId: Long, val incognito: Boolean, val connReq: String): CC()
|
class APIConnect(val userId: Long, val incognito: Boolean, val connReq: String): CC()
|
||||||
class ApiDeleteChat(val type: ChatType, val id: Long): CC()
|
class ApiDeleteChat(val type: ChatType, val id: Long, val notify: Boolean?): CC()
|
||||||
class ApiClearChat(val type: ChatType, val id: Long): CC()
|
class ApiClearChat(val type: ChatType, val id: Long): CC()
|
||||||
class ApiListContacts(val userId: Long): CC()
|
class ApiListContacts(val userId: Long): CC()
|
||||||
class ApiUpdateProfile(val userId: Long, val profile: Profile): CC()
|
class ApiUpdateProfile(val userId: Long, val profile: Profile): CC()
|
||||||
@ -2034,7 +2034,11 @@ sealed class CC {
|
|||||||
is ApiSetConnectionIncognito -> "/_set incognito :$connId ${onOff(incognito)}"
|
is ApiSetConnectionIncognito -> "/_set incognito :$connId ${onOff(incognito)}"
|
||||||
is APIConnectPlan -> "/_connect plan $userId $connReq"
|
is APIConnectPlan -> "/_connect plan $userId $connReq"
|
||||||
is APIConnect -> "/_connect $userId incognito=${onOff(incognito)} $connReq"
|
is APIConnect -> "/_connect $userId incognito=${onOff(incognito)} $connReq"
|
||||||
is ApiDeleteChat -> "/_delete ${chatRef(type, id)}"
|
is ApiDeleteChat -> if (notify != null) {
|
||||||
|
"/_delete ${chatRef(type, id)} notify=${onOff(notify)}"
|
||||||
|
} else {
|
||||||
|
"/_delete ${chatRef(type, id)}"
|
||||||
|
}
|
||||||
is ApiClearChat -> "/_clear chat ${chatRef(type, id)}"
|
is ApiClearChat -> "/_clear chat ${chatRef(type, id)}"
|
||||||
is ApiListContacts -> "/_contacts $userId"
|
is ApiListContacts -> "/_contacts $userId"
|
||||||
is ApiUpdateProfile -> "/_profile $userId ${json.encodeToString(profile)}"
|
is ApiUpdateProfile -> "/_profile $userId ${json.encodeToString(profile)}"
|
||||||
|
@ -196,13 +196,55 @@ sealed class SendReceipts {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun deleteContactDialog(chatInfo: ChatInfo, chatModel: ChatModel, close: (() -> Unit)? = null) {
|
fun deleteContactDialog(chatInfo: ChatInfo, chatModel: ChatModel, close: (() -> Unit)? = null) {
|
||||||
AlertManager.shared.showAlertDialog(
|
AlertManager.shared.showAlertDialogButtonsColumn(
|
||||||
title = generalGetString(MR.strings.delete_contact_question),
|
title = generalGetString(MR.strings.delete_contact_question),
|
||||||
text = generalGetString(MR.strings.delete_contact_all_messages_deleted_cannot_undo_warning),
|
text = AnnotatedString(generalGetString(MR.strings.delete_contact_all_messages_deleted_cannot_undo_warning)),
|
||||||
confirmText = generalGetString(MR.strings.delete_verb),
|
buttons = {
|
||||||
onConfirm = {
|
Column {
|
||||||
|
if (chatInfo is ChatInfo.Direct && chatInfo.contact.ready && chatInfo.contact.active) {
|
||||||
|
// Delete and notify contact
|
||||||
|
SectionItemView({
|
||||||
|
AlertManager.shared.hideAlert()
|
||||||
withApi {
|
withApi {
|
||||||
val r = chatModel.controller.apiDeleteChat(chatInfo.chatType, chatInfo.apiId)
|
deleteContact(chatInfo, chatModel, close, notify = true)
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Text(generalGetString(MR.strings.delete_and_notify_contact), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = MaterialTheme.colors.error)
|
||||||
|
}
|
||||||
|
// Delete
|
||||||
|
SectionItemView({
|
||||||
|
AlertManager.shared.hideAlert()
|
||||||
|
withApi {
|
||||||
|
deleteContact(chatInfo, chatModel, close, notify = false)
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Text(generalGetString(MR.strings.delete_verb), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = MaterialTheme.colors.error)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Delete
|
||||||
|
SectionItemView({
|
||||||
|
AlertManager.shared.hideAlert()
|
||||||
|
withApi {
|
||||||
|
deleteContact(chatInfo, chatModel, close)
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Text(generalGetString(MR.strings.delete_verb), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = MaterialTheme.colors.error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Cancel
|
||||||
|
SectionItemView({
|
||||||
|
AlertManager.shared.hideAlert()
|
||||||
|
}) {
|
||||||
|
Text(stringResource(MR.strings.cancel_verb), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = MaterialTheme.colors.primary)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deleteContact(chatInfo: ChatInfo, chatModel: ChatModel, close: (() -> Unit)?, notify: Boolean? = null) {
|
||||||
|
withApi {
|
||||||
|
val r = chatModel.controller.apiDeleteChat(chatInfo.chatType, chatInfo.apiId, notify)
|
||||||
if (r) {
|
if (r) {
|
||||||
chatModel.removeChat(chatInfo.id)
|
chatModel.removeChat(chatInfo.id)
|
||||||
if (chatModel.chatId.value == chatInfo.id) {
|
if (chatModel.chatId.value == chatInfo.id) {
|
||||||
@ -213,9 +255,6 @@ fun deleteContactDialog(chatInfo: ChatInfo, chatModel: ChatModel, close: (() ->
|
|||||||
close?.invoke()
|
close?.invoke()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
destructive = true,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clearChatDialog(chatInfo: ChatInfo, chatModel: ChatModel, close: (() -> Unit)? = null) {
|
fun clearChatDialog(chatInfo: ChatInfo, chatModel: ChatModel, close: (() -> Unit)? = null) {
|
||||||
|
@ -317,7 +317,7 @@ private fun showUserGroupsReceiptsAlert(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val laDelays = listOf(10, 30, 60, 180, 0)
|
private val laDelays = listOf(10, 30, 60, 180, 600, 0)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SimplexLockView(
|
fun SimplexLockView(
|
||||||
|
@ -350,6 +350,7 @@
|
|||||||
<!-- Chat Info Actions - ChatInfoView.kt -->
|
<!-- Chat Info Actions - ChatInfoView.kt -->
|
||||||
<string name="delete_contact_question">Delete contact?</string>
|
<string name="delete_contact_question">Delete contact?</string>
|
||||||
<string name="delete_contact_all_messages_deleted_cannot_undo_warning">Contact and all messages will be deleted - this cannot be undone!</string>
|
<string name="delete_contact_all_messages_deleted_cannot_undo_warning">Contact and all messages will be deleted - this cannot be undone!</string>
|
||||||
|
<string name="delete_and_notify_contact">Delete and notify contact</string>
|
||||||
<string name="button_delete_contact">Delete contact</string>
|
<string name="button_delete_contact">Delete contact</string>
|
||||||
<string name="text_field_set_contact_placeholder">Set contact name…</string>
|
<string name="text_field_set_contact_placeholder">Set contact name…</string>
|
||||||
<string name="icon_descr_server_status_connected">Connected</string>
|
<string name="icon_descr_server_status_connected">Connected</string>
|
||||||
|
@ -9,7 +9,7 @@ constraints: zip +disable-bzip2 +disable-zstd
|
|||||||
source-repository-package
|
source-repository-package
|
||||||
type: git
|
type: git
|
||||||
location: https://github.com/simplex-chat/simplexmq.git
|
location: https://github.com/simplex-chat/simplexmq.git
|
||||||
tag: 2a43717738eaf7a1457f70b48586df19d73a10f3
|
tag: 9dfc0e0e924721cf9c4092887b1fe5c954519cb1
|
||||||
|
|
||||||
source-repository-package
|
source-repository-package
|
||||||
type: git
|
type: git
|
||||||
@ -19,7 +19,7 @@ source-repository-package
|
|||||||
source-repository-package
|
source-repository-package
|
||||||
type: git
|
type: git
|
||||||
location: https://github.com/kazu-yamamoto/http2.git
|
location: https://github.com/kazu-yamamoto/http2.git
|
||||||
tag: b5a1b7200cf5bc7044af34ba325284271f6dff25
|
tag: 804fa283f067bd3fd89b8c5f8d25b3047813a517
|
||||||
|
|
||||||
source-repository-package
|
source-repository-package
|
||||||
type: git
|
type: git
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
name: simplex-chat
|
name: simplex-chat
|
||||||
version: 5.4.0.1
|
version: 5.4.0.2
|
||||||
#synopsis:
|
#synopsis:
|
||||||
#description:
|
#description:
|
||||||
homepage: https://github.com/simplex-chat/simplex-chat#readme
|
homepage: https://github.com/simplex-chat/simplex-chat#readme
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"https://github.com/simplex-chat/simplexmq.git"."2a43717738eaf7a1457f70b48586df19d73a10f3" = "1iqaiw48zvk0s9s2dgpmsmi78nw1q6nkmfi0n3xiv6q23l40sf6c";
|
"https://github.com/simplex-chat/simplexmq.git"."9dfc0e0e924721cf9c4092887b1fe5c954519cb1" = "0c7402727nq0gal64n6jjk3038wqiyw3yczzg0q1b1qkd9nc8r0m";
|
||||||
"https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38";
|
"https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38";
|
||||||
"https://github.com/kazu-yamamoto/http2.git"."b5a1b7200cf5bc7044af34ba325284271f6dff25" = "0dqb50j57an64nf4qcf5vcz4xkd1vzvghvf8bk529c1k30r9nfzb";
|
"https://github.com/kazu-yamamoto/http2.git"."804fa283f067bd3fd89b8c5f8d25b3047813a517" = "1j67wp7rfybfx3ryx08z6gqmzj85j51hmzhgx47ihgmgr47sl895";
|
||||||
"https://github.com/simplex-chat/direct-sqlcipher.git"."34309410eb2069b029b8fc1872deb1e0db123294" = "0kwkmhyfsn2lixdlgl15smgr1h5gjk7fky6abzh8rng2h5ymnffd";
|
"https://github.com/simplex-chat/direct-sqlcipher.git"."34309410eb2069b029b8fc1872deb1e0db123294" = "0kwkmhyfsn2lixdlgl15smgr1h5gjk7fky6abzh8rng2h5ymnffd";
|
||||||
"https://github.com/simplex-chat/sqlcipher-simple.git"."5e154a2aeccc33ead6c243ec07195ab673137221" = "1d1gc5wax4vqg0801ajsmx1sbwvd9y7p7b8mmskvqsmpbwgbh0m0";
|
"https://github.com/simplex-chat/sqlcipher-simple.git"."5e154a2aeccc33ead6c243ec07195ab673137221" = "1d1gc5wax4vqg0801ajsmx1sbwvd9y7p7b8mmskvqsmpbwgbh0m0";
|
||||||
"https://github.com/simplex-chat/aeson.git"."aab7b5a14d6c5ea64c64dcaee418de1bb00dcc2b" = "0jz7kda8gai893vyvj96fy962ncv8dcsx71fbddyy8zrvc88jfrr";
|
"https://github.com/simplex-chat/aeson.git"."aab7b5a14d6c5ea64c64dcaee418de1bb00dcc2b" = "0jz7kda8gai893vyvj96fy962ncv8dcsx71fbddyy8zrvc88jfrr";
|
||||||
|
@ -5,7 +5,7 @@ cabal-version: 1.12
|
|||||||
-- see: https://github.com/sol/hpack
|
-- see: https://github.com/sol/hpack
|
||||||
|
|
||||||
name: simplex-chat
|
name: simplex-chat
|
||||||
version: 5.4.0.1
|
version: 5.4.0.2
|
||||||
category: Web, System, Services, Cryptography
|
category: Web, System, Services, Cryptography
|
||||||
homepage: https://github.com/simplex-chat/simplex-chat#readme
|
homepage: https://github.com/simplex-chat/simplex-chat#readme
|
||||||
author: simplex.chat
|
author: simplex.chat
|
||||||
@ -117,6 +117,7 @@ library
|
|||||||
Simplex.Chat.Migrations.M20231002_conn_initiated
|
Simplex.Chat.Migrations.M20231002_conn_initiated
|
||||||
Simplex.Chat.Migrations.M20231009_via_group_link_uri_hash
|
Simplex.Chat.Migrations.M20231009_via_group_link_uri_hash
|
||||||
Simplex.Chat.Migrations.M20231010_member_settings
|
Simplex.Chat.Migrations.M20231010_member_settings
|
||||||
|
Simplex.Chat.Migrations.M20231019_indexes
|
||||||
Simplex.Chat.Mobile
|
Simplex.Chat.Mobile
|
||||||
Simplex.Chat.Mobile.File
|
Simplex.Chat.Mobile.File
|
||||||
Simplex.Chat.Mobile.Shared
|
Simplex.Chat.Mobile.Shared
|
||||||
|
@ -146,7 +146,10 @@ defaultChatConfig =
|
|||||||
_defaultSMPServers :: NonEmpty SMPServerWithAuth
|
_defaultSMPServers :: NonEmpty SMPServerWithAuth
|
||||||
_defaultSMPServers =
|
_defaultSMPServers =
|
||||||
L.fromList
|
L.fromList
|
||||||
[ "smp://h--vW7ZSkXPeOUpfxlFGgauQmXNFOzGoizak7Ult7cw=@smp15.simplex.im,oauu4bgijybyhczbnxtlggo6hiubahmeutaqineuyy23aojpih3dajad.onion",
|
[ "smp://1OwYGt-yqOfe2IyVHhxz3ohqo3aCCMjtB-8wn4X_aoY=@smp11.simplex.im,6ioorbm6i3yxmuoezrhjk6f6qgkc4syabh7m3so74xunb5nzr4pwgfqd.onion",
|
||||||
|
"smp://UkMFNAXLXeAAe0beCa4w6X_zp18PwxSaSjY17BKUGXQ=@smp12.simplex.im,ie42b5weq7zdkghocs3mgxdjeuycheeqqmksntj57rmejagmg4eor5yd.onion",
|
||||||
|
"smp://enEkec4hlR3UtKx2NMpOUK_K4ZuDxjWBO1d9Y4YXVaA=@smp14.simplex.im,aspkyu2sopsnizbyfabtsicikr2s4r3ti35jogbcekhm3fsoeyjvgrid.onion",
|
||||||
|
"smp://h--vW7ZSkXPeOUpfxlFGgauQmXNFOzGoizak7Ult7cw=@smp15.simplex.im,oauu4bgijybyhczbnxtlggo6hiubahmeutaqineuyy23aojpih3dajad.onion",
|
||||||
"smp://hejn2gVIqNU6xjtGM3OwQeuk8ZEbDXVJXAlnSBJBWUA=@smp16.simplex.im,p3ktngodzi6qrf7w64mmde3syuzrv57y55hxabqcq3l5p6oi7yzze6qd.onion",
|
"smp://hejn2gVIqNU6xjtGM3OwQeuk8ZEbDXVJXAlnSBJBWUA=@smp16.simplex.im,p3ktngodzi6qrf7w64mmde3syuzrv57y55hxabqcq3l5p6oi7yzze6qd.onion",
|
||||||
"smp://ZKe4uxF4Z_aLJJOEsC-Y6hSkXgQS5-oc442JQGkyP8M=@smp17.simplex.im,ogtwfxyi3h2h5weftjjpjmxclhb5ugufa5rcyrmg7j4xlch7qsr5nuqd.onion",
|
"smp://ZKe4uxF4Z_aLJJOEsC-Y6hSkXgQS5-oc442JQGkyP8M=@smp17.simplex.im,ogtwfxyi3h2h5weftjjpjmxclhb5ugufa5rcyrmg7j4xlch7qsr5nuqd.onion",
|
||||||
"smp://PtsqghzQKU83kYTlQ1VKg996dW4Cw4x_bvpKmiv8uns=@smp18.simplex.im,lyqpnwbs2zqfr45jqkncwpywpbtq7jrhxnib5qddtr6npjyezuwd3nqd.onion",
|
"smp://PtsqghzQKU83kYTlQ1VKg996dW4Cw4x_bvpKmiv8uns=@smp18.simplex.im,lyqpnwbs2zqfr45jqkncwpywpbtq7jrhxnib5qddtr6npjyezuwd3nqd.onion",
|
||||||
@ -2242,7 +2245,7 @@ processChatCommand = \case
|
|||||||
case groupLinkId of
|
case groupLinkId of
|
||||||
-- contact address
|
-- contact address
|
||||||
Nothing ->
|
Nothing ->
|
||||||
withStore' (`getUserContactLinkByConnReq` cReqSchemas) >>= \case
|
withStore' (\db -> getUserContactLinkByConnReq db user cReqSchemas) >>= \case
|
||||||
Just _ -> pure $ CPContactAddress CAPOwnLink
|
Just _ -> pure $ CPContactAddress CAPOwnLink
|
||||||
Nothing -> do
|
Nothing -> do
|
||||||
withStore' (\db -> getContactConnEntityByConnReqHash db user cReqHashes) >>= \case
|
withStore' (\db -> getContactConnEntityByConnReqHash db user cReqHashes) >>= \case
|
||||||
|
32
src/Simplex/Chat/Migrations/M20231019_indexes.hs
Normal file
32
src/Simplex/Chat/Migrations/M20231019_indexes.hs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
{-# LANGUAGE QuasiQuotes #-}
|
||||||
|
|
||||||
|
module Simplex.Chat.Migrations.M20231019_indexes where
|
||||||
|
|
||||||
|
import Database.SQLite.Simple (Query)
|
||||||
|
import Database.SQLite.Simple.QQ (sql)
|
||||||
|
|
||||||
|
m20231019_indexes :: Query
|
||||||
|
m20231019_indexes =
|
||||||
|
[sql|
|
||||||
|
DROP INDEX idx_connections_conn_req_inv;
|
||||||
|
CREATE INDEX idx_connections_conn_req_inv ON connections(user_id, conn_req_inv);
|
||||||
|
|
||||||
|
DROP INDEX idx_groups_via_group_link_uri_hash;
|
||||||
|
CREATE INDEX idx_groups_via_group_link_uri_hash ON groups(user_id, via_group_link_uri_hash);
|
||||||
|
|
||||||
|
DROP INDEX idx_connections_via_contact_uri_hash;
|
||||||
|
CREATE INDEX idx_connections_via_contact_uri_hash ON connections(user_id, via_contact_uri_hash);
|
||||||
|
|]
|
||||||
|
|
||||||
|
down_m20231019_indexes :: Query
|
||||||
|
down_m20231019_indexes =
|
||||||
|
[sql|
|
||||||
|
DROP INDEX idx_connections_conn_req_inv;
|
||||||
|
CREATE INDEX idx_connections_conn_req_inv ON connections(conn_req_inv);
|
||||||
|
|
||||||
|
DROP INDEX idx_groups_via_group_link_uri_hash;
|
||||||
|
CREATE INDEX idx_groups_via_group_link_uri_hash ON groups(via_group_link_uri_hash);
|
||||||
|
|
||||||
|
DROP INDEX idx_connections_via_contact_uri_hash;
|
||||||
|
CREATE INDEX idx_connections_via_contact_uri_hash ON connections(via_contact_uri_hash);
|
||||||
|
|]
|
@ -524,9 +524,6 @@ CREATE INDEX contact_profiles_index ON contact_profiles(
|
|||||||
full_name
|
full_name
|
||||||
);
|
);
|
||||||
CREATE INDEX idx_groups_inv_queue_info ON groups(inv_queue_info);
|
CREATE INDEX idx_groups_inv_queue_info ON groups(inv_queue_info);
|
||||||
CREATE INDEX idx_connections_via_contact_uri_hash ON connections(
|
|
||||||
via_contact_uri_hash
|
|
||||||
);
|
|
||||||
CREATE INDEX idx_contact_requests_xcontact_id ON contact_requests(xcontact_id);
|
CREATE INDEX idx_contact_requests_xcontact_id ON contact_requests(xcontact_id);
|
||||||
CREATE INDEX idx_contacts_xcontact_id ON contacts(xcontact_id);
|
CREATE INDEX idx_contacts_xcontact_id ON contacts(xcontact_id);
|
||||||
CREATE INDEX idx_messages_shared_msg_id ON messages(shared_msg_id);
|
CREATE INDEX idx_messages_shared_msg_id ON messages(shared_msg_id);
|
||||||
@ -738,7 +735,15 @@ CREATE INDEX idx_received_probes_probe_hash ON received_probes(probe_hash);
|
|||||||
CREATE INDEX idx_sent_probes_created_at ON sent_probes(created_at);
|
CREATE INDEX idx_sent_probes_created_at ON sent_probes(created_at);
|
||||||
CREATE INDEX idx_sent_probe_hashes_created_at ON sent_probe_hashes(created_at);
|
CREATE INDEX idx_sent_probe_hashes_created_at ON sent_probe_hashes(created_at);
|
||||||
CREATE INDEX idx_received_probes_created_at ON received_probes(created_at);
|
CREATE INDEX idx_received_probes_created_at ON received_probes(created_at);
|
||||||
CREATE INDEX idx_connections_conn_req_inv ON connections(conn_req_inv);
|
CREATE INDEX idx_connections_conn_req_inv ON connections(
|
||||||
|
user_id,
|
||||||
|
conn_req_inv
|
||||||
|
);
|
||||||
CREATE INDEX idx_groups_via_group_link_uri_hash ON groups(
|
CREATE INDEX idx_groups_via_group_link_uri_hash ON groups(
|
||||||
|
user_id,
|
||||||
via_group_link_uri_hash
|
via_group_link_uri_hash
|
||||||
);
|
);
|
||||||
|
CREATE INDEX idx_connections_via_contact_uri_hash ON connections(
|
||||||
|
user_id,
|
||||||
|
via_contact_uri_hash
|
||||||
|
);
|
||||||
|
@ -152,9 +152,9 @@ getConnectionEntity db user@User {userId, userContactId} agentConnId = do
|
|||||||
userContact_ _ = Left SEUserContactLinkNotFound
|
userContact_ _ = Left SEUserContactLinkNotFound
|
||||||
|
|
||||||
getConnectionEntityByConnReq :: DB.Connection -> User -> (ConnReqInvitation, ConnReqInvitation) -> IO (Maybe ConnectionEntity)
|
getConnectionEntityByConnReq :: DB.Connection -> User -> (ConnReqInvitation, ConnReqInvitation) -> IO (Maybe ConnectionEntity)
|
||||||
getConnectionEntityByConnReq db user (cReqSchema1, cReqSchema2) = do
|
getConnectionEntityByConnReq db user@User {userId} (cReqSchema1, cReqSchema2) = do
|
||||||
connId_ <- maybeFirstRow fromOnly $
|
connId_ <- maybeFirstRow fromOnly $
|
||||||
DB.query db "SELECT agent_conn_id FROM connections WHERE conn_req_inv IN (?,?) LIMIT 1" (cReqSchema1, cReqSchema2)
|
DB.query db "SELECT agent_conn_id FROM connections WHERE user_id = ? AND conn_req_inv IN (?,?) LIMIT 1" (userId, cReqSchema1, cReqSchema2)
|
||||||
maybe (pure Nothing) (fmap eitherToMaybe . runExceptT . getConnectionEntity db user) connId_
|
maybe (pure Nothing) (fmap eitherToMaybe . runExceptT . getConnectionEntity db user) connId_
|
||||||
|
|
||||||
-- search connection for connection plan:
|
-- search connection for connection plan:
|
||||||
@ -162,7 +162,7 @@ getConnectionEntityByConnReq db user (cReqSchema1, cReqSchema2) = do
|
|||||||
-- this function searches for latest connection with contact so that "known contact" plan would be chosen;
|
-- this function searches for latest connection with contact so that "known contact" plan would be chosen;
|
||||||
-- deleted connections are filtered out to allow re-connecting via same contact address
|
-- deleted connections are filtered out to allow re-connecting via same contact address
|
||||||
getContactConnEntityByConnReqHash :: DB.Connection -> User -> (ConnReqUriHash, ConnReqUriHash) -> IO (Maybe ConnectionEntity)
|
getContactConnEntityByConnReqHash :: DB.Connection -> User -> (ConnReqUriHash, ConnReqUriHash) -> IO (Maybe ConnectionEntity)
|
||||||
getContactConnEntityByConnReqHash db user (cReqHash1, cReqHash2) = do
|
getContactConnEntityByConnReqHash db user@User {userId} (cReqHash1, cReqHash2) = do
|
||||||
connId_ <- maybeFirstRow fromOnly $
|
connId_ <- maybeFirstRow fromOnly $
|
||||||
DB.query
|
DB.query
|
||||||
db
|
db
|
||||||
@ -172,12 +172,12 @@ getContactConnEntityByConnReqHash db user (cReqHash1, cReqHash2) = do
|
|||||||
agent_conn_id,
|
agent_conn_id,
|
||||||
(CASE WHEN contact_id IS NOT NULL THEN 1 ELSE 0 END) AS conn_ord
|
(CASE WHEN contact_id IS NOT NULL THEN 1 ELSE 0 END) AS conn_ord
|
||||||
FROM connections
|
FROM connections
|
||||||
WHERE via_contact_uri_hash IN (?,?) AND conn_status != ?
|
WHERE user_id = ? AND via_contact_uri_hash IN (?,?) AND conn_status != ?
|
||||||
ORDER BY conn_ord DESC, created_at DESC
|
ORDER BY conn_ord DESC, created_at DESC
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
)
|
)
|
||||||
|]
|
|]
|
||||||
(cReqHash1, cReqHash2, ConnDeleted)
|
(userId, cReqHash1, cReqHash2, ConnDeleted)
|
||||||
maybe (pure Nothing) (fmap eitherToMaybe . runExceptT . getConnectionEntity db user) connId_
|
maybe (pure Nothing) (fmap eitherToMaybe . runExceptT . getConnectionEntity db user) connId_
|
||||||
|
|
||||||
getConnectionsToSubscribe :: DB.Connection -> IO ([ConnId], [ConnectionEntity])
|
getConnectionsToSubscribe :: DB.Connection -> IO ([ConnId], [ConnectionEntity])
|
||||||
|
@ -162,7 +162,7 @@ getContactByConnReqHash db user@User {userId} cReqHash =
|
|||||||
FROM contacts ct
|
FROM contacts ct
|
||||||
JOIN contact_profiles cp ON ct.contact_profile_id = cp.contact_profile_id
|
JOIN contact_profiles cp ON ct.contact_profile_id = cp.contact_profile_id
|
||||||
JOIN connections c ON c.contact_id = ct.contact_id
|
JOIN connections c ON c.contact_id = ct.contact_id
|
||||||
WHERE ct.user_id = ? AND c.via_contact_uri_hash = ? AND ct.contact_status = ? AND ct.deleted = 0
|
WHERE c.user_id = ? AND c.via_contact_uri_hash = ? AND ct.contact_status = ? AND ct.deleted = 0
|
||||||
ORDER BY c.created_at DESC
|
ORDER BY c.created_at DESC
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
|]
|
|]
|
||||||
|
@ -1117,16 +1117,16 @@ getGroupInfo db User {userId, userContactId} groupId =
|
|||||||
(groupId, userId, userContactId)
|
(groupId, userId, userContactId)
|
||||||
|
|
||||||
getGroupInfoByUserContactLinkConnReq :: DB.Connection -> User -> (ConnReqContact, ConnReqContact) -> IO (Maybe GroupInfo)
|
getGroupInfoByUserContactLinkConnReq :: DB.Connection -> User -> (ConnReqContact, ConnReqContact) -> IO (Maybe GroupInfo)
|
||||||
getGroupInfoByUserContactLinkConnReq db user (cReqSchema1, cReqSchema2) = do
|
getGroupInfoByUserContactLinkConnReq db user@User {userId} (cReqSchema1, cReqSchema2) = do
|
||||||
groupId_ <- maybeFirstRow fromOnly $
|
groupId_ <- maybeFirstRow fromOnly $
|
||||||
DB.query
|
DB.query
|
||||||
db
|
db
|
||||||
[sql|
|
[sql|
|
||||||
SELECT group_id
|
SELECT group_id
|
||||||
FROM user_contact_links
|
FROM user_contact_links
|
||||||
WHERE conn_req_contact IN (?,?)
|
WHERE user_id = ? AND conn_req_contact IN (?,?)
|
||||||
|]
|
|]
|
||||||
(cReqSchema1, cReqSchema2)
|
(userId, cReqSchema1, cReqSchema2)
|
||||||
maybe (pure Nothing) (fmap eitherToMaybe . runExceptT . getGroupInfo db user) groupId_
|
maybe (pure Nothing) (fmap eitherToMaybe . runExceptT . getGroupInfo db user) groupId_
|
||||||
|
|
||||||
getGroupInfoByGroupLinkHash :: DB.Connection -> User -> (ConnReqUriHash, ConnReqUriHash) -> IO (Maybe GroupInfo)
|
getGroupInfoByGroupLinkHash :: DB.Connection -> User -> (ConnReqUriHash, ConnReqUriHash) -> IO (Maybe GroupInfo)
|
||||||
|
@ -85,6 +85,7 @@ import Simplex.Chat.Migrations.M20230926_contact_status
|
|||||||
import Simplex.Chat.Migrations.M20231002_conn_initiated
|
import Simplex.Chat.Migrations.M20231002_conn_initiated
|
||||||
import Simplex.Chat.Migrations.M20231009_via_group_link_uri_hash
|
import Simplex.Chat.Migrations.M20231009_via_group_link_uri_hash
|
||||||
import Simplex.Chat.Migrations.M20231010_member_settings
|
import Simplex.Chat.Migrations.M20231010_member_settings
|
||||||
|
import Simplex.Chat.Migrations.M20231019_indexes
|
||||||
import Simplex.Messaging.Agent.Store.SQLite.Migrations (Migration (..))
|
import Simplex.Messaging.Agent.Store.SQLite.Migrations (Migration (..))
|
||||||
|
|
||||||
schemaMigrations :: [(String, Query, Maybe Query)]
|
schemaMigrations :: [(String, Query, Maybe Query)]
|
||||||
@ -169,7 +170,8 @@ schemaMigrations =
|
|||||||
("20230926_contact_status", m20230926_contact_status, Just down_m20230926_contact_status),
|
("20230926_contact_status", m20230926_contact_status, Just down_m20230926_contact_status),
|
||||||
("20231002_conn_initiated", m20231002_conn_initiated, Just down_m20231002_conn_initiated),
|
("20231002_conn_initiated", m20231002_conn_initiated, Just down_m20231002_conn_initiated),
|
||||||
("20231009_via_group_link_uri_hash", m20231009_via_group_link_uri_hash, Just down_m20231009_via_group_link_uri_hash),
|
("20231009_via_group_link_uri_hash", m20231009_via_group_link_uri_hash, Just down_m20231009_via_group_link_uri_hash),
|
||||||
("20231010_member_settings", m20231010_member_settings, Just down_m20231010_member_settings)
|
("20231010_member_settings", m20231010_member_settings, Just down_m20231010_member_settings),
|
||||||
|
("20231019_indexes", m20231019_indexes, Just down_m20231019_indexes)
|
||||||
]
|
]
|
||||||
|
|
||||||
-- | The list of migrations in ascending order by date
|
-- | The list of migrations in ascending order by date
|
||||||
|
@ -437,17 +437,17 @@ getUserContactLinkById db userId userContactLinkId =
|
|||||||
|]
|
|]
|
||||||
(userId, userContactLinkId)
|
(userId, userContactLinkId)
|
||||||
|
|
||||||
getUserContactLinkByConnReq :: DB.Connection -> (ConnReqContact, ConnReqContact) -> IO (Maybe UserContactLink)
|
getUserContactLinkByConnReq :: DB.Connection -> User -> (ConnReqContact, ConnReqContact) -> IO (Maybe UserContactLink)
|
||||||
getUserContactLinkByConnReq db (cReqSchema1, cReqSchema2) =
|
getUserContactLinkByConnReq db User {userId} (cReqSchema1, cReqSchema2) =
|
||||||
maybeFirstRow toUserContactLink $
|
maybeFirstRow toUserContactLink $
|
||||||
DB.query
|
DB.query
|
||||||
db
|
db
|
||||||
[sql|
|
[sql|
|
||||||
SELECT conn_req_contact, auto_accept, auto_accept_incognito, auto_reply_msg_content
|
SELECT conn_req_contact, auto_accept, auto_accept_incognito, auto_reply_msg_content
|
||||||
FROM user_contact_links
|
FROM user_contact_links
|
||||||
WHERE conn_req_contact IN (?,?)
|
WHERE user_id = ? AND conn_req_contact IN (?,?)
|
||||||
|]
|
|]
|
||||||
(cReqSchema1, cReqSchema2)
|
(userId, cReqSchema1, cReqSchema2)
|
||||||
|
|
||||||
updateUserAddressAutoAccept :: DB.Connection -> User -> Maybe AutoAccept -> ExceptT StoreError IO UserContactLink
|
updateUserAddressAutoAccept :: DB.Connection -> User -> Maybe AutoAccept -> ExceptT StoreError IO UserContactLink
|
||||||
updateUserAddressAutoAccept db user@User {userId} autoAccept = do
|
updateUserAddressAutoAccept db user@User {userId} autoAccept = do
|
||||||
|
@ -49,9 +49,9 @@ extra-deps:
|
|||||||
# - simplexmq-1.0.0@sha256:34b2004728ae396e3ae449cd090ba7410781e2b3cefc59259915f4ca5daa9ea8,8561
|
# - simplexmq-1.0.0@sha256:34b2004728ae396e3ae449cd090ba7410781e2b3cefc59259915f4ca5daa9ea8,8561
|
||||||
# - ../simplexmq
|
# - ../simplexmq
|
||||||
- github: simplex-chat/simplexmq
|
- github: simplex-chat/simplexmq
|
||||||
commit: 2a43717738eaf7a1457f70b48586df19d73a10f3
|
commit: 9dfc0e0e924721cf9c4092887b1fe5c954519cb1
|
||||||
- github: kazu-yamamoto/http2
|
- github: kazu-yamamoto/http2
|
||||||
commit: b5a1b7200cf5bc7044af34ba325284271f6dff25
|
commit: 804fa283f067bd3fd89b8c5f8d25b3047813a517
|
||||||
# - ../direct-sqlcipher
|
# - ../direct-sqlcipher
|
||||||
- github: simplex-chat/direct-sqlcipher
|
- github: simplex-chat/direct-sqlcipher
|
||||||
commit: 34309410eb2069b029b8fc1872deb1e0db123294
|
commit: 34309410eb2069b029b8fc1872deb1e0db123294
|
||||||
|
@ -71,7 +71,9 @@ skipComparisonForDownMigrations =
|
|||||||
-- on down migration idx_chat_items_timed_delete_at index moves down to the end of the file
|
-- on down migration idx_chat_items_timed_delete_at index moves down to the end of the file
|
||||||
"20230529_indexes",
|
"20230529_indexes",
|
||||||
-- table and index definitions move down the file, so fields are re-created as not unique
|
-- table and index definitions move down the file, so fields are re-created as not unique
|
||||||
"20230914_member_probes"
|
"20230914_member_probes",
|
||||||
|
-- on down migration idx_connections_via_contact_uri_hash index moves down to the end of the file
|
||||||
|
"20231019_indexes"
|
||||||
]
|
]
|
||||||
|
|
||||||
getSchema :: FilePath -> FilePath -> IO String
|
getSchema :: FilePath -> FilePath -> IO String
|
||||||
|
Loading…
Reference in New Issue
Block a user