Compare commits

..

6 Commits

Author SHA1 Message Date
Avently 4c4794fe33 lib path 2024-12-13 10:31:34 -08:00
Avently f179db9545 package 2024-12-13 10:19:43 -08:00
Avently 52160f2602 change lib name 2024-12-13 10:14:37 -08:00
Avently 2a99a5235b changes 2024-12-13 19:57:06 +07:00
Avently 4fe7b674e6 rename 2024-12-13 16:50:22 +07:00
Avently a5e7fa2f9f nodejs: addon 2024-12-12 22:11:42 +07:00
32 changed files with 1299 additions and 694 deletions
+3 -5
View File
@@ -102,7 +102,7 @@ jobs:
uses: actions/checkout@v3
- name: Setup Haskell
uses: haskell/actions/setup@v2
uses: haskell-actions/setup@v2
with:
ghc-version: ${{ matrix.ghc }}
cabal-version: "3.10.1.0"
@@ -230,7 +230,7 @@ jobs:
APPLE_SIMPLEX_NOTARIZATION_APPLE_ID: ${{ secrets.APPLE_SIMPLEX_NOTARIZATION_APPLE_ID }}
APPLE_SIMPLEX_NOTARIZATION_PASSWORD: ${{ secrets.APPLE_SIMPLEX_NOTARIZATION_PASSWORD }}
run: |
scripts/build-desktop-mac.sh
scripts/ci/build-desktop-mac.sh
path=$(echo $PWD/apps/multiplatform/release/main/dmg/SimpleX-*.dmg)
echo "package_path=$path" >> $GITHUB_OUTPUT
echo "package_hash=$(echo SHA2-512\(${{ matrix.desktop_asset_name }}\)= $(openssl sha512 $path | cut -d' ' -f 2))" >> $GITHUB_OUTPUT
@@ -310,9 +310,7 @@ jobs:
# Unix /
# / Windows
# * In powershell multiline commands do not fail if individual commands fail - https://github.community/t/multiline-commands-on-windows-do-not-fail-if-individual-commands-fail/16753
# * And GitHub Actions does not support parameterizing shell in a matrix job - https://github.community/t/using-matrix-to-specify-shell-is-it-possible/17065
# rm -rf dist-newstyle/src/direct-sq* is here because of the bug in cabal's dependency which prevents second build from finishing
- name: 'Setup MSYS2'
if: matrix.os == 'windows-latest'
+3
View File
@@ -79,3 +79,6 @@ website/package-lock.json
website/.cache
website/test/stubs-layout-cache/_includes/*.js
apps/android/app/release
packages/simplex-chat-nodejs/build
packages/simplex-chat-nodejs/.vscode
packages/simplex-chat-nodejs/libs
+21 -39
View File
@@ -440,7 +440,6 @@ struct ChatView: View {
maxWidth: maxWidth,
composeState: $composeState,
selectedMember: $selectedMember,
showChatInfoSheet: $showChatInfoSheet,
revealedChatItem: $revealedChatItem,
selectedChatItems: $selectedChatItems,
forwardedChatItems: $forwardedChatItems
@@ -894,14 +893,12 @@ struct ChatView: View {
private struct ChatItemWithMenu: View {
@EnvironmentObject var m: ChatModel
@EnvironmentObject var theme: AppTheme
@AppStorage(DEFAULT_PROFILE_IMAGE_CORNER_RADIUS) private var profileRadius = defaultProfileImageCorner
@Binding @ObservedObject var chat: Chat
@ObservedObject var dummyModel: ChatItemDummyModel = .shared
let chatItem: ChatItem
let maxWidth: CGFloat
@Binding var composeState: ComposeState
@Binding var selectedMember: GMember?
@Binding var showChatInfoSheet: Bool
@Binding var revealedChatItem: ChatItem?
@State private var deletingItem: ChatItem? = nil
@@ -1258,22 +1255,16 @@ struct ChatView: View {
setReaction(ci, add: !r.userReacted, reaction: r.reaction)
}
}
switch chat.chatInfo {
case let .group(groupInfo):
if case let .group(groupInfo) = chat.chatInfo {
v.contextMenu {
ReactionContextMenu(
groupInfo: groupInfo,
itemId: ci.id,
reactionCount: r,
selectedMember: $selectedMember,
profileRadius: profileRadius
selectedMember: $selectedMember
)
}
case let .direct(contact):
v.contextMenu {
contactReactionMenu(contact, r)
}
default:
} else {
v
}
}
@@ -1776,20 +1767,6 @@ struct ChatView: View {
}
}
}
@ViewBuilder private func contactReactionMenu(_ contact: Contact, _ r: CIReactionCount) -> some View {
if !r.userReacted || r.totalReacted > 1 {
Button { showChatInfoSheet = true } label: {
profileMenuItem(Text(contact.displayName), contact.image, radius: profileRadius)
}
}
if r.userReacted {
Button {} label: {
profileMenuItem(Text("you"), m.currentUser?.profile.image, radius: profileRadius)
}
.disabled(true)
}
}
private struct SelectedChatItem: View {
@EnvironmentObject var theme: AppTheme
@@ -1882,12 +1859,13 @@ struct ReactionContextMenu: View {
var itemId: Int64
var reactionCount: CIReactionCount
@Binding var selectedMember: GMember?
var profileRadius: CGFloat
@State private var memberReactions: [MemberReaction] = []
@AppStorage(DEFAULT_PROFILE_IMAGE_CORNER_RADIUS) private var radius = defaultProfileImageCorner
var body: some View {
groupMemberReactionList()
.task {
logger.debug("ReactionContextMenu task \(radius)")
await loadChatItemReaction()
}
}
@@ -1911,12 +1889,27 @@ struct ReactionContextMenu: View {
selectedMember = member
}
} label: {
profileMenuItem(Text(mem.displayName), mem.image, radius: profileRadius)
HStack {
Text(mem.displayName)
if let img = cropImage(mem.image) {
Image(uiImage: img)
} else {
Image(systemName: "person.crop.circle")
}
}
}
.disabled(userMember)
}
}
}
private func cropImage(_ img: String?) -> UIImage? {
return if let originalImage = imageFromBase64(img) {
maskToCustomShape(originalImage, size: 30, radius: radius)
} else {
nil
}
}
private func loadChatItemReaction() async {
do {
@@ -1934,17 +1927,6 @@ struct ReactionContextMenu: View {
}
}
func profileMenuItem(_ nameText: Text, _ image: String?, radius: CGFloat) -> some View {
HStack {
nameText
if let image, let img = imageFromBase64(image) {
Image(uiImage: maskToCustomShape(img, size: 30, radius: radius))
} else {
Image(systemName: "person.crop.circle")
}
}
}
func maskToCustomShape(_ image: UIImage, size: CGFloat, radius: CGFloat) -> UIImage {
let path = Path { path in
if radius >= 50 {
+20 -20
View File
@@ -1931,7 +1931,7 @@
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 255;
CURRENT_PROJECT_VERSION = 254;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
@@ -1956,7 +1956,7 @@
"@executable_path/Frameworks",
);
LLVM_LTO = YES_THIN;
MARKETING_VERSION = 6.2.1;
MARKETING_VERSION = 6.2;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
PRODUCT_NAME = SimpleX;
SDKROOT = iphoneos;
@@ -1980,7 +1980,7 @@
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 255;
CURRENT_PROJECT_VERSION = 254;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
@@ -2005,7 +2005,7 @@
"@executable_path/Frameworks",
);
LLVM_LTO = YES;
MARKETING_VERSION = 6.2.1;
MARKETING_VERSION = 6.2;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
PRODUCT_NAME = SimpleX;
SDKROOT = iphoneos;
@@ -2021,11 +2021,11 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 255;
CURRENT_PROJECT_VERSION = 254;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
MARKETING_VERSION = 6.2.1;
MARKETING_VERSION = 6.2;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.Tests-iOS";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -2041,11 +2041,11 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 255;
CURRENT_PROJECT_VERSION = 254;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
MARKETING_VERSION = 6.2.1;
MARKETING_VERSION = 6.2;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.Tests-iOS";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -2066,7 +2066,7 @@
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 255;
CURRENT_PROJECT_VERSION = 254;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
GCC_OPTIMIZATION_LEVEL = s;
@@ -2081,7 +2081,7 @@
"@executable_path/../../Frameworks",
);
LLVM_LTO = YES;
MARKETING_VERSION = 6.2.1;
MARKETING_VERSION = 6.2;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -2103,7 +2103,7 @@
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 255;
CURRENT_PROJECT_VERSION = 254;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
ENABLE_CODE_COVERAGE = NO;
@@ -2118,7 +2118,7 @@
"@executable_path/../../Frameworks",
);
LLVM_LTO = YES;
MARKETING_VERSION = 6.2.1;
MARKETING_VERSION = 6.2;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -2140,7 +2140,7 @@
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES;
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 255;
CURRENT_PROJECT_VERSION = 254;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
DYLIB_COMPATIBILITY_VERSION = 1;
@@ -2166,7 +2166,7 @@
"$(PROJECT_DIR)/Libraries/sim",
);
LLVM_LTO = YES;
MARKETING_VERSION = 6.2.1;
MARKETING_VERSION = 6.2;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SDKROOT = iphoneos;
@@ -2191,7 +2191,7 @@
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES;
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 255;
CURRENT_PROJECT_VERSION = 254;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
DYLIB_COMPATIBILITY_VERSION = 1;
@@ -2217,7 +2217,7 @@
"$(PROJECT_DIR)/Libraries/sim",
);
LLVM_LTO = YES;
MARKETING_VERSION = 6.2.1;
MARKETING_VERSION = 6.2;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SDKROOT = iphoneos;
@@ -2242,7 +2242,7 @@
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CODE_SIGN_ENTITLEMENTS = "SimpleX SE/SimpleX SE.entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 255;
CURRENT_PROJECT_VERSION = 254;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
@@ -2257,7 +2257,7 @@
"@executable_path/../../Frameworks",
);
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MARKETING_VERSION = 6.2.1;
MARKETING_VERSION = 6.2;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-SE";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -2276,7 +2276,7 @@
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CODE_SIGN_ENTITLEMENTS = "SimpleX SE/SimpleX SE.entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 255;
CURRENT_PROJECT_VERSION = 254;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
@@ -2291,7 +2291,7 @@
"@executable_path/../../Frameworks",
);
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MARKETING_VERSION = 6.2.1;
MARKETING_VERSION = 6.2;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-SE";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -1,11 +1,10 @@
package chat.simplex.common.platform
import android.util.Log
import chat.simplex.common.model.ChatController.appPrefs
actual object Log {
actual fun d(tag: String, text: String) { if (appPrefs.logLevel.get() <= LogLevel.DEBUG && appPrefs.developerTools.get()) Log.d(tag, text) }
actual fun e(tag: String, text: String) { if (appPrefs.logLevel.get() <= LogLevel.ERROR || !appPrefs.developerTools.get()) Log.e(tag, text) }
actual fun i(tag: String, text: String) { if (appPrefs.logLevel.get() <= LogLevel.INFO && appPrefs.developerTools.get()) Log.i(tag, text) }
actual fun w(tag: String, text: String) { if (appPrefs.logLevel.get() <= LogLevel.WARNING || !appPrefs.developerTools.get()) Log.w(tag, text) }
actual fun d(tag: String, text: String) = Log.d(tag, text).run{}
actual fun e(tag: String, text: String) = Log.e(tag, text).run{}
actual fun i(tag: String, text: String) = Log.i(tag, text).run{}
actual fun w(tag: String, text: String) = Log.w(tag, text).run{}
}
@@ -54,11 +54,10 @@ add_library( # Sets the name of the library.
simplex-api.c)
add_library( simplex SHARED IMPORTED )
FILE(GLOB SIMPLEXLIB ${CMAKE_SOURCE_DIR}/libs/${OS_LIB_PATH}-${OS_LIB_ARCH}/libsimplex.${OS_LIB_EXT})
if(WIN32)
FILE(GLOB SIMPLEXLIB ${CMAKE_SOURCE_DIR}/libs/${OS_LIB_PATH}-${OS_LIB_ARCH}/lib*simplex*.${OS_LIB_EXT})
set_target_properties( simplex PROPERTIES IMPORTED_IMPLIB ${SIMPLEXLIB})
else()
FILE(GLOB SIMPLEXLIB ${CMAKE_SOURCE_DIR}/libs/${OS_LIB_PATH}-${OS_LIB_ARCH}/lib*simplex-chat*.${OS_LIB_EXT})
set_target_properties( simplex PROPERTIES IMPORTED_LOCATION ${SIMPLEXLIB})
endif()
@@ -71,7 +70,7 @@ if(NOT APPLE)
else()
# Without direct linking it can't find hs_init in linking step
add_library( rts SHARED IMPORTED )
FILE(GLOB RTSLIB ${CMAKE_SOURCE_DIR}/libs/${OS_LIB_PATH}-${OS_LIB_ARCH}/deps/libHSrts*_thr-*.${OS_LIB_EXT})
FILE(GLOB RTSLIB ${CMAKE_SOURCE_DIR}/libs/${OS_LIB_PATH}-${OS_LIB_ARCH}/libHSrts*_thr-*.${OS_LIB_EXT})
set_target_properties( rts PROPERTIES IMPORTED_LOCATION ${RTSLIB})
target_link_libraries(app-lib rts simplex)
@@ -132,7 +132,6 @@ class AppPreferences {
val chatLastStart = mkDatePreference(SHARED_PREFS_CHAT_LAST_START, null)
val chatStopped = mkBoolPreference(SHARED_PREFS_CHAT_STOPPED, false)
val developerTools = mkBoolPreference(SHARED_PREFS_DEVELOPER_TOOLS, false)
val logLevel = mkEnumPreference(SHARED_PREFS_LOG_LEVEL, LogLevel.WARNING) { LogLevel.entries.firstOrNull { it.name == this } }
val showInternalErrors = mkBoolPreference(SHARED_PREFS_SHOW_INTERNAL_ERRORS, false)
val showSlowApiCalls = mkBoolPreference(SHARED_PREFS_SHOW_SLOW_API_CALLS, false)
val terminalAlwaysVisible = mkBoolPreference(SHARED_PREFS_TERMINAL_ALWAYS_VISIBLE, false)
@@ -394,7 +393,6 @@ class AppPreferences {
private const val SHARED_PREFS_CHAT_LAST_START = "ChatLastStart"
private const val SHARED_PREFS_CHAT_STOPPED = "ChatStopped"
private const val SHARED_PREFS_DEVELOPER_TOOLS = "DeveloperTools"
private const val SHARED_PREFS_LOG_LEVEL = "LogLevel"
private const val SHARED_PREFS_SHOW_INTERNAL_ERRORS = "ShowInternalErrors"
private const val SHARED_PREFS_SHOW_SLOW_API_CALLS = "ShowSlowApiCalls"
private const val SHARED_PREFS_TERMINAL_ALWAYS_VISIBLE = "TerminalAlwaysVisible"
@@ -2,10 +2,6 @@ package chat.simplex.common.platform
const val TAG = "SIMPLEX"
enum class LogLevel {
DEBUG, INFO, WARNING, ERROR
}
expect object Log {
fun d(tag: String, text: String)
fun e(tag: String, text: String)
@@ -296,7 +296,6 @@ fun ChatItemInfoView(chatRh: Long?, ci: ChatItem, ciInfo: ChatItemInfo, devTools
}
}
SectionBottomSpacer()
SectionBottomSpacer()
}
}
@@ -310,7 +309,6 @@ fun ChatItemInfoView(chatRh: Long?, ci: ChatItem, ciInfo: ChatItemInfo, devTools
QuotedMsgView(qi)
}
SectionBottomSpacer()
SectionBottomSpacer()
}
}
@@ -326,7 +324,6 @@ fun ChatItemInfoView(chatRh: Long?, ci: ChatItem, ciInfo: ChatItemInfo, devTools
ForwardedFromView(forwardedFromItem)
}
SectionBottomSpacer()
SectionBottomSpacer()
}
}
@@ -398,7 +395,6 @@ fun ChatItemInfoView(chatRh: Long?, ci: ChatItem, ciInfo: ChatItemInfo, devTools
}
}
SectionBottomSpacer()
SectionBottomSpacer()
}
}
@@ -437,11 +433,12 @@ fun ChatItemInfoView(chatRh: Long?, ci: ChatItem, ciInfo: ChatItemInfo, devTools
Column {
if (numTabs() > 1) {
Box(
Column(
Modifier
.fillMaxHeight()
.fillMaxHeight(),
verticalArrangement = Arrangement.SpaceBetween
) {
Column {
Column(Modifier.weight(1f)) {
when (val sel = selection.value) {
is CIInfoTab.Delivery -> {
DeliveryTab(sel.memberDeliveryStatuses)
@@ -482,7 +479,7 @@ fun ChatItemInfoView(chatRh: Long?, ci: ChatItem, ciInfo: ChatItemInfo, devTools
}
}
val oneHandUI = remember { appPrefs.oneHandUI.state }
Box(Modifier.align(Alignment.BottomCenter).navigationBarsPadding().offset(x = 0.dp, y = if (oneHandUI.value) -AppBarHeight * fontSizeSqrtMultiplier else 0.dp)) {
Box(Modifier.offset(x = 0.dp, y = if (oneHandUI.value) -AppBarHeight * fontSizeSqrtMultiplier else 0.dp)) {
TabRow(
selectedTabIndex = availableTabs.indexOfFirst { it::class == selection.value::class },
Modifier.height(AppBarHeight * fontSizeSqrtMultiplier),
@@ -665,18 +665,13 @@ fun ChatLayout(
AdaptingBottomPaddingLayout(Modifier, CHAT_COMPOSE_LAYOUT_ID, composeViewHeight) {
if (chatInfo != null) {
Box(Modifier.fillMaxSize()) {
// disables scrolling to top of chat item on click inside the bubble
CompositionLocalProvider(LocalBringIntoViewSpec provides object : BringIntoViewSpec {
override fun calculateScrollDistance(offset: Float, size: Float, containerSize: Float): Float = 0f
}) {
ChatItemsList(
remoteHostId, chatInfo, unreadCount, composeState, composeViewHeight, searchValue,
useLinkPreviews, linkMode, selectedChatItems, showMemberInfo, showChatInfo = info, loadMessages, deleteMessage, deleteMessages,
receiveFile, cancelFile, joinGroup, acceptCall, acceptFeature, openDirectChat, forwardItem,
updateContactStats, updateMemberStats, syncContactConnection, syncMemberConnection, findModelChat, findModelMember,
setReaction, showItemDetails, markItemsRead, markChatRead, remember { { onComposed(it) } }, developerTools, showViaProxy,
)
}
ChatItemsList(
remoteHostId, chatInfo, unreadCount, composeState, composeViewHeight, searchValue,
useLinkPreviews, linkMode, selectedChatItems, showMemberInfo, loadMessages, deleteMessage, deleteMessages,
receiveFile, cancelFile, joinGroup, acceptCall, acceptFeature, openDirectChat, forwardItem,
updateContactStats, updateMemberStats, syncContactConnection, syncMemberConnection, findModelChat, findModelMember,
setReaction, showItemDetails, markItemsRead, markChatRead, remember { { onComposed(it) } }, developerTools, showViaProxy,
)
}
}
Box(
@@ -944,7 +939,6 @@ fun BoxScope.ChatItemsList(
linkMode: SimplexLinkMode,
selectedChatItems: MutableState<Set<Long>?>,
showMemberInfo: (GroupInfo, GroupMember) -> Unit,
showChatInfo: () -> Unit,
loadMessages: suspend (ChatId, ChatPagination, ActiveChatState, visibleItemIndexesNonReversed: () -> IntRange) -> Unit,
deleteMessage: (Long, CIDeleteMode) -> Unit,
deleteMessages: (List<Long>) -> Unit,
@@ -1072,7 +1066,7 @@ fun BoxScope.ChatItemsList(
highlightedItems.value = setOf()
}
}
ChatItemView(remoteHostId, chatInfo, cItem, composeState, provider, useLinkPreviews = useLinkPreviews, linkMode = linkMode, revealed = revealed, highlighted = highlighted, range = range, fillMaxWidth = fillMaxWidth, selectedChatItems = selectedChatItems, selectChatItem = { selectUnselectChatItem(true, cItem, revealed, selectedChatItems) }, deleteMessage = deleteMessage, deleteMessages = deleteMessages, receiveFile = receiveFile, cancelFile = cancelFile, joinGroup = joinGroup, acceptCall = acceptCall, acceptFeature = acceptFeature, openDirectChat = openDirectChat, forwardItem = forwardItem, updateContactStats = updateContactStats, updateMemberStats = updateMemberStats, syncContactConnection = syncContactConnection, syncMemberConnection = syncMemberConnection, findModelChat = findModelChat, findModelMember = findModelMember, scrollToItem = scrollToItem, scrollToQuotedItemFromItem = scrollToQuotedItemFromItem, setReaction = setReaction, showItemDetails = showItemDetails, reveal = reveal, showMemberInfo = showMemberInfo, showChatInfo = showChatInfo, developerTools = developerTools, showViaProxy = showViaProxy, itemSeparation = itemSeparation, showTimestamp = itemSeparation.timestamp)
ChatItemView(remoteHostId, chatInfo, cItem, composeState, provider, useLinkPreviews = useLinkPreviews, linkMode = linkMode, revealed = revealed, highlighted = highlighted, range = range, fillMaxWidth = fillMaxWidth, selectedChatItems = selectedChatItems, selectChatItem = { selectUnselectChatItem(true, cItem, revealed, selectedChatItems) }, deleteMessage = deleteMessage, deleteMessages = deleteMessages, receiveFile = receiveFile, cancelFile = cancelFile, joinGroup = joinGroup, acceptCall = acceptCall, acceptFeature = acceptFeature, openDirectChat = openDirectChat, forwardItem = forwardItem, updateContactStats = updateContactStats, updateMemberStats = updateMemberStats, syncContactConnection = syncContactConnection, syncMemberConnection = syncMemberConnection, findModelChat = findModelChat, findModelMember = findModelMember, scrollToItem = scrollToItem, scrollToQuotedItemFromItem = scrollToQuotedItemFromItem, setReaction = setReaction, showItemDetails = showItemDetails, reveal = reveal, showMemberInfo = showMemberInfo, developerTools = developerTools, showViaProxy = showViaProxy, itemSeparation = itemSeparation, showTimestamp = itemSeparation.timestamp)
}
}
@@ -24,12 +24,12 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.*
import chat.simplex.common.model.*
import chat.simplex.common.model.ChatModel.controller
import chat.simplex.common.model.ChatModel.currentUser
import chat.simplex.common.platform.*
import chat.simplex.common.ui.theme.*
import chat.simplex.common.views.chat.*
import chat.simplex.common.views.helpers.*
import chat.simplex.res.MR
import kotlinx.coroutines.launch
import kotlinx.datetime.Clock
import kotlin.math.*
@@ -51,12 +51,6 @@ fun chatEventText(eventText: String, ts: String): AnnotatedString =
withStyle(chatEventStyle) { append("$eventText $ts") }
}
data class ChatItemReactionMenuItem (
val name: String,
val image: String?,
val onClick: (() -> Unit)?
)
@Composable
fun ChatItemView(
rhId: Long?,
@@ -93,7 +87,6 @@ fun ChatItemView(
showItemDetails: (ChatInfo, ChatItem) -> Unit,
reveal: (Boolean) -> Unit,
showMemberInfo: (GroupInfo, GroupMember) -> Unit,
showChatInfo: () -> Unit,
developerTools: Boolean,
showViaProxy: Boolean,
showTimestamp: Boolean,
@@ -127,7 +120,7 @@ fun ChatItemView(
Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.chatItemOffset(cItem, itemSeparation.largeGap, inverted = true, revealed = true)) {
cItem.reactions.forEach { r ->
val showReactionMenu = remember { mutableStateOf(false) }
val reactionMenuItems = remember { mutableStateOf(emptyList<ChatItemReactionMenuItem>()) }
val reactionMembers = remember { mutableStateOf(emptyList<MemberReaction>()) }
val interactionSource = remember { MutableInteractionSource() }
val enterInteraction = remember { HoverInteraction.Enter() }
KeyChangeEffect(highlighted.value) {
@@ -141,39 +134,18 @@ fun ChatItemView(
var modifier = Modifier.padding(horizontal = 5.dp, vertical = 2.dp).clip(RoundedCornerShape(8.dp))
if (cInfo.featureEnabled(ChatFeature.Reactions)) {
fun showReactionsMenu() {
when (cInfo) {
is ChatInfo.Group -> {
withBGApi {
try {
val members = controller.apiGetReactionMembers(rhId, cInfo.groupInfo.groupId, cItem.id, r.reaction)
if (members != null) {
showReactionMenu.value = true
reactionMenuItems.value = members.map {
val enabled = cInfo.groupInfo.membership.groupMemberId != it.groupMember.groupMemberId
val click = if (enabled) ({ showMemberInfo(cInfo.groupInfo, it.groupMember) }) else null
ChatItemReactionMenuItem(it.groupMember.displayName, it.groupMember.image, click)
}
}
} catch (e: Exception) {
Log.d(TAG, "chatItemView ChatItemReactions onLongClick: unexpected exception: ${e.stackTraceToString()}")
if (cInfo is ChatInfo.Group) {
withBGApi {
try {
val members = controller.apiGetReactionMembers(rhId, cInfo.groupInfo.groupId, cItem.id, r.reaction)
if (members != null) {
showReactionMenu.value = true
reactionMembers.value = members
}
} catch (e: Exception) {
Log.d(TAG, "hatItemView ChatItemReactions onLongClick: unexpected exception: ${e.stackTraceToString()}")
}
}
is ChatInfo.Direct -> {
showReactionMenu.value = true
val reactions = mutableListOf<ChatItemReactionMenuItem>()
if (!r.userReacted || r.totalReacted > 1) {
val contact = cInfo.contact
reactions.add(ChatItemReactionMenuItem(contact.displayName, contact.image, showChatInfo))
}
if (r.userReacted) {
reactions.add(ChatItemReactionMenuItem(generalGetString(MR.strings.sender_you_pronoun), currentUser.value?.image, null))
}
reactionMenuItems.value = reactions
}
else -> {}
}
}
modifier = modifier
@@ -194,19 +166,19 @@ fun ChatItemView(
Row(modifier.padding(2.dp), verticalAlignment = Alignment.CenterVertically) {
ReactionIcon(r.reaction.text, fontSize = 12.sp)
DefaultDropdownMenu(showMenu = showReactionMenu) {
reactionMenuItems.value.forEach { m ->
reactionMembers.value.forEach { m ->
ItemAction(
text = m.name,
composable = { ProfileImage(44.dp, m.image) },
text = m.groupMember.displayName,
composable = { ProfileImage(44.dp, m.groupMember.image) },
onClick = {
val click = m.onClick
if (click != null) {
click()
if (cInfo is ChatInfo.Group && cInfo.groupInfo.membership.groupMemberId != m.groupMember.groupMemberId) {
showMemberInfo(cInfo.groupInfo, m.groupMember)
showReactionMenu.value = false
} else {
showReactionMenu.value = false
}
},
lineLimit = 1,
color = if (m.onClick == null) MaterialTheme.colors.secondary else MenuTextColor
lineLimit = 1
)
}
}
@@ -1216,7 +1188,6 @@ fun PreviewChatItemView(
showItemDetails = { _, _ -> },
reveal = {},
showMemberInfo = { _, _ ->},
showChatInfo = {},
developerTools = false,
showViaProxy = false,
showTimestamp = true,
@@ -1262,7 +1233,6 @@ fun PreviewChatItemViewDeletedContent() {
showItemDetails = { _, _ -> },
reveal = {},
showMemberInfo = { _, _ ->},
showChatInfo = {},
developerTools = false,
showViaProxy = false,
preview = true,
@@ -30,7 +30,6 @@ import kotlinx.datetime.*
import java.io.*
import java.net.URI
import java.nio.file.Files
import java.nio.file.StandardCopyOption
import java.text.SimpleDateFormat
import java.util.*
import kotlin.collections.ArrayList
@@ -45,14 +44,11 @@ fun DatabaseView() {
val chatArchiveFile = remember { mutableStateOf<String?>(null) }
val stopped = remember { m.chatRunning }.value == false
val saveArchiveLauncher = rememberFileChooserLauncher(false) { to: URI? ->
val archive = chatArchiveFile.value
if (archive != null && to != null) {
copyFileToFile(File(archive), to) {}
}
// delete no matter the database was exported or canceled the export process
if (archive != null) {
File(archive).delete()
chatArchiveFile.value = null
val file = chatArchiveFile.value
if (file != null && to != null) {
copyFileToFile(File(file), to) {
chatArchiveFile.value = null
}
}
}
val appFilesCountAndSize = remember { mutableStateOf(directoryFileCountAndSize(appFilesDir.absolutePath)) }
@@ -684,8 +680,6 @@ suspend fun importArchive(
} finally {
File(archivePath).delete()
}
} else {
progressIndicator.value = false
}
return false
}
@@ -697,15 +691,14 @@ private fun saveArchiveFromURI(importedArchiveURI: URI): String? {
if (inputStream != null && archiveName != null) {
val archivePath = "$databaseExportDir${File.separator}$archiveName"
val destFile = File(archivePath)
Files.copy(inputStream, destFile.toPath(), StandardCopyOption.REPLACE_EXISTING)
Files.copy(inputStream, destFile.toPath())
archivePath
} else {
Log.e(TAG, "saveArchiveFromURI null inputStream")
null
}
} catch (e: Exception) {
AlertManager.shared.showAlertMsg(generalGetString(MR.strings.error_saving_database), e.stackTraceToString())
Log.e(TAG, "saveArchiveFromURI error: ${e.stackTraceToString()}")
Log.e(TAG, "saveArchiveFromURI error: ${e.message}")
null
}
}
@@ -14,7 +14,6 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalUriHandler
import chat.simplex.common.model.*
import chat.simplex.common.model.ChatController.appPrefs
import chat.simplex.common.platform.*
import dev.icerock.moko.resources.compose.painterResource
import dev.icerock.moko.resources.compose.stringResource
@@ -45,12 +44,6 @@ fun DeveloperView(withAuth: (title: String, desc: String, block: () -> Unit) ->
if (devTools.value) {
SectionDividerSpaced(maxTopPadding = true)
SectionView(stringResource(MR.strings.developer_options_section).uppercase()) {
SettingsActionItemWithContent(painterResource(MR.images.ic_breaking_news), stringResource(MR.strings.debug_logs)) {
DefaultSwitch(
checked = remember { appPrefs.logLevel.state }.value <= LogLevel.DEBUG,
onCheckedChange = { appPrefs.logLevel.set(if (it) LogLevel.DEBUG else LogLevel.WARNING) }
)
}
SettingsPreferenceItem(painterResource(MR.images.ic_drive_folder_upload), stringResource(MR.strings.confirm_database_upgrades), m.controller.appPrefs.confirmDBUpgrades)
if (appPlatform.isDesktop) {
TerminalAlwaysVisibleItem(m.controller.appPrefs.terminalAlwaysVisible) { checked ->
@@ -907,7 +907,6 @@
<string name="show_dev_options">Show:</string>
<string name="hide_dev_options">Hide:</string>
<string name="show_developer_options">Show developer options</string>
<string name="debug_logs">Enable logs</string>
<string name="developer_options">Database IDs and Transport isolation option.</string>
<string name="developer_options_section">Developer options</string>
<string name="show_internal_errors">Show internal errors</string>
@@ -1339,7 +1338,6 @@
<string name="chat_database_exported_migrate">You may migrate the exported database.</string>
<string name="chat_database_exported_not_all_files">Some file(s) were not exported</string>
<string name="chat_database_exported_continue">Continue</string>
<string name="error_saving_database">Error saving database</string>
<!-- DatabaseEncryptionView.kt -->
<string name="save_passphrase_in_keychain">Save passphrase in Keystore</string>
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" height="22px" viewBox="0 -960 960 960" width="22px" fill="#5f6368"><path d="M262.5-285q11.5 0 20.25-8.5t8.75-20q0-11.5-8.75-20.25t-20.25-8.75q-11.5 0-20 8.75T234-313.5q0 11.5 8.5 20t20 8.5Zm-29-168.5H291v-227h-57.5v227Zm217.5 174h275.5V-337H451v57.5Zm0-174h275.5V-511H451v57.5Zm0-169.5h275.5v-57.5H451v57.5ZM134.5-124.5q-22.97 0-40.23-17.27Q77-159.03 77-182v-596q0-22.97 17.27-40.23 17.26-17.27 40.23-17.27h691q22.97 0 40.23 17.27Q883-800.97 883-778v596q0 22.97-17.27 40.23-17.26 17.27-40.23 17.27h-691Zm0-57.5h691v-596h-691v596Zm0 0v-596 596Z"/></svg>

Before

Width:  |  Height:  |  Size: 592 B

@@ -67,7 +67,7 @@ object NtfManager {
ntf.second.close()
} catch (e: Exception) {
// Can be java.lang.UnsupportedOperationException, for example. May do nothing
Log.e(TAG, "Failed to close notification: ${e.stackTraceToString()}")
println("Failed to close notification: ${e.stackTraceToString()}")
}*/
}
}
@@ -85,8 +85,7 @@ object NtfManager {
}
fun cancelAllNotifications() {
// prevNtfs.forEach { try { it.second.close() } catch (e: Exception) { Log.e(TAG, "Failed to close notification: ${e
// .stackTraceToString()}") } }
// prevNtfs.forEach { try { it.second.close() } catch (e: Exception) { println("Failed to close notification: ${e.stackTraceToString()}") } }
withBGApi {
prevNtfsMutex.withLock {
prevNtfs.clear()
@@ -154,7 +153,7 @@ object NtfManager {
ImageIO.write(icon.toAwtImage(), "PNG", newFile.outputStream())
newFile.absolutePath
} catch (e: Exception) {
Log.e(TAG, "Failed to write an icon to tmpDir: ${e.stackTraceToString()}")
println("Failed to write an icon to tmpDir: ${e.stackTraceToString()}")
null
}
} else null
@@ -1,10 +1,8 @@
package chat.simplex.common.platform
import chat.simplex.common.model.ChatController.appPrefs
actual object Log {
actual fun d(tag: String, text: String) { if (appPrefs.logLevel.get() <= LogLevel.DEBUG && appPrefs.developerTools.get()) println("D: $text") }
actual fun e(tag: String, text: String) { if (appPrefs.logLevel.get() <= LogLevel.ERROR || !appPrefs.developerTools.get()) println("E: $text") }
actual fun i(tag: String, text: String) { if (appPrefs.logLevel.get() <= LogLevel.INFO && appPrefs.developerTools.get()) println("I: $text") }
actual fun w(tag: String, text: String) { if (appPrefs.logLevel.get() <= LogLevel.WARNING || !appPrefs.developerTools.get()) println("W: $text") }
actual fun d(tag: String, text: String) = println("D: $text")
actual fun e(tag: String, text: String) = println("E: $text")
actual fun i(tag: String, text: String) = println("I: $text")
actual fun w(tag: String, text: String) = println("W: $text")
}
+4 -4
View File
@@ -24,11 +24,11 @@ android.nonTransitiveRClass=true
kotlin.mpp.androidSourceSetLayoutVersion=2
kotlin.jvm.target=11
android.version_name=6.2.1
android.version_code=261
android.version_name=6.2
android.version_code=259
desktop.version_name=6.2.1
desktop.version_code=83
desktop.version_name=6.2
desktop.version_code=82
kotlin.version=1.9.23
gradle.plugin.version=8.2.0
Generated
+281 -469
View File
@@ -16,21 +16,6 @@
"type": "github"
}
},
"blank": {
"locked": {
"lastModified": 1625557891,
"narHash": "sha256-O8/MWsPBGhhyPoPLHZAuoZiiHo9q6FLlEeIDEXuj6T4=",
"owner": "divnix",
"repo": "blank",
"rev": "5a5d2684073d9f563072ed07c871d577a6c614a8",
"type": "github"
},
"original": {
"owner": "divnix",
"repo": "blank",
"type": "github"
}
},
"cabal-32": {
"flake": false,
"locked": {
@@ -98,64 +83,6 @@
"type": "github"
}
},
"devshell": {
"inputs": {
"flake-utils": [
"haskellNix",
"tullia",
"std",
"flake-utils"
],
"nixpkgs": [
"haskellNix",
"tullia",
"std",
"nixpkgs"
]
},
"locked": {
"lastModified": 1663445644,
"narHash": "sha256-+xVlcK60x7VY1vRJbNUEAHi17ZuoQxAIH4S4iUFUGBA=",
"owner": "numtide",
"repo": "devshell",
"rev": "e3dc3e21594fe07bdb24bdf1c8657acaa4cb8f66",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "devshell",
"type": "github"
}
},
"dmerge": {
"inputs": {
"nixlib": [
"haskellNix",
"tullia",
"std",
"nixpkgs"
],
"yants": [
"haskellNix",
"tullia",
"std",
"yants"
]
},
"locked": {
"lastModified": 1659548052,
"narHash": "sha256-fzI2gp1skGA8mQo/FBFrUAtY0GQkAIAaV/V127TJPyY=",
"owner": "divnix",
"repo": "data-merge",
"rev": "d160d18ce7b1a45b88344aa3f13ed1163954b497",
"type": "github"
},
"original": {
"owner": "divnix",
"repo": "data-merge",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
@@ -173,74 +100,34 @@
"type": "github"
}
},
"flake-compat_2": {
"flake": false,
"flake-parts": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1650374568,
"narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "b4a34015c698c7793d592d66adbab377907a2be8",
"lastModified": 1698579227,
"narHash": "sha256-KVWjFZky+gRuWennKsbo6cWyo7c/z/VgCte5pR9pEKg=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "f76e870d64779109e41370848074ac4eaa1606ec",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-utils": {
"locked": {
"lastModified": 1676283394,
"narHash": "sha256-XX2f9c3iySLCw54rJ/CZs+ZK6IQy7GXNY4nSOyu2QG4=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "3db36a8b464d0c4532ba1c7dda728f4576d6d073",
"type": "github"
"inputs": {
"systems": "systems"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_2": {
"locked": {
"lastModified": 1667395993,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
"lastModified": 1701680307,
"narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_3": {
"locked": {
"lastModified": 1653893745,
"narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_4": {
"locked": {
"lastModified": 1659877975,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
"rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
"type": "github"
},
"original": {
@@ -266,33 +153,51 @@
"type": "github"
}
},
"gomod2nix": {
"inputs": {
"nixpkgs": "nixpkgs_2",
"utils": "utils"
},
"ghc98X": {
"flake": false,
"locked": {
"lastModified": 1655245309,
"narHash": "sha256-d/YPoQ/vFn1+GTmSdvbSBSTOai61FONxB4+Lt6w/IVI=",
"owner": "tweag",
"repo": "gomod2nix",
"rev": "40d32f82fc60d66402eb0972e6e368aeab3faf58",
"type": "github"
"lastModified": 1715066704,
"narHash": "sha256-F0EVR8x/fcpj1st+hz96Wdsz5uwVIOziGKAwRxLOYJw=",
"ref": "ghc-9.8",
"rev": "78a253543d466ac511a1664a3e6aff032ca684d5",
"revCount": 61757,
"submodules": true,
"type": "git",
"url": "https://gitlab.haskell.org/ghc/ghc"
},
"original": {
"owner": "tweag",
"repo": "gomod2nix",
"type": "github"
"ref": "ghc-9.8",
"submodules": true,
"type": "git",
"url": "https://gitlab.haskell.org/ghc/ghc"
}
},
"ghc99": {
"flake": false,
"locked": {
"lastModified": 1726585445,
"narHash": "sha256-IdwQBex4boY6s0Plj5+ixf36rfYSUyMdTWrztKvZH30=",
"ref": "refs/heads/master",
"rev": "7fd9e5e29ab54eb406880077463e8552e2ddd39a",
"revCount": 67238,
"submodules": true,
"type": "git",
"url": "https://gitlab.haskell.org/ghc/ghc"
},
"original": {
"submodules": true,
"type": "git",
"url": "https://gitlab.haskell.org/ghc/ghc"
}
},
"hackage": {
"flake": false,
"locked": {
"lastModified": 1702340598,
"narHash": "sha256-CC0HI+6iKPtH+8r/ZfcpW5v/OYvL7zMwpr0xfkXV1zU=",
"lastModified": 1702513363,
"narHash": "sha256-kloro9uEe8aYhPMoMjVNq2rfrXNgMOZhOPwVH5DH2K0=",
"owner": "input-output-hk",
"repo": "hackage.nix",
"rev": "24617c569995e38bf3b83b48eec6628a50fdb4fb",
"rev": "a9d931d0398da67846fa257922a924829233cb91",
"type": "github"
},
"original": {
@@ -309,33 +214,43 @@
"cabal-36": "cabal-36",
"cardano-shell": "cardano-shell",
"flake-compat": "flake-compat",
"flake-utils": "flake-utils_2",
"ghc-8.6.5-iohk": "ghc-8.6.5-iohk",
"ghc98X": "ghc98X",
"ghc99": "ghc99",
"hackage": [
"hackage"
],
"hls-1.10": "hls-1.10",
"hls-2.0": "hls-2.0",
"hls-2.2": "hls-2.2",
"hls-2.3": "hls-2.3",
"hls-2.4": "hls-2.4",
"hls-2.5": "hls-2.5",
"hls-2.6": "hls-2.6",
"hpc-coveralls": "hpc-coveralls",
"hydra": "hydra",
"iserv-proxy": "iserv-proxy",
"nixpkgs": [
"nixpkgs"
"haskellNix",
"nixpkgs-unstable"
],
"nixpkgs-2003": "nixpkgs-2003",
"nixpkgs-2105": "nixpkgs-2105",
"nixpkgs-2111": "nixpkgs-2111",
"nixpkgs-2205": "nixpkgs-2205",
"nixpkgs-2211": "nixpkgs-2211",
"nixpkgs-2305": "nixpkgs-2305",
"nixpkgs-2311": "nixpkgs-2311",
"nixpkgs-unstable": "nixpkgs-unstable",
"old-ghc-nix": "old-ghc-nix",
"stackage": "stackage",
"tullia": "tullia"
"stackage": "stackage"
},
"locked": {
"lastModified": 1677975916,
"narHash": "sha256-dbe8lEEPyfzjdRwpePClv7J9p9lQg7BwbBqAMCw4RLw=",
"lastModified": 1705833500,
"narHash": "sha256-rUIr6JNbCedt1g4gVYVvE9t0oFU6FUspCA0DS5cA8Bg=",
"owner": "input-output-hk",
"repo": "haskell.nix",
"rev": "ab5efd87ce3fd8ade38a01d97693d29a4f1ae7e4",
"rev": "d0c35e75cbbc6858770af42ac32b0b85495fbd71",
"type": "github"
},
"original": {
@@ -345,6 +260,125 @@
"type": "github"
}
},
"hls-1.10": {
"flake": false,
"locked": {
"lastModified": 1680000865,
"narHash": "sha256-rc7iiUAcrHxwRM/s0ErEsSPxOR3u8t7DvFeWlMycWgo=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "b08691db779f7a35ff322b71e72a12f6e3376fd9",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "1.10.0.0",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-2.0": {
"flake": false,
"locked": {
"lastModified": 1687698105,
"narHash": "sha256-OHXlgRzs/kuJH8q7Sxh507H+0Rb8b7VOiPAjcY9sM1k=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "783905f211ac63edf982dd1889c671653327e441",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "2.0.0.1",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-2.2": {
"flake": false,
"locked": {
"lastModified": 1693064058,
"narHash": "sha256-8DGIyz5GjuCFmohY6Fa79hHA/p1iIqubfJUTGQElbNk=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "b30f4b6cf5822f3112c35d14a0cba51f3fe23b85",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "2.2.0.0",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-2.3": {
"flake": false,
"locked": {
"lastModified": 1695910642,
"narHash": "sha256-tR58doOs3DncFehHwCLczJgntyG/zlsSd7DgDgMPOkI=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "458ccdb55c9ea22cd5d13ec3051aaefb295321be",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "2.3.0.0",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-2.4": {
"flake": false,
"locked": {
"lastModified": 1699862708,
"narHash": "sha256-YHXSkdz53zd0fYGIYOgLt6HrA0eaRJi9mXVqDgmvrjk=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "54507ef7e85fa8e9d0eb9a669832a3287ffccd57",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "2.4.0.1",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-2.5": {
"flake": false,
"locked": {
"lastModified": 1701080174,
"narHash": "sha256-fyiR9TaHGJIIR0UmcCb73Xv9TJq3ht2ioxQ2mT7kVdc=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "27f8c3d3892e38edaef5bea3870161815c4d014c",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "2.5.0.0",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-2.6": {
"flake": false,
"locked": {
"lastModified": 1705325287,
"narHash": "sha256-+P87oLdlPyMw8Mgoul7HMWdEvWP/fNlo8jyNtwME8E8=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "6e0b342fa0327e628610f2711f8c3e4eaaa08b1e",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "2.6.0.0",
"repo": "haskell-language-server",
"type": "github"
}
},
"hpc-coveralls": {
"flake": false,
"locked": {
@@ -384,37 +418,14 @@
"type": "indirect"
}
},
"incl": {
"inputs": {
"nixlib": [
"haskellNix",
"tullia",
"std",
"nixpkgs"
]
},
"locked": {
"lastModified": 1669263024,
"narHash": "sha256-E/+23NKtxAqYG/0ydYgxlgarKnxmDbg6rCMWnOBqn9Q=",
"owner": "divnix",
"repo": "incl",
"rev": "ce7bebaee048e4cd7ebdb4cee7885e00c4e2abca",
"type": "github"
},
"original": {
"owner": "divnix",
"repo": "incl",
"type": "github"
}
},
"iserv-proxy": {
"flake": false,
"locked": {
"lastModified": 1670983692,
"narHash": "sha256-avLo34JnI9HNyOuauK5R69usJm+GfW3MlyGlYxZhTgY=",
"lastModified": 1707968597,
"narHash": "sha256-C53NqToxl+n9s1pQ0iLtiH6P5vX3rM+NW/mFt4Ykpsk=",
"ref": "hkm/remote-iserv",
"rev": "50d0abb3317ac439a4e7495b185a64af9b7b9300",
"revCount": 10,
"rev": "1b7f8aeb37bbc7c00f04e44d9379aa15a4409e8b",
"revCount": 18,
"type": "git",
"url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git"
},
@@ -440,32 +451,22 @@
"type": "github"
}
},
"n2c": {
"mac2ios": {
"inputs": {
"flake-utils": [
"haskellNix",
"tullia",
"std",
"flake-utils"
],
"nixpkgs": [
"haskellNix",
"tullia",
"std",
"nixpkgs"
]
"flake-parts": "flake-parts",
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1665039323,
"narHash": "sha256-SAh3ZjFGsaCI8FRzXQyp56qcGdAqgKEfJWPCQ0Sr7tQ=",
"owner": "nlewo",
"repo": "nix2container",
"rev": "b008fe329ffb59b67bf9e7b08ede6ee792f2741a",
"lastModified": 1699767871,
"narHash": "sha256-kxeCUfwC/Vgh2FvVMlBUq0eVx1JvfHyN+5MPKUik9mE=",
"owner": "zw3rk",
"repo": "mobile-core-tools",
"rev": "4dcb77d5ea896d749381806dfab5358851b08951",
"type": "github"
},
"original": {
"owner": "nlewo",
"repo": "nix2container",
"owner": "zw3rk",
"repo": "mobile-core-tools",
"type": "github"
}
},
@@ -490,95 +491,6 @@
"type": "github"
}
},
"nix-nomad": {
"inputs": {
"flake-compat": "flake-compat_2",
"flake-utils": [
"haskellNix",
"tullia",
"nix2container",
"flake-utils"
],
"gomod2nix": "gomod2nix",
"nixpkgs": [
"haskellNix",
"tullia",
"nixpkgs"
],
"nixpkgs-lib": [
"haskellNix",
"tullia",
"nixpkgs"
]
},
"locked": {
"lastModified": 1658277770,
"narHash": "sha256-T/PgG3wUn8Z2rnzfxf2VqlR1CBjInPE0l1yVzXxPnt0=",
"owner": "tristanpemble",
"repo": "nix-nomad",
"rev": "054adcbdd0a836ae1c20951b67ed549131fd2d70",
"type": "github"
},
"original": {
"owner": "tristanpemble",
"repo": "nix-nomad",
"type": "github"
}
},
"nix2container": {
"inputs": {
"flake-utils": "flake-utils_3",
"nixpkgs": "nixpkgs_3"
},
"locked": {
"lastModified": 1658567952,
"narHash": "sha256-XZ4ETYAMU7XcpEeAFP3NOl9yDXNuZAen/aIJ84G+VgA=",
"owner": "nlewo",
"repo": "nix2container",
"rev": "60bb43d405991c1378baf15a40b5811a53e32ffa",
"type": "github"
},
"original": {
"owner": "nlewo",
"repo": "nix2container",
"type": "github"
}
},
"nixago": {
"inputs": {
"flake-utils": [
"haskellNix",
"tullia",
"std",
"flake-utils"
],
"nixago-exts": [
"haskellNix",
"tullia",
"std",
"blank"
],
"nixpkgs": [
"haskellNix",
"tullia",
"std",
"nixpkgs"
]
},
"locked": {
"lastModified": 1661824785,
"narHash": "sha256-/PnwdWoO/JugJZHtDUioQp3uRiWeXHUdgvoyNbXesz8=",
"owner": "nix-community",
"repo": "nixago",
"rev": "8c1f9e5f1578d4b2ea989f618588d62a335083c3",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nixago",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1657693803,
@@ -645,11 +557,11 @@
},
"nixpkgs-2205": {
"locked": {
"lastModified": 1672580127,
"narHash": "sha256-3lW3xZslREhJogoOkjeZtlBtvFMyxHku7I/9IVehhT8=",
"lastModified": 1685573264,
"narHash": "sha256-Zffu01pONhs/pqH07cjlF10NnMDLok8ix5Uk4rhOnZQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "0874168639713f547c05947c76124f78441ea46c",
"rev": "380be19fbd2d9079f677978361792cb25e8a3635",
"type": "github"
},
"original": {
@@ -661,11 +573,11 @@
},
"nixpkgs-2211": {
"locked": {
"lastModified": 1675730325,
"narHash": "sha256-uNvD7fzO5hNlltNQUAFBPlcEjNG5Gkbhl/ROiX+GZU4=",
"lastModified": 1688392541,
"narHash": "sha256-lHrKvEkCPTUO+7tPfjIcb7Trk6k31rz18vkyqmkeJfY=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b7ce17b1ebf600a72178f6302c77b6382d09323f",
"rev": "ea4c80b39be4c09702b0cb3b42eab59e2ba4f24b",
"type": "github"
},
"original": {
@@ -675,6 +587,56 @@
"type": "github"
}
},
"nixpkgs-2305": {
"locked": {
"lastModified": 1705033721,
"narHash": "sha256-K5eJHmL1/kev6WuqyqqbS1cdNnSidIZ3jeqJ7GbrYnQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a1982c92d8980a0114372973cbdfe0a307f1bdea",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-23.05-darwin",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-2311": {
"locked": {
"lastModified": 1719957072,
"narHash": "sha256-gvFhEf5nszouwLAkT9nWsDzocUTqLWHuL++dvNjMp9I=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "7144d6241f02d171d25fba3edeaf15e0f2592105",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-23.11-darwin",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-lib": {
"locked": {
"dir": "lib",
"lastModified": 1696019113,
"narHash": "sha256-X3+DKYWJm93DRSdC5M6K5hLqzSya9BjibtBsuARoPco=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "f5892ddac112a1e9b3612c39af1b72987ee5783a",
"type": "github"
},
"original": {
"dir": "lib",
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-regression": {
"locked": {
"lastModified": 1643052045,
@@ -693,98 +655,36 @@
},
"nixpkgs-unstable": {
"locked": {
"lastModified": 1675758091,
"narHash": "sha256-7gFSQbSVAFUHtGCNHPF7mPc5CcqDk9M2+inlVPZSneg=",
"lastModified": 1694822471,
"narHash": "sha256-6fSDCj++lZVMZlyqOe9SIOL8tYSBz1bI8acwovRwoX8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "747927516efcb5e31ba03b7ff32f61f6d47e7d87",
"rev": "47585496bcb13fb72e4a90daeea2f434e2501998",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"rev": "47585496bcb13fb72e4a90daeea2f434e2501998",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1653581809,
"narHash": "sha256-Uvka0V5MTGbeOfWte25+tfRL3moECDh1VwokWSZUdoY=",
"lastModified": 1698434055,
"narHash": "sha256-Phxi5mUKSoL7A0IYUiYtkI9e8NcGaaV5PJEaJApU1Ko=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "83658b28fe638a170a19b8933aa008b30640fbd1",
"rev": "1a3c95e3b23b3cdb26750621c08cc2f1560cb883",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"ref": "nixos-23.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_3": {
"locked": {
"lastModified": 1654807842,
"narHash": "sha256-ADymZpr6LuTEBXcy6RtFHcUZdjKTBRTMYwu19WOx17E=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "fc909087cc3386955f21b4665731dbdaceefb1d8",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_4": {
"locked": {
"lastModified": 1665087388,
"narHash": "sha256-FZFPuW9NWHJteATOf79rZfwfRn5fE0wi9kRzvGfDHPA=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "95fda953f6db2e9496d2682c4fc7b82f959878f7",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_5": {
"locked": {
"lastModified": 1676726892,
"narHash": "sha256-M7OYVR6dKmzmlebIjybFf3l18S2uur8lMyWWnHQooLY=",
"owner": "angerman",
"repo": "nixpkgs",
"rev": "729469087592bdea58b360de59dadf6d58714c42",
"type": "github"
},
"original": {
"owner": "angerman",
"ref": "release-22.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nosys": {
"locked": {
"lastModified": 1667881534,
"narHash": "sha256-FhwJ15uPLRsvaxtt/bNuqE/ykMpNAPF0upozFKhTtXM=",
"owner": "divnix",
"repo": "nosys",
"rev": "2d0d5207f6a230e9d0f660903f8db9807b54814f",
"type": "github"
},
"original": {
"owner": "divnix",
"repo": "nosys",
"type": "github"
}
},
"old-ghc-nix": {
"flake": false,
"locked": {
@@ -807,17 +707,21 @@
"flake-utils": "flake-utils",
"hackage": "hackage",
"haskellNix": "haskellNix",
"nixpkgs": "nixpkgs_5"
"mac2ios": "mac2ios",
"nixpkgs": [
"haskellNix",
"nixpkgs-2305"
]
}
},
"stackage": {
"flake": false,
"locked": {
"lastModified": 1677888571,
"narHash": "sha256-YkhRNOaN6QVagZo1cfykYV8KqkI8/q6r2F5+jypOma4=",
"lastModified": 1726532152,
"narHash": "sha256-LRXbVY3M2S8uQWdwd2zZrsnVPEvt2GxaHGoy8EFFdJA=",
"owner": "input-output-hk",
"repo": "stackage.nix",
"rev": "cb50e6fabdfb2d7e655059039012ad0623f06a27",
"rev": "c77b3530cebad603812cb111c6f64968c2d2337d",
"type": "github"
},
"original": {
@@ -826,110 +730,18 @@
"type": "github"
}
},
"std": {
"inputs": {
"arion": [
"haskellNix",
"tullia",
"std",
"blank"
],
"blank": "blank",
"devshell": "devshell",
"dmerge": "dmerge",
"flake-utils": "flake-utils_4",
"incl": "incl",
"makes": [
"haskellNix",
"tullia",
"std",
"blank"
],
"microvm": [
"haskellNix",
"tullia",
"std",
"blank"
],
"n2c": "n2c",
"nixago": "nixago",
"nixpkgs": "nixpkgs_4",
"nosys": "nosys",
"yants": "yants"
},
"systems": {
"locked": {
"lastModified": 1674526466,
"narHash": "sha256-tMTaS0bqLx6VJ+K+ZT6xqsXNpzvSXJTmogkraBGzymg=",
"owner": "divnix",
"repo": "std",
"rev": "516387e3d8d059b50e742a2ff1909ed3c8f82826",
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "divnix",
"repo": "std",
"type": "github"
}
},
"tullia": {
"inputs": {
"nix-nomad": "nix-nomad",
"nix2container": "nix2container",
"nixpkgs": [
"haskellNix",
"nixpkgs"
],
"std": "std"
},
"locked": {
"lastModified": 1675695930,
"narHash": "sha256-B7rEZ/DBUMlK1AcJ9ajnAPPxqXY6zW2SBX+51bZV0Ac=",
"owner": "input-output-hk",
"repo": "tullia",
"rev": "621365f2c725608f381b3ad5b57afef389fd4c31",
"type": "github"
},
"original": {
"owner": "input-output-hk",
"repo": "tullia",
"type": "github"
}
},
"utils": {
"locked": {
"lastModified": 1653893745,
"narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"yants": {
"inputs": {
"nixpkgs": [
"haskellNix",
"tullia",
"std",
"nixpkgs"
]
},
"locked": {
"lastModified": 1667096281,
"narHash": "sha256-wRRec6ze0gJHmGn6m57/zhz/Kdvp9HS4Nl5fkQ+uIuA=",
"owner": "divnix",
"repo": "yants",
"rev": "d18f356ec25cb94dc9c275870c3a7927a10f8c3c",
"type": "github"
},
"original": {
"owner": "divnix",
"repo": "yants",
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
+278 -24
View File
@@ -1,15 +1,15 @@
{
description = "nix flake for simplex-chat";
inputs.nixpkgs.url = "github:angerman/nixpkgs/release-22.11";
inputs.haskellNix.url = "github:input-output-hk/haskell.nix/armv7a";
inputs.haskellNix.inputs.nixpkgs.follows = "nixpkgs";
inputs.nixpkgs.follows = "haskellNix/nixpkgs-2305";
inputs.mac2ios.url = "github:zw3rk/mobile-core-tools";
inputs.hackage = {
url = "github:input-output-hk/hackage.nix";
flake = false;
};
inputs.haskellNix.inputs.hackage.follows = "hackage";
inputs.flake-utils.url = "github:numtide/flake-utils";
outputs = { self, haskellNix, nixpkgs, flake-utils, ... }:
outputs = { self, haskellNix, nixpkgs, flake-utils, mac2ios, ... }:
let systems = [ "x86_64-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin" ]; in
flake-utils.lib.eachSystem systems (system:
# this android26 overlay makes the pkgsCross.{aarch64-android,armv7a-android-prebuilt} to set stdVer to 26 (Android 8).
@@ -30,7 +30,7 @@
# `appendOverlays` with a singleton is identical to `extend`.
let pkgs = haskellNix.legacyPackages.${system}.appendOverlays [android26]; in
let drv' = { extra-modules, pkgs', ... }: pkgs'.haskell-nix.project {
compiler-nix-name = "ghc8107";
compiler-nix-name = "ghc963";
index-state = "2023-12-12T00:00:00Z";
# We need this, to specify we want the cabal project.
# If the stack.yaml was dropped, this would not be necessary.
@@ -40,9 +40,12 @@
src = ./.;
};
sha256map = import ./scripts/nix/sha256map.nix;
modules = [{
modules = [
({ pkgs, lib, ...}: lib.mkIf (!pkgs.stdenv.hostPlatform.isWindows) {
# This patch adds `dl` as an extra-library to direct-sqlciper, which is needed
# on pretty much all unix platforms, but then blows up on windows m(
packages.direct-sqlcipher.patches = [ ./scripts/nix/direct-sqlcipher-2.3.27.patch ];
}
})
({ pkgs,lib, ... }: lib.mkIf (pkgs.stdenv.hostPlatform.isAndroid) {
packages.simplex-chat.components.library.ghcOptions = [ "-pie" ];
})] ++ extra-modules;
@@ -64,6 +67,9 @@
}); in
let iosPostInstall = bundleName: ''
${pkgs.tree}/bin/tree $out
mkdir tmp
find ./dist -name "libHS*-ghc*.a" -exec cp {} tmp \;
(cd tmp; ${pkgs.tree}/bin/tree .; ar x libHS*.a; for o in *.o; do if /usr/bin/otool -xv $o|grep ldadd ; then echo $o; fi; done; cd ..; rm -fR tmp)
mkdir -p $out/_pkg
# copy over includes, we might want those, but maybe not.
# cp -r $out/lib/*/*/include $out/_pkg/
@@ -74,6 +80,18 @@
find ${pkgs.gmp6.override { withStatic = true; }}/lib -name "*.a" -exec cp {} $out/_pkg \;
# There is no static libc
${pkgs.tree}/bin/tree $out/_pkg
for pkg in $out/_pkg/*.a; do
chmod +w $pkg
${mac2ios.packages.${system}.mac2ios}/bin/mac2ios $pkg
chmod -w $pkg
done
mkdir tmp
find $out/_pkg -name "libHS*-ghc*.a" -exec cp {} tmp \;
(cd tmp; ${pkgs.tree}/bin/tree .; ar x libHS*.a; for o in *.o; do if /usr/bin/otool -xv $o|grep ldadd ; then echo $o; fi; done; cd ..; rm -fR tmp)
sha256sum $out/_pkg/*.a
(cd $out/_pkg; ${pkgs.zip}/bin/zip -r -9 $out/${bundleName}.zip *)
rm -fR $out/_pkg
mkdir -p $out/nix-support
@@ -119,13 +137,150 @@
hardeningDisable = [ "fortify" ];
}
);in {
# STATIC x86_64-linux
"${pkgs.pkgsCross.musl64.hostPlatform.system}-static:exe:simplex-chat" = (drv pkgs.pkgsCross.musl64).simplex-chat.components.exes.simplex-chat;
"${pkgs.pkgsCross.musl32.hostPlatform.system}-static:exe:simplex-chat" = (drv pkgs.pkgsCross.musl32).simplex-chat.components.exes.simplex-chat;
# STATIC i686-linux
"${pkgs.pkgsCross.musl32.hostPlatform.system}-static:exe:simplex-chat" = (drv' {
pkgs' = pkgs.pkgsCross.musl32;
extra-modules = [{
# 32 bit patches
packages.basement.patches = [
./scripts/nix/basement-pr-573.patch
];
packages.memory.patches = [
./scripts/nix/memory-pr-99.patch
];
}];
}).simplex-chat.components.exes.simplex-chat;
# WINDOWS x86_64-mingwW64
"${pkgs.pkgsCross.mingwW64.hostPlatform.system}:exe:simplex-chat" = (drv' {
pkgs' = pkgs.pkgsCross.mingwW64;
extra-modules = [{
packages.direct-sqlcipher.flags.openssl = true;
packages.bitvec.flags.simd = false;
packages.direct-sqlcipher.patches = [
./scripts/nix/direct-sqlcipher-2.3.27-win.patch
];
packages.direct-sqlcipher.components.library.libs = pkgs.lib.mkForce [
(pkgs.pkgsCross.mingwW64.openssl) #.override) # { static = true; enableKTLS = false; })
];
packages.simplexmq.components.library.libs = pkgs.lib.mkForce [
(pkgs.pkgsCross.mingwW64.openssl) #.override) # { static = true; enableKTLS = false; })
];
packages.unix-time.postPatch = ''
sed -i 's/mingwex//g' unix-time.cabal
'';
}];
}).simplex-chat.components.exes.simplex-chat.override {
postInstall = ''
set -x
${pkgs.tree}/bin/tree $out
mkdir -p $out/_pkg
cp $out/bin/* $out/_pkg
${pkgs.tree}/bin/tree $out/_pkg
(cd $out/_pkg; ${pkgs.zip}/bin/zip -r -9 $out/${pkgs.pkgsCross.mingwW64.hostPlatform.system}-simplex-chat.zip *)
rm -fR $out/_pkg
mkdir -p $out/nix-support
echo "file binary-dist \"$(echo $out/*.zip)\"" \
> $out/nix-support/hydra-build-products
'';
};
"${pkgs.pkgsCross.mingwW64.hostPlatform.system}:lib:simplex-chat" = (drv' rec {
pkgs' = pkgs.pkgsCross.mingwW64;
extra-modules = [{
packages.direct-sqlcipher.flags.openssl = true;
# simd will try to read __cpu_model, which we don't expose
# from the rts (yet!).
packages.bitvec.flags.simd = false;
packages.direct-sqlcipher.patches = [
./scripts/nix/direct-sqlcipher-2.3.27-win.patch
];
packages.direct-sqlcipher.components.library.libs = pkgs.lib.mkForce [
pkgs.pkgsCross.mingwW64.openssl
];
packages.simplexmq.flags.client_library = true;
packages.simplexmq.components.library.libs = pkgs.lib.mkForce [
pkgs.pkgsCross.mingwW64.openssl
];
packages.unix-time.postPatch = ''
sed -i 's/mingwex//g' unix-time.cabal
'';
}];
}).simplex-chat.components.library
.override (p: {
# enableShared = false;
setupBuildFlags = p.component.setupBuildFlags ++ map (x: "--ghc-option=${x}") [
"-shared"
"-threaded"
"-o" "libsimplex.dll"
# "-optl-lHSrts_thr"
"-optl-lffi"
# "-optl-static-libgcc"
# We can't do -optl-static-libstdc++ with gcc. g++ might
# but then we are chaning the compiler altogether.
"${./libsimplex.dll.def}"
];
postInstall = ''
set -x
function deps() {
${pkgs.binutils}/bin/strings "$1" | grep '.\.dll'|grep -v -E 'Winsock|ADVAPI32|dbghelp|KERNEL32|msvcrt|ntdll|ole32|RPCRT4|SHELL32|USER32|WINMM|WS2_32|kernel32|GDI32'|grep -v "$1"
}
${pkgs.tree}/bin/tree $out
mkdir -p $out/_pkg
cp libsimplex.dll $out/_pkg
cp libsimplex.dll.a $out/_pkg
mkdir $out/libs
find ${pkgs.lib.getBin pkgs.pkgsCross.mingwW64.openssl} -name "*.dll" -exec cp {} $out/libs \;
find ${pkgs.lib.getBin pkgs.pkgsCross.mingwW64.libffi} -name "*.dll" -exec cp {} $out/libs \;
find ${pkgs.lib.getBin pkgs.pkgsCross.mingwW64.gmp} -name "*.dll" -exec cp {} $out/libs \;
find ${pkgs.lib.getBin pkgs.pkgsCross.mingwW64.stdenv.cc.cc} -name "*.dll" -exec cp {} $out/libs \;
find ${pkgs.lib.getBin pkgs.pkgsCross.mingwW64.windows.mcfgthreads} -name "*.dll" -exec cp {} $out/libs \;
pushd $out/_pkg
function copyDeps() {
for dep in $(deps "$1"); do
if [ ! -f "$dep" ]; then
if [ ! -f ../libs/"$dep" ]; then
echo "WARN: $1 -> $dep not found!"
else
cp ../libs/"$dep" .
copyDeps "$dep"
fi
fi
done
}
copyDeps libsimplex.dll
popd
${pkgs.tree}/bin/tree $out/_pkg
(cd $out/_pkg; ${pkgs.zip}/bin/zip -r -9 $out/pkg-${pkgs.pkgsCross.mingwW64.hostPlatform.system}-libsimplex.zip *)
rm -fR $out/_pkg
mkdir -p $out/nix-support
echo "file binary-dist \"$(echo $out/*.zip)\"" \
> $out/nix-support/hydra-build-products
'';
});
# "${pkgs.pkgsCross.muslpi.hostPlatform.system}-static:exe:simplex-chat" = (drv pkgs.pkgsCross.muslpi).simplex-chat.components.exes.simplex-chat;
# STATIC aarch64-linux
"${pkgs.pkgsCross.aarch64-multiplatform-musl.hostPlatform.system}-static:exe:simplex-chat" = (drv pkgs.pkgsCross.aarch64-multiplatform-musl).simplex-chat.components.exes.simplex-chat;
"armv7a-android:lib:support" = (drv android32Pkgs).android-support.components.library.override {
smallAddressSpace = true; enableShared = false;
setupBuildFlags = map (x: "--ghc-option=${x}") [ "-shared" "-o" "libsupport.so" ];
"armv7a-android:lib:support" = (drv android32Pkgs).android-support.components.library.override (p: {
smallAddressSpace = true;
# we won't want -dyamic (see aarch64-android:lib:simplex-chat)
enableShared = false;
# we also do not want to have any dependencies listed (especially no rts!)
enableStatic = false;
# This used to work with 8.10.7...
# setupBuildFlags = p.component.setupBuildFlags ++ map (x: "--ghc-option=${x}") [ "-shared" "-o" "libsupport.so" ];
# ... but now with 9.6+
# we have to do the -shared thing by hand.
postBuild = ''
armv7a-unknown-linux-androideabi-ghc -shared -o libsupport.so \
-optl-Wl,-u,setLineBuffering \
-optl-Wl,-u,pipe_std_to_socket \
dist/build/*.a
'';
postInstall = ''
mkdir -p $out/_pkg
@@ -138,14 +293,29 @@
echo "file binary-dist \"$(echo $out/*.zip)\"" \
> $out/nix-support/hydra-build-products
'';
};
"aarch64-android:lib:support" = (drv androidPkgs).android-support.components.library.override {
smallAddressSpace = true; enableShared = false;
setupBuildFlags = map (x: "--ghc-option=${x}") [ "-shared" "-o" "libsupport.so" ];
});
# The android-support package is at
# https://github.com/simplex-chat/android-support
"aarch64-android:lib:support" = (drv androidPkgs).android-support.components.library.override (p: {
smallAddressSpace = true;
# no -dynamic
enableShared = false;
# but also no -staticlib
enableStatic = false;
# we have to do the -shared thing by hand.
postBuild = ''
aarch64-unknown-linux-android-ghc -shared -o libsupport.so \
-optl-Wl,-u,setLineBuffering \
-optl-Wl,-u,pipe_std_to_socket \
dist/build/*.a
'';
postInstall = ''
mkdir -p $out/_pkg
cp libsupport.so $out/_pkg
ls -lah $out/_pkg/*
${pkgs.patchelf}/bin/patchelf --remove-needed libunwind.so.1 $out/_pkg/libsupport.so
(cd $out/_pkg; ${pkgs.zip}/bin/zip -r -9 $out/pkg-aarch64-android-libsupport.zip *)
rm -fR $out/_pkg
@@ -154,10 +324,11 @@
echo "file binary-dist \"$(echo $out/*.zip)\"" \
> $out/nix-support/hydra-build-products
'';
};
});
"armv7a-android:lib:simplex-chat" = (drv' {
pkgs' = android32Pkgs;
extra-modules = [{
packages.text.flags.simdutf = false;
packages.direct-sqlcipher.flags.openssl = true;
packages.direct-sqlcipher.components.library.libs = pkgs.lib.mkForce [
(android32Pkgs.openssl.override { static = true; enableKTLS = false; })
@@ -169,13 +340,56 @@
packages.simplexmq.components.library.libs = pkgs.lib.mkForce [
(android32Pkgs.openssl.override { static = true; enableKTLS = false; })
];
# 32 bit patches
packages.basement.patches = [
./scripts/nix/basement-pr-573.patch
];
packages.memory.patches = [
./scripts/nix/memory-pr-99.patch
];
}];
}).simplex-chat.components.library.override {
smallAddressSpace = true; enableShared = false;
}).simplex-chat.components.library.override (p: {
smallAddressSpace = true;
# we want -shared, but not -dyanmic, hence `enableShared = false`.
enableShared = false;
# we _do_ want rts, and other libs. Hence `enableStatic = true`.
enableStatic = true;
# for android we build a shared library, passing these arguments is a bit tricky, as
# we want only the threaded rts (HSrts_thr) and ffi to be linked, but not fed into iserv for
# template haskell cross compilation. Thus we just pass them as linker options (-optl).
setupBuildFlags = map (x: "--ghc-option=${x}") [ "-shared" "-o" "libsimplex.so" "-optl-lHSrts_thr" "-optl-lffi"];
setupBuildFlags = p.component.setupBuildFlags
# flags to tell GHC we want to produce a -shared object, and we want to also link
# - the ffi library (ffi)
++ map (x: "--ghc-option=${x}") [
"-shared" "-o" "libsimplex.so"
"-threaded"
# "-debug"
"-optl-lffi"
]
# This is fairly idiotic. LLD will strip out foreign exported
# symbols (a GHC bug? Codegen bug?). So we need to pass `-u <sym>`
# to ensure they stay in the produced library. Having them
# _undefined_ and _lazy_ (lld will tell with -y <sym> that the
# symbol is lazy), makes them _defined_. m(
++ map (sym: "--ghc-option=-optl-Wl,-u,${sym}") [
"chat_close_store"
"chat_decrypt_file"
"chat_decrypt_media"
"chat_encrypt_file"
"chat_encrypt_media"
"chat_migrate_init"
"chat_parse_markdown"
"chat_parse_server"
"chat_password_hash"
"chat_read_file"
"chat_recv_msg"
"chat_recv_msg_wait"
"chat_send_cmd"
"chat_send_remote_cmd"
"chat_valid_name"
"chat_json_length"
"chat_write_file"
];
postInstall = ''
set -x
${pkgs.tree}/bin/tree $out
@@ -219,10 +433,11 @@
echo "file binary-dist \"$(echo $out/*.zip)\"" \
> $out/nix-support/hydra-build-products
'';
};
});
"aarch64-android:lib:simplex-chat" = (drv' {
pkgs' = androidPkgs;
extra-modules = [{
packages.text.flags.simdutf = false;
packages.direct-sqlcipher.flags.openssl = true;
packages.direct-sqlcipher.components.library.libs = pkgs.lib.mkForce [
(androidPkgs.openssl.override { static = true; })
@@ -235,12 +450,50 @@
(androidPkgs.openssl.override { static = true; })
];
}];
}).simplex-chat.components.library.override {
smallAddressSpace = true; enableShared = false;
}).simplex-chat.components.library.override (p: {
smallAddressSpace = true;
# we do not want a dynamically linked object, even though we _do_
# want to produce a _shared_ object. But `shared` implied -dyanmic
# with cabal, so we disable and pass `-shared` explicitly.
enableShared = false;
# we do want static (e.g. pass all dependencies in, so we get -staticlib)
enableStatic = true;
# for android we build a shared library, passing these arguments is a bit tricky, as
# we want only the threaded rts (HSrts_thr) and ffi to be linked, but not fed into iserv for
# template haskell cross compilation. Thus we just pass them as linker options (-optl).
setupBuildFlags = map (x: "--ghc-option=${x}") [ "-shared" "-o" "libsimplex.so" "-optl-lHSrts_thr" "-optl-lffi"];
setupBuildFlags = p.component.setupBuildFlags
# flags to tell GHC we want to produce a -shared object, and we want to also link
# - the ffi library (ffi)
++ map (x: "--ghc-option=${x}") [
"-shared" "-o" "libsimplex.so"
"-threaded"
# "-debug"
"-optl-lffi"
]
# This is fairly idiotic. LLD will strip out foreign exported
# symbols (a GHC bug? Codegen bug?). So we need to pass `-u <sym>`
# to ensure they stay in the produced library. Having them
# _undefined_ and _lazy_ (lld will tell with -y <sym> that the
# symbol is lazy), makes them _defined_. m(
++ map (sym: "--ghc-option=-optl-Wl,-u,${sym}") [
"chat_close_store"
"chat_decrypt_file"
"chat_decrypt_media"
"chat_encrypt_file"
"chat_encrypt_media"
"chat_migrate_init"
"chat_parse_markdown"
"chat_parse_server"
"chat_password_hash"
"chat_read_file"
"chat_recv_msg"
"chat_recv_msg_wait"
"chat_send_cmd"
"chat_send_remote_cmd"
"chat_valid_name"
"chat_json_length"
"chat_write_file"
];
postInstall = ''
set -x
${pkgs.tree}/bin/tree $out
@@ -284,7 +537,7 @@
echo "file binary-dist \"$(echo $out/*.zip)\"" \
> $out/nix-support/hydra-build-products
'';
};
});
};
# builds for iOS and iOS simulator
@@ -299,7 +552,8 @@
packages.entropy.flags.DoNotGetEntropy = true;
packages.simplexmq.flags.client_library = true;
packages.simplexmq.components.library.libs = pkgs.lib.mkForce [
(pkgs.openssl.override { static = true; })
# TODO: have a cross override for iOS, that sets this.
((pkgs.openssl.override { static = true; }).overrideDerivation (old: { CFLAGS = "-mcpu=apple-a7 -march=armv8-a+norcpc" ;}))
];
}];
}).simplex-chat.components.library.override (
+14
View File
@@ -0,0 +1,14 @@
{
"targets": [
{
"target_name": "addon",
"sources": [ "cpp/simplex.cc" ],
"libraries": [
"-Wl,-rpath,libs",
"-L<(module_root_dir)/build/Release/",
"-L<(module_root_dir)/libs",
"-lsimplex"
]
}
]
}
+188
View File
@@ -0,0 +1,188 @@
#include <sstream>
#include <string>
#include <node.h>
#include "simplex.h"
namespace simplex
{
using v8::Array;
using v8::ArrayBuffer;
using v8::Context;
using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Maybe;
using v8::Number;
using v8::Object;
using v8::String;
using v8::Value;
void haskell_init()
{
int argc = 5;
char *argv[] = {
"simplex",
"+RTS", // requires `hs_init_with_rtsopts`
"-A64m", // chunk size for new allocations
"-H64m", // initial heap size
"-xn", // non-moving GC
0};
char **pargv = argv;
hs_init_with_rtsopts(&argc, &pargv);
}
void ChatMigrateInit(const FunctionCallbackInfo<Value> &args)
{
Isolate *isolate = args.GetIsolate();
Local<Context> context = isolate->GetCurrentContext();
std::string path(*(v8::String::Utf8Value(isolate, args[0])));
std::string key(*(v8::String::Utf8Value(isolate, args[1])));
std::string confirm(*(v8::String::Utf8Value(isolate, args[2])));
long *ctrl(0);
std::string res = chat_migrate_init(path.c_str(), key.c_str(), confirm.c_str(), &ctrl);
std::stringstream ss;
ss << ctrl
<< "\n"
<< res;
// printf("ChatCtrl after init %d", cChatCtrl);
// v8::Local<v8::String> ctrl = v8::String::NewFromUtf8(isolate, cppChatCtrl.c_str(), v8::String::kNormalString);
args.GetReturnValue().Set(
String::NewFromUtf8(
isolate, ss.str().c_str())
.ToLocalChecked());
}
void ChatCloseStore(const FunctionCallbackInfo<Value> &args)
{
Isolate *isolate = args.GetIsolate();
Local<Context> context = isolate->GetCurrentContext();
long *ctrl = (long *)((long)args[0].As<Number>()->Value());
args.GetReturnValue().Set(
String::NewFromUtf8(
isolate, chat_close_store(ctrl))
.ToLocalChecked());
}
void ChatSendCmd(const FunctionCallbackInfo<Value> &args)
{
Isolate *isolate = args.GetIsolate();
Local<Context> context = isolate->GetCurrentContext();
long *ctrl = (long *)((long)args[0].As<Number>()->Value());
std::string cmd(*(v8::String::Utf8Value(isolate, args[1])));
args.GetReturnValue().Set(
String::NewFromUtf8(
isolate, chat_send_cmd(ctrl, cmd.c_str()))
.ToLocalChecked());
}
void ChatRecvMsgWait(const FunctionCallbackInfo<Value> &args)
{
Isolate *isolate = args.GetIsolate();
Local<Context> context = isolate->GetCurrentContext();
long *ctrl = (long *)((long)args[0].As<Number>()->Value());
long wait = ((long)args[1].As<Number>()->Value());
args.GetReturnValue().Set(
String::NewFromUtf8(
isolate, chat_recv_msg_wait(ctrl, wait))
.ToLocalChecked());
}
void ChatWriteFile(const FunctionCallbackInfo<Value> &args)
{
Isolate *isolate = args.GetIsolate();
Local<Context> context = isolate->GetCurrentContext();
long *ctrl = (long *)((long)args[0].As<Number>()->Value());
std::string path(*(v8::String::Utf8Value(isolate, args[1])));
Local<v8::ArrayBuffer> arr = args[2].As<ArrayBuffer>();
char *buffer = (char *)arr->Data();
int len(arr->ByteLength());
// std::array address(*arr);
// v8::Array a = *buffer;
// std::string data(*((isolate, args[1])));
args.GetReturnValue().Set(
String::NewFromUtf8(
isolate, chat_write_file(ctrl, path.c_str(), buffer, len))
.ToLocalChecked());
}
void ChatReadFile(const FunctionCallbackInfo<Value> &args)
{
Isolate *isolate = args.GetIsolate();
Local<Context> context = isolate->GetCurrentContext();
long *ctrl = (long *)((long)args[0].As<Number>()->Value());
std::string path(*(v8::String::Utf8Value(isolate, args[1])));
Local<v8::ArrayBuffer> arr = args[2].As<ArrayBuffer>();
char *buffer = (char *)arr->Data();
int len(arr->ByteLength());
args.GetReturnValue().Set(
String::NewFromUtf8(
isolate, chat_write_file(ctrl, path.c_str(), buffer, len))
.ToLocalChecked());
}
void ChatEncryptFile(const FunctionCallbackInfo<Value> &args)
{
Isolate *isolate = args.GetIsolate();
Local<Context> context = isolate->GetCurrentContext();
long *ctrl = (long *)((long)args[0].As<Number>()->Value());
std::string fromPath(*(v8::String::Utf8Value(isolate, args[1])));
std::string toPath(*(v8::String::Utf8Value(isolate, args[2])));
args.GetReturnValue().Set(
String::NewFromUtf8(
isolate, chat_encrypt_file(ctrl, fromPath.c_str(), toPath.c_str()))
.ToLocalChecked());
}
void ChatDecryptFile(const FunctionCallbackInfo<Value> &args)
{
Isolate *isolate = args.GetIsolate();
Local<Context> context = isolate->GetCurrentContext();
std::string fromPath(*(v8::String::Utf8Value(isolate, args[0])));
std::string key(*(v8::String::Utf8Value(isolate, args[1])));
std::string nonce(*(v8::String::Utf8Value(isolate, args[2])));
std::string toPath(*(v8::String::Utf8Value(isolate, args[3])));
args.GetReturnValue().Set(
String::NewFromUtf8(
isolate, chat_decrypt_file(fromPath.c_str(), key.c_str(), nonce.c_str(), toPath.c_str()))
.ToLocalChecked());
}
void Initialize(Local<Object> exports)
{
haskell_init();
NODE_SET_METHOD(exports, "chat_migrate_init", ChatMigrateInit);
NODE_SET_METHOD(exports, "chat_close_store", ChatCloseStore);
NODE_SET_METHOD(exports, "chat_send_cmd", ChatSendCmd);
NODE_SET_METHOD(exports, "chat_recv_msg_wait", ChatRecvMsgWait);
NODE_SET_METHOD(exports, "chat_write_file", ChatWriteFile);
NODE_SET_METHOD(exports, "chat_read_file", ChatReadFile);
NODE_SET_METHOD(exports, "chat_encrypt_file", ChatEncryptFile);
NODE_SET_METHOD(exports, "chat_decrypt_file", ChatDecryptFile);
}
NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize)
} // namespace simplex
@@ -0,0 +1,46 @@
//
// simplex.h
// SimpleX
//
// Created by Evgeny on 30/05/2022.
// Copyright © 2022 SimpleX Chat. All rights reserved.
//
#ifndef SimpleX_h
#define SimpleX_h
extern "C" void hs_init(int argc, char **argv[]);
extern "C" void hs_init_with_rtsopts(int * argc, char **argv[]);
typedef long* chat_ctrl;
// the last parameter is used to return the pointer to chat controller
extern "C" char *chat_migrate_init(const char *path, const char *key, const char *confirm, chat_ctrl *ctrl);
extern "C" char *chat_close_store(chat_ctrl ctrl);
extern "C" char *chat_reopen_store(chat_ctrl ctrl);
extern "C" char *chat_send_cmd(chat_ctrl ctrl, const char *cmd);
extern "C" char *chat_recv_msg_wait(chat_ctrl ctrl, const int wait);
extern "C" char *chat_parse_markdown(const char *str);
extern "C" char *chat_parse_server(const char *str);
extern "C" char *chat_password_hash(const char *pwd, const char *salt);
extern "C" char *chat_valid_name(const char *name);
extern "C" int chat_json_length(const char *str);
extern "C" char *chat_encrypt_media(chat_ctrl ctrl, const char *key, const char *frame, const int len);
extern "C" char *chat_decrypt_media(const char *key, const char *frame, const int len);
// chat_write_file returns null-terminated string with JSON of WriteFileResult
extern "C" char *chat_write_file(chat_ctrl ctrl, const char *path, const char *data, const int len);
// chat_read_file returns a buffer with:
// result status (1 byte), then if
// status == 0 (success): buffer length (uint32, 4 bytes), buffer of specified length.
// status == 1 (error): null-terminated error message string.
extern "C" char *chat_read_file(const char *path, const char *key, const char *nonce);
// chat_encrypt_file returns null-terminated string with JSON of WriteFileResult
extern "C" char *chat_encrypt_file(chat_ctrl ctrl, const char *fromPath, const char *toPath);
// chat_decrypt_file returns null-terminated string with the error message
extern "C" char *chat_decrypt_file(const char *fromPath, const char *key, const char *nonce, const char *toPath);
#endif /* simplex_h */
+31
View File
@@ -0,0 +1,31 @@
{
"name": "simplexjs",
"version": "1.0.0",
"main": "src/index.js",
"scripts": {
"install-tools": "npm install -g node-gyp",
"configure": "node-gyp configure; mkdir libs 2> /dev/null | true",
"rebuild": "node-gyp rebuild",
"build": "node-gyp build",
"run": "node src/index.js",
"build-run": "node-gyp build && node src/index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/simplex-chat/simplex-chat.git"
},
"keywords": [
"messenger",
"chat",
"privacy",
"security"
],
"author": "SimpleX Chat",
"license": "AGPL-3.0",
"bugs": {
"url": "https://github.com/simplex-chat/simplex-chat/issues"
},
"homepage": "https://github.com/simplex-chat/simplex-chat/packages/simplex-chat-nodejs#readme",
"description": ""
}
+22
View File
@@ -0,0 +1,22 @@
const addon = require('../build/Release/addon');
const fs = require('fs');
const ctrlAndRes = addon.chat_migrate_init("db", "a", "yesUp")
const ctrl = Number(ctrlAndRes.split("\n")[0])
const res = ctrlAndRes.split("\n")[1]
console.log("Migrate ctrl:", ctrl, "res:", res)
console.log(addon.chat_send_cmd(ctrl, "/v"))
// const wait = 15_000_000
// console.log(ctrl, addon.chat_recv_msg_wait(ctrl, wait))
const path = "/tmp/write_file.txt"
const data = [0, 1, 2]
console.log(addon.chat_write_file(ctrl, path, new ArrayBuffer(data)))
fs.writeFileSync("/tmp/file_unencrypted.txt", "unencrypted")
const encRes = JSON.parse(addon.chat_encrypt_file(ctrl, "/tmp/file_unencrypted.txt", "/tmp/file_encrypted.txt"))
const key = encRes.cryptoArgs.fileKey
const nonce = encRes.cryptoArgs.fileNonce
console.log(encRes)
console.log(addon.chat_decrypt_file("/tmp/file_encrypted.txt", key, nonce, "/tmp/file_decrypted.txt"))
@@ -2,7 +2,7 @@
set -e
trap "rm apps/multiplatform/local.properties || true; rm local.properties || true; rm /tmp/simplex.keychain || true" EXIT
trap "rm apps/multiplatform/local.properties 2> /dev/null || true; rm local.properties 2> /dev/null || true; rm /tmp/simplex.keychain" EXIT
echo "desktop.mac.signing.identity=Developer ID Application: SimpleX Chat Ltd (5NN7GUYB6T)" >> apps/multiplatform/local.properties
echo "desktop.mac.signing.keychain=/tmp/simplex.keychain" >> apps/multiplatform/local.properties
echo "desktop.mac.notarization.apple_id=$APPLE_SIMPLEX_NOTARIZATION_APPLE_ID" >> apps/multiplatform/local.properties
@@ -10,6 +10,10 @@ echo "desktop.mac.notarization.password=$APPLE_SIMPLEX_NOTARIZATION_PASSWORD" >>
echo "desktop.mac.notarization.team_id=5NN7GUYB6T" >> apps/multiplatform/local.properties
echo "$APPLE_SIMPLEX_SIGNING_KEYCHAIN" | base64 --decode -o /tmp/simplex.keychain
security unlock-keychain -p "" /tmp/simplex.keychain
# Adding keychain to the list of keychains.
# Otherwise, it can find cert but exits while signing with "error: The specified item could not be found in the keychain."
security list-keychains -s `security list-keychains | xargs` /tmp/simplex.keychain
scripts/desktop/build-lib-mac.sh
cd apps/multiplatform
./gradlew packageDmg
+10
View File
@@ -0,0 +1,10 @@
#!/bin/bash
security create-keychain -p "" simplex.keychain
security set-keychain-settings -u simplex.keychain
security add-certificates -k simplex.keychain "Developer ID Application: SimpleX Chat Ltd (5NN7GUYB6T).cer"
security add-certificates -k simplex.keychain "Developer ID Certification Authority.cer"
# Private key with access from any app
security import "SimpleX Chat.p12" -P "" -k simplex.keychain -A
# Public key
security import "SimpleX Chat.pem" -k simplex.keychain
+9 -8
View File
@@ -8,7 +8,7 @@ function readlink() {
OS=linux
ARCH=${1:-`uname -a | rev | cut -d' ' -f2 | rev`}
GHC_VERSION=8.10.7
GHC_VERSION=9.6.3
if [ "$ARCH" == "aarch64" ]; then
COMPOSE_ARCH=arm64
@@ -24,18 +24,19 @@ exports=( $(sed 's/foreign export ccall "chat_migrate_init_key"//' src/Simplex/C
for elem in "${exports[@]}"; do count=$(grep -R "$elem$" libsimplex.dll.def | wc -l); if [ $count -ne 1 ]; then echo Wrong exports in libsimplex.dll.def. Add \"$elem\" to that file; exit 1; fi ; done
for elem in "${exports[@]}"; do count=$(grep -R "\"$elem\"" flake.nix | wc -l); if [ $count -ne 2 ]; then echo Wrong exports in flake.nix. Add \"$elem\" in two places of the file; exit 1; fi ; done
rm -rf $BUILD_DIR
cabal build lib:simplex-chat --ghc-options='-optl-Wl,-rpath,$ORIGIN' --ghc-options="-optl-L$(ghc --print-libdir)/rts -optl-Wl,--as-needed,-lHSrts_thr-ghc$GHC_VERSION" --constraint 'simplexmq +client_library'
#rm -rf $BUILD_DIR
cabal build lib:simplex-chat --ghc-options='-optl-Wl,-rpath,$ORIGIN -optl-Wl,-soname,libsimplex.so -flink-rts -threaded' --constraint 'simplexmq +client_library'
cd $BUILD_DIR/build
#patchelf --add-needed libHSrts_thr-ghc${GHC_VERSION}.so libHSsimplex-chat-*-inplace-ghc${GHC_VERSION}.so
#patchelf --add-rpath '$ORIGIN' libHSsimplex-chat-*-inplace-ghc${GHC_VERSION}.so
mv libHSsimplex-chat-*-inplace-ghc${GHC_VERSION}.so libsimplex.so 2> /dev/null || true
#patchelf --add-needed libHSrts_thr-ghc${GHC_VERSION}.so libsimplex.so
#patchelf --add-rpath '$ORIGIN' libsimplex.so
# GitHub's Ubuntu 20.04 runner started to set libffi.so.7 as a dependency while Ubuntu 20.04 on user's devices may not have it
# but libffi.so.8 is shipped as an external library with other libs
patchelf --replace-needed "libffi.so.7" "libffi.so.8" libHSsimplex-chat-*-inplace-ghc${GHC_VERSION}.so
patchelf --replace-needed "libffi.so.7" "libffi.so.8" libsimplex.so
mkdir deps 2> /dev/null || true
ldd libHSsimplex-chat-*-inplace-ghc${GHC_VERSION}.so | grep "ghc" | cut -d' ' -f 3 | xargs -I {} cp {} ./deps/
ldd libsimplex.so | grep "ghc" | cut -d' ' -f 3 | xargs -I {} cp {} ./deps/
cd -
@@ -44,7 +45,7 @@ rm -rf apps/multiplatform/desktop/build/cmake
mkdir -p apps/multiplatform/common/src/commonMain/cpp/desktop/libs/$OS-$ARCH/
cp -r $BUILD_DIR/build/deps/* apps/multiplatform/common/src/commonMain/cpp/desktop/libs/$OS-$ARCH/
cp $BUILD_DIR/build/libHSsimplex-chat-*-inplace-ghc${GHC_VERSION}.so apps/multiplatform/common/src/commonMain/cpp/desktop/libs/$OS-$ARCH/
cp $BUILD_DIR/build/libsimplex.so apps/multiplatform/common/src/commonMain/cpp/desktop/libs/$OS-$ARCH/
scripts/desktop/prepare-vlc-linux.sh
links_dir=apps/multiplatform/build/links
+22 -5
View File
@@ -5,15 +5,16 @@ set -e
OS=mac
ARCH="${1:-`uname -a | rev | cut -d' ' -f1 | rev`}"
COMPOSE_ARCH=$ARCH
GHC_VERSION=8.10.7
GHC_VERSION=9.6.3
if [ "$ARCH" == "arm64" ]; then
ARCH=aarch64
else
COMPOSE_ARCH=x64
fi
LIB_EXT=dylib
LIB=libHSsimplex-chat-*-inplace-ghc*.$LIB_EXT
LIB=libsimplex.$LIB_EXT
GHC_LIBS_DIR=$(ghc --print-libdir)
BUILD_DIR=dist-newstyle/build/$ARCH-*/ghc-*/simplex-chat-*
@@ -23,13 +24,27 @@ for elem in "${exports[@]}"; do count=$(grep -R "$elem$" libsimplex.dll.def | wc
for elem in "${exports[@]}"; do count=$(grep -R "\"$elem\"" flake.nix | wc -l); if [ $count -ne 2 ]; then echo Wrong exports in flake.nix. Add \"$elem\" in two places of the file; exit 1; fi ; done
rm -rf $BUILD_DIR
cabal build lib:simplex-chat lib:simplex-chat --ghc-options="-optl-Wl,-rpath,@loader_path -optl-Wl,-L$GHC_LIBS_DIR/rts -optl-lHSrts_thr-ghc8.10.7 -optl-lffi" --constraint 'simplexmq +client_library'
cabal build lib:simplex-chat lib:simplex-chat --ghc-options="-optl-Wl,-rpath,@loader_path -optl-Wl,-install_name,@rpath/$LIB -optl-Wl,-L$GHC_LIBS_DIR/$ARCH-osx-ghc-$GHC_VERSION -optl-lHSrts_thr-ghc$GHC_VERSION -optl-lffi" --constraint 'simplexmq +client_library'
cd $BUILD_DIR/build
mv libHSsimplex-chat-*-inplace-ghc*.$LIB_EXT libsimplex.dylib 2> /dev/null || true
mkdir deps 2> /dev/null || true
# It's not included by default for some reason. Compiled lib tries to find system one but it's not always available
cp $GHC_LIBS_DIR/rts/libffi.dylib ./deps
#cp $GHC_LIBS_DIR/libffi.dylib ./deps
(
BUILD=$PWD
cp /tmp/libffi-3.4.4/*-apple-darwin*/.libs/libffi.dylib $BUILD/deps || \
( \
cd /tmp && \
curl --tlsv1.2 "https://gitlab.haskell.org/ghc/libffi-tarballs/-/raw/libffi-3.4.4/libffi-3.4.4.tar.gz?inline=false" -o libffi.tar.gz && \
tar -xzvf libffi.tar.gz && \
cd "libffi-3.4.4" && \
./configure && \
make && \
cp *-apple-darwin*/.libs/libffi.dylib $BUILD/deps \
)
)
DYLIBS=`otool -L $LIB | grep @rpath | tail -n +2 | cut -d' ' -f 1 | cut -d'/' -f2`
RPATHS=`otool -l $LIB | grep "path "| cut -d' ' -f11`
@@ -70,6 +85,8 @@ function copy_deps() {
}
copy_deps $LIB
# Special case
cp $(ghc --print-libdir)/$ARCH-osx-ghc-$GHC_VERSION/libHSghc-boot-th-$GHC_VERSION-ghc$GHC_VERSION.dylib deps
rm deps/`basename $LIB`
cd -
@@ -79,7 +96,7 @@ rm -rf apps/multiplatform/desktop/build/cmake
mkdir -p apps/multiplatform/common/src/commonMain/cpp/desktop/libs/$OS-$ARCH/
cp -r $BUILD_DIR/build/deps/* apps/multiplatform/common/src/commonMain/cpp/desktop/libs/$OS-$ARCH/
cp $BUILD_DIR/build/libHSsimplex-chat-*-inplace-ghc*.$LIB_EXT apps/multiplatform/common/src/commonMain/cpp/desktop/libs/$OS-$ARCH/
cp $BUILD_DIR/build/$LIB apps/multiplatform/common/src/commonMain/cpp/desktop/libs/$OS-$ARCH/
cd apps/multiplatform/common/src/commonMain/cpp/desktop/libs/$OS-$ARCH/
+242
View File
@@ -0,0 +1,242 @@
From 38be2c93acb6f459d24ed6c626981c35ccf44095 Mon Sep 17 00:00:00 2001
From: Sylvain Henry <sylvain@haskus.fr>
Date: Thu, 16 Feb 2023 15:40:45 +0100
Subject: [PATCH] Fix build on 32-bit architectures
---
Basement/Bits.hs | 4 ++++
Basement/From.hs | 24 -----------------------
Basement/Numerical/Additive.hs | 4 ++++
Basement/Numerical/Conversion.hs | 20 +++++++++++++++++++
Basement/PrimType.hs | 6 +++++-
Basement/Types/OffsetSize.hs | 22 +++++++++++++++++++--
6 files changed, 53 insertions(+), 27 deletions(-)
diff --git a/Basement/Bits.hs b/Basement/Bits.hs
index 7eeea0f5..24520ed7 100644
--- a/Basement/Bits.hs
+++ b/Basement/Bits.hs
@@ -54,8 +54,12 @@ import GHC.Int
import Basement.Compat.Primitive
#if WORD_SIZE_IN_BITS < 64
+#if __GLASGOW_HASKELL__ >= 904
+import GHC.Exts
+#else
import GHC.IntWord64
#endif
+#endif
-- | operation over finite bits
class FiniteBitsOps bits where
diff --git a/Basement/From.hs b/Basement/From.hs
index 7bbe141c..80014b3e 100644
--- a/Basement/From.hs
+++ b/Basement/From.hs
@@ -272,23 +272,11 @@ instance (NatWithinBound (CountOf ty) n, KnownNat n, PrimType ty)
tryFrom = BlockN.toBlockN . UArray.toBlock . BoxArray.mapToUnboxed id
instance (KnownNat n, NatWithinBound Word8 n) => From (Zn64 n) Word8 where
-#if __GLASGOW_HASKELL__ >= 904
- from = narrow . unZn64 where narrow (W64# w) = W8# (wordToWord8# (word64ToWord# (GHC.Prim.word64ToWord# w)))
-#else
from = narrow . unZn64 where narrow (W64# w) = W8# (wordToWord8# (word64ToWord# w))
-#endif
instance (KnownNat n, NatWithinBound Word16 n) => From (Zn64 n) Word16 where
-#if __GLASGOW_HASKELL__ >= 904
- from = narrow . unZn64 where narrow (W64# w) = W16# (wordToWord16# (word64ToWord# (GHC.Prim.word64ToWord# w)))
-#else
from = narrow . unZn64 where narrow (W64# w) = W16# (wordToWord16# (word64ToWord# w))
-#endif
instance (KnownNat n, NatWithinBound Word32 n) => From (Zn64 n) Word32 where
-#if __GLASGOW_HASKELL__ >= 904
- from = narrow . unZn64 where narrow (W64# w) = W32# (wordToWord32# (word64ToWord# (GHC.Prim.word64ToWord# w)))
-#else
from = narrow . unZn64 where narrow (W64# w) = W32# (wordToWord32# (word64ToWord# w))
-#endif
instance From (Zn64 n) Word64 where
from = unZn64
instance From (Zn64 n) Word128 where
@@ -297,23 +285,11 @@ instance From (Zn64 n) Word256 where
from = from . unZn64
instance (KnownNat n, NatWithinBound Word8 n) => From (Zn n) Word8 where
-#if __GLASGOW_HASKELL__ >= 904
- from = narrow . naturalToWord64 . unZn where narrow (W64# w) = W8# (wordToWord8# (word64ToWord# (GHC.Prim.word64ToWord# w)))
-#else
from = narrow . naturalToWord64 . unZn where narrow (W64# w) = W8# (wordToWord8# (word64ToWord# w))
-#endif
instance (KnownNat n, NatWithinBound Word16 n) => From (Zn n) Word16 where
-#if __GLASGOW_HASKELL__ >= 904
- from = narrow . naturalToWord64 . unZn where narrow (W64# w) = W16# (wordToWord16# (word64ToWord# (GHC.Prim.word64ToWord# w)))
-#else
from = narrow . naturalToWord64 . unZn where narrow (W64# w) = W16# (wordToWord16# (word64ToWord# w))
-#endif
instance (KnownNat n, NatWithinBound Word32 n) => From (Zn n) Word32 where
-#if __GLASGOW_HASKELL__ >= 904
- from = narrow . naturalToWord64 . unZn where narrow (W64# w) = W32# (wordToWord32# (word64ToWord# (GHC.Prim.word64ToWord# w)))
-#else
from = narrow . naturalToWord64 . unZn where narrow (W64# w) = W32# (wordToWord32# (word64ToWord# w))
-#endif
instance (KnownNat n, NatWithinBound Word64 n) => From (Zn n) Word64 where
from = naturalToWord64 . unZn
instance (KnownNat n, NatWithinBound Word128 n) => From (Zn n) Word128 where
diff --git a/Basement/Numerical/Additive.hs b/Basement/Numerical/Additive.hs
index d0dfb973..8ab65aa0 100644
--- a/Basement/Numerical/Additive.hs
+++ b/Basement/Numerical/Additive.hs
@@ -30,8 +30,12 @@ import qualified Basement.Types.Word128 as Word128
import qualified Basement.Types.Word256 as Word256
#if WORD_SIZE_IN_BITS < 64
+#if __GLASGOW_HASKELL__ >= 904
+import GHC.Exts
+#else
import GHC.IntWord64
#endif
+#endif
-- | Represent class of things that can be added together,
-- contains a neutral element and is commutative.
diff --git a/Basement/Numerical/Conversion.hs b/Basement/Numerical/Conversion.hs
index db502c07..fddc8232 100644
--- a/Basement/Numerical/Conversion.hs
+++ b/Basement/Numerical/Conversion.hs
@@ -26,8 +26,12 @@ import GHC.Word
import Basement.Compat.Primitive
#if WORD_SIZE_IN_BITS < 64
+#if __GLASGOW_HASKELL__ >= 904
+import GHC.Exts
+#else
import GHC.IntWord64
#endif
+#endif
intToInt64 :: Int -> Int64
#if WORD_SIZE_IN_BITS == 64
@@ -96,11 +100,22 @@ int64ToWord64 (I64# i) = W64# (int64ToWord64# i)
#endif
#if WORD_SIZE_IN_BITS == 64
+#if __GLASGOW_HASKELL__ >= 904
+word64ToWord# :: Word64# -> Word#
+word64ToWord# i = word64ToWord# i
+#else
word64ToWord# :: Word# -> Word#
word64ToWord# i = i
+#endif
{-# INLINE word64ToWord# #-}
#endif
+#if WORD_SIZE_IN_BITS < 64
+word64ToWord32# :: Word64# -> Word32#
+word64ToWord32# i = wordToWord32# (word64ToWord# i)
+{-# INLINE word64ToWord32# #-}
+#endif
+
-- | 2 Word32s
data Word32x2 = Word32x2 {-# UNPACK #-} !Word32
{-# UNPACK #-} !Word32
@@ -113,9 +128,14 @@ word64ToWord32s (W64# w64) = Word32x2 (W32# (wordToWord32# (uncheckedShiftRL# (G
word64ToWord32s (W64# w64) = Word32x2 (W32# (wordToWord32# (uncheckedShiftRL# w64 32#))) (W32# (wordToWord32# w64))
#endif
#else
+#if __GLASGOW_HASKELL__ >= 904
+word64ToWord32s :: Word64 -> Word32x2
+word64ToWord32s (W64# w64) = Word32x2 (W32# (word64ToWord32# (uncheckedShiftRL64# w64 32#))) (W32# (word64ToWord32# w64))
+#else
word64ToWord32s :: Word64 -> Word32x2
word64ToWord32s (W64# w64) = Word32x2 (W32# (word64ToWord# (uncheckedShiftRL64# w64 32#))) (W32# (word64ToWord# w64))
#endif
+#endif
wordToChar :: Word -> Char
wordToChar (W# word) = C# (chr# (word2Int# word))
diff --git a/Basement/PrimType.hs b/Basement/PrimType.hs
index f8ca2926..a888ec91 100644
--- a/Basement/PrimType.hs
+++ b/Basement/PrimType.hs
@@ -54,7 +54,11 @@ import Basement.Nat
import qualified Prelude (quot)
#if WORD_SIZE_IN_BITS < 64
-import GHC.IntWord64
+#if __GLASGOW_HASKELL__ >= 904
+import GHC.Exts
+#else
+import GHC.IntWord64
+#endif
#endif
#ifdef FOUNDATION_BOUNDS_CHECK
diff --git a/Basement/Types/OffsetSize.hs b/Basement/Types/OffsetSize.hs
index cd944927..1ea80dad 100644
--- a/Basement/Types/OffsetSize.hs
+++ b/Basement/Types/OffsetSize.hs
@@ -70,8 +70,12 @@ import Data.List (foldl')
import qualified Prelude
#if WORD_SIZE_IN_BITS < 64
+#if __GLASGOW_HASKELL__ >= 904
+import GHC.Exts
+#else
import GHC.IntWord64
#endif
+#endif
-- | File size in bytes
newtype FileSize = FileSize Word64
@@ -225,20 +229,26 @@ countOfRoundUp alignment (CountOf n) = CountOf ((n + (alignment-1)) .&. compleme
csizeOfSize :: CountOf Word8 -> CSize
#if WORD_SIZE_IN_BITS < 64
+#if __GLASGOW_HASKELL__ >= 904
+csizeOfSize (CountOf (I# sz)) = CSize (W32# (wordToWord32# (int2Word# sz)))
+#else
csizeOfSize (CountOf (I# sz)) = CSize (W32# (int2Word# sz))
+#endif
#else
#if __GLASGOW_HASKELL__ >= 904
csizeOfSize (CountOf (I# sz)) = CSize (W64# (wordToWord64# (int2Word# sz)))
-
#else
csizeOfSize (CountOf (I# sz)) = CSize (W64# (int2Word# sz))
-
#endif
#endif
csizeOfOffset :: Offset8 -> CSize
#if WORD_SIZE_IN_BITS < 64
+#if __GLASGOW_HASKELL__ >= 904
+csizeOfOffset (Offset (I# sz)) = CSize (W32# (wordToWord32# (int2Word# sz)))
+#else
csizeOfOffset (Offset (I# sz)) = CSize (W32# (int2Word# sz))
+#endif
#else
#if __GLASGOW_HASKELL__ >= 904
csizeOfOffset (Offset (I# sz)) = CSize (W64# (wordToWord64# (int2Word# sz)))
@@ -250,7 +260,11 @@ csizeOfOffset (Offset (I# sz)) = CSize (W64# (int2Word# sz))
sizeOfCSSize :: CSsize -> CountOf Word8
sizeOfCSSize (CSsize (-1)) = error "invalid size: CSSize is -1"
#if WORD_SIZE_IN_BITS < 64
+#if __GLASGOW_HASKELL__ >= 904
+sizeOfCSSize (CSsize (I32# sz)) = CountOf (I# (int32ToInt# sz))
+#else
sizeOfCSSize (CSsize (I32# sz)) = CountOf (I# sz)
+#endif
#else
#if __GLASGOW_HASKELL__ >= 904
sizeOfCSSize (CSsize (I64# sz)) = CountOf (I# (int64ToInt# sz))
@@ -261,7 +275,11 @@ sizeOfCSSize (CSsize (I64# sz)) = CountOf (I# sz)
sizeOfCSize :: CSize -> CountOf Word8
#if WORD_SIZE_IN_BITS < 64
+#if __GLASGOW_HASKELL__ >= 904
+sizeOfCSize (CSize (W32# sz)) = CountOf (I# (word2Int# (word32ToWord# sz)))
+#else
sizeOfCSize (CSize (W32# sz)) = CountOf (I# (word2Int# sz))
+#endif
#else
#if __GLASGOW_HASKELL__ >= 904
sizeOfCSize (CSize (W64# sz)) = CountOf (I# (word2Int# (word64ToWord# sz)))
@@ -0,0 +1,12 @@
diff --git a/direct-sqlcipher.cabal b/direct-sqlcipher.cabal
index 728ba3e..c63745e 100644
--- a/direct-sqlcipher.cabal
+++ b/direct-sqlcipher.cabal
@@ -84,6 +84,8 @@ library
cc-options: -DSQLITE_TEMP_STORE=2
-DSQLITE_HAS_CODEC
+ extra-libraries: ws2_32
+
if !os(windows) && !os(android)
extra-libraries: pthread
+36
View File
@@ -0,0 +1,36 @@
From 2738929ce15b4c8704bbbac24a08539b5d4bf30e Mon Sep 17 00:00:00 2001
From: sternenseemann <sternenseemann@systemli.org>
Date: Mon, 14 Aug 2023 10:51:30 +0200
Subject: [PATCH] Data.Memory.Internal.CompatPrim64: fix 32 bit with GHC >= 9.4
Since 9.4, GHC.Prim exports Word64# operations like timesWord64# even on
i686 whereas GHC.IntWord64 no longer exists. Therefore, we can just use
the ready made solution.
Closes #98, as it should be the better solution.
---
Data/Memory/Internal/CompatPrim64.hs | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/Data/Memory/Internal/CompatPrim64.hs b/Data/Memory/Internal/CompatPrim64.hs
index b9eef8a..a134c88 100644
--- a/Data/Memory/Internal/CompatPrim64.hs
+++ b/Data/Memory/Internal/CompatPrim64.hs
@@ -150,6 +150,7 @@ w64# :: Word# -> Word# -> Word# -> Word64#
w64# w _ _ = w
#elif WORD_SIZE_IN_BITS == 32
+#if __GLASGOW_HASKELL__ < 904
import GHC.IntWord64
import GHC.Prim (Word#)
@@ -158,6 +159,9 @@ timesWord64# a b =
let !ai = word64ToInt64# a
!bi = word64ToInt64# b
in int64ToWord64# (timesInt64# ai bi)
+#else
+import GHC.Prim
+#endif
w64# :: Word# -> Word# -> Word# -> Word64#
w64# _ hw lw =