diff --git a/syng-im/.re-natal b/syng-im/.re-natal index 20f66539ae..8fd652b4ea 100644 --- a/syng-im/.re-natal +++ b/syng-im/.re-natal @@ -9,7 +9,11 @@ "realm", "react-native-loading-spinner-overlay", "react-native-i18n", - "realm/react-native" + "realm/react-native", + "react-native-action-button", + "react-native-vector-icons/Ionicons", + "react-native-circle-checkbox", + "react-native-randombytes" ], "imageDirs": [ "images" diff --git a/syng-im/android/app/build.gradle b/syng-im/android/app/build.gradle index 8c1f179166..9f152c2e9b 100644 --- a/syng-im/android/app/build.gradle +++ b/syng-im/android/app/build.gradle @@ -119,6 +119,9 @@ android { } dependencies { + compile project(':randombytes') + compile project(':realm') + compile project(':react-native-vector-icons') compile fileTree(dir: "libs", include: ["*.jar"]) compile "com.android.support:appcompat-v7:23.0.1" compile "com.facebook.react:react-native:+" // From node_modules @@ -127,6 +130,5 @@ dependencies { // compile(name:'geth', ext:'aar') compile(group: 'syng-im', name: 'android-geth', version: '1.4.0-201603131817-92d65cf', ext: 'aar') - compile project(":realm") compile fileTree(dir: "node_modules/realm/android/libs", include: ["*.jar"]) } diff --git a/syng-im/android/app/src/main/assets/fonts/Entypo.ttf b/syng-im/android/app/src/main/assets/fonts/Entypo.ttf new file mode 100644 index 0000000000..1c8f5e910b Binary files /dev/null and b/syng-im/android/app/src/main/assets/fonts/Entypo.ttf differ diff --git a/syng-im/android/app/src/main/assets/fonts/EvilIcons.ttf b/syng-im/android/app/src/main/assets/fonts/EvilIcons.ttf new file mode 100644 index 0000000000..b270f98519 Binary files /dev/null and b/syng-im/android/app/src/main/assets/fonts/EvilIcons.ttf differ diff --git a/syng-im/android/app/src/main/assets/fonts/FontAwesome.ttf b/syng-im/android/app/src/main/assets/fonts/FontAwesome.ttf new file mode 100644 index 0000000000..26dea7951a Binary files /dev/null and b/syng-im/android/app/src/main/assets/fonts/FontAwesome.ttf differ diff --git a/syng-im/android/app/src/main/assets/fonts/Foundation.ttf b/syng-im/android/app/src/main/assets/fonts/Foundation.ttf new file mode 100644 index 0000000000..6cce217ddc Binary files /dev/null and b/syng-im/android/app/src/main/assets/fonts/Foundation.ttf differ diff --git a/syng-im/android/app/src/main/assets/fonts/Ionicons.ttf b/syng-im/android/app/src/main/assets/fonts/Ionicons.ttf new file mode 100644 index 0000000000..c4e4632486 Binary files /dev/null and b/syng-im/android/app/src/main/assets/fonts/Ionicons.ttf differ diff --git a/syng-im/android/app/src/main/assets/fonts/MaterialIcons.ttf b/syng-im/android/app/src/main/assets/fonts/MaterialIcons.ttf new file mode 100644 index 0000000000..7015564ad1 Binary files /dev/null and b/syng-im/android/app/src/main/assets/fonts/MaterialIcons.ttf differ diff --git a/syng-im/android/app/src/main/assets/fonts/Octicons.ttf b/syng-im/android/app/src/main/assets/fonts/Octicons.ttf new file mode 100644 index 0000000000..0a62bb9ea6 Binary files /dev/null and b/syng-im/android/app/src/main/assets/fonts/Octicons.ttf differ diff --git a/syng-im/android/app/src/main/assets/fonts/Zocial.ttf b/syng-im/android/app/src/main/assets/fonts/Zocial.ttf new file mode 100644 index 0000000000..e4ae46c628 Binary files /dev/null and b/syng-im/android/app/src/main/assets/fonts/Zocial.ttf differ diff --git a/syng-im/android/app/src/main/java/com/syngim/MainActivity.java b/syng-im/android/app/src/main/java/com/syngim/MainActivity.java index 45d4f60e4a..b080070f49 100644 --- a/syng-im/android/app/src/main/java/com/syngim/MainActivity.java +++ b/syng-im/android/app/src/main/java/com/syngim/MainActivity.java @@ -1,12 +1,15 @@ package com.syngim; import com.facebook.react.ReactActivity; +import io.realm.react.RealmReactPackage; +import com.oblador.vectoricons.VectorIconsPackage; import com.facebook.react.ReactPackage; import com.facebook.react.shell.MainReactPackage; import com.rt2zz.reactnativecontacts.ReactNativeContacts; import android.os.Bundle; import android.os.Environment; import com.github.ethereum.go_ethereum.cmd.Geth; +import com.bitgo.randombytes.RandomBytesPackage; import java.util.Arrays; import java.util.List; @@ -63,17 +66,19 @@ public class MainActivity extends ReactActivity { return BuildConfig.DEBUG; } - /** - * A list of packages used by the app. If the app uses additional views - * or modules besides the default ones, add more packages here. - */ + /** + * A list of packages used by the app. If the app uses additional views + * or modules besides the default ones, add more packages here. + */ @Override protected List getPackages() { return Arrays.asList( new MainReactPackage(), + new RealmReactPackage(), + new VectorIconsPackage(), new ReactNativeContacts(), new ReactNativeI18n(), - new RealmReactPackage() + new RandomBytesPackage() ); } } diff --git a/syng-im/android/settings.gradle b/syng-im/android/settings.gradle index 34c3013fea..784925e19a 100644 --- a/syng-im/android/settings.gradle +++ b/syng-im/android/settings.gradle @@ -8,5 +8,9 @@ project(':react-native-contacts').projectDir = new File(settingsDir, '../node_mo include ':react-native-i18n' project(':react-native-i18n').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-i18n/android') // realm dependency +include ':react-native-vector-icons' +project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android') include ':realm' project(':realm').projectDir = new File(rootProject.projectDir, '../node_modules/realm/android') +include ':randombytes' +project(':randombytes').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-randombytes/app') \ No newline at end of file diff --git a/syng-im/images/v.png b/syng-im/images/v.png new file mode 100644 index 0000000000..b078afbebe Binary files /dev/null and b/syng-im/images/v.png differ diff --git a/syng-im/ios/Messenger.xcodeproj/project.pbxproj b/syng-im/ios/Messenger.xcodeproj/project.pbxproj index 664e54be92..2780f9a5f1 100644 --- a/syng-im/ios/Messenger.xcodeproj/project.pbxproj +++ b/syng-im/ios/Messenger.xcodeproj/project.pbxproj @@ -5,7 +5,6 @@ }; objectVersion = 46; objects = { - /* Begin PBXBuildFile section */ 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; }; 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; }; @@ -25,6 +24,19 @@ E343FE8E1C96F54100C01DB5 /* libRNI18n.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E343FE8B1C96F4E200C01DB5 /* libRNI18n.a */; }; E343FE8F1C96F54A00C01DB5 /* libRCTContacts.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E343FE841C96F4DA00C01DB5 /* libRCTContacts.a */; }; E343FE911C971D4200C01DB5 /* Geth.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E343FE901C971D4200C01DB5 /* Geth.framework */; }; + 5F301739E81C4A7B92E80915 /* libRNVectorIcons.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1429DFB76DE749D59880DD64 /* libRNVectorIcons.a */; }; + 2171A55FE83747678065F72A /* Entypo.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 93C8E68B46DA4C0A98C39F9D /* Entypo.ttf */; }; + BDF23426F8854AC2A0416A03 /* EvilIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 38E7B297EE0748008056796A /* EvilIcons.ttf */; }; + 221509FA6D5443C0B5215C52 /* FontAwesome.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 2CF9FE7E98A3454D980A0BED /* FontAwesome.ttf */; }; + A33AC3EAFBC04C0B93BD2EC4 /* Foundation.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 5A831378BBA14830A9540B8C /* Foundation.ttf */; }; + 1A4121618C94428C9F0DF1FE /* Ionicons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 5F085711AC4A4BA3887A4655 /* Ionicons.ttf */; }; + 59FCD4F0208949BE80CC72BF /* MaterialIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 0063E967269B49EE80DC3A77 /* MaterialIcons.ttf */; }; + 4452A93C123F4392A99A7719 /* Octicons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = A74F40BECFF8439FB1F41D8A /* Octicons.ttf */; }; + 1AE91A3E2C1A43EFA90C1CD7 /* Zocial.ttf in Resources */ = {isa = PBXBuildFile; fileRef = BCEC948817B84597AC493C0B /* Zocial.ttf */; }; + 34535F62E77D4A75A25E2981 /* libRNRandomBytes.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2925028DE4684DDAAA7389D7 /* libRNRandomBytes.a */; }; + 97BD21CBE96A4223B253A1E2 /* libRealmReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2B29C182EE0942C889049F91 /* libRealmReact.a */; }; + 22802A9C745148D885F0AA01 /* libc++.tbd in Resources */ = {isa = PBXBuildFile; fileRef = 8003209F13C24D35AABD3933 /* libc++.tbd */; }; + 50EE6BCC6F1A48BBA1BDB893 /* libz.tbd in Resources */ = {isa = PBXBuildFile; fileRef = 313A77B1D7804DBDBE6FF6F5 /* libz.tbd */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -153,6 +165,22 @@ E343FE7F1C96F4DA00C01DB5 /* RCTContacts.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTContacts.xcodeproj; path = "../node_modules/react-native-contacts/ios/RCTContacts.xcodeproj"; sourceTree = ""; }; E343FE851C96F4E200C01DB5 /* RNI18n.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RNI18n.xcodeproj; path = "../node_modules/react-native-i18n/RNI18n.xcodeproj"; sourceTree = ""; }; E343FE901C971D4200C01DB5 /* Geth.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Geth.framework; path = target/Frameworks/Geth.framework; sourceTree = ""; }; + F04672B9D3824B768FCF6F71 /* RNVectorIcons.xcodeproj */ = {isa = PBXFileReference; name = "RNVectorIcons.xcodeproj"; path = "../node_modules/react-native-vector-icons/RNVectorIcons.xcodeproj"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = wrapper.pb-project; explicitFileType = undefined; includeInIndex = 0; }; + 1429DFB76DE749D59880DD64 /* libRNVectorIcons.a */ = {isa = PBXFileReference; name = "libRNVectorIcons.a"; path = "libRNVectorIcons.a"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = archive.ar; explicitFileType = undefined; includeInIndex = 0; }; + 93C8E68B46DA4C0A98C39F9D /* Entypo.ttf */ = {isa = PBXFileReference; name = "Entypo.ttf"; path = "../node_modules/react-native-vector-icons/Fonts/Entypo.ttf"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; }; + 38E7B297EE0748008056796A /* EvilIcons.ttf */ = {isa = PBXFileReference; name = "EvilIcons.ttf"; path = "../node_modules/react-native-vector-icons/Fonts/EvilIcons.ttf"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; }; + 2CF9FE7E98A3454D980A0BED /* FontAwesome.ttf */ = {isa = PBXFileReference; name = "FontAwesome.ttf"; path = "../node_modules/react-native-vector-icons/Fonts/FontAwesome.ttf"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; }; + 5A831378BBA14830A9540B8C /* Foundation.ttf */ = {isa = PBXFileReference; name = "Foundation.ttf"; path = "../node_modules/react-native-vector-icons/Fonts/Foundation.ttf"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; }; + 5F085711AC4A4BA3887A4655 /* Ionicons.ttf */ = {isa = PBXFileReference; name = "Ionicons.ttf"; path = "../node_modules/react-native-vector-icons/Fonts/Ionicons.ttf"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; }; + 0063E967269B49EE80DC3A77 /* MaterialIcons.ttf */ = {isa = PBXFileReference; name = "MaterialIcons.ttf"; path = "../node_modules/react-native-vector-icons/Fonts/MaterialIcons.ttf"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; }; + A74F40BECFF8439FB1F41D8A /* Octicons.ttf */ = {isa = PBXFileReference; name = "Octicons.ttf"; path = "../node_modules/react-native-vector-icons/Fonts/Octicons.ttf"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; }; + BCEC948817B84597AC493C0B /* Zocial.ttf */ = {isa = PBXFileReference; name = "Zocial.ttf"; path = "../node_modules/react-native-vector-icons/Fonts/Zocial.ttf"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; }; + 06F26555B4054594966B6B08 /* RNRandomBytes.xcodeproj */ = {isa = PBXFileReference; name = "RNRandomBytes.xcodeproj"; path = "../node_modules/react-native-randombytes/RNRandomBytes.xcodeproj"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = wrapper.pb-project; explicitFileType = undefined; includeInIndex = 0; }; + 2925028DE4684DDAAA7389D7 /* libRNRandomBytes.a */ = {isa = PBXFileReference; name = "libRNRandomBytes.a"; path = "libRNRandomBytes.a"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = archive.ar; explicitFileType = undefined; includeInIndex = 0; }; + 0D4A52AE301842E1B2533BD3 /* RealmReact.xcodeproj */ = {isa = PBXFileReference; name = "RealmReact.xcodeproj"; path = "../node_modules/realm/react-native/ios/RealmReact.xcodeproj"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = wrapper.pb-project; explicitFileType = undefined; includeInIndex = 0; }; + 2B29C182EE0942C889049F91 /* libRealmReact.a */ = {isa = PBXFileReference; name = "libRealmReact.a"; path = "libRealmReact.a"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = archive.ar; explicitFileType = undefined; includeInIndex = 0; }; + 8003209F13C24D35AABD3933 /* libc++.tbd */ = {isa = PBXFileReference; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; fileEncoding = undefined; lastKnownFileType = sourcecode.text-based-dylib-definition; explicitFileType = undefined; includeInIndex = 0; }; + 313A77B1D7804DBDBE6FF6F5 /* libz.tbd */ = {isa = PBXFileReference; name = "libz.tbd"; path = "usr/lib/libz.tbd"; sourceTree = SDKROOT; fileEncoding = undefined; lastKnownFileType = sourcecode.text-based-dylib-definition; explicitFileType = undefined; includeInIndex = 0; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -180,6 +208,11 @@ 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */, 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */, 139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */, + 5F301739E81C4A7B92E80915 /* libRNVectorIcons.a in Frameworks */, + 34535F62E77D4A75A25E2981 /* libRNRandomBytes.a in Frameworks */, + 97BD21CBE96A4223B253A1E2 /* libRealmReact.a in Frameworks */, + 22802A9C745148D885F0AA01 /* libc++.tbd in Resources */, + 50EE6BCC6F1A48BBA1BDB893 /* libz.tbd in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -304,6 +337,9 @@ 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */, 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */, 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */, + F04672B9D3824B768FCF6F71 /* RNVectorIcons.xcodeproj */, + 06F26555B4054594966B6B08 /* RNRandomBytes.xcodeproj */, + 0D4A52AE301842E1B2533BD3 /* RealmReact.xcodeproj */, ); name = Libraries; sourceTree = ""; @@ -324,6 +360,7 @@ 832341AE1AAA6A7D00B99B32 /* Libraries */, 00E356EF1AD99517003FC87E /* MessengerTests */, 83CBBA001A601CBA00E9B192 /* Products */, + A72CA0FB822D450E98649ACB /* Resources */, ); indentWidth = 2; sourceTree = ""; @@ -359,10 +396,28 @@ isa = PBXGroup; children = ( E343FE901C971D4200C01DB5 /* Geth.framework */, + 8003209F13C24D35AABD3933 /* libc++.tbd */, + 313A77B1D7804DBDBE6FF6F5 /* libz.tbd */, ); name = Frameworks; sourceTree = ""; }; + A72CA0FB822D450E98649ACB /* Resources */ = { + isa = PBXGroup; + children = ( + 93C8E68B46DA4C0A98C39F9D /* Entypo.ttf */, + 38E7B297EE0748008056796A /* EvilIcons.ttf */, + 2CF9FE7E98A3454D980A0BED /* FontAwesome.ttf */, + 5A831378BBA14830A9540B8C /* Foundation.ttf */, + 5F085711AC4A4BA3887A4655 /* Ionicons.ttf */, + 0063E967269B49EE80DC3A77 /* MaterialIcons.ttf */, + A74F40BECFF8439FB1F41D8A /* Octicons.ttf */, + BCEC948817B84597AC493C0B /* Zocial.ttf */, + ); + name = Resources; + path = ""; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -408,7 +463,7 @@ 83CBB9F71A601CBA00E9B192 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0720; + LastUpgradeCheck = 720; ORGANIZATIONNAME = Facebook; TargetAttributes = { 00E356ED1AD99517003FC87E = { @@ -594,6 +649,14 @@ files = ( 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */, + 2171A55FE83747678065F72A /* Entypo.ttf in Resources */, + BDF23426F8854AC2A0416A03 /* EvilIcons.ttf in Resources */, + 221509FA6D5443C0B5215C52 /* FontAwesome.ttf in Resources */, + A33AC3EAFBC04C0B93BD2EC4 /* Foundation.ttf in Resources */, + 1A4121618C94428C9F0DF1FE /* Ionicons.ttf in Resources */, + 59FCD4F0208949BE80CC72BF /* MaterialIcons.ttf in Resources */, + 4452A93C123F4392A99A7719 /* Octicons.ttf in Resources */, + 1AE91A3E2C1A43EFA90C1CD7 /* Zocial.ttf in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -675,6 +738,11 @@ PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Messenger.app/Messenger"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", + ); }; name = Debug; }; @@ -693,6 +761,11 @@ PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Messenger.app/Messenger"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", + ); }; name = Release; }; @@ -709,6 +782,9 @@ "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, "$(SRCROOT)/../node_modules/react-native/React/**", + "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", + "$(SRCROOT)/../node_modules/react-native-randombytes", + "$(SRCROOT)/../node_modules/realm/src/**", ); INFOPLIST_FILE = Messenger/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -730,6 +806,9 @@ "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, "$(SRCROOT)/../node_modules/react-native/React/**", + "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", + "$(SRCROOT)/../node_modules/react-native-randombytes", + "$(SRCROOT)/../node_modules/realm/src/**", ); INFOPLIST_FILE = Messenger/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -778,6 +857,9 @@ "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, "$(SRCROOT)/../node_modules/react-native/React/**", + "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", + "$(SRCROOT)/../node_modules/react-native-randombytes", + "$(SRCROOT)/../node_modules/realm/src/**", ); IPHONEOS_DEPLOYMENT_TARGET = 7.0; MTL_ENABLE_DEBUG_INFO = YES; @@ -818,6 +900,9 @@ "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, "$(SRCROOT)/../node_modules/react-native/React/**", + "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", + "$(SRCROOT)/../node_modules/react-native-randombytes", + "$(SRCROOT)/../node_modules/realm/src/**", ); IPHONEOS_DEPLOYMENT_TARGET = 7.0; MTL_ENABLE_DEBUG_INFO = NO; diff --git a/syng-im/package.json b/syng-im/package.json index 9a81d2f595..f069c032a4 100644 --- a/syng-im/package.json +++ b/syng-im/package.json @@ -8,10 +8,14 @@ "dependencies": { "awesome-phonenumber": "^1.0.12", "react-native": "^0.22.0", + "react-native-action-button": "^1.1.3", + "react-native-circle-checkbox": "^0.1.3", "react-native-contacts": "^0.2.1", "react-native-i18n": "0.0.8", "react-native-invertible-scroll-view": "^0.2.0", "react-native-loading-spinner-overlay": "0.0.6", + "react-native-randombytes": "^2.0.0", + "react-native-vector-icons": "^1.3.3", "realm": "^0.11.0" } } diff --git a/syng-im/src/syng_im/android/core.cljs b/syng-im/src/syng_im/android/core.cljs index 1cd03b3b51..2b80e8436d 100644 --- a/syng-im/src/syng_im/android/core.cljs +++ b/syng-im/src/syng_im/android/core.cljs @@ -12,8 +12,10 @@ [syng-im.components.sign-up :refer [sign-up-view]] [syng-im.components.sign-up-confirm :refer [sign-up-confirm-view]] [syng-im.components.chats.chats-list :refer [chats-list]] + [syng-im.components.chats.new-group :refer [new-group]] [syng-im.utils.logging :as log] - [syng-im.navigation :as nav])) + [syng-im.navigation :as nav] + [syng-im.utils.encryption])) (def back-button-handler (cljs/atom {:nav nil :handler nil})) @@ -32,8 +34,7 @@ (add-event-listener "hardwareBackPress" new-listener))))) (defn app-root [] - [navigator {:initial-route (clj->js {:view-id ;:chat-list - :chat}) + [navigator {:initial-route (clj->js {:view-id :chat-list}) :render-scene (fn [route nav] (log/debug "route" route) (when true ;; nav/*nav-render* @@ -42,6 +43,7 @@ (init-back-button-handler! nav) (case view-id :chat-list (r/as-element [chats-list {:navigator nav}]) + :new-group (r/as-element [new-group {:navigator nav}]) :contact-list (r/as-element [contact-list {:navigator nav}]) :chat (r/as-element [chat {:navigator nav}]) :sign-up (r/as-element [sign-up-view {:navigator nav}]) @@ -49,6 +51,7 @@ (defn init [] (dispatch-sync [:initialize-db]) + (dispatch [:initialize-crypt]) (dispatch [:initialize-protocol]) (dispatch [:load-user-phone-number]) (dispatch [:load-syng-contacts]) diff --git a/syng-im/src/syng_im/components/action_button.cljs b/syng-im/src/syng_im/components/action_button.cljs new file mode 100644 index 0000000000..bfabb5ad0e --- /dev/null +++ b/syng-im/src/syng_im/components/action_button.cljs @@ -0,0 +1,7 @@ +(ns syng-im.components.action-button + (:require [reagent.core :as r])) + +(set! js/window.ActionButton (js/require "react-native-action-button")) + +(def action-button (r/adapt-react-class (.-default js/ActionButton))) +(def action-button-item (r/adapt-react-class (.. js/ActionButton -default -Item))) \ No newline at end of file diff --git a/syng-im/src/syng_im/components/chat.cljs b/syng-im/src/syng_im/components/chat.cljs index 13ab983ee7..5804e557ab 100644 --- a/syng-im/src/syng_im/components/chat.cljs +++ b/syng-im/src/syng_im/components/chat.cljs @@ -19,7 +19,8 @@ (defn chat [{:keys [navigator]}] - (let [messages (subscribe [:get-chat-messages])] + (let [messages (subscribe [:get-chat-messages]) + chat (subscribe [:get-current-chat])] (fn [] (let [msgs @messages _ (log/debug "messages=" msgs) @@ -29,7 +30,8 @@ (when android? ;; TODO add IOS version [toolbar-android {:logo res/logo-icon - :title "Chat name" + :title (or (@chat :name) + "Chat name") :titleColor "#4A5258" :subtitle "Last seen just now" :subtitleColor "#AAB2B2" diff --git a/syng-im/src/syng_im/components/chat/plain_message_input.cljs b/syng-im/src/syng_im/components/chat/plain_message_input.cljs index aa53427c30..3ad75a8802 100644 --- a/syng-im/src/syng_im/components/chat/plain_message_input.cljs +++ b/syng-im/src/syng_im/components/chat/plain_message_input.cljs @@ -11,8 +11,8 @@ [reagent.core :as r])) (defn plain-message-input-view [] - (let [text (r/atom "") - chat-id (subscribe [:get-current-chat-id])] + (let [text (r/atom "") + chat (subscribe [:get-current-chat])] (dispatch [:generate-suggestions @text]) (fn [] [view {:style {:flexDirection "column"}} @@ -42,7 +42,10 @@ (reset! text new-text) (r/flush)) :onSubmitEditing (fn [e] - (dispatch [:send-chat-msg @chat-id @text]) + (let [{:keys [group-chat chat-id]} (:chat-id @chat)] + (if group-chat + (dispatch [:send-group-chat-msg chat-id @text]) + (dispatch [:send-chat-msg chat-id @text]))) (reset! text nil))}] [image {:source res/smile :style {:marginTop 11 diff --git a/syng-im/src/syng_im/components/chats/chats_list.cljs b/syng-im/src/syng_im/components/chats/chats_list.cljs index cdb6325989..6947c87742 100644 --- a/syng-im/src/syng_im/components/chats/chats_list.cljs +++ b/syng-im/src/syng_im/components/chats/chats_list.cljs @@ -13,7 +13,10 @@ [syng-im.resources :as res] [syng-im.utils.listview :refer [to-realm-datasource]] [reagent.core :as r] - [syng-im.components.chats.chat-list-item :refer [chat-list-item]])) + [syng-im.components.chats.chat-list-item :refer [chat-list-item]] + [syng-im.components.action-button :refer [action-button + action-button-item]] + [syng-im.components.icons.ionicons :refer [icon]])) (defn chats-list [{:keys [navigator]}] @@ -40,4 +43,21 @@ [list-view {:dataSource datasource :renderRow (fn [row section-id row-id] (r/as-element [chat-list-item row navigator])) - :style {:backgroundColor "white"}}]])))) + :style {:backgroundColor "white"}}] + [action-button {:buttonColor "rgba(231,76,60,1)"} + [action-button-item {:title "New Chat" + :buttonColor "#9b59b6" + :onPress (fn [] + (dispatch [:show-contacts navigator]))} + [icon {:name "android-create" + :style {:fontSize 20 + :height 22 + :color "white"}}]] + [action-button-item {:title "New Group Chat" + :buttonColor "#1abc9c" + :onPress (fn [] + (dispatch [:show-group-new navigator]))} + [icon {:name "person-stalker" + :style {:fontSize 20 + :height 22 + :color "white"}}]]]])))) diff --git a/syng-im/src/syng_im/components/chats/new_group.cljs b/syng-im/src/syng_im/components/chats/new_group.cljs new file mode 100644 index 0000000000..c402ebd799 --- /dev/null +++ b/syng-im/src/syng_im/components/chats/new_group.cljs @@ -0,0 +1,52 @@ +(ns syng-im.components.chats.new-group + (:require [re-frame.core :refer [subscribe dispatch dispatch-sync]] + [syng-im.resources :as res] + [syng-im.components.react :refer [view toolbar-android android? text-input]] + [syng-im.components.realm :refer [list-view]] + [syng-im.utils.listview :refer [to-realm-datasource]] + [syng-im.components.chats.new-group-contact :refer [new-group-contact]] + [reagent.core :as r] + [syng-im.navigation :refer [nav-pop]])) + +(defn new-group [{:keys [navigator]}] + (let [contacts (subscribe [:all-contacts]) + group-name (atom nil)] + (fn [] + (let [contacts-ds (to-realm-datasource @contacts)] + [view {:style {:flex 1 + :backgroundColor "white"}} + (when android? + ;; TODO add IOS version + [toolbar-android {:logo res/logo-icon + :title "New Group Chat" + :titleColor "#4A5258" + :style {:backgroundColor "white" + :height 56 + :elevation 2} + :actions [{:title "Create" + :icon res/v + :show "always"}] + :onActionSelected (fn [position] + (dispatch [:create-new-group @group-name navigator])) + :navIcon res/nav-back-icon + :onIconClicked (fn [] + (nav-pop navigator))}]) + [text-input {:underlineColorAndroid "#9CBFC0" + :style {:marginLeft 5 + :marginRight 5 + :fontSize 14 + :fontFamily "Avenir-Roman" + :color "#9CBFC0"} + :autoFocus true + :placeholder "Group Name" + :value @group-name + :onChangeText (fn [new-text] + (reset! group-name new-text) + (r/flush)) + :onSubmitEditing (fn [e] + ;(dispatch [:send-chat-msg @chat-id @text]) + (reset! group-name nil))}] + [list-view {:dataSource contacts-ds + :renderRow (fn [row section-id row-id] + (r/as-element [new-group-contact (js->clj row :keywordize-keys true) navigator])) + :style {:backgroundColor "white"}}]])))) diff --git a/syng-im/src/syng_im/components/chats/new_group_contact.cljs b/syng-im/src/syng_im/components/chats/new_group_contact.cljs new file mode 100644 index 0000000000..f0e7303763 --- /dev/null +++ b/syng-im/src/syng_im/components/chats/new_group_contact.cljs @@ -0,0 +1,24 @@ +(ns syng-im.components.chats.new-group-contact + (:require [syng-im.resources :as res] + [re-frame.core :refer [subscribe dispatch dispatch-sync]] + [syng-im.components.react :refer [view]] + [syng-im.components.contact-list.contact-inner :refer [contact-inner-view]] + [syng-im.components.item-checkbox :refer [item-checkbox]] + [syng-im.utils.logging :as log] + [reagent.core :as r])) + +(defn new-group-contact [{:keys [whisper-identity] :as contact} navigator] + (let [checked (r/atom false)] + (fn [] + [view {:style {:flexDirection "row" + :marginTop 5 + :marginBottom 5 + :paddingLeft 15 + :paddingRight 15 + :height 75}} + [item-checkbox {:onToggle (fn [checked?] + (reset! checked checked?) + (dispatch [:select-for-new-group whisper-identity checked?])) + :checked @checked + :size 30}] + [contact-inner-view contact]]))) diff --git a/syng-im/src/syng_im/components/contact_list/contact.cljs b/syng-im/src/syng_im/components/contact_list/contact.cljs index 7c5e4ddeda..c13f9fd9e6 100644 --- a/syng-im/src/syng_im/components/contact_list/contact.cljs +++ b/syng-im/src/syng_im/components/contact_list/contact.cljs @@ -1,103 +1,14 @@ (ns syng-im.components.contact-list.contact (:require [syng-im.components.react :refer [view text image touchable-highlight]] [syng-im.resources :as res] - [syng-im.navigation :as nav])) + [syng-im.navigation :as nav] + [syng-im.components.contact-list.contact-inner :refer [contact-inner-view]])) (defn show-chat [navigator whisper-identity] (nav/nav-push navigator {:view-id :chat})) (defn contact-view [{:keys [navigator contact]}] - (let [{:keys [name photo-path delivery-status datetime new-messages-count - online whisper-identity]} contact] + (let [{:keys [whisper-identity]} contact] [touchable-highlight {:onPress (fn [] (show-chat navigator whisper-identity))} - [view {:style {:flexDirection "row" - :marginTop 5 - :marginBottom 5 - :paddingLeft 15 - :paddingRight 15 - :height 75}} - [view {:width 54 - :height 54} - ;;; photo - [view {:width 54 - :height 54 - :borderRadius 50 - :backgroundColor "#FFFFFF" - :elevation 6} - [image {:source (if (< 0 (count photo-path)) - {:uri photo-path} - res/user-no-photo) - :style {:borderWidth 2 - :borderColor "#FFFFFF" - :borderRadius 50 - :width 54 - :height 54 - :position "absolute"}}]] - ;;; online - (when online - [view {:position "absolute" - :top 41 - :left 36 - :width 12 - :height 12 - :borderRadius 50 - :backgroundColor "#FFFFFF" - :elevation 6} - [image {:source res/online-icon - :style {:width 12 - :height 12}}]])] - [view {:style {:flexDirection "column" - :marginLeft 7 - :marginRight 10 - :flex 1 - :position "relative"}} - ;;; name - [text {:style {:fontSize 15 - :fontFamily "Avenir-Roman"}} name] - ;;; last message - [text {:style {:color "#AAB2B2" - :fontFamily "Avenir-Roman" - :fontSize 14 - :marginTop 2 - :paddingRight 10}} - (str "Hi, I'm " name)]] - [view {:style {:flexDirection "column"}} - ;;; delivery status - [view {:style {:flexDirection "row" - :position "absolute" - :top 0 - :right 0}} - (when delivery-status - [image {:source (if (= (keyword delivery-status) :seen) - res/seen-icon - res/delivered-icon) - :style {:marginTop 5}}]) - ;;; datetime - [text {:style {:fontFamily "Avenir-Roman" - :fontSize 11 - :color "#AAB2B2" - :letterSpacing 1 - :lineHeight 15 - :marginLeft 5}} - datetime]] - ;;; new messages count - (when (< 0 new-messages-count) - [view {:style {:position "absolute" - :right 0 - :bottom 24 - :width 18 - :height 18 - :backgroundColor "#6BC6C8" - :borderColor "#FFFFFF" - :borderRadius 50 - :alignSelf "flex-end"}} - [text {:style {:width 18 - :height 17 - :fontFamily "Avenir-Roman" - :fontSize 10 - :color "#FFFFFF" - :lineHeight 19 - :textAlign "center" - :top 1}} - new-messages-count]])]]])) + [contact-inner-view contact]])) diff --git a/syng-im/src/syng_im/components/contact_list/contact_inner.cljs b/syng-im/src/syng_im/components/contact_list/contact_inner.cljs new file mode 100644 index 0000000000..c047551c57 --- /dev/null +++ b/syng-im/src/syng_im/components/contact_list/contact_inner.cljs @@ -0,0 +1,104 @@ +(ns syng-im.components.contact-list.contact-inner + (:require [clojure.string :as s] + [syng-im.components.react :refer [view image text]] + [syng-im.resources :as res])) + +(defn contact-photo [{:keys [photo-path]}] + [view {:width 54 + :height 54 + :borderRadius 50 + :backgroundColor "#FFFFFF" + :elevation 6} + [image {:source (if (s/blank? photo-path) + res/user-no-photo + {:uri photo-path}) + :style {:borderWidth 2 + :borderColor "#FFFFFF" + :borderRadius 50 + :width 54 + :height 54 + :position "absolute"}}]]) + +(defn contact-online [{:keys [online]}] + (when online + [view {:position "absolute" + :top 41 + :left 36 + :width 12 + :height 12 + :borderRadius 50 + :backgroundColor "#FFFFFF" + :elevation 6} + [image {:source res/online-icon + :style {:width 12 + :height 12}}]])) + +(defn contact-inner-view [{:keys [name photo-path delivery-status datetime new-messages-count + online whisper-identity]}] + [view {:style {:flexDirection "row" + :marginTop 5 + :marginBottom 5 + :paddingLeft 15 + :paddingRight 15 + :height 75}} + [view {:width 54 + :height 54} + ;;; photo + [contact-photo {:photo-path photo-path}] + ;;; online + [contact-online {:online online}]] + [view {:style {:flexDirection "column" + :marginLeft 7 + :marginRight 10 + :flex 1 + :position "relative"}} + ;;; name + [text {:style {:fontSize 15 + :fontFamily "Avenir-Roman"}} name] + ;;; last message + [text {:style {:color "#AAB2B2" + :fontFamily "Avenir-Roman" + :fontSize 14 + :marginTop 2 + :paddingRight 10}} + (str "Hi, I'm " name)]] + [view {:style {:flexDirection "column"}} + ;;; delivery status + [view {:style {:flexDirection "row" + :position "absolute" + :top 0 + :right 0}} + (when delivery-status + [image {:source (if (= (keyword delivery-status) :seen) + res/seen-icon + res/delivered-icon) + :style {:marginTop 5}}]) + ;;; datetime + [text {:style {:fontFamily "Avenir-Roman" + :fontSize 11 + :color "#AAB2B2" + :letterSpacing 1 + :lineHeight 15 + :marginLeft 5}} + datetime]] + ;;; new messages count + (when (< 0 new-messages-count) + [view {:style {:position "absolute" + :right 0 + :bottom 24 + :width 18 + :height 18 + :backgroundColor "#6BC6C8" + :borderColor "#FFFFFF" + :borderRadius 50 + :alignSelf "flex-end"}} + [text {:style {:width 18 + :height 17 + :fontFamily "Avenir-Roman" + :fontSize 10 + :color "#FFFFFF" + :lineHeight 19 + :textAlign "center" + :top 1}} + new-messages-count]])]]) + diff --git a/syng-im/src/syng_im/components/contact_list/contact_list.cljs b/syng-im/src/syng_im/components/contact_list/contact_list.cljs index b01fb7773a..d2aeb9b321 100644 --- a/syng-im/src/syng_im/components/contact_list/contact_list.cljs +++ b/syng-im/src/syng_im/components/contact_list/contact_list.cljs @@ -26,7 +26,7 @@ [view {:style {:flex 1 :backgroundColor "white"}} [toolbar-android {:logo res/logo-icon - :title "Chats" + :title "Contacts" :titleColor "#4A5258" :style {:backgroundColor "white" :height 56 diff --git a/syng-im/src/syng_im/components/icons/ionicons.cljs b/syng-im/src/syng_im/components/icons/ionicons.cljs new file mode 100644 index 0000000000..2b76fe5233 --- /dev/null +++ b/syng-im/src/syng_im/components/icons/ionicons.cljs @@ -0,0 +1,6 @@ +(ns syng-im.components.icons.ionicons + (:require [reagent.core :as r])) + +(set! js/window.Ionicons (js/require "react-native-vector-icons/Ionicons")) + +(def icon (r/adapt-react-class js/Ionicons)) diff --git a/syng-im/src/syng_im/components/item_checkbox.cljs b/syng-im/src/syng_im/components/item_checkbox.cljs new file mode 100644 index 0000000000..3ddea93b7f --- /dev/null +++ b/syng-im/src/syng_im/components/item_checkbox.cljs @@ -0,0 +1,7 @@ +(ns syng-im.components.item-checkbox + (:require [reagent.core :as r])) + +(set! js/window.ItemCheckbox (js/require "react-native-circle-checkbox")) + +(def item-checkbox (r/adapt-react-class js/ItemCheckbox)) + diff --git a/syng-im/src/syng_im/db.cljs b/syng-im/src/syng_im/db.cljs index 90b768fe80..e265eb1386 100644 --- a/syng-im/src/syng_im/db.cljs +++ b/syng-im/src/syng_im/db.cljs @@ -12,7 +12,8 @@ :suggestions [] :command nil} :chats {} - :chats-updated-signal 0}) + :chats-updated-signal 0 + :new-group #{}}) (def protocol-initialized-path [:protocol-initialized]) @@ -23,3 +24,5 @@ (def updated-chats-signal-path [:chats-updated-signal]) (defn updated-chat-signal-path [chat-id] [:chats chat-id :chat-updated-signal]) +(def new-group-path [:new-group]) + diff --git a/syng-im/src/syng_im/handlers.cljs b/syng-im/src/syng_im/handlers.cljs index b83c8893ec..e93b3d2824 100644 --- a/syng-im/src/syng_im/handlers.cljs +++ b/syng-im/src/syng_im/handlers.cljs @@ -1,6 +1,6 @@ (ns syng-im.handlers (:require - [re-frame.core :refer [register-handler after]] + [re-frame.core :refer [register-handler after dispatch]] [schema.core :as s :include-macros true] [syng-im.db :refer [app-db schema]] [syng-im.protocol.api :refer [init-protocol]] @@ -20,11 +20,15 @@ [syng-im.models.chats :refer [create-chat]] [syng-im.models.chat :refer [signal-chat-updated - set-current-chat-id]] + set-current-chat-id + update-new-group-selection + clear-new-group + new-group-selection]] [syng-im.utils.logging :as log] [syng-im.protocol.api :as api] [syng-im.constants :refer [text-content-type]] - [syng-im.navigation :refer [nav-push]])) + [syng-im.navigation :refer [nav-push]] + [syng-im.utils.crypt :refer [gen-random-bytes]])) ;; -- Middleware ------------------------------------------------------------ ;; @@ -50,6 +54,33 @@ (fn [db [_ value]] (assoc db :loading value))) +(register-handler :initialize-crypt + (fn [db _] + (log/debug "initializing crypt") + (gen-random-bytes 1024 (fn [{:keys [error buffer]}] + (if error + (do + (log/error "Failed to generate random bytes to initialize sjcl crypto") + (dispatch [:notify-user {:type :error + :error error}])) + (do + (->> (.toString buffer "hex") + (.toBits (.. js/ecc -sjcl -codec -hex)) + (.addEntropy (.. js/ecc -sjcl -random))) + (dispatch [:crypt-initialized]))))) + db)) + +(register-handler :crypt-initialized + (fn [db _] + (log/debug "crypt initialized") + db)) + +(register-handler :navigate-to + (fn [db [action navigator route]] + (log/debug action route) + (nav-push navigator route) + db)) + ;; -- Protocol -------------------------------------------------------------- (register-handler :initialize-protocol @@ -69,9 +100,15 @@ (log/debug action "msg" msg) (save-message chat-id msg) (-> db - (create-chat chat-id [chat-id]) + (create-chat chat-id [chat-id] false) (signal-chat-updated chat-id)))) +(register-handler :group-received-msg + (fn [db [action {chat-id :group-id :as msg}]] + (log/debug action "msg" msg) + (save-message chat-id msg) + (signal-chat-updated db chat-id))) + (register-handler :acked-msg (fn [db [_ from msg-id]] (update-message! {:msg-id msg-id @@ -122,6 +159,21 @@ (save-message chat-id msg) (signal-chat-updated db chat-id)))) +(register-handler :send-group-chat-msg + (fn [db [action chat-id text]] + (log/debug action "chat-id" chat-id "text" text) + (let [{msg-id :msg-id + {from :from} :msg} (api/send-group-user-msg {:group-id chat-id + :content text}) + msg {:msg-id msg-id + :from from + :to nil + :content text + :content-type text-content-type + :outgoing true}] + (save-message chat-id msg) + (signal-chat-updated db chat-id)))) + ;; -- User data -------------------------------------------------------------- (register-handler :set-user-phone-number @@ -165,8 +217,9 @@ (register-handler :show-chat (fn [db [action chat-id navigator]] (log/debug action "chat-id" chat-id) - (nav-push navigator {:view-id :chat}) - (set-current-chat-id db chat-id))) + (let [db (set-current-chat-id db chat-id)] + (dispatch [:navigate-to navigator {:view-id :chat}]) + db))) (register-handler :set-sign-up-chat (fn [db [_]] @@ -183,3 +236,39 @@ (register-handler :set-input-command (fn [db [_ command]] (commands-service/set-input-command db command))) + +(register-handler :show-contacts + (fn [db [action navigator]] + (log/debug action) + (nav-push navigator {:view-id :contact-list}) + db)) + +(register-handler :show-group-new + (fn [db [action navigator]] + (log/debug action) + (nav-push navigator {:view-id :new-group}) + (clear-new-group db))) + +(register-handler :select-for-new-group + (fn [db [action identity add?]] + (log/debug action identity add?) + (update-new-group-selection db identity add?))) + +(register-handler :create-new-group + (fn [db [action group-name navigator]] + (log/debug action) + (let [identities (-> (new-group-selection db) + (vec)) + group-id (api/start-group-chat identities group-name) + db (create-chat db group-id identities true group-name)] + (dispatch [:show-chat group-id navigator]) + db))) + +(register-handler :group-chat-invite-received + (fn [db [action from group-id identities group-name]] + (log/debug action from group-id identities) + (create-chat db group-id identities true group-name))) + +(comment + + ) diff --git a/syng-im/src/syng_im/models/chat.cljs b/syng-im/src/syng_im/models/chat.cljs index dba7b41a27..7a8b29d4ce 100644 --- a/syng-im/src/syng_im/models/chat.cljs +++ b/syng-im/src/syng_im/models/chat.cljs @@ -17,8 +17,22 @@ (->> (db/updated-chat-signal-path chat-id) (get-in db))) +(defn update-new-group-selection [db identity add?] + (update-in db db/new-group-path (fn [new-group] + (if add? + (conj new-group identity) + (disj new-group identity))))) + +(defn new-group-selection [db] + (get-in db db/new-group-path)) + +(defn clear-new-group [db] + (assoc-in db db/new-group-path #{})) + (comment (swap! re-frame.db/app-db (fn [db] (signal-chat-updated db "0x0479a5ed1f38cadfad1db6cd56c4b659b0ebe052bbe9efa950f6660058519fa4ca6be2dda66afa80de96ab00eb97a2605d5267a1e8f4c2a166ab551f6826608cdd"))) + +(current-chat-id @re-frame.db/app-db) ) \ No newline at end of file diff --git a/syng-im/src/syng_im/models/chats.cljs b/syng-im/src/syng_im/models/chats.cljs index 8f801a4828..fa63a2d353 100644 --- a/syng-im/src/syng_im/models/chats.cljs +++ b/syng-im/src/syng_im/models/chats.cljs @@ -30,9 +30,9 @@ chat-id)) (defn create-chat - ([db chat-id identities] - (create-chat db chat-id identities nil)) - ([db chat-id identities chat-name] + ([db chat-id identities group-chat?] + (create-chat db chat-id identities group-chat? nil)) + ([db chat-id identities group-chat? chat-name] (if (r/exists? :chats :chat-id chat-id) db (let [chat-name (or chat-name @@ -40,8 +40,7 @@ _ (log/debug "creating chat" chat-name)] (r/write (fn [] - (let [group-chat? (> (count identities) 1) - contacts (mapv (fn [ident] + (let [contacts (mapv (fn [ident] {:identity ident}) identities)] (r/create :chats {:chat-id chat-id :name chat-name @@ -54,8 +53,12 @@ (-> (r/get-all :chats) (r/sorted :timestamp :desc))) +(defn chat-by-id [chat-id] + (-> (r/get-by-field :chats :chat-id chat-id) + (r/single-cljs))) (comment + (chat-by-id "1459693168208-31d4942e-ca3b-5c03-a397-cd7a29f777d4") (chats-list) (r/delete (chats-list)) @@ -65,4 +68,11 @@ (create-chat "0x0479a5ed1f38cadfad1db6cd56c4b659b0ebe052bbe9efa950f6660058519fa4ca6be2dda66afa80de96ab00eb97a2605d5267a1e8f4c2a166ab551f6826608cdd" ["0x0479a5ed1f38cadfad1db6cd56c4b659b0ebe052bbe9efa950f6660058519fa4ca6be2dda66afa80de96ab00eb97a2605d5267a1e8f4c2a166ab551f6826608cdd"]) + (+ 1 1) + + + + (swap! re-frame.db/app-db (fn [db] + (create-chat db "A group chat"))) + ) \ No newline at end of file diff --git a/syng-im/src/syng_im/models/contacts.cljs b/syng-im/src/syng_im/models/contacts.cljs index f96fccec28..0250eb9183 100644 --- a/syng-im/src/syng_im/models/contacts.cljs +++ b/syng-im/src/syng_im/models/contacts.cljs @@ -2,7 +2,8 @@ (:require [cljs.core.async :as async :refer [chan put! !]] [re-frame.core :refer [subscribe dispatch dispatch-sync]] [syng-im.utils.utils :refer [log toast]] - [syng-im.persistence.realm :as realm])) + [syng-im.persistence.realm :as realm] + [syng-im.persistence.realm :as r])) ;; TODO see https://github.com/rt2zz/react-native-contacts/issues/45 (def fake-phone-contacts? true) @@ -11,13 +12,13 @@ (def react-native-contacts (js/require "react-native-contacts")) (defn- generate-contact [n] - {:name (str "Contact " n) - :photo-path "" - :phone-numbers [{:label "mobile" :number (apply str (repeat 7 n))}] - :delivery-status (if (< (rand) 0.5) :delivered :seen) - :datetime "15:30" + {:name (str "Contact " n) + :photo-path "" + :phone-numbers [{:label "mobile" :number (apply str (repeat 7 n))}] + :delivery-status (if (< (rand) 0.5) :delivered :seen) + :datetime "15:30" :new-messages-count (rand-int 3) - :online (< (rand) 0.5)}) + :online (< (rand) 0.5)}) (defn- generate-contacts [n] (map generate-contact (range 1 (inc n)))) @@ -31,41 +32,41 @@ (put! ch {:error error :contacts - (when (not error) - (log raw-contacts) - (map (fn [contact] - (merge contact - (generate-contact 1) - {:name (:givenName contact) - :photo-path (:thumbnailPath contact) - :phone-numbers (:phoneNumbers contact)})) - (js->clj raw-contacts :keywordize-keys true)))})))) + (when (not error) + (log raw-contacts) + (map (fn [contact] + (merge contact + (generate-contact 1) + {:name (:givenName contact) + :photo-path (:thumbnailPath contact) + :phone-numbers (:phoneNumbers contact)})) + (js->clj raw-contacts :keywordize-keys true)))})))) ch)) (defn- get-contacts [] (if fake-contacts? - [{:phone-number "123" + [{:phone-number "123" :whisper-identity "abc" - :name "fake" - :photo-path ""}] + :name "fake" + :photo-path ""}] (realm/get-list :contacts))) (defn load-syng-contacts [db] (let [contacts (map (fn [contact] (merge contact - {:delivery-status (if (< (rand) 0.5) :delivered :seen) - :datetime "15:30" + {:delivery-status (if (< (rand) 0.5) :delivered :seen) + :datetime "15:30" :new-messages-count (rand-int 3) - :online (< (rand) 0.5)})) + :online (< (rand) 0.5)})) (get-contacts))] (assoc db :contacts contacts))) (defn- create-contact [{:keys [phone-number whisper-identity name photo-path]}] (realm/create :contacts - {:phone-number phone-number + {:phone-number phone-number :whisper-identity whisper-identity - :name (or name "") - :photo-path (or photo-path "")})) + :name (or name "") + :photo-path (or photo-path "")})) (defn- contact-exist? [contacts contact] (some #(= (:phone-number contact) (:phone-number %)) contacts)) @@ -82,3 +83,28 @@ (defn save-syng-contacts [syng-contacts] (add-contacts syng-contacts)) + + +;;;;;;;;;;;;;;;;;;;;---------------------------------------------- + +(defn contacts-list [] + (-> (r/get-all :contacts) + (r/sorted :name :asc))) + +(comment + + (r/write #(create-contact {:phone-number "0543072333" + :whisper-identity "0x04b6552945c18ebca487c8a829365d3812a246e1cd00d775f47248a21a61bad0912409b8bd18dc0604d1df494cea001cce85098906df231d2a431067734ecc5a21" + :name "Mr. Bean" + :photo-path ""})) + + (r/write #(create-contact {:phone-number "0544828649" + :whisper-identity "0x043d9e25c6cf89941849cf5e4439084a93002f757cfd49fef411d4793d888b408dfa5bc54ac5989f65da8d764dc332f06b646f3cfae194a0801f6090b272a0c56e" + :name "Mr. Batman" + :photo-path ""})) + + (contacts-list) + + (:new-group @re-frame.db/app-db) + + ) \ No newline at end of file diff --git a/syng-im/src/syng_im/models/messages.cljs b/syng-im/src/syng_im/models/messages.cljs index 36257e47c8..da53dad990 100644 --- a/syng-im/src/syng_im/models/messages.cljs +++ b/syng-im/src/syng_im/models/messages.cljs @@ -5,7 +5,8 @@ [syng-im.db :as db] [syng-im.utils.logging :as log])) -(defn save-message [chat-id {:keys [from to msg-id content content-type outgoing] :or {outgoing false} :as msg}] +(defn save-message [chat-id {:keys [from to msg-id content content-type outgoing] :or {outgoing false + to nil} :as msg}] (when-not (r/exists? :msgs :msg-id msg-id) (r/write (fn [] diff --git a/syng-im/src/syng_im/persistence/realm.cljs b/syng-im/src/syng_im/persistence/realm.cljs index 103e34eb91..819c2839d9 100644 --- a/syng-im/src/syng_im/persistence/realm.cljs +++ b/syng-im/src/syng_im/persistence/realm.cljs @@ -23,7 +23,8 @@ :primaryKey :msg-id :properties {:msg-id "string" :from "string" - :to "string" + :to {:type "string" + :optional true} :content "string" ;; TODO make it ArrayBuffer :content-type "string" :timestamp "int" @@ -119,8 +120,22 @@ (comment - (write #(.create realm "msgs" (clj->js {:msg-id "1459175391577-a2185a35-5c49-5a6b-9c08-6eb5b87ceb7f" + (write #(.create realm "msgs" (clj->js {:msg-id "12" :content "sdfd" + :from "sdfsd" + :chat-id "56" + :content-type "fg" + :timestamp 2 + :outgoing true + :to "sfs" :delivery-status "seen"}) true)) + (.addListener realm "change" (fn [& args] + (log/debug args))) + + ;realm.addListener('change', () => { + ; // Update UI + ; ... + ; }); + ) \ No newline at end of file diff --git a/syng-im/src/syng_im/protocol/protocol_handler.cljs b/syng-im/src/syng_im/protocol/protocol_handler.cljs index 69e889a717..9b1ab11206 100644 --- a/syng-im/src/syng_im/protocol/protocol_handler.cljs +++ b/syng-im/src/syng_im/protocol/protocol_handler.cljs @@ -21,15 +21,15 @@ (dispatch [:acked-msg from msg-id])) :delivery-failed (let [{:keys [msg-id]} event] (dispatch [:msg-delivery-failed msg-id])) - ;:new-group-chat (let [{:keys [from group-id identities]} event] - ; (set-group-id! group-id) - ; (set-group-identities identities) - ; (add-to-chat "group-chat" ":" (str "Received group chat invitation from " from " for group-id: " group-id))) + :new-group-chat (let [{:keys [from group-id identities group-name]} event] + (dispatch [:group-chat-invite-received from group-id identities group-name])) + :new-group-msg (let [{from :from + group-id :group-id + payload :payload} event] + (dispatch [:group-received-msg (assoc payload :from from + :group-id group-id)])) ;:group-chat-invite-acked (let [{:keys [from group-id]} event] ; (add-to-chat "group-chat" ":" (str "Received ACK for group chat invitation from " from " for group-id: " group-id))) - ;:new-group-msg (let [{from :from - ; {content :content} :payload} event] - ; (add-to-chat "group-chat" from content)) ;:group-new-participant (let [{:keys [group-id identity from]} event] ; (add-to-chat "group-chat" ":" (str (shorten from) " added " (shorten identity) " to group chat")) ; (add-identity-to-group-list identity)) diff --git a/syng-im/src/syng_im/resources.cljs b/syng-im/src/syng_im/resources.cljs index e66eb96449..52a956d3f6 100644 --- a/syng-im/src/syng_im/resources.cljs +++ b/syng-im/src/syng_im/resources.cljs @@ -12,3 +12,4 @@ (def mic (js/require "./images/mic.png")) (def smile (js/require "./images/smile.png")) (def att (js/require "./images/att.png")) +(def v (js/require "./images/v.png")) diff --git a/syng-im/src/syng_im/subs.cljs b/syng-im/src/syng_im/subs.cljs index 0d548c485b..c058af7d7d 100644 --- a/syng-im/src/syng_im/subs.cljs +++ b/syng-im/src/syng_im/subs.cljs @@ -5,8 +5,10 @@ [syng-im.models.chat :refer [current-chat-id chat-updated?]] [syng-im.models.chats :refer [chats-list - chats-updated?]] - [syng-im.models.messages :refer [get-messages]])) + chats-updated? + chat-by-id]] + [syng-im.models.messages :refer [get-messages]] + [syng-im.models.contacts :refer [contacts-list]])) ;; -- Chat -------------------------------------------------------------- @@ -43,6 +45,14 @@ (let [_ @chats-updated] (chats-list)))))) +(register-sub :get-current-chat + (fn [db _] + (let [current-chat-id (-> (current-chat-id @db) + (reaction))] + (-> (when-let [chat-id @current-chat-id] + (chat-by-id chat-id)) + (reaction))))) + ;; -- User data -------------------------------------------------------------- (register-sub @@ -74,3 +84,9 @@ (fn [db _] (reaction (get @db :contacts)))) + +(register-sub :all-contacts + (fn [db _] + (reaction + (contacts-list)))) + diff --git a/syng-im/src/syng_im/utils/crypt.cljs b/syng-im/src/syng_im/utils/crypt.cljs index cb80de1a8d..ecf3ef7ff7 100644 --- a/syng-im/src/syng_im/utils/crypt.cljs +++ b/syng-im/src/syng_im/utils/crypt.cljs @@ -2,6 +2,8 @@ (:require [goog.crypt :refer [byteArrayToHex]]) (:import goog.crypt.Sha256)) +(set! js/window.RnRandomBytes (js/require "react-native-randombytes")) + (def sha-256 (Sha256.)) (defn bytes-to-str [arr] @@ -15,3 +17,9 @@ (.update sha-256 s) (-> (.digest sha-256) byteArrayToHex)) + +(defn gen-random-bytes [length cb] + (.randomBytes js/window.RnRandomBytes length (fn [& [err buf]] + (if err + (cb {:error err}) + (cb {:buffer buf}))))) diff --git a/syng-im/src/syng_im/utils/listview.cljs b/syng-im/src/syng_im/utils/listview.cljs index b6bd9ec080..c511773a3a 100644 --- a/syng-im/src/syng_im/utils/listview.cljs +++ b/syng-im/src/syng_im/utils/listview.cljs @@ -2,12 +2,12 @@ (:require-macros [natal-shell.data-source :refer [data-source clone-with-rows]]) (:require [syng-im.components.realm])) -(defn to-datasource [msgs] +(defn to-datasource [items] (-> (data-source {:rowHasChanged (fn [row1 row2] (not= row1 row2))}) - (clone-with-rows msgs))) + (clone-with-rows items))) -(defn to-realm-datasource [msgs] +(defn to-realm-datasource [items] (-> (js/RealmReactNative.ListView.DataSource. (cljs.core/clj->js {:rowHasChanged (fn [row1 row2] (not= row1 row2))})) - (clone-with-rows msgs))) \ No newline at end of file + (clone-with-rows items))) \ No newline at end of file