imessage fix (#6)

* first draft : static views wip

* refactor to ChatMessage and ChatMessageHeader

* add pedantic

* fix lints

* remove hardcoded message

* appBar title : iMessage

* format date

* cupertino style and model view

* fix display of message based on isReceived or sent

* SendMessageInput

* refactor to MessagesPage

* MissingPluginException

* use builtins instead of custom stream builders

* handle isReceived

* delete channel header

* fix layout issues in ChannelPreview

* fix formatDate

* sticky message input

* usage of builtin MessageListCore

* remove unused imports and a todo

* rename channelsStates to channels

* replace file imports /w package:imessage/filename

* remove size required ChannelNameText

* lint and format

* sendMessage

* transition animation

* stream_chat_flutter_core instead

* format Date differently if same week

* add padding to bubble

* remove iMessage text from header

* reverse message order

* if same day don't display date

* padding chat bubble right

* remove unused extension

* constraint message width

* group messages By dates

* unused import

* fix bug input + layout+ preview onTap

* change updatedAt to createdAt

* add filter on channel

* handle refresh

* handle pagination with core LazyLoadScrollView

* preview simple medias

* upload bug

* fix attachment

* visual changes to message input

* remove size

* clean up

* wait 5 sec before displaying image(hack)

* fix a couple of things

* fix padding in channel preview

* fix upload + debugShowCheckedModeBanner false

* fix overflow and refactor to Divider

* fix android build

* add imessage clone hero image

* update README

Co-authored-by: Sacha Arbonel <sacha.arbonel@hotmail.fr>
This commit is contained in:
Salvatore Giordano
2021-02-26 18:06:54 +01:00
committed by GitHub
parent 6feccd57dd
commit f861eb4584
21 changed files with 344 additions and 279 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

+46 -9
View File
@@ -1,16 +1,53 @@
# imessage # iMessage Clone
A new Flutter project. ![](https://raw.githubusercontent.com/GetStream/flutter-samples/master/images/imessage_clone_hero_v1.png)
iMessage Clone is a sample app implemented using Stream Chat and Flutter. It is a fully fledged messaging app built using core packages.
## Getting Started ## Getting Started
This project is a starting point for a Flutter application. Before running this project please ensure Flutter is installed and configured on your machine. If you're new to Flutter, please checkout the [official guide](https://flutter.dev/docs/get-started/install) with installation instructions for your OS.
A few resources to get you started if this is your first Flutter project:
- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
For help getting started with Flutter, view our This project is only configured to support the following platforms:
[online documentation](https://flutter.dev/docs), which offers tutorials,
samples, guidance on mobile development, and a full API reference. - Android
- iOS
Web and Desktop are not supported at this time.
After installing Flutter and the necessary toolchain for your device (Android or iOS), connect your device or open your emulator before running the following:
**Clone the repo**
```bash
git clone https://github.com/GetStream/flutter-samples
```
**Open the app folder**
```bash
cd flutter-samples/imessage
```
**Install package dependencies:**
```bash
flutter packages get
```
**Open or create an emulator**
```bash
# To run an emulator, run 'flutter emulators --launch <emulator id>'.
# To create a new emulator, run 'flutter emulators --create [--name xyz]'.
# You can find more information on managing emulators at the links below:
# [https://developer.android.com/studio/run/managing-avds](https://developer.android.com/studio/run/managing-avds)[https://developer.android.com/studio/command-line/avdmanager](https://developer.android.com/studio/command-line/avdmanager)
```
**Run the project on your device or emulator:**
```bash
flutter run
```
+1 -1
View File
@@ -35,7 +35,7 @@ android {
defaultConfig { defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.example.imessage" applicationId "com.example.imessage"
minSdkVersion 16 minSdkVersion 21
targetSdkVersion 30 targetSdkVersion 30
versionCode flutterVersionCode.toInteger() versionCode flutterVersionCode.toInteger()
versionName flutterVersionName versionName flutterVersionName
+1
View File
@@ -1,3 +1,4 @@
org.gradle.jvmargs=-Xmx1536M org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true android.useAndroidX=true
android.enableJetifier=true android.enableJetifier=true
android.enableR8=true
+2 -2
View File
@@ -3,7 +3,7 @@
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>en</string> <string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>App</string> <string>App</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
@@ -21,6 +21,6 @@
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1.0</string> <string>1.0</string>
<key>MinimumOSVersion</key> <key>MinimumOSVersion</key>
<string>8.0</string> <string>10.0</string>
</dict> </dict>
</plist> </plist>
-1
View File
@@ -1,3 +1,2 @@
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig" #include "Generated.xcconfig"
-1
View File
@@ -1,3 +1,2 @@
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig" #include "Generated.xcconfig"
+58 -75
View File
@@ -9,11 +9,11 @@
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
54127ED34F2B67975767881F /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F124A271054C4FEB7BA298EA /* Pods_Runner.framework */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
AD80798B75BEF39A28B8324C /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0EA12FA64E96796BC730E03 /* Pods_Runner.framework */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */ /* Begin PBXCopyFilesBuildPhase section */
@@ -30,14 +30,15 @@
/* End PBXCopyFilesBuildPhase section */ /* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
10AA3A20A8E8F51016843518 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
1DFBF673D502906C56E28E7F /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; }; 212173E324AE0FED45F2866A /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7851D9CF8A0104A48AF22BF4 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
87BC4F0CB1D55BC3C77185AD /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -45,8 +46,7 @@
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
F124A271054C4FEB7BA298EA /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D0EA12FA64E96796BC730E03 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
F6E360FB0F19A8EE63C4281A /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@@ -54,27 +54,27 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
54127ED34F2B67975767881F /* Pods_Runner.framework in Frameworks */, AD80798B75BEF39A28B8324C /* Pods_Runner.framework in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
/* End PBXFrameworksBuildPhase section */ /* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */ /* Begin PBXGroup section */
053DC9E602F5F5F21DC144A5 /* Frameworks */ = { 3F98BA59D9BB09C5816FF126 /* Frameworks */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
F124A271054C4FEB7BA298EA /* Pods_Runner.framework */, D0EA12FA64E96796BC730E03 /* Pods_Runner.framework */,
); );
name = Frameworks; name = Frameworks;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
15FB9768D11A361EAB687B81 /* Pods */ = { 7231B8C27F5ACE1DDE056446 /* Pods */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
1DFBF673D502906C56E28E7F /* Pods-Runner.debug.xcconfig */, 87BC4F0CB1D55BC3C77185AD /* Pods-Runner.debug.xcconfig */,
7851D9CF8A0104A48AF22BF4 /* Pods-Runner.release.xcconfig */, 10AA3A20A8E8F51016843518 /* Pods-Runner.release.xcconfig */,
F6E360FB0F19A8EE63C4281A /* Pods-Runner.profile.xcconfig */, 212173E324AE0FED45F2866A /* Pods-Runner.profile.xcconfig */,
); );
name = Pods; name = Pods;
path = Pods; path = Pods;
@@ -97,8 +97,8 @@
9740EEB11CF90186004384FC /* Flutter */, 9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */, 97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */, 97C146EF1CF9000F007C117D /* Products */,
15FB9768D11A361EAB687B81 /* Pods */, 7231B8C27F5ACE1DDE056446 /* Pods */,
053DC9E602F5F5F21DC144A5 /* Frameworks */, 3F98BA59D9BB09C5816FF126 /* Frameworks */,
); );
sourceTree = "<group>"; sourceTree = "<group>";
}; };
@@ -132,14 +132,14 @@
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = ( buildPhases = (
F8BE585E4B71465AB994DDE3 /* [CP] Check Pods Manifest.lock */, CAA82304056351F698F2FE92 /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */, 9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */, 97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */, 97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */, 97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */, 9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
FF3AE7DF11C51CD94F69B7CD /* [CP] Embed Pods Frameworks */, 5C9569EFDB9DD32B2BAFBEBB /* [CP] Embed Pods Frameworks */,
); );
buildRules = ( buildRules = (
); );
@@ -212,6 +212,23 @@
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
}; };
5C9569EFDB9DD32B2BAFBEBB /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
9740EEB61CF901F6004384FC /* Run Script */ = { 9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
@@ -226,7 +243,7 @@
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
}; };
F8BE585E4B71465AB994DDE3 /* [CP] Check Pods Manifest.lock */ = { CAA82304056351F698F2FE92 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
@@ -248,64 +265,6 @@
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0; showEnvVarsInLog = 0;
}; };
FF3AE7DF11C51CD94F69B7CD /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/DKImagePickerController/DKImagePickerController.framework",
"${BUILT_PRODUCTS_DIR}/DKPhotoGallery/DKPhotoGallery.framework",
"${BUILT_PRODUCTS_DIR}/FMDB/FMDB.framework",
"${PODS_ROOT}/../Flutter/Flutter.framework",
"${BUILT_PRODUCTS_DIR}/SDWebImage/SDWebImage.framework",
"${BUILT_PRODUCTS_DIR}/SwiftyGif/SwiftyGif.framework",
"${BUILT_PRODUCTS_DIR}/esys_flutter_share/esys_flutter_share.framework",
"${BUILT_PRODUCTS_DIR}/file_picker/file_picker.framework",
"${BUILT_PRODUCTS_DIR}/flutter_app_badger/flutter_app_badger.framework",
"${BUILT_PRODUCTS_DIR}/flutter_keyboard_visibility/flutter_keyboard_visibility.framework",
"${BUILT_PRODUCTS_DIR}/image_gallery_saver/image_gallery_saver.framework",
"${BUILT_PRODUCTS_DIR}/image_picker/image_picker.framework",
"${BUILT_PRODUCTS_DIR}/libwebp/libwebp.framework",
"${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework",
"${BUILT_PRODUCTS_DIR}/photo_manager/photo_manager.framework",
"${BUILT_PRODUCTS_DIR}/sqflite/sqflite.framework",
"${BUILT_PRODUCTS_DIR}/url_launcher/url_launcher.framework",
"${BUILT_PRODUCTS_DIR}/video_compress/video_compress.framework",
"${BUILT_PRODUCTS_DIR}/video_player/video_player.framework",
"${BUILT_PRODUCTS_DIR}/video_thumbnail/video_thumbnail.framework",
"${BUILT_PRODUCTS_DIR}/wakelock/wakelock.framework",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DKImagePickerController.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DKPhotoGallery.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FMDB.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImage.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftyGif.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/esys_flutter_share.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/file_picker.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_app_badger.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_keyboard_visibility.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/image_gallery_saver.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/image_picker.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libwebp.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/photo_manager.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqflite.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_compress.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_player.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_thumbnail.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/wakelock.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */ /* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */
@@ -398,8 +357,16 @@
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.imessage; PRODUCT_BUNDLE_IDENTIFIER = com.example.imessage;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -522,8 +489,16 @@
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.imessage; PRODUCT_BUNDLE_IDENTIFIER = com.example.imessage;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -541,8 +516,16 @@
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.imessage; PRODUCT_BUNDLE_IDENTIFIER = com.example.imessage;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>
+32 -29
View File
@@ -13,35 +13,38 @@ class ChannelListView extends StatelessWidget {
channels.removeWhere((channel) => channel.lastMessageAt == null); channels.removeWhere((channel) => channel.lastMessageAt == null);
return SliverList( return SliverList(
delegate: SliverChildBuilderDelegate( delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) { (
//TODO: separators BuildContext context,
return Column( int index,
children: [ ) {
ChannelPreview( return Padding(
channel: channels[index], padding: const EdgeInsets.symmetric(vertical: 4.0),
onTap: () { child: ChannelPreview(
Navigator.push( channel: channels[index],
context, onTap: () {
PageRouteBuilder( Navigator.push(
pageBuilder: (_, __, ___) => StreamChannel( context,
channel: channels[index], PageRouteBuilder(
child: MessagePage(), pageBuilder: (_, __, ___) => StreamChannel(
), channel: channels[index],
transitionsBuilder: ( child: MessagePage(),
_, ),
animation, transitionsBuilder: (
secondaryAnimation, _,
child, animation,
) => secondaryAnimation,
SharedAxisTransition( child,
child: child, ) =>
animation: animation, SharedAxisTransition(
secondaryAnimation: secondaryAnimation, child: child,
transitionType: SharedAxisTransitionType.horizontal, animation: animation,
), secondaryAnimation: secondaryAnimation,
)); transitionType: SharedAxisTransitionType.horizontal,
}) ),
], ),
);
},
),
); );
}, },
childCount: channels.length, childCount: channels.length,
+10 -6
View File
@@ -2,8 +2,11 @@ import 'package:flutter/cupertino.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart' show Channel; import 'package:stream_chat_flutter/stream_chat_flutter.dart' show Channel;
class ChannelNameText extends StatelessWidget { class ChannelNameText extends StatelessWidget {
const ChannelNameText({Key key, @required this.channel, this.size = 12}) const ChannelNameText({
: super(key: key); Key key,
@required this.channel,
this.size = 17,
}) : super(key: key);
final Channel channel; final Channel channel;
final double size; final double size;
@@ -11,11 +14,12 @@ class ChannelNameText extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Text( return Text(
channel.extraData['name'] as String ?? channel.config.name, channel.extraData['name'] as String ?? 'No name',
style: TextStyle( style: TextStyle(
fontSize: size, fontSize: size,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: CupertinoColors.black), color: CupertinoColors.black,
),
); );
} }
} }
+69 -47
View File
@@ -9,6 +9,7 @@ import 'utils.dart';
class ChannelPreview extends StatelessWidget { class ChannelPreview extends StatelessWidget {
final VoidCallback onTap; final VoidCallback onTap;
final Channel channel; final Channel channel;
const ChannelPreview({ const ChannelPreview({
Key key, Key key,
@required this.onTap, @required this.onTap,
@@ -24,9 +25,9 @@ class ChannelPreview extends StatelessWidget {
? lastMessage?.attachments //TODO: ugly ? lastMessage?.attachments //TODO: ugly
?.map((e) { ?.map((e) {
if (e.type == 'image') { if (e.type == 'image') {
return '📷'; return '📷 ';
} else if (e.type == 'video') { } else if (e.type == 'video') {
return '🎬'; return '🎬 ';
} }
return null; return null;
}) })
@@ -35,57 +36,78 @@ class ChannelPreview extends StatelessWidget {
: ''; : '';
return GestureDetector( return GestureDetector(
onTap: onTap, onTap: onTap,
child: Padding( behavior: HitTestBehavior.opaque,
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 8.0), child: Container(
child: Container( constraints: BoxConstraints.tightFor(
decoration: BoxDecoration( height: 90,
borderRadius: BorderRadius.circular(5), ),
color: CupertinoColors.white), child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 8.0,
),
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
ChannelImage(channel: channel, size: 50), Padding(
padding:
const EdgeInsets.symmetric(vertical: 16.0, horizontal: 8.0),
child: ChannelImage(
channel: channel,
size: 50,
),
),
Expanded( Expanded(
child: Padding( child: Column(
padding: const EdgeInsets.all(8.0), mainAxisAlignment: MainAxisAlignment.start,
child: Column( crossAxisAlignment: CrossAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, children: [
children: [ Row(
Row( mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Padding( Padding(
padding: padding: const EdgeInsets.symmetric(horizontal: 8.0),
const EdgeInsets.symmetric(horizontal: 8.0), child: ChannelNameText(
child: ChannelNameText( channel: channel,
channel: channel,
),
), ),
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 8.0),
child: Text(
isSameWeek(channel.lastMessageAt)
? formatDateSameWeek(channel.lastMessageAt)
: formatDate(channel.lastMessageAt),
style: TextStyle(
fontWeight: FontWeight.bold,
color: CupertinoColors.systemGrey),
),
)
],
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'$prefix ${lastMessage?.text ?? ''}',
style: TextStyle(
fontWeight: FontWeight.normal,
color: CupertinoColors.systemGrey),
overflow: TextOverflow.ellipsis,
), ),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Row(
children: [
Text(
isSameWeek(channel.lastMessageAt)
? formatDateSameWeek(channel.lastMessageAt)
: formatDate(channel.lastMessageAt),
style: TextStyle(
fontSize: 15,
color: CupertinoColors.systemGrey,
),
),
Icon(
CupertinoIcons.right_chevron,
color: CupertinoColors.systemGrey3,
),
],
),
)
],
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'$prefix${lastMessage?.text ?? ''}',
style: TextStyle(
fontWeight: FontWeight.normal,
color: CupertinoColors.systemGrey,
fontSize: 16,
),
maxLines: 2,
overflow: TextOverflow.ellipsis,
), ),
], ),
), Divider(),
],
), ),
) )
], ],
+22 -21
View File
@@ -43,6 +43,7 @@ class IMessage extends StatelessWidget {
initializeDateFormatting('en_US', null); initializeDateFormatting('en_US', null);
return CupertinoApp( return CupertinoApp(
title: 'Flutter Demo', title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: CupertinoThemeData(brightness: Brightness.light), theme: CupertinoThemeData(brightness: Brightness.light),
home: StreamChatCore(client: client, child: ChatLoader()), home: StreamChatCore(client: client, child: ChatLoader()),
); );
@@ -50,31 +51,26 @@ class IMessage extends StatelessWidget {
} }
class ChatLoader extends StatelessWidget { class ChatLoader extends StatelessWidget {
const ChatLoader({ ChatLoader({
Key key, Key key,
}) : super(key: key); }) : super(key: key);
final channelListController = ChannelListController();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final user = StreamChatCore.of(context).user; final user = StreamChatCore.of(context).user;
var channelListController = ChannelListController();
return CupertinoPageScaffold( return CupertinoPageScaffold(
child: ChannelsBloc( child: ChannelsBloc(
child: ChannelListCore( child: ChannelListCore(
channelListController: channelListController, channelListController: channelListController,
filter: { filter: {
r'$and': [ 'members': {
{ r'$in': [user.id],
'members': { },
r'$in': [user.id], 'type': {
} r'$eq': 'messaging',
}, },
{
'type': {
r'$eq': 'messaging',
}
}
]
}, },
sort: [SortOption('last_message_at')], sort: [SortOption('last_message_at')],
pagination: PaginationParams( pagination: PaginationParams(
@@ -108,13 +104,18 @@ class ChatLoader extends StatelessWidget {
onEndOfPage: () async { onEndOfPage: () async {
channelListController.paginateData(); channelListController.paginateData();
}, },
child: CustomScrollView(slivers: [ child: CustomScrollView(
CupertinoSliverRefreshControl(onRefresh: () async { slivers: [
channelListController.loadData(); CupertinoSliverRefreshControl(onRefresh: () async {
}), channelListController.loadData();
ChannelPageAppBar(), }),
ChannelListView(channels: channels) ChannelPageAppBar(),
]), SliverPadding(
sliver: ChannelListView(channels: channels),
padding: const EdgeInsets.only(top: 16),
)
],
),
)))); ))));
} }
} }
+4 -2
View File
@@ -9,8 +9,10 @@ class MessageHeader extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final receivedAt = DateTime.parse(rawTimeStamp); final receivedAt = DateTime.parse(rawTimeStamp);
var textStyle = TextStyle( final textStyle = TextStyle(
fontWeight: FontWeight.bold, color: CupertinoColors.systemGrey); color: CupertinoColors.systemGrey,
fontSize: 14,
);
return isSameWeek(receivedAt) return isSameWeek(receivedAt)
? Text( ? Text(
formatDateSameWeek(receivedAt), formatDateSameWeek(receivedAt),
+42 -38
View File
@@ -12,48 +12,52 @@ class MessageListView extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final entries = groupBy(messages.reversed, final entries = groupBy(messages,
(Message message) => message.createdAt.toString().substring(0, 10)) (Message message) => message.createdAt.toString().substring(0, 10))
.entries .entries
.toList(); .toList();
return Stack( return Column(
children: [ children: [
SizedBox( Expanded(
height: MediaQuery.of(context).size.height * 0.9, child: SizedBox(
child: Align( height: MediaQuery.of(context).size.height * 0.9,
alignment: FractionalOffset.topCenter, child: Align(
child: ListView.builder( alignment: FractionalOffset.topCenter,
shrinkWrap: true, child: ListView.builder(
itemCount: entries.length, reverse: true,
itemBuilder: (context, index) { itemCount: entries.length,
itemBuilder: (context, index) {
return Column( return Column(
children: [ children: [
Padding( Padding(
padding: padding:
const EdgeInsets.fromLTRB(8.0, 24.0, 8.0, 8.0), const EdgeInsets.fromLTRB(8.0, 24.0, 8.0, 8.0),
child: MessageHeader( child: MessageHeader(
rawTimeStamp: entries[index].key), //date rawTimeStamp: entries[index].key), //date
), ),
...entries[index].value //messages ...entries[index]
.map((message) { .value //messages
return MessageWidget( .map((message) {
alignment: isReceived(message, context) return MessageWidget(
? Alignment.centerLeft alignment: isReceived(message, context)
: Alignment.topRight, ? Alignment.centerLeft
color: isReceived(message, context) : Alignment.topRight,
? CupertinoColors.systemGrey5 color: isReceived(message, context)
: CupertinoColors.systemBlue, ? CupertinoColors.systemGrey5
messageColor: isReceived(message, context) : CupertinoColors.systemBlue,
? CupertinoColors.black messageColor: isReceived(message, context)
: CupertinoColors.white, ? CupertinoColors.black
message: message, : CupertinoColors.white,
); message: message,
}).toList() );
], })
); .toList()
}), .reversed,
)), ],
);
}),
)),
),
MessageInput() MessageInput()
], ],
); );
+8 -2
View File
@@ -21,8 +21,14 @@ class MessagePage extends StatelessWidget {
navigationBar: CupertinoNavigationBar( navigationBar: CupertinoNavigationBar(
middle: Column( middle: Column(
children: [ children: [
ChannelImage(size: 25, channel: streamChannel.channel), ChannelImage(
ChannelNameText(channel: streamChannel.channel) size: 25,
channel: streamChannel.channel,
),
ChannelNameText(
size: 16,
channel: streamChannel.channel,
),
], ],
), ),
), //ChannelHeader ), //ChannelHeader
+14 -17
View File
@@ -1,7 +1,8 @@
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:imessage/cutom_painter.dart'; import 'package:imessage/cutom_painter.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart' show Message, AttachmentUploadStateBuilder; import 'package:stream_chat_flutter/stream_chat_flutter.dart'
show Message, AttachmentUploadStateBuilder;
class MessageWidget extends StatelessWidget { class MessageWidget extends StatelessWidget {
final Alignment alignment; final Alignment alignment;
@@ -19,7 +20,7 @@ class MessageWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (message.attachments.isNotEmpty && if (message.attachments?.isNotEmpty == true &&
message.attachments.first.type == "image") { message.attachments.first.type == "image") {
return MessageImage( return MessageImage(
color: color, message: message, messageColor: messageColor); color: color, message: message, messageColor: messageColor);
@@ -58,21 +59,17 @@ class MessageImage extends StatelessWidget {
color: color, color: color,
child: Column( child: Column(
children: [ children: [
if (message.attachments.first.file != null)
FutureBuilder<String>( //hack: //AttachmentUploadStateBuilder once https://github.com/GetStream/stream-chat-flutter/pull/276 is merged Image.memory(
future: Future.delayed( message.attachments.first.file.bytes,
const Duration(seconds: 5), fit: BoxFit.cover,
() => )
message.attachments.first.thumbUrl ?? else
message.attachments.first.imageUrl ?? CachedNetworkImage(
message.attachments.first.assetUrl), imageUrl: message.attachments.first.thumbUrl ??
builder: (context, snapshot) { message.attachments.first.imageUrl ??
return snapshot.hasData message.attachments.first.assetUrl,
? CachedNetworkImage( ),
imageUrl: snapshot.data,
)
: CupertinoActivityIndicator();
}),
if (message.attachments.first?.title != null) if (message.attachments.first?.title != null)
Padding( Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
+29 -4
View File
@@ -8,13 +8,17 @@ String formatDate(DateTime date) {
} }
String formatDateSameWeek(DateTime date) { String formatDateSameWeek(DateTime date) {
final dateFormat = DateFormat('EEEE, hh:mm a'); DateFormat dateFormat;
if (date.day == DateTime.now().day) {
dateFormat = DateFormat('hh:mm a');
} else {
dateFormat = DateFormat('EEEE, hh:mm a');
}
return dateFormat.format(date); return dateFormat.format(date);
} }
String formatDateMessage(DateTime date) { String formatDateMessage(DateTime date) {
final dateFormat = final dateFormat = DateFormat('EEE. MMM. d ' 'yy' ' hh:mm a');
DateFormat('EEE. MMM. d ' 'yy' ' hh:mm a');
return dateFormat.format(date); return dateFormat.format(date);
} }
@@ -35,7 +39,8 @@ class CupertinoCircleAvatar extends StatelessWidget {
height: size, height: size,
width: size, width: size,
fit: BoxFit.cover, fit: BoxFit.cover,
errorWidget: (context, url, error) { //TODO: this crash the app when getting 404 and in debug mode, see :https://github.com/Baseflow/flutter_cached_network_image/issues/504 errorWidget: (context, url, error) {
//TODO: this crash the app when getting 404 and in debug mode, see :https://github.com/Baseflow/flutter_cached_network_image/issues/504
return CachedNetworkImage( return CachedNetworkImage(
imageUrl: imageUrl:
"https://4.bp.blogspot.com/-Jx21kNqFSTU/UXemtqPhZCI/AAAAAAAAh74/BMGSzpU6F48/s1600/funny-cat-pictures-047-001.jpg"); "https://4.bp.blogspot.com/-Jx21kNqFSTU/UXemtqPhZCI/AAAAAAAAh74/BMGSzpU6F48/s1600/funny-cat-pictures-047-001.jpg");
@@ -43,3 +48,23 @@ class CupertinoCircleAvatar extends StatelessWidget {
); );
} }
} }
class Divider extends StatelessWidget {
const Divider({
Key key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Expanded(
child: Align(
child: Container(
height: 1,
color: CupertinoColors.systemGrey5,
),
alignment: Alignment.bottomCenter,
),
);
}
}
+6 -1
View File
@@ -24,7 +24,12 @@ dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
intl: ^0.16.1 intl: ^0.16.1
stream_chat_flutter: ^1.2.0-beta #stream_chat_flutter: ^1.2.0-beta
stream_chat_flutter:
git:
url: git://github.com/GetStream/stream-chat-flutter.git
path: packages/stream_chat_flutter
ref: develop
animations: ^1.0.0+5 animations: ^1.0.0+5
collection: ^1.14.13 collection: ^1.14.13
cached_network_image: ^2.0.0-rc cached_network_image: ^2.0.0-rc