├── example ├── linux │ ├── .gitignore │ ├── main.cc │ ├── my_application.h │ ├── flutter │ │ └── CMakeLists.txt │ └── my_application.cc ├── ios │ ├── Runner │ │ ├── Runner-Bridging-Header.h │ │ ├── Assets.xcassets │ │ │ ├── LaunchImage.imageset │ │ │ │ ├── LaunchImage.png │ │ │ │ ├── LaunchImage@2x.png │ │ │ │ ├── LaunchImage@3x.png │ │ │ │ ├── README.md │ │ │ │ └── Contents.json │ │ │ └── AppIcon.appiconset │ │ │ │ ├── Icon-App-20x20@1x.png │ │ │ │ ├── Icon-App-20x20@2x.png │ │ │ │ ├── Icon-App-20x20@3x.png │ │ │ │ ├── Icon-App-29x29@1x.png │ │ │ │ ├── Icon-App-29x29@2x.png │ │ │ │ ├── Icon-App-29x29@3x.png │ │ │ │ ├── Icon-App-40x40@1x.png │ │ │ │ ├── Icon-App-40x40@2x.png │ │ │ │ ├── Icon-App-40x40@3x.png │ │ │ │ ├── Icon-App-60x60@2x.png │ │ │ │ ├── Icon-App-60x60@3x.png │ │ │ │ ├── Icon-App-76x76@1x.png │ │ │ │ ├── Icon-App-76x76@2x.png │ │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ │ ├── Icon-App-83.5x83.5@2x.png │ │ │ │ └── Contents.json │ │ ├── AppDelegate.swift │ │ ├── Base.lproj │ │ │ ├── Main.storyboard │ │ │ └── LaunchScreen.storyboard │ │ └── Info.plist │ ├── Flutter │ │ ├── Debug.xcconfig │ │ ├── Release.xcconfig │ │ └── AppFrameworkInfo.plist │ ├── Runner.xcodeproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── RunnerTests │ │ └── RunnerTests.swift │ ├── .gitignore │ └── Podfile ├── web │ ├── favicon.png │ ├── icons │ │ ├── Icon-192.png │ │ ├── Icon-512.png │ │ ├── Icon-maskable-192.png │ │ └── Icon-maskable-512.png │ ├── manifest.json │ └── index.html ├── android │ ├── gradle.properties │ ├── app │ │ ├── src │ │ │ ├── main │ │ │ │ ├── res │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── drawable │ │ │ │ │ │ └── launch_background.xml │ │ │ │ │ ├── drawable-v21 │ │ │ │ │ │ └── launch_background.xml │ │ │ │ │ ├── values │ │ │ │ │ │ └── styles.xml │ │ │ │ │ └── values-night │ │ │ │ │ │ └── styles.xml │ │ │ │ ├── kotlin │ │ │ │ │ └── com │ │ │ │ │ │ └── simform │ │ │ │ │ │ └── chatview_connect │ │ │ │ │ │ └── MainActivity.kt │ │ │ │ └── AndroidManifest.xml │ │ │ ├── debug │ │ │ │ └── AndroidManifest.xml │ │ │ └── profile │ │ │ │ └── AndroidManifest.xml │ │ └── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ ├── .gitignore │ ├── build.gradle │ └── settings.gradle ├── macos │ ├── Runner │ │ ├── Configs │ │ │ ├── Debug.xcconfig │ │ │ ├── Release.xcconfig │ │ │ ├── Warnings.xcconfig │ │ │ └── AppInfo.xcconfig │ │ ├── Assets.xcassets │ │ │ └── AppIcon.appiconset │ │ │ │ ├── app_icon_16.png │ │ │ │ ├── app_icon_32.png │ │ │ │ ├── app_icon_64.png │ │ │ │ ├── app_icon_1024.png │ │ │ │ ├── app_icon_128.png │ │ │ │ ├── app_icon_256.png │ │ │ │ ├── app_icon_512.png │ │ │ │ └── Contents.json │ │ ├── Release.entitlements │ │ ├── AppDelegate.swift │ │ ├── MainFlutterWindow.swift │ │ ├── DebugProfile.entitlements │ │ └── Info.plist │ ├── Flutter │ │ ├── Flutter-Debug.xcconfig │ │ └── Flutter-Release.xcconfig │ ├── .gitignore │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── Runner.xcodeproj │ │ ├── project.xcworkspace │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── RunnerTests │ │ └── RunnerTests.swift │ └── Podfile ├── lib │ ├── values │ │ ├── images.dart │ │ ├── borders.dart │ │ ├── enums.dart │ │ ├── app_colors.dart │ │ └── icons.dart │ ├── app.dart │ ├── widgets │ │ ├── user_stacked_profile.dart │ │ ├── chat_user_avatar.dart │ │ └── category_chip.dart │ ├── firebase_options.dart │ ├── modules │ │ ├── chat_list │ │ │ └── widgets │ │ │ │ ├── category_chip.dart │ │ │ │ ├── user_activity_tile.dart │ │ │ │ └── reply_message_tile.dart │ │ ├── create_chat │ │ │ ├── widgets │ │ │ │ └── create_chat_tile.dart │ │ │ └── create_chat_screen.dart │ │ └── chat_detail │ │ │ └── widgets │ │ │ ├── chat_room_user_acitivity_tile.dart │ │ │ └── chat_detail_screen_app_bar.dart │ ├── main.dart │ └── models │ │ └── chat_list_theme.dart ├── assets │ ├── images │ │ └── chat_background.png │ └── vectors │ │ ├── plus.svg │ │ ├── add.svg │ │ ├── more_horizontal.svg │ │ ├── send.svg │ │ ├── check_mark.svg │ │ ├── camera.svg │ │ ├── lock.svg │ │ ├── archived.svg │ │ ├── video.svg │ │ ├── mic.svg │ │ ├── close_circular.svg │ │ ├── pinned.svg │ │ ├── status.svg │ │ ├── phone.svg │ │ ├── messages.svg │ │ ├── calls.svg │ │ ├── ai_logo.svg │ │ ├── sticker.svg │ │ ├── camera_outline.svg │ │ ├── community.svg │ │ └── settings.svg ├── windows │ ├── runner │ │ ├── resources │ │ │ └── app_icon.ico │ │ ├── resource.h │ │ ├── utils.h │ │ ├── runner.exe.manifest │ │ ├── flutter_window.h │ │ ├── main.cpp │ │ ├── CMakeLists.txt │ │ ├── utils.cpp │ │ ├── flutter_window.cpp │ │ ├── Runner.rc │ │ └── win32_window.h │ ├── .gitignore │ ├── flutter │ │ └── CMakeLists.txt │ └── CMakeLists.txt ├── devtools_options.yaml ├── analysis_options.yaml ├── .metadata ├── README.md ├── .gitignore └── pubspec.yaml ├── preview └── banner.png ├── lib ├── src │ ├── models │ │ ├── config │ │ │ ├── cloud_service_config.dart │ │ │ ├── config.dart │ │ │ ├── firebase │ │ │ │ ├── firebase_storage_config.dart │ │ │ │ ├── firebase_cloud_config.dart │ │ │ │ ├── firestore_chat_collection_name_config.dart │ │ │ │ └── firestore_chat_database_path_config.dart │ │ │ ├── chat_user_config.dart │ │ │ └── chat_controller_config.dart │ │ ├── models.dart │ │ ├── message_dm.dart │ │ ├── user_metadata.dart │ │ ├── chat_room_display_metadata.dart │ │ └── user_chat_metadata.dart │ ├── chatview_connect_constants.dart │ ├── database │ │ └── firebase │ │ │ └── chatview_firestore_path.dart │ ├── storage │ │ ├── firebase │ │ │ └── chatview_firebase_storage_refs.dart │ │ └── storage_service.dart │ └── typedefs.dart └── chatview_connect.dart ├── .metadata ├── .github ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── workflows │ ├── title-validation.yml │ └── flutter.yaml └── pull_request_template.md ├── analysis_options.yaml ├── CHANGELOG.md ├── .gitignore ├── pubspec.yaml ├── doc └── firebase │ ├── rules │ └── storage-security-rules │ ├── firebase-storage-structure.md │ └── firebase-database-schema.md ├── flutter_chatview_db_connection.iml ├── LICENSE └── README.md /example/linux/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ephemeral 2 | -------------------------------------------------------------------------------- /example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /preview/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/preview/banner.png -------------------------------------------------------------------------------- /example/web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/web/favicon.png -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx4G 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /example/macos/Runner/Configs/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Debug.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /example/macos/Runner/Configs/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Release.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /example/lib/values/images.dart: -------------------------------------------------------------------------------- 1 | class AppImages { 2 | static const String chatBackground = "assets/images/chat_background.png"; 3 | } 4 | -------------------------------------------------------------------------------- /example/web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/web/icons/Icon-192.png -------------------------------------------------------------------------------- /example/web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/web/icons/Icon-512.png -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/web/icons/Icon-maskable-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/web/icons/Icon-maskable-192.png -------------------------------------------------------------------------------- /example/web/icons/Icon-maskable-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/web/icons/Icon-maskable-512.png -------------------------------------------------------------------------------- /example/assets/images/chat_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/assets/images/chat_background.png -------------------------------------------------------------------------------- /example/windows/runner/resources/app_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/windows/runner/resources/app_icon.ico -------------------------------------------------------------------------------- /lib/src/models/config/cloud_service_config.dart: -------------------------------------------------------------------------------- 1 | /// An abstract interface for defining cloud service configurations. 2 | abstract interface class CloudServiceConfig {} 3 | -------------------------------------------------------------------------------- /example/macos/Flutter/Flutter-Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "ephemeral/Flutter-Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/macos/Flutter/Flutter-Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "ephemeral/Flutter-Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /lib/src/models/models.dart: -------------------------------------------------------------------------------- 1 | export 'chat_room_display_metadata.dart'; 2 | export 'chat_room_metadata.dart'; 3 | export 'chat_room_participant.dart'; 4 | export 'message_dm.dart'; 5 | -------------------------------------------------------------------------------- /example/macos/.gitignore: -------------------------------------------------------------------------------- 1 | # Flutter-related 2 | **/Flutter/ephemeral/ 3 | **/Pods/ 4 | 5 | # Xcode-related 6 | **/dgph 7 | **/xcuserdata/ 8 | 9 | **/GoogleService-Info.plist 10 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png -------------------------------------------------------------------------------- /example/devtools_options.yaml: -------------------------------------------------------------------------------- 1 | description: This file stores settings for Dart & Flutter DevTools. 2 | documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states 3 | extensions: 4 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/linux/main.cc: -------------------------------------------------------------------------------- 1 | #include "my_application.h" 2 | 3 | int main(int argc, char** argv) { 4 | g_autoptr(MyApplication) app = my_application_new(); 5 | return g_application_run(G_APPLICATION(app), argc, argv); 6 | } 7 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /example/android/app/src/main/kotlin/com/simform/chatview_connect/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.simform.chatview_connect 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity : FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/assets/vectors/plus.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/assets/vectors/add.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip 6 | -------------------------------------------------------------------------------- /lib/src/models/config/config.dart: -------------------------------------------------------------------------------- 1 | export 'chat_controller_config.dart'; 2 | export 'chat_user_config.dart'; 3 | export 'firebase/firebase_cloud_config.dart'; 4 | export 'firebase/firestore_chat_collection_name_config.dart'; 5 | export 'firebase/firestore_chat_database_path_config.dart'; 6 | -------------------------------------------------------------------------------- /example/macos/Runner/Release.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/assets/vectors/more_horizontal.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/assets/vectors/send.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/macos/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /lib/src/chatview_connect_constants.dart: -------------------------------------------------------------------------------- 1 | /// A utility class that holds constant values. 2 | abstract final class ChatViewConnectConstants { 3 | /// The default number of retry attempts. 4 | static const int defaultRetry = 2; 5 | 6 | /// A predefined empty string constant. 7 | static const String emptyString = ''; 8 | } 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/lib/values/borders.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class AppBorders { 4 | static const Border chatBubbleBorder = Border.fromBorderSide( 5 | BorderSide( 6 | width: 0.66, 7 | color: Color(0x0F000000), 8 | strokeAlign: BorderSide.strokeAlignOutside, 9 | ), 10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: "46787ee49c1fd80ab603f0702733edab54653aef" 8 | channel: "stable" 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /example/assets/vectors/check_mark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/ios/RunnerTests/RunnerTests.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | import XCTest 4 | 5 | class RunnerTests: XCTestCase { 6 | 7 | func testExample() { 8 | // If you add code to the Runner application, consider adding tests here. 9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest. 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /example/macos/RunnerTests/RunnerTests.swift: -------------------------------------------------------------------------------- 1 | import FlutterMacOS 2 | import Cocoa 3 | import XCTest 4 | 5 | class RunnerTests: XCTestCase { 6 | 7 | func testExample() { 8 | // If you add code to the Runner application, consider adding tests here. 9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest. 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /example/windows/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ephemeral/ 2 | 3 | # Visual Studio user-specific files. 4 | *.suo 5 | *.user 6 | *.userosscache 7 | *.sln.docstates 8 | 9 | # Visual Studio build-related files. 10 | x64/ 11 | x86/ 12 | 13 | # Visual Studio cache files 14 | # files ending in .cache can be ignored 15 | *.[Cc]ache 16 | # but keep track of directories ending in .cache 17 | !*.[Cc]ache/ 18 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /example/macos/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | @main 5 | class AppDelegate: FlutterAppDelegate { 6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { 7 | return true 8 | } 9 | 10 | override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { 11 | return true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | **/google-services.json 15 | **/.cxx 16 | -------------------------------------------------------------------------------- /example/assets/vectors/camera.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/assets/vectors/lock.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @main 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/macos/Runner/MainFlutterWindow.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | class MainFlutterWindow: NSWindow { 5 | override func awakeFromNib() { 6 | let flutterViewController = FlutterViewController() 7 | let windowFrame = self.frame 8 | self.contentViewController = flutterViewController 9 | self.setFrame(windowFrame, display: true) 10 | 11 | RegisterGeneratedPlugins(registry: flutterViewController) 12 | 13 | super.awakeFromNib() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /example/linux/my_application.h: -------------------------------------------------------------------------------- 1 | #ifndef FLUTTER_MY_APPLICATION_H_ 2 | #define FLUTTER_MY_APPLICATION_H_ 3 | 4 | #include 5 | 6 | G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, 7 | GtkApplication) 8 | 9 | /** 10 | * my_application_new: 11 | * 12 | * Creates a new Flutter-based application. 13 | * 14 | * Returns: a new #MyApplication. 15 | */ 16 | MyApplication* my_application_new(); 17 | 18 | #endif // FLUTTER_MY_APPLICATION_H_ 19 | -------------------------------------------------------------------------------- /example/assets/vectors/archived.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/windows/runner/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by Runner.rc 4 | // 5 | #define IDI_APP_ICON 101 6 | 7 | // Next default values for new objects 8 | // 9 | #ifdef APSTUDIO_INVOKED 10 | #ifndef APSTUDIO_READONLY_SYMBOLS 11 | #define _APS_NEXT_RESOURCE_VALUE 102 12 | #define _APS_NEXT_COMMAND_VALUE 40001 13 | #define _APS_NEXT_CONTROL_VALUE 1001 14 | #define _APS_NEXT_SYMED_VALUE 101 15 | #endif 16 | #endif 17 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /lib/src/database/firebase/chatview_firestore_path.dart: -------------------------------------------------------------------------------- 1 | /// provides Firestore paths. 2 | abstract final class ChatViewFireStorePath { 3 | /// Path to the 'messages' collection. 4 | static const String messages = 'messages'; 5 | 6 | /// Path to the 'users' collection. 7 | static const String users = 'users'; 8 | 9 | /// Path to the 'user_chats' collection. 10 | static const String userChats = 'user_chats'; 11 | 12 | /// Path to the 'chats' collection inside 'user_chats' collection. 13 | static const String chats = 'chats'; 14 | } 15 | -------------------------------------------------------------------------------- /example/assets/vectors/video.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/assets/vectors/mic.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/macos/Runner/DebugProfile.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.cs.allow-jit 8 | 9 | com.apple.security.network.server 10 | 11 | com.apple.security.network.client 12 | 13 | com.apple.security.files.user-selected.read-only 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /example/assets/vectors/close_circular.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/macos/Runner/Configs/Warnings.xcconfig: -------------------------------------------------------------------------------- 1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings 2 | GCC_WARN_UNDECLARED_SELECTOR = YES 3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES 4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE 5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES 6 | CLANG_WARN_PRAGMA_PACK = YES 7 | CLANG_WARN_STRICT_PROTOTYPES = YES 8 | CLANG_WARN_COMMA = YES 9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES 10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES 11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES 12 | GCC_WARN_SHADOW = YES 13 | CLANG_WARN_UNREACHABLE_CODE = YES 14 | -------------------------------------------------------------------------------- /example/assets/vectors/pinned.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '2.0.0' 3 | repositories { 4 | google() 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 10 | } 11 | } 12 | 13 | allprojects { 14 | repositories { 15 | google() 16 | mavenCentral() 17 | } 18 | } 19 | 20 | rootProject.buildDir = '../build' 21 | subprojects { 22 | project.buildDir = "${rootProject.buildDir}/${project.name}" 23 | } 24 | subprojects { 25 | project.evaluationDependsOn(':app') 26 | } 27 | 28 | tasks.register("clean", Delete) { 29 | delete rootProject.buildDir 30 | } 31 | -------------------------------------------------------------------------------- /example/lib/app.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'modules/chat_list/chat_list_screen.dart'; 4 | import 'values/app_colors.dart'; 5 | 6 | class ChatViewConnectExampleApp extends StatelessWidget { 7 | const ChatViewConnectExampleApp({super.key}); 8 | 9 | @override 10 | Widget build(BuildContext context) { 11 | return MaterialApp( 12 | title: 'Chat View Connect Demo', 13 | debugShowCheckedModeBanner: false, 14 | theme: ThemeData( 15 | primaryColor: AppColors.uiTwoGreen, 16 | colorScheme: ColorScheme.fromSwatch(accentColor: AppColors.uiTwoGreen), 17 | ), 18 | home: const ChatListScreen(), 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | 3 | analyzer: 4 | strong-mode: 5 | implicit-casts: false 6 | implicit-dynamic: false 7 | errors: 8 | argument_type_not_assignable: error 9 | invalid_assignment: error 10 | dead_code: warning 11 | overridden_fields: ignore 12 | use_key_in_widget_constructors: ignore 13 | 14 | linter: 15 | rules: 16 | public_member_api_docs: true 17 | avoid_print: true 18 | avoid_empty_else: true 19 | annotate_overrides: true 20 | cancel_subscriptions: true 21 | close_sinks: true 22 | avoid_positional_boolean_parameters: true 23 | use_super_parameters: true 24 | prefer_relative_imports: true 25 | -------------------------------------------------------------------------------- /example/lib/values/enums.dart: -------------------------------------------------------------------------------- 1 | import 'package:chatview/chatview.dart'; 2 | 3 | enum FilterType { 4 | all('All'), 5 | unread('Unread'), 6 | group('Groups'); 7 | 8 | const FilterType(this.label); 9 | 10 | final String label; 11 | 12 | bool get isAll => this == all; 13 | 14 | bool get isUnread => this == unread; 15 | 16 | bool get isGroup => this == group; 17 | 18 | List filterChats(List chats) { 19 | return switch (this) { 20 | FilterType.unread => 21 | chats.where((e) => (e.unreadCount ?? 0) > 0).toList(), 22 | FilterType.group => chats.where((e) => e.chatRoomType.isGroup).toList(), 23 | FilterType.all => chats, 24 | }; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /example/macos/Runner/Configs/AppInfo.xcconfig: -------------------------------------------------------------------------------- 1 | // Application-level settings for the Runner target. 2 | // 3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the 4 | // future. If not, the values below would default to using the project name when this becomes a 5 | // 'flutter create' template. 6 | 7 | // The application's name. By default this is also the title of the Flutter window. 8 | PRODUCT_NAME = ChatView Connect Example 9 | 10 | // The application's bundle identifier 11 | PRODUCT_BUNDLE_IDENTIFIER = com.simform.chatview-connect 12 | 13 | // The copyright displayed in application information 14 | PRODUCT_COPYRIGHT = Copyright © 2024 com.example. All rights reserved. 15 | -------------------------------------------------------------------------------- /example/windows/runner/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_UTILS_H_ 2 | #define RUNNER_UTILS_H_ 3 | 4 | #include 5 | #include 6 | 7 | // Creates a console for the process, and redirects stdout and stderr to 8 | // it for both the runner and the Flutter library. 9 | void CreateAndAttachConsole(); 10 | 11 | // Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string 12 | // encoded in UTF-8. Returns an empty std::string on failure. 13 | std::string Utf8FromUtf16(const wchar_t* utf16_string); 14 | 15 | // Gets the command line arguments passed in as a std::vector, 16 | // encoded in UTF-8. Returns an empty std::vector on failure. 17 | std::vector GetCommandLineArguments(); 18 | 19 | #endif // RUNNER_UTILS_H_ 20 | -------------------------------------------------------------------------------- /example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | 36 | **/GoogleService-Info.plist 37 | Podfile.lock -------------------------------------------------------------------------------- /.github/workflows/title-validation.yml: -------------------------------------------------------------------------------- 1 | # See https://github.com/amannn/action-semantic-pull-request 2 | name: 'PR Title is Conventional' 3 | 4 | on: 5 | pull_request_target: 6 | types: 7 | - opened 8 | - edited 9 | - synchronize 10 | - reopened 11 | 12 | jobs: 13 | main: 14 | name: Validate PR title 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: amannn/action-semantic-pull-request@v4 18 | env: 19 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 20 | with: 21 | types: | 22 | build 23 | chore 24 | ci 25 | docs 26 | feat 27 | fix 28 | perf 29 | refactor 30 | revert 31 | style 32 | test 33 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 3.0.0 2 | 3 | * **Feat**: [53](https://github.com/SimformSolutionsPvtLtd/chatview_connect/pull/53) Introduced 4 | `ChatListManager` to support `ChatList` functionality with methods like `createChat()`, 5 | `createGroupChat()`, `pinChat()`, `muteChat()`, and `deleteChat()`. 6 | * **Feat**: [49](https://github.com/SimformSolutionsPvtLtd/chatview_connect/pull/49) Added 7 | `chatRoomChangesStream()` in ChatManager for real-time chat room updates. 8 | * **Feat**: [51](https://github.com/SimformSolutionsPvtLtd/chatview_connect/pull/51) Added 9 | `onLoadMoreData()` and `loadOldReplyMessage()` in ChatManager to fetch older messages and replies. 10 | * **Breaking**: [61](https://github.com/SimformSolutionsPvtLtd/chatview_connect/pull/61) Update package 11 | versions and refactor voice recording settings 12 | 13 | ## 0.0.1 14 | 15 | * Initial release. 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://www.dartlang.org/guides/libraries/private-files 2 | 3 | # Files and directories created by pub 4 | .dart_tool/ 5 | .packages 6 | build/ 7 | # If you're building an application, you may want to check-in your pubspec.lock 8 | pubspec.lock 9 | 10 | # Directory created by dartdoc 11 | # If you don't generate documentation locally you can remove this line. 12 | doc/api/ 13 | 14 | # dotenv environment variables file 15 | .env* 16 | 17 | # Avoid committing generated Javascript files: 18 | *.dart.js 19 | *.info.json # Produced by the --dump-info flag. 20 | *.js # When generated by dart2js. Don't specify *.js if your 21 | # project includes source files written in JavaScript. 22 | *.js_ 23 | *.js.deps 24 | *.js.map 25 | 26 | .flutter-plugins 27 | .flutter-plugins-dependencies 28 | 29 | .idea/ 30 | 31 | **/firebase.json 32 | -------------------------------------------------------------------------------- /lib/src/models/message_dm.dart: -------------------------------------------------------------------------------- 1 | import 'package:chatview_utils/chatview_utils.dart'; 2 | import 'package:cloud_firestore/cloud_firestore.dart'; 3 | 4 | /// encapsulates information about message, 5 | /// including content of [Message] Data model and 6 | /// the corresponding [DocumentSnapshot] of [Message]? document snapshot. 7 | class MessageDm { 8 | /// Creates an instance of [MessageDm] 9 | /// 10 | /// **Parameters:** 11 | /// - (required): [message] The [Message] model containing the message data. 12 | /// - (optional): [snapshot] The Firestore [DocumentSnapshot] associated 13 | /// with the message. 14 | const MessageDm({required this.message, this.snapshot}); 15 | 16 | /// provides content of the [Message] model. 17 | final Message message; 18 | 19 | /// provides firebase document snapshot. 20 | final DocumentSnapshot? snapshot; 21 | } 22 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 12.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /.github/workflows/flutter.yaml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout input branch from github 13 | uses: actions/checkout@v4.1.1 14 | - name: Install Flutter 15 | uses: subosito/flutter-action@v2.13.0 16 | with: 17 | flutter-version: '3.22.0' 18 | cache: true 19 | cache-key: 'flutter-macos-stable-3.22.0' 20 | cache-path: '${{ runner.tool_cache }}/flutter/macos-stable-3.22.0' 21 | pub-cache-key: 'flutter-pub-macos-stable-3.22.0' 22 | - name: Flutter pub get 23 | run: flutter pub get 24 | - name: Flutter Analyze 25 | run: dart analyze 26 | - name: Code Formatting 27 | run: dart format --set-exit-if-changed . 28 | - name: Check Publish Warnings 29 | run: flutter pub publish --dry-run 30 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: chatview_connect 2 | description: "Specialized wrapper for chatview package providing seamless integration with Database & Storage for your flutter chat app." 3 | version: 3.0.0 4 | issue_tracker: https://github.com/SimformSolutionsPvtLtd/chatview_connect/issues 5 | homepage: https://github.com/SimformSolutionsPvtLtd/chatview_connect 6 | topics: 7 | - chatview 8 | - firebase 9 | - chat-backend 10 | - plug-and-play 11 | - backend-integration 12 | 13 | platforms: 14 | android: 15 | ios: 16 | web: 17 | macos: 18 | windows: 19 | 20 | environment: 21 | sdk: '>=3.4.0 <4.0.0' 22 | 23 | dependencies: 24 | chatview_utils: 3.0.0 25 | 26 | cloud_firestore: ^6.1.1 27 | firebase_storage: ^13.0.5 28 | 29 | flutter: 30 | sdk: flutter 31 | 32 | http: ^1.4.0 33 | intl: ^0.20.2 34 | path: ^1.9.0 35 | rxdart: ^0.28.0 36 | uuid: ^4.5.1 37 | 38 | dev_dependencies: 39 | flutter_lints: ^2.0.1 40 | flutter_test: 41 | sdk: flutter 42 | -------------------------------------------------------------------------------- /example/windows/runner/runner.exe.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PerMonitorV2 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | -OS(e.g. iOS) 28 | -Browser(e.g. chrome, safari) 29 | -Version(e.g. 22) 30 | 31 | **Smartphone (please complete the following information):** 32 | -Device(e.g. iPhone6) 33 | -OS(e.g. iOS8.1) 34 | -Browser(e.g. stock browser, safari) 35 | -Version(e.g. 22) 36 | 37 | **Additional context** 38 | Add any other context about the problem here. -------------------------------------------------------------------------------- /doc/firebase/rules/storage-security-rules: -------------------------------------------------------------------------------- 1 | rules_version = '2'; 2 | 3 | service firebase.storage { 4 | match /b/{bucket}/o { 5 | 6 | // TODO: Update the path as per configured in chatview_connect 7 | function chatCollection() { 8 | return 'chats'; 9 | } 10 | 11 | function isSignedIn() { 12 | return request.auth != null; 13 | } 14 | 15 | function getChatRoomUserPath(userId, chatRoomID) { 16 | return /databases/(default)/documents/$(chatCollection())/$(chatRoomID)/users/$(userId); 17 | } 18 | 19 | match /chats/{chatRoomID} { 20 | function isUserMember() { 21 | let doc = firestore.get(getChatRoomUserPath(request.auth.uid, chatRoomID)); 22 | return doc != null && doc.data.membership_status != "left" 23 | } 24 | 25 | match /{allPaths=**} { 26 | allow read, write: if isSignedIn() && isUserMember(); 27 | } 28 | } 29 | 30 | match /{allPaths=**} { 31 | allow read: if isSignedIn(); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /example/lib/values/app_colors.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | class AppColors { 4 | static const Color grey200 = Color(0xffffffff); 5 | static const Color red200 = Color(0xFFFFCDD2); 6 | static const Color grey = Color(0xff767779); 7 | static const Color dividerGrey = Color(0x33000000); 8 | static const Color background = Color(0xFFF5F2EB); 9 | static const Color replyLineColor = Color(0xffD42A66); 10 | static const Color senderBgColor = Color(0xffD0FECF); 11 | static const Color menuHighlight = Color(0x80D0FECF); 12 | static const Color chatviewBackground = Color(0xFFE5DDD5); 13 | 14 | static const Color black20 = Color(0x33000000); 15 | static const Color white20 = Color(0x33ffffff); 16 | static const Color uiTwoGreen = Color(0xff1DAB61); 17 | static const Color uiTwoGrey = Color(0xff767779); 18 | static const Color uiTwoBackground = Color(0xFFF5F2EB); 19 | static const Color uiTwoReplyLineColor = Color(0xffD42A66); 20 | static const Color uiTwoSenderBgColor = Color(0xffD0FECF); 21 | } 22 | -------------------------------------------------------------------------------- /flutter_chatview_db_connection.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /example/assets/vectors/status.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | def flutterSdkPath = { 3 | def properties = new Properties() 4 | file("local.properties").withInputStream { properties.load(it) } 5 | def flutterSdkPath = properties.getProperty("flutter.sdk") 6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 7 | return flutterSdkPath 8 | } 9 | settings.ext.flutterSdkPath = flutterSdkPath() 10 | 11 | includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle") 12 | 13 | repositories { 14 | google() 15 | mavenCentral() 16 | gradlePluginPortal() 17 | } 18 | 19 | plugins { 20 | id "dev.flutter.flutter-gradle-plugin" version "1.0.0" apply false 21 | } 22 | } 23 | 24 | plugins { 25 | id "dev.flutter.flutter-plugin-loader" version "1.0.0" 26 | id "com.android.application" version "8.10.1" apply false 27 | id "com.google.gms.google-services" version "4.3.15" apply false 28 | } 29 | 30 | include ":app" 31 | -------------------------------------------------------------------------------- /example/lib/widgets/user_stacked_profile.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class UserStackedProfile extends StatelessWidget { 4 | const UserStackedProfile({required this.usersProfileURLs, super.key}); 5 | 6 | final List usersProfileURLs; 7 | 8 | @override 9 | Widget build(BuildContext context) { 10 | final usersProfileURLsLength = usersProfileURLs.length; 11 | final urlsLength = usersProfileURLsLength > 2 ? 2 : usersProfileURLsLength; 12 | return Stack( 13 | children: List.generate( 14 | urlsLength, 15 | (index) { 16 | final position = index * 10.0; 17 | final profilePhoto = usersProfileURLs[index]; 18 | return Positioned( 19 | left: position, 20 | top: position, 21 | child: CircleAvatar( 22 | radius: 15, 23 | backgroundColor: Colors.transparent, 24 | backgroundImage: NetworkImage(profilePhoto), 25 | ), 26 | ); 27 | }, 28 | ), 29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /example/windows/runner/flutter_window.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_FLUTTER_WINDOW_H_ 2 | #define RUNNER_FLUTTER_WINDOW_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include "win32_window.h" 10 | 11 | // A window that does nothing but host a Flutter view. 12 | class FlutterWindow : public Win32Window { 13 | public: 14 | // Creates a new FlutterWindow hosting a Flutter view running |project|. 15 | explicit FlutterWindow(const flutter::DartProject& project); 16 | virtual ~FlutterWindow(); 17 | 18 | protected: 19 | // Win32Window: 20 | bool OnCreate() override; 21 | void OnDestroy() override; 22 | LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, 23 | LPARAM const lparam) noexcept override; 24 | 25 | private: 26 | // The project to run. 27 | flutter::DartProject project_; 28 | 29 | // The Flutter instance hosted by this window. 30 | std::unique_ptr flutter_controller_; 31 | }; 32 | 33 | #endif // RUNNER_FLUTTER_WINDOW_H_ 34 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ChatView Connect Example", 3 | "short_name": "ChatView Connect Example", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "Example of ChatView Connect", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | }, 22 | { 23 | "src": "icons/Icon-maskable-192.png", 24 | "sizes": "192x192", 25 | "type": "image/png", 26 | "purpose": "maskable" 27 | }, 28 | { 29 | "src": "icons/Icon-maskable-512.png", 30 | "sizes": "512x512", 31 | "type": "image/png", 32 | "purpose": "maskable" 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /example/assets/vectors/phone.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/chatview_connect.dart: -------------------------------------------------------------------------------- 1 | /// chatview_connect: Cloud-Powered ChatView Integration 2 | /// 3 | /// `chatview_connect` is your go-to solution for integrating 4 | /// a fully functional, cloud-backed chat module into your Flutter applications. 5 | /// 6 | /// Currently, the package offers seamless integration with Firebase 7 | /// as the backend. In the future, additional cloud services will be supported, 8 | /// ensuring flexibility and scalability. Built as a powerful wrapper around 9 | /// the popular `chatview` package, it provides real-time chat capabilities 10 | /// and a suite of easy-to-use methods to manage chats, users, and messages 11 | /// without the hassle of complex backend setups. 12 | library; 13 | 14 | export 'src/chatview_connect.dart'; 15 | export 'src/enum.dart' 16 | hide 17 | DocumentChangeTypeExtension, 18 | MembershipStatusExtension, 19 | RoleExtension, 20 | TypeWriterStatusExtension; 21 | export 'src/manager/chat/chat_manager.dart'; 22 | export 'src/manager/chat_list/chat_list_manager.dart'; 23 | export 'src/models/config/config.dart'; 24 | export 'src/models/models.dart'; 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Simform Solutions 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /example/lib/firebase_options.dart: -------------------------------------------------------------------------------- 1 | // File generated by FlutterFire CLI. 2 | // ignore_for_file: type=lint 3 | import 'package:firebase_core/firebase_core.dart' show FirebaseOptions; 4 | import 'package:flutter/foundation.dart' show defaultTargetPlatform, kIsWeb; 5 | 6 | /// Default [FirebaseOptions] for use with your Firebase apps. 7 | /// 8 | /// Example: 9 | /// ```dart 10 | /// import 'firebase_options.dart'; 11 | /// // ... 12 | /// await Firebase.initializeApp( 13 | /// options: DefaultFirebaseOptions.currentPlatform, 14 | /// ); 15 | /// ``` 16 | class DefaultFirebaseOptions { 17 | static FirebaseOptions get currentPlatform { 18 | if (kIsWeb) { 19 | throw UnsupportedError( 20 | 'DefaultFirebaseOptions have not been configured for web - ' 21 | 'you can reconfigure this by running the FlutterFire CLI again.', 22 | ); 23 | } 24 | switch (defaultTargetPlatform) { 25 | default: 26 | throw UnsupportedError( 27 | 'DefaultFirebaseOptions have not been configured for $defaultTargetPlatform - ' 28 | 'you can reconfigure this by running the FlutterFire CLI again.', 29 | ); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /example/assets/vectors/messages.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/assets/vectors/calls.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/macos/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | $(PRODUCT_COPYRIGHT) 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /lib/src/models/config/firebase/firebase_storage_config.dart: -------------------------------------------------------------------------------- 1 | /// Configuration class for managing Firebase Storage settings, 2 | /// including synchronization options for voice and image files. 3 | class FirebaseStorageConfig { 4 | /// Creates a [FirebaseStorageConfig] instance with the required 5 | /// configurations. 6 | /// 7 | /// - [syncVoice] controls whether voice files should be stored in 8 | /// Firebase Storage. 9 | /// - [syncImage] controls whether image files should be stored in 10 | /// Firebase Storage. 11 | const FirebaseStorageConfig({ 12 | required this.syncVoice, 13 | required this.syncImage, 14 | }); 15 | 16 | /// Determines whether voice files should be uploaded to or deleted 17 | /// from storage. 18 | /// 19 | /// - Set to `true` to enable automatic upload and deletion in storage. 20 | /// - Set to `false` to prevent any modifications in storage. 21 | final bool syncVoice; 22 | 23 | /// Determines whether image files should be uploaded to or deleted 24 | /// from storage. 25 | /// 26 | /// - Set to `true` to enable automatic upload and deletion in storage. 27 | /// - Set to `false` to prevent any modifications in storage. 28 | final bool syncImage; 29 | } 30 | -------------------------------------------------------------------------------- /doc/firebase/firebase-storage-structure.md: -------------------------------------------------------------------------------- 1 | ## 💾 Firebase Storage Structure 2 | 3 | This document outlines the Firebase Storage structure used for managing chat-related media files, 4 | including images and audio messages. 5 | 6 | ```plaintext 7 | 📂 chats (Top Directory) 8 | ├── 📂 {chatID} (Sub Directory) 9 | ├── 📂 images: (Sub Directory) 10 | ├── 📄 {messageId}_{sendBy}_{timestamp}_{fileName}.{fileExtension} 11 | ├── 📂 voices: (Sub Directory) 12 | ├── 📄 {messageId}_{sendBy}_{timestamp}_{fileName}.{fileExtension} 13 | 14 | ``` 15 | 16 | ### Breakdown of Path Components: 17 | 18 | - **`chats/{chatId}/`** → Represents a unique chat session identified by `chatId`. 19 | - **`images/` or `voices/`** → Specifies the type of media stored. 20 | - **`{messageId}_{sendBy}_{timestamp}_{fileName}.{fileExtension}`** → A unique identifier for each 21 | media file, composed of: 22 | - `messageId` → Unique ID of the message containing the media. 23 | - `sendBy` → Unique ID of the user who sent media files. 24 | - `timestamp` → Unix timestamp in microseconds to maintain order. 25 | - `fileName` → The original or system-generated name of the file. 26 | - `fileExtension` → The format of the file (e.g., jpg, png, mp3, wav). 27 | -------------------------------------------------------------------------------- /example/assets/vectors/ai_logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/lib/widgets/chat_user_avatar.dart: -------------------------------------------------------------------------------- 1 | import 'package:chatview/chatview.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class ChatUserAvatar extends StatelessWidget { 5 | const ChatUserAvatar({ 6 | required this.profileURL, 7 | this.status = UserActiveStatus.offline, 8 | super.key, 9 | }); 10 | 11 | final String? profileURL; 12 | final UserActiveStatus? status; 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | return Stack( 17 | children: [ 18 | CircleAvatar( 19 | backgroundColor: Colors.transparent, 20 | backgroundImage: 21 | profileURL == null ? null : NetworkImage(profileURL!), 22 | ), 23 | if (status?.isOnline ?? false) 24 | const Positioned( 25 | top: 0, 26 | right: 0, 27 | child: DecoratedBox( 28 | decoration: BoxDecoration( 29 | color: Colors.green, 30 | shape: BoxShape.circle, 31 | border: Border.fromBorderSide( 32 | BorderSide(width: 2, color: Colors.white), 33 | ), 34 | ), 35 | child: SizedBox(width: 14, height: 14), 36 | ), 37 | ), 38 | ], 39 | ); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /example/assets/vectors/sticker.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/src/storage/firebase/chatview_firebase_storage_refs.dart: -------------------------------------------------------------------------------- 1 | /// Contains Firebase storage path references. 2 | abstract final class ChatViewFirebaseStorageRefs { 3 | /// Path for storing images in Firebase storage. 4 | static const String _images = 'images'; 5 | 6 | /// Path for storing voices in Firebase storage. 7 | static const String _voices = 'voices'; 8 | 9 | /// Path for storing chats in Firebase storage. 10 | static const String _chats = 'chats'; 11 | 12 | /// Returns the Firebase storage reference path for a specific chat. 13 | /// 14 | /// [chatId] - The unique identifier of the chat. 15 | /// Example output: 'chats/{chatId}' 16 | static String getChatsRefById(String chatId) => '$_chats/$chatId'; 17 | 18 | /// Returns the Firebase storage reference path for images within 19 | /// a specific chat. 20 | /// 21 | /// [chatId] - The unique identifier of the chat. 22 | /// Example output: 'chats/{chatId}/images' 23 | static String getImageRef(String chatId) => 24 | '${getChatsRefById(chatId)}/$_images'; 25 | 26 | /// Returns the Firebase storage reference path for voice messages within 27 | /// a specific chat. 28 | /// 29 | /// [chatId] - The unique identifier of the chat. 30 | /// Example output: 'chats/{chatId}/voices' 31 | static String getVoiceRef(String chatId) => 32 | '${getChatsRefById(chatId)}/$_voices'; 33 | } 34 | -------------------------------------------------------------------------------- /example/lib/values/icons.dart: -------------------------------------------------------------------------------- 1 | class AppIcons { 2 | static const String camera = 'assets/vectors/camera.svg'; 3 | static const String cameraOutline = "assets/vectors/camera_outline.svg"; 4 | static const String checkMark = "assets/vectors/check_mark.svg"; 5 | static const String pinned = "assets/vectors/pinned.svg"; 6 | static const String video = "assets/vectors/video.svg"; 7 | static const String phone = "assets/vectors/phone.svg"; 8 | static const String sticker = "assets/vectors/sticker.svg"; 9 | static const String ai = "assets/vectors/ai_logo.svg"; 10 | static const String add = 'assets/vectors/add.svg'; 11 | static const String calls = "assets/vectors/calls.svg"; 12 | static const String archived = "assets/vectors/archived.svg"; 13 | static const String closeCircular = "assets/vectors/close_circular.svg"; 14 | static const String plus = 'assets/vectors/plus.svg'; 15 | static const String community = "assets/vectors/community.svg"; 16 | static const String lock = "assets/vectors/lock.svg"; 17 | static const String status = "assets/vectors/status.svg"; 18 | static const String messages = "assets/vectors/messages.svg"; 19 | static const String settings = "assets/vectors/settings.svg"; 20 | static const String mic = "assets/vectors/mic.svg"; 21 | static const String send = "assets/vectors/send.svg"; 22 | static const String moreHoriz = 'assets/vectors/more_horizontal.svg'; 23 | } 24 | -------------------------------------------------------------------------------- /lib/src/models/config/chat_user_config.dart: -------------------------------------------------------------------------------- 1 | import 'package:chatview_utils/chatview_utils.dart'; 2 | 3 | /// A configurable implementation of [ChatUserConfig] that allows 4 | /// dynamic mapping of user properties when serializing and deserializing JSON. 5 | /// 6 | /// By default, user data is stored and retrieved using standard keys such as 7 | /// `id`, `name`, and `profilePhoto`. 8 | /// However, different data sources may use custom key names 9 | /// (e.g., `username` instead of `name`). 10 | /// This class provides flexibility to define custom key mappings 11 | /// to correctly interpret user data from various sources. 12 | final class ChatUserConfig implements ChatUserConfigBase { 13 | /// Creates a [ChatUserConfig] instance with optional key mappings. 14 | /// 15 | /// If a data source uses different keys (e.g., `username` instead of `name`), 16 | /// those keys can be specified here to ensure correct JSON parsing. 17 | const ChatUserConfig({ 18 | this.idKey, 19 | this.nameKey, 20 | this.profilePhotoKey, 21 | }); 22 | 23 | /// The JSON key used for uniquely identifying a user. Default: `"id"`. 24 | @override 25 | final String? idKey; 26 | 27 | /// The JSON key used for storing the user's display name. Default: `"name"`. 28 | @override 29 | final String? nameKey; 30 | 31 | /// The JSON key used for the user's profile photo. Default: `"profilePhoto"`. 32 | @override 33 | final String? profilePhotoKey; 34 | } 35 | -------------------------------------------------------------------------------- /example/windows/runner/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "flutter_window.h" 6 | #include "utils.h" 7 | 8 | int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, 9 | _In_ wchar_t *command_line, _In_ int show_command) { 10 | // Attach to console when present (e.g., 'flutter run') or create a 11 | // new console when running with a debugger. 12 | if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { 13 | CreateAndAttachConsole(); 14 | } 15 | 16 | // Initialize COM, so that it is available for use in the library and/or 17 | // plugins. 18 | ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); 19 | 20 | flutter::DartProject project(L"data"); 21 | 22 | std::vector command_line_arguments = 23 | GetCommandLineArguments(); 24 | 25 | project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); 26 | 27 | FlutterWindow window(project); 28 | Win32Window::Point origin(10, 10); 29 | Win32Window::Size size(1280, 720); 30 | if (!window.Create(L"example", origin, size)) { 31 | return EXIT_FAILURE; 32 | } 33 | window.SetQuitOnClose(true); 34 | 35 | ::MSG msg; 36 | while (::GetMessage(&msg, nullptr, 0, 0)) { 37 | ::TranslateMessage(&msg); 38 | ::DispatchMessage(&msg); 39 | } 40 | 41 | ::CoUninitialize(); 42 | return EXIT_SUCCESS; 43 | } 44 | -------------------------------------------------------------------------------- /lib/src/models/config/firebase/firebase_cloud_config.dart: -------------------------------------------------------------------------------- 1 | import '../cloud_service_config.dart'; 2 | import 'firestore_chat_collection_name_config.dart'; 3 | import 'firestore_chat_database_path_config.dart'; 4 | 5 | /// A configuration class for Firebase integration. 6 | /// 7 | /// This class holds the necessary configurations for database paths and 8 | /// collection names required to interact with Firebase Firestore. 9 | class FirebaseCloudConfig implements CloudServiceConfig { 10 | /// Creates a [FirebaseCloudConfig] instance with the required configurations. 11 | /// 12 | /// **Parameters:** 13 | /// - (optional): [databasePathConfig] Defines the Firestore database 14 | /// paths for retrieving user data. 15 | /// - If omitted, the default top-level `users` collection will be used. 16 | /// - (optional): [collectionNameConfig] Allows customization of 17 | /// Firestore collection names. 18 | /// - If a value is `null`, the default collection name will be used. 19 | const FirebaseCloudConfig({ 20 | this.databasePathConfig, 21 | this.collectionNameConfig, 22 | }); 23 | 24 | /// Defines the Firestore database paths for retrieving user data. 25 | /// Defaults to the top-level `users` collection if not provided. 26 | final FirestoreChatDatabasePathConfig? databasePathConfig; 27 | 28 | /// Allows customization of Firestore collection names. 29 | /// If `null`, the default collection name will be used. 30 | final FirestoreChatCollectionNameConfig? collectionNameConfig; 31 | } 32 | -------------------------------------------------------------------------------- /example/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the analyzer, which statically analyzes Dart code to 2 | # check for errors, warnings, and lints. 3 | # 4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled 5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be 6 | # invoked from the command line by running `flutter analyze`. 7 | 8 | # The following line activates a set of recommended lints for Flutter apps, 9 | # packages, and plugins designed to encourage good coding practices. 10 | include: package:flutter_lints/flutter.yaml 11 | 12 | linter: 13 | # The lint rules applied to this project can be customized in the 14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml` 15 | # included above or to enable additional rules. A list of all available lints 16 | # and their documentation is published at https://dart.dev/lints. 17 | # 18 | # Instead of disabling a lint rule for the entire project in the 19 | # section below, it can also be suppressed for a single line of code 20 | # or a specific dart file by using the `// ignore: name_of_lint` and 21 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file 22 | # producing the lint. 23 | rules: 24 | # avoid_print: false # Uncomment to disable the `avoid_print` rule 25 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule 26 | 27 | # Additional information about this file can be found at 28 | # https://dart.dev/guides/language/analysis-options 29 | -------------------------------------------------------------------------------- /example/macos/Podfile: -------------------------------------------------------------------------------- 1 | platform :osx, '12' 2 | 3 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 4 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 5 | 6 | project 'Runner', { 7 | 'Debug' => :debug, 8 | 'Profile' => :release, 9 | 'Release' => :release, 10 | } 11 | 12 | def flutter_root 13 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) 14 | unless File.exist?(generated_xcode_build_settings_path) 15 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" 16 | end 17 | 18 | File.foreach(generated_xcode_build_settings_path) do |line| 19 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 20 | return matches[1].strip if matches 21 | end 22 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" 23 | end 24 | 25 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 26 | 27 | flutter_macos_podfile_setup 28 | 29 | target 'Runner' do 30 | use_frameworks! 31 | use_modular_headers! 32 | 33 | flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) 34 | target 'RunnerTests' do 35 | inherit! :search_paths 36 | end 37 | end 38 | 39 | post_install do |installer| 40 | installer.pods_project.targets.each do |target| 41 | flutter_additional_macos_build_settings(target) 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /example/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | platform :ios, '16.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | use_frameworks! 32 | use_modular_headers! 33 | 34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 35 | target 'RunnerTests' do 36 | inherit! :search_paths 37 | end 38 | end 39 | 40 | post_install do |installer| 41 | installer.pods_project.targets.each do |target| 42 | flutter_additional_ios_build_settings(target) 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /example/assets/vectors/camera_outline.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /example/lib/widgets/category_chip.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../values/app_colors.dart'; 4 | import '../values/enums.dart'; 5 | 6 | class CategoryChip extends StatelessWidget { 7 | const CategoryChip({ 8 | required this.value, 9 | required this.groupValue, 10 | this.onSelected, 11 | this.counts, 12 | super.key, 13 | }); 14 | 15 | final int? counts; 16 | final VoidCallback? onSelected; 17 | final FilterType value; 18 | final FilterType groupValue; 19 | 20 | @override 21 | Widget build(BuildContext context) { 22 | final isSelected = value == groupValue; 23 | return FilterChip.elevated( 24 | elevation: 0, 25 | pressElevation: 0, 26 | selected: isSelected, 27 | showCheckmark: false, 28 | padding: const EdgeInsets.symmetric( 29 | horizontal: 6, 30 | vertical: 10, 31 | ), 32 | shape: const RoundedRectangleBorder( 33 | borderRadius: BorderRadius.all(Radius.circular(30)), 34 | ), 35 | color: WidgetStateProperty.resolveWith( 36 | (states) => states.contains(WidgetState.selected) 37 | ? AppColors.red200 38 | : AppColors.grey200, 39 | ), 40 | labelStyle: TextStyle( 41 | color: isSelected ? Colors.black : Colors.grey.shade600, 42 | fontWeight: isSelected ? FontWeight.w600 : FontWeight.w500, 43 | ), 44 | backgroundColor: Colors.grey.shade200, 45 | label: Text( 46 | counts == null ? groupValue.label : '${groupValue.label} ($counts)', 47 | ), 48 | onSelected: (_) => onSelected?.call(), 49 | ); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "app_icon_16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "app_icon_32.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "app_icon_32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "app_icon_64.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "app_icon_128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "app_icon_256.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "app_icon_256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "app_icon_512.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "app_icon_512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "app_icon_1024.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /example/lib/modules/chat_list/widgets/category_chip.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../../../models/chat_list_theme.dart'; 4 | import '../../../values/enums.dart'; 5 | 6 | class CategoryChip extends StatelessWidget { 7 | const CategoryChip({ 8 | required this.value, 9 | required this.groupValue, 10 | required this.theme, 11 | this.onSelected, 12 | this.counts, 13 | super.key, 14 | }); 15 | 16 | final int? counts; 17 | final VoidCallback? onSelected; 18 | final FilterType value; 19 | final FilterType groupValue; 20 | final ChatListTheme theme; 21 | 22 | @override 23 | Widget build(BuildContext context) { 24 | final isSelected = value == groupValue; 25 | final count = counts ?? 0; 26 | final title = groupValue.label; 27 | return FilterChip.elevated( 28 | elevation: 0, 29 | pressElevation: 0, 30 | selected: isSelected, 31 | showCheckmark: false, 32 | padding: const EdgeInsets.symmetric( 33 | horizontal: 6, 34 | vertical: 10, 35 | ), 36 | shape: const StadiumBorder(), 37 | labelStyle: TextStyle( 38 | color: isSelected ? theme.selectedChip : theme.chipText, 39 | fontWeight: FontWeight.w600, 40 | fontSize: 14, 41 | ), 42 | backgroundColor: theme.chipBg, 43 | selectedColor: theme.selectedChipBg, 44 | label: Text( 45 | count > 0 ? '$title ($counts)' : title, 46 | ), 47 | onSelected: (_) => onSelected?.call(), 48 | side: BorderSide.none, 49 | materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, 50 | visualDensity: VisualDensity.compact, 51 | ); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: "46787ee49c1fd80ab603f0702733edab54653aef" 8 | channel: "stable" 9 | 10 | project_type: app 11 | 12 | # Tracks metadata for the flutter migrate command 13 | migration: 14 | platforms: 15 | - platform: root 16 | create_revision: 46787ee49c1fd80ab603f0702733edab54653aef 17 | base_revision: 46787ee49c1fd80ab603f0702733edab54653aef 18 | - platform: android 19 | create_revision: 46787ee49c1fd80ab603f0702733edab54653aef 20 | base_revision: 46787ee49c1fd80ab603f0702733edab54653aef 21 | - platform: ios 22 | create_revision: 46787ee49c1fd80ab603f0702733edab54653aef 23 | base_revision: 46787ee49c1fd80ab603f0702733edab54653aef 24 | - platform: linux 25 | create_revision: 46787ee49c1fd80ab603f0702733edab54653aef 26 | base_revision: 46787ee49c1fd80ab603f0702733edab54653aef 27 | - platform: macos 28 | create_revision: 46787ee49c1fd80ab603f0702733edab54653aef 29 | base_revision: 46787ee49c1fd80ab603f0702733edab54653aef 30 | - platform: web 31 | create_revision: 46787ee49c1fd80ab603f0702733edab54653aef 32 | base_revision: 46787ee49c1fd80ab603f0702733edab54653aef 33 | - platform: windows 34 | create_revision: 46787ee49c1fd80ab603f0702733edab54653aef 35 | base_revision: 46787ee49c1fd80ab603f0702733edab54653aef 36 | 37 | # User provided section 38 | 39 | # List of Local paths (relative to this file) that should be 40 | # ignored by the migrate tool. 41 | # 42 | # Files that are not part of the templates will be ignored by default. 43 | unmanaged_files: 44 | - 'lib/main.dart' 45 | - 'ios/Runner.xcodeproj/project.pbxproj' 46 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:chatview_connect/chatview_connect.dart'; 2 | import 'package:firebase_core/firebase_core.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | import 'app.dart'; 6 | import 'firebase_options.dart'; 7 | 8 | Future main() async { 9 | WidgetsFlutterBinding.ensureInitialized(); 10 | await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); 11 | ChatViewConnect.initialize( 12 | ChatViewCloudService.firebase, 13 | // Configuration for mapping user data fields from your backend 14 | // to the expected fields used by ChatViewConnect. 15 | // chatUserConfig: const ChatUserConfig( 16 | // idKey: 'user_id', 17 | // nameKey: 'first_name', 18 | // profilePhotoKey: 'avatar', 19 | // ), 20 | // Configuration for customizing Firebase Firestore paths and 21 | // collection names used by ChatViewConnect. 22 | // 23 | // Example: 24 | // cloudServiceConfig: FirebaseCloudConfig( 25 | // databasePathConfig: FirestoreChatDatabasePathConfig( 26 | // userCollectionPath: 'organizations/simform', 27 | // ), 28 | // collectionNameConfig: FirestoreChatCollectionNameConfig( 29 | // users: 'app_users', 30 | // ), 31 | // ), 32 | ); 33 | 34 | // Sets the current user ID for the ChatViewConnect instance 35 | // based on the authenticated user. 36 | // 37 | // This ensures that all future chat-related operations are scoped 38 | // to the currently logged-in user (e.g., fetching user-specific 39 | // chat rooms or messages). 40 | // 41 | // It should be called after confirming a valid user is logged in 42 | // For example, on Firebase through `FirebaseAuth.instance.authStateChanges()` 43 | ChatViewConnect.instance.setCurrentUserId( 44 | 'EWEsGWI7LXXBWHkCZVMh11XMOKz2', 45 | ); 46 | runApp(const ChatViewConnectExampleApp()); 47 | } 48 | -------------------------------------------------------------------------------- /example/assets/vectors/community.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/lib/modules/chat_list/widgets/user_activity_tile.dart: -------------------------------------------------------------------------------- 1 | import 'package:chatview/chatview.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class UserActivityTile extends StatelessWidget { 5 | const UserActivityTile({ 6 | required this.userName, 7 | this.userStatus = UserActiveStatus.offline, 8 | this.userTypeStatus = TypeWriterStatus.typed, 9 | this.isLast = true, 10 | super.key, 11 | }); 12 | 13 | final String userName; 14 | final UserActiveStatus userStatus; 15 | final TypeWriterStatus userTypeStatus; 16 | final bool isLast; 17 | 18 | @override 19 | Widget build(BuildContext context) { 20 | return Row( 21 | children: [ 22 | if (userStatus.isOnline) ...const [ 23 | CircleAvatar(radius: 3, backgroundColor: Colors.green), 24 | SizedBox(width: 6), 25 | ], 26 | AnimatedCrossFade( 27 | alignment: Alignment.centerLeft, 28 | duration: const Duration(milliseconds: 300), 29 | secondCurve: Curves.fastOutSlowIn, 30 | firstChild: Text( 31 | isLast ? '$userName is typing' : '$userName is typing,', 32 | maxLines: 1, 33 | overflow: TextOverflow.ellipsis, 34 | style: const TextStyle( 35 | fontSize: 13, 36 | color: Colors.black87, 37 | fontStyle: FontStyle.italic, 38 | ), 39 | ), 40 | secondChild: Text( 41 | isLast ? userName : '$userName,', 42 | maxLines: 1, 43 | overflow: TextOverflow.ellipsis, 44 | style: const TextStyle( 45 | fontSize: 13, 46 | color: Colors.black87, 47 | ), 48 | ), 49 | crossFadeState: userTypeStatus.isTyping 50 | ? CrossFadeState.showFirst 51 | : CrossFadeState.showSecond, 52 | ), 53 | ], 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /example/lib/modules/create_chat/widgets/create_chat_tile.dart: -------------------------------------------------------------------------------- 1 | import 'package:chatview/chatview.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | import '../../../widgets/chat_user_avatar.dart'; 5 | 6 | class CreateChatTile extends StatelessWidget { 7 | const CreateChatTile({ 8 | required this.username, 9 | required this.userProfile, 10 | this.oneToOneUserStatus, 11 | this.onTap, 12 | super.key, 13 | }); 14 | 15 | final String username; 16 | final String? userProfile; 17 | final VoidCallback? onTap; 18 | final UserActiveStatus? oneToOneUserStatus; 19 | 20 | @override 21 | Widget build(BuildContext context) { 22 | return GestureDetector( 23 | onTap: onTap, 24 | behavior: HitTestBehavior.translucent, 25 | child: Container( 26 | padding: const EdgeInsets.all(12), 27 | decoration: BoxDecoration( 28 | color: Colors.white, 29 | border: Border.fromBorderSide( 30 | BorderSide(color: Colors.grey.shade300), 31 | ), 32 | borderRadius: const BorderRadius.all(Radius.circular(16)), 33 | ), 34 | child: Row( 35 | children: [ 36 | SizedBox.square( 37 | dimension: 34, 38 | child: ChatUserAvatar( 39 | profileURL: userProfile, 40 | status: oneToOneUserStatus, 41 | ), 42 | ), 43 | const SizedBox(width: 12), 44 | Expanded( 45 | child: Text( 46 | username, 47 | maxLines: 1, 48 | overflow: TextOverflow.ellipsis, 49 | style: const TextStyle( 50 | fontSize: 16, 51 | fontWeight: FontWeight.w700, 52 | ), 53 | ), 54 | ), 55 | const SizedBox(width: 12), 56 | ], 57 | ), 58 | ), 59 | ); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 18 | 22 | 25 | 26 | 27 | 28 | 29 | 30 | 32 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CADisableMinimumFrameDurationOnPhone 6 | 7 | CFBundleDevelopmentRegion 8 | $(DEVELOPMENT_LANGUAGE) 9 | CFBundleDisplayName 10 | ChatView Connect Example 11 | CFBundleExecutable 12 | $(EXECUTABLE_NAME) 13 | CFBundleIdentifier 14 | $(PRODUCT_BUNDLE_IDENTIFIER) 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | example 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | $(FLUTTER_BUILD_NAME) 23 | CFBundleSignature 24 | ???? 25 | CFBundleVersion 26 | $(FLUTTER_BUILD_NUMBER) 27 | LSRequiresIPhoneOS 28 | 29 | NSMicrophoneUsageDescription 30 | This app requires Mic permission. 31 | UIApplicationSupportsIndirectInputEvents 32 | 33 | UILaunchStoryboardName 34 | LaunchScreen 35 | UIMainStoryboardFile 36 | Main 37 | UISupportedInterfaceOrientations 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationLandscapeLeft 41 | UIInterfaceOrientationLandscapeRight 42 | 43 | UISupportedInterfaceOrientations~ipad 44 | 45 | UIInterfaceOrientationPortrait 46 | UIInterfaceOrientationPortraitUpsideDown 47 | UIInterfaceOrientationLandscapeLeft 48 | UIInterfaceOrientationLandscapeRight 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /example/windows/runner/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | project(runner LANGUAGES CXX) 3 | 4 | # Define the application target. To change its name, change BINARY_NAME in the 5 | # top-level CMakeLists.txt, not the value here, or `flutter run` will no longer 6 | # work. 7 | # 8 | # Any new source files that you add to the application should be added here. 9 | add_executable(${BINARY_NAME} WIN32 10 | "flutter_window.cpp" 11 | "main.cpp" 12 | "utils.cpp" 13 | "win32_window.cpp" 14 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" 15 | "Runner.rc" 16 | "runner.exe.manifest" 17 | ) 18 | 19 | # Apply the standard set of build settings. This can be removed for applications 20 | # that need different build settings. 21 | apply_standard_settings(${BINARY_NAME}) 22 | 23 | # Add preprocessor definitions for the build version. 24 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") 25 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") 26 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") 27 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") 28 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") 29 | 30 | # Disable Windows macros that collide with C++ standard library functions. 31 | target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") 32 | 33 | # Add dependency libraries and include directories. Add any application-specific 34 | # dependencies here. 35 | target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) 36 | target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") 37 | target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") 38 | 39 | # Run the Flutter tool portions of the build. This must not be removed. 40 | add_dependencies(${BINARY_NAME} flutter_assemble) 41 | -------------------------------------------------------------------------------- /lib/src/models/user_metadata.dart: -------------------------------------------------------------------------------- 1 | import 'package:chatview_utils/chatview_utils.dart'; 2 | 3 | /// Represents a user's status data model. 4 | /// 5 | /// The [UserMetadata] class is used to manage and store a user's online/offline status 6 | /// within a user chat system. It provides methods for JSON serialization, 7 | /// deserialization, and copying instances with updated fields. 8 | class UserMetadata { 9 | /// Constructs a [UserMetadata] instance. 10 | /// 11 | /// **Parameters:** 12 | /// - (required): [userActiveStatus] represents the online/offline status of the user. 13 | const UserMetadata({required this.userActiveStatus}); 14 | 15 | /// Creates a [UserMetadata] instance from a JSON map. 16 | /// 17 | /// **Parameters:** 18 | /// - (required): [json] is a map containing the serialized data. 19 | factory UserMetadata.fromJson(Map json) { 20 | return UserMetadata( 21 | userActiveStatus: UserActiveStatusExtension.parse( 22 | json['user_active_status'].toString(), 23 | ), 24 | ); 25 | } 26 | 27 | /// The online/offline status of the user. 28 | /// 29 | /// Possible values include statuses such as online or offline. 30 | final UserActiveStatus userActiveStatus; 31 | 32 | /// Converts the [UserMetadata] instance to a JSON map. 33 | Map toJson() { 34 | return {'user_active_status': userActiveStatus.name}; 35 | } 36 | 37 | /// Creates a copy of the current [UserMetadata] instance with 38 | /// updated fields. 39 | /// 40 | /// Any field not provided will retain its current value. 41 | /// 42 | /// **Parameters:** 43 | /// - (optional): [userActiveStatus] is the updated online/offline status. 44 | /// 45 | /// Returns a new [UserMetadata] instance with the specified updates. 46 | UserMetadata copyWith({UserActiveStatus? userActiveStatus}) { 47 | return UserMetadata( 48 | userActiveStatus: userActiveStatus ?? this.userActiveStatus, 49 | ); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # Description 2 | 3 | 9 | 10 | ## Checklist 11 | 12 | 16 | 17 | - [ ] The title of my PR starts with a [Conventional Commit] prefix (`fix:`, `feat:`, `docs:` etc). 18 | - [ ] I have followed the [Contributor Guide] when preparing my PR. 19 | - [ ] I have updated/added tests for ALL new/updated/fixed functionality. 20 | - [ ] I have updated/added relevant documentation in `docs` and added dartdoc comments with `///`. 21 | - [ ] I have updated/added relevant examples in `examples` or `docs`. 22 | 23 | ## Breaking Change? 24 | 25 | 37 | 38 | - [ ] Yes, this PR is a breaking change. 39 | - [ ] No, this PR is not a breaking change. 40 | 41 | ## Related Issues 42 | 43 | 47 | 48 | 49 | 50 | [Contributor Guide]: https://github.com/SimformSolutionsPvtLtd/chatview_connect/blob/master/CONTRIBUTING.md 51 | 52 | [Conventional Commit]: https://www.conventionalcommits.org 53 | -------------------------------------------------------------------------------- /example/windows/runner/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | void CreateAndAttachConsole() { 11 | if (::AllocConsole()) { 12 | FILE *unused; 13 | if (freopen_s(&unused, "CONOUT$", "w", stdout)) { 14 | _dup2(_fileno(stdout), 1); 15 | } 16 | if (freopen_s(&unused, "CONOUT$", "w", stderr)) { 17 | _dup2(_fileno(stdout), 2); 18 | } 19 | std::ios::sync_with_stdio(); 20 | FlutterDesktopResyncOutputStreams(); 21 | } 22 | } 23 | 24 | std::vector GetCommandLineArguments() { 25 | // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. 26 | int argc; 27 | wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); 28 | if (argv == nullptr) { 29 | return std::vector(); 30 | } 31 | 32 | std::vector command_line_arguments; 33 | 34 | // Skip the first argument as it's the binary name. 35 | for (int i = 1; i < argc; i++) { 36 | command_line_arguments.push_back(Utf8FromUtf16(argv[i])); 37 | } 38 | 39 | ::LocalFree(argv); 40 | 41 | return command_line_arguments; 42 | } 43 | 44 | std::string Utf8FromUtf16(const wchar_t* utf16_string) { 45 | if (utf16_string == nullptr) { 46 | return std::string(); 47 | } 48 | int target_length = ::WideCharToMultiByte( 49 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, 50 | -1, nullptr, 0, nullptr, nullptr) 51 | -1; // remove the trailing null character 52 | int input_length = (int)wcslen(utf16_string); 53 | std::string utf8_string; 54 | if (target_length <= 0 || target_length > utf8_string.max_size()) { 55 | return utf8_string; 56 | } 57 | utf8_string.resize(target_length); 58 | int converted_length = ::WideCharToMultiByte( 59 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, 60 | input_length, utf8_string.data(), target_length, nullptr, nullptr); 61 | if (converted_length == 0) { 62 | return std::string(); 63 | } 64 | return utf8_string; 65 | } 66 | -------------------------------------------------------------------------------- /example/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | example 33 | 34 | 35 | 39 | 40 | 41 | 42 | 43 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /lib/src/models/chat_room_display_metadata.dart: -------------------------------------------------------------------------------- 1 | /// Represents metadata for a chat room, supporting both one-to-one and 2 | /// group chats. 3 | /// 4 | /// This model provides details about the chat, including its name and 5 | /// profile picture. 6 | /// - For one-to-one chats, it retrieves the other user's name and 7 | /// profile picture. 8 | /// - For group chats, it includes the group name and profile photo. 9 | /// 10 | /// The properties dynamically determine the appropriate values based 11 | /// on the chat type. 12 | class ChatRoomDisplayMetadata { 13 | /// Creates an instance of [ChatRoomDisplayMetadata]. 14 | /// 15 | /// **Parameters:** 16 | /// - (required): [chatName] represents the name of the chat. 17 | /// - In one-to-one chats, this is the name of the other user. 18 | /// - In group chats, this is the group name. If unavailable, 19 | /// a fallback name is used. 20 | /// - (optional): [chatProfilePhoto] represents the chat profile picture URL. 21 | /// - In one-to-one chats, this is the profile picture of the other user. 22 | /// - In group chats, this is the group photo URL, if available. 23 | const ChatRoomDisplayMetadata({ 24 | required this.chatName, 25 | this.chatProfilePhoto, 26 | }); 27 | 28 | /// The name of the chat. 29 | /// 30 | /// - For one-to-one chats, this is the name of the other user. 31 | /// If `null`, "Unknown User" is returned. 32 | /// - For group chats, this is the group name. If unavailable, 33 | /// a comma-separated list of user names is used. 34 | /// If both the group name and user names are unavailable, 35 | /// "Unknown Group" is returned. 36 | final String chatName; 37 | 38 | /// The profile picture URL of the chat. 39 | /// 40 | /// - For one-to-one chats, this is the profile picture of the other user, 41 | /// if available. 42 | /// - For group chats, this is the group photo URL, if available. 43 | final String? chatProfilePhoto; 44 | 45 | @override 46 | String toString() => ''' 47 | ChatRoomDisplayMetadata( 48 | 'chatName': $chatName, 49 | 'chatProfilePhoto': $chatProfilePhoto, 50 | )'''; 51 | } 52 | -------------------------------------------------------------------------------- /lib/src/models/config/firebase/firestore_chat_collection_name_config.dart: -------------------------------------------------------------------------------- 1 | import '../../../database/firebase/chatview_firestore_path.dart'; 2 | import '../../../extensions.dart'; 3 | 4 | /// This allows users to customize the collection names used in Firestore 5 | /// if they prefer different names than the default. 6 | /// 7 | /// Example usage: 8 | /// ```dart 9 | /// final config = FirestoreChatCollectionNameConfig( 10 | /// messages: 'custom_messages', 11 | /// users: 'custom_users', 12 | /// userChats: 'custom_user_chats', 13 | /// chats: 'custom_chats', 14 | /// ); 15 | /// ``` 16 | /// 17 | /// If a value is `null`, the default collection name will be used. 18 | class FirestoreChatCollectionNameConfig { 19 | /// Creates a configuration for firestore collection names. 20 | /// 21 | /// This allows you to customize the names of the Firestore collections 22 | /// used for chat-related data. 23 | /// 24 | /// **Parameters:** 25 | /// - [users]: Collection name for storing user documents. 26 | /// - [chats]: Collection name for storing chat documents. 27 | /// - [messages]: Collection name for storing message documents. 28 | /// - [userChats]: Collection name for mapping users to chats. 29 | FirestoreChatCollectionNameConfig({ 30 | this.users = ChatViewFireStorePath.users, 31 | this.chats = ChatViewFireStorePath.chats, 32 | this.messages = ChatViewFireStorePath.messages, 33 | this.userChats = ChatViewFireStorePath.userChats, 34 | }) : assert( 35 | users.isValidFirestoreCollectionName && 36 | chats.isValidFirestoreCollectionName && 37 | messages.isValidFirestoreCollectionName && 38 | userChats.isValidFirestoreCollectionName, 39 | 'a collectionPath path must be a non-empty string or a must not contain "//" or "/"', 40 | ); 41 | 42 | /// Collection name for storing messages. 43 | final String messages; 44 | 45 | /// Collection name for storing user data. 46 | final String users; 47 | 48 | /// Collection name for storing user-to-chat relationships. 49 | final String userChats; 50 | 51 | /// Collection name for storing chat details inside `userChats`. 52 | final String chats; 53 | } 54 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "com.android.application" 3 | id 'com.google.gms.google-services' 4 | id "kotlin-android" 5 | id "dev.flutter.flutter-gradle-plugin" 6 | } 7 | 8 | def localProperties = new Properties() 9 | def localPropertiesFile = rootProject.file('local.properties') 10 | if (localPropertiesFile.exists()) { 11 | localPropertiesFile.withReader('UTF-8') { reader -> 12 | localProperties.load(reader) 13 | } 14 | } 15 | 16 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 17 | if (flutterVersionCode == null) { 18 | flutterVersionCode = '1' 19 | } 20 | 21 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 22 | if (flutterVersionName == null) { 23 | flutterVersionName = '1.0' 24 | } 25 | 26 | android { 27 | namespace "com.simform.chatview_connect" 28 | compileSdkVersion 35 29 | ndkVersion flutter.ndkVersion 30 | 31 | compileOptions { 32 | sourceCompatibility JavaVersion.VERSION_1_8 33 | targetCompatibility JavaVersion.VERSION_1_8 34 | } 35 | 36 | kotlinOptions { 37 | jvmTarget = '1.8' 38 | } 39 | 40 | sourceSets { 41 | main.java.srcDirs += 'src/main/kotlin' 42 | } 43 | 44 | defaultConfig { 45 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 46 | applicationId "com.simform.chatview_connect" 47 | // You can update the following values to match your application needs. 48 | // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. 49 | minSdkVersion 23 50 | targetSdkVersion flutter.targetSdkVersion 51 | versionCode flutterVersionCode.toInteger() 52 | versionName flutterVersionName 53 | } 54 | 55 | buildTypes { 56 | release { 57 | // TODO: Add your own signing config for the release build. 58 | // Signing with the debug keys for now, so `flutter run --release` works. 59 | signingConfig signingConfigs.debug 60 | } 61 | } 62 | } 63 | 64 | flutter { 65 | source '../..' 66 | } 67 | 68 | dependencies {} 69 | -------------------------------------------------------------------------------- /lib/src/storage/storage_service.dart: -------------------------------------------------------------------------------- 1 | import 'package:chatview_utils/chatview_utils.dart'; 2 | 3 | /// Defined different methods to interact with a cloud storage service. 4 | abstract interface class StorageService { 5 | const StorageService._(); 6 | 7 | /// Uploads an image or voice media from a [Message] to Cloud Storage. 8 | /// 9 | /// The file is stored in the specified directory path with a generated 10 | /// or provided file name. 11 | /// 12 | /// Once the upload is successful, the method returns the media's URL. 13 | /// 14 | /// **Parameters:** 15 | /// - (required): [retry] The number of times to retry the upload in case of 16 | /// failure. 17 | /// - (required): [message] Containing the media to upload. 18 | /// - (required): [chatId] The unique identifier of the chat where the 19 | /// media belongs. 20 | /// - (optional): [path] Specifies the directory path in Cloud Storage 21 | /// where the file will be stored. 22 | /// - (optional): [fileName] Specifies the name of the media file. 23 | /// (including the file's extension) 24 | /// 25 | /// **Returns:** A [Future] that resolves to the download URL of the uploaded 26 | /// media, or `null` if the upload fails. 27 | /// 28 | /// {@macro chatview_connect.StorageService.getFileName} 29 | Future uploadMedia({ 30 | required int retry, 31 | required Message message, 32 | required String chatId, 33 | String? path, 34 | String? fileName, 35 | }); 36 | 37 | /// Deletes a media from Cloud Storage. 38 | /// 39 | /// **Parameters:** 40 | /// - (required): The [Message] containing the media to be deleted. 41 | /// 42 | /// **Returns:** A [Future] that resolves to `true` 43 | /// if the media is successfully deleted, otherwise `false`. 44 | Future deleteMedia(Message message); 45 | 46 | /// Deletes all documents related to the specified chat, including any images 47 | /// or voice messages shared within the chat. 48 | /// 49 | /// **Parameters:** 50 | /// - (required): [chatId] The unique identifier of the chat whose documents 51 | /// will be deleted. 52 | /// 53 | /// Returns a true/false indicating whether the deletion was successful. 54 | Future deleteAllMedia(String chatId); 55 | } 56 | -------------------------------------------------------------------------------- /lib/src/models/config/firebase/firestore_chat_database_path_config.dart: -------------------------------------------------------------------------------- 1 | import '../../../extensions.dart'; 2 | 3 | /// {@template chatview_connect.FirestoreChatDatabasePathConfig} 4 | /// Configuration class for defining database paths for chat-related data. 5 | /// 6 | /// This class allows customization of Firestore database paths for 7 | /// storing user data, ensuring efficient organization of collections. 8 | /// 9 | /// ### Example Usage: 10 | /// ```dart 11 | /// ChatViewConnect.initialize( 12 | /// ChatViewCloudService.firebase, 13 | /// cloudServiceConfig: FirebaseCloudConfig( 14 | /// databasePathConfig: FirestoreChatDatabasePathConfig( 15 | /// userCollectionPath: 'organizations/simform', 16 | /// ), 17 | /// ), 18 | /// ); 19 | /// ``` 20 | /// If [userCollectionPath] is not specified, 21 | /// the default top-level `users` collection is used. 22 | /// {@endtemplate} 23 | final class FirestoreChatDatabasePathConfig { 24 | /// Creates a new instance of [FirestoreChatDatabasePathConfig]. 25 | /// 26 | /// **Parameters:** 27 | /// - (optional) [userCollectionPath] The Firestore collection path for 28 | /// retrieving user data. 29 | /// If omitted, defaults to the top-level `users` collection. 30 | /// 31 | /// {@macro chatview_connect.FirestoreChatDatabasePathConfig.userCollectionPath} 32 | FirestoreChatDatabasePathConfig({this.userCollectionPath}) 33 | : assert( 34 | userCollectionPath == null || 35 | userCollectionPath.isValidFirestoreDocumentName, 36 | 'Chat Collection Path should not have the nested collection', 37 | ); 38 | 39 | /// {@template chatview_connect.FirestoreChatDatabasePathConfig.userCollectionPath} 40 | /// The collection path where user data is stored. 41 | /// 42 | /// If the 'users' collection is nested within other collections, specify 43 | /// the parent path excluding 'users'. For example, if the user collection 44 | /// is located at: 45 | /// 46 | /// **Firestore structure:** 47 | /// `organizations/org123/users` 48 | /// 49 | /// Then specify: 50 | /// 51 | /// ```dart 52 | /// userCollectionPath: 'organizations/org123' 53 | /// ``` 54 | /// {@endtemplate} 55 | final String? userCollectionPath; 56 | } 57 | -------------------------------------------------------------------------------- /lib/src/models/user_chat_metadata.dart: -------------------------------------------------------------------------------- 1 | /// Represents a user's chat conversation details. 2 | /// 3 | /// This data model is used to manage and serialize/deserialize chat conversations. 4 | /// The `userId` is used in one-to-one chats to uniquely identify that 5 | /// the chat has already been created. For group chats, 6 | /// `userId` field will be empty. 7 | /// 8 | /// The [UserChatMetadata] class is essential for handling individual 9 | /// or group chat conversations. 10 | final class UserChatMetadata { 11 | /// Creates a [UserChatMetadata] instance with the specified [userId]. 12 | /// 13 | /// **Parameters:** 14 | /// - (required): [userId] The unique identifier of the user 15 | /// associated with the chat conversation. 16 | /// 17 | /// In a one-to-one chat, the `userId` uniquely identifies that 18 | /// the chat has already been created. For group chats, 19 | /// the `userId` will be empty. 20 | const UserChatMetadata({this.userId}); 21 | 22 | /// Creates a [UserChatMetadata] instance from a JSON object. 23 | /// 24 | /// - [json]: A [Map] containing the chat conversation data. 25 | factory UserChatMetadata.fromJson(Map json) { 26 | return UserChatMetadata(userId: json['user_id'].toString()); 27 | } 28 | 29 | /// The unique identifier of the other user associated with 30 | /// the chat conversation. 31 | /// 32 | /// This value is used to identify a one-to-one chat already created or not. 33 | /// For group chats, this value is empty. 34 | final String? userId; 35 | 36 | /// Converts the [UserChatMetadata] instance into a JSON object. 37 | /// 38 | /// Returns a [Map] with the `user_id` field. 39 | Map toJson() { 40 | return { 41 | if (userId?.isNotEmpty ?? false) 'user_id': userId, 42 | }; 43 | } 44 | 45 | /// Creates a copy of the current [UserChatMetadata] with 46 | /// updated fields. 47 | /// 48 | /// - [userId]: The new user ID. 49 | /// Defaults to the current [userId] if not provided. 50 | /// 51 | /// Returns a new [UserChatMetadata] instance with the updated values. 52 | UserChatMetadata copyWith({String? userId}) { 53 | return UserChatMetadata(userId: userId ?? this.userId); 54 | } 55 | 56 | @override 57 | String toString() => 'UserChatMetadata(${toJson()})'; 58 | } 59 | -------------------------------------------------------------------------------- /example/lib/models/chat_list_theme.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class ChatListTheme { 4 | const ChatListTheme({ 5 | required this.textColor, 6 | required this.iconColor, 7 | required this.searchBg, 8 | required this.searchText, 9 | required this.lastMessageText, 10 | required this.backgroundColor, 11 | required this.secondaryBg, 12 | required this.iconButton, 13 | required this.divider, 14 | required this.floatingButton, 15 | required this.selectedChip, 16 | required this.selectedChipBg, 17 | this.chipBg = Colors.transparent, 18 | this.chipText = Colors.black, 19 | }); 20 | 21 | final Color textColor; 22 | final Color iconColor; 23 | final Color searchBg; 24 | final Color searchText; 25 | final Color lastMessageText; 26 | final Color backgroundColor; 27 | final Color secondaryBg; 28 | final Color iconButton; 29 | final Color divider; 30 | final Color floatingButton; 31 | final Color selectedChip; 32 | final Color selectedChipBg; 33 | final Color chipBg; 34 | final Color chipText; 35 | 36 | static const ChatListTheme uiTwoDark = ChatListTheme( 37 | iconColor: Colors.white, 38 | iconButton: Color(0xff222222), 39 | textColor: Colors.white, 40 | searchBg: Color(0xff222222), 41 | searchText: Color(0xff969494), 42 | lastMessageText: Color(0xff74787F), 43 | backgroundColor: Color(0xff0A0A0A), 44 | secondaryBg: Color(0xff26292E), 45 | divider: Color(0xff212121), 46 | floatingButton: Color(0xFF242626), 47 | selectedChipBg: Color(0xFF1A342A), 48 | selectedChip: Color(0xFFE0FCD6), 49 | chipBg: Color(0xFF161717), 50 | chipText: Color(0xFF969595), 51 | ); 52 | 53 | static const ChatListTheme uiTwoLight = ChatListTheme( 54 | iconColor: Colors.black, 55 | iconButton: Color(0x080A0A0A), 56 | textColor: Colors.black, 57 | searchBg: Color(0xFFF4F4F4), 58 | searchText: Color(0xff767779), 59 | lastMessageText: Colors.black, 60 | backgroundColor: Color(0xffFEFFFE), 61 | secondaryBg: Color(0xffF3F5F7), 62 | divider: Color(0x33000000), 63 | floatingButton: Color(0xFFF5F2EB), 64 | selectedChipBg: Color(0xFFD0FECF), 65 | selectedChip: Color(0xFF15603E), 66 | chipBg: Color(0xFFF4F4F4), 67 | chipText: Color(0xFF767779), 68 | ); 69 | } 70 | -------------------------------------------------------------------------------- /example/windows/runner/flutter_window.cpp: -------------------------------------------------------------------------------- 1 | #include "flutter_window.h" 2 | 3 | #include 4 | 5 | #include "flutter/generated_plugin_registrant.h" 6 | 7 | FlutterWindow::FlutterWindow(const flutter::DartProject& project) 8 | : project_(project) {} 9 | 10 | FlutterWindow::~FlutterWindow() {} 11 | 12 | bool FlutterWindow::OnCreate() { 13 | if (!Win32Window::OnCreate()) { 14 | return false; 15 | } 16 | 17 | RECT frame = GetClientArea(); 18 | 19 | // The size here must match the window dimensions to avoid unnecessary surface 20 | // creation / destruction in the startup path. 21 | flutter_controller_ = std::make_unique( 22 | frame.right - frame.left, frame.bottom - frame.top, project_); 23 | // Ensure that basic setup of the controller was successful. 24 | if (!flutter_controller_->engine() || !flutter_controller_->view()) { 25 | return false; 26 | } 27 | RegisterPlugins(flutter_controller_->engine()); 28 | SetChildContent(flutter_controller_->view()->GetNativeWindow()); 29 | 30 | flutter_controller_->engine()->SetNextFrameCallback([&]() { 31 | this->Show(); 32 | }); 33 | 34 | // Flutter can complete the first frame before the "show window" callback is 35 | // registered. The following call ensures a frame is pending to ensure the 36 | // window is shown. It is a no-op if the first frame hasn't completed yet. 37 | flutter_controller_->ForceRedraw(); 38 | 39 | return true; 40 | } 41 | 42 | void FlutterWindow::OnDestroy() { 43 | if (flutter_controller_) { 44 | flutter_controller_ = nullptr; 45 | } 46 | 47 | Win32Window::OnDestroy(); 48 | } 49 | 50 | LRESULT 51 | FlutterWindow::MessageHandler(HWND hwnd, UINT const message, 52 | WPARAM const wparam, 53 | LPARAM const lparam) noexcept { 54 | // Give Flutter, including plugins, an opportunity to handle window messages. 55 | if (flutter_controller_) { 56 | std::optional result = 57 | flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, 58 | lparam); 59 | if (result) { 60 | return *result; 61 | } 62 | } 63 | 64 | switch (message) { 65 | case WM_FONTCHANGE: 66 | flutter_controller_->engine()->ReloadSystemFonts(); 67 | break; 68 | } 69 | 70 | return Win32Window::MessageHandler(hwnd, message, wparam, lparam); 71 | } 72 | -------------------------------------------------------------------------------- /example/lib/modules/chat_detail/widgets/chat_room_user_acitivity_tile.dart: -------------------------------------------------------------------------------- 1 | import 'package:chatview/chatview.dart'; 2 | import 'package:chatview_connect/chatview_connect.dart'; 3 | import 'package:flutter/foundation.dart'; 4 | import 'package:flutter/material.dart'; 5 | 6 | import '../../chat_list/widgets/user_activity_tile.dart'; 7 | 8 | class ChatRoomUserActivityTile extends StatelessWidget { 9 | const ChatRoomUserActivityTile({ 10 | required this.usersActivitiesNotifier, 11 | required this.chatController, 12 | required this.chatRoomType, 13 | super.key, 14 | }); 15 | 16 | final ChatManager chatController; 17 | final ChatRoomType chatRoomType; 18 | final ValueListenable> 19 | usersActivitiesNotifier; 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | return ValueListenableBuilder( 24 | valueListenable: usersActivitiesNotifier, 25 | builder: (_, usersActivity, __) { 26 | final otherUsers = chatController.otherActiveUsers; 27 | final otherUsersLength = otherUsers.length; 28 | final otherUsersLastIndex = otherUsersLength - 1; 29 | return Row( 30 | children: List.generate( 31 | otherUsersLength, 32 | (index) { 33 | final user = otherUsers[index]; 34 | final userActivity = usersActivity[user.id]; 35 | final typeStatus = 36 | userActivity?.typingStatus ?? TypeWriterStatus.typed; 37 | final status = 38 | userActivity?.userActiveStatus ?? UserActiveStatus.offline; 39 | return switch (chatRoomType) { 40 | ChatRoomType.oneToOne when status.isOnline => 41 | const UserActivityTile( 42 | userName: 'Online', 43 | userStatus: UserActiveStatus.online, 44 | ), 45 | ChatRoomType.group => Padding( 46 | padding: const EdgeInsets.only(right: 4), 47 | child: UserActivityTile( 48 | userStatus: status, 49 | userName: user.name, 50 | userTypeStatus: typeStatus, 51 | isLast: index == otherUsersLastIndex, 52 | ), 53 | ), 54 | _ => const SizedBox.shrink(), 55 | }; 56 | }, 57 | ), 58 | ); 59 | }, 60 | ); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /example/assets/vectors/settings.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /lib/src/models/config/chat_controller_config.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../chat_room_display_metadata.dart'; 4 | import '../chat_room_metadata.dart'; 5 | import '../chat_room_participant.dart'; 6 | 7 | /// Configuration for managing chat connections and real-time updates. 8 | class ChatControllerConfig { 9 | /// Creates a configuration for the connection manager. 10 | /// 11 | /// **Parameters:** 12 | /// 13 | /// - (required): [syncOtherUsersInfo] Determines whether the chat controller 14 | /// should listen for real-time updates to user information, 15 | /// such as profile picture and username changes. 16 | /// - If `true`, user details (e.g., username, profile picture) will be 17 | /// dynamically fetched and updated. 18 | /// - If `false`, no user data will be fetched. 19 | /// 20 | /// - (optional): [chatRoomMetadata] Provides details about the chat room, 21 | /// including participants and other metadata. This callback receives an 22 | /// instance of [ChatRoomMetadata] containing relevant chat room 23 | /// information. 24 | /// 25 | /// - (optional): [onUsersActivityChange] Listens for updates on user 26 | /// activity within the chat room, such as online status and typing 27 | /// indicators. This callback receives a map of user IDs to their 28 | /// corresponding [ChatRoomParticipant] data. 29 | /// 30 | /// - (optional): [onChatRoomDisplayMetadataChange] Listens for real-time 31 | /// updates to chat room metadata, including the chat name and profile photo. 32 | /// - For **group chats**, this callback receives an instance of 33 | /// [ChatRoomDisplayMetadata] with updated details. 34 | /// - For **one-to-one chats**, `ChatRoomMetadata` is still provided, 35 | /// but updates are based on the other user's profile. 36 | /// 37 | /// **Note:** For one-to-one chats, setting the typing indicator value from 38 | /// the chat controller is handled internally. 39 | const ChatControllerConfig({ 40 | required this.syncOtherUsersInfo, 41 | this.chatRoomMetadata, 42 | this.onUsersActivityChange, 43 | this.onChatRoomDisplayMetadataChange, 44 | }); 45 | 46 | /// Whether to sync other users' information. 47 | final bool syncOtherUsersInfo; 48 | 49 | /// Callback to receive chat room participants' details. 50 | final ValueSetter? chatRoomMetadata; 51 | 52 | /// Callback triggered when users' activity status (e.g., online/offline) changes. 53 | final ValueSetter>? onUsersActivityChange; 54 | 55 | /// Callback triggered when chat room metadata (e.g., name, profile) updates. 56 | final ValueSetter? onChatRoomDisplayMetadataChange; 57 | } 58 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # ChatView Connect Example 2 | 3 | A Flutter app demonstrating the use of `chatview_connect` — a wrapper around the `chatview` package that supports multiple cloud backends. This example focuses on Firebase integration. 4 | 5 | ### Prerequisites 6 | 7 | 1. [Flutter SDK](https://docs.flutter.dev/release/archive#stable-channel) (version 3.22.0 or higher) 8 | 2. [Firebase project](https://console.firebase.google.com/) 9 | 10 | ### Firebase Setup 11 | 12 | 1. **Create a Firebase project**: 13 | - Go to [Firebase Console](https://console.firebase.google.com/) 14 | - Create a new project or use an existing one 15 | 16 | 2. **Add Firebase to your Flutter app**: 17 | - Register your app with Firebase (Android, iOS, Web and Others) 18 | - Download the configuration files: 19 | - `google-services.json` for Android 20 | - `GoogleService-Info.plist` for iOS, MacOS 21 | - Configure web, windows as needed 22 | 23 | 3. **Enable Firestore Database and Storage**: 24 | - In Firebase Console, enable [Cloud Firestore](https://console.firebase.google.com/project/_/firestore/?_gl=1*1df50if*_ga*MjA5MDI2ODM5My4xNzEyNTY1Njkx*_ga_CW55HF8NVT*czE3NDcxOTc5OTckbzExJGcxJHQxNzQ3MjAyNzkwJGozMCRsMCRoMA..) 25 | - Set up Firestore security rules (see [documentation](https://simform-flutter-packages.web.app/chatViewConnect/firebase-security-rules) for reference rules) 26 | - Enable [Firebase Storage](https://console.firebase.google.com/project/_/storage/?_gl=1*10n1fix*_ga*MjA5MDI2ODM5My4xNzEyNTY1Njkx*_ga_CW55HF8NVT*czE3NDcxOTc5OTckbzExJGcxJHQxNzQ3MjAzMTkyJGo1MiRsMCRoMA..) for handling media files 27 | - Configure storage security rules (see [documentation](https://simform-flutter-packages.web.app/chatViewConnect/firebase-security-rules) for reference rules) 28 | 29 | ### Running the Example App 30 | 31 | 1. Clone the [repository](https://github.com/SimformSolutionsPvtLtd/chatview_connect.git) 32 | 2. Navigate to the example directory (e.g. in terminal, `cd example`) 33 | 3. Configure Firebase: 34 | ```bash 35 | flutterfire configure 36 | ``` 37 | 4. Install dependencies: 38 | ```bash 39 | flutter pub get 40 | ``` 41 | 5. Run the app: 42 | ```bash 43 | flutter run 44 | ``` 45 | 46 | ## Code Structure 47 | 48 | The example app follows a modular structure: 49 | 50 | - `main.dart`: Entry point with Firebase initialization and ChatViewConnect setup 51 | - `modules/`: Feature-based screens and components 52 | - `chat_list/`: Chat conversations list screen 53 | - `chat_detail/`: Individual chat screen 54 | - `create_chat/`: Screen for creating new chats 55 | 56 | ## Additional Resources 57 | 58 | - [ChatView Connect Documentation](https://simform-flutter-packages.web.app/chatViewConnect) 59 | - [Firebase Documentation](https://firebase.google.com/docs) 60 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .build/ 9 | .buildlog/ 10 | .history 11 | .svn/ 12 | .swiftpm/ 13 | migrate_working_dir/ 14 | 15 | # IntelliJ related 16 | *.iml 17 | *.ipr 18 | *.iws 19 | .idea/ 20 | 21 | # The .vscode folder contains launch configuration and tasks you configure in 22 | # VS Code which you may wish to be included in version control, so this line 23 | # is commented out by default. 24 | .vscode/ 25 | 26 | # Flutter/Dart/Pub related 27 | **/doc/api/ 28 | **/ios/Flutter/.last_build_id 29 | .dart_tool/ 30 | .flutter-plugins 31 | .flutter-plugins-dependencies 32 | .pub-cache/ 33 | .pub/ 34 | /build/ 35 | 36 | # Android related 37 | **/android/**/gradle-wrapper.jar 38 | **/android/.gradle 39 | **/android/captures/ 40 | **/android/gradlew 41 | **/android/gradlew.bat 42 | **/android/local.properties 43 | **/android/**/GeneratedPluginRegistrant.java 44 | 45 | # iOS/XCode related 46 | **/ios/**/*.mode1v3 47 | **/ios/**/*.mode2v3 48 | **/ios/**/*.moved-aside 49 | **/ios/**/*.pbxuser 50 | **/ios/**/*.perspectivev3 51 | **/ios/**/*sync/ 52 | **/ios/**/.sconsign.dblite 53 | **/ios/**/.tags* 54 | **/ios/**/.vagrant/ 55 | **/ios/**/DerivedData/ 56 | **/ios/**/Icon? 57 | **/ios/**/Pods/ 58 | **/ios/**/.symlinks/ 59 | **/ios/**/profile 60 | **/ios/**/xcuserdata 61 | **/ios/.generated/ 62 | **/ios/Flutter/App.framework 63 | **/ios/Flutter/Flutter.framework 64 | **/ios/Flutter/Generated.xcconfig 65 | **/ios/Flutter/app.flx 66 | **/ios/Flutter/app.zip 67 | **/ios/Flutter/flutter_assets/ 68 | **/ios/ServiceDefinitions.json 69 | **/ios/Runner/GeneratedPluginRegistrant.* 70 | /ios/Flutter/.last_build_id 71 | # Exceptions to above rules. 72 | !**/ios/**/default.mode1v3 73 | !**/ios/**/default.mode2v3 74 | !**/ios/**/default.pbxuser 75 | !**/ios/**/default.perspectivev3 76 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 77 | /ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings 78 | pubspec.lock 79 | 80 | # Windows project. 81 | windows/flutter/generated_plugin_registrant.cc 82 | windows/flutter/generated_plugin_registrant.h 83 | windows/flutter/generated_plugins.cmake 84 | 85 | # Linux Project 86 | linux/flutter/generated_plugin_registrant.cc 87 | linux/flutter/generated_plugin_registrant.h 88 | linux/flutter/generated_plugins.cmake 89 | 90 | # macOS Project 91 | macos/Flutter/ephemeral/Flutter-Generated.xcconfig 92 | macos/Flutter/ephemeral/flutter_export_environment.sh 93 | macos/Flutter/GeneratedPluginRegistrant.swift 94 | 95 | # Symbolication related 96 | app.*.symbols 97 | 98 | # Obfuscation related 99 | app.*.map.json 100 | 101 | # Android Studio will place build artifacts here 102 | /android/app/debug 103 | /android/app/profile 104 | /android/app/release 105 | 106 | **/firebase.json 107 | -------------------------------------------------------------------------------- /example/linux/flutter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This file controls Flutter-level build steps. It should not be edited. 2 | cmake_minimum_required(VERSION 3.10) 3 | 4 | set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") 5 | 6 | # Configuration provided via flutter tool. 7 | include(${EPHEMERAL_DIR}/generated_config.cmake) 8 | 9 | # TODO: Move the rest of this into files in ephemeral. See 10 | # https://github.com/flutter/flutter/issues/57146. 11 | 12 | # Serves the same purpose as list(TRANSFORM ... PREPEND ...), 13 | # which isn't available in 3.10. 14 | function(list_prepend LIST_NAME PREFIX) 15 | set(NEW_LIST "") 16 | foreach(element ${${LIST_NAME}}) 17 | list(APPEND NEW_LIST "${PREFIX}${element}") 18 | endforeach(element) 19 | set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) 20 | endfunction() 21 | 22 | # === Flutter Library === 23 | # System-level dependencies. 24 | find_package(PkgConfig REQUIRED) 25 | pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) 26 | pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) 27 | pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) 28 | 29 | set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") 30 | 31 | # Published to parent scope for install step. 32 | set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) 33 | set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) 34 | set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) 35 | set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) 36 | 37 | list(APPEND FLUTTER_LIBRARY_HEADERS 38 | "fl_basic_message_channel.h" 39 | "fl_binary_codec.h" 40 | "fl_binary_messenger.h" 41 | "fl_dart_project.h" 42 | "fl_engine.h" 43 | "fl_json_message_codec.h" 44 | "fl_json_method_codec.h" 45 | "fl_message_codec.h" 46 | "fl_method_call.h" 47 | "fl_method_channel.h" 48 | "fl_method_codec.h" 49 | "fl_method_response.h" 50 | "fl_plugin_registrar.h" 51 | "fl_plugin_registry.h" 52 | "fl_standard_message_codec.h" 53 | "fl_standard_method_codec.h" 54 | "fl_string_codec.h" 55 | "fl_value.h" 56 | "fl_view.h" 57 | "flutter_linux.h" 58 | ) 59 | list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") 60 | add_library(flutter INTERFACE) 61 | target_include_directories(flutter INTERFACE 62 | "${EPHEMERAL_DIR}" 63 | ) 64 | target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") 65 | target_link_libraries(flutter INTERFACE 66 | PkgConfig::GTK 67 | PkgConfig::GLIB 68 | PkgConfig::GIO 69 | ) 70 | add_dependencies(flutter flutter_assemble) 71 | 72 | # === Flutter tool backend === 73 | # _phony_ is a non-existent file to force this command to run every time, 74 | # since currently there's no way to get a full input/output list from the 75 | # flutter tool. 76 | add_custom_command( 77 | OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} 78 | ${CMAKE_CURRENT_BINARY_DIR}/_phony_ 79 | COMMAND ${CMAKE_COMMAND} -E env 80 | ${FLUTTER_TOOL_ENVIRONMENT} 81 | "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" 82 | ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} 83 | VERBATIM 84 | ) 85 | add_custom_target(flutter_assemble DEPENDS 86 | "${FLUTTER_LIBRARY}" 87 | ${FLUTTER_LIBRARY_HEADERS} 88 | ) 89 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /example/lib/modules/chat_detail/widgets/chat_detail_screen_app_bar.dart: -------------------------------------------------------------------------------- 1 | import 'package:chatview/chatview.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | import '../../../values/app_colors.dart'; 5 | import '../../../widgets/chat_user_avatar.dart'; 6 | import '../../../widgets/user_stacked_profile.dart'; 7 | 8 | class ChatDetailScreenAppBar extends StatelessWidget { 9 | const ChatDetailScreenAppBar({ 10 | required this.chatName, 11 | required this.usersProfileURLs, 12 | required this.chatProfileUrl, 13 | this.oneToOneUserStatus, 14 | this.description, 15 | this.descriptionWidget, 16 | this.actions = const [], 17 | super.key, 18 | }); 19 | 20 | final String chatName; 21 | final String? description; 22 | final Widget? descriptionWidget; 23 | final String? chatProfileUrl; 24 | final List usersProfileURLs; 25 | final UserActiveStatus? oneToOneUserStatus; 26 | final List actions; 27 | 28 | @override 29 | Widget build(BuildContext context) { 30 | return AppBar( 31 | titleSpacing: 0, 32 | centerTitle: true, 33 | actions: actions, 34 | backgroundColor: AppColors.background, 35 | title: Row( 36 | children: [ 37 | Center( 38 | child: SizedBox.square( 39 | dimension: 40, 40 | child: chatProfileUrl == null 41 | ? UserStackedProfile(usersProfileURLs: usersProfileURLs) 42 | : ChatUserAvatar( 43 | profileURL: chatProfileUrl, 44 | status: oneToOneUserStatus, 45 | ), 46 | ), 47 | ), 48 | const SizedBox(width: 12), 49 | Expanded( 50 | child: AnimatedSize( 51 | alignment: Alignment.topLeft, 52 | duration: const Duration(milliseconds: 600), 53 | child: Column( 54 | crossAxisAlignment: CrossAxisAlignment.start, 55 | children: [ 56 | Text( 57 | chatName, 58 | maxLines: 1, 59 | style: const TextStyle( 60 | fontSize: 18, 61 | color: Colors.black, 62 | fontWeight: FontWeight.w600, 63 | ), 64 | overflow: TextOverflow.ellipsis, 65 | ), 66 | if (descriptionWidget case final descriptionWidget?) ...[ 67 | const SizedBox(height: 2), 68 | descriptionWidget, 69 | ], 70 | if (description?.isNotEmpty ?? false) ...[ 71 | const SizedBox(height: 2), 72 | Text( 73 | description!, 74 | maxLines: 1, 75 | overflow: TextOverflow.ellipsis, 76 | style: const TextStyle( 77 | fontSize: 10, 78 | fontWeight: FontWeight.w400, 79 | ), 80 | ), 81 | ], 82 | ], 83 | ), 84 | ), 85 | ), 86 | ], 87 | ), 88 | titleTextStyle: const TextStyle( 89 | fontSize: 20, 90 | color: Colors.black, 91 | fontWeight: FontWeight.w600, 92 | ), 93 | ); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /doc/firebase/firebase-database-schema.md: -------------------------------------------------------------------------------- 1 | ## 🗄️ Firestore Database Schema 2 | 3 | This document outlines the Firestore database schema for a chat application. Firestore uses a NoSQL, 4 | document-based structure in which data is stored in collections and documents. 5 | 6 | ### Collections & Documents: 7 | 8 | #### Users Collection: 9 | 10 | The `users` collection stores user information, with each document representing a single user. This 11 | collection is read-only for us. 12 | 13 | ```plaintext 14 | 📂 users (Collection) 15 | ├── 📄 {userId} (Document) 16 | ├── id: string (Unique identifier for the user.) 17 | ├── name: string (User’s display name.) 18 | ├── profilePhoto: string (URL to the user's profile picture.) 19 | ``` 20 | 21 | This collection is **mandatory** for enabling chat between users, as it provides essential user 22 | details. It is used to fetch user information during chat creation and in other operation, without 23 | modifying the data. 24 | 25 | **Note:** If your Firestore database has a different path for the user collection, a different 26 | collection name, or different field keys for user details, configure the `cloudServiceConfig`. 27 | for Firebase, use the `FirebaseCloudConfig` class while initializing the `ChatViewConnect` 28 | constructor. 29 | 30 | #### Chats Collection: 31 | 32 | The `chats` collection contains chat room details. 33 | 34 | ```plaintext 35 | 📂 chats (Collection) 36 | ├── 📄 {chatId} (Document) 37 | ├── chat_room_type: string (one-to-one/group) 38 | ├── chat_room_create_by: string (User who created the group. Applicable only for group chats.) 39 | ├── group_name: string (Name of the group) 40 | ├── group_photo_url: string (URL of the group profile picture) 41 | 42 | 📂 messages (Subcollection under chats) 43 | ├── 📄 {messageId} (Document) 44 | ├── createAt: Timestamp 45 | ├── id: string 46 | ├── message: string 47 | ├── message_type: string (image/text/voice/custom) 48 | ├── reaction: map 49 | ├── reply_message: map 50 | ├── sentBy: string (user_id) 51 | ├── status: string (read/delivered/undelivered/pending) 52 | ├── voice_message_duration: string (optional) 53 | ├── update: map (optional) 54 | ├── update_at: Timestamp (optional) 55 | 56 | 📂 users (Subcollection under chats) 57 | ├── 📄 {userId} (Document) 58 | ├── membership_status: string (Status of the user in the chat ie: member/left/removed) 59 | ├── membership_status_timestamp: Timestamp (Timestamp of when the membership status changed) 60 | ├── mute_status: string (muted/unmuted) 61 | ├── pin_status: string (pinned/unpinned) 62 | ├── pin_status_timestamp: Timestamp (Timestamp of when the pin status changed) 63 | ├── role: string (Role of the user in the chat ie: admin/user) 64 | ├── typing_status: string (Indicates whether the user is typing ie: typed/typing) 65 | ``` 66 | 67 | #### User Chats Collection: 68 | 69 | The `user_chats` collection maintains a mapping between individual users and their associated chat 70 | rooms. 71 | 72 | ```plaintext 73 | 📂 user_chats (Collection) 74 | ├── 📄 {userId} (Document) 75 | ├── user_active_status: string (online/offline) 76 | 77 | 📂 chats (Subcollection under user_chats) 78 | ├── 📄 {chatId} (Document) 79 | ├── user_id: string (ID of the user associated with one-to-one chat) 80 | ``` 81 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![ChatView Connect - Simform LLC.](https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview_connect/master/preview/banner.png) 2 | 3 | # ChatView Connect 4 | 5 | [![Build](https://github.com/SimformSolutionsPvtLtd/chatview_connect/actions/workflows/flutter.yaml/badge.svg?branch=master)](https://github.com/SimformSolutionsPvtLtd/chatview_connect/actions) [![chatview_connect](https://img.shields.io/pub/v/chatview_connect?label=chatview_connect)](https://pub.dev/packages/chatview_connect) 6 | 7 | `chatview_connect` is a specialized wrapper for the [`chatview`][chatViewPackage] 8 | package, providing seamless integration with Database & Storage for your Flutter chat app. 9 | 10 | _Check out other amazing 11 | open-source [Flutter libraries](https://simform-flutter-packages.web.app) 12 | and [Mobile libraries](https://github.com/SimformSolutionsPvtLtd/Awesome-Mobile-Libraries) developed 13 | by Simform Solutions!_ 14 | 15 | ## Preview 16 | 17 | | ChatList | ChatView | 18 | |------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------| 19 | | ![ChatList_Preview](https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview/main/preview/chatlist.gif) | ![ChatView Preview](https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview/main/preview/chatview.gif) | 20 | 21 | ## Features 22 | 23 | - **Easy Setup:** Integrate with the [`chatview`][chatViewPackage] package in 3 steps: 24 | 1. Initialize the package by specifying the **Cloud Service** (e.g., Firebase). 25 | 2. Set the current **User ID**. 26 | 3. Widget-wise controllers to use it with the [`chatview`][chatViewPackage] package: 27 | 1. For `ChatList` obtain the **`ChatListManager`** 28 | 2. For `ChatView` obtain the **`ChatManager`** 29 | - Supports **one-on-one** and **group chats** with **media uploads** *(audio not supported).* 30 | 31 | ***Note:*** *Currently, it supports only Firebase Cloud Services. Support for additional cloud 32 | services will be included in future releases.* 33 | 34 | ## Documentation 35 | 36 | Visit our [documentation](https://simform-flutter-packages.web.app/chatViewConnect) site for 37 | detailed implementation instructions, usage examples, advanced features, database & 38 | storage structures, and rules. 39 | 40 | ## Installation 41 | 42 | ```yaml 43 | dependencies: 44 | chatview_connect: 45 | ``` 46 | 47 | ## Compatibility with [`chatview`][chatViewPackage] 48 | 49 | | [`chatview`][chatViewPackage] version | `chatview_connect` version | 50 | |---------------------------------------|----------------------------| 51 | | `>=2.4.1 <3.0.0` | `0.0.1` | 52 | | `>= 3.0.0` | `3.0.0` | 53 | 54 | ## Support 55 | 56 | For questions, issues, or feature 57 | requests, [create an issue](https://github.com/SimformSolutionsPvtLtd/chatview_connect/issues) 58 | on GitHub or reach out via the GitHub Discussions tab. We're happy to help and encourage community 59 | contributions. 60 | 61 | To contribute documentation updates specifically, please make changes to the `doc/documentation.md` 62 | file and submit a pull request. 63 | 64 | ## License 65 | 66 | This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. 67 | 68 | [chatViewPackage]: https://pub.dev/packages/chatview 69 | -------------------------------------------------------------------------------- /example/windows/runner/Runner.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | #pragma code_page(65001) 4 | #include "resource.h" 5 | 6 | #define APSTUDIO_READONLY_SYMBOLS 7 | ///////////////////////////////////////////////////////////////////////////// 8 | // 9 | // Generated from the TEXTINCLUDE 2 resource. 10 | // 11 | #include "winres.h" 12 | 13 | ///////////////////////////////////////////////////////////////////////////// 14 | #undef APSTUDIO_READONLY_SYMBOLS 15 | 16 | ///////////////////////////////////////////////////////////////////////////// 17 | // English (United States) resources 18 | 19 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 20 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 21 | 22 | #ifdef APSTUDIO_INVOKED 23 | ///////////////////////////////////////////////////////////////////////////// 24 | // 25 | // TEXTINCLUDE 26 | // 27 | 28 | 1 TEXTINCLUDE 29 | BEGIN 30 | "resource.h\0" 31 | END 32 | 33 | 2 TEXTINCLUDE 34 | BEGIN 35 | "#include ""winres.h""\r\n" 36 | "\0" 37 | END 38 | 39 | 3 TEXTINCLUDE 40 | BEGIN 41 | "\r\n" 42 | "\0" 43 | END 44 | 45 | #endif // APSTUDIO_INVOKED 46 | 47 | 48 | ///////////////////////////////////////////////////////////////////////////// 49 | // 50 | // Icon 51 | // 52 | 53 | // Icon with lowest ID value placed first to ensure application icon 54 | // remains consistent on all systems. 55 | IDI_APP_ICON ICON "resources\\app_icon.ico" 56 | 57 | 58 | ///////////////////////////////////////////////////////////////////////////// 59 | // 60 | // Version 61 | // 62 | 63 | #if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) 64 | #define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD 65 | #else 66 | #define VERSION_AS_NUMBER 1,0,0,0 67 | #endif 68 | 69 | #if defined(FLUTTER_VERSION) 70 | #define VERSION_AS_STRING FLUTTER_VERSION 71 | #else 72 | #define VERSION_AS_STRING "1.0.0" 73 | #endif 74 | 75 | VS_VERSION_INFO VERSIONINFO 76 | FILEVERSION VERSION_AS_NUMBER 77 | PRODUCTVERSION VERSION_AS_NUMBER 78 | FILEFLAGSMASK VS_FFI_FILEFLAGSMASK 79 | #ifdef _DEBUG 80 | FILEFLAGS VS_FF_DEBUG 81 | #else 82 | FILEFLAGS 0x0L 83 | #endif 84 | FILEOS VOS__WINDOWS32 85 | FILETYPE VFT_APP 86 | FILESUBTYPE 0x0L 87 | BEGIN 88 | BLOCK "StringFileInfo" 89 | BEGIN 90 | BLOCK "040904e4" 91 | BEGIN 92 | VALUE "CompanyName", "com.simform" "\0" 93 | VALUE "FileDescription", "ChatView Connect Example" "\0" 94 | VALUE "FileVersion", VERSION_AS_STRING "\0" 95 | VALUE "InternalName", "ChatView Connect Example" "\0" 96 | VALUE "LegalCopyright", "Copyright (C) 2024 com.simform. All rights reserved." "\0" 97 | VALUE "OriginalFilename", "example.exe" "\0" 98 | VALUE "ProductName", "ChatView Connect Example" "\0" 99 | VALUE "ProductVersion", VERSION_AS_STRING "\0" 100 | END 101 | END 102 | BLOCK "VarFileInfo" 103 | BEGIN 104 | VALUE "Translation", 0x409, 1252 105 | END 106 | END 107 | 108 | #endif // English (United States) resources 109 | ///////////////////////////////////////////////////////////////////////////// 110 | 111 | 112 | 113 | #ifndef APSTUDIO_INVOKED 114 | ///////////////////////////////////////////////////////////////////////////// 115 | // 116 | // Generated from the TEXTINCLUDE 3 resource. 117 | // 118 | 119 | 120 | ///////////////////////////////////////////////////////////////////////////// 121 | #endif // not APSTUDIO_INVOKED 122 | -------------------------------------------------------------------------------- /example/lib/modules/chat_list/widgets/reply_message_tile.dart: -------------------------------------------------------------------------------- 1 | import 'package:audio_waveforms/audio_waveforms.dart'; 2 | import 'package:chatview/chatview.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | import '../../../values/app_colors.dart'; 6 | 7 | class ReplyMessageTile extends StatelessWidget { 8 | const ReplyMessageTile({ 9 | required this.replyMessage, 10 | required this.chatController, 11 | super.key, 12 | }); 13 | 14 | final ReplyMessage? replyMessage; 15 | final ChatController chatController; 16 | 17 | @override 18 | Widget build(BuildContext context) { 19 | const textStyle = TextStyle( 20 | fontSize: 12, 21 | height: 1.33, 22 | color: Color(0xFF232626), 23 | fontWeight: FontWeight.w400, 24 | ); 25 | final reply = replyMessage; 26 | if (reply == null) { 27 | return const SizedBox.shrink(); 28 | } 29 | final replyBySender = reply.replyBy == chatController.currentUser.id; 30 | final messagedUser = chatController.getUserFromId(reply.replyBy); 31 | final replyBy = 32 | replyBySender ? PackageStrings.currentLocale.you : messagedUser.name; 33 | return Container( 34 | constraints: BoxConstraints( 35 | maxWidth: MediaQuery.of(context).size.width * 0.75, 36 | ), 37 | margin: const EdgeInsets.only(bottom: 6), 38 | decoration: BoxDecoration( 39 | color: replyBySender ? AppColors.senderBgColor : Colors.white, 40 | borderRadius: const BorderRadius.all(Radius.circular(12)), 41 | ), 42 | child: Container( 43 | padding: const EdgeInsets.fromLTRB(9, 9.5, 9, 10.5), 44 | decoration: const BoxDecoration( 45 | color: Color(0x0A0A0A0A), 46 | borderRadius: BorderRadius.all(Radius.circular(8)), 47 | border: Border( 48 | left: BorderSide(color: AppColors.replyLineColor, width: 4), 49 | ), 50 | ), 51 | child: Column( 52 | crossAxisAlignment: CrossAxisAlignment.start, 53 | children: [ 54 | Text( 55 | replyBy, 56 | maxLines: 1, 57 | overflow: TextOverflow.ellipsis, 58 | style: const TextStyle( 59 | fontSize: 14, 60 | height: 1.36, 61 | letterSpacing: -0.01, 62 | fontWeight: FontWeight.w600, 63 | color: AppColors.replyLineColor, 64 | ), 65 | ), 66 | const SizedBox(height: 2), 67 | switch (reply.messageType) { 68 | MessageType.voice => Row( 69 | mainAxisSize: MainAxisSize.min, 70 | children: [ 71 | const Icon(Icons.mic), 72 | const SizedBox(width: 4), 73 | if (reply.voiceMessageDuration != null) 74 | Text( 75 | reply.voiceMessageDuration!.toHHMMSS(), 76 | style: textStyle, 77 | ), 78 | ], 79 | ), 80 | MessageType.image => Row( 81 | mainAxisSize: MainAxisSize.min, 82 | children: [ 83 | Icon( 84 | Icons.photo, 85 | size: 20, 86 | color: Colors.grey.shade700, 87 | ), 88 | Text( 89 | PackageStrings.currentLocale.photo, 90 | style: textStyle, 91 | ), 92 | ], 93 | ), 94 | MessageType.custom || MessageType.text => Text( 95 | reply.message, 96 | maxLines: 1, 97 | overflow: TextOverflow.ellipsis, 98 | style: textStyle, 99 | ), 100 | }, 101 | ], 102 | ), 103 | ), 104 | ); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /example/windows/runner/win32_window.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_WIN32_WINDOW_H_ 2 | #define RUNNER_WIN32_WINDOW_H_ 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | // A class abstraction for a high DPI-aware Win32 Window. Intended to be 11 | // inherited from by classes that wish to specialize with custom 12 | // rendering and input handling 13 | class Win32Window { 14 | public: 15 | struct Point { 16 | unsigned int x; 17 | unsigned int y; 18 | Point(unsigned int x, unsigned int y) : x(x), y(y) {} 19 | }; 20 | 21 | struct Size { 22 | unsigned int width; 23 | unsigned int height; 24 | Size(unsigned int width, unsigned int height) 25 | : width(width), height(height) {} 26 | }; 27 | 28 | Win32Window(); 29 | virtual ~Win32Window(); 30 | 31 | // Creates a win32 window with |title| that is positioned and sized using 32 | // |origin| and |size|. New windows are created on the default monitor. Window 33 | // sizes are specified to the OS in physical pixels, hence to ensure a 34 | // consistent size this function will scale the inputted width and height as 35 | // as appropriate for the default monitor. The window is invisible until 36 | // |Show| is called. Returns true if the window was created successfully. 37 | bool Create(const std::wstring& title, const Point& origin, const Size& size); 38 | 39 | // Show the current window. Returns true if the window was successfully shown. 40 | bool Show(); 41 | 42 | // Release OS resources associated with window. 43 | void Destroy(); 44 | 45 | // Inserts |content| into the window tree. 46 | void SetChildContent(HWND content); 47 | 48 | // Returns the backing Window handle to enable clients to set icon and other 49 | // window properties. Returns nullptr if the window has been destroyed. 50 | HWND GetHandle(); 51 | 52 | // If true, closing this window will quit the application. 53 | void SetQuitOnClose(bool quit_on_close); 54 | 55 | // Return a RECT representing the bounds of the current client area. 56 | RECT GetClientArea(); 57 | 58 | protected: 59 | // Processes and route salient window messages for mouse handling, 60 | // size change and DPI. Delegates handling of these to member overloads that 61 | // inheriting classes can handle. 62 | virtual LRESULT MessageHandler(HWND window, 63 | UINT const message, 64 | WPARAM const wparam, 65 | LPARAM const lparam) noexcept; 66 | 67 | // Called when CreateAndShow is called, allowing subclass window-related 68 | // setup. Subclasses should return false if setup fails. 69 | virtual bool OnCreate(); 70 | 71 | // Called when Destroy is called. 72 | virtual void OnDestroy(); 73 | 74 | private: 75 | friend class WindowClassRegistrar; 76 | 77 | // OS callback called by message pump. Handles the WM_NCCREATE message which 78 | // is passed when the non-client area is being created and enables automatic 79 | // non-client DPI scaling so that the non-client area automatically 80 | // responds to changes in DPI. All other messages are handled by 81 | // MessageHandler. 82 | static LRESULT CALLBACK WndProc(HWND const window, 83 | UINT const message, 84 | WPARAM const wparam, 85 | LPARAM const lparam) noexcept; 86 | 87 | // Retrieves a class instance pointer for |window| 88 | static Win32Window* GetThisFromHandle(HWND const window) noexcept; 89 | 90 | // Update the window frame's theme to match the system theme. 91 | static void UpdateTheme(HWND const window); 92 | 93 | bool quit_on_close_ = false; 94 | 95 | // window handle for top level window. 96 | HWND window_handle_ = nullptr; 97 | 98 | // window handle for hosted content. 99 | HWND child_content_ = nullptr; 100 | }; 101 | 102 | #endif // RUNNER_WIN32_WINDOW_H_ 103 | -------------------------------------------------------------------------------- /example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 43 | 49 | 50 | 51 | 52 | 53 | 63 | 65 | 71 | 72 | 73 | 74 | 80 | 82 | 88 | 89 | 90 | 91 | 93 | 94 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /example/linux/my_application.cc: -------------------------------------------------------------------------------- 1 | #include "my_application.h" 2 | 3 | #include 4 | #ifdef GDK_WINDOWING_X11 5 | #include 6 | #endif 7 | 8 | #include "flutter/generated_plugin_registrant.h" 9 | 10 | struct _MyApplication { 11 | GtkApplication parent_instance; 12 | char** dart_entrypoint_arguments; 13 | }; 14 | 15 | G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) 16 | 17 | // Implements GApplication::activate. 18 | static void my_application_activate(GApplication* application) { 19 | MyApplication* self = MY_APPLICATION(application); 20 | GtkWindow* window = 21 | GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); 22 | 23 | // Use a header bar when running in GNOME as this is the common style used 24 | // by applications and is the setup most users will be using (e.g. Ubuntu 25 | // desktop). 26 | // If running on X and not using GNOME then just use a traditional title bar 27 | // in case the window manager does more exotic layout, e.g. tiling. 28 | // If running on Wayland assume the header bar will work (may need changing 29 | // if future cases occur). 30 | gboolean use_header_bar = TRUE; 31 | #ifdef GDK_WINDOWING_X11 32 | GdkScreen* screen = gtk_window_get_screen(window); 33 | if (GDK_IS_X11_SCREEN(screen)) { 34 | const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); 35 | if (g_strcmp0(wm_name, "GNOME Shell") != 0) { 36 | use_header_bar = FALSE; 37 | } 38 | } 39 | #endif 40 | if (use_header_bar) { 41 | GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); 42 | gtk_widget_show(GTK_WIDGET(header_bar)); 43 | gtk_header_bar_set_title(header_bar, "ChatView Connect Example"); 44 | gtk_header_bar_set_show_close_button(header_bar, TRUE); 45 | gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); 46 | } else { 47 | gtk_window_set_title(window, "ChatView Connect Example"); 48 | } 49 | 50 | gtk_window_set_default_size(window, 1280, 720); 51 | gtk_widget_show(GTK_WIDGET(window)); 52 | 53 | g_autoptr(FlDartProject) project = fl_dart_project_new(); 54 | fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); 55 | 56 | FlView* view = fl_view_new(project); 57 | gtk_widget_show(GTK_WIDGET(view)); 58 | gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); 59 | 60 | fl_register_plugins(FL_PLUGIN_REGISTRY(view)); 61 | 62 | gtk_widget_grab_focus(GTK_WIDGET(view)); 63 | } 64 | 65 | // Implements GApplication::local_command_line. 66 | static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) { 67 | MyApplication* self = MY_APPLICATION(application); 68 | // Strip out the first argument as it is the binary name. 69 | self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); 70 | 71 | g_autoptr(GError) error = nullptr; 72 | if (!g_application_register(application, nullptr, &error)) { 73 | g_warning("Failed to register: %s", error->message); 74 | *exit_status = 1; 75 | return TRUE; 76 | } 77 | 78 | g_application_activate(application); 79 | *exit_status = 0; 80 | 81 | return TRUE; 82 | } 83 | 84 | // Implements GObject::dispose. 85 | static void my_application_dispose(GObject* object) { 86 | MyApplication* self = MY_APPLICATION(object); 87 | g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); 88 | G_OBJECT_CLASS(my_application_parent_class)->dispose(object); 89 | } 90 | 91 | static void my_application_class_init(MyApplicationClass* klass) { 92 | G_APPLICATION_CLASS(klass)->activate = my_application_activate; 93 | G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; 94 | G_OBJECT_CLASS(klass)->dispose = my_application_dispose; 95 | } 96 | 97 | static void my_application_init(MyApplication* self) {} 98 | 99 | MyApplication* my_application_new() { 100 | return MY_APPLICATION(g_object_new(my_application_get_type(), 101 | "application-id", APPLICATION_ID, 102 | "flags", G_APPLICATION_NON_UNIQUE, 103 | nullptr)); 104 | } 105 | -------------------------------------------------------------------------------- /lib/src/typedefs.dart: -------------------------------------------------------------------------------- 1 | import 'package:chatview_utils/chatview_utils.dart'; 2 | import 'package:cloud_firestore/cloud_firestore.dart'; 3 | 4 | import 'database/database_service.dart'; 5 | import 'enum.dart'; 6 | import 'models/chat_room_participant.dart'; 7 | import 'storage/storage_service.dart'; 8 | 9 | /// Callback function used for updating reactions. 10 | /// **Parameters:** 11 | /// - (optional): `userId` specifies id of the user who performed the reaction. 12 | /// - (optional): `emoji` specifies emoji that user has used. 13 | typedef ReactionCallback = ({String userId, String emoji}); 14 | 15 | /// A record that encapsulates cloud-based services, including database and 16 | /// storage. This allows managing both services within a single variable. 17 | typedef CloudServicesRecord = ({ 18 | DatabaseService database, 19 | StorageService storage, 20 | }); 21 | 22 | /// A callback function for uploading a media to cloud storage. 23 | /// Returns the download URL as a [String] or `null` if the upload fails. 24 | typedef UploadMediaCallback = Future Function( 25 | Message message, { 26 | String? uploadPath, 27 | String? fileName, 28 | }); 29 | 30 | /// A callback function for deleting a specific media from storage. 31 | /// Returns `true` if the deletion is successful, otherwise `false`. 32 | typedef DeleteMediaCallback = Future Function(Message message); 33 | 34 | /// A callback function for deleting all media associated with a specific 35 | /// [chatId] from storage. 36 | /// Returns `true` if the operation is successful, otherwise `false`. 37 | typedef DeleteChatMediaCallback = Future Function(String chatId); 38 | 39 | /// Represents a record of chat room participants, 40 | /// including the current user and other users in the chat. 41 | /// 42 | /// **Parameters:** 43 | /// - (optional): `currentUser` The current user participating in the chat room. 44 | /// If `null`, the user may not be a member. 45 | /// - (required): `otherUsers` A list of other users in the chat room excluding 46 | /// the current user. 47 | typedef ChatRoomParticipantsRecord = ({ 48 | ChatRoomParticipant? currentUser, 49 | List otherUsers, 50 | }); 51 | 52 | /// A record type representing a user's information along with their status. 53 | /// 54 | /// **Parameters:** 55 | /// - (optional): `user` [ChatUser] instance representing the user's details. 56 | /// - (optional): `userActiveStatus` [UserActiveStatus] indicating the user's online/offline status. 57 | typedef UserInfoWithStatusRecord = ({ 58 | ChatUser? user, 59 | UserActiveStatus? userActiveStatus, 60 | }); 61 | 62 | /// Represents information about a group, including its name and participants. 63 | /// 64 | /// **Parameters:** 65 | /// - (required): `groupName` A string representing the name of the group, 66 | /// generated based on participants' names. 67 | /// - (required): `participants` A map of user IDs to their assigned [Role] in 68 | /// the group. 69 | typedef GroupInfoRecord = ({String groupName, Map participants}); 70 | 71 | /// Maps a [QuerySnapshot] of [Message] objects to a custom type [T]. 72 | /// 73 | /// Useful for transforming Firestore query results into 74 | /// your desired data structure. 75 | typedef MessageQueryMapper = T Function(QuerySnapshot docSnapshot); 76 | 77 | /// A callback function that extracts a chat room ID from a given snapshot. 78 | /// 79 | /// **Parameters:** 80 | /// - (required): `snapshot` The snapshot object of type [T] from which to extract 81 | /// the chat room ID. 82 | typedef ChatRoomIdCallback = String Function(T snapshot); 83 | 84 | /// A callback function for filtering operations. 85 | /// Returns `true` if the object meets the specified condition, otherwise `false`. 86 | /// 87 | /// **Parameters:** 88 | /// - (required): `item` The object of type [T] to be evaluated against the filter criteria. 89 | typedef WhereCallback = bool Function(T item); 90 | 91 | /// A record type representing a chat item along with its associated status. 92 | /// 93 | /// **Parameters:** 94 | /// - (required): `chat` [ChatListItem] instance representing the chat details 95 | /// - (required): `status` A generic type [T] representing the status associated with the chat. 96 | typedef ChatStatusRecord = ({ChatListItem chat, T status}); 97 | -------------------------------------------------------------------------------- /example/windows/flutter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This file controls Flutter-level build steps. It should not be edited. 2 | cmake_minimum_required(VERSION 3.14) 3 | 4 | set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") 5 | 6 | # Configuration provided via flutter tool. 7 | include(${EPHEMERAL_DIR}/generated_config.cmake) 8 | 9 | # TODO: Move the rest of this into files in ephemeral. See 10 | # https://github.com/flutter/flutter/issues/57146. 11 | set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") 12 | 13 | # Set fallback configurations for older versions of the flutter tool. 14 | if (NOT DEFINED FLUTTER_TARGET_PLATFORM) 15 | set(FLUTTER_TARGET_PLATFORM "windows-x64") 16 | endif() 17 | 18 | # === Flutter Library === 19 | set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") 20 | 21 | # Published to parent scope for install step. 22 | set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) 23 | set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) 24 | set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) 25 | set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) 26 | 27 | list(APPEND FLUTTER_LIBRARY_HEADERS 28 | "flutter_export.h" 29 | "flutter_windows.h" 30 | "flutter_messenger.h" 31 | "flutter_plugin_registrar.h" 32 | "flutter_texture_registrar.h" 33 | ) 34 | list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") 35 | add_library(flutter INTERFACE) 36 | target_include_directories(flutter INTERFACE 37 | "${EPHEMERAL_DIR}" 38 | ) 39 | target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") 40 | add_dependencies(flutter flutter_assemble) 41 | 42 | # === Wrapper === 43 | list(APPEND CPP_WRAPPER_SOURCES_CORE 44 | "core_implementations.cc" 45 | "standard_codec.cc" 46 | ) 47 | list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") 48 | list(APPEND CPP_WRAPPER_SOURCES_PLUGIN 49 | "plugin_registrar.cc" 50 | ) 51 | list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") 52 | list(APPEND CPP_WRAPPER_SOURCES_APP 53 | "flutter_engine.cc" 54 | "flutter_view_controller.cc" 55 | ) 56 | list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") 57 | 58 | # Wrapper sources needed for a plugin. 59 | add_library(flutter_wrapper_plugin STATIC 60 | ${CPP_WRAPPER_SOURCES_CORE} 61 | ${CPP_WRAPPER_SOURCES_PLUGIN} 62 | ) 63 | apply_standard_settings(flutter_wrapper_plugin) 64 | set_target_properties(flutter_wrapper_plugin PROPERTIES 65 | POSITION_INDEPENDENT_CODE ON) 66 | set_target_properties(flutter_wrapper_plugin PROPERTIES 67 | CXX_VISIBILITY_PRESET hidden) 68 | target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) 69 | target_include_directories(flutter_wrapper_plugin PUBLIC 70 | "${WRAPPER_ROOT}/include" 71 | ) 72 | add_dependencies(flutter_wrapper_plugin flutter_assemble) 73 | 74 | # Wrapper sources needed for the runner. 75 | add_library(flutter_wrapper_app STATIC 76 | ${CPP_WRAPPER_SOURCES_CORE} 77 | ${CPP_WRAPPER_SOURCES_APP} 78 | ) 79 | apply_standard_settings(flutter_wrapper_app) 80 | target_link_libraries(flutter_wrapper_app PUBLIC flutter) 81 | target_include_directories(flutter_wrapper_app PUBLIC 82 | "${WRAPPER_ROOT}/include" 83 | ) 84 | add_dependencies(flutter_wrapper_app flutter_assemble) 85 | 86 | # === Flutter tool backend === 87 | # _phony_ is a non-existent file to force this command to run every time, 88 | # since currently there's no way to get a full input/output list from the 89 | # flutter tool. 90 | set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") 91 | set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) 92 | add_custom_command( 93 | OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} 94 | ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} 95 | ${CPP_WRAPPER_SOURCES_APP} 96 | ${PHONY_OUTPUT} 97 | COMMAND ${CMAKE_COMMAND} -E env 98 | ${FLUTTER_TOOL_ENVIRONMENT} 99 | "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" 100 | ${FLUTTER_TARGET_PLATFORM} $ 101 | VERBATIM 102 | ) 103 | add_custom_target(flutter_assemble DEPENDS 104 | "${FLUTTER_LIBRARY}" 105 | ${FLUTTER_LIBRARY_HEADERS} 106 | ${CPP_WRAPPER_SOURCES_CORE} 107 | ${CPP_WRAPPER_SOURCES_PLUGIN} 108 | ${CPP_WRAPPER_SOURCES_APP} 109 | ) 110 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 38 | 39 | 40 | 41 | 44 | 50 | 51 | 52 | 53 | 54 | 66 | 68 | 74 | 75 | 76 | 77 | 83 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /example/lib/modules/create_chat/create_chat_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:chatview/chatview.dart'; 2 | import 'package:chatview_connect/chatview_connect.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | import '../chat_detail/chat_detail_screen.dart'; 6 | import 'widgets/create_chat_tile.dart'; 7 | 8 | class CreateChatScreen extends StatefulWidget { 9 | const CreateChatScreen({required this.chatListController, super.key}); 10 | 11 | final ChatListManager chatListController; 12 | 13 | @override 14 | State createState() => _CreateChatScreenState(); 15 | } 16 | 17 | class _CreateChatScreenState extends State { 18 | final currentUser = ChatViewConnect.instance.currentUserId; 19 | ChatUser? currentChatUser; 20 | List otherChatUsers = []; 21 | 22 | @override 23 | Widget build(BuildContext context) { 24 | return Scaffold( 25 | appBar: AppBar(title: const Text('New Chat')), 26 | body: FutureBuilder( 27 | future: widget.chatListController.getUsers(), 28 | builder: (_, snapshot) { 29 | final users = snapshot.data?.values.toList() ?? []; 30 | _separateUsers(users); 31 | if (users.isEmpty) { 32 | return const Center(child: Text('No Users')); 33 | } else { 34 | final usersLength = otherChatUsers.length + 1; 35 | final lastLength = usersLength - 1; 36 | return ListView.separated( 37 | itemCount: usersLength, 38 | padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), 39 | separatorBuilder: (_, __) => const SizedBox(height: 12), 40 | itemBuilder: (_, index) { 41 | if (index == lastLength) { 42 | return FilledButton( 43 | onPressed: _createGroupChat, 44 | child: const Text('Create a group of all'), 45 | ); 46 | } else { 47 | final user = otherChatUsers[index]; 48 | return CreateChatTile( 49 | username: user.name, 50 | userProfile: user.profilePhoto, 51 | onTap: () => _createOneToOneChat(otherUser: user), 52 | ); 53 | } 54 | }, 55 | ); 56 | } 57 | }, 58 | ), 59 | ); 60 | } 61 | 62 | void _separateUsers(List users) { 63 | otherChatUsers.clear(); 64 | final usersLength = users.length; 65 | for (var i = 0; i < usersLength; i++) { 66 | final user = users[i]; 67 | if (user.id == currentUser) { 68 | currentChatUser = user; 69 | } else { 70 | otherChatUsers.add(user); 71 | } 72 | } 73 | } 74 | 75 | Future _createOneToOneChat({required ChatUser otherUser}) async { 76 | final chatRoomId = await widget.chatListController.createChat(otherUser.id); 77 | if (chatRoomId == null || !mounted) return; 78 | return Navigator.push( 79 | context, 80 | MaterialPageRoute( 81 | builder: (_) => ChatDetailScreen( 82 | chat: ChatListItem( 83 | id: chatRoomId, 84 | name: otherUser.name, 85 | chatRoomType: ChatRoomType.oneToOne, 86 | ), 87 | ), 88 | ), 89 | ); 90 | } 91 | 92 | Future _createGroupChat({ 93 | String groupName = 'Test Group', 94 | String groupProfilePic = 95 | 'https://images.unsplash.com/photo-1739305235159-308ddffb4129?w=900&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxmZWF0dXJlZC1waG90b3MtZmVlZHw2fHx8ZW58MHx8fHx8', 96 | bool createWithChatManager = false, 97 | }) async { 98 | final participants = {}; 99 | for (var i = 0; i < otherChatUsers.length; i++) { 100 | final user = otherChatUsers[i]; 101 | participants[user.id] = Role.admin; 102 | } 103 | final chatRoomId = await widget.chatListController.createGroupChat( 104 | groupName: groupName, 105 | groupProfilePic: groupProfilePic, 106 | participants: participants, 107 | ); 108 | if (chatRoomId == null || !mounted) return; 109 | return Navigator.push( 110 | context, 111 | MaterialPageRoute( 112 | builder: (_) => ChatDetailScreen( 113 | chat: ChatListItem( 114 | id: chatRoomId, 115 | name: groupName, 116 | imageUrl: groupProfilePic, 117 | chatRoomType: ChatRoomType.group, 118 | ), 119 | ), 120 | ), 121 | ); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: chatview_connect_example 2 | description: "Flutter project integrating chatview with chatview_connect package." 3 | # The following line prevents the package from being accidentally published to 4 | # pub.dev using `flutter pub publish`. This is preferred for private packages. 5 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev 6 | 7 | # The following defines the version and build number for your application. 8 | # A version number is three numbers separated by dots, like 1.2.43 9 | # followed by an optional build number separated by a +. 10 | # Both the version and the builder number may be overridden in flutter 11 | # build by specifying --build-name and --build-number, respectively. 12 | # In Android, build-name is used as versionName while build-number used as versionCode. 13 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 14 | # In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. 15 | # Read more about iOS versioning at 16 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 17 | # In Windows, build-name is used as the major, minor, and patch parts 18 | # of the product and file versions while build-number is used as the build suffix. 19 | version: 1.0.0+1 20 | 21 | environment: 22 | sdk: '>=3.4.0 <4.0.0' 23 | 24 | # Dependencies specify other packages that your package needs in order to work. 25 | # To automatically upgrade your package dependencies to the latest versions 26 | # consider running `flutter pub upgrade --major-versions`. Alternatively, 27 | # dependencies can be manually updated by changing the version numbers below to 28 | # the latest version available on pub.dev. To see which dependencies have newer 29 | # versions available, run `flutter pub outdated`. 30 | dependencies: 31 | flutter: 32 | sdk: flutter 33 | 34 | 35 | # The following adds the Cupertino Icons font to your application. 36 | # Use with the CupertinoIcons class for iOS style icons. 37 | cupertino_icons: ^1.0.2 38 | firebase_core: ^4.3.0 39 | cloud_firestore: ^6.1.1 40 | uuid: ^4.5.1 41 | intl: 42 | audio_waveforms: ^2.0.1 43 | chatview: ^3.0.0 44 | 45 | flutter_svg: ^2.1.0 46 | 47 | chatview_connect: 48 | path: .. 49 | 50 | dev_dependencies: 51 | flutter_test: 52 | sdk: flutter 53 | 54 | # The "flutter_lints" package below contains a set of recommended lints to 55 | # encourage good coding practices. The lint set provided by the package is 56 | # activated in the `analysis_options.yaml` file located at the root of your 57 | # package. See that file for information about deactivating specific lint 58 | # rules and activating additional ones. 59 | flutter_lints: ^2.0.0 60 | 61 | # For information on the generic Dart part of this file, see the 62 | # following page: https://dart.dev/tools/pub/pubspec 63 | 64 | # The following section is specific to Flutter packages. 65 | flutter: 66 | 67 | assets: 68 | - assets/images/ 69 | - assets/vectors/ 70 | 71 | # The following line ensures that the Material Icons font is 72 | # included with your application, so that you can use the icons in 73 | # the material Icons class. 74 | uses-material-design: true 75 | 76 | # To add assets to your application, add an assets section, like this: 77 | # assets: 78 | # - images/a_dot_burr.jpeg 79 | # - images/a_dot_ham.jpeg 80 | 81 | # An image asset can refer to one or more resolution-specific "variants", see 82 | # https://flutter.dev/assets-and-images/#resolution-aware 83 | 84 | # For details regarding adding assets from package dependencies, see 85 | # https://flutter.dev/assets-and-images/#from-packages 86 | 87 | # To add custom fonts to your application, add a fonts section here, 88 | # in this "flutter" section. Each entry in this list should have a 89 | # "family" key with the font family name, and a "fonts" key with a 90 | # list giving the asset and other descriptors for the font. For 91 | # example: 92 | # fonts: 93 | # - family: Schyler 94 | # fonts: 95 | # - asset: fonts/Schyler-Regular.ttf 96 | # - asset: fonts/Schyler-Italic.ttf 97 | # style: italic 98 | # - family: Trajan Pro 99 | # fonts: 100 | # - asset: fonts/TrajanPro.ttf 101 | # - asset: fonts/TrajanPro_Bold.ttf 102 | # weight: 700 103 | # 104 | # For details regarding fonts from package dependencies, 105 | # see https://flutter.dev/custom-fonts/#from-packages 106 | -------------------------------------------------------------------------------- /example/windows/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Project-level configuration. 2 | cmake_minimum_required(VERSION 3.14) 3 | project(example LANGUAGES CXX) 4 | 5 | # The name of the executable created for the application. Change this to change 6 | # the on-disk name of your application. 7 | set(BINARY_NAME "example") 8 | 9 | # Explicitly opt in to modern CMake behaviors to avoid warnings with recent 10 | # versions of CMake. 11 | cmake_policy(VERSION 3.14...3.25) 12 | 13 | # Define build configuration option. 14 | get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) 15 | if(IS_MULTICONFIG) 16 | set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" 17 | CACHE STRING "" FORCE) 18 | else() 19 | if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) 20 | set(CMAKE_BUILD_TYPE "Debug" CACHE 21 | STRING "Flutter build mode" FORCE) 22 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS 23 | "Debug" "Profile" "Release") 24 | endif() 25 | endif() 26 | # Define settings for the Profile build mode. 27 | set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") 28 | set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") 29 | set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") 30 | set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") 31 | 32 | # Use Unicode for all projects. 33 | add_definitions(-DUNICODE -D_UNICODE) 34 | 35 | # Compilation settings that should be applied to most targets. 36 | # 37 | # Be cautious about adding new options here, as plugins use this function by 38 | # default. In most cases, you should add new options to specific targets instead 39 | # of modifying this function. 40 | function(APPLY_STANDARD_SETTINGS TARGET) 41 | target_compile_features(${TARGET} PUBLIC cxx_std_17) 42 | target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") 43 | target_compile_options(${TARGET} PRIVATE /EHsc) 44 | target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") 45 | target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") 46 | endfunction() 47 | 48 | # Flutter library and tool build rules. 49 | set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") 50 | add_subdirectory(${FLUTTER_MANAGED_DIR}) 51 | 52 | # Application build; see runner/CMakeLists.txt. 53 | add_subdirectory("runner") 54 | 55 | 56 | # Generated plugin build rules, which manage building the plugins and adding 57 | # them to the application. 58 | include(flutter/generated_plugins.cmake) 59 | 60 | 61 | # === Installation === 62 | # Support files are copied into place next to the executable, so that it can 63 | # run in place. This is done instead of making a separate bundle (as on Linux) 64 | # so that building and running from within Visual Studio will work. 65 | set(BUILD_BUNDLE_DIR "$") 66 | # Make the "install" step default, as it's required to run. 67 | set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) 68 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) 69 | set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) 70 | endif() 71 | 72 | set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") 73 | set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") 74 | 75 | install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" 76 | COMPONENT Runtime) 77 | 78 | install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" 79 | COMPONENT Runtime) 80 | 81 | install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 82 | COMPONENT Runtime) 83 | 84 | if(PLUGIN_BUNDLED_LIBRARIES) 85 | install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" 86 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 87 | COMPONENT Runtime) 88 | endif() 89 | 90 | # Copy the native assets provided by the build.dart from all packages. 91 | set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") 92 | install(DIRECTORY "${NATIVE_ASSETS_DIR}" 93 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 94 | COMPONENT Runtime) 95 | 96 | # Fully re-copy the assets directory on each build to avoid having stale files 97 | # from a previous install. 98 | set(FLUTTER_ASSET_DIR_NAME "flutter_assets") 99 | install(CODE " 100 | file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") 101 | " COMPONENT Runtime) 102 | install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" 103 | DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) 104 | 105 | # Install the AOT library on non-Debug builds only. 106 | install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" 107 | CONFIGURATIONS Profile;Release 108 | COMPONENT Runtime) 109 | --------------------------------------------------------------------------------