From 99378c27d97385299c741c4e9e13a1dd24ffe374 Mon Sep 17 00:00:00 2001 From: "Neevash Ramdial (Nash)" Date: Wed, 10 Mar 2021 15:18:00 -0400 Subject: [PATCH 001/172] Improve repo structure (#22) * app updated * readme updated * rename base folder * update chatty's readme * move apps to packages dir * update repo overview Co-authored-by: diegoveloper --- stream_chat_v1/README.md | 71 ++ stream_chat_v1/android/.gitignore | 7 + stream_chat_v1/android/app/build.gradle | 80 ++ stream_chat_v1/android/app/debug.keystore | Bin 0 -> 2105 bytes .../android/app/google-services.json | 40 + .../android/app/src/debug/AndroidManifest.xml | 7 + .../android/app/src/main/AndroidManifest.xml | 39 + .../kotlin/com/example/example/Application.kt | 23 + .../com/example/example/MainActivity.kt | 12 + .../main/res/drawable/launch_background.xml | 5 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 5905 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 3283 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 8478 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 15150 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 21173 bytes .../app/src/main/res/values/colors.xml | 4 + .../app/src/main/res/values/styles.xml | 8 + .../app/src/profile/AndroidManifest.xml | 7 + stream_chat_v1/android/build.gradle | 32 + stream_chat_v1/android/gradle.properties | 4 + .../gradle/wrapper/gradle-wrapper.properties | 6 + stream_chat_v1/android/settings.gradle | 15 + stream_chat_v1/android/settings_aar.gradle | 1 + stream_chat_v1/assets/android_icon.png | Bin 0 -> 15354 bytes stream_chat_v1/assets/floating_boat.json | 1 + stream_chat_v1/assets/icon_arrow_right.svg | 5 + stream_chat_v1/assets/ios_icon.png | Bin 0 -> 40617 bytes stream_chat_v1/assets/logo.svg | 3 + stream_chat_v1/ios/.gitignore | 32 + stream_chat_v1/ios/Flutter/.last_build_id | 1 + .../ios/Flutter/AppFrameworkInfo.plist | 26 + stream_chat_v1/ios/Flutter/Debug.xcconfig | 3 + stream_chat_v1/ios/Flutter/Release.xcconfig | 3 + stream_chat_v1/ios/Gemfile | 6 + stream_chat_v1/ios/Gemfile.lock | 180 +++ stream_chat_v1/ios/Notifications/Info.plist | 31 + .../Notifications/NotificationService.swift | 182 +++ .../Notifications/Notifications.entitlements | 10 + .../ios/Runner.xcodeproj/project.pbxproj | 837 +++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../xcschemes/Notifications.xcscheme | 96 ++ .../xcshareddata/xcschemes/Runner.xcscheme | 87 ++ .../contents.xcworkspacedata | 10 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + stream_chat_v1/ios/Runner/AppDelegate.swift | 45 + .../AppIcon.appiconset/Contents.json | 122 ++ .../Icon-App-1024x1024@1x.png | Bin 0 -> 52126 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 0 -> 572 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 0 -> 1472 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 0 -> 2358 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 0 -> 990 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 0 -> 2338 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 0 -> 3744 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 0 -> 1472 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 0 -> 3342 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 0 -> 5281 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 0 -> 5281 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 0 -> 8289 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 0 -> 3132 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 0 -> 6964 bytes .../Icon-App-83.5x83.5@2x.png | Bin 0 -> 7597 bytes .../LaunchBackground.imageset/Contents.json | 21 + .../LaunchBackground.imageset/background.png | Bin 0 -> 70 bytes .../LaunchImage.imageset/Contents.json | 23 + .../LaunchImage.imageset/LaunchImage.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/README.md | 5 + .../Runner/Base.lproj/LaunchScreen.storyboard | 44 + .../ios/Runner/Base.lproj/Main.storyboard | 26 + stream_chat_v1/ios/Runner/Info.plist | 66 + .../ios/Runner/Runner-Bridging-Header.h | 1 + stream_chat_v1/ios/Runner/Runner.entitlements | 12 + stream_chat_v1/ios/fastlane/Appfile | 6 + stream_chat_v1/ios/fastlane/Fastfile | 46 + stream_chat_v1/ios/fastlane/Matchfile | 16 + stream_chat_v1/ios/fastlane/Pluginfile | 5 + stream_chat_v1/ios/fastlane/README.md | 37 + .../fastlane/beta_gym_export_options.plist | 15 + stream_chat_v1/ios/fastlane/report.xml | 33 + stream_chat_v1/lib/advanced_options_page.dart | 327 +++++ stream_chat_v1/lib/chat_info_screen.dart | 603 ++++++++++ .../lib/chips_input_text_field.dart | 166 +++ stream_chat_v1/lib/choose_user_page.dart | 269 +++++ .../lib/group_chat_details_screen.dart | 331 +++++ stream_chat_v1/lib/group_info_screen.dart | 1038 ++++++++++++++++ stream_chat_v1/lib/main.dart | 1066 +++++++++++++++++ stream_chat_v1/lib/new_chat_screen.dart | 417 +++++++ stream_chat_v1/lib/new_group_chat_screen.dart | 339 ++++++ stream_chat_v1/lib/notifications_service.dart | 38 + stream_chat_v1/lib/routes/app_routes.dart | 93 ++ stream_chat_v1/lib/routes/routes.dart | 13 + stream_chat_v1/lib/search_text_field.dart | 94 ++ stream_chat_v1/lib/stream_version.dart | 39 + stream_chat_v1/pubspec.yaml | 45 + stream_chat_v1/web/favicon.png | Bin 0 -> 917 bytes stream_chat_v1/web/icons/Icon-192.png | Bin 0 -> 5292 bytes stream_chat_v1/web/icons/Icon-512.png | Bin 0 -> 8252 bytes stream_chat_v1/web/index.html | 34 + stream_chat_v1/web/manifest.json | 23 + stream_chat_v1/web/sql-wasm.js | 207 ++++ stream_chat_v1/web/sql-wasm.wasm | Bin 0 -> 1450157 bytes 105 files changed, 7578 insertions(+) create mode 100644 stream_chat_v1/README.md create mode 100644 stream_chat_v1/android/.gitignore create mode 100644 stream_chat_v1/android/app/build.gradle create mode 100644 stream_chat_v1/android/app/debug.keystore create mode 100644 stream_chat_v1/android/app/google-services.json create mode 100644 stream_chat_v1/android/app/src/debug/AndroidManifest.xml create mode 100644 stream_chat_v1/android/app/src/main/AndroidManifest.xml create mode 100644 stream_chat_v1/android/app/src/main/kotlin/com/example/example/Application.kt create mode 100644 stream_chat_v1/android/app/src/main/kotlin/com/example/example/MainActivity.kt create mode 100644 stream_chat_v1/android/app/src/main/res/drawable/launch_background.xml create mode 100644 stream_chat_v1/android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 stream_chat_v1/android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 stream_chat_v1/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 stream_chat_v1/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 stream_chat_v1/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 stream_chat_v1/android/app/src/main/res/values/colors.xml create mode 100644 stream_chat_v1/android/app/src/main/res/values/styles.xml create mode 100644 stream_chat_v1/android/app/src/profile/AndroidManifest.xml create mode 100644 stream_chat_v1/android/build.gradle create mode 100644 stream_chat_v1/android/gradle.properties create mode 100644 stream_chat_v1/android/gradle/wrapper/gradle-wrapper.properties create mode 100644 stream_chat_v1/android/settings.gradle create mode 100644 stream_chat_v1/android/settings_aar.gradle create mode 100644 stream_chat_v1/assets/android_icon.png create mode 100644 stream_chat_v1/assets/floating_boat.json create mode 100644 stream_chat_v1/assets/icon_arrow_right.svg create mode 100644 stream_chat_v1/assets/ios_icon.png create mode 100644 stream_chat_v1/assets/logo.svg create mode 100644 stream_chat_v1/ios/.gitignore create mode 100644 stream_chat_v1/ios/Flutter/.last_build_id create mode 100644 stream_chat_v1/ios/Flutter/AppFrameworkInfo.plist create mode 100644 stream_chat_v1/ios/Flutter/Debug.xcconfig create mode 100644 stream_chat_v1/ios/Flutter/Release.xcconfig create mode 100644 stream_chat_v1/ios/Gemfile create mode 100644 stream_chat_v1/ios/Gemfile.lock create mode 100644 stream_chat_v1/ios/Notifications/Info.plist create mode 100644 stream_chat_v1/ios/Notifications/NotificationService.swift create mode 100644 stream_chat_v1/ios/Notifications/Notifications.entitlements create mode 100644 stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj create mode 100644 stream_chat_v1/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 stream_chat_v1/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 stream_chat_v1/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 stream_chat_v1/ios/Runner.xcodeproj/xcshareddata/xcschemes/Notifications.xcscheme create mode 100644 stream_chat_v1/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 stream_chat_v1/ios/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 stream_chat_v1/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 stream_chat_v1/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 stream_chat_v1/ios/Runner/AppDelegate.swift create mode 100644 stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png create mode 100644 stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png create mode 100644 stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png create mode 100644 stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png create mode 100644 stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png create mode 100644 stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png create mode 100644 stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png create mode 100644 stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png create mode 100644 stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png create mode 100644 stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png create mode 100644 stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png create mode 100644 stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png create mode 100644 stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png create mode 100644 stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png create mode 100644 stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 stream_chat_v1/ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json create mode 100644 stream_chat_v1/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png create mode 100644 stream_chat_v1/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json create mode 100644 stream_chat_v1/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png create mode 100644 stream_chat_v1/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png create mode 100644 stream_chat_v1/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png create mode 100644 stream_chat_v1/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md create mode 100644 stream_chat_v1/ios/Runner/Base.lproj/LaunchScreen.storyboard create mode 100644 stream_chat_v1/ios/Runner/Base.lproj/Main.storyboard create mode 100644 stream_chat_v1/ios/Runner/Info.plist create mode 100644 stream_chat_v1/ios/Runner/Runner-Bridging-Header.h create mode 100644 stream_chat_v1/ios/Runner/Runner.entitlements create mode 100644 stream_chat_v1/ios/fastlane/Appfile create mode 100644 stream_chat_v1/ios/fastlane/Fastfile create mode 100644 stream_chat_v1/ios/fastlane/Matchfile create mode 100644 stream_chat_v1/ios/fastlane/Pluginfile create mode 100644 stream_chat_v1/ios/fastlane/README.md create mode 100644 stream_chat_v1/ios/fastlane/beta_gym_export_options.plist create mode 100644 stream_chat_v1/ios/fastlane/report.xml create mode 100644 stream_chat_v1/lib/advanced_options_page.dart create mode 100644 stream_chat_v1/lib/chat_info_screen.dart create mode 100644 stream_chat_v1/lib/chips_input_text_field.dart create mode 100644 stream_chat_v1/lib/choose_user_page.dart create mode 100644 stream_chat_v1/lib/group_chat_details_screen.dart create mode 100644 stream_chat_v1/lib/group_info_screen.dart create mode 100644 stream_chat_v1/lib/main.dart create mode 100644 stream_chat_v1/lib/new_chat_screen.dart create mode 100644 stream_chat_v1/lib/new_group_chat_screen.dart create mode 100644 stream_chat_v1/lib/notifications_service.dart create mode 100644 stream_chat_v1/lib/routes/app_routes.dart create mode 100644 stream_chat_v1/lib/routes/routes.dart create mode 100644 stream_chat_v1/lib/search_text_field.dart create mode 100644 stream_chat_v1/lib/stream_version.dart create mode 100644 stream_chat_v1/pubspec.yaml create mode 100644 stream_chat_v1/web/favicon.png create mode 100644 stream_chat_v1/web/icons/Icon-192.png create mode 100644 stream_chat_v1/web/icons/Icon-512.png create mode 100644 stream_chat_v1/web/index.html create mode 100644 stream_chat_v1/web/manifest.json create mode 100644 stream_chat_v1/web/sql-wasm.js create mode 100644 stream_chat_v1/web/sql-wasm.wasm diff --git a/stream_chat_v1/README.md b/stream_chat_v1/README.md new file mode 100644 index 0000000000..834bc8d534 --- /dev/null +++ b/stream_chat_v1/README.md @@ -0,0 +1,71 @@ +# Stream Chat v1 + +![](https://raw.githubusercontent.com/GetStream/flutter-samples/master/images/sdk_hero_v4.png) + +Stream Chat V1 is a sample app implemented using Stream Chat and Flutter. It is a fully fledged messaging app built using a combination of our pre-made widgets and custom Flutter widgets. + +It supports several advanced features like: + +- Channels list UI +- Channel UI +- Message reactions +- Link preview +- Image, video and file attachments +- Editing and deleting messages +- Typing indicators +- Read indicators +- Image gallery +- GIF support +- Light and dark themes +- Threads +- Slash commands +- Markdown message formatting +- Count for unread messages + +## Getting Started + +Before running this project please ensure Flutter is installed and configured on your machine. If you're new to Flutter, please checkout the [official guide](https://flutter.dev/docs/get-started/install) with installation instructions for your OS. + + + +This project is only configured to support the following platforms: + +- Android +- iOS + +Web and Desktop are not supported at this time. + +After installing Flutter and the necessary toolchain for your device (Android or iOS), connect your device or open your emulator before running the following: + +**Clone the repo** + +```bash +git clone https://github.com/GetStream/flutter-samples +``` + +**Open the app folder** + +```bash +cd flutter-samples/stream_chat_v1 +``` + +**Install package dependencies:** + +```bash +flutter packages get +``` + +**Open or create an emulator** + +```bash +# To run an emulator, run 'flutter emulators --launch '. +# To create a new emulator, run 'flutter emulators --create [--name xyz]'. +# You can find more information on managing emulators at the links below: +# [https://developer.android.com/studio/run/managing-avds](https://developer.android.com/studio/run/managing-avds)[https://developer.android.com/studio/command-line/avdmanager](https://developer.android.com/studio/command-line/avdmanager) +``` + +**Run the project on your device or emulator:** + +```bash +flutter run +``` diff --git a/stream_chat_v1/android/.gitignore b/stream_chat_v1/android/.gitignore new file mode 100644 index 0000000000..bc2100d8f7 --- /dev/null +++ b/stream_chat_v1/android/.gitignore @@ -0,0 +1,7 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java diff --git a/stream_chat_v1/android/app/build.gradle b/stream_chat_v1/android/app/build.gradle new file mode 100644 index 0000000000..e91ca1bbe0 --- /dev/null +++ b/stream_chat_v1/android/app/build.gradle @@ -0,0 +1,80 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + compileSdkVersion 29 + ndkVersion '21.4.7075529' + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + lintOptions { + disable 'InvalidPackage' + checkReleaseBuilds false + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.example.example" + minSdkVersion 21 + targetSdkVersion 29 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + signingConfigs { + debug { + storeFile file('debug.keystore') + storePassword 'android' + keyAlias 'androiddebugkey' + keyPassword 'android' + } + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test:runner:1.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' + implementation 'com.google.firebase:firebase-messaging:20.1.2' +} + +apply plugin: 'com.google.gms.google-services' diff --git a/stream_chat_v1/android/app/debug.keystore b/stream_chat_v1/android/app/debug.keystore new file mode 100644 index 0000000000000000000000000000000000000000..cdfc792b63fa962b13c94ababd37bff37a677354 GIT binary patch literal 2105 zcmbW1Ydq5p8^`yb8JlAfC5)e@D*al4pRw zx2NZYKZ2;f7eY6AP*31cHwYvSpy?1HS{4e|g#r*j2fPIU#6b``WEz+9C@Li^8)M}8 zm{?b`pm^A4(Am+;!`xToR*D-P{It-`b9{&@76aYohdWC8AGkP0m zNX2OVnx@{>QjHV=JaqC?nM)%tsoaBnc8Ne)UQ@Q`*YX%2mWa8tCXH@nN5kO(-3mFP z@%IYoSCDE$HA@E(*uA}?8TVI2tR#G+#C%F`Z_0e`wF;m#W@Pns;Qb`K?eajaQ z57+pg?aPKqJ6?R%=BRSH8)XxOM@AEFhbBX%xQm| z>JlQpi>y)W{E+sXfxu;6J@L^tdKe+ z#`?4f1H&aBbaW+y*wigEi0DUVdwKXY%FMRxhUg9q5OeD&a!0MjFx*6<_hQa3b#AM1 zxohqKuyP`=v-QU0zH48K{cyulacep?_#DyCfcjGn?T6)yO7_ba63*3*>5zQ|m$AV^ z`C5)qW`}PS$mNcWle3#N67EUdGR&dPxCHy@lHz$?^B>Ea#lJOVi8!N9B@a znozDyl-Ai^teD6a|5VeXy zp%BAZkNcquj=)j|y9mBNBL>n*T5(KN)Tj)8rh1v26`Vd5-Rjzym==3F8Og=8pLN@i z1wW-I;&EjQn$t>3k!{b)%{pGewAaw0xl3VO2c#iA5Pli+c(qj`^PC68eyQ$Pi(br9 z3=y0DbK2|$0n6yeo5Qe-#w~A|ChdX`ejes{-5Ps$ifSltQKG`_PMdFZxO4QKwqzwi zicFqG564uPxJ`Ap6d>4vs+1m|x7=a1B>2JddP9mhUgkkRU@4D!_wmcs`UvLb#&J-K zNO>sTdSHh^I%t|THM-#bCOj-W3h*}_&kH#3REYNjs1tEbLT61lc$beCc%kgbx704k zsdGhDn7nRp$|NXY_(z5*3emz9d#Fr%9~LT)WjVZ!8w! z+pWOD-;4B7mM^Aco|JKSPFtN@gcG(4Nw1vWGMg1r~*;krO^QyF*T85}*fm>ium<@$&{I zXtPacPNC`GF*F@$1_Jzh27@t0o1ym^n>ufoGeVpE2Izml|38`zApg7O zro6@IfE;LZ12~ut0HDa*q@6bSL}JGc#yhgiUM^bpxz^jOJTTxLEO^~|sCw9tKf90~ zsxdG*=rjye(d#+(_5om8n1eO0>DZ$ULOSH9H781Amdj@})N z`%^_V#nnp8kk#qZ@L{K(LWoUK#_Z%{)EWPSyV}o+Su*CYkd_1c3I6H$@Q^ept8;ieYZ?;X{|wcLXp zC(F*BN~QrtThp5wbk4&(7^Hg45fvJuAYOOdmz5M1ZhwO)SCMJ){RB2d-dPWfggrM& z>&YUyr*^Y?#;Y6iP|$&;KKNBp7&(J!4Dagq2|=`-JQUfNyA0BXhlM2Sdt1kFmxKSX l(9lMG;rd4yhX&iG*Lg|sXum9Y^S!PY%4kv}X?@nE{|5I{xpM#j literal 0 HcmV?d00001 diff --git a/stream_chat_v1/android/app/google-services.json b/stream_chat_v1/android/app/google-services.json new file mode 100644 index 0000000000..261138303a --- /dev/null +++ b/stream_chat_v1/android/app/google-services.json @@ -0,0 +1,40 @@ +{ + "project_info": { + "project_number": "1004276287628", + "firebase_url": "https://test-a0490.firebaseio.com", + "project_id": "test-a0490", + "storage_bucket": "test-a0490.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:1004276287628:android:7fff771d5e464c6a5f93a9", + "android_client_info": { + "package_name": "com.example.example" + } + }, + "oauth_client": [ + { + "client_id": "1004276287628-43j2uub5rd0968ois7h963i0np373t6k.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyC2ESbd8qWtIUWwGn1L_Dbxzh2W6yfGqiU" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "1004276287628-43j2uub5rd0968ois7h963i0np373t6k.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/stream_chat_v1/android/app/src/debug/AndroidManifest.xml b/stream_chat_v1/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000000..c208884f30 --- /dev/null +++ b/stream_chat_v1/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/stream_chat_v1/android/app/src/main/AndroidManifest.xml b/stream_chat_v1/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..0492c6da87 --- /dev/null +++ b/stream_chat_v1/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/stream_chat_v1/android/app/src/main/kotlin/com/example/example/Application.kt b/stream_chat_v1/android/app/src/main/kotlin/com/example/example/Application.kt new file mode 100644 index 0000000000..d32cec4de0 --- /dev/null +++ b/stream_chat_v1/android/app/src/main/kotlin/com/example/example/Application.kt @@ -0,0 +1,23 @@ +package com.example.example + +import com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin +import io.flutter.app.FlutterApplication +import io.flutter.plugin.common.PluginRegistry +import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback +import io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin +import io.flutter.plugins.pathprovider.PathProviderPlugin + +class Application : FlutterApplication(), PluginRegistrantCallback { + override fun onCreate() { + super.onCreate() + } + + override fun registerWith(registry: PluginRegistry?) { + PathProviderPlugin.registerWith(registry?.registrarFor( + "io.flutter.plugins.pathprovider.PathProviderPlugin")) + SharedPreferencesPlugin.registerWith(registry?.registrarFor( + "io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin")) + FlutterLocalNotificationsPlugin.registerWith(registry?.registrarFor( + "com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin")) + } +} \ No newline at end of file diff --git a/stream_chat_v1/android/app/src/main/kotlin/com/example/example/MainActivity.kt b/stream_chat_v1/android/app/src/main/kotlin/com/example/example/MainActivity.kt new file mode 100644 index 0000000000..1656503f3f --- /dev/null +++ b/stream_chat_v1/android/app/src/main/kotlin/com/example/example/MainActivity.kt @@ -0,0 +1,12 @@ +package com.example.example + +import androidx.annotation.NonNull; +import io.flutter.embedding.android.FlutterActivity +import io.flutter.embedding.engine.FlutterEngine +import io.flutter.plugins.GeneratedPluginRegistrant + +class MainActivity: FlutterActivity() { + override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { + GeneratedPluginRegistrant.registerWith(flutterEngine); + } +} diff --git a/stream_chat_v1/android/app/src/main/res/drawable/launch_background.xml b/stream_chat_v1/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 0000000000..3618fa7ad7 --- /dev/null +++ b/stream_chat_v1/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/stream_chat_v1/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/stream_chat_v1/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..91797672c7ce9b88327a8f87325cb5895ca0c0d4 GIT binary patch literal 5905 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 literal 0 HcmV?d00001 diff --git a/stream_chat_v1/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/stream_chat_v1/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..103da98b58d1b062818d94e10cae84e7c85d04cf GIT binary patch literal 3283 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 literal 0 HcmV?d00001 diff --git a/stream_chat_v1/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/stream_chat_v1/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..fc254c2599eae9c57035df9afa482e4a3fddf8c8 GIT binary patch literal 21173 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 Y0}D + + #005fff + \ No newline at end of file diff --git a/stream_chat_v1/android/app/src/main/res/values/styles.xml b/stream_chat_v1/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000000..00fa4417cf --- /dev/null +++ b/stream_chat_v1/android/app/src/main/res/values/styles.xml @@ -0,0 +1,8 @@ + + + + diff --git a/stream_chat_v1/android/app/src/profile/AndroidManifest.xml b/stream_chat_v1/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000000..c208884f30 --- /dev/null +++ b/stream_chat_v1/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/stream_chat_v1/android/build.gradle b/stream_chat_v1/android/build.gradle new file mode 100644 index 0000000000..8c57e18a0f --- /dev/null +++ b/stream_chat_v1/android/build.gradle @@ -0,0 +1,32 @@ +buildscript { + ext.kotlin_version = '1.3.50' + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.6.2' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + classpath 'com.google.gms:google-services:4.3.2' + } +} + +allprojects { + repositories { + google() + jcenter() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/stream_chat_v1/android/gradle.properties b/stream_chat_v1/android/gradle.properties new file mode 100644 index 0000000000..38c8d4544f --- /dev/null +++ b/stream_chat_v1/android/gradle.properties @@ -0,0 +1,4 @@ +org.gradle.jvmargs=-Xmx1536M +android.enableR8=true +android.useAndroidX=true +android.enableJetifier=true diff --git a/stream_chat_v1/android/gradle/wrapper/gradle-wrapper.properties b/stream_chat_v1/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..4a4c204382 --- /dev/null +++ b/stream_chat_v1/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Thu Oct 22 11:03:39 CEST 2020 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip diff --git a/stream_chat_v1/android/settings.gradle b/stream_chat_v1/android/settings.gradle new file mode 100644 index 0000000000..5a2f14fb18 --- /dev/null +++ b/stream_chat_v1/android/settings.gradle @@ -0,0 +1,15 @@ +include ':app' + +def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() + +def plugins = new Properties() +def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') +if (pluginsFile.exists()) { + pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } +} + +plugins.each { name, path -> + def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() + include ":$name" + project(":$name").projectDir = pluginDirectory +} diff --git a/stream_chat_v1/android/settings_aar.gradle b/stream_chat_v1/android/settings_aar.gradle new file mode 100644 index 0000000000..e7b4def49c --- /dev/null +++ b/stream_chat_v1/android/settings_aar.gradle @@ -0,0 +1 @@ +include ':app' diff --git a/stream_chat_v1/assets/android_icon.png b/stream_chat_v1/assets/android_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3b85d6c36f7b5e617a7bca1c85d5c9b524890d5b GIT binary patch literal 15354 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 literal 0 HcmV?d00001 diff --git a/stream_chat_v1/assets/floating_boat.json b/stream_chat_v1/assets/floating_boat.json new file mode 100644 index 0000000000..a9a5171ab3 --- /dev/null +++ b/stream_chat_v1/assets/floating_boat.json @@ -0,0 +1 @@ +{"v":"5.7.4","fr":30,"ip":0,"op":226,"w":360,"h":360,"nm":"Ext Comp","ddd":0,"assets":[{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Front wave","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":20,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":50,"s":[70]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":205,"s":[70]},{"t":225,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":0,"s":[1564.796,242,0],"to":[-407.163,0,0],"ti":[289.072,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":215,"s":[-224,242,0],"to":[-312,0,0],"ti":[312,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":216,"s":[1648,242,0],"to":[-2.701,0,0],"ti":[2.84,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":217,"s":[1639.687,242,0],"to":[-2.71,0,0],"ti":[2.834,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":218,"s":[1631.371,242,0],"to":[-2.716,0,0],"ti":[2.829,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":219,"s":[1623.052,242,0],"to":[-2.722,0,0],"ti":[2.824,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":220,"s":[1614.733,242,0],"to":[-2.727,0,0],"ti":[2.82,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":221,"s":[1606.412,242,0],"to":[-2.731,0,0],"ti":[2.817,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":222,"s":[1598.09,242,0],"to":[-2.734,0,0],"ti":[2.814,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":223,"s":[1589.767,242,0],"to":[-2.737,0,0],"ti":[2.812,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":224,"s":[1581.444,242,0],"to":[-2.739,0,0],"ti":[2.809,0,0]},{"t":225,"s":[1573.12,242,0]}],"ix":2,"l":2},"a":{"a":0,"k":[1406.5,240,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[19.62,7.876],[40.177,0],[19.63,-7.88],[37.902,0],[19.621,7.876],[40.178,0],[19.63,-7.88],[37.901,0],[19.62,7.876],[40.178,0],[19.629,-7.88],[37.901,0],[19.62,7.876],[40.178,0],[19.63,-7.88],[37.902,0],[19.621,7.876],[40.178,0],[19.63,-7.88],[37.901,0],[19.62,7.876],[40.178,0],[19.629,-7.88],[37.901,0],[19.62,7.876],[40.178,0],[19.63,-7.88],[37.902,0],[19.621,7.876],[40.178,0],[19.63,-7.88],[37.901,0],[19.621,7.876],[40.177,0],[19.63,-7.88],[37.9,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[-19.63,-7.88],[-40.178,0],[-19.621,7.876],[-37.901,0],[-19.629,-7.88],[-40.178,0],[-19.62,7.876],[-37.901,0],[-19.629,-7.88],[-40.177,0],[-19.62,7.876],[-37.901,0],[-19.629,-7.88],[-40.178,0],[-19.62,7.876],[-37.901,0],[-19.629,-7.88],[-40.178,0],[-19.62,7.876],[-37.9,0],[-19.629,-7.88],[-40.177,0],[-19.62,7.876],[-37.901,0],[-19.63,-7.88],[-40.178,0],[-19.62,7.876],[-37.9,0],[-19.629,-7.88],[-40.178,0],[-19.62,7.876],[-37.9,0],[-19.629,-7.88],[-40.178,0],[-19.62,7.876],[0,0],[0,0],[0,0],[0,0],[0,0],[-37.901,0]],"v":[[1329.527,-98.735],[1249.415,-114.762],[1169.312,-98.735],[1093.266,-83.422],[1017.211,-98.735],[937.099,-114.762],[856.987,-98.735],[780.932,-83.422],[704.877,-98.735],[624.765,-114.762],[544.653,-98.735],[468.598,-83.422],[392.543,-98.735],[312.431,-114.762],[232.328,-98.735],[156.282,-83.422],[80.227,-98.735],[0.115,-114.762],[-79.997,-98.735],[-156.052,-83.422],[-232.107,-98.735],[-312.219,-114.762],[-392.331,-98.735],[-468.386,-83.422],[-544.441,-98.735],[-624.553,-114.762],[-704.656,-98.735],[-780.702,-83.422],[-856.757,-98.735],[-936.869,-114.762],[-1016.981,-98.735],[-1093.036,-83.422],[-1169.091,-98.735],[-1249.202,-114.762],[-1329.315,-98.735],[-1405.369,-83.422],[-1405.369,169.836],[-468.386,169.836],[468.598,169.836],[1405.582,169.836],[1405.582,-83.422]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.539331054688,0.709956449621,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[1407.045,365.237],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-10,"op":230,"st":-10,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"paper boat Outlines","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[359.816]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":1,"s":[362.408]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":2,"s":[364.96]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":3,"s":[364.96]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":4,"s":[367.509]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":5,"s":[370.002]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":6,"s":[372.212]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":7,"s":[374.185]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":8,"s":[374.185]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":9,"s":[375.787]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[377.003]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":11,"s":[377.809]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":12,"s":[378.081]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":13,"s":[378.081]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":14,"s":[377.884]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":15,"s":[377.367]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":16,"s":[376.545]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":17,"s":[375.456]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":18,"s":[375.456]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":19,"s":[373.961]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":20,"s":[372.364]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":21,"s":[370.531]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":22,"s":[368.674]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":23,"s":[368.535]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":24,"s":[366.661]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":25,"s":[364.561]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":26,"s":[362.474]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":27,"s":[360.211]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":28,"s":[360.211]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":29,"s":[358.249]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":30,"s":[356.135]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":31,"s":[354.276]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":32,"s":[352.507]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":33,"s":[352.475]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":34,"s":[350.878]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":35,"s":[349.403]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":36,"s":[348.362]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":37,"s":[347.373]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":38,"s":[347.373]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":39,"s":[346.854]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":40,"s":[346.737]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":41,"s":[346.824]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":42,"s":[347.457]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":43,"s":[347.457]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":44,"s":[348.301]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":45,"s":[349.417]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":46,"s":[350.785]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":47,"s":[352.361]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":48,"s":[352.361]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":49,"s":[354.248]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":50,"s":[356.159]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":51,"s":[358.144]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":52,"s":[360.292]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":53,"s":[360.292]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":54,"s":[362.443]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":55,"s":[364.472]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":56,"s":[366.651]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":57,"s":[368.573]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":58,"s":[368.654]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":59,"s":[370.617]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":60,"s":[372.391]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":61,"s":[373.907]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":62,"s":[375.317]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":63,"s":[375.317]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":64,"s":[376.536]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":65,"s":[377.362]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":66,"s":[377.972]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":67,"s":[378.121]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":68,"s":[378.127]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":69,"s":[377.717]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":70,"s":[377.034]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":71,"s":[375.71]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":72,"s":[374.172]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":73,"s":[374.172]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":74,"s":[372.214]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":75,"s":[369.93]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":76,"s":[367.585]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":77,"s":[365.093]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":78,"s":[365.093]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":79,"s":[362.408]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":80,"s":[359.734]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":81,"s":[357.283]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":82,"s":[354.86]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":83,"s":[354.86]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":84,"s":[352.722]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":85,"s":[350.694]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":86,"s":[349.019]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":87,"s":[347.739]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":88,"s":[347.739]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":89,"s":[346.982]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":90,"s":[346.654]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":91,"s":[346.921]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":92,"s":[347.453]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":93,"s":[347.453]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":94,"s":[348.361]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":95,"s":[349.61]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":96,"s":[351.115]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":97,"s":[352.934]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":98,"s":[352.906]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":99,"s":[354.785]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":100,"s":[356.923]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":101,"s":[359.038]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":102,"s":[361.22]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":103,"s":[361.218]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":104,"s":[363.451]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":105,"s":[365.537]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":106,"s":[367.834]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":107,"s":[369.833]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":108,"s":[369.844]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":109,"s":[371.875]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":110,"s":[373.629]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":111,"s":[375.077]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":112,"s":[376.301]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":113,"s":[376.348]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":114,"s":[377.198]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":115,"s":[377.773]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":116,"s":[378.027]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":117,"s":[377.93]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":118,"s":[377.93]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":119,"s":[377.558]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":120,"s":[376.838]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":121,"s":[376.02]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":122,"s":[374.966]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":123,"s":[374.966]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":124,"s":[373.749]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":125,"s":[372.452]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":126,"s":[370.997]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":127,"s":[369.351]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":128,"s":[369.351]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":129,"s":[367.601]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":130,"s":[365.932]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":131,"s":[364.137]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":132,"s":[362.401]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":133,"s":[362.401]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":134,"s":[360.608]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":135,"s":[358.776]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":136,"s":[357.057]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":137,"s":[355.366]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":138,"s":[355.424]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":139,"s":[353.834]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":140,"s":[352.22]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":141,"s":[351.013]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":142,"s":[349.682]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":143,"s":[349.682]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":144,"s":[348.61]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":145,"s":[347.828]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":146,"s":[347.196]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":147,"s":[346.844]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":148,"s":[346.845]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":149,"s":[346.754]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[346.778]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":151,"s":[347.155]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":152,"s":[347.78]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":153,"s":[347.786]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[348.565]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":155,"s":[349.573]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":156,"s":[350.623]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":157,"s":[351.876]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":158,"s":[351.876]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":159,"s":[353.337]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":160,"s":[354.852]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":161,"s":[356.456]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":162,"s":[358.113]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":163,"s":[358.113]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":164,"s":[359.784]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":165,"s":[361.494]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":166,"s":[363.422]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":167,"s":[364.954]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":168,"s":[364.954]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":169,"s":[366.765]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":170,"s":[368.359]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":171,"s":[369.99]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":172,"s":[371.474]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":173,"s":[371.474]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":174,"s":[372.897]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":175,"s":[374.157]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":176,"s":[375.283]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":177,"s":[376.254]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":178,"s":[376.254]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":179,"s":[377.071]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":180,"s":[377.607]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":181,"s":[377.995]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":182,"s":[378.109]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":183,"s":[378.109]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":184,"s":[377.974]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":185,"s":[377.501]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":186,"s":[376.949]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":187,"s":[376.064]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":188,"s":[376.064]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":189,"s":[375.027]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":190,"s":[373.889]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":191,"s":[372.628]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":192,"s":[370.922]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":193,"s":[370.922]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":194,"s":[369.356]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":195,"s":[367.62]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":196,"s":[365.906]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":197,"s":[364.196]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":198,"s":[364.196]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":199,"s":[362.428]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":200,"s":[360.629]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":201,"s":[358.858]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":202,"s":[357.076]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":203,"s":[357.076]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":204,"s":[355.464]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":205,"s":[353.751]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":206,"s":[352.269]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":207,"s":[350.957]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":208,"s":[351.027]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":209,"s":[349.752]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":210,"s":[348.702]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":211,"s":[347.877]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":212,"s":[347.188]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":213,"s":[347.136]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":214,"s":[346.854]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":215,"s":[346.729]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":216,"s":[346.754]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":217,"s":[346.889]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":218,"s":[347.787]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":219,"s":[347.787]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":220,"s":[348.996]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":221,"s":[350.562]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":222,"s":[352.621]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":223,"s":[354.806]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":224,"s":[354.775]},{"t":225,"s":[357.252]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":0,"s":[498.155,211.72,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":1,"s":[499.562,204.275,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":2,"s":[500.994,197.036,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":3,"s":[500.994,197.036,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":4,"s":[502.521,190.4,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":5,"s":[504,184.122,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":6,"s":[505.5,178.992,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":7,"s":[507,174.779,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":8,"s":[507,174.779,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":9,"s":[508.497,172.225,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":10,"s":[509.35,170.862,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":11,"s":[510.111,170.874,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":12,"s":[510.653,172.148,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":13,"s":[510.653,172.148,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":14,"s":[510.645,174.504,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":15,"s":[509.933,177.709,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":16,"s":[508.62,181.312,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":17,"s":[507.858,185.812,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":18,"s":[507.858,185.812,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":19,"s":[507.056,191.338,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":20,"s":[506.124,196.588,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":21,"s":[504.132,202.312,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":22,"s":[503.25,207.8,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":23,"s":[503.191,208.312,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":24,"s":[501.75,213.771,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":25,"s":[500.851,219.381,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":26,"s":[499.5,224.338,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":27,"s":[498.683,229.811,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":28,"s":[498.683,229.811,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":29,"s":[497.886,233.812,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":30,"s":[497.147,237.39,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":31,"s":[496.541,239.892,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":32,"s":[496.055,241.254,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":33,"s":[496.055,241.254,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":34,"s":[496.014,241.813,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":35,"s":[495.905,241.6,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":36,"s":[495.674,240.141,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":37,"s":[495.75,238.494,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":38,"s":[495.75,238.494,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":39,"s":[495.686,235.799,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":40,"s":[495.48,232.447,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":41,"s":[495.938,228.756,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":42,"s":[495.615,224.423,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":43,"s":[495.615,224.423,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":44,"s":[495.501,220.011,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":45,"s":[495.882,215.83,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":46,"s":[495.753,211.6,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":47,"s":[496.336,207.891,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":48,"s":[496.336,207.891,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":49,"s":[496.5,204.545,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":50,"s":[497.08,201.902,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":51,"s":[497.804,199.942,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":52,"s":[498.557,198.562,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":53,"s":[498.557,198.562,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":54,"s":[499.477,197.812,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":55,"s":[500.774,197.774,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":56,"s":[501.847,197.936,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":57,"s":[503.25,198.791,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":58,"s":[503.25,198.791,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":59,"s":[504.1,199.204,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":60,"s":[505.5,200.062,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":61,"s":[506.979,201.337,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":62,"s":[507.75,202.225,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":63,"s":[507.75,202.225,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":64,"s":[509.162,203.306,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":65,"s":[509.335,203.874,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":66,"s":[510.044,204.656,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":67,"s":[510.044,204.674,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":68,"s":[510.047,204.68,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":69,"s":[510.021,205.028,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":70,"s":[509.25,204.486,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":71,"s":[508.468,204.475,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":72,"s":[507,204.012,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":73,"s":[507,204.012,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":74,"s":[505.553,203.821,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":75,"s":[504.067,203.877,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":76,"s":[502.447,203.748,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":77,"s":[500.936,203.78,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":78,"s":[500.936,203.78,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":79,"s":[499.523,204.278,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":80,"s":[498.645,205.157,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":81,"s":[497.836,206.01,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":82,"s":[496.723,207.161,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":83,"s":[496.723,207.161,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":84,"s":[495.873,208.614,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":85,"s":[495.75,210.41,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":86,"s":[495.521,212.607,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":87,"s":[495.75,215.215,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":88,"s":[495.75,215.215,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":89,"s":[495.46,217.714,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":90,"s":[495.378,220.471,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":91,"s":[495.457,222.952,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":92,"s":[495.75,225.741,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":93,"s":[495.75,225.741,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":94,"s":[495.785,227.859,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":95,"s":[495.545,229.688,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":96,"s":[495.917,231.188,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":97,"s":[496.058,231.938,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":98,"s":[496.058,231.938,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":99,"s":[497.065,232.427,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":100,"s":[497.291,231.938,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":101,"s":[498.29,230.886,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":102,"s":[499.266,228.993,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":103,"s":[499.274,228.999,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":104,"s":[500.121,226.005,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":105,"s":[501.659,222.771,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":106,"s":[502.562,218.212,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":107,"s":[504,213.457,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":108,"s":[504.029,213.419,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":109,"s":[505.5,208.14,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":110,"s":[506.329,202.632,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":111,"s":[507.867,197.827,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":112,"s":[508.597,192.894,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":113,"s":[508.614,192.715,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":114,"s":[509.3,188.194,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":115,"s":[510,184.242,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":116,"s":[510.047,180.308,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":117,"s":[510.05,177.668,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":118,"s":[510.05,177.668,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":119,"s":[509.956,175.462,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":120,"s":[509.312,174.352,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":121,"s":[508.562,173.596,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":122,"s":[507.727,173.698,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":123,"s":[507.727,173.698,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":124,"s":[506.974,175.04,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":125,"s":[506.162,177.472,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":126,"s":[504.75,180.562,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":127,"s":[503.892,185.062,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":128,"s":[503.892,185.062,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":129,"s":[502.582,190.16,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":130,"s":[501.668,195.738,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":131,"s":[500.414,201.647,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":132,"s":[499.603,207.911,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":133,"s":[499.603,207.911,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":134,"s":[498.647,214.125,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":135,"s":[498.035,220.588,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":136,"s":[497.329,226.62,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":137,"s":[496.934,232.222,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":138,"s":[496.764,232.017,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":139,"s":[496.315,237.217,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":140,"s":[496.438,241.688,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":141,"s":[495.724,244.931,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":142,"s":[495.984,247.57,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":143,"s":[495.984,247.57,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":144,"s":[495.618,248.733,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":145,"s":[495.586,248.643,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":146,"s":[495.63,247.72,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":147,"s":[495.387,245.628,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":148,"s":[495.387,245.625,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":149,"s":[495.422,242.812,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":150,"s":[495.627,239.438,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":151,"s":[495.577,235.312,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":152,"s":[495.393,230.625,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":153,"s":[495.393,230.625,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":154,"s":[495.595,225.905,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":155,"s":[495.375,220.925,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":156,"s":[496.075,216.354,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":157,"s":[496.33,211.863,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":158,"s":[496.33,211.863,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":159,"s":[496.33,207.363,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":160,"s":[497.077,203.971,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":161,"s":[497.391,200.936,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":162,"s":[497.833,198.724,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":163,"s":[497.833,198.724,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":164,"s":[498.598,197.701,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":165,"s":[499.354,197.323,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":166,"s":[499.673,197.115,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":167,"s":[500.95,198.302,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":168,"s":[500.95,198.302,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":169,"s":[501.715,199.204,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":170,"s":[502.597,200.575,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":171,"s":[504,202.195,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":172,"s":[504.882,203.599,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":173,"s":[504.882,203.599,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":174,"s":[506.224,205.102,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":175,"s":[507.041,206.32,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":176,"s":[507.797,206.921,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":177,"s":[508.538,207.056,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":178,"s":[508.538,207.059,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":179,"s":[509.306,206.446,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":180,"s":[509.947,205.271,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":181,"s":[510.067,203.684,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":182,"s":[510.12,201.809,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":183,"s":[510.12,201.809,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":184,"s":[510.105,199.397,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":185,"s":[510,197.543,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":186,"s":[509.361,195.108,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":187,"s":[508.6,193.037,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":188,"s":[508.6,193.037,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":189,"s":[507.768,191.303,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":190,"s":[506.938,189.434,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":191,"s":[505.608,187.846,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":192,"s":[504.776,187.465,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":193,"s":[504.773,187.462,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":194,"s":[503.924,187.248,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":195,"s":[502.5,187.122,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":196,"s":[501.727,188.013,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":197,"s":[500.37,189.24,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":198,"s":[500.37,189.24,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":199,"s":[499.5,191.32,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":200,"s":[498.759,194.988,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":201,"s":[498.038,199.506,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":202,"s":[497.279,204.773,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":203,"s":[497.279,204.773,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":204,"s":[496.617,210.615,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":205,"s":[496.441,217.008,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":206,"s":[496.277,223.312,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":207,"s":[495.882,229.626,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":208,"s":[495.955,229.351,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":209,"s":[495.803,235.567,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":210,"s":[495.762,240.929,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":211,"s":[495.422,245.508,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":212,"s":[495.51,249.252,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":213,"s":[495.51,249.252,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":214,"s":[495.633,251.599,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":215,"s":[495.621,252.082,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":216,"s":[495.375,252.188,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":217,"s":[495.75,251.625,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":218,"s":[495.633,248.812,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":219,"s":[495.633,248.812,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":220,"s":[495.647,244.799,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":221,"s":[496.342,239.812,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":222,"s":[495.946,233.534,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":223,"s":[496.808,226.711,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":224,"s":[496.978,226.778,0],"to":[0,0,0],"ti":[0,0,0]},{"t":225,"s":[497.487,219.478,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-5,28.4,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[50.022,0.594],[83.038,-11.929],[41.526,-8.954]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-50.332,0.594],[-41.834,-8.954],[-83.347,-11.929]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[2.707,18.338],[39.636,4.437],[2.707,-37.245]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-2.572,18.338],[-2.572,-37.252],[-39.501,4.437]],"c":true},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ind":4,"ty":"sh","ix":5,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[7.715,22.194],[52.881,39.053],[86.11,-7.135]],"c":true},"ix":2},"nm":"Path 5","mn":"ADBE Vector Shape - Group","hd":false},{"ind":5,"ty":"sh","ix":6,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-7.715,22.194],[-86.109,-7.135],[-52.881,39.053]],"c":true},"ix":2},"nm":"Path 6","mn":"ADBE Vector Shape - Group","hd":false},{"ind":6,"ty":"sh","ix":7,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-2.614,42.661],[-2.614,26.14],[-46.82,42.661]],"c":true},"ix":2},"nm":"Path 7","mn":"ADBE Vector Shape - Group","hd":false},{"ind":7,"ty":"sh","ix":8,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[46.913,42.661],[2.707,26.14],[2.707,42.661]],"c":true},"ix":2},"nm":"Path 8","mn":"ADBE Vector Shape - Group","hd":false},{"ind":8,"ty":"sh","ix":9,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[2.629,-3.661],[0,0],[1.714,0],[0,0],[1,1.389],[0,0],[-4.499,-0.32],[0,0],[0,0],[-2.108,-2.393]],"o":[[0,0],[4.496,-0.319],[0,0],[-0.999,1.392],[0,0],[-1.711,0],[0,0],[-2.635,-3.661],[0,0],[0,0],[2.125,-2.376],[0,0]],"v":[[32.648,-18.986],[100.763,-23.814],[105.461,-15.405],[57.812,50.966],[53.491,53.184],[-53.364,53.184],[-57.682,50.972],[-105.458,-15.399],[-100.763,-23.814],[-32.854,-18.985],[-3.85,-51.411],[4.108,-51.381]],"c":true},"ix":2},"nm":"Path 9","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[106.472,53.184],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":13,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-96.851,-15.276],[-56.693,45.196],[47.875,46.299],[96.85,-18.425],[30.079,-15.591],[-1.89,-46.299],[-36.536,-14.961]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0.405691139371,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[109.748,54.329],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":-10,"op":230,"st":-10,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Back wave","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":11,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":41,"s":[30]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":200,"s":[30]},{"t":220,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":0,"s":[1426.53,243,0],"to":[-339.955,0,0],"ti":[241.357,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":215,"s":[-67,243,0],"to":[-260.5,0,0],"ti":[260.5,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":216,"s":[1496,243,0],"to":[-2.255,0,0],"ti":[2.372,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":217,"s":[1489.059,243,0],"to":[-2.262,0,0],"ti":[2.366,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":218,"s":[1482.115,243,0],"to":[-2.268,0,0],"ti":[2.362,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":219,"s":[1475.17,243,0],"to":[-2.273,0,0],"ti":[2.358,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":220,"s":[1468.224,243,0],"to":[-2.277,0,0],"ti":[2.355,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":221,"s":[1461.276,243,0],"to":[-2.28,0,0],"ti":[2.352,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":222,"s":[1454.328,243,0],"to":[-2.283,0,0],"ti":[2.35,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":223,"s":[1447.379,243,0],"to":[-2.285,0,0],"ti":[2.348,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":224,"s":[1440.43,243,0],"to":[-2.287,0,0],"ti":[2.346,0,0]},{"t":225,"s":[1433.48,243,0]}],"ix":2,"l":2},"a":{"a":0,"k":[1406.5,240,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[19.62,7.876],[40.177,0],[19.63,-7.88],[37.902,0],[19.621,7.876],[40.178,0],[19.63,-7.88],[37.901,0],[19.62,7.876],[40.178,0],[19.629,-7.88],[37.901,0],[19.62,7.876],[40.178,0],[19.63,-7.88],[37.902,0],[19.621,7.876],[40.178,0],[19.63,-7.88],[37.901,0],[19.62,7.876],[40.178,0],[19.629,-7.88],[37.901,0],[19.62,7.876],[40.178,0],[19.63,-7.88],[37.902,0],[19.621,7.876],[40.178,0],[19.63,-7.88],[37.901,0],[19.621,7.876],[40.177,0],[19.63,-7.88],[37.9,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[-19.63,-7.88],[-40.178,0],[-19.621,7.876],[-37.901,0],[-19.629,-7.88],[-40.178,0],[-19.62,7.876],[-37.901,0],[-19.629,-7.88],[-40.177,0],[-19.62,7.876],[-37.901,0],[-19.629,-7.88],[-40.178,0],[-19.62,7.876],[-37.901,0],[-19.629,-7.88],[-40.178,0],[-19.62,7.876],[-37.9,0],[-19.629,-7.88],[-40.177,0],[-19.62,7.876],[-37.901,0],[-19.63,-7.88],[-40.178,0],[-19.62,7.876],[-37.9,0],[-19.629,-7.88],[-40.178,0],[-19.62,7.876],[-37.9,0],[-19.629,-7.88],[-40.178,0],[-19.62,7.876],[0,0],[0,0],[0,0],[0,0],[0,0],[-37.901,0]],"v":[[1329.527,-98.735],[1249.415,-114.762],[1169.312,-98.735],[1093.266,-83.422],[1017.211,-98.735],[937.099,-114.762],[856.987,-98.735],[780.932,-83.422],[704.877,-98.735],[624.765,-114.762],[544.653,-98.735],[468.598,-83.422],[392.543,-98.735],[312.431,-114.762],[232.328,-98.735],[156.282,-83.422],[80.227,-98.735],[0.115,-114.762],[-79.997,-98.735],[-156.052,-83.422],[-232.107,-98.735],[-312.219,-114.762],[-392.331,-98.735],[-468.386,-83.422],[-544.441,-98.735],[-624.553,-114.762],[-704.656,-98.735],[-780.702,-83.422],[-856.757,-98.735],[-936.869,-114.762],[-1016.981,-98.735],[-1093.036,-83.422],[-1169.091,-98.735],[-1249.202,-114.762],[-1329.315,-98.735],[-1405.369,-83.422],[-1405.369,169.836],[-468.386,169.836],[468.598,169.836],[1405.582,169.836],[1405.582,-83.422]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.539331054688,0.709956449621,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[1407.045,365.237],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-10,"op":230,"st":-10,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"Inner comp","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[180,180,0],"ix":2,"l":2},"a":{"a":0,"k":[600,240,0],"ix":1,"l":2},"s":{"a":0,"k":[30.6,30.6,100],"ix":6,"l":2}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"a","pt":{"a":0,"k":{"i":[[108.108,0],[0,-108.108],[-108.108,0],[0,108.108]],"o":[[-108.108,0],[0,108.108],[108.108,0],[0,-108.108]],"v":[[600,42.62],[404.254,238.366],[600,434.112],[795.746,238.366]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 2"}],"w":1200,"h":480,"ip":0,"op":240,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/stream_chat_v1/assets/icon_arrow_right.svg b/stream_chat_v1/assets/icon_arrow_right.svg new file mode 100644 index 0000000000..7cfa0c5601 --- /dev/null +++ b/stream_chat_v1/assets/icon_arrow_right.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/stream_chat_v1/assets/ios_icon.png b/stream_chat_v1/assets/ios_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..314eb1db06c8771bc18c08234ab84940adfb033a GIT binary patch literal 40617 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 c8n + + diff --git a/stream_chat_v1/ios/.gitignore b/stream_chat_v1/ios/.gitignore new file mode 100644 index 0000000000..e96ef602b8 --- /dev/null +++ b/stream_chat_v1/ios/.gitignore @@ -0,0 +1,32 @@ +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/stream_chat_v1/ios/Flutter/.last_build_id b/stream_chat_v1/ios/Flutter/.last_build_id new file mode 100644 index 0000000000..7f117abae3 --- /dev/null +++ b/stream_chat_v1/ios/Flutter/.last_build_id @@ -0,0 +1 @@ +c3757524e06ced55f3d1b83411b9e99c \ No newline at end of file diff --git a/stream_chat_v1/ios/Flutter/AppFrameworkInfo.plist b/stream_chat_v1/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 0000000000..6b4c0f78a7 --- /dev/null +++ b/stream_chat_v1/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 8.0 + + diff --git a/stream_chat_v1/ios/Flutter/Debug.xcconfig b/stream_chat_v1/ios/Flutter/Debug.xcconfig new file mode 100644 index 0000000000..b2f5fae9c2 --- /dev/null +++ b/stream_chat_v1/ios/Flutter/Debug.xcconfig @@ -0,0 +1,3 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/stream_chat_v1/ios/Flutter/Release.xcconfig b/stream_chat_v1/ios/Flutter/Release.xcconfig new file mode 100644 index 0000000000..88c29144c8 --- /dev/null +++ b/stream_chat_v1/ios/Flutter/Release.xcconfig @@ -0,0 +1,3 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/stream_chat_v1/ios/Gemfile b/stream_chat_v1/ios/Gemfile new file mode 100644 index 0000000000..cdd3a6b349 --- /dev/null +++ b/stream_chat_v1/ios/Gemfile @@ -0,0 +1,6 @@ +source "https://rubygems.org" + +gem "fastlane" + +plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile') +eval_gemfile(plugins_path) if File.exist?(plugins_path) diff --git a/stream_chat_v1/ios/Gemfile.lock b/stream_chat_v1/ios/Gemfile.lock new file mode 100644 index 0000000000..dc0ee04fca --- /dev/null +++ b/stream_chat_v1/ios/Gemfile.lock @@ -0,0 +1,180 @@ +GEM + remote: https://rubygems.org/ + specs: + CFPropertyList (3.0.2) + addressable (2.7.0) + public_suffix (>= 2.0.2, < 5.0) + atomos (0.1.3) + aws-eventstream (1.1.0) + aws-partitions (1.380.0) + aws-sdk-core (3.109.1) + aws-eventstream (~> 1, >= 1.0.2) + aws-partitions (~> 1, >= 1.239.0) + aws-sigv4 (~> 1.1) + jmespath (~> 1.0) + aws-sdk-kms (1.39.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-s3 (1.83.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-kms (~> 1) + aws-sigv4 (~> 1.1) + aws-sigv4 (1.2.2) + aws-eventstream (~> 1, >= 1.0.2) + babosa (1.0.3) + claide (1.0.3) + colored (1.2) + colored2 (3.1.2) + commander-fastlane (4.4.6) + highline (~> 1.7.2) + declarative (0.0.20) + declarative-option (0.1.0) + digest-crc (0.6.1) + rake (~> 13.0) + domain_name (0.5.20190701) + unf (>= 0.0.5, < 1.0.0) + dotenv (2.7.6) + emoji_regex (3.0.0) + excon (0.76.0) + faraday (1.0.1) + multipart-post (>= 1.2, < 3) + faraday-cookie_jar (0.0.7) + faraday (>= 0.8.0) + http-cookie (~> 1.0.0) + faraday_middleware (1.0.0) + faraday (~> 1.0) + fastimage (2.2.0) + fastlane (2.162.0) + CFPropertyList (>= 2.3, < 4.0.0) + addressable (>= 2.3, < 3.0.0) + aws-sdk-s3 (~> 1.0) + babosa (>= 1.0.3, < 2.0.0) + bundler (>= 1.12.0, < 3.0.0) + colored + commander-fastlane (>= 4.4.6, < 5.0.0) + dotenv (>= 2.1.1, < 3.0.0) + emoji_regex (>= 0.1, < 4.0) + excon (>= 0.71.0, < 1.0.0) + faraday (~> 1.0) + faraday-cookie_jar (~> 0.0.6) + faraday_middleware (~> 1.0) + fastimage (>= 2.1.0, < 3.0.0) + gh_inspector (>= 1.1.2, < 2.0.0) + google-api-client (>= 0.37.0, < 0.39.0) + google-cloud-storage (>= 1.15.0, < 2.0.0) + highline (>= 1.7.2, < 2.0.0) + json (< 3.0.0) + jwt (>= 2.1.0, < 3) + mini_magick (>= 4.9.4, < 5.0.0) + multipart-post (~> 2.0.0) + plist (>= 3.1.0, < 4.0.0) + rubyzip (>= 2.0.0, < 3.0.0) + security (= 0.1.3) + simctl (~> 1.6.3) + slack-notifier (>= 2.0.0, < 3.0.0) + terminal-notifier (>= 2.0.0, < 3.0.0) + terminal-table (>= 1.4.5, < 2.0.0) + tty-screen (>= 0.6.3, < 1.0.0) + tty-spinner (>= 0.8.0, < 1.0.0) + word_wrap (~> 1.0.0) + xcodeproj (>= 1.13.0, < 2.0.0) + xcpretty (~> 0.3.0) + xcpretty-travis-formatter (>= 0.0.3) + fastlane-plugin-firebase_app_distribution (0.2.3) + gh_inspector (1.1.3) + google-api-client (0.38.0) + addressable (~> 2.5, >= 2.5.1) + googleauth (~> 0.9) + httpclient (>= 2.8.1, < 3.0) + mini_mime (~> 1.0) + representable (~> 3.0) + retriable (>= 2.0, < 4.0) + signet (~> 0.12) + google-cloud-core (1.5.0) + google-cloud-env (~> 1.0) + google-cloud-errors (~> 1.0) + google-cloud-env (1.3.3) + faraday (>= 0.17.3, < 2.0) + google-cloud-errors (1.0.1) + google-cloud-storage (1.29.1) + addressable (~> 2.5) + digest-crc (~> 0.4) + google-api-client (~> 0.33) + google-cloud-core (~> 1.2) + googleauth (~> 0.9) + mini_mime (~> 1.0) + googleauth (0.13.1) + faraday (>= 0.17.3, < 2.0) + jwt (>= 1.4, < 3.0) + memoist (~> 0.16) + multi_json (~> 1.11) + os (>= 0.9, < 2.0) + signet (~> 0.14) + highline (1.7.10) + http-cookie (1.0.3) + domain_name (~> 0.5) + httpclient (2.8.3) + jmespath (1.4.0) + json (2.3.1) + jwt (2.2.2) + memoist (0.16.2) + mini_magick (4.10.1) + mini_mime (1.0.2) + multi_json (1.15.0) + multipart-post (2.0.0) + nanaimo (0.3.0) + naturally (2.2.0) + os (1.1.1) + plist (3.5.0) + public_suffix (4.0.6) + rake (13.0.1) + representable (3.0.4) + declarative (< 0.1.0) + declarative-option (< 0.2.0) + uber (< 0.2.0) + retriable (3.1.2) + rouge (2.0.7) + rubyzip (2.3.0) + security (0.1.3) + signet (0.14.0) + addressable (~> 2.3) + faraday (>= 0.17.3, < 2.0) + jwt (>= 1.5, < 3.0) + multi_json (~> 1.10) + simctl (1.6.8) + CFPropertyList + naturally + slack-notifier (2.3.2) + terminal-notifier (2.0.0) + terminal-table (1.8.0) + unicode-display_width (~> 1.1, >= 1.1.1) + tty-cursor (0.7.1) + tty-screen (0.8.1) + tty-spinner (0.9.3) + tty-cursor (~> 0.7) + uber (0.1.0) + unf (0.1.4) + unf_ext + unf_ext (0.0.7.7) + unicode-display_width (1.7.0) + word_wrap (1.0.0) + xcodeproj (1.18.0) + CFPropertyList (>= 2.3.3, < 4.0) + atomos (~> 0.1.3) + claide (>= 1.0.2, < 2.0) + colored2 (~> 3.1) + nanaimo (~> 0.3.0) + xcpretty (0.3.0) + rouge (~> 2.0.7) + xcpretty-travis-formatter (1.0.0) + xcpretty (~> 0.2, >= 0.0.7) + +PLATFORMS + ruby + +DEPENDENCIES + fastlane + fastlane-plugin-firebase_app_distribution + +BUNDLED WITH + 2.0.2 diff --git a/stream_chat_v1/ios/Notifications/Info.plist b/stream_chat_v1/ios/Notifications/Info.plist new file mode 100644 index 0000000000..a225b5ca00 --- /dev/null +++ b/stream_chat_v1/ios/Notifications/Info.plist @@ -0,0 +1,31 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Notifications + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + NSExtension + + NSExtensionPointIdentifier + com.apple.usernotifications.service + NSExtensionPrincipalClass + $(PRODUCT_MODULE_NAME).NotificationService + + + diff --git a/stream_chat_v1/ios/Notifications/NotificationService.swift b/stream_chat_v1/ios/Notifications/NotificationService.swift new file mode 100644 index 0000000000..976e8d6a92 --- /dev/null +++ b/stream_chat_v1/ios/Notifications/NotificationService.swift @@ -0,0 +1,182 @@ +// +// NotificationService.swift +// Notifications +// +// Created by Salvatore Giordano on 25/03/2020. +// Copyright ยฉ 2020 The Chromium Authors. All rights reserved. +// + +import UserNotifications +//import StreamChatClient + +final class NotificationService: UNNotificationServiceExtension { + + var contentHandler: ((UNNotificationContent) -> Void)? + var bestAttemptContent: UNMutableNotificationContent? + + override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { + self.contentHandler = contentHandler + bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) + + guard let sharedDefaults = UserDefaults(suiteName: "group.io.getstream.flutter"), + let apiKey = sharedDefaults.string(forKey: "KEY_API_KEY"), + let userId = sharedDefaults.string(forKey: "KEY_USER_ID"), + let token = sharedDefaults.string(forKey: "KEY_TOKEN"), + let messageId = bestAttemptContent?.userInfo["message_id"] as? String else { + return + } + +// Client.config = .init(apiKey: apiKey, logOptions: .error) +// Client.shared.set(user: User(id: userId), token: token) { res in +// guard res.isConnected else { +// return +// } +// +// Client.shared.message(withId: messageId) { [weak self] res in +// if let message = res.value?.message, +// let channel = res.value?.channel { +// let messageWrapper = MessageWrapper(channel: channel, message: message) +// if let encodedData = try? JSONEncoder.stream.encode(messageWrapper), +// let encodedString = String(data: encodedData, encoding: .utf8) { +// let storedMessages = sharedDefaults.stringArray(forKey: "messageQueue") ?? [] +// sharedDefaults.setValue(storedMessages + [encodedString], forKey: "messageQueue") +// +// // Modify the notification content here... +// self?.bestAttemptContent?.title = "[modified] \(self?.bestAttemptContent?.title ?? "")" +// contentHandler(self?.bestAttemptContent ?? request.content) +// } +// Client.shared.disconnect() +// } +// } +// } + } + + override func serviceExtensionTimeWillExpire() { + if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent { + contentHandler(bestAttemptContent) + } + } +} + +//public struct MessageWrapper: Encodable { +// private enum CodingKeys: String, CodingKey { +// case id +// case channel +// case type +// case user +// case created = "created_at" +// case updated = "updated_at" +// case text +// case command +// case args +// case attachments +// case parentId = "parent_id" +// case showReplyInChannel = "show_in_channel" +// case mentionedUsers = "mentioned_users" +// } +// +// init(channel: Channel, message: Message) { +// id = message.id +// type = message.type +// user = message.user +// created = message.created +// updated = message.updated +// text = message.text +// command = message.command +// args = message.args +// attachments = message.attachments +// parentId = message.parentId +// showReplyInChannel = message.showReplyInChannel +// mentionedUsers = message.mentionedUsers +// extraData = message.extraData +// self.channel = ChannelWrapper(channel: channel) +// } +// +// /// A message id. +// public let id: String +// /// The channel cid. +// public let channel: ChannelWrapper? +// /// A message type (see `MessageType`). +// public let type: MessageType +// /// A user (see `User`). +// public let user: User +// /// A created date. +// public let created: Date +// /// A updated date. +// public let updated: Date +// /// A text. +// public let text: String +// /// A used command name. +// public let command: String? +// /// A used command args. +// public let args: String? +// /// Attachments (see `Attachment`). +// public let attachments: [Attachment] +// /// A parent message id. +// public let parentId: String? +// /// Check if this reply message needs to show in the channel. +// public let showReplyInChannel: Bool +// /// Mentioned users (see `User`). +// public let mentionedUsers: [User] +// /// An extra data for the message. +// public let extraData: Codable? +//} +// +//public struct ChannelWrapper: Encodable { +// /// Coding keys for the encoding. +// private enum CodingKeys: String, CodingKey { +// case id +// case cid +// case type +// case name +// case imageURL = "image" +// case members +// case lastMessageDate = "last_message_at" +// case createdBy = "created_by" +// case created = "created_at" +// case deleted = "deleted_at" +// case frozen +// } +// +// init(channel: Channel) { +// id = channel.id +// cid = channel.cid +// type = channel.type +// name = channel.name +// imageURL = channel.imageURL +// lastMessageDate = channel.lastMessageDate +// created = channel.created +// deleted = channel.deleted +// createdBy = channel.createdBy +// config = channel.config +// frozen = channel.frozen +// extraData = channel.extraData +// } +// +// /// A channel id. +// public let id: String +// /// A channel type + id. +// public let cid: ChannelId +// /// A channel type. +// public let type: ChannelType +// /// A channel name. +// public let name: String? +// /// An image of the channel. +// public let imageURL: URL? +// /// The last message date. +// public let lastMessageDate: Date? +// /// A channel created date. +// public let created: Date +// /// A channel deleted date. +// public let deleted: Date? +// /// A creator of the channel. +// public let createdBy: User? +// /// A config. +// public let config: Channel.Config +// /// Checks if the channel is frozen. +// public let frozen: Bool +// /// A list of user ids of the channel members. +// public let members = Set() +// /// An extra data for the channel. +// public let extraData: Codable? +//} diff --git a/stream_chat_v1/ios/Notifications/Notifications.entitlements b/stream_chat_v1/ios/Notifications/Notifications.entitlements new file mode 100644 index 0000000000..e5b7189037 --- /dev/null +++ b/stream_chat_v1/ios/Notifications/Notifications.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.application-groups + + group.io.getstream.flutter + + + diff --git a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..e3a96e702d --- /dev/null +++ b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,837 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 0BC14C50242B5A7A0028DE94 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BC14C4F242B5A7A0028DE94 /* NotificationService.swift */; }; + 0BC14C54242B5A7A0028DE94 /* Notifications.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 0BC14C4D242B5A7A0028DE94 /* Notifications.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 6322551A583705BBA2F048DD /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC299D593714162503D904EB /* Pods_Runner.framework */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 0BC14C52242B5A7A0028DE94 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0BC14C4C242B5A7A0028DE94; + remoteInfo = Notifications; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 0BC14C55242B5A7A0028DE94 /* Embed App Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + 0BC14C54242B5A7A0028DE94 /* Notifications.appex in Embed App Extensions */, + ); + name = "Embed App Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0BC14C4D242B5A7A0028DE94 /* Notifications.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = Notifications.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + 0BC14C4F242B5A7A0028DE94 /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = ""; }; + 0BC14C51242B5A7A0028DE94 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 0BC14C5A242B5ED90028DE94 /* Notifications.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Notifications.entitlements; sourceTree = ""; }; + 0BC14C5B242B5FF50028DE94 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 1DFB9D7CB4D2FBB0BD3BD534 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 34DDA6B7AEE7F881BA31E310 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 7069E97E2E50CF0E633E719F /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + CC299D593714162503D904EB /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 0BC14C4A242B5A7A0028DE94 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6322551A583705BBA2F048DD /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 0BC14C4E242B5A7A0028DE94 /* Notifications */ = { + isa = PBXGroup; + children = ( + 0BC14C5A242B5ED90028DE94 /* Notifications.entitlements */, + 0BC14C4F242B5A7A0028DE94 /* NotificationService.swift */, + 0BC14C51242B5A7A0028DE94 /* Info.plist */, + ); + path = Notifications; + sourceTree = ""; + }; + 7771A729FBB96FF718254442 /* Frameworks */ = { + isa = PBXGroup; + children = ( + CC299D593714162503D904EB /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 97C146F01CF9000F007C117D /* Runner */, + 9740EEB11CF90186004384FC /* Flutter */, + 0BC14C4E242B5A7A0028DE94 /* Notifications */, + 97C146EF1CF9000F007C117D /* Products */, + CF168B61BAB91958681C7C21 /* Pods */, + 7771A729FBB96FF718254442 /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + 0BC14C4D242B5A7A0028DE94 /* Notifications.appex */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 0BC14C5B242B5FF50028DE94 /* Runner.entitlements */, + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 97C146F11CF9000F007C117D /* Supporting Files */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; + 97C146F11CF9000F007C117D /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + CF168B61BAB91958681C7C21 /* Pods */ = { + isa = PBXGroup; + children = ( + 1DFB9D7CB4D2FBB0BD3BD534 /* Pods-Runner.debug.xcconfig */, + 7069E97E2E50CF0E633E719F /* Pods-Runner.release.xcconfig */, + 34DDA6B7AEE7F881BA31E310 /* Pods-Runner.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 0BC14C4C242B5A7A0028DE94 /* Notifications */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0BC14C59242B5A7A0028DE94 /* Build configuration list for PBXNativeTarget "Notifications" */; + buildPhases = ( + 0BC14C49242B5A7A0028DE94 /* Sources */, + 0BC14C4A242B5A7A0028DE94 /* Frameworks */, + 0BC14C4B242B5A7A0028DE94 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Notifications; + productName = Notifications; + productReference = 0BC14C4D242B5A7A0028DE94 /* Notifications.appex */; + productType = "com.apple.product-type.app-extension"; + }; + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 22D055914083BAC1E72E76DD /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 0BC14C55242B5A7A0028DE94 /* Embed App Extensions */, + 21997A6DA96DFFF3D7D29CC3 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 0BC14C53242B5A7A0028DE94 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1140; + LastUpgradeCheck = 1020; + ORGANIZATIONNAME = "The Chromium Authors"; + TargetAttributes = { + 0BC14C4C242B5A7A0028DE94 = { + CreatedOnToolsVersion = 11.4; + DevelopmentTeam = EHV7XZLAHA; + ProvisioningStyle = Manual; + }; + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + DevelopmentTeam = EHV7XZLAHA; + LastSwiftMigration = 1100; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + 0BC14C4C242B5A7A0028DE94 /* Notifications */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 0BC14C4B242B5A7A0028DE94 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 21997A6DA96DFFF3D7D29CC3 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/Starscream-framework/Starscream.framework", + "${BUILT_PRODUCTS_DIR}/StreamChatClient-framework/StreamChatClient.framework", + "${BUILT_PRODUCTS_DIR}/DKImagePickerController/DKImagePickerController.framework", + "${BUILT_PRODUCTS_DIR}/DKPhotoGallery/DKPhotoGallery.framework", + "${BUILT_PRODUCTS_DIR}/FMDB/FMDB.framework", + "${BUILT_PRODUCTS_DIR}/SDWebImage/SDWebImage.framework", + "${BUILT_PRODUCTS_DIR}/SwiftyGif/SwiftyGif.framework", + "${BUILT_PRODUCTS_DIR}/esys_flutter_share/esys_flutter_share.framework", + "${BUILT_PRODUCTS_DIR}/file_picker/file_picker.framework", + "${BUILT_PRODUCTS_DIR}/flutter_app_badger/flutter_app_badger.framework", + "${BUILT_PRODUCTS_DIR}/flutter_keyboard_visibility/flutter_keyboard_visibility.framework", + "${BUILT_PRODUCTS_DIR}/flutter_local_notifications/flutter_local_notifications.framework", + "${BUILT_PRODUCTS_DIR}/flutter_secure_storage/flutter_secure_storage.framework", + "${BUILT_PRODUCTS_DIR}/image_gallery_saver/image_gallery_saver.framework", + "${BUILT_PRODUCTS_DIR}/image_picker/image_picker.framework", + "${BUILT_PRODUCTS_DIR}/libwebp/libwebp.framework", + "${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework", + "${BUILT_PRODUCTS_DIR}/photo_manager/photo_manager.framework", + "${BUILT_PRODUCTS_DIR}/shared_preferences/shared_preferences.framework", + "${BUILT_PRODUCTS_DIR}/sqflite/sqflite.framework", + "${BUILT_PRODUCTS_DIR}/sqlite3/sqlite3.framework", + "${BUILT_PRODUCTS_DIR}/sqlite3_flutter_libs/sqlite3_flutter_libs.framework", + "${BUILT_PRODUCTS_DIR}/url_launcher/url_launcher.framework", + "${BUILT_PRODUCTS_DIR}/video_compress/video_compress.framework", + "${BUILT_PRODUCTS_DIR}/video_player/video_player.framework", + "${BUILT_PRODUCTS_DIR}/video_thumbnail/video_thumbnail.framework", + "${BUILT_PRODUCTS_DIR}/wakelock/wakelock.framework", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Starscream.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/StreamChatClient.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DKImagePickerController.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DKPhotoGallery.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FMDB.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImage.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftyGif.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/esys_flutter_share.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/file_picker.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_app_badger.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_keyboard_visibility.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_local_notifications.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_secure_storage.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/image_gallery_saver.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/image_picker.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libwebp.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/photo_manager.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqflite.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqlite3.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqlite3_flutter_libs.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_compress.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_player.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_thumbnail.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/wakelock.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 22D055914083BAC1E72E76DD /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 0BC14C49242B5A7A0028DE94 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0BC14C50242B5A7A0028DE94 /* NotificationService.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 0BC14C53242B5A7A0028DE94 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0BC14C4C242B5A7A0028DE94 /* Notifications */; + targetProxy = 0BC14C52242B5A7A0028DE94 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 0BC14C56242B5A7A0028DE94 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_ENTITLEMENTS = Notifications/Notifications.entitlements; + CODE_SIGN_IDENTITY = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = EHV7XZLAHA; + ENABLE_BITCODE = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = Notifications/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 13.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter.Notifications; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter.Notifications"; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 0BC14C57242B5A7A0028DE94 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_ENTITLEMENTS = Notifications/Notifications.entitlements; + CODE_SIGN_IDENTITY = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = EHV7XZLAHA; + ENABLE_BITCODE = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = Notifications/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 13.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter.Notifications; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter.Notifications"; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 0BC14C58242B5A7A0028DE94 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_ENTITLEMENTS = Notifications/Notifications.entitlements; + CODE_SIGN_IDENTITY = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = EHV7XZLAHA; + ENABLE_BITCODE = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = Notifications/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 13.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter.Notifications; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter.Notifications"; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Profile; + }; + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; + CODE_SIGN_IDENTITY = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = EHV7XZLAHA; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; + CODE_SIGN_IDENTITY = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = EHV7XZLAHA; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; + CODE_SIGN_IDENTITY = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = EHV7XZLAHA; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 0BC14C59242B5A7A0028DE94 /* Build configuration list for PBXNativeTarget "Notifications" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0BC14C56242B5A7A0028DE94 /* Debug */, + 0BC14C57242B5A7A0028DE94 /* Release */, + 0BC14C58242B5A7A0028DE94 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/stream_chat_v1/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/stream_chat_v1/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000000..919434a625 --- /dev/null +++ b/stream_chat_v1/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/stream_chat_v1/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/stream_chat_v1/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000000..18d981003d --- /dev/null +++ b/stream_chat_v1/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/stream_chat_v1/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/stream_chat_v1/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000000..f9b0d7c5ea --- /dev/null +++ b/stream_chat_v1/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/stream_chat_v1/ios/Runner.xcodeproj/xcshareddata/xcschemes/Notifications.xcscheme b/stream_chat_v1/ios/Runner.xcodeproj/xcshareddata/xcschemes/Notifications.xcscheme new file mode 100644 index 0000000000..9387f0d0e7 --- /dev/null +++ b/stream_chat_v1/ios/Runner.xcodeproj/xcshareddata/xcschemes/Notifications.xcscheme @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/stream_chat_v1/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/stream_chat_v1/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000000..fb2dffc49b --- /dev/null +++ b/stream_chat_v1/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/stream_chat_v1/ios/Runner.xcworkspace/contents.xcworkspacedata b/stream_chat_v1/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000000..21a3cc14c7 --- /dev/null +++ b/stream_chat_v1/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/stream_chat_v1/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/stream_chat_v1/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000000..18d981003d --- /dev/null +++ b/stream_chat_v1/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/stream_chat_v1/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/stream_chat_v1/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000000..f9b0d7c5ea --- /dev/null +++ b/stream_chat_v1/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/stream_chat_v1/ios/Runner/AppDelegate.swift b/stream_chat_v1/ios/Runner/AppDelegate.swift new file mode 100644 index 0000000000..e024c1ef27 --- /dev/null +++ b/stream_chat_v1/ios/Runner/AppDelegate.swift @@ -0,0 +1,45 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + let sharedDefaults = UserDefaults(suiteName: "group.io.getstream.flutter") + + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + if let messageQueue = sharedDefaults?.stringArray(forKey: "messageQueue") { + UserDefaults.standard.setValue(messageQueue, forKey: "flutter.messageQueue") + sharedDefaults?.removeObject(forKey: "messageQueue") + } + + if #available(iOS 10.0, *) { + UNUserNotificationCenter.current().delegate = self + } + + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } + + override func applicationDidEnterBackground(_ application: UIApplication) { + if let apiKey = UserDefaults.standard.string(forKey: "flutter.KEY_API_KEY") { + sharedDefaults?.setValue(apiKey, forKey: "KEY_API_KEY") + } + + if let token = UserDefaults.standard.string(forKey: "flutter.KEY_TOKEN") { + sharedDefaults?.setValue(token, forKey: "KEY_TOKEN") + } + + if let userId = UserDefaults.standard.string(forKey: "flutter.KEY_USER_ID") { + sharedDefaults?.setValue(userId, forKey: "KEY_USER_ID") + } + } + + override func applicationWillEnterForeground(_ application: UIApplication) { + if let messageQueue = sharedDefaults?.stringArray(forKey: "messageQueue") { + UserDefaults.standard.setValue(messageQueue, forKey: "flutter.messageQueue") + sharedDefaults?.removeObject(forKey: "messageQueue") + } + } +} diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000000..d36b1fab2d --- /dev/null +++ b/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..6286cc9f763187f78f678193a66633449b2b2484 GIT binary patch literal 52126 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 NeyIK+|DM^q{{wI=gKz)< literal 0 HcmV?d00001 diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..95d13de016c50adba90f2c7c7cd635453462c743 GIT binary patch literal 572 zcmV-C0>k}@P)?huP^cLN@0qz$S>+3BhKY8L*R;6J3 z+5ji6IA{x6bKin3sa7c24a>+nmLY=8Mzz=0PoM;e3lJvL|&v|Ius>jLaO^A)>B z;mKL5+u>SUh)2&{T+b5{#fAopOLt7Q!jV@V=kgBWC5r104ZF8$3WElFnfm#$zwduq zCLlofhg}-#Ebb0DmDpKp*dt6msSpn&u&d8!_1GaQ5AM`hGxrzdylI=}M*AYh$3`g@ zi?nq#v#--gjjNiXXus@`YYowL%TOn&PRUb0+v`+R)rO(oR-9@MGWvXkSS&^+lVQz@ zAjg{&>8w-TWuK+?V{qIh5{ZyZCdudXM59r<3-bh& zX`$u(G)EgXhYp|Soy==0W4QgqogbiYAHKlJtNs+2s=I&xZ}SZ?Ji0oR_DVPa0000< KMNUMnLSTaL6bn@V literal 0 HcmV?d00001 diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5ad80187a2b9d75d67946055753881cefd525c76 GIT binary patch literal 1472 zcmV;x1wZWoUqHR^*Ry6wOA>oEp%`|jtS zbMCq4SstBx!^Ax-%YO~fmbwA`RX3o&>IU>z-GKh88_-{MD&Wj#MFa*2*mg*VAau?% zI}LEk2obAh%Me8Ys^-GZBBN8D+bMu!o)EAuRz^J)M(nd9O2(Bs1qUnrhx8lp$q)f) z@7Qqul7StCI&4;EO$i(4$%tC(!m;!IRddY%g93n;M@ndHGEvuPqV@(*+d$vxUPl%( z48ap$j|2nT7Rmho*o_KCJSOqBd7BmFePBcSLK)Lnx$yfHcYl*uMZv`VJp}X&1Re;F6>@r z!PG*ECtN5f6; ziXSAfaS;|Ms);!txp3~U=969g2bfD%{el38g^MUYso|$znO7Ky3HyD(guxOV{Y0|5 zfRa-h_8-$}q%V9kK$AKw*{WjS3K5bBWFFM;{16E}Y`{0=Iu2CoST|ROZkSkkTq17(oAzj!I8?;YFpb)t=2$J%r_ zFZ+(~M;mAwEr?ma>Nf*ZlbdkDX^?9LM31*%)F6>Bx}Mx!an3+qiH@uF9ROrnyIaHP zK@wKXl5zBG6E6G>zS3%PUG)VG7SW_wm9T84mB$o|JF5gt8ZJ@@fKQsX#^tfrxCoJl zN3dP=nP9T^8Sl$|j=aW(cS0h#eOSS0svP16t`ACL0#a)gG4V*B>(1RqE{T;bko7a$XJ z-O3yVYhr9zGR=zByELB9Li>^nM@twVA>lZ=Zu4FZ1CHvnnFJ0vZL|eTr(3aXhf2>d zk@BYOfm2l#(b3V!&CNwvSQyr?Uyq=mAl|l;PN5&Fo9HBJCm>Vqk2+aELmXMDNii|f zA>yXX?ZVA_yjC61N90@Pmp|C0Q5G;MF|*AjqEAoJW4YVmii(O55)$H>ixnGhjHQ$4 zTfO~&Y^O3y3<(vn=oJ~4YYo1_1(QX(te##hN3t9|Yn=PBe_k~x&8UccT=Kxh#Kd^u z3JVK;;BG0>!TNUy5U8g_9iOIP;S>v6IS6pI&iD7F8h0%9c6$$5Sy{-=&gO6h1qDb< zOhj2(83qmt3q=-?JdV=XJX2ovBSp)e;bY6;*r`X_Ed-VT$FTNY<2J~0= aJm9}AoLVfo$i1r3h3HVLDn9#Ro~yLghve!@ZvNVS%&$K+VRyz z1v~%QdY{!=jqre8K-Mff95w-#6*;b9{FS8HL)3I#tNE>rvhzgVGS z>jKxk?B6*safw2!eS7EAEMdEBp>ulym#Zz*sV*11o}|j2U-cV1`uCEc>K2}OO~Hw? zAi}Qu<(C*~1$j?95!qG5+SzubEK^Xe`2P|X9TxrBiAgBUwW^NI)%Wv02~(t@Fx`QE z;Sz7xsunI)nW(G+D#-wq)$U)b!8MDF<2ipm&4!WvWgfHh)+#t~qH&y-k^!cZA=nBJ z=_BFwU)wP+TSX@-TcI83Xb*1m(DttLF!tMlu7$Yo3kaiM79tE6Doy-gK^@JvY0|z4 zQ-7!3^H4iFZ`VaauP#1~=M&5FRctS@e0s-0GQ{uKC|L1J2kwuSQL_BTBh6t$vtH

8dwfqTgzA-I4tT42rUO^k=k3$w1`!mIaG!{6 z2MuHuX*ltv#mTr!&D4iPJe%s|=S4>~q;JywQd6u8GfYI7ipdYS-nTTb4w<`6SU~+d z21N--86#u-_hcTw$Is|=%|&DLevN9n+3fpT^qm*q)JZUiJQgD;n@(I@haRB<5@RIf z&v)XB3nsa%fgOho4DBnBm~gF7$q5~^Gc}r&{|Sgqbm1F1x^xtfFv^B`Ne+}%C^&lB zqBgxdMn?C}0*!6psWmG0e{ABZi888cb?(aPo3s{<+ah7Z6!2S`cwxFoE-T{Y>2{1? zq~QJI7XG+iBdI7M`TG+7kYwW)mnDI$ZeZH0DirglLEe4w^aU92FTeoFo<`T16S@8x5Wbw;nWU6JVlu zR}G0oJc*9JJw+^{484Um2M3Nbm-LS~oAj`|1TvtFyhTL$MU%$Yk-Oi(nXla(1zzqV zy9!*jv65MS$v?7w6J{v1BnSHnn(=er{$ESqdcYHz-K~YkZ zb7P@4F-F7$N@UFSpWCQW7QfCq+!UCCnVqR(+X5$*5D`lsw_#?6=F_CC|Mn7-CSlUb zX*4Mb&-~0rWlZGv<3~zZ^LGsk$uOUvcMsz|R?IyDZ8{ui?`-^z($Z2?R8-Wr2M!!a zVbvXj`-n(euHa%-<7ckB!hdqcB_y6rb>Jr>Y)BbvBKN)K_q07aTeO-Ieo8LM6wy}{ zo2*a+6tdY?DsyN5>utM!J%P-bO_SZZb0?CLlAtIGZzm)qATKYEpR+uZNk&S2 zL4j_1KYK%xX3g6MemGR;S@gNb?Bu?6`0TuQAC_1iyjP?oCSx4A>?dbTYVln6pa7J`x7TRhMe6Y_MDZsbC_#LS5JxMv~aEFn5)LvWmuIwrRplhR$E7(H7Lgw1;h8rHYYWvSdl4Cs^OPs}*wRrvG)* z#tFMV`7EZA_s)kV<|WD))`Y%h&~yts4(nLHRmZtX-{ZA;!VGL-577=PajA*{y)=v- zETT_$5l)-Hzjm-Mr~5uO==>Ia(`qYVE`6#TbgFVf71#S1PKQ^f`kJdLBfHK cZyn+P0|T$88os5VyZ`_I07*qoM6N<$f-`c93;+NC literal 0 HcmV?d00001 diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..6f26f228f1ce9125c879ab7a8c07e9b8e199448c GIT binary patch literal 990 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 literal 0 HcmV?d00001 diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..3ab319af19f5e751718d55411b14d25ff4610565 GIT binary patch literal 3744 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 R{*OF~bU=ohwa=ij{{u=RJS+eJ literal 0 HcmV?d00001 diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..5ad80187a2b9d75d67946055753881cefd525c76 GIT binary patch literal 1472 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 literal 0 HcmV?d00001 diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f049762f057fca745ca451c25a3f1052195be542 GIT binary patch literal 5281 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 literal 0 HcmV?d00001 diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..b51e00a7e59da211b022b622a91217b0dab107fb GIT binary patch literal 8289 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 literal 0 HcmV?d00001 diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..8c4973081f22d5f81b781442cb0eb6b18514317a GIT binary patch literal 3132 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 literal 0 HcmV?d00001 diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c59c5739cdf36e1185d8a74be7e78ddfee41238e GIT binary patch literal 6964 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

wfbU}SOG#?y4 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 Q1}MSc>FVdQ&MBb@0IDSp>i_@% literal 0 HcmV?d00001 diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/stream_chat_v1/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 0000000000..00cabce836 --- /dev/null +++ b/stream_chat_v1/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "LaunchImage.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "LaunchImage@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "LaunchImage@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/stream_chat_v1/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 0000000000000000000000000000000000000000..67774cf3dacac0ad161013438381c330272b67f7 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1|;Q0k8}blZci7-kP61+L + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/stream_chat_v1/ios/Runner/Base.lproj/Main.storyboard b/stream_chat_v1/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 0000000000..f3c28516fb --- /dev/null +++ b/stream_chat_v1/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/stream_chat_v1/ios/Runner/Info.plist b/stream_chat_v1/ios/Runner/Info.plist new file mode 100644 index 0000000000..d9f250b76c --- /dev/null +++ b/stream_chat_v1/ios/Runner/Info.plist @@ -0,0 +1,66 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ChatSample + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + NSAppleMusicUsageDescription + Used to send message attachments + NSCameraUsageDescription + Used to send message attachments + NSMicrophoneUsageDescription + Used to send message attachments + NSPhotoLibraryUsageDescription + Used to send message attachments + UIBackgroundModes + + fetch + remote-notification + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + UIBackgroundModes + + remote-notification + + UIViewControllerBasedStatusBarAppearance + + UIStatusBarHidden + + + \ No newline at end of file diff --git a/stream_chat_v1/ios/Runner/Runner-Bridging-Header.h b/stream_chat_v1/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 0000000000..7335fdf900 --- /dev/null +++ b/stream_chat_v1/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" \ No newline at end of file diff --git a/stream_chat_v1/ios/Runner/Runner.entitlements b/stream_chat_v1/ios/Runner/Runner.entitlements new file mode 100644 index 0000000000..433bdfe097 --- /dev/null +++ b/stream_chat_v1/ios/Runner/Runner.entitlements @@ -0,0 +1,12 @@ + + + + + aps-environment + development + com.apple.security.application-groups + + group.io.getstream.flutter + + + diff --git a/stream_chat_v1/ios/fastlane/Appfile b/stream_chat_v1/ios/fastlane/Appfile new file mode 100644 index 0000000000..1803063093 --- /dev/null +++ b/stream_chat_v1/ios/fastlane/Appfile @@ -0,0 +1,6 @@ +# app_identifier("[[APP_IDENTIFIER]]") # The bundle identifier of your app +# apple_id("[[APPLE_ID]]") # Your Apple email address + + +# For more information about the Appfile, see: +# https://docs.fastlane.tools/advanced/#appfile diff --git a/stream_chat_v1/ios/fastlane/Fastfile b/stream_chat_v1/ios/fastlane/Fastfile new file mode 100644 index 0000000000..ec2adc8166 --- /dev/null +++ b/stream_chat_v1/ios/fastlane/Fastfile @@ -0,0 +1,46 @@ +fastlane_version "2.162.0" +default_platform :ios + +before_all do + if is_ci + setup_ci() + end +end + +desc "Installs all Certs and Profiles necessary for development and ad-hoc" +lane :match_me do + match( + type: "adhoc", + app_identifier: [ + "io.getstream.flutter", + "io.getstream.flutter.Notifications" + ], + readonly: is_ci, + force_for_new_devices: true + ) +end + +platform :ios do + desc "Deploy build to Firebase" + lane :deploy_to_firebase do + match_me + + gym( + workspace: "./Runner.xcworkspace", + scheme: "Runner", + export_method: "ad-hoc", + export_options: "./fastlane/beta_gym_export_options.plist", + silent: true, + clean: true, + include_symbols: true, + output_directory: "./dist" + ) + + message = changelog_from_git_commits(commits_count: 10) + + firebase_app_distribution( + app: "1:674907137625:ios:cafb9fb076a453c4d7f348", + groups: "ios-stream-testers" + ) + end +end \ No newline at end of file diff --git a/stream_chat_v1/ios/fastlane/Matchfile b/stream_chat_v1/ios/fastlane/Matchfile new file mode 100644 index 0000000000..cc976de1a7 --- /dev/null +++ b/stream_chat_v1/ios/fastlane/Matchfile @@ -0,0 +1,16 @@ +git_url("https://github.com/GetStream/ios-certificates") + +storage_mode("git") + +username("salvatore@getstream.io") + +team_id("EHV7XZLAHA") + +# app_identifier(["tools.fastlane.app", "tools.fastlane.app2"]) + +# username("user@fastlane.tools") # Your Apple Developer Portal username + +# For all available options run `fastlane match --help` +# Remove the # in the beginning of the line to enable the other options + +# The docs are available on https://docs.fastlane.tools/actions/match diff --git a/stream_chat_v1/ios/fastlane/Pluginfile b/stream_chat_v1/ios/fastlane/Pluginfile new file mode 100644 index 0000000000..b18539bc9b --- /dev/null +++ b/stream_chat_v1/ios/fastlane/Pluginfile @@ -0,0 +1,5 @@ +# Autogenerated by fastlane +# +# Ensure this file is checked in to source control! + +gem 'fastlane-plugin-firebase_app_distribution' diff --git a/stream_chat_v1/ios/fastlane/README.md b/stream_chat_v1/ios/fastlane/README.md new file mode 100644 index 0000000000..e464ef2411 --- /dev/null +++ b/stream_chat_v1/ios/fastlane/README.md @@ -0,0 +1,37 @@ +fastlane documentation +================ +# Installation + +Make sure you have the latest version of the Xcode command line tools installed: + +``` +xcode-select --install +``` + +Install _fastlane_ using +``` +[sudo] gem install fastlane -NV +``` +or alternatively using `brew install fastlane` + +# Available Actions +### match_me +``` +fastlane match_me +``` +Installs all Certs and Profiles necessary for development and ad-hoc + +---- + +## iOS +### ios deploy_to_firebase +``` +fastlane ios deploy_to_firebase +``` +Deploy build to Firebase + +---- + +This README.md is auto-generated and will be re-generated every time [fastlane](https://fastlane.tools) is run. +More information about fastlane can be found on [fastlane.tools](https://fastlane.tools). +The documentation of fastlane can be found on [docs.fastlane.tools](https://docs.fastlane.tools). diff --git a/stream_chat_v1/ios/fastlane/beta_gym_export_options.plist b/stream_chat_v1/ios/fastlane/beta_gym_export_options.plist new file mode 100644 index 0000000000..53c7409888 --- /dev/null +++ b/stream_chat_v1/ios/fastlane/beta_gym_export_options.plist @@ -0,0 +1,15 @@ + + + + + iCloudContainerEnvironment + Development + provisioningProfiles + + io.getstream.flutter + match AdHoc io.getstream.flutter + io.getstream.flutter.Notifications + match AdHoc io.getstream.flutter.Notifications + + + \ No newline at end of file diff --git a/stream_chat_v1/ios/fastlane/report.xml b/stream_chat_v1/ios/fastlane/report.xml new file mode 100644 index 0000000000..b6e7bdcbac --- /dev/null +++ b/stream_chat_v1/ios/fastlane/report.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/stream_chat_v1/lib/advanced_options_page.dart b/stream_chat_v1/lib/advanced_options_page.dart new file mode 100644 index 0000000000..f3ea431be2 --- /dev/null +++ b/stream_chat_v1/lib/advanced_options_page.dart @@ -0,0 +1,327 @@ +import 'package:example/routes/routes.dart'; +import 'package:example/stream_version.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; + +import 'choose_user_page.dart'; +import 'main.dart'; + +class AdvancedOptionsPage extends StatefulWidget { + @override + _AdvancedOptionsPageState createState() => _AdvancedOptionsPageState(); +} + +class _AdvancedOptionsPageState extends State { + final _formKey = GlobalKey(); + + final TextEditingController _apiKeyController = TextEditingController(); + String _apiKeyError; + + final TextEditingController _userIdController = TextEditingController(); + String _userIdError; + + final TextEditingController _userTokenController = TextEditingController(); + String _userTokenError; + + final TextEditingController _usernameController = TextEditingController(); + + bool loading = false; + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + appBar: AppBar( + backgroundColor: StreamChatTheme.of(context).colorTheme.white, + elevation: 1, + centerTitle: true, + brightness: Theme.of(context).brightness, + title: Text( + 'Advanced Options', + style: StreamChatTheme.of(context) + .textTheme + .headlineBold + .copyWith(color: StreamChatTheme.of(context).colorTheme.black), + ), + leading: IconButton( + icon: StreamSvgIcon.left( + color: StreamChatTheme.of(context).colorTheme.black, + ), + onPressed: () { + Navigator.pop(context); + }, + ), + ), + body: Builder( + builder: (context) { + return Padding( + padding: const EdgeInsets.fromLTRB(16, 16, 16, 0), + child: Form( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + TextFormField( + controller: _apiKeyController, + onChanged: (_) { + if (_apiKeyError != null) { + setState(() { + _apiKeyError = null; + }); + } + }, + validator: (value) { + if (value.isEmpty) { + setState(() { + _apiKeyError = 'Please enter the Chat API Key'; + }); + return _apiKeyError; + } + return null; + }, + style: TextStyle( + fontSize: 14, + color: StreamChatTheme.of(context).colorTheme.black, + ), + decoration: InputDecoration( + errorStyle: TextStyle(height: 0, fontSize: 0), + labelStyle: TextStyle( + fontSize: 14, + fontWeight: FontWeight.bold, + color: _apiKeyError != null + ? StreamChatTheme.of(context).colorTheme.accentRed + : StreamChatTheme.of(context).colorTheme.grey, + ), + border: UnderlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide.none, + ), + fillColor: + StreamChatTheme.of(context).colorTheme.whiteSmoke, + filled: true, + labelText: + 'Chat API Key ${_apiKeyError != null ? ': $_apiKeyError' : ''}', + ), + textInputAction: TextInputAction.next, + ), + SizedBox(height: 8), + TextFormField( + controller: _userIdController, + onChanged: (_) { + if (_userIdError != null) { + setState(() { + _userIdError = null; + }); + } + }, + validator: (value) { + if (value.isEmpty) { + setState(() { + _userIdError = 'Please enter the User ID'; + }); + return _userIdError; + } + return null; + }, + style: TextStyle( + fontSize: 14, + color: StreamChatTheme.of(context).colorTheme.black, + ), + textInputAction: TextInputAction.next, + decoration: InputDecoration( + errorStyle: TextStyle(height: 0, fontSize: 0), + labelStyle: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 14, + color: _userIdError != null + ? StreamChatTheme.of(context).colorTheme.accentRed + : StreamChatTheme.of(context).colorTheme.grey, + ), + border: UnderlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide.none, + ), + fillColor: + StreamChatTheme.of(context).colorTheme.whiteSmoke, + filled: true, + labelText: + 'User ID ${_userIdError != null ? ': $_userIdError' : ''}', + ), + ), + SizedBox(height: 8), + TextFormField( + onChanged: (_) { + if (_userTokenError != null) { + setState(() { + _userTokenError = null; + }); + } + }, + controller: _userTokenController, + validator: (value) { + if (value.isEmpty) { + setState(() { + _userTokenError = 'Please enter the user token'; + }); + return _userTokenError; + } + return null; + }, + style: TextStyle( + fontSize: 14, + color: StreamChatTheme.of(context).colorTheme.black, + ), + textInputAction: TextInputAction.next, + decoration: InputDecoration( + errorStyle: TextStyle(height: 0, fontSize: 0), + labelStyle: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 14, + color: _userTokenError != null + ? StreamChatTheme.of(context).colorTheme.accentRed + : StreamChatTheme.of(context).colorTheme.grey, + ), + border: UnderlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide.none, + ), + fillColor: + StreamChatTheme.of(context).colorTheme.whiteSmoke, + filled: true, + labelText: + 'User Token ${_userTokenError != null ? ': $_userTokenError' : ''}', + ), + ), + SizedBox(height: 8), + TextFormField( + controller: _usernameController, + textInputAction: TextInputAction.done, + decoration: InputDecoration( + labelStyle: TextStyle( + fontSize: 14, + fontWeight: FontWeight.bold, + color: StreamChatTheme.of(context).colorTheme.grey, + ), + border: UnderlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide.none, + ), + fillColor: + StreamChatTheme.of(context).colorTheme.whiteSmoke, + filled: true, + labelText: 'Username (optional)', + ), + ), + Spacer(), + RaisedButton( + color: Theme.of(context).brightness == Brightness.light + ? StreamChatTheme.of(context).colorTheme.accentBlue + : Colors.white, + elevation: 0, + padding: const EdgeInsets.symmetric(vertical: 16), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(26), + ), + child: Text( + 'Login', + style: TextStyle( + fontSize: 16, + color: Theme.of(context).brightness != Brightness.light + ? StreamChatTheme.of(context).colorTheme.accentBlue + : Colors.white, + ), + ), + onPressed: () async { + if (loading) { + return; + } + if (_formKey.currentState.validate()) { + final apiKey = _apiKeyController.text; + final userId = _userIdController.text; + final userToken = _userTokenController.text; + final username = _usernameController.text; + + loading = true; + showDialog( + barrierDismissible: false, + context: context, + barrierColor: + StreamChatTheme.of(context).colorTheme.overlay, + builder: (context) => Center( + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16), + color: StreamChatTheme.of(context) + .colorTheme + .white, + ), + height: 100, + width: 100, + child: Center( + child: CircularProgressIndicator(), + ), + ), + ), + ); + + final client = StreamChatClient( + apiKey, + logLevel: Level.INFO, + )..chatPersistenceClient = chatPersistentClient; + + try { + await client.setUser( + User(id: userId, extraData: { + 'name': username, + }), + userToken, + ); + + final secureStorage = FlutterSecureStorage(); + secureStorage.write( + key: kStreamApiKey, + value: apiKey, + ); + secureStorage.write( + key: kStreamUserId, + value: userId, + ); + secureStorage.write( + key: kStreamToken, + value: userToken, + ); + } catch (e) { + var errorText = 'Error connecting, retry'; + if (e is Map) { + errorText = e['message'] ?? errorText; + } + Navigator.pop(context); + setState(() { + _apiKeyError = errorText; + }); + loading = false; + await client.disconnect(); + return; + } + loading = false; + await Navigator.pushNamedAndRemoveUntil( + context, + Routes.APP, + ModalRoute.withName(Routes.APP), + arguments: client, + ); + } + }, + ), + StreamVersion(), + ], + ), + ), + ); + }, + ), + ); + } +} diff --git a/stream_chat_v1/lib/chat_info_screen.dart b/stream_chat_v1/lib/chat_info_screen.dart new file mode 100644 index 0000000000..5c8441ed05 --- /dev/null +++ b/stream_chat_v1/lib/chat_info_screen.dart @@ -0,0 +1,603 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:jiffy/jiffy.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; + +import 'main.dart'; +import 'routes/routes.dart'; + +/// Detail screen for a 1:1 chat correspondence +class ChatInfoScreen extends StatefulWidget { + /// User in consideration + final User user; + + const ChatInfoScreen({Key key, this.user}) : super(key: key); + + @override + _ChatInfoScreenState createState() => _ChatInfoScreenState(); +} + +class _ChatInfoScreenState extends State { + ValueNotifier mutedBool = ValueNotifier(false); + + @override + void initState() { + super.initState(); + mutedBool = ValueNotifier(StreamChannel.of(context).channel.isMuted); + } + + @override + Widget build(BuildContext context) { + final channel = StreamChannel.of(context).channel; + return Scaffold( + backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + body: ListView( + children: [ + _buildUserHeader(), + Container( + height: 8.0, + color: StreamChatTheme.of(context).colorTheme.greyGainsboro, + ), + _buildOptionListTiles(), + Container( + height: 8.0, + color: StreamChatTheme.of(context).colorTheme.greyGainsboro, + ), + if ([ + 'admin', + 'owner', + ].contains(channel.state.members + .firstWhere((m) => m.userId == channel.client.state.user.id, + orElse: () => null) + ?.role)) + _buildDeleteListTile(), + ], + ), + ); + } + + Widget _buildUserHeader() { + return Material( + color: StreamChatTheme.of(context).colorTheme.whiteSnow, + child: SafeArea( + child: Stack( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.all(16.0), + child: UserAvatar( + user: widget.user, + constraints: BoxConstraints( + maxWidth: 72.0, + maxHeight: 72.0, + ), + borderRadius: BorderRadius.circular(36.0), + showOnlineStatus: false, + ), + ), + Text( + widget.user.name, + style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold), + ), + SizedBox(height: 7.0), + _buildConnectedTitleState(), + SizedBox(height: 15.0), + OptionListTile( + title: '@${widget.user.id}', + tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + trailing: Padding( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + child: Text( + widget.user.name, + style: TextStyle( + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(0.5), + fontSize: 16.0), + ), + ), + onTap: () {}, + ), + ], + ), + Positioned( + top: 0, + left: 0, + width: 58, + child: StreamBackButton(), + ), + ], + ), + ), + ); + } + + Widget _buildOptionListTiles() { + var channel = StreamChannel.of(context); + + return Column( + children: [ + // _OptionListTile( + // title: 'Notifications', + // leading: StreamSvgIcon.Icon_notification( + // size: 24.0, + // color: StreamChatTheme.of(context).colorTheme.black.withOpacity(0.5), + // ), + // trailing: CupertinoSwitch( + // value: true, + // onChanged: (val) {}, + // ), + // onTap: () {}, + // ), + StreamBuilder( + stream: StreamChannel.of(context).channel.isMutedStream, + builder: (context, snapshot) { + mutedBool.value = snapshot.data; + + return OptionListTile( + tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + title: 'Mute user', + titleTextStyle: StreamChatTheme.of(context).textTheme.body, + leading: Padding( + padding: const EdgeInsets.symmetric(horizontal: 22.0), + child: StreamSvgIcon.mute( + size: 24.0, + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(0.5), + ), + ), + trailing: snapshot.data == null + ? CircularProgressIndicator() + : ValueListenableBuilder( + valueListenable: mutedBool, + builder: (context, value, _) { + return CupertinoSwitch( + value: value, + onChanged: (val) { + mutedBool.value = val; + + if (snapshot.data) { + channel.channel.unmute(); + } else { + channel.channel.mute(); + } + }, + ); + }), + onTap: () {}, + ); + }), + // _OptionListTile( + // title: 'Block User', + // leading: StreamSvgIcon.Icon_user_delete( + // size: 24.0, + // color: StreamChatTheme.of(context).colorTheme.black.withOpacity(0.5), + // ), + // trailing: CupertinoSwitch( + // value: widget.user.banned, + // onChanged: (val) { + // if (widget.user.banned) { + // channel.channel.shadowBan(widget.user.id, {}); + // } else { + // channel.channel.unbanUser(widget.user.id); + // } + // }, + // ), + // onTap: () {}, + // ), + OptionListTile( + title: 'Photos & Videos', + tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + titleTextStyle: StreamChatTheme.of(context).textTheme.body, + leading: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: StreamSvgIcon.pictures( + size: 36.0, + color: + StreamChatTheme.of(context).colorTheme.black.withOpacity(0.5), + ), + ), + trailing: StreamSvgIcon.right( + color: StreamChatTheme.of(context).colorTheme.grey, + ), + onTap: () { + final channel = StreamChannel.of(context).channel; + + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => StreamChannel( + channel: channel, + child: MessageSearchBloc( + child: ChannelMediaDisplayScreen( + sortOptions: [ + SortOption( + 'created_at', + direction: SortOption.ASC, + ), + ], + paginationParams: PaginationParams(limit: 20), + onShowMessage: (m, c) async { + final client = StreamChat.of(context).client; + final message = m; + final channel = client.channel( + c.type, + id: c.id, + ); + if (channel.state == null) { + await channel.watch(); + } + Navigator.pushNamed( + context, + Routes.CHANNEL_PAGE, + arguments: ChannelPageArgs( + channel: channel, + initialMessage: message, + ), + ); + }, + ), + ), + ), + ), + ); + }, + ), + OptionListTile( + title: 'Files', + tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + titleTextStyle: StreamChatTheme.of(context).textTheme.body, + leading: Padding( + padding: const EdgeInsets.symmetric(horizontal: 18.0), + child: StreamSvgIcon.files( + size: 32.0, + color: + StreamChatTheme.of(context).colorTheme.black.withOpacity(0.5), + ), + ), + trailing: StreamSvgIcon.right( + color: StreamChatTheme.of(context).colorTheme.grey, + ), + onTap: () { + final channel = StreamChannel.of(context).channel; + + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => StreamChannel( + channel: channel, + child: MessageSearchBloc( + child: ChannelFileDisplayScreen( + sortOptions: [ + SortOption( + 'created_at', + direction: SortOption.ASC, + ), + ], + paginationParams: PaginationParams(limit: 20), + ), + ), + ), + ), + ); + }, + ), + OptionListTile( + title: 'Shared groups', + tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + titleTextStyle: StreamChatTheme.of(context).textTheme.body, + leading: Padding( + padding: const EdgeInsets.symmetric(horizontal: 22.0), + child: StreamSvgIcon.iconGroup( + size: 24.0, + color: + StreamChatTheme.of(context).colorTheme.black.withOpacity(0.5), + ), + ), + trailing: StreamSvgIcon.right( + color: StreamChatTheme.of(context).colorTheme.grey, + ), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => _SharedGroupsScreen( + StreamChat.of(context).user, widget.user))); + }, + ), + ], + ); + } + + Widget _buildDeleteListTile() { + return OptionListTile( + title: 'Delete Conversation', + tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + titleTextStyle: StreamChatTheme.of(context).textTheme.body.copyWith( + color: StreamChatTheme.of(context).colorTheme.accentRed, + ), + leading: Padding( + padding: const EdgeInsets.symmetric(horizontal: 22.0), + child: StreamSvgIcon.delete( + color: StreamChatTheme.of(context).colorTheme.accentRed, + size: 24.0, + ), + ), + onTap: () { + _showDeleteDialog(); + }, + titleColor: StreamChatTheme.of(context).colorTheme.accentRed, + ); + } + + void _showDeleteDialog() async { + final res = await showConfirmationDialog( + context, + title: 'Delete Conversation', + okText: 'DELETE', + question: 'Are you sure you want to delete this conversation?', + cancelText: 'CANCEL', + icon: StreamSvgIcon.delete( + color: StreamChatTheme.of(context).colorTheme.accentRed, + ), + ); + var channel = StreamChannel.of(context).channel; + if (res == true) { + await channel.delete().then((value) { + Navigator.pop(context); + Navigator.pop(context); + }); + } + } + + Widget _buildConnectedTitleState() { + var alternativeWidget; + + final otherMember = widget.user; + + if (otherMember != null) { + if (otherMember.online) { + alternativeWidget = Text( + 'Online', + style: TextStyle( + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(0.5)), + ); + } else { + alternativeWidget = Text( + 'Last seen ${Jiffy(otherMember.lastActive).fromNow()}', + style: TextStyle( + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(0.5)), + ); + } + } + + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + if (widget.user.online) + Material( + type: MaterialType.circle, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + constraints: BoxConstraints.tightFor( + width: 24, + height: 12, + ), + child: Material( + shape: CircleBorder(), + color: StreamChatTheme.of(context).colorTheme.accentGreen, + ), + ), + color: StreamChatTheme.of(context).colorTheme.white, + ), + alternativeWidget, + if (widget.user.online) + SizedBox( + width: 24.0, + ), + ], + ); + } +} + +class _SharedGroupsScreen extends StatefulWidget { + final User mainUser; + final User otherUser; + + _SharedGroupsScreen(this.mainUser, this.otherUser); + + @override + __SharedGroupsScreenState createState() => __SharedGroupsScreenState(); +} + +class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { + @override + Widget build(BuildContext context) { + var chat = StreamChat.of(context); + + return Scaffold( + backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + appBar: AppBar( + brightness: Theme.of(context).brightness, + elevation: 1, + centerTitle: true, + title: Text( + 'Shared Groups', + style: TextStyle( + color: StreamChatTheme.of(context).colorTheme.black, + fontSize: 16.0), + ), + leading: StreamBackButton(), + backgroundColor: StreamChatTheme.of(context).colorTheme.white, + ), + body: StreamBuilder>( + stream: chat.client.queryChannels( + filter: { + r'$and': [ + { + 'members': { + r'$in': [widget.otherUser.id], + }, + }, + { + 'members': { + r'$in': [widget.mainUser.id], + }, + } + ], + }, + ), + builder: (context, snapshot) { + if (!snapshot.hasData) { + return Center( + child: CircularProgressIndicator(), + ); + } + + if (snapshot.data.isEmpty) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + StreamSvgIcon.message( + size: 136.0, + color: StreamChatTheme.of(context).colorTheme.greyGainsboro, + ), + SizedBox(height: 16.0), + Text( + 'No Shared Groups', + style: TextStyle( + fontSize: 14.0, + color: StreamChatTheme.of(context).colorTheme.black, + ), + ), + SizedBox(height: 8.0), + Text( + 'Group shared with User will appear here.', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 14.0, + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(0.5), + ), + ), + ], + ), + ); + } + + final channels = snapshot.data + .where((c) => + c.state.members.any((m) => + m.userId != widget.mainUser.id && + m.userId != widget.otherUser.id) || + !c.isDistinct) + .toList(); + + return ListView.builder( + itemCount: channels.length, + itemBuilder: (context, position) { + return StreamChannel( + channel: channels[position], + child: _buildListTile(channels[position]), + ); + }, + ); + }, + ), + ); + } + + Widget _buildListTile(Channel channel) { + var extraData = channel.extraData; + var members = channel.state.members; + + var textStyle = TextStyle(fontSize: 14.0, fontWeight: FontWeight.bold); + + return Container( + height: 64.0, + child: LayoutBuilder(builder: (context, constraints) { + String title; + if (extraData['name'] == null) { + final otherMembers = members.where( + (member) => member.userId != StreamChat.of(context).user.id); + if (otherMembers.isNotEmpty) { + final maxWidth = constraints.maxWidth; + final maxChars = maxWidth / textStyle.fontSize; + var currentChars = 0; + final currentMembers = []; + otherMembers.forEach((element) { + final newLength = currentChars + element.user.name.length; + if (newLength < maxChars) { + currentChars = newLength; + currentMembers.add(element); + } + }); + + final exceedingMembers = + otherMembers.length - currentMembers.length; + title = + '${currentMembers.map((e) => e.user.name).join(', ')} ${exceedingMembers > 0 ? '+ $exceedingMembers' : ''}'; + } else { + title = 'No title'; + } + } else { + title = extraData['name']; + } + + return Column( + children: [ + Expanded( + child: Row( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: ChannelImage( + channel: channel, + constraints: + BoxConstraints(maxWidth: 40.0, maxHeight: 40.0), + ), + ), + Expanded( + child: Text( + title, + style: textStyle, + )), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + '${channel.memberCount} members', + style: TextStyle( + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(0.5)), + ), + ) + ], + ), + ), + Container( + height: 1.0, + color: + StreamChatTheme.of(context).colorTheme.black.withOpacity(.08), + ), + ], + ); + }), + ); + } +} diff --git a/stream_chat_v1/lib/chips_input_text_field.dart b/stream_chat_v1/lib/chips_input_text_field.dart new file mode 100644 index 0000000000..0fc079182e --- /dev/null +++ b/stream_chat_v1/lib/chips_input_text_field.dart @@ -0,0 +1,166 @@ +import 'package:flutter/material.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; + +typedef ChipBuilder = Widget Function(BuildContext context, T chip); +typedef OnChipAdded = void Function(T chip); +typedef OnChipRemoved = void Function(T chip); + +class ChipsInputTextField extends StatefulWidget { + final TextEditingController controller; + final FocusNode focusNode; + final ValueChanged onInputChanged; + final ChipBuilder chipBuilder; + final OnChipAdded onChipAdded; + final OnChipRemoved onChipRemoved; + final String hint; + + const ChipsInputTextField({ + Key key, + @required this.chipBuilder, + @required this.controller, + this.onInputChanged, + this.focusNode, + this.onChipAdded, + this.onChipRemoved, + this.hint = 'Type a name', + }) : super(key: key); + + @override + ChipInputTextFieldState createState() => ChipInputTextFieldState(); +} + +class ChipInputTextFieldState extends State> { + final _chips = {}; + bool _pauseItemAddition = false; + + void addItem(T item) { + setState(() => _chips.add(item)); + if (widget.onChipAdded != null) widget.onChipAdded(item); + } + + void removeItem(T item) { + setState(() { + _chips.remove(item); + if (_chips.isEmpty) resumeItemAddition(); + }); + if (widget.onChipRemoved != null) widget.onChipRemoved(item); + } + + void pauseItemAddition() { + if (!_pauseItemAddition) { + setState(() => _pauseItemAddition = true); + } + widget.focusNode?.unfocus(); + } + + void resumeItemAddition() { + if (_pauseItemAddition) { + setState(() => _pauseItemAddition = false); + } + widget.focusNode?.requestFocus(); + } + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: _pauseItemAddition ? resumeItemAddition : null, + child: Material( + elevation: 1, + color: StreamChatTheme.of(context).colorTheme.white, + child: Container( + child: Padding( + padding: const EdgeInsets.fromLTRB(16, 16, 16, 16), + child: Row( + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 4.0), + child: Text( + 'TO:', + style: StreamChatTheme.of(context) + .textTheme + .footnote + .copyWith( + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(.5)), + ), + ), + SizedBox(width: 12), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Wrap( + spacing: 8.0, + runSpacing: 4.0, + children: _chips.map((item) { + return widget.chipBuilder(context, item); + }).toList(), + ), + if (!_pauseItemAddition) + TextField( + controller: widget.controller, + onChanged: widget.onInputChanged, + focusNode: widget.focusNode, + decoration: InputDecoration( + isDense: true, + border: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + errorBorder: InputBorder.none, + disabledBorder: InputBorder.none, + contentPadding: const EdgeInsets.only(top: 4.0), + hintText: widget.hint, + hintStyle: StreamChatTheme.of(context) + .textTheme + .body + .copyWith( + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(.5)), + ), + ), + ], + ), + ), + SizedBox(width: 12), + Align( + alignment: Alignment.bottomCenter, + child: IconButton( + icon: _chips.isEmpty + ? StreamSvgIcon.user( + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(0.5), + size: 24, + ) + : StreamSvgIcon.userAdd( + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(0.5), + size: 24, + ), + onPressed: resumeItemAddition, + alignment: Alignment.topRight, + visualDensity: VisualDensity.compact, + padding: const EdgeInsets.all(0), + splashRadius: 24, + constraints: BoxConstraints.tightFor( + height: 24, + width: 24, + ), + ), + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/stream_chat_v1/lib/choose_user_page.dart b/stream_chat_v1/lib/choose_user_page.dart new file mode 100644 index 0000000000..b796e5e873 --- /dev/null +++ b/stream_chat_v1/lib/choose_user_page.dart @@ -0,0 +1,269 @@ +import 'package:example/stream_version.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; + +import 'routes/routes.dart'; + +const kStreamApiKey = 'STREAM_API_KEY'; +const kStreamUserId = 'STREAM_USER_ID'; +const kStreamToken = 'STREAM_TOKEN'; +const kDefaultStreamApiKey = 'kv7mcsxr24p8'; + +class ChooseUserPage extends StatelessWidget { + @override + Widget build(BuildContext context) { + final users = { + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoic2FsdmF0b3JlIn0.pgiJz7sIc7iP29BHKFwe3nLm5-OaR_1l2P-SlgiC9a8': + User( + id: 'salvatore', + extraData: { + 'name': 'Salvatore Giordano', + 'image': + 'https://avatars.githubusercontent.com/u/20601437?s=460&u=3f66c22a7483980624804054ae7f357cf102c784&v=4', + }, + ), + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoic2FoaWwifQ.WnIUoB5gR2kcAsFhiDvkiD6zdHXZ-VSU2aQWWkhsvfo': + User( + id: 'sahil', + extraData: { + 'name': 'Sahil Kumar', + 'image': + 'https://avatars.githubusercontent.com/u/25670178?s=400&u=30ded3784d8d2310c5748f263fd5e6433c119aa1&v=4', + }, + ), + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiYmVuIn0.nAz2sNFGQwY7rl2Og2z3TGHUsdpnN53tOsUglJFvLmg': + User( + id: 'ben', + extraData: { + 'name': 'Ben Golden', + 'image': 'https://avatars.githubusercontent.com/u/1581974?s=400&v=4', + }, + ), + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoidGhpZXJyeSJ9.lEq6TrZtHzjoNtf7HHRufUPyGo_pa8vg4_XhEBp4ckY': + User( + id: 'thierry', + extraData: { + 'name': 'Thierry Schellenbach', + 'image': + 'https://avatars.githubusercontent.com/u/265409?s=400&u=2d0e3bb1820db992066196bff7b004f0eee8e28d&v=4', + }, + ), + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoidG9tbWFzbyJ9.GLSI0ESshERMo2WjUpysD709NEtn1zmGimUN2an7g9o': + User( + id: 'tommaso', + extraData: { + 'name': 'Tommaso Barbugli', + 'image': 'https://avatars.githubusercontent.com/u/88735?s=400&v=4', + }, + ), + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiZGV2ZW4ifQ.z3zI4PqJnNhc-1o-VKcmb6BnnQ0oxFNCRHwEulHqcWc': + User( + id: 'deven', + extraData: { + 'name': 'Deven Joshi', + 'image': + 'https://avatars.githubusercontent.com/u/26357843?s=400&u=0c61d890866e67bf69f58878be58915e9bfd39ee&v=4', + }, + ), + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoibmVldmFzaCJ9.3EdHegTxibrz3A9cTiKmpEyawwcCVB8FXnoFzr4eKvw': + User( + id: 'neevash', + extraData: { + 'name': 'Neevash Ramdial', + 'image': + 'https://avatars.githubusercontent.com/u/25674767?s=400&u=1d7333baf7dd9d143db8bfcdb31a838b89cfff9c&v=4', + }, + ), + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoicWF0ZXN0MSJ9.fnelU7HcP7QoEEsCGteNlF1fppofzNlrnpDQuIgeKCU': + User( + id: 'qatest1', + extraData: { + 'name': 'QA test 1', + }, + ), + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoicWF0ZXN0MiJ9.vSCqAEbs2WVmMWsOsa7065Fsjq-rsTih6qsHPynl7XM': + User( + id: 'qatest2', + extraData: { + 'name': 'QA test 2', + }, + ), + }; + + return Scaffold( + backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + body: SafeArea( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.only( + top: 34, + bottom: 20, + ), + child: Center( + child: SvgPicture.asset( + 'assets/logo.svg', + height: 40, + color: StreamChatTheme.of(context).colorTheme.accentBlue, + ), + ), + ), + Padding( + padding: const EdgeInsets.only(bottom: 13.0), + child: Text( + 'Welcome to Stream Chat', + style: StreamChatTheme.of(context).textTheme.title, + ), + ), + Text( + 'Select a user to try the Flutter SDK:', + style: StreamChatTheme.of(context).textTheme.body, + ), + Expanded( + child: Padding( + padding: const EdgeInsets.only(top: 32), + child: ListView.separated( + separatorBuilder: (context, i) { + return Container( + height: 1, + color: StreamChatTheme.of(context).colorTheme.greyWhisper, + ); + }, + itemCount: users.length + 1, + itemBuilder: (context, i) { + return [ + ...users.entries.map((entry) { + final token = entry.key; + final user = entry.value; + return ListTile( + visualDensity: VisualDensity.compact, + onTap: () async { + showDialog( + barrierDismissible: false, + context: context, + barrierColor: StreamChatTheme.of(context) + .colorTheme + .overlay, + builder: (context) => Center( + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16), + color: StreamChatTheme.of(context) + .colorTheme + .white, + ), + height: 100, + width: 100, + child: Center( + child: CircularProgressIndicator(), + ), + ), + ), + ); + + final client = StreamChat.of(context).client; + client.apiKey = kDefaultStreamApiKey; + await client.connectUser( + user, + token, + ); + + if (!kIsWeb) { + final secureStorage = FlutterSecureStorage(); + secureStorage.write( + key: kStreamApiKey, + value: kDefaultStreamApiKey, + ); + secureStorage.write( + key: kStreamUserId, + value: user.id, + ); + secureStorage.write( + key: kStreamToken, + value: token, + ); + } + Navigator.pushNamedAndRemoveUntil( + context, + Routes.HOME, + ModalRoute.withName(Routes.HOME), + ); + }, + leading: UserAvatar( + user: user, + constraints: BoxConstraints.tight( + Size.fromRadius(20), + ), + ), + title: Text( + user.name, + style: + StreamChatTheme.of(context).textTheme.bodyBold, + ), + subtitle: Text( + 'Stream test account', + style: StreamChatTheme.of(context) + .textTheme + .footnote + .copyWith( + color: StreamChatTheme.of(context) + .colorTheme + .grey, + ), + ), + trailing: StreamSvgIcon.arrowRight( + color: StreamChatTheme.of(context) + .colorTheme + .accentBlue, + ), + ); + }), + ListTile( + onTap: () { + Navigator.pushNamed(context, Routes.ADVANCED_OPTIONS); + }, + leading: CircleAvatar( + child: StreamSvgIcon.settings( + color: StreamChatTheme.of(context).colorTheme.black, + ), + backgroundColor: StreamChatTheme.of(context) + .colorTheme + .greyWhisper, + ), + title: Text( + 'Advanced Options', + style: StreamChatTheme.of(context).textTheme.bodyBold, + ), + subtitle: Text( + 'Custom settings', + style: StreamChatTheme.of(context) + .textTheme + .footnote + .copyWith( + color: + StreamChatTheme.of(context).colorTheme.grey, + ), + ), + trailing: SvgPicture.asset( + 'assets/icon_arrow_right.svg', + height: 24, + width: 24, + clipBehavior: Clip.none, + ), + ), + ][i]; + }, + ), + ), + ), + StreamVersion(), + ], + ), + ), + ); + } +} diff --git a/stream_chat_v1/lib/group_chat_details_screen.dart b/stream_chat_v1/lib/group_chat_details_screen.dart new file mode 100644 index 0000000000..afc9d12f7a --- /dev/null +++ b/stream_chat_v1/lib/group_chat_details_screen.dart @@ -0,0 +1,331 @@ +import 'package:flutter/material.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; +import 'package:uuid/uuid.dart'; + +import 'main.dart'; +import 'routes/routes.dart'; + +class GroupChatDetailsScreen extends StatefulWidget { + final List selectedUsers; + + const GroupChatDetailsScreen({ + Key key, + @required this.selectedUsers, + }) : super(key: key); + + @override + _GroupChatDetailsScreenState createState() => _GroupChatDetailsScreenState(); +} + +class _GroupChatDetailsScreenState extends State { + final _selectedUsers = []; + + TextEditingController _groupNameController; + + bool _isGroupNameEmpty = true; + + int get _totalUsers => _selectedUsers.length; + + void _groupNameListener() { + final name = _groupNameController.text; + if (mounted) { + setState(() { + _isGroupNameEmpty = name.isEmpty; + }); + } + } + + @override + void initState() { + super.initState(); + _selectedUsers.addAll(widget.selectedUsers); + _groupNameController = TextEditingController() + ..addListener(_groupNameListener); + } + + @override + void dispose() { + _groupNameController?.removeListener(_groupNameListener); + _groupNameController?.clear(); + _groupNameController?.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return WillPopScope( + onWillPop: () async { + Navigator.pop(context, _selectedUsers); + return false; + }, + child: Scaffold( + backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + appBar: AppBar( + brightness: Theme.of(context).brightness, + elevation: 1, + backgroundColor: StreamChatTheme.of(context).colorTheme.white, + leading: const StreamBackButton(), + title: Text( + 'Name of Group Chat', + style: TextStyle( + color: StreamChatTheme.of(context).colorTheme.black, + fontSize: 16, + ), + ), + centerTitle: true, + bottom: PreferredSize( + preferredSize: Size.fromHeight(kToolbarHeight), + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 18, horizontal: 16), + child: Row( + children: [ + Text( + 'NAME', + style: TextStyle( + fontSize: 12, + color: StreamChatTheme.of(context).colorTheme.grey, + ), + ), + SizedBox(width: 16), + Expanded( + child: TextField( + controller: _groupNameController, + decoration: InputDecoration( + isDense: true, + border: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + errorBorder: InputBorder.none, + disabledBorder: InputBorder.none, + contentPadding: const EdgeInsets.all(0), + hintText: 'Choose a group chat name', + hintStyle: TextStyle( + fontSize: 14, + color: StreamChatTheme.of(context).colorTheme.grey, + ), + ), + ), + ), + ], + ), + ), + ), + actions: [ + StreamNeumorphicButton( + child: IconButton( + padding: const EdgeInsets.all(0), + icon: StreamSvgIcon.check( + size: 24, + color: _isGroupNameEmpty + ? StreamChatTheme.of(context).colorTheme.grey + : StreamChatTheme.of(context).colorTheme.accentBlue, + ), + onPressed: _isGroupNameEmpty + ? null + : () async { + try { + final groupName = _groupNameController.text; + final client = StreamChat.of(context).client; + final channel = client.channel('messaging', + id: Uuid().v4(), + extraData: { + 'members': [ + client.state.user.id, + ..._selectedUsers.map((e) => e.id), + ], + 'name': groupName, + }); + await channel.watch(); + Navigator.pushNamedAndRemoveUntil( + context, + Routes.CHANNEL_PAGE, + ModalRoute.withName(Routes.HOME), + arguments: ChannelPageArgs(channel: channel), + ); + } catch (err) { + _showErrorAlert(); + } + }, + ), + ), + ], + ), + body: ConnectionStatusBuilder( + statusBuilder: (context, status) { + String statusString = ''; + bool showStatus = true; + + switch (status) { + case ConnectionStatus.connected: + statusString = 'Connected'; + showStatus = false; + break; + case ConnectionStatus.connecting: + statusString = 'Reconnecting...'; + break; + case ConnectionStatus.disconnected: + statusString = 'Disconnected'; + break; + } + return InfoTile( + showMessage: showStatus, + tileAnchor: Alignment.topCenter, + childAnchor: Alignment.topCenter, + message: statusString, + child: Column( + children: [ + Container( + width: double.maxFinite, + decoration: BoxDecoration( + gradient: + StreamChatTheme.of(context).colorTheme.bgGradient, + ), + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 8, + horizontal: 8, + ), + child: Text( + '$_totalUsers ${_totalUsers > 1 ? 'Members' : 'Member'}', + style: TextStyle( + color: StreamChatTheme.of(context).colorTheme.grey, + ), + ), + ), + ), + Expanded( + child: GestureDetector( + behavior: HitTestBehavior.opaque, + onPanDown: (_) => FocusScope.of(context).unfocus(), + child: ListView.separated( + itemCount: _selectedUsers.length + 1, + separatorBuilder: (_, __) => Container( + height: 1, + color: StreamChatTheme.of(context) + .colorTheme + .greyWhisper, + ), + itemBuilder: (_, index) { + if (index == _selectedUsers.length) { + return Container( + height: 1, + color: StreamChatTheme.of(context) + .colorTheme + .greyWhisper, + ); + } + final user = _selectedUsers[index]; + return ListTile( + key: ObjectKey(user), + leading: UserAvatar( + user: user, + constraints: BoxConstraints.tightFor( + width: 40, + height: 40, + ), + ), + title: Text( + user.name, + style: TextStyle(fontWeight: FontWeight.bold), + ), + contentPadding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 8, + ), + trailing: IconButton( + icon: Icon( + Icons.clear_rounded, + color: StreamChatTheme.of(context) + .colorTheme + .black, + ), + padding: const EdgeInsets.all(0), + splashRadius: 24, + onPressed: () { + setState(() { + _selectedUsers.remove(user); + }); + if (_selectedUsers.isEmpty) { + Navigator.pop(context, _selectedUsers); + } + }, + ), + ); + }, + ), + ), + ), + ], + ), + ); + }, + ), + ), + ); + } + + void _showErrorAlert() { + showModalBottomSheet( + backgroundColor: StreamChatTheme.of(context).colorTheme.white, + context: context, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(16.0), + topRight: Radius.circular(16.0), + )), + builder: (context) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + height: 26.0, + ), + StreamSvgIcon.error( + color: StreamChatTheme.of(context).colorTheme.accentRed, + size: 24.0, + ), + SizedBox( + height: 26.0, + ), + Text( + 'Something went wrong', + style: StreamChatTheme.of(context).textTheme.headlineBold, + ), + SizedBox( + height: 7.0, + ), + Text('The operation couldn\'t be completed.'), + SizedBox( + height: 36.0, + ), + Container( + color: + StreamChatTheme.of(context).colorTheme.black.withOpacity(.08), + height: 1.0, + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + FlatButton( + child: Text( + 'OK', + style: StreamChatTheme.of(context) + .textTheme + .bodyBold + .copyWith( + color: StreamChatTheme.of(context) + .colorTheme + .accentBlue), + ), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ), + ], + ); + }, + ); + } +} diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/group_info_screen.dart new file mode 100644 index 0000000000..f0c7ff34f4 --- /dev/null +++ b/stream_chat_v1/lib/group_info_screen.dart @@ -0,0 +1,1038 @@ +import 'dart:async'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:jiffy/jiffy.dart'; +import 'package:stream_chat_flutter/src/option_list_tile.dart'; +import 'package:stream_chat_flutter/src/stream_svg_icon.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; + +import 'chat_info_screen.dart'; +import 'main.dart'; +import 'routes/routes.dart'; + +class GroupInfoScreen extends StatefulWidget { + @override + _GroupInfoScreenState createState() => _GroupInfoScreenState(); +} + +class _GroupInfoScreenState extends State { + TextEditingController _nameController; + + TextEditingController _searchController; + String _userNameQuery = ''; + + Timer _debounce; + Function modalSetStateCallback; + + final FocusNode _focusNode = FocusNode(); + + bool listExpanded = false; + + ValueNotifier mutedBool = ValueNotifier(false); + + void _userNameListener() { + if (_searchController.text == _userNameQuery) { + return; + } + if (_debounce?.isActive ?? false) _debounce.cancel(); + _debounce = Timer(const Duration(milliseconds: 350), () { + if (mounted && modalSetStateCallback != null) { + modalSetStateCallback(() { + _userNameQuery = _searchController.text; + }); + } + }); + } + + @override + void initState() { + super.initState(); + var channel = StreamChannel.of(context); + _nameController = TextEditingController.fromValue( + TextEditingValue(text: channel.channel.extraData['name'] ?? '')); + _searchController = TextEditingController()..addListener(_userNameListener); + + _nameController.addListener(() { + setState(() {}); + }); + mutedBool = ValueNotifier(StreamChannel.of(context).channel.isMuted); + } + + @override + Widget build(BuildContext context) { + var channel = StreamChannel.of(context); + + return StreamBuilder>( + stream: channel.channel.state.membersStream, + builder: (context, snapshot) { + if (!snapshot.hasData) { + return Container( + color: StreamChatTheme.of(context).colorTheme.greyGainsboro, + child: Center(child: CircularProgressIndicator()), + ); + } + + var userMember = snapshot.data.firstWhere( + (e) => e.user.id == StreamChat.of(context).user.id, + orElse: () => null, + ); + var isOwner = userMember?.role == 'owner'; + + return Scaffold( + backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + appBar: AppBar( + brightness: Theme.of(context).brightness, + elevation: 1.0, + toolbarHeight: 56.0, + backgroundColor: StreamChatTheme.of(context).colorTheme.white, + leading: StreamBackButton(), + title: Column( + children: [ + StreamBuilder( + stream: channel.channelStateStream, + builder: (context, state) { + if (!state.hasData) { + return Text( + 'Loading...', + style: TextStyle( + color: + StreamChatTheme.of(context).colorTheme.black, + fontSize: 16, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ); + } + + return Text( + _getChannelName( + 2 * MediaQuery.of(context).size.width / 3, + members: snapshot.data, + extraData: state.data.channel.extraData, + maxFontSize: 16.0), + style: TextStyle( + color: StreamChatTheme.of(context).colorTheme.black, + fontSize: 16, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ); + }), + SizedBox( + height: 3.0, + ), + Text( + '${channel.channel.memberCount} Members, ${snapshot?.data?.where((e) => e.user.online)?.length ?? 0} Online', + style: TextStyle( + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(0.5), + fontSize: 12.0, + ), + ), + ], + ), + centerTitle: true, + actions: [ + if (!channel.channel.isDistinct && isOwner) + StreamNeumorphicButton( + child: InkWell( + onTap: () { + _buildAddUserModal(context); + }, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: StreamSvgIcon.userAdd( + color: StreamChatTheme.of(context) + .colorTheme + .accentBlue), + ), + ), + ), + ], + ), + body: ListView( + children: [ + _buildMembers(snapshot.data), + Container( + height: 8.0, + color: StreamChatTheme.of(context).colorTheme.greyGainsboro, + ), + if (isOwner) _buildNameTile(), + _buildOptionListTiles(), + ], + ), + ); + }); + } + + Widget _buildMembers(List members) { + final groupMembers = members + ..sort((prev, curr) { + if (curr.role == 'owner') return 1; + return 0; + }); + + int groupMembersLength; + + if (listExpanded) { + groupMembersLength = groupMembers.length; + } else { + groupMembersLength = groupMembers.length > 6 ? 6 : groupMembers.length; + } + + return Column( + children: [ + ListView.builder( + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + itemCount: groupMembersLength, + itemBuilder: (context, index) { + final member = groupMembers[index]; + return Material( + child: InkWell( + onTap: () { + final userMember = groupMembers.firstWhere( + (e) => e.user.id == StreamChat.of(context).user.id, + orElse: () => null, + ); + _showUserInfoModal(member.user, userMember?.role == 'owner'); + }, + child: Container( + height: 65.0, + child: Column( + children: [ + Row( + children: [ + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 8.0, vertical: 12.0), + child: UserAvatar( + user: member.user, + constraints: BoxConstraints( + maxHeight: 40.0, maxWidth: 40.0), + ), + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + member.user.name, + style: TextStyle(fontWeight: FontWeight.bold), + ), + SizedBox( + height: 1.0, + ), + Text( + _getLastSeen(member.user), + style: TextStyle( + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(0.5)), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + member.role == 'owner' ? 'Owner' : '', + style: TextStyle( + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(0.5)), + ), + ), + ], + ), + Container( + height: 1.0, + color: StreamChatTheme.of(context) + .colorTheme + .greyGainsboro, + ), + ], + ), + ), + ), + color: StreamChatTheme.of(context).colorTheme.whiteSnow, + ); + }, + ), + if (groupMembersLength != groupMembers.length) + InkWell( + onTap: () { + setState(() { + listExpanded = true; + }); + }, + child: Material( + color: StreamChatTheme.of(context).colorTheme.whiteSnow, + child: Container( + height: 65.0, + child: Column( + children: [ + Expanded( + child: Row( + children: [ + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 21.0, vertical: 12.0), + child: StreamSvgIcon.down( + color: + StreamChatTheme.of(context).colorTheme.grey, + ), + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + '${members.length - groupMembersLength} more', + style: TextStyle( + color: StreamChatTheme.of(context) + .colorTheme + .grey), + ), + ], + ), + ), + ], + ), + ), + Container( + height: 1.0, + color: + StreamChatTheme.of(context).colorTheme.greyGainsboro, + ), + ], + ), + ), + ), + ), + ], + ); + } + + Widget _buildNameTile() { + var channel = StreamChannel.of(context).channel; + var channelName = channel.extraData['name'] ?? ''; + + return Material( + color: StreamChatTheme.of(context).colorTheme.whiteSnow, + child: Container( + height: 56.0, + alignment: Alignment.center, + child: Row( + children: [ + Padding( + padding: const EdgeInsets.all(7.0), + child: Text( + 'NAME', + style: StreamChatTheme.of(context).textTheme.footnote.copyWith( + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(0.5)), + ), + ), + SizedBox( + width: 7.0, + ), + Expanded( + child: TextField( + focusNode: _focusNode, + controller: _nameController, + cursorColor: StreamChatTheme.of(context).colorTheme.black, + decoration: InputDecoration.collapsed( + hintText: 'Add a group name', + hintStyle: StreamChatTheme.of(context) + .textTheme + .bodyBold + .copyWith( + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(0.5))), + style: TextStyle( + fontWeight: FontWeight.bold, + height: 0.82, + ), + ), + ), + if ((channelName == null) || + (channelName != _nameController.text.trim())) + Row( + mainAxisSize: MainAxisSize.min, + children: [ + InkWell( + child: StreamSvgIcon.closeSmall(), + onTap: () { + setState(() { + _nameController.text = + _getChannelName(MediaQuery.of(context).size.width); + _focusNode.unfocus(); + }); + }, + ), + Padding( + padding: const EdgeInsets.only(right: 16.0, left: 8.0), + child: InkWell( + child: StreamSvgIcon.check( + color: + StreamChatTheme.of(context).colorTheme.accentBlue, + size: 24.0, + ), + onTap: () { + StreamChannel.of(context).channel.update({ + 'name': _nameController.text.trim(), + }).catchError((err) { + setState(() { + _nameController.text = channelName; + _focusNode.unfocus(); + }); + }); + }, + ), + ), + ], + ), + ], + ), + ), + ); + } + + Widget _buildOptionListTiles() { + var channel = StreamChannel.of(context); + + return Column( + children: [ + // OptionListTile( + // title: 'Notifications', + // leading: StreamSvgIcon.Icon_notification( + // size: 24.0, + // color: StreamChatTheme.of(context).colorTheme.black.withOpacity(0.5), + // ), + // trailing: CupertinoSwitch( + // value: true, + // onChanged: (val) {}, + // ), + // onTap: () {}, + // ), + StreamBuilder( + stream: StreamChannel.of(context).channel.isMutedStream, + builder: (context, snapshot) { + mutedBool.value = snapshot.data; + + return OptionListTile( + tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + separatorColor: + StreamChatTheme.of(context).colorTheme.greyGainsboro, + title: 'Mute group', + titleTextStyle: StreamChatTheme.of(context).textTheme.body, + leading: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: StreamSvgIcon.mute( + size: 24.0, + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(0.5), + ), + ), + trailing: snapshot.data == null + ? CircularProgressIndicator() + : ValueListenableBuilder( + valueListenable: mutedBool, + builder: (context, value, _) { + return CupertinoSwitch( + value: value, + onChanged: (val) { + mutedBool.value = val; + + if (snapshot.data) { + channel.channel.unmute(); + } else { + channel.channel.mute(); + } + }, + ); + }), + onTap: () {}, + ); + }), + OptionListTile( + tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + separatorColor: StreamChatTheme.of(context).colorTheme.greyGainsboro, + title: 'Photos & Videos', + titleTextStyle: StreamChatTheme.of(context).textTheme.body, + leading: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: StreamSvgIcon.pictures( + size: 32.0, + color: + StreamChatTheme.of(context).colorTheme.black.withOpacity(0.5), + ), + ), + trailing: StreamSvgIcon.right( + color: StreamChatTheme.of(context).colorTheme.grey, + ), + onTap: () { + var channel = StreamChannel.of(context).channel; + + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => StreamChannel( + channel: channel, + child: MessageSearchBloc( + child: ChannelMediaDisplayScreen( + sortOptions: [ + SortOption( + 'created_at', + direction: SortOption.ASC, + ), + ], + paginationParams: PaginationParams(limit: 20), + onShowMessage: (m, c) async { + final client = StreamChat.of(context).client; + final message = m; + final channel = client.channel( + c.type, + id: c.id, + ); + if (channel.state == null) { + await channel.watch(); + } + await Navigator.pushNamed( + context, + Routes.CHANNEL_PAGE, + arguments: ChannelPageArgs( + channel: channel, + initialMessage: message, + ), + ); + }, + ), + ), + ), + ), + ); + }, + ), + OptionListTile( + tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + separatorColor: StreamChatTheme.of(context).colorTheme.greyGainsboro, + title: 'Files', + titleTextStyle: StreamChatTheme.of(context).textTheme.body, + leading: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: StreamSvgIcon.files( + size: 32.0, + color: + StreamChatTheme.of(context).colorTheme.black.withOpacity(0.5), + ), + ), + trailing: StreamSvgIcon.right( + color: StreamChatTheme.of(context).colorTheme.grey, + ), + onTap: () { + var channel = StreamChannel.of(context).channel; + + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => StreamChannel( + channel: channel, + child: MessageSearchBloc( + child: ChannelFileDisplayScreen( + sortOptions: [ + SortOption( + 'created_at', + direction: SortOption.ASC, + ), + ], + paginationParams: PaginationParams(limit: 20), + ), + ), + ), + ), + ); + }, + ), + if (!channel.channel.isDistinct) + OptionListTile( + tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + separatorColor: + StreamChatTheme.of(context).colorTheme.greyGainsboro, + title: 'Leave Group', + titleTextStyle: StreamChatTheme.of(context).textTheme.body, + leading: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: StreamSvgIcon.userRemove( + size: 24.0, + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(0.5), + ), + ), + trailing: Container( + height: 24.0, + width: 24.0, + ), + onTap: () async { + final res = await showConfirmationDialog( + context, + title: 'Leave conversation', + okText: 'LEAVE', + question: 'Are you sure you want to leave this conversation?', + cancelText: 'CANCEL', + icon: StreamSvgIcon.userRemove( + color: StreamChatTheme.of(context).colorTheme.accentRed, + ), + ); + if (res == true) { + final channel = StreamChannel.of(context).channel; + await channel.removeMembers([StreamChat.of(context).user.id]); + Navigator.pop(context); + } + }, + ), + ], + ); + } + + void _buildAddUserModal(context) { + var channel = StreamChannel.of(context).channel; + + showDialog( + context: context, + barrierColor: StreamChatTheme.of(context).colorTheme.overlay, + builder: (context) { + return StatefulBuilder(builder: (context, modalSetState) { + modalSetStateCallback = modalSetState; + return Padding( + padding: EdgeInsets.only(top: 16.0, left: 8.0, right: 8.0), + child: Material( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(16.0), + topRight: Radius.circular(16.0), + ), + clipBehavior: Clip.antiAlias, + child: Scaffold( + body: UsersBloc( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: _buildTextInputSection(modalSetState), + ), + Expanded( + child: UserListView( + selectedUsers: {}, + onUserTap: (user, _) async { + _searchController.clear(); + + await channel.addMembers([user.id]); + Navigator.pop(context); + setState(() {}); + }, + crossAxisCount: 4, + pagination: PaginationParams( + limit: 25, + ), + filter: { + if (_searchController.text.isNotEmpty) + 'name': { + r'$autocomplete': _userNameQuery, + }, + 'id': { + r'$nin': [ + StreamChat.of(context).user.id, + ...channel.state.members.map((e) => e.userId), + ], + }, + }, + sort: [ + SortOption( + 'name', + direction: 1, + ), + ], + emptyBuilder: (_) { + return LayoutBuilder( + builder: (context, viewportConstraints) { + return SingleChildScrollView( + physics: AlwaysScrollableScrollPhysics(), + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: viewportConstraints.maxHeight, + ), + child: Center( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(24), + child: StreamSvgIcon.search( + size: 96, + color: StreamChatTheme.of(context) + .colorTheme + .grey, + ), + ), + Text( + 'No user matches these keywords...'), + ], + ), + ), + ), + ); + }, + ); + }, + ), + ), + ], + ), + ), + ), + ), + ); + }); + }, + ); + } + + Widget _buildTextInputSection(modalSetState) { + final theme = StreamChatTheme.of(context); + return Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Container( + height: 36, + child: TextField( + controller: _searchController, + cursorColor: theme.colorTheme.black, + autofocus: true, + decoration: InputDecoration( + hintText: 'Search', + hintStyle: theme.textTheme.body.copyWith( + color: theme.colorTheme.grey, + ), + prefixIconConstraints: BoxConstraints.tight(Size(40, 24)), + prefixIcon: StreamSvgIcon.search( + color: theme.colorTheme.black, + size: 24, + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(24.0), + borderSide: BorderSide( + color: theme.colorTheme.greyWhisper, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(24.0), + borderSide: BorderSide( + color: theme.colorTheme.greyWhisper, + )), + contentPadding: const EdgeInsets.all(0), + ), + ), + ), + ), + SizedBox(width: 16.0), + IconButton( + icon: StreamSvgIcon.closeSmall( + color: theme.colorTheme.grey, + ), + constraints: BoxConstraints.tightFor( + height: 24, + width: 24, + ), + padding: EdgeInsets.zero, + splashRadius: 24, + onPressed: () => Navigator.pop(context), + ) + ], + ), + ], + ); + } + + void _showUserInfoModal(User user, bool isUserAdmin) { + var channel = StreamChannel.of(context).channel; + + showModalBottomSheet( + context: context, + clipBehavior: Clip.antiAlias, + isScrollControlled: true, + builder: (context) { + return StreamChannel( + channel: channel, + child: Material( + color: StreamChatTheme.of(context).colorTheme.white, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + height: 24.0, + ), + Center( + child: Text( + user.name, + style: TextStyle( + fontSize: 16.0, + fontWeight: FontWeight.bold, + ), + ), + ), + SizedBox( + height: 5.0, + ), + _buildConnectedTitleState(user), + Center( + child: Padding( + padding: const EdgeInsets.all(16.0), + child: UserAvatar( + user: user, + constraints: BoxConstraints( + maxHeight: 64.0, + minHeight: 64.0, + ), + borderRadius: BorderRadius.circular(32.0), + ), + ), + ), + if (StreamChat.of(context).user.id != user.id) + _buildModalListTile( + context, + StreamSvgIcon.user( + color: StreamChatTheme.of(context).colorTheme.grey, + size: 24.0, + ), + 'View info', + () async { + var client = StreamChat.of(context).client; + + var c = client.channel('messaging', extraData: { + 'members': [ + user.id, + StreamChat.of(context).user.id, + ], + }); + + await c.watch(); + + await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => StreamChannel( + channel: c, + child: ChatInfoScreen( + user: user, + ), + ), + ), + ); + }, + ), + if (StreamChat.of(context).user.id != user.id) + _buildModalListTile( + context, + StreamSvgIcon.message( + color: StreamChatTheme.of(context).colorTheme.grey, + size: 24.0, + ), + 'Message', + () async { + var client = StreamChat.of(context).client; + + var c = client.channel('messaging', extraData: { + 'members': [ + user.id, + StreamChat.of(context).user.id, + ], + }); + + await c.watch(); + + await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => StreamChannel( + channel: c, + child: ChannelPage(), + ), + ), + ); + }, + ), + if (!channel.isDistinct && + StreamChat.of(context).user.id != user.id && + isUserAdmin) + _buildModalListTile( + context, + StreamSvgIcon.iconUserSettings( + color: StreamChatTheme.of(context).colorTheme.grey, + size: 24.0, + ), + 'Make Owner', () { + // TODO: Add make owner implementation (Remaining from backend) + }), + if (!channel.isDistinct && + StreamChat.of(context).user.id != user.id && + isUserAdmin) + _buildModalListTile( + context, + StreamSvgIcon.userRemove( + color: StreamChatTheme.of(context).colorTheme.accentRed, + size: 24.0, + ), + 'Remove From Group', () async { + await channel.removeMembers([user.id]); + Navigator.pop(context); + }, color: StreamChatTheme.of(context).colorTheme.accentRed), + _buildModalListTile( + context, + StreamSvgIcon.closeSmall( + color: StreamChatTheme.of(context).colorTheme.grey, + size: 24.0, + ), + 'Cancel', () { + Navigator.pop(context); + }), + ], + ), + ), + ); + }, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(16.0), + topRight: Radius.circular(16.0), + ), + ), + ); + } + + Widget _buildConnectedTitleState(User user) { + var alternativeWidget; + + final otherMember = user; + + if (otherMember != null) { + if (otherMember.online) { + alternativeWidget = Text( + 'Online', + style: TextStyle( + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(0.5)), + ); + } else { + alternativeWidget = Text( + 'Last seen ${Jiffy(otherMember.lastActive).fromNow()}', + style: TextStyle( + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(0.5)), + ); + } + } + + return alternativeWidget; + } + + Widget _buildModalListTile( + BuildContext context, Widget leading, String title, VoidCallback onTap, + {Color color}) { + color ??= StreamChatTheme.of(context).colorTheme.black; + + return Material( + color: StreamChatTheme.of(context).colorTheme.white, + child: InkWell( + onTap: onTap, + child: Column( + children: [ + Container( + height: 1.0, + color: StreamChatTheme.of(context).colorTheme.greyGainsboro, + ), + Container( + height: 64.0, + child: Row( + children: [ + Padding( + padding: const EdgeInsets.all(16.0), + child: leading, + ), + Expanded( + child: Text( + title, + style: + TextStyle(color: color, fontWeight: FontWeight.bold), + ), + ) + ], + ), + ), + ], + ), + ), + ); + } + + String _getChannelName(double width, + {List members, Map extraData, double maxFontSize}) { + String title; + var client = StreamChat.of(context); + if (extraData['name'] == null) { + final otherMembers = + members.where((member) => member.user.id != client.user.id); + if (otherMembers.isNotEmpty) { + final maxWidth = width; + final maxChars = maxWidth / maxFontSize; + var currentChars = 0; + final currentMembers = []; + otherMembers.forEach((element) { + final newLength = currentChars + element.user.name.length; + if (newLength < maxChars) { + currentChars = newLength; + currentMembers.add(element); + } + }); + + final exceedingMembers = otherMembers.length - currentMembers.length; + title = + '${currentMembers.map((e) => e.user.name).join(', ')} ${exceedingMembers > 0 ? '+ $exceedingMembers' : ''}'; + } else { + title = 'No title'; + } + } else { + title = extraData['name']; + } + return title; + } + + String _getLastSeen(User user) { + if (user.online) { + return 'Online'; + } else { + return 'Last seen ${Jiffy(user.lastActive).fromNow()}'; + } + } +} diff --git a/stream_chat_v1/lib/main.dart b/stream_chat_v1/lib/main.dart new file mode 100644 index 0000000000..2fb2cf8b1b --- /dev/null +++ b/stream_chat_v1/lib/main.dart @@ -0,0 +1,1066 @@ +import 'dart:async'; + +import 'package:example/chat_info_screen.dart'; +import 'package:example/choose_user_page.dart'; +import 'package:example/group_info_screen.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_app_badger/flutter_app_badger.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:lottie/lottie.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; +import 'package:stream_chat_persistence/stream_chat_persistence.dart'; +import 'package:streaming_shared_preferences/streaming_shared_preferences.dart'; + +import 'notifications_service.dart'; +import 'routes/app_routes.dart'; +import 'routes/routes.dart'; +import 'search_text_field.dart'; + +final chatPersistentClient = StreamChatPersistenceClient( + logLevel: Level.SEVERE, + connectionMode: ConnectionMode.background, +); + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + + runApp(MyApp()); +} + +class MyApp extends StatefulWidget { + @override + _MyAppState createState() => _MyAppState(); +} + +class _MyAppState extends State with TickerProviderStateMixin { + InitData _initData; + bool _animCompleted = false; + Animation _animation, _scaleAnimation; + AnimationController _animationController, _scaleAnimationController; + Animation _colorAnimation; + int timeOfStartMs; + + Future _initConnection() async { + String apiKey, userId, token; + + if (!kIsWeb) { + final secureStorage = FlutterSecureStorage(); + apiKey = await secureStorage.read(key: kStreamApiKey); + userId = await secureStorage.read(key: kStreamUserId); + token = await secureStorage.read(key: kStreamToken); + } + + final client = StreamChatClient( + apiKey ?? kDefaultStreamApiKey, + logLevel: Level.SEVERE, + )..chatPersistenceClient = chatPersistentClient; + + if (userId != null) { + await client.connectUser( + User(id: userId), + token, + ); + } + + final prefs = await StreamingSharedPreferences.instance; + + return InitData(client, prefs); + } + + void _createAnimations() { + _scaleAnimationController = AnimationController( + vsync: this, + value: 0, + duration: Duration( + milliseconds: 500, + ), + ); + _scaleAnimation = Tween( + begin: 1.0, + end: 1.5, + ).animate(CurvedAnimation( + parent: _scaleAnimationController, + curve: Curves.easeInOutBack, + )); + + _animationController = AnimationController( + vsync: this, + duration: Duration( + milliseconds: 1000, + ), + ); + _animation = Tween( + begin: 0.0, + end: 1000.0, + ).animate(CurvedAnimation( + parent: _animationController, + curve: Curves.easeInOut, + )); + _colorAnimation = ColorTween( + begin: Color(0xff005FFF), + end: Color(0xff005FFF), + ).animate(CurvedAnimation( + parent: _animationController, + curve: Curves.easeInOut, + )); + _colorAnimation = ColorTween( + begin: Color(0xff005FFF), + end: Colors.transparent, + ).animate(CurvedAnimation( + parent: _animationController, + curve: Curves.easeInOut, + )); + } + + @override + void initState() { + timeOfStartMs = DateTime.now().millisecondsSinceEpoch; + + _createAnimations(); + + _initConnection().then( + (initData) { + setState(() { + _initData = initData; + }); + + var now = DateTime.now().millisecondsSinceEpoch; + + if (now - timeOfStartMs > 1500) { + SchedulerBinding.instance.addPostFrameCallback((timeStamp) { + _scaleAnimationController.forward().whenComplete(() { + _animationController.forward(); + }); + }); + } else { + Future.delayed(Duration(milliseconds: 1500)).then((value) { + _scaleAnimationController.forward().whenComplete(() { + _animationController.forward(); + }); + }); + } + + if (!kIsWeb) { + _initData.client.state?.totalUnreadCountStream?.listen((count) { + if (count > 0) { + FlutterAppBadger.updateBadgeCount(count); + } else { + FlutterAppBadger.removeBadge(); + } + }); + } + }, + ); + _animationController.addStatusListener((status) { + if (status == AnimationStatus.completed) { + setState(() { + _animCompleted = true; + }); + } + }); + + super.initState(); + } + + Widget _buildAnimation() { + return MaterialApp( + home: Stack( + clipBehavior: Clip.none, + alignment: Alignment.center, + children: [ + AnimatedBuilder( + animation: _scaleAnimation, + builder: (context, _) { + return Transform.scale( + scale: _scaleAnimation.value, + child: AnimatedBuilder( + animation: _colorAnimation, + builder: (context, snapshot) { + return Container( + alignment: Alignment.center, + constraints: BoxConstraints.expand(), + color: _colorAnimation == null + ? Color(0xff005FFF) + : _colorAnimation.value, + child: !_animationController.isAnimating + ? Lottie.asset( + 'assets/floating_boat.json', + alignment: Alignment.center, + ) + : SizedBox(), + ); + }), + ); + }, + ), + AnimatedBuilder( + animation: _animation, + builder: (context, snapshot) { + return Transform.scale( + scale: _animation.value, + child: Container( + width: 1.0, + height: 1.0, + decoration: BoxDecoration( + color: Colors.white + .withOpacity(1 - _animationController.value), + shape: BoxShape.circle, + ), + ), + ); + }, + ), + ], + ), + ); + } + + @override + Widget build(BuildContext context) { + return Stack( + alignment: Alignment.center, + children: [ + if (_initData != null) + PreferenceBuilder( + preference: _initData.preferences.getInt( + 'theme', + defaultValue: 0, + ), + builder: (context, snapshot) => MaterialApp( + builder: (context, child) { + return StreamChat( + client: _initData.client, + onBackgroundEventReceived: (e) => + showLocalNotification(e, _initData.client.state.user.id), + child: Builder( + builder: (context) => AnnotatedRegion( + child: child, + value: SystemUiOverlayStyle( + systemNavigationBarColor: + StreamChatTheme.of(context).colorTheme.white, + systemNavigationBarIconBrightness: + Theme.of(context).brightness == Brightness.dark + ? Brightness.light + : Brightness.dark, + ), + ), + ), + ); + }, + theme: ThemeData.light(), + darkTheme: ThemeData.dark(), + themeMode: { + -1: ThemeMode.dark, + 0: ThemeMode.system, + 1: ThemeMode.light, + }[snapshot], + onGenerateRoute: AppRoutes.generateRoute, + initialRoute: _initData.client.state.user == null + ? Routes.CHOOSE_USER + : Routes.HOME, + ), + ), + if (!_animCompleted) _buildAnimation(), + ], + ); + } +} + +class HomePage extends StatefulWidget { + @override + _HomePageState createState() => _HomePageState(); +} + +class _HomePageState extends State { + int _currentIndex = 0; + + bool _isSelected(int index) => _currentIndex == index; + + List get _navBarItems { + return [ + BottomNavigationBarItem( + icon: Stack( + clipBehavior: Clip.none, + children: [ + StreamSvgIcon.message( + color: _isSelected(0) + ? StreamChatTheme.of(context).colorTheme.black + : Colors.grey, + ), + Positioned( + top: -3, + right: -16, + child: UnreadIndicator(), + ), + ], + ), + label: 'Chats', + ), + BottomNavigationBarItem( + icon: Stack( + clipBehavior: Clip.none, + children: [ + StreamSvgIcon.mentions( + color: _isSelected(1) + ? StreamChatTheme.of(context).colorTheme.black + : Colors.grey, + ), + ], + ), + label: 'Mentions', + ), + ]; + } + + @override + Widget build(BuildContext context) { + final user = StreamChat.of(context).user; + return Scaffold( + backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + appBar: ChannelListHeader( + onNewChatButtonTap: () { + Navigator.pushNamed(context, Routes.NEW_CHAT); + }, + preNavigationCallback: () { + FocusScope.of(context).requestFocus(FocusNode()); + }, + ), + drawer: _buildDrawer(context, user), + drawerEdgeDragWidth: 50, + bottomNavigationBar: BottomNavigationBar( + backgroundColor: StreamChatTheme.of(context).colorTheme.white, + currentIndex: _currentIndex, + items: _navBarItems, + selectedLabelStyle: StreamChatTheme.of(context).textTheme.footnoteBold, + unselectedLabelStyle: + StreamChatTheme.of(context).textTheme.footnoteBold, + type: BottomNavigationBarType.fixed, + selectedItemColor: StreamChatTheme.of(context).colorTheme.black, + unselectedItemColor: Colors.grey, + onTap: (index) { + setState(() => _currentIndex = index); + }, + ), + body: IndexedStack( + index: _currentIndex, + children: [ + ChannelListPage(), + UserMentionPage(), + ], + ), + ); + } + + Drawer _buildDrawer(BuildContext context, User user) { + return Drawer( + child: Container( + color: StreamChatTheme.of(context).colorTheme.white, + child: SafeArea( + child: Padding( + padding: EdgeInsets.only( + top: MediaQuery.of(context).viewPadding.top + 8, + ), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.only( + bottom: 20.0, + left: 8, + ), + child: Row( + children: [ + UserAvatar( + user: user, + showOnlineStatus: false, + constraints: BoxConstraints.tight(Size.fromRadius(20)), + ), + Padding( + padding: const EdgeInsets.only(left: 16.0), + child: Text( + user.name, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + ), + ListTile( + leading: StreamSvgIcon.penWrite( + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(.5), + ), + onTap: () { + Navigator.popAndPushNamed( + context, + Routes.NEW_CHAT, + ); + }, + title: Text( + 'New direct message', + style: TextStyle( + fontSize: 14.5, + ), + ), + ), + ListTile( + leading: StreamSvgIcon.contacts( + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(.5), + ), + onTap: () { + Navigator.popAndPushNamed( + context, + Routes.NEW_GROUP_CHAT, + ); + }, + title: Text( + 'New group', + style: TextStyle( + fontSize: 14.5, + ), + ), + ), + Expanded( + child: Container( + alignment: Alignment.bottomCenter, + child: ListTile( + onTap: () async { + Navigator.pop(context); + + if (!kIsWeb) { + final secureStorage = FlutterSecureStorage(); + await secureStorage.deleteAll(); + } + + StreamChat.of(context).client.disconnect( + clearUser: true, + ); + + await Navigator.pushReplacementNamed( + context, + Routes.CHOOSE_USER, + ); + }, + leading: StreamSvgIcon.user( + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(.5), + ), + title: Text( + 'Sign out', + style: TextStyle( + fontSize: 14.5, + ), + ), + trailing: IconButton( + icon: StreamSvgIcon.iconMoon( + size: 24, + ), + color: StreamChatTheme.of(context).colorTheme.grey, + onPressed: () async { + final sp = await StreamingSharedPreferences.instance; + sp.setInt( + 'theme', + Theme.of(context).brightness == Brightness.dark + ? 1 + : -1, + ); + }, + ), + ), + ), + ), + ], + ), + ), + ), + ), + ); + } +} + +class UserMentionPage extends StatelessWidget { + @override + Widget build(BuildContext context) { + final user = StreamChat.of(context).user; + return MessageSearchBloc( + child: MessageSearchListView( + filters: { + 'members': { + r'$in': [user.id], + }, + }, + messageFilters: { + 'mentioned_users.id': { + r'$contains': user.id, + }, + }, + sortOptions: [ + SortOption( + 'created_at', + direction: SortOption.ASC, + ), + ], + paginationParams: PaginationParams(limit: 20), + showResultCount: false, + emptyBuilder: (_) { + return LayoutBuilder( + builder: (context, viewportConstraints) { + return SingleChildScrollView( + physics: AlwaysScrollableScrollPhysics(), + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: viewportConstraints.maxHeight, + ), + child: Center( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(24), + child: StreamSvgIcon.mentions( + size: 96, + color: StreamChatTheme.of(context) + .colorTheme + .greyGainsboro, + ), + ), + Text( + 'No mentions exist yet...', + style: StreamChatTheme.of(context) + .textTheme + .body + .copyWith( + color: + StreamChatTheme.of(context).colorTheme.grey, + ), + ), + ], + ), + ), + ), + ); + }, + ); + }, + onItemTap: (messageResponse) async { + final client = StreamChat.of(context).client; + final message = messageResponse.message; + final channel = client.channel( + messageResponse.channel.type, + id: messageResponse.channel.id, + ); + if (channel.state == null) { + await channel.watch(); + } + Navigator.pushNamed( + context, + Routes.CHANNEL_PAGE, + arguments: ChannelPageArgs( + channel: channel, + initialMessage: message, + ), + ); + }, + ), + ); + } +} + +class ChannelListPage extends StatefulWidget { + @override + _ChannelListPageState createState() => _ChannelListPageState(); +} + +class _ChannelListPageState extends State { + TextEditingController _controller; + + String _channelQuery = ''; + + bool _isSearchActive = false; + + Timer _debounce; + + void _channelQueryListener() { + if (_debounce?.isActive ?? false) _debounce.cancel(); + _debounce = Timer(const Duration(milliseconds: 350), () { + if (mounted) { + setState(() { + _channelQuery = _controller.text; + _isSearchActive = _channelQuery.isNotEmpty; + }); + } + }); + } + + @override + void initState() { + super.initState(); + _controller = TextEditingController()..addListener(_channelQueryListener); + } + + @override + void dispose() { + _controller?.removeListener(_channelQueryListener); + _controller?.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final user = StreamChat.of(context).user; + return WillPopScope( + onWillPop: () async { + if (_isSearchActive) { + _controller.clear(); + setState(() => _isSearchActive = false); + return false; + } + return true; + }, + child: ChannelsBloc( + child: MessageSearchBloc( + child: NestedScrollView( + floatHeaderSlivers: true, + headerSliverBuilder: (_, __) => [ + SliverToBoxAdapter( + child: SearchTextField( + controller: _controller, + showCloseButton: _isSearchActive, + ), + ), + ], + body: AnimatedSwitcher( + duration: const Duration(milliseconds: 350), + child: GestureDetector( + behavior: HitTestBehavior.opaque, + onPanDown: (_) => FocusScope.of(context).unfocus(), + child: _isSearchActive + ? MessageSearchListView( + showErrorTile: true, + messageQuery: _channelQuery, + filters: { + 'members': { + r'$in': [user.id] + }, + }, + sortOptions: [ + SortOption( + 'created_at', + direction: SortOption.ASC, + ), + ], + pullToRefresh: false, + paginationParams: PaginationParams(limit: 20), + emptyBuilder: (_) { + return LayoutBuilder( + builder: (context, viewportConstraints) { + return SingleChildScrollView( + physics: AlwaysScrollableScrollPhysics(), + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: viewportConstraints.maxHeight, + ), + child: Center( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(24), + child: StreamSvgIcon.search( + size: 96, + color: Colors.grey, + ), + ), + Text( + 'No results...', + ), + ], + ), + ), + ), + ); + }, + ); + }, + onItemTap: (messageResponse) async { + FocusScope.of(context).requestFocus(FocusNode()); + final client = StreamChat.of(context).client; + final message = messageResponse.message; + final channel = client.channel( + messageResponse.channel.type, + id: messageResponse.channel.id, + ); + if (channel.state == null) { + await channel.watch(); + } + Navigator.pushNamed( + context, + Routes.CHANNEL_PAGE, + arguments: ChannelPageArgs( + channel: channel, + initialMessage: message, + ), + ); + }, + ) + : ChannelListView( + onStartChatPressed: () { + Navigator.pushNamed(context, Routes.NEW_CHAT); + }, + swipeToAction: true, + filter: { + 'members': { + r'$in': [user.id], + }, + }, + options: { + 'presence': true, + }, + pagination: PaginationParams( + limit: 20, + ), + channelWidget: ChannelPage(), + onViewInfoTap: (channel) { + Navigator.pop(context); + if (channel.memberCount == 2 && channel.isDistinct) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => StreamChannel( + channel: channel, + child: ChatInfoScreen( + user: channel.state.members + .where((m) => + m.userId != + channel.client.state.user.id) + .first + .user, + ), + ), + ), + ); + } else { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => StreamChannel( + channel: channel, + child: GroupInfoScreen(), + ), + ), + ); + } + }, + ), + ), + ), + ), + ), + ), + ); + } +} + +class ChannelPageArgs { + final Channel channel; + final Message initialMessage; + + const ChannelPageArgs({ + this.channel, + this.initialMessage, + }); +} + +class ChannelPage extends StatefulWidget { + final int initialScrollIndex; + final double initialAlignment; + final bool highlightInitialMessage; + + const ChannelPage({ + Key key, + this.initialScrollIndex, + this.initialAlignment, + this.highlightInitialMessage = false, + }) : super(key: key); + + @override + _ChannelPageState createState() => _ChannelPageState(); +} + +class _ChannelPageState extends State { + Message _quotedMessage; + FocusNode _focusNode; + + @override + void initState() { + _focusNode = FocusNode(); + super.initState(); + } + + @override + void dispose() { + _focusNode.dispose(); + super.dispose(); + } + + void _reply(Message message) { + setState(() => _quotedMessage = message); + WidgetsBinding.instance.addPostFrameCallback((timeStamp) { + _focusNode.requestFocus(); + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + appBar: ChannelHeader( + showTypingIndicator: false, + onImageTap: () async { + var channel = StreamChannel.of(context).channel; + + if (channel.memberCount == 2 && channel.isDistinct) { + final currentUser = StreamChat.of(context).user; + final otherUser = channel.state.members.firstWhere( + (element) => element.user.id != currentUser.id, + orElse: () => null, + ); + if (otherUser != null) { + final pop = await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => StreamChannel( + child: ChatInfoScreen( + user: otherUser.user, + ), + channel: channel, + ), + ), + ); + + if (pop == true) { + Navigator.pop(context); + } + } + } else { + await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => StreamChannel( + child: GroupInfoScreen(), + channel: channel, + ), + ), + ); + } + }, + ), + body: Column( + children: [ + Expanded( + child: Stack( + children: [ + MessageListView( + initialScrollIndex: widget.initialScrollIndex, + initialAlignment: widget.initialAlignment, + highlightInitialMessage: widget.highlightInitialMessage, + onMessageSwiped: _reply, + onReplyTap: _reply, + threadBuilder: (_, parentMessage) { + return ThreadPage( + parent: parentMessage, + ); + }, + onShowMessage: (m, c) async { + final client = StreamChat.of(context).client; + final message = m; + final channel = client.channel( + c.type, + id: c.id, + ); + if (channel.state == null) { + await channel.watch(); + } + Navigator.pushReplacementNamed( + context, + Routes.CHANNEL_PAGE, + arguments: ChannelPageArgs( + channel: channel, + initialMessage: message, + ), + ); + }, + ), + Positioned( + bottom: 0, + left: 0, + right: 0, + child: Container( + alignment: Alignment.centerLeft, + color: StreamChatTheme.of(context) + .colorTheme + .whiteSnow + .withOpacity(.9), + child: TypingIndicator( + alignment: Alignment.centerLeft, + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 4, + ), + style: StreamChatTheme.of(context) + .textTheme + .footnote + .copyWith( + color: + StreamChatTheme.of(context).colorTheme.grey), + ), + ), + ), + ], + ), + ), + MessageInput( + focusNode: _focusNode, + quotedMessage: _quotedMessage, + onQuotedMessageCleared: () { + setState(() => _quotedMessage = null); + _focusNode.unfocus(); + }, + ), + ], + ), + ); + } +} + +class ThreadPage extends StatefulWidget { + final Message parent; + final int initialScrollIndex; + final double initialAlignment; + + ThreadPage({ + Key key, + this.parent, + this.initialScrollIndex, + this.initialAlignment, + }) : super(key: key); + + @override + _ThreadPageState createState() => _ThreadPageState(); +} + +class _ThreadPageState extends State { + Message _quotedMessage; + FocusNode _focusNode = FocusNode(); + + @override + void dispose() { + _focusNode.dispose(); + super.dispose(); + } + + void _reply(Message message) { + setState(() => _quotedMessage = message); + WidgetsBinding.instance.addPostFrameCallback((timeStamp) { + _focusNode.requestFocus(); + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + appBar: ThreadHeader( + parent: widget.parent, + ), + body: Column( + children: [ + Expanded( + child: MessageListView( + parentMessage: widget.parent, + initialScrollIndex: widget.initialScrollIndex, + initialAlignment: widget.initialAlignment, + onMessageSwiped: _reply, + onReplyTap: _reply, + ), + ), + if (widget.parent.type != 'deleted') + MessageInput( + parentMessage: widget.parent, + focusNode: _focusNode, + quotedMessage: _quotedMessage, + onQuotedMessageCleared: () { + setState(() => _quotedMessage = null); + _focusNode.unfocus(); + }, + ), + ], + ), + ); + } +} + +class InitData { + final StreamChatClient client; + final StreamingSharedPreferences preferences; + + InitData(this.client, this.preferences); +} + +class HolePainter extends CustomPainter { + HolePainter({ + @required this.color, + @required this.holeSize, + }); + + Color color; + double holeSize; + + @override + void paint(Canvas canvas, Size size) { + double radius = holeSize / 2; + Rect rect = Rect.fromLTWH(0, 0, size.width, size.height); + Rect outerCircleRect = Rect.fromCircle( + center: Offset(size.width / 2, size.height / 2), radius: radius); + Rect innerCircleRect = Rect.fromCircle( + center: Offset(size.width / 2, size.height / 2), radius: radius / 2); + + Path transparentHole = Path.combine( + PathOperation.difference, + Path()..addRect(rect), + Path() + ..addOval(outerCircleRect) + ..close(), + ); + + Path halfTransparentRing = Path.combine( + PathOperation.difference, + Path() + ..addOval(outerCircleRect) + ..close(), + Path() + ..addOval(innerCircleRect) + ..close(), + ); + + canvas.drawPath(transparentHole, Paint()..color = color); + canvas.drawPath( + halfTransparentRing, Paint()..color = color.withOpacity(0.5)); + } + + @override + bool shouldRepaint(CustomPainter oldDelegate) { + return true; + } +} diff --git a/stream_chat_v1/lib/new_chat_screen.dart b/stream_chat_v1/lib/new_chat_screen.dart new file mode 100644 index 0000000000..d4a68887d3 --- /dev/null +++ b/stream_chat_v1/lib/new_chat_screen.dart @@ -0,0 +1,417 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; + +import 'chips_input_text_field.dart'; +import 'main.dart'; +import 'routes/routes.dart'; + +class NewChatScreen extends StatefulWidget { + @override + _NewChatScreenState createState() => _NewChatScreenState(); +} + +class _NewChatScreenState extends State { + final _chipInputTextFieldStateKey = + GlobalKey>(); + + TextEditingController _controller; + + ChipInputTextFieldState get _chipInputTextFieldState => + _chipInputTextFieldStateKey.currentState; + + String _userNameQuery = ''; + + final _selectedUsers = {}; + + final _searchFocusNode = FocusNode(); + final _messageInputFocusNode = FocusNode(); + + bool _isSearchActive = false; + + Channel channel; + + Timer _debounce; + + bool _showUserList = true; + + void _userNameListener() { + if (_debounce?.isActive ?? false) _debounce.cancel(); + _debounce = Timer(const Duration(milliseconds: 350), () { + if (mounted) + setState(() { + _userNameQuery = _controller.text; + _isSearchActive = _userNameQuery.isNotEmpty; + }); + }); + } + + @override + void initState() { + super.initState(); + channel = StreamChat.of(context).client.channel('messaging'); + _controller = TextEditingController()..addListener(_userNameListener); + + _searchFocusNode.addListener(() async { + if (_searchFocusNode.hasFocus && !_showUserList) { + setState(() { + _showUserList = true; + }); + } + }); + + _messageInputFocusNode.addListener(() async { + if (_messageInputFocusNode.hasFocus && _selectedUsers.isNotEmpty) { + final chatState = StreamChat.of(context); + + final res = await chatState.client.queryChannelsOnline( + options: { + 'state': false, + 'watch': false, + }, + filter: { + 'members': [ + ..._selectedUsers.map((e) => e.id), + chatState.user.id, + ], + 'distinct': true, + }, + messageLimit: 0, + paginationParams: PaginationParams( + limit: 1, + ), + ); + + final _channelExisted = res.length == 1; + if (_channelExisted) { + channel = res.first; + await channel.watch(); + } else { + channel = chatState.client.channel( + 'messaging', + extraData: { + 'members': [ + ..._selectedUsers.map((e) => e.id), + chatState.user.id, + ], + }, + ); + } + + setState(() { + _showUserList = false; + }); + } + }); + } + + @override + void dispose() { + _searchFocusNode.dispose(); + _messageInputFocusNode.dispose(); + _controller?.clear(); + _controller?.removeListener(_userNameListener); + _controller?.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + appBar: AppBar( + brightness: Theme.of(context).brightness, + elevation: 0, + backgroundColor: StreamChatTheme.of(context).colorTheme.white, + leading: const StreamBackButton(), + title: Text( + 'New Chat', + style: StreamChatTheme.of(context) + .textTheme + .headlineBold + .copyWith(color: StreamChatTheme.of(context).colorTheme.black), + ), + centerTitle: true, + ), + body: ConnectionStatusBuilder( + statusBuilder: (context, status) { + String statusString = ''; + bool showStatus = true; + + switch (status) { + case ConnectionStatus.connected: + statusString = 'Connected'; + showStatus = false; + break; + case ConnectionStatus.connecting: + statusString = 'Reconnecting...'; + break; + case ConnectionStatus.disconnected: + statusString = 'Disconnected'; + break; + } + return InfoTile( + showMessage: showStatus, + tileAnchor: Alignment.topCenter, + childAnchor: Alignment.topCenter, + message: statusString, + child: StreamChannel( + showLoading: false, + channel: channel, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ChipsInputTextField( + key: _chipInputTextFieldStateKey, + controller: _controller, + focusNode: _searchFocusNode, + chipBuilder: (context, user) { + return GestureDetector( + onTap: () { + _chipInputTextFieldState.removeItem(user); + _searchFocusNode.requestFocus(); + }, + child: Stack( + alignment: AlignmentDirectional.centerStart, + children: [ + Container( + decoration: BoxDecoration( + color: StreamChatTheme.of(context) + .colorTheme + .greyGainsboro, + borderRadius: BorderRadius.circular(12), + ), + padding: const EdgeInsets.only(left: 24), + child: Padding( + padding: const EdgeInsets.fromLTRB(8, 4, 12, 4), + child: Text( + user.name, + maxLines: 1, + style: TextStyle( + color: StreamChatTheme.of(context) + .colorTheme + .black, + ), + ), + ), + ), + Container( + foregroundDecoration: BoxDecoration( + color: StreamChatTheme.of(context) + .colorTheme + .overlay, + shape: BoxShape.circle, + ), + child: UserAvatar( + showOnlineStatus: false, + user: user, + constraints: BoxConstraints.tightFor( + height: 24, + width: 24, + ), + ), + ), + StreamSvgIcon.close(), + ], + ), + ); + }, + onChipAdded: (user) { + setState(() => _selectedUsers.add(user)); + }, + onChipRemoved: (user) { + setState(() => _selectedUsers.remove(user)); + }, + ), + if (!_isSearchActive && !_selectedUsers.isNotEmpty) + Container( + child: InkWell( + onTap: () { + Navigator.pushNamed( + context, + Routes.NEW_GROUP_CHAT, + ); + }, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Row( + children: [ + StreamNeumorphicButton( + child: Center( + child: StreamSvgIcon.contacts( + color: StreamChatTheme.of(context) + .colorTheme + .accentBlue, + size: 24, + ), + ), + ), + SizedBox(width: 8), + Text( + 'Create a Group', + style: StreamChatTheme.of(context) + .textTheme + .bodyBold, + ), + ], + ), + ), + ), + ), + if (_showUserList) + Container( + width: double.maxFinite, + decoration: BoxDecoration( + gradient: + StreamChatTheme.of(context).colorTheme.bgGradient, + ), + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 8, + horizontal: 8, + ), + child: Text( + _isSearchActive + ? "Matches for \"$_userNameQuery\"" + : 'On the platform', + style: StreamChatTheme.of(context) + .textTheme + .footnote + .copyWith( + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(.5))), + ), + ), + Expanded( + child: _showUserList + ? GestureDetector( + behavior: HitTestBehavior.opaque, + onPanDown: (_) => FocusScope.of(context).unfocus(), + child: UsersBloc( + child: UserListView( + selectedUsers: _selectedUsers, + groupAlphabetically: + _isSearchActive ? false : true, + onUserTap: (user, _) { + _controller.clear(); + if (!_selectedUsers.contains(user)) { + _chipInputTextFieldState + ..addItem(user) + ..pauseItemAddition(); + } else { + _chipInputTextFieldState.removeItem(user); + } + }, + pagination: PaginationParams( + limit: 25, + ), + filter: { + if (_userNameQuery.isNotEmpty) + 'name': { + r'$autocomplete': _userNameQuery, + }, + 'id': { + r'$ne': StreamChat.of(context).user.id, + }, + }, + sort: [ + SortOption( + 'name', + direction: 1, + ), + ], + emptyBuilder: (_) { + return LayoutBuilder( + builder: (context, viewportConstraints) { + return SingleChildScrollView( + physics: + AlwaysScrollableScrollPhysics(), + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: + viewportConstraints.maxHeight, + ), + child: Center( + child: Column( + children: [ + Padding( + padding: + const EdgeInsets.all(24), + child: StreamSvgIcon.search( + size: 96, + color: Colors.grey, + ), + ), + Text( + 'No user matches these keywords...', + style: StreamChatTheme.of( + context) + .textTheme + .footnote + .copyWith( + color: StreamChatTheme + .of(context) + .colorTheme + .black + .withOpacity(.5)), + ), + ], + ), + ), + ), + ); + }, + ); + }, + ), + ), + ) + : FutureBuilder( + future: channel.initialized, + builder: (context, snapshot) { + if (snapshot.data == true) { + return MessageListView(); + } + + return Center( + child: Text( + 'No chats here yet...', + style: TextStyle( + fontSize: 12, + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(.5), + ), + ), + ); + }, + ), + ), + MessageInput( + focusNode: _messageInputFocusNode, + preMessageSending: (message) async { + await channel.watch(); + return message; + }, + onMessageSent: (m) { + Navigator.pushNamedAndRemoveUntil( + context, + Routes.CHANNEL_PAGE, + ModalRoute.withName(Routes.HOME), + arguments: ChannelPageArgs(channel: channel), + ); + }, + ), + ], + ), + ), + ); + }, + ), + ); + } +} diff --git a/stream_chat_v1/lib/new_group_chat_screen.dart b/stream_chat_v1/lib/new_group_chat_screen.dart new file mode 100644 index 0000000000..209d37292b --- /dev/null +++ b/stream_chat_v1/lib/new_group_chat_screen.dart @@ -0,0 +1,339 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; + +import 'routes/routes.dart'; +import 'search_text_field.dart'; + +class NewGroupChatScreen extends StatefulWidget { + @override + _NewGroupChatScreenState createState() => _NewGroupChatScreenState(); +} + +class _NewGroupChatScreenState extends State { + TextEditingController _controller; + + String _userNameQuery = ''; + + final _selectedUsers = {}; + + bool _isSearchActive = false; + + Timer _debounce; + + void _userNameListener() { + if (_debounce?.isActive ?? false) _debounce.cancel(); + _debounce = Timer(const Duration(milliseconds: 350), () { + if (mounted) { + setState(() { + _userNameQuery = _controller.text; + _isSearchActive = _userNameQuery.isNotEmpty; + }); + } + }); + } + + @override + void initState() { + super.initState(); + _controller = TextEditingController()..addListener(_userNameListener); + } + + @override + void dispose() { + _controller?.clear(); + _controller?.removeListener(_userNameListener); + _controller?.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + appBar: AppBar( + elevation: 1, + backgroundColor: StreamChatTheme.of(context).colorTheme.white, + leading: const StreamBackButton(), + title: Text( + 'Add Group Members', + style: TextStyle( + color: StreamChatTheme.of(context).colorTheme.black, + fontSize: 16, + ), + ), + centerTitle: true, + actions: [ + if (_selectedUsers.isNotEmpty) + IconButton( + icon: StreamSvgIcon.arrowRight( + color: StreamChatTheme.of(context).colorTheme.accentBlue, + ), + onPressed: () async { + final updatedList = await Navigator.pushNamed( + context, + Routes.NEW_GROUP_CHAT_DETAILS, + arguments: _selectedUsers.toList(growable: false), + ); + if (updatedList != null) { + setState(() { + _selectedUsers + ..clear() + ..addAll(updatedList); + }); + } + }, + ) + ], + ), + body: ConnectionStatusBuilder( + statusBuilder: (context, status) { + String statusString = ''; + bool showStatus = true; + + switch (status) { + case ConnectionStatus.connected: + statusString = 'Connected'; + showStatus = false; + break; + case ConnectionStatus.connecting: + statusString = 'Reconnecting...'; + break; + case ConnectionStatus.disconnected: + statusString = 'Disconnected'; + break; + } + return InfoTile( + showMessage: showStatus, + tileAnchor: Alignment.topCenter, + childAnchor: Alignment.topCenter, + message: statusString, + child: NestedScrollView( + floatHeaderSlivers: true, + headerSliverBuilder: + (BuildContext context, bool innerBoxIsScrolled) { + return [ + SliverToBoxAdapter( + child: SearchTextField( + controller: _controller, + ), + ), + if (_selectedUsers.isNotEmpty) + SliverToBoxAdapter( + child: Container( + height: 104, + child: ListView.separated( + scrollDirection: Axis.horizontal, + itemCount: _selectedUsers.length, + padding: const EdgeInsets.all(8), + separatorBuilder: (_, __) => SizedBox(width: 16), + itemBuilder: (_, index) { + final user = _selectedUsers.elementAt(index); + return Column( + children: [ + Stack( + children: [ + UserAvatar( + onlineIndicatorAlignment: + Alignment(0.9, 0.9), + user: user, + showOnlineStatus: true, + borderRadius: BorderRadius.circular(32), + constraints: BoxConstraints.tightFor( + height: 64, + width: 64, + ), + ), + Positioned( + top: -4, + right: -4, + child: GestureDetector( + onTap: () { + if (_selectedUsers.contains(user)) { + setState(() => + _selectedUsers.remove(user)); + } + }, + child: Container( + decoration: BoxDecoration( + color: StreamChatTheme.of(context) + .colorTheme + .white, + shape: BoxShape.circle, + border: Border.all( + color: StreamChatTheme.of(context) + .colorTheme + .whiteSnow, + ), + ), + child: StreamSvgIcon.close( + color: StreamChatTheme.of(context) + .colorTheme + .black, + size: 24, + ), + ), + ), + ) + ], + ), + SizedBox(height: 4), + Text( + user.name.split(' ')[0], + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 12, + ), + ), + ], + ); + }, + ), + ), + ), + SliverPersistentHeader( + pinned: true, + delegate: _HeaderDelegate( + height: 30, + child: Container( + width: double.maxFinite, + decoration: BoxDecoration( + gradient: + StreamChatTheme.of(context).colorTheme.bgGradient, + ), + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 8, + horizontal: 8, + ), + child: Text( + _isSearchActive + ? 'Matches for \"$_userNameQuery\"' + : 'On the platform', + style: TextStyle( + color: + StreamChatTheme.of(context).colorTheme.grey, + ), + ), + ), + ), + ), + ), + ]; + }, + body: GestureDetector( + behavior: HitTestBehavior.opaque, + onPanDown: (_) => FocusScope.of(context).unfocus(), + child: UsersBloc( + child: UserListView( + selectedUsers: _selectedUsers, + pullToRefresh: false, + groupAlphabetically: _isSearchActive ? false : true, + onUserTap: (user, _) { + if (!_selectedUsers.contains(user)) { + setState(() { + _selectedUsers.add(user); + }); + } else { + setState(() { + _selectedUsers.remove(user); + }); + } + }, + pagination: PaginationParams( + limit: 25, + ), + filter: { + if (_userNameQuery.isNotEmpty) + 'name': { + r'$autocomplete': _userNameQuery, + }, + 'id': { + r'$ne': StreamChat.of(context).user.id, + } + }, + sort: [ + SortOption( + 'name', + direction: 1, + ), + ], + emptyBuilder: (_) { + return LayoutBuilder( + builder: (context, viewportConstraints) { + return SingleChildScrollView( + physics: AlwaysScrollableScrollPhysics(), + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: viewportConstraints.maxHeight, + ), + child: Center( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(24), + child: StreamSvgIcon.search( + size: 96, + color: StreamChatTheme.of(context) + .colorTheme + .grey, + ), + ), + Text( + 'No user matches these keywords...', + style: StreamChatTheme.of(context) + .textTheme + .footnote + .copyWith( + color: StreamChatTheme.of(context) + .colorTheme + .grey, + ), + ), + ], + ), + ), + ), + ); + }, + ); + }, + ), + ), + ), + ), + ); + }, + ), + ); + } +} + +class _HeaderDelegate extends SliverPersistentHeaderDelegate { + final Widget child; + final double height; + + const _HeaderDelegate({ + @required this.child, + @required this.height, + }); + + @override + Widget build( + BuildContext context, double shrinkOffset, bool overlapsContent) { + return Container( + color: StreamChatTheme.of(context).colorTheme.white, + child: child, + ); + } + + @override + double get maxExtent => height; + + @override + double get minExtent => height; + + @override + bool shouldRebuild(_HeaderDelegate oldDelegate) => true; +} diff --git a/stream_chat_v1/lib/notifications_service.dart b/stream_chat_v1/lib/notifications_service.dart new file mode 100644 index 0000000000..c72ac19f7e --- /dev/null +++ b/stream_chat_v1/lib/notifications_service.dart @@ -0,0 +1,38 @@ +import 'package:flutter_local_notifications/flutter_local_notifications.dart' + hide Message; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; + +void showLocalNotification(Event event, String currentUserId) async { + if (![ + EventType.messageNew, + EventType.notificationMessageNew, + ].contains(event.type) || + event.user.id == currentUserId) { + return; + } + if (event.message == null) return; + final flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); + final initializationSettingsAndroid = + AndroidInitializationSettings('launch_background'); + final initializationSettingsIOS = IOSInitializationSettings(); + final initializationSettings = InitializationSettings( + android: initializationSettingsAndroid, + iOS: initializationSettingsIOS, + ); + await flutterLocalNotificationsPlugin.initialize(initializationSettings); + await flutterLocalNotificationsPlugin.show( + event.message.id.hashCode, + event.message.user.name, + event.message.text, + NotificationDetails( + android: AndroidNotificationDetails( + 'message channel', + 'Message channel', + 'Channel used for showing messages', + priority: Priority.high, + importance: Importance.high, + ), + iOS: IOSNotificationDetails(), + ), + ); +} diff --git a/stream_chat_v1/lib/routes/app_routes.dart b/stream_chat_v1/lib/routes/app_routes.dart new file mode 100644 index 0000000000..c641b048ca --- /dev/null +++ b/stream_chat_v1/lib/routes/app_routes.dart @@ -0,0 +1,93 @@ +import 'routes.dart'; +import 'package:flutter/material.dart'; +import '../choose_user_page.dart'; +import '../advanced_options_page.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; +import '../main.dart'; +import '../group_chat_details_screen.dart'; +import '../new_group_chat_screen.dart'; +import '../new_chat_screen.dart'; +import '../chat_info_screen.dart'; +import '../group_info_screen.dart'; + +class AppRoutes { + /// Add entry for new route here + static Route generateRoute(RouteSettings settings) { + final args = settings.arguments; + switch (settings.name) { + case Routes.APP: + return MaterialPageRoute( + settings: const RouteSettings(name: Routes.APP), + builder: (_) { + return MyApp(); + }); + case Routes.HOME: + return MaterialPageRoute( + settings: const RouteSettings(name: Routes.HOME), + builder: (_) { + return HomePage(); + }); + case Routes.CHOOSE_USER: + return MaterialPageRoute( + settings: const RouteSettings(name: Routes.CHOOSE_USER), + builder: (_) { + return ChooseUserPage(); + }); + case Routes.ADVANCED_OPTIONS: + return MaterialPageRoute( + settings: const RouteSettings(name: Routes.ADVANCED_OPTIONS), + builder: (_) => AdvancedOptionsPage(), + ); + case Routes.CHANNEL_PAGE: + return MaterialPageRoute( + settings: const RouteSettings(name: Routes.CHANNEL_PAGE), + builder: (_) { + final arg = args as ChannelPageArgs; + return StreamChannel( + channel: arg.channel, + initialMessageId: arg.initialMessage?.id, + child: ChannelPage( + highlightInitialMessage: arg.initialMessage != null, + ), + ); + }); + case Routes.NEW_CHAT: + return MaterialPageRoute( + settings: const RouteSettings(name: Routes.NEW_CHAT), + builder: (_) { + return NewChatScreen(); + }); + case Routes.NEW_GROUP_CHAT: + return MaterialPageRoute( + settings: const RouteSettings(name: Routes.NEW_GROUP_CHAT), + builder: (_) { + return NewGroupChatScreen(); + }); + case Routes.NEW_GROUP_CHAT_DETAILS: + return MaterialPageRoute( + settings: const RouteSettings(name: Routes.NEW_GROUP_CHAT_DETAILS), + builder: (_) { + return GroupChatDetailsScreen( + selectedUsers: args, + ); + }); + case Routes.CHAT_INFO_SCREEN: + return MaterialPageRoute( + settings: const RouteSettings(name: Routes.CHAT_INFO_SCREEN), + builder: (_) { + return ChatInfoScreen( + user: args, + ); + }); + case Routes.GROUP_INFO_SCREEN: + return MaterialPageRoute( + settings: const RouteSettings(name: Routes.GROUP_INFO_SCREEN), + builder: (_) { + return GroupInfoScreen(); + }); + // Default case, should not reach here. + default: + return null; + } + } +} diff --git a/stream_chat_v1/lib/routes/routes.dart b/stream_chat_v1/lib/routes/routes.dart new file mode 100644 index 0000000000..2280ca306b --- /dev/null +++ b/stream_chat_v1/lib/routes/routes.dart @@ -0,0 +1,13 @@ +/// Define all the route names here +class Routes { + static const String APP = '/app'; + static const String HOME = '/home'; + static const String CHOOSE_USER = '/choose_user'; + static const String ADVANCED_OPTIONS = '/advance_options'; + static const String CHANNEL_PAGE = '/channel_page'; + static const String NEW_CHAT = '/new_chat'; + static const String NEW_GROUP_CHAT = '/new_group_chat'; + static const String NEW_GROUP_CHAT_DETAILS = '/new_group_chat_details'; + static const String CHAT_INFO_SCREEN = '/chat_info_screen'; + static const String GROUP_INFO_SCREEN = '/group_info_screen'; +} diff --git a/stream_chat_v1/lib/search_text_field.dart b/stream_chat_v1/lib/search_text_field.dart new file mode 100644 index 0000000000..9628ddba94 --- /dev/null +++ b/stream_chat_v1/lib/search_text_field.dart @@ -0,0 +1,94 @@ +import 'package:flutter/material.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; + +class SearchTextField extends StatelessWidget { + final TextEditingController controller; + final ValueChanged onChanged; + final String hintText; + final VoidCallback onTap; + final bool showCloseButton; + + const SearchTextField({ + Key key, + @required this.controller, + this.onChanged, + this.onTap, + this.hintText = 'Search', + this.showCloseButton = true, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + height: 36, + decoration: BoxDecoration( + color: StreamChatTheme.of(context).colorTheme.white, + border: Border.all( + color: StreamChatTheme.of(context).colorTheme.greyWhisper, + ), + borderRadius: BorderRadius.circular(24), + ), + margin: const EdgeInsets.symmetric( + vertical: 8, + horizontal: 8, + ), + child: Row( + children: [ + Expanded( + child: TextField( + onTap: onTap, + controller: controller, + onChanged: onChanged, + decoration: InputDecoration( + prefixText: ' ', + prefixIconConstraints: BoxConstraints.tight(Size(40, 24)), + prefixIcon: Padding( + padding: const EdgeInsets.only( + left: 8, + right: 8, + ), + child: StreamSvgIcon.search( + color: StreamChatTheme.of(context).colorTheme.black, + size: 24, + ), + ), + hintText: hintText, + hintStyle: StreamChatTheme.of(context).textTheme.body.copyWith( + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(.5)), + contentPadding: const EdgeInsets.all(0), + border: OutlineInputBorder( + borderSide: BorderSide.none, + borderRadius: BorderRadius.circular(24), + ), + ), + ), + ), + if (showCloseButton) + Material( + color: Colors.transparent, + child: IconButton( + padding: const EdgeInsets.all(0), + icon: StreamSvgIcon.closeSmall( + color: Colors.grey, + ), + splashRadius: 24, + onPressed: () { + if (controller.text.isNotEmpty) { + Future.microtask( + () => [ + controller.clear(), + if (onChanged != null) onChanged(''), + ], + ); + } + }, + ), + ), + ], + ), + ); + } +} diff --git a/stream_chat_v1/lib/stream_version.dart b/stream_chat_v1/lib/stream_version.dart new file mode 100644 index 0000000000..b3f926bea9 --- /dev/null +++ b/stream_chat_v1/lib/stream_version.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:yaml/yaml.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; + +class StreamVersion extends StatelessWidget { + const StreamVersion({ + Key key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(vertical: 16), + alignment: Alignment.bottomCenter, + child: FutureBuilder( + future: rootBundle.loadString('pubspec.lock'), + builder: (context, snapshot) { + if (!snapshot.hasData) { + return SizedBox(); + } + + final pubspec = snapshot.data; + final yaml = loadYaml(pubspec); + final streamChatDep = + yaml['packages']['stream_chat_flutter']['version']; + + return Text( + 'Stream SDK v ${streamChatDep}', + style: TextStyle( + fontSize: 14, + color: StreamChatTheme.of(context).colorTheme.greyGainsboro, + ), + ); + }, + ), + ); + } +} diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml new file mode 100644 index 0000000000..97b84d97c4 --- /dev/null +++ b/stream_chat_v1/pubspec.yaml @@ -0,0 +1,45 @@ +name: example +description: A new Flutter project. +publish_to: 'none' +version: 1.3.3 + +environment: + sdk: ">=2.2.2 <3.0.0" + +dependencies: + flutter_app_badger: ^1.1.2 + flutter: + sdk: flutter + stream_chat_flutter: + git: + url: https://github.com/GetStream/stream-chat-flutter.git + ref: develop + path: packages/stream_chat_flutter + stream_chat_persistence: + git: + url: https://github.com/GetStream/stream-chat-flutter.git + ref: develop + path: packages/stream_chat_persistence + flutter_local_notifications: ^2.0.2 + flutter_svg: ^0.19.3 + flutter_secure_storage: ^3.3.5 + yaml: ^2.2.1 + uuid: ^2.2.2 + streaming_shared_preferences: ^1.0.2 + lottie: ^0.7.0+1 + +dev_dependencies: + flutter_launcher_icons: ^0.8.1 + test: any + +flutter: + assets: + - assets/ + - pubspec.lock + uses-material-design: true + +flutter_icons: + android: true + ios: true + image_path_android: "assets/android_icon.png" + image_path_ios: "assets/ios_icon.png" diff --git a/stream_chat_v1/web/favicon.png b/stream_chat_v1/web/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..8aaa46ac1ae21512746f852a42ba87e4165dfdd1 GIT binary patch literal 917 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|I14-?iy0X7 zltGxWVyS%@P(fs7NJL45ua8x7ey(0(N`6wRUPW#JP&EUCO@$SZnVVXYs8ErclUHn2 zVXFjIVFhG^g!Ppaz)DK8ZIvQ?0~DO|i&7O#^-S~(l1AfjnEK zjFOT9D}DX)@^Za$W4-*MbbUihOG|wNBYh(yU7!lx;>x^|#0uTKVr7USFmqf|i<65o z3raHc^AtelCMM;Vme?vOfh>Xph&xL%(-1c06+^uR^q@XSM&D4+Kp$>4P^%3{)XKjo zGZknv$b36P8?Z_gF{nK@`XI}Z90TzwSQO}0J1!f2c(B=V`5aP@1P1a|PZ!4!3&Gl8 zTYqUsf!gYFyJnXpu0!n&N*SYAX-%d(5gVjrHJWqXQshj@!Zm{!01WsQrH~9=kTxW#6SvuapgMqt>$=j#%eyGrQzr zP{L-3gsMA^$I1&gsBAEL+vxi1*Igl=8#8`5?A-T5=z-sk46WA1IUT)AIZHx1rdUrf zVJrJn<74DDw`j)Ki#gt}mIT-Q`XRa2-jQXQoI%w`nb|XblvzK${ZzlV)m-XcwC(od z71_OEC5Bt9GEXosOXaPTYOia#R4ID2TiU~`zVMl08TV_C%DnU4^+HE>9(CE4D6?Fz oujB08i7adh9xk7*FX66dWH6F5TM;?E2b5PlUHx3vIVCg!0Dx9vYXATM literal 0 HcmV?d00001 diff --git a/stream_chat_v1/web/icons/Icon-192.png b/stream_chat_v1/web/icons/Icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..b749bfef07473333cf1dd31e9eed89862a5d52aa GIT binary patch literal 5292 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 literal 0 HcmV?d00001 diff --git a/stream_chat_v1/web/icons/Icon-512.png b/stream_chat_v1/web/icons/Icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..88cfd48dff1169879ba46840804b412fe02fefd6 GIT binary patch literal 8252 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 literal 0 HcmV?d00001 diff --git a/stream_chat_v1/web/index.html b/stream_chat_v1/web/index.html new file mode 100644 index 0000000000..c9fb727522 --- /dev/null +++ b/stream_chat_v1/web/index.html @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + example + + + + + + + + + diff --git a/stream_chat_v1/web/manifest.json b/stream_chat_v1/web/manifest.json new file mode 100644 index 0000000000..97eb9afb4a --- /dev/null +++ b/stream_chat_v1/web/manifest.json @@ -0,0 +1,23 @@ +{ + "name": "Stream Chat v1", + "short_name": "SCv1", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "Sample app for the Stream Chat Flutter SDK", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + } + ] +} diff --git a/stream_chat_v1/web/sql-wasm.js b/stream_chat_v1/web/sql-wasm.js new file mode 100644 index 0000000000..9ef1837d7b --- /dev/null +++ b/stream_chat_v1/web/sql-wasm.js @@ -0,0 +1,207 @@ +// We are modularizing this manually because the current modularize setting in Emscripten has some issues: +// https://github.com/kripken/emscripten/issues/5820 +// In addition, When you use emcc's modularization, it still expects to export a global object called `Module`, +// which is able to be used/called before the WASM is loaded. +// The modularization below exports a promise that loads and resolves to the actual sql.js module. +// That way, this module can't be used before the WASM is finished loading. + +// We are going to define a function that a user will call to start loading initializing our Sql.js library +// However, that function might be called multiple times, and on subsequent calls, we don't actually want it to instantiate a new instance of the Module +// Instead, we want to return the previously loaded module + +// TODO: Make this not declare a global if used in the browser +var initSqlJsPromise = undefined; + +var initSqlJs = function (moduleConfig) { + +if (initSqlJsPromise){ +return initSqlJsPromise; +} +// If we're here, we've never called this function before +initSqlJsPromise = new Promise((resolveModule, reject) => { + +// We are modularizing this manually because the current modularize setting in Emscripten has some issues: +// https://github.com/kripken/emscripten/issues/5820 + +// The way to affect the loading of emcc compiled modules is to create a variable called `Module` and add +// properties to it, like `preRun`, `postRun`, etc +// We are using that to get notified when the WASM has finished loading. +// Only then will we return our promise + +// If they passed in a moduleConfig object, use that +// Otherwise, initialize Module to the empty object +var Module = typeof moduleConfig !== 'undefined' ? moduleConfig : {}; + +// EMCC only allows for a single onAbort function (not an array of functions) +// So if the user defined their own onAbort function, we remember it and call it +var originalOnAbortFunction = Module['onAbort']; +Module['onAbort'] = function (errorThatCausedAbort) { +reject(new Error(errorThatCausedAbort)); +if (originalOnAbortFunction){ +originalOnAbortFunction(errorThatCausedAbort); +} +}; + +Module['postRun'] = Module['postRun'] || []; +Module['postRun'].push(function () { +// When Emscripted calls postRun, this promise resolves with the built Module +resolveModule(Module); +}); + +// There is a section of code in the emcc-generated code below that looks like this: +// (Note that this is lowercase `module`) +// if (typeof module !== 'undefined') { +// module['exports'] = Module; +// } +// When that runs, it's going to overwrite our own modularization export efforts in shell-post.js! +// The only way to tell emcc not to emit it is to pass the MODULARIZE=1 or MODULARIZE_INSTANCE=1 flags, +// but that carries with it additional unnecessary baggage/bugs we don't want either. +// So, we have three options: +// 1) We undefine `module` +// 2) We remember what `module['exports']` was at the beginning of this function and we restore it later +// 3) We write a script to remove those lines of code as part of the Make process. +// +// Since those are the only lines of code that care about module, we will undefine it. It's the most straightforward +// of the options, and has the side effect of reducing emcc's efforts to modify the module if its output were to change in the future. +// That's a nice side effect since we're handling the modularization efforts ourselves +module = undefined; + +// The emcc-generated code and shell-post.js code goes below, +// meaning that all of it runs inside of this promise. If anything throws an exception, our promise will abort +var aa;var f;f||(f=typeof Module !== 'undefined' ? Module : {}); +var va=function(){var a;var b=h(4);var c={};var d=function(){function a(a,b){this.fb=a;this.db=b;this.nb=1;this.Eb=[]}a.prototype.bind=function(a){if(!this.fb)throw"Statement closed";this.reset();return Array.isArray(a)?this.lc(a):this.mc(a)};a.prototype.step=function(){var a;if(!this.fb)throw"Statement closed";this.nb=1;switch(a=Tb(this.fb)){case c.hc:return!0;case c.DONE:return!1;default:return this.db.handleError(a)}};a.prototype.sc=function(a){null==a&&(a=this.nb++);return Ub(this.fb,a)};a.prototype.tc= +function(a){null==a&&(a=this.nb++);return Vb(this.fb,a)};a.prototype.getBlob=function(a){var b;null==a&&(a=this.nb++);var c=Wb(this.fb,a);var d=Xb(this.fb,a);var e=new Uint8Array(c);for(a=b=0;0<=c?bc;a=0<=c?++b:--b)e[a]=l[d+a];return e};a.prototype.get=function(a){var b,d;null!=a&&this.bind(a)&&this.step();var e=[];a=b=0;for(d=ib(this.fb);0<=d?bd;a=0<=d?++b:--b)switch(Yb(this.fb,a)){case c.fc:case c.FLOAT:e.push(this.sc(a));break;case c.ic:e.push(this.tc(a));break;case c.Zb:e.push(this.getBlob(a)); +break;default:e.push(null)}return e};a.prototype.getColumnNames=function(){var a,b;var c=[];var d=a=0;for(b=ib(this.fb);0<=b?ab;d=0<=b?++a:--a)c.push(Zb(this.fb,d));return c};a.prototype.getAsObject=function(a){var b,c;var d=this.get(a);var e=this.getColumnNames();var g={};a=b=0;for(c=e.length;b>>0);if(null!=a){var c=this.filename,d=c?n("/",c):"/";c=ia(!0,!0);d=ja(d,(void 0!==c?c:438)&4095|32768,0);if(a){if("string"===typeof a){for(var e=Array(a.length),k=0,m=a.length;kc;e=0<=c?++g:--g){var m=q(d+4*e,"i32");var z=jc(m);e=function(){switch(!1){case 1!==z:return kc; +case 2!==z:return lc;case 3!==z:return mc;case 4!==z:return function(a){var b,c;var d=nc(a);var e=oc(a);a=new Uint8Array(d);for(b=c=0;0<=d?cd;b=0<=d?++c:--c)a[b]=l[e+b];return a};default:return function(){return null}}}();e=e(m);k.push(e)}if(c=b.apply(null,k))switch(typeof c){case "number":return pc(a,c);case "string":return qc(a,c,-1,-1)}else return rc(a)});this.handleError(sc(this.db,a,b.length,c.jc,0,d,0,0,0));return this};return a}();var g=f.cwrap("sqlite3_open","number",["string","number"]); +var k=f.cwrap("sqlite3_close_v2","number",["number"]);var m=f.cwrap("sqlite3_exec","number",["number","string","number","number","number"]);f.cwrap("sqlite3_free","",["number"]);var y=f.cwrap("sqlite3_changes","number",["number"]);var z=f.cwrap("sqlite3_prepare_v2","number",["number","string","number","number","number"]);var fa=f.cwrap("sqlite3_prepare_v2","number",["number","number","number","number","number"]);var ca=f.cwrap("sqlite3_bind_text","number",["number","number","number","number","number"]); +var Ia=f.cwrap("sqlite3_bind_blob","number",["number","number","number","number","number"]);var ac=f.cwrap("sqlite3_bind_double","number",["number","number","number"]);var $b=f.cwrap("sqlite3_bind_int","number",["number","number","number"]);var bc=f.cwrap("sqlite3_bind_parameter_index","number",["number","string"]);var Tb=f.cwrap("sqlite3_step","number",["number"]);var hc=f.cwrap("sqlite3_errmsg","string",["number"]);var ib=f.cwrap("sqlite3_data_count","number",["number"]);var Ub=f.cwrap("sqlite3_column_double", +"number",["number","number"]);var Vb=f.cwrap("sqlite3_column_text","string",["number","number"]);var Xb=f.cwrap("sqlite3_column_blob","number",["number","number"]);var Wb=f.cwrap("sqlite3_column_bytes","number",["number","number"]);var Yb=f.cwrap("sqlite3_column_type","number",["number","number"]);var Zb=f.cwrap("sqlite3_column_name","string",["number","number"]);var dc=f.cwrap("sqlite3_reset","number",["number"]);var cc=f.cwrap("sqlite3_clear_bindings","number",["number"]);var ec=f.cwrap("sqlite3_finalize", +"number",["number"]);var sc=f.cwrap("sqlite3_create_function_v2","number","number string number number number number number number number".split(" "));var jc=f.cwrap("sqlite3_value_type","number",["number"]);var nc=f.cwrap("sqlite3_value_bytes","number",["number"]);var mc=f.cwrap("sqlite3_value_text","string",["number"]);var kc=f.cwrap("sqlite3_value_int","number",["number"]);var oc=f.cwrap("sqlite3_value_blob","number",["number"]);var lc=f.cwrap("sqlite3_value_double","number",["number"]);var pc= +f.cwrap("sqlite3_result_double","",["number","number"]);var rc=f.cwrap("sqlite3_result_null","",["number"]);var qc=f.cwrap("sqlite3_result_text","",["number","string","number","number"]);var fc=f.cwrap("RegisterExtensionFunctions","number",["number"]);this.SQL={Database:e};for(a in this.SQL)f[a]=this.SQL[a];var da=0;c.xb=0;c.we=1;c.Pe=2;c.Ze=3;c.Cc=4;c.Ec=5;c.Se=6;c.NOMEM=7;c.bf=8;c.Qe=9;c.Re=10;c.Hc=11;c.NOTFOUND=12;c.Oe=13;c.Fc=14;c.$e=15;c.EMPTY=16;c.cf=17;c.df=18;c.Gc=19;c.Te=20;c.Ue=21;c.Ve= +22;c.Dc=23;c.Ne=24;c.af=25;c.We=26;c.Xe=27;c.ef=28;c.hc=100;c.DONE=101;c.fc=1;c.FLOAT=2;c.ic=3;c.Zb=4;c.Ye=5;c.jc=1}.bind(this);f.preRun=f.preRun||[];f.preRun.push(va);var wa={},u;for(u in f)f.hasOwnProperty(u)&&(wa[u]=f[u]);f.arguments=[];f.thisProgram="./this.program";f.quit=function(a,b){throw b;};f.preRun=[];f.postRun=[];var v=!1,w=!1,x=!1,xa=!1;v="object"===typeof window;w="function"===typeof importScripts;x="object"===typeof process&&"function"===typeof require&&!v&&!w;xa=!v&&!x&&!w;var A=""; +if(x){A=__dirname+"/";var ya,za;f.read=function(a,b){ya||(ya=require("fs"));za||(za=require("path"));a=za.normalize(a);a=ya.readFileSync(a);return b?a:a.toString()};f.readBinary=function(a){a=f.read(a,!0);a.buffer||(a=new Uint8Array(a));assert(a.buffer);return a};1>2];a=b+a+15&-16;if(a<=Da())D[Ca>>2]=a;else if(!Ea(a))return 0;return b} +var Fa={"f64-rem":function(a,b){return a%b},"debugger":function(){debugger}},Ga=1,E=Array(64);function ua(a){for(var b=0;64>b;b++)if(!E[b])return E[b]=a,Ga+b;throw"Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.";}"object"!==typeof WebAssembly&&C("no native wasm support detected"); +function q(a,b){b=b||"i8";"*"===b.charAt(b.length-1)&&(b="i32");switch(b){case "i1":return l[a>>0];case "i8":return l[a>>0];case "i16":return Ha[a>>1];case "i32":return D[a>>2];case "i64":return D[a>>2];case "float":return Ja[a>>2];case "double":return Ka[a>>3];default:B("invalid type for getValue: "+b)}return null}var La,Ma=!1;function assert(a,b){a||B("Assertion failed: "+b)}function Na(a){var b=f["_"+a];assert(b,"Cannot call unknown function "+a+", make sure it is exported");return b} +function Oa(a,b,c,d){var e={string:function(a){var b=0;if(null!==a&&void 0!==a&&0!==a){var c=(a.length<<2)+1;b=h(c);r(a,F,b,c)}return b},array:function(a){var b=h(a.length);l.set(a,b);return b}},g=Na(a),k=[];a=0;if(d)for(var m=0;m>0]=0;break;case "i8":l[a>>0]=0;break;case "i16":Ha[a>>1]=0;break;case "i32":D[a>>2]=0;break;case "i64":aa=[0,1<=+Pa(0)?~~+Qa(0)>>>0:0];D[a>>2]=aa[0];D[a+4>>2]=aa[1];break;case "float":Ja[a>>2]=0;break;case "double":Ka[a>>3]=0;break;default:B("invalid type for setValue: "+b)}}var Ra=0,Sa=3; +function ea(a){var b=Ra;if("number"===typeof a){var c=!0;var d=a}else c=!1,d=a.length;b=b==Sa?e:[Ta,h,Ba][b](Math.max(d,1));if(c){var e=b;assert(0==(b&3));for(a=b+(d&-4);e>2]=0;for(a=b+d;e>0]=0;return b}a.subarray||a.slice?F.set(a,b):F.set(new Uint8Array(a),b);return b}var Ua="undefined"!==typeof TextDecoder?new TextDecoder("utf8"):void 0; +function t(a,b,c){var d=b+c;for(c=b;a[c]&&!(c>=d);)++c;if(16e?d+=String.fromCharCode(e):(e-=65536,d+=String.fromCharCode(55296|e>>10,56320|e&1023))}}else d+=String.fromCharCode(e)}return d}function G(a){return a?t(F,a,void 0):""} +function r(a,b,c,d){if(!(0=k){var m=a.charCodeAt(++g);k=65536+((k&1023)<<10)|m&1023}if(127>=k){if(c>=d)break;b[c++]=k}else{if(2047>=k){if(c+1>=d)break;b[c++]=192|k>>6}else{if(65535>=k){if(c+2>=d)break;b[c++]=224|k>>12}else{if(c+3>=d)break;b[c++]=240|k>>18;b[c++]=128|k>>12&63}b[c++]=128|k>>6&63}b[c++]=128|k&63}}b[c]=0;return c-e} +function oa(a){for(var b=0,c=0;c=d&&(d=65536+((d&1023)<<10)|a.charCodeAt(++c)&1023);127>=d?++b:b=2047>=d?b+2:65535>=d?b+3:b+4}return b}"undefined"!==typeof TextDecoder&&new TextDecoder("utf-16le");function Va(a){return a.replace(/__Z[\w\d_]+/g,function(a){return a===a?a:a+" ["+a+"]"})}function Wa(a){0Ya&&C("TOTAL_MEMORY should be larger than TOTAL_STACK, was "+Ya+"! (TOTAL_STACK=5242880)"); +f.buffer?buffer=f.buffer:"object"===typeof WebAssembly&&"function"===typeof WebAssembly.Memory?(La=new WebAssembly.Memory({initial:Ya/65536}),buffer=La.buffer):buffer=new ArrayBuffer(Ya);Xa();D[Ca>>2]=5303264;function Za(a){for(;0>2];var c=D[b>>2]}else ob.rb=!0,J.USER=J.LOGNAME="web_user",J.PATH="/",J.PWD="/",J.HOME="/home/web_user",J.LANG="C.UTF-8",J._=f.thisProgram,c=db?Ta(1024):Ba(1024),b=db?Ta(256):Ba(256),D[b>>2]=c,D[a>>2]=b;a=[];var d=0,e;for(e in J)if("string"===typeof J[e]){var g=e+"="+J[e];a.push(g);d+=g.length}if(1024>0]=d.charCodeAt(m);l[k>>0]=0;D[b+ +4*e>>2]=c;c+=g.length+1}D[b+4*a.length>>2]=0}function pb(a){f.___errno_location&&(D[f.___errno_location()>>2]=a);return a}function qb(a,b){for(var c=0,d=a.length-1;0<=d;d--){var e=a[d];"."===e?a.splice(d,1):".."===e?(a.splice(d,1),c++):c&&(a.splice(d,1),c--)}if(b)for(;c;c--)a.unshift("..");return a}function rb(a){var b="/"===a.charAt(0),c="/"===a.substr(-1);(a=qb(a.split("/").filter(function(a){return!!a}),!b).join("/"))||b||(a=".");a&&c&&(a+="/");return(b?"/":"")+a} +function sb(a){var b=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/.exec(a).slice(1);a=b[0];b=b[1];if(!a&&!b)return".";b&&(b=b.substr(0,b.length-1));return a+b}function tb(a){if("/"===a)return"/";var b=a.lastIndexOf("/");return-1===b?a:a.substr(b+1)}function ub(){var a=Array.prototype.slice.call(arguments,0);return rb(a.join("/"))}function n(a,b){return rb(a+"/"+b)} +function vb(){for(var a="",b=!1,c=arguments.length-1;-1<=c&&!b;c--){b=0<=c?arguments[c]:"/";if("string"!==typeof b)throw new TypeError("Arguments to path.resolve must be strings");if(!b)return"";a=b+"/"+a;b="/"===b.charAt(0)}a=qb(a.split("/").filter(function(a){return!!a}),!b).join("/");return(b?"/":"")+a||"."}var wb=[];function xb(a,b){wb[a]={input:[],output:[],ub:b};yb(a,zb)} +var zb={open:function(a){var b=wb[a.node.rdev];if(!b)throw new K(L.Cb);a.tty=b;a.seekable=!1},close:function(a){a.tty.ub.flush(a.tty)},flush:function(a){a.tty.ub.flush(a.tty)},read:function(a,b,c,d){if(!a.tty||!a.tty.ub.Xb)throw new K(L.Ob);for(var e=0,g=0;g=b||(b=Math.max(b,c*(1048576>c?2:1.125)|0),0!=c&&(b=Math.max(b,256)),c=a.bb,a.bb=new Uint8Array(b),0b)a.bb.length=b;else for(;a.bb.length=a.node.gb)return 0;a=Math.min(a.node.gb-e,d);if(8b)throw new K(L.ib);return b},Pb:function(a,b,c){M.Tb(a.node,b+c);a.node.gb=Math.max(a.node.gb,b+c)},zb:function(a,b,c,d,e,g,k){if(32768!== +(a.node.mode&61440))throw new K(L.Cb);c=a.node.bb;if(k&2||c.buffer!==b&&c.buffer!==b.buffer){if(0>2)}catch(c){if(!c.code)throw c; +throw new K(L[c.code]);}return b.mode},kb:function(a){for(var b=[];a.parent!==a;)b.push(a.name),a=a.parent;b.push(a.jb.Hb.root);b.reverse();return ub.apply(null,b)},qc:function(a){a&=-2656257;var b=0,c;for(c in P.Ub)a&c&&(b|=P.Ub[c],a^=c);if(a)throw new K(L.ib);return b},ab:{lb:function(a){a=P.kb(a);try{var b=fs.lstatSync(a)}catch(c){if(!c.code)throw c;throw new K(L[c.code]);}P.yb&&!b.pb&&(b.pb=4096);P.yb&&!b.blocks&&(b.blocks=(b.size+b.pb-1)/b.pb|0);return{dev:b.dev,ino:b.ino,mode:b.mode,nlink:b.nlink, +uid:b.uid,gid:b.gid,rdev:b.rdev,size:b.size,atime:b.atime,mtime:b.mtime,ctime:b.ctime,pb:b.pb,blocks:b.blocks}},hb:function(a,b){var c=P.kb(a);try{void 0!==b.mode&&(fs.chmodSync(c,b.mode),a.mode=b.mode),void 0!==b.size&&fs.truncateSync(c,b.size)}catch(d){if(!d.code)throw d;throw new K(L[d.code]);}},lookup:function(a,b){var c=n(P.kb(a),b);c=P.Wb(c);return P.createNode(a,b,c)},vb:function(a,b,c,d){a=P.createNode(a,b,c,d);b=P.kb(a);try{N(a.mode)?fs.mkdirSync(b,a.mode):fs.writeFileSync(b,"",{mode:a.mode})}catch(e){if(!e.code)throw e; +throw new K(L[e.code]);}return a},rename:function(a,b,c){a=P.kb(a);b=n(P.kb(b),c);try{fs.renameSync(a,b)}catch(d){if(!d.code)throw d;throw new K(L[d.code]);}},unlink:function(a,b){a=n(P.kb(a),b);try{fs.unlinkSync(a)}catch(c){if(!c.code)throw c;throw new K(L[c.code]);}},rmdir:function(a,b){a=n(P.kb(a),b);try{fs.rmdirSync(a)}catch(c){if(!c.code)throw c;throw new K(L[c.code]);}},readdir:function(a){a=P.kb(a);try{return fs.readdirSync(a)}catch(b){if(!b.code)throw b;throw new K(L[b.code]);}},symlink:function(a, +b,c){a=n(P.kb(a),b);try{fs.symlinkSync(c,a)}catch(d){if(!d.code)throw d;throw new K(L[d.code]);}},readlink:function(a){var b=P.kb(a);try{return b=fs.readlinkSync(b),b=Fb.relative(Fb.resolve(a.jb.Hb.root),b)}catch(c){if(!c.code)throw c;throw new K(L[c.code]);}}},cb:{open:function(a){var b=P.kb(a.node);try{32768===(a.node.mode&61440)&&(a.wb=fs.openSync(b,P.qc(a.flags)))}catch(c){if(!c.code)throw c;throw new K(L[c.code]);}},close:function(a){try{32768===(a.node.mode&61440)&&a.wb&&fs.closeSync(a.wb)}catch(b){if(!b.code)throw b; +throw new K(L[b.code]);}},read:function(a,b,c,d,e){if(0===d)return 0;try{return fs.readSync(a.wb,P.Rb(b.buffer),c,d,e)}catch(g){throw new K(L[g.code]);}},write:function(a,b,c,d,e){try{return fs.writeSync(a.wb,P.Rb(b.buffer),c,d,e)}catch(g){throw new K(L[g.code]);}},ob:function(a,b,c){if(1===c)b+=a.position;else if(2===c&&32768===(a.node.mode&61440))try{b+=fs.fstatSync(a.wb).size}catch(d){throw new K(L[d.code]);}if(0>b)throw new K(L.ib);return b}}},Gb=null,Hb={},Q=[],Ib=1,R=null,Jb=!0,S={},K=null, +Eb={};function T(a,b){a=vb("/",a);b=b||{};if(!a)return{path:"",node:null};var c={Vb:!0,Jb:0},d;for(d in c)void 0===b[d]&&(b[d]=c[d]);if(8>>0)%R.length}function Nb(a){var b=Mb(a.parent.id,a.name);a.tb=R[b];R[b]=a}function Ob(a){var b=Mb(a.parent.id,a.name);if(R[b]===a)R[b]=a.tb;else for(b=R[b];b;){if(b.tb===a){b.tb=a.tb;break}b=b.tb}} +function O(a,b){var c;if(c=(c=Pb(a,"x"))?c:a.ab.lookup?0:13)throw new K(c,a);for(c=R[Mb(a.id,b)];c;c=c.tb){var d=c.name;if(c.parent.id===a.id&&d===b)return c}return a.ab.lookup(a,b)} +function Db(a,b,c,d){Qb||(Qb=function(a,b,c,d){a||(a=this);this.parent=a;this.jb=a.jb;this.sb=null;this.id=Ib++;this.name=b;this.mode=c;this.ab={};this.cb={};this.rdev=d},Qb.prototype={},Object.defineProperties(Qb.prototype,{read:{get:function(){return 365===(this.mode&365)},set:function(a){a?this.mode|=365:this.mode&=-366}},write:{get:function(){return 146===(this.mode&146)},set:function(a){a?this.mode|=146:this.mode&=-147}}}));a=new Qb(a,b,c,d);Nb(a);return a} +function N(a){return 16384===(a&61440)}var Rb={r:0,rs:1052672,"r+":2,w:577,wx:705,xw:705,"w+":578,"wx+":706,"xw+":706,a:1089,ax:1217,xa:1217,"a+":1090,"ax+":1218,"xa+":1218};function ic(a){var b=["r","w","rw"][a&3];a&512&&(b+="w");return b}function Pb(a,b){if(Jb)return 0;if(-1===b.indexOf("r")||a.mode&292){if(-1!==b.indexOf("w")&&!(a.mode&146)||-1!==b.indexOf("x")&&!(a.mode&73))return 13}else return 13;return 0}function tc(a,b){try{return O(a,b),17}catch(c){}return Pb(a,"wx")} +function uc(a,b,c){try{var d=O(a,b)}catch(e){return e.eb}if(a=Pb(a,"wx"))return a;if(c){if(!N(d.mode))return 20;if(d===d.parent||"/"===Lb(d))return 16}else if(N(d.mode))return 21;return 0}function vc(a){var b=4096;for(a=a||0;a<=b;a++)if(!Q[a])return a;throw new K(24);} +function wc(a,b){xc||(xc=function(){},xc.prototype={},Object.defineProperties(xc.prototype,{object:{get:function(){return this.node},set:function(a){this.node=a}}}));var c=new xc,d;for(d in a)c[d]=a[d];a=c;b=vc(b);a.fd=b;return Q[b]=a}var Cb={open:function(a){a.cb=Hb[a.node.rdev].cb;a.cb.open&&a.cb.open(a)},ob:function(){throw new K(29);}};function yb(a,b){Hb[a]={cb:b}} +function yc(a,b){var c="/"===b,d=!b;if(c&&Gb)throw new K(16);if(!c&&!d){var e=T(b,{Vb:!1});b=e.path;e=e.node;if(e.sb)throw new K(16);if(!N(e.mode))throw new K(20);}b={type:a,Hb:{},Yb:b,wc:[]};a=a.jb(b);a.jb=b;b.root=a;c?Gb=a:e&&(e.sb=b,e.jb&&e.jb.wc.push(b))}function ja(a,b,c){var d=T(a,{parent:!0}).node;a=tb(a);if(!a||"."===a||".."===a)throw new K(22);var e=tc(d,a);if(e)throw new K(e);if(!d.ab.vb)throw new K(1);return d.ab.vb(d,a,b,c)}function U(a,b){ja(a,(void 0!==b?b:511)&1023|16384,0)} +function zc(a,b,c){"undefined"===typeof c&&(c=b,b=438);ja(a,b|8192,c)}function Ac(a,b){if(!vb(a))throw new K(2);var c=T(b,{parent:!0}).node;if(!c)throw new K(2);b=tb(b);var d=tc(c,b);if(d)throw new K(d);if(!c.ab.symlink)throw new K(1);c.ab.symlink(c,b,a)} +function ta(a){var b=T(a,{parent:!0}).node,c=tb(a),d=O(b,c),e=uc(b,c,!1);if(e)throw new K(e);if(!b.ab.unlink)throw new K(1);if(d.sb)throw new K(16);try{S.willDeletePath&&S.willDeletePath(a)}catch(g){console.log("FS.trackingDelegate['willDeletePath']('"+a+"') threw an exception: "+g.message)}b.ab.unlink(b,c);Ob(d);try{if(S.onDeletePath)S.onDeletePath(a)}catch(g){console.log("FS.trackingDelegate['onDeletePath']('"+a+"') threw an exception: "+g.message)}} +function Kb(a){a=T(a).node;if(!a)throw new K(2);if(!a.ab.readlink)throw new K(22);return vb(Lb(a.parent),a.ab.readlink(a))}function ra(a,b){a=T(a,{qb:!b}).node;if(!a)throw new K(2);if(!a.ab.lb)throw new K(1);return a.ab.lb(a)}function Bc(a){return ra(a,!0)}function ka(a,b){var c;"string"===typeof a?c=T(a,{qb:!0}).node:c=a;if(!c.ab.hb)throw new K(1);c.ab.hb(c,{mode:b&4095|c.mode&-4096,timestamp:Date.now()})} +function Cc(a){var b;"string"===typeof a?b=T(a,{qb:!0}).node:b=a;if(!b.ab.hb)throw new K(1);b.ab.hb(b,{timestamp:Date.now()})}function Dc(a,b){if(0>b)throw new K(22);var c;"string"===typeof a?c=T(a,{qb:!0}).node:c=a;if(!c.ab.hb)throw new K(1);if(N(c.mode))throw new K(21);if(32768!==(c.mode&61440))throw new K(22);if(a=Pb(c,"w"))throw new K(a);c.ab.hb(c,{size:b,timestamp:Date.now()})} +function p(a,b,c,d){if(""===a)throw new K(2);if("string"===typeof b){var e=Rb[b];if("undefined"===typeof e)throw Error("Unknown file open mode: "+b);b=e}c=b&64?("undefined"===typeof c?438:c)&4095|32768:0;if("object"===typeof a)var g=a;else{a=rb(a);try{g=T(a,{qb:!(b&131072)}).node}catch(k){}}e=!1;if(b&64)if(g){if(b&128)throw new K(17);}else g=ja(a,c,0),e=!0;if(!g)throw new K(2);8192===(g.mode&61440)&&(b&=-513);if(b&65536&&!N(g.mode))throw new K(20);if(!e&&(c=g?40960===(g.mode&61440)?40:N(g.mode)&& +("r"!==ic(b)||b&512)?21:Pb(g,ic(b)):2))throw new K(c);b&512&&Dc(g,0);b&=-641;d=wc({node:g,path:Lb(g),flags:b,seekable:!0,position:0,cb:g.cb,Bc:[],error:!1},d);d.cb.open&&d.cb.open(d);!f.logReadFiles||b&1||(Ec||(Ec={}),a in Ec||(Ec[a]=1,console.log("FS.trackingDelegate error on read file: "+a)));try{S.onOpenFile&&(g=0,1!==(b&2097155)&&(g|=1),0!==(b&2097155)&&(g|=2),S.onOpenFile(a,g))}catch(k){console.log("FS.trackingDelegate['onOpenFile']('"+a+"', flags) threw an exception: "+k.message)}return d} +function ma(a){if(null===a.fd)throw new K(9);a.Gb&&(a.Gb=null);try{a.cb.close&&a.cb.close(a)}catch(b){throw b;}finally{Q[a.fd]=null}a.fd=null}function Fc(a,b,c){if(null===a.fd)throw new K(9);if(!a.seekable||!a.cb.ob)throw new K(29);if(0!=c&&1!=c&&2!=c)throw new K(22);a.position=a.cb.ob(a,b,c);a.Bc=[]} +function sa(a,b,c,d,e){if(0>d||0>e)throw new K(22);if(null===a.fd)throw new K(9);if(1===(a.flags&2097155))throw new K(9);if(N(a.node.mode))throw new K(21);if(!a.cb.read)throw new K(22);var g="undefined"!==typeof e;if(!g)e=a.position;else if(!a.seekable)throw new K(29);b=a.cb.read(a,b,c,d,e);g||(a.position+=b);return b} +function la(a,b,c,d,e,g){if(0>d||0>e)throw new K(22);if(null===a.fd)throw new K(9);if(0===(a.flags&2097155))throw new K(9);if(N(a.node.mode))throw new K(21);if(!a.cb.write)throw new K(22);a.flags&1024&&Fc(a,0,2);var k="undefined"!==typeof e;if(!k)e=a.position;else if(!a.seekable)throw new K(29);b=a.cb.write(a,b,c,d,e,g);k||(a.position+=b);try{if(a.path&&S.onWriteToFile)S.onWriteToFile(a.path)}catch(m){console.log("FS.trackingDelegate['onWriteToFile']('"+a.path+"') threw an exception: "+m.message)}return b} +function Gc(){K||(K=function(a,b){this.node=b;this.zc=function(a){this.eb=a};this.zc(a);this.message="FS error";this.stack&&Object.defineProperty(this,"stack",{value:Error().stack,writable:!0})},K.prototype=Error(),K.prototype.constructor=K,[2].forEach(function(a){Eb[a]=new K(a);Eb[a].stack=""}))}var Hc;function ia(a,b){var c=0;a&&(c|=365);b&&(c|=146);return c} +function Ic(a,b,c){a=n("/dev",a);var d=ia(!!b,!!c);Jc||(Jc=64);var e=Jc++<<8|0;yb(e,{open:function(a){a.seekable=!1},close:function(){c&&c.buffer&&c.buffer.length&&c(10)},read:function(a,c,d,e){for(var g=0,k=0;k>2]=d.dev;D[c+4>>2]=0;D[c+8>>2]=d.ino;D[c+12>>2]=d.mode;D[c+16>>2]=d.nlink;D[c+20>>2]=d.uid;D[c+24>>2]=d.gid;D[c+28>>2]=d.rdev;D[c+32>>2]=0;D[c+36>>2]=d.size;D[c+40>>2]=4096;D[c+44>>2]=d.blocks;D[c+48>>2]=d.atime.getTime()/1E3|0;D[c+52>>2]=0;D[c+56>>2]=d.mtime.getTime()/1E3|0;D[c+60>>2]=0;D[c+64>>2]=d.ctime.getTime()/1E3|0;D[c+68>>2]=0;D[c+72>>2]=d.ino;return 0}var W=0; +function X(){W+=4;return D[W-4>>2]}function Y(){return G(X())}function Z(){var a=Q[X()];if(!a)throw new K(L.Kb);return a}function Da(){return l.length}function Ea(a){if(2147418112=b?b=Wa(2*b):b=Math.min(Wa((3*b+2147483648)/4),2147418112);a=Wa(b);var c=buffer.byteLength;try{var d=-1!==La.grow((a-c)/65536)?buffer=La.buffer:null}catch(e){d=null}if(!d||d.byteLength!=b)return!1;Xa();return!0} +function Mc(a){if(0===a)return 0;a=G(a);if(!J.hasOwnProperty(a))return 0;Mc.rb&&ha(Mc.rb);a=J[a];var b=oa(a)+1,c=Ta(b);c&&r(a,l,c,b);Mc.rb=c;return Mc.rb}r("GMT",F,60272,4); +function Nc(){function a(a){return(a=a.toTimeString().match(/\(([A-Za-z ]+)\)$/))?a[1]:"GMT"}if(!Oc){Oc=!0;D[Pc()>>2]=60*(new Date).getTimezoneOffset();var b=new Date(2E3,0,1),c=new Date(2E3,6,1);D[Qc()>>2]=Number(b.getTimezoneOffset()!=c.getTimezoneOffset());var d=a(b),e=a(c);d=ea(ba(d));e=ea(ba(e));c.getTimezoneOffset()>2]=d,D[Rc()+4>>2]=e):(D[Rc()>>2]=e,D[Rc()+4>>2]=d)}}var Oc; +function Sc(a){a/=1E3;if((v||w)&&self.performance&&self.performance.now)for(var b=self.performance.now();self.performance.now()-b>2]=c.position;c.Gb&&0===d&&0===g&&(c.Gb=null);return 0}catch(k){return"undefined"!==typeof V&&k instanceof K||B(k),-k.eb}},ca:function(a,b){W=b;try{var c=Y(),d=X();ka(c,d);return 0}catch(e){return"undefined"!==typeof V&&e instanceof K||B(e),-e.eb}},ba:function(a,b){W=b;try{var c=X(),d=X();if(0===d)return-L.ib;if(dd?-L.ib:p(c.path,c.flags,0,d).fd;case 1:case 2:return 0; +case 3:return c.flags;case 4:return d=X(),c.flags|=d,0;case 12:return d=X(),Ha[d+0>>1]=2,0;case 13:case 14:return 0;case 16:case 8:return-L.ib;case 9:return pb(L.ib),-1;default:return-L.ib}}catch(e){return"undefined"!==typeof V&&e instanceof K||B(e),-e.eb}},U:function(a,b){W=b;try{var c=Z(),d=X(),e=X();return sa(c,l,d,e)}catch(g){return"undefined"!==typeof V&&g instanceof K||B(g),-g.eb}},T:function(a,b){W=b;try{var c=Y();var d=X();if(d&-8)var e=-L.ib;else{var g=T(c,{qb:!0}).node;a="";d&4&&(a+="r"); +d&2&&(a+="w");d&1&&(a+="x");e=a&&Pb(g,a)?-L.$b:0}return e}catch(k){return"undefined"!==typeof V&&k instanceof K||B(k),-k.eb}},S:function(a,b){W=b;try{var c=Y(),d=X();a=c;a=rb(a);"/"===a[a.length-1]&&(a=a.substr(0,a.length-1));U(a,d);return 0}catch(e){return"undefined"!==typeof V&&e instanceof K||B(e),-e.eb}},R:function(a,b){W=b;try{var c=Z(),d=X(),e=X();return la(c,l,d,e)}catch(g){return"undefined"!==typeof V&&g instanceof K||B(g),-g.eb}},Q:function(a,b){W=b;try{var c=Y(),d=T(c,{parent:!0}).node, +e=tb(c),g=O(d,e),k=uc(d,e,!0);if(k)throw new K(k);if(!d.ab.rmdir)throw new K(1);if(g.sb)throw new K(16);try{S.willDeletePath&&S.willDeletePath(c)}catch(m){console.log("FS.trackingDelegate['willDeletePath']('"+c+"') threw an exception: "+m.message)}d.ab.rmdir(d,e);Ob(g);try{if(S.onDeletePath)S.onDeletePath(c)}catch(m){console.log("FS.trackingDelegate['onDeletePath']('"+c+"') threw an exception: "+m.message)}return 0}catch(m){return"undefined"!==typeof V&&m instanceof K||B(m),-m.eb}},P:function(a,b){W= +b;try{var c=Y(),d=X(),e=X();return p(c,d,e).fd}catch(g){return"undefined"!==typeof V&&g instanceof K||B(g),-g.eb}},s:function(a,b){W=b;try{var c=Z();ma(c);return 0}catch(d){return"undefined"!==typeof V&&d instanceof K||B(d),-d.eb}},O:function(a,b){W=b;try{var c=Y(),d=X();var e=X();if(0>=e)var g=-L.ib;else{var k=Kb(c),m=Math.min(e,oa(k)),y=l[d+m];r(k,F,d,e+1);l[d+m]=y;g=m}return g}catch(z){return"undefined"!==typeof V&&z instanceof K||B(z),-z.eb}},N:function(a,b){W=b;try{var c=X(),d=X(),e=Kc[c];if(!e)return 0; +if(d===e.uc){var g=Q[e.fd],k=e.flags,m=new Uint8Array(F.subarray(c,c+d));g&&g.cb.Ab&&g.cb.Ab(g,m,0,d,k);Kc[c]=null;e.Db&&ha(e.vc)}return 0}catch(y){return"undefined"!==typeof V&&y instanceof K||B(y),-y.eb}},M:function(a,b){W=b;try{var c=X(),d=X(),e=Q[c];if(!e)throw new K(9);ka(e.node,d);return 0}catch(g){return"undefined"!==typeof V&&g instanceof K||B(g),-g.eb}},L:Da,K:function(a,b,c){F.set(F.subarray(b,b+c),a)},J:Ea,r:Mc,q:function(a){var b=Date.now();D[a>>2]=b/1E3|0;D[a+4>>2]=b%1E3*1E3|0;return 0}, +I:function(a){return Math.log(a)/Math.LN10},p:function(){B("trap!")},H:function(a){Nc();a=new Date(1E3*D[a>>2]);D[15056]=a.getSeconds();D[15057]=a.getMinutes();D[15058]=a.getHours();D[15059]=a.getDate();D[15060]=a.getMonth();D[15061]=a.getFullYear()-1900;D[15062]=a.getDay();var b=new Date(a.getFullYear(),0,1);D[15063]=(a.getTime()-b.getTime())/864E5|0;D[15065]=-(60*a.getTimezoneOffset());var c=(new Date(2E3,6,1)).getTimezoneOffset();b=b.getTimezoneOffset();a=(c!=b&&a.getTimezoneOffset()==Math.min(b, +c))|0;D[15064]=a;a=D[Rc()+(a?4:0)>>2];D[15066]=a;return 60224},G:function(a,b){var c=D[a>>2];a=D[a+4>>2];0!==b&&(D[b>>2]=0,D[b+4>>2]=0);return Sc(1E6*c+a/1E3)},F:function(a){switch(a){case 30:return 16384;case 85:return 131068;case 132:case 133:case 12:case 137:case 138:case 15:case 235:case 16:case 17:case 18:case 19:case 20:case 149:case 13:case 10:case 236:case 153:case 9:case 21:case 22:case 159:case 154:case 14:case 77:case 78:case 139:case 80:case 81:case 82:case 68:case 67:case 164:case 11:case 29:case 47:case 48:case 95:case 52:case 51:case 46:return 200809; +case 79:return 0;case 27:case 246:case 127:case 128:case 23:case 24:case 160:case 161:case 181:case 182:case 242:case 183:case 184:case 243:case 244:case 245:case 165:case 178:case 179:case 49:case 50:case 168:case 169:case 175:case 170:case 171:case 172:case 97:case 76:case 32:case 173:case 35:return-1;case 176:case 177:case 7:case 155:case 8:case 157:case 125:case 126:case 92:case 93:case 129:case 130:case 131:case 94:case 91:return 1;case 74:case 60:case 69:case 70:case 4:return 1024;case 31:case 42:case 72:return 32; +case 87:case 26:case 33:return 2147483647;case 34:case 1:return 47839;case 38:case 36:return 99;case 43:case 37:return 2048;case 0:return 2097152;case 3:return 65536;case 28:return 32768;case 44:return 32767;case 75:return 16384;case 39:return 1E3;case 89:return 700;case 71:return 256;case 40:return 255;case 2:return 100;case 180:return 64;case 25:return 20;case 5:return 16;case 6:return 6;case 73:return 4;case 84:return"object"===typeof navigator?navigator.hardwareConcurrency||1:1}pb(22);return-1}, +E:function(a){var b=Date.now()/1E3|0;a&&(D[a>>2]=b);return b},D:function(a,b){if(b){var c=1E3*D[b+8>>2];c+=D[b+12>>2]/1E3}else c=Date.now();a=G(a);try{b=c;var d=T(a,{qb:!0}).node;d.ab.hb(d,{timestamp:Math.max(b,c)});return 0}catch(e){a=e;if(!(a instanceof K)){a+=" : ";a:{d=Error();if(!d.stack){try{throw Error(0);}catch(g){d=g}if(!d.stack){d="(no stack trace available)";break a}}d=d.stack.toString()}f.extraStackTrace&&(d+="\n"+f.extraStackTrace());d=Va(d);throw a+d;}pb(a.eb);return-1}},C:function(){B("OOM")}, +a:Ca},buffer);f.asm=Vc;f._RegisterExtensionFunctions=function(){return f.asm.ha.apply(null,arguments)};var nb=f.___emscripten_environ_constructor=function(){return f.asm.ia.apply(null,arguments)};f.___errno_location=function(){return f.asm.ja.apply(null,arguments)}; +var Qc=f.__get_daylight=function(){return f.asm.ka.apply(null,arguments)},Pc=f.__get_timezone=function(){return f.asm.la.apply(null,arguments)},Rc=f.__get_tzname=function(){return f.asm.ma.apply(null,arguments)},ha=f._free=function(){return f.asm.na.apply(null,arguments)},Ta=f._malloc=function(){return f.asm.oa.apply(null,arguments)},Tc=f._memalign=function(){return f.asm.pa.apply(null,arguments)},Uc=f._memset=function(){return f.asm.qa.apply(null,arguments)}; +f._sqlite3_bind_blob=function(){return f.asm.ra.apply(null,arguments)};f._sqlite3_bind_double=function(){return f.asm.sa.apply(null,arguments)};f._sqlite3_bind_int=function(){return f.asm.ta.apply(null,arguments)};f._sqlite3_bind_parameter_index=function(){return f.asm.ua.apply(null,arguments)};f._sqlite3_bind_text=function(){return f.asm.va.apply(null,arguments)};f._sqlite3_changes=function(){return f.asm.wa.apply(null,arguments)};f._sqlite3_clear_bindings=function(){return f.asm.xa.apply(null,arguments)}; +f._sqlite3_close_v2=function(){return f.asm.ya.apply(null,arguments)};f._sqlite3_column_blob=function(){return f.asm.za.apply(null,arguments)};f._sqlite3_column_bytes=function(){return f.asm.Aa.apply(null,arguments)};f._sqlite3_column_double=function(){return f.asm.Ba.apply(null,arguments)};f._sqlite3_column_name=function(){return f.asm.Ca.apply(null,arguments)};f._sqlite3_column_text=function(){return f.asm.Da.apply(null,arguments)};f._sqlite3_column_type=function(){return f.asm.Ea.apply(null,arguments)}; +f._sqlite3_create_function_v2=function(){return f.asm.Fa.apply(null,arguments)};f._sqlite3_data_count=function(){return f.asm.Ga.apply(null,arguments)};f._sqlite3_errmsg=function(){return f.asm.Ha.apply(null,arguments)};f._sqlite3_exec=function(){return f.asm.Ia.apply(null,arguments)};f._sqlite3_finalize=function(){return f.asm.Ja.apply(null,arguments)};f._sqlite3_free=function(){return f.asm.Ka.apply(null,arguments)};f._sqlite3_open=function(){return f.asm.La.apply(null,arguments)}; +f._sqlite3_prepare_v2=function(){return f.asm.Ma.apply(null,arguments)};f._sqlite3_reset=function(){return f.asm.Na.apply(null,arguments)};f._sqlite3_result_double=function(){return f.asm.Oa.apply(null,arguments)};f._sqlite3_result_null=function(){return f.asm.Pa.apply(null,arguments)};f._sqlite3_result_text=function(){return f.asm.Qa.apply(null,arguments)};f._sqlite3_step=function(){return f.asm.Ra.apply(null,arguments)};f._sqlite3_value_blob=function(){return f.asm.Sa.apply(null,arguments)}; +f._sqlite3_value_bytes=function(){return f.asm.Ta.apply(null,arguments)};f._sqlite3_value_double=function(){return f.asm.Ua.apply(null,arguments)};f._sqlite3_value_int=function(){return f.asm.Va.apply(null,arguments)};f._sqlite3_value_text=function(){return f.asm.Wa.apply(null,arguments)};f._sqlite3_value_type=function(){return f.asm.Xa.apply(null,arguments)}; +var h=f.stackAlloc=function(){return f.asm.Za.apply(null,arguments)},qa=f.stackRestore=function(){return f.asm._a.apply(null,arguments)},na=f.stackSave=function(){return f.asm.$a.apply(null,arguments)};f.dynCall_vi=function(){return f.asm.Ya.apply(null,arguments)};f.asm=Vc;f.cwrap=function(a,b,c,d){c=c||[];var e=c.every(function(a){return"number"===a});return"string"!==b&&e&&!d?Na(a):function(){return Oa(a,b,c,arguments)}};f.stackSave=na;f.stackRestore=qa;f.stackAlloc=h; +function Wc(a){this.name="ExitStatus";this.message="Program terminated with exit("+a+")";this.status=a}Wc.prototype=Error();Wc.prototype.constructor=Wc;gb=function Xc(){f.calledRun||Yc();f.calledRun||(gb=Xc)}; +function Yc(){function a(){if(!f.calledRun&&(f.calledRun=!0,!Ma)){db||(db=!0,f.noFSInit||Hc||(Hc=!0,Gc(),f.stdin=f.stdin,f.stdout=f.stdout,f.stderr=f.stderr,f.stdin?Ic("stdin",f.stdin):Ac("/dev/tty","/dev/stdin"),f.stdout?Ic("stdout",null,f.stdout):Ac("/dev/tty","/dev/stdout"),f.stderr?Ic("stderr",null,f.stderr):Ac("/dev/tty1","/dev/stderr"),p("/dev/stdin","r"),p("/dev/stdout","w"),p("/dev/stderr","w")),Za(ab));Jb=!1;Za(bb);if(f.onRuntimeInitialized)f.onRuntimeInitialized();if(f.postRun)for("function"== +typeof f.postRun&&(f.postRun=[f.postRun]);f.postRun.length;){var a=f.postRun.shift();cb.unshift(a)}Za(cb)}}if(!(02&huzyoEav; zCCE5>FGIp2L}Uq@gngF)L0JN_6IO%lo9qY(f~;W?+4+CI@2Ot08p!CKXP$pUe&^Jw zv%cp&?|HX#%A4`culkFu8j9(OC(!3XJ@N(XIIb8RwA|%V}D^BH zvome)2zEOxg3?5v98IXhFaH8tvn_vLKV3^4&|XY!H1N$-ie&ICJYeBn+O1Um^Z zN^+yLels6d%yj^e*aTSsw1abMW%!R@`Uqa1{MV}7 zx2pR8tqQ;Gt#9SOQ}yrvRQ)Tf{%u*M|7BJ0N2>a^s-Cy5!jD$z+f>gV^CnrnAFrN2 zQH}GHUft3^RpsBd3jeAK|GEl4U4@^i!oR7)&sO2zR^jKW@bgvpg)01CRrtj!{8ANe z?80Eij4JZ?gUCM&B3~Iq{&5ibr$OYOXE-pXU;5IHGyZ=2fBe$l&-ms)hI8DM%pel| z^Y&l=`x)CeKK8YL`j@Z$%Z}d(cd~cUSO4*=U*F+7fj8G?xo(C1Z+LSjh39t9=_YB| zsQFzz@} z3w__O)%HcWsx6D%xX2yOVe6bi-KAbg+Z;iaRdPi`$0y&(0gwbrCt(v8`g>-t@#Zv zP5i*~yHnB$K^jnvAJu|d(4*qods3dM&i9I1h}&ivqe|d+$WwdoPQs=A}WFzBj04#d~>^ z`5}WyYJo=wf^=e<)@z~HO8$EkCA>*OAUnbL{wPQ(2auEZzc-pzn;3?zC<;^mZD~k< z!l+dX-aFyFVKi}l&rgzC7}xv>2_W*Aj+RFxoJbS3Y|^Aje@dUzpw+6i0&hAasYS^q zwF%LCCniBOfeDHH$V-86s9&0-K(4iZQ2XPkct5>ef8s<&N`I#}rgyXSJwX}*!Z6Lk zK;xu00dNe0D0^=RdQf{daUyl_K8VS|#0E5^2_{oe3xPk)`M$@TMS-783^opYKjEcn z0s7R+WCm#zHS%;)FzHW(UX$LjLDf)Aa0`4g*J{E(LhE_;CmB5~m#*X>=)AoHdUzrK zYchR?LenixJcFoN32K}Q;F%>b4+K;mzy}loq58-`XmpScs(6Vf#L2>%pVkZ5e1!|HzyjcwLgFK zCKyFm6>ANDEQ*zXt4xFd41N|(e)kVzKKPAA2T2L^Z56+86=|zX>M0evRjc*vul-?p zuj04L)KQ|NBBD#H{D~A+KM~$l{vdg4|AVfs^sBGp7p)>~wMi*&*4uPbw!2BKfIpF6 z*JhZ8lP3Amgm8}kPCwbne`k=)@yq*f50iL7@W;V+GrW0G@GmpGySl;58Q!(^VAc%p zj&8914Da@C@YNaKo!#JTGrV1c;OjHI-Gbm7GrSw>!R#5{Uj{qO@b-^_Z_e;uuLnEM z@E)rN|2o6Fz8-vQhWCql@NYA`J@eq(GrY^=;5#$CXFI|Fnc@973d$MYrGBvG4DW;} z_{$mIVNvjr8QyVGu+@X;CGxlypq3~%2c_!wpV;NvsAj|QKZ;Vt%q zPtNe3ZwH^6;qB55wk3NU{M8I^KR@_uM&bvbCdCgvGsF8#@Hh0&4?a7?`%x|U+Zo;g ze(*VZ83do7;hpaXU!XT}@V{nwPb9$?XL!$agD=hS_HG0l&+uMqHm@&y@10&Uchaoe zy0><3>E7JEse5DhhVJ#<>$=x=uj&4*dv$kd_ov;fx>t6u=w9Bvtb1v9N%xZO#odd# z7j`e`p5HyMdv5n9@QY`67kAIn`e^+C8PauzOPXhussqCv=bR z9@jm#drbG}?or(%yGL{n?;h4Yw7Z~tNcRWbgS(G*pG#(~%kRhjLEQtp2Xy!E&hPHm z-M70>ckk}^yL)xN*PYkhv%5$4yWQQpyLET%&h5UDzn;IAznZ_2zns66znK3vej}^PlIp<+tW{WRIo4NUy3t)_tVABsn&@v3XPYMEqF%>-bmEFQW&e1+@pF zd!u8+#nGA3eznu1Q=@%r3u>oCCq_3#Cxq8VKZ_2iEsbspPYCsIezb42cl7<}p3ZTt zAN#-izfawg-<;o+-Uz=Z(|17^cUz-0kzbd~nzaqapzbwBrUy@&vUz}f* zUznetpO>GT|0F*rKRaKXpOv4PpOODK|51Kgz9>I6KP5joUznei|1du>KOsLpKQ2Eu zKPEpqKPo>mKO#RoKP*2qUyvV?{~$j&KPW#iKOmpmcr|_@el~tO{$=)?)?=+j*)iF{ z*$MTz+2Zu_`o;At>X+1?=swteJvqOAUj54Yg~5fvsmTwL??is@Y;J8$y$tvx$?biUi!y|Y_q*Um1Txt%xKueV=ozuJDK z{c`)I_KWS`wqI!fru|&|+4eK-W$mZiPqm+HKhb`?{aE|a_9N|IwI6Oj)c$4r!S(~~ z``f>0-`BpkeNX%D_Fe5e+jq2YZ~we~Tl?1bE$y4zH??nU-_X9keO>$7_BHLFwXbe3 zZU3}=RePVtt?A?O8PUnn)zLoD()iZsTW{(2Z&$XjXkXsGti7atN&DjVMePgQ7qriB zpVvOO{gd|D?Zxf0+Gn=UXrJExar;N@)7p#Lr?yXNpWI&9KB@h~_KEEi+Q+w#Yai1- zx_wmp$o3KK!`p|o4{a}KAJYCo`{4FL?E~8fwD)h%Z|~RMx4lpM`|Z8j-)qln@7dm? z{oVHN?cLhDwjby&i+>WG6WtJ9A6*n(5FHr36u%h1693zq|9x$j_T2Ux+3VSB*{j(r z*~{5W*^Ak4vlp`8WY1^MWzS~MWXrOrv!}8rvnR60v&XVuXOCu&WWUND&K}Ah%pS<@ z&wi2Jm))D)lii)&mED=$p8Y(#ExR?lCA&GhDZ4SdA-g`iHoGSKS$1`{H2Z0GRd!`| zMRs|1X|^Q0B)d4fF1swdvUz^X z>_^#Y*{Rtn*~!_$?4<06*@@W++40$N+0ofi*^${1+2Pq?*`e8j?2zmS*+JQX*#X)9 z+5Bw3Y~O63Z13#**22vP>CNd)>5b_P>GkP#>9y%K>Ce)o=}*(E(ks&|(#zA! z(o54N=_TpK=|$;<=>_Te>3Qk7=}*#g(zDaE(lgVe(tlp3-#?v^o}T_V{ZV>ax+pz0 zJtbY3o|OJDJuy8YJw81yJvKciJvu!yJt93kJuE#mU63A<{vbU#Jt#deJs{mbouBTP z?wjtD?wx)=-7B4!?wRh9emC7c-7VcU-6fryzLC6^yqdg{yqvt0yqNqpc_H~t@_h1a z@=UTUc{+J2c``XU{ik*M9qT`yJeK@Ac{F(>`Bn08@=)^2qJ_~f|cnB?f>sN~4xh~)6( zu;kEWL2^iPaB@&`U~)jRe=;_MwVrJ~(^}Sgy7g4+$<`CC$6LQ{J=%Jt^{dvyt%q9o zMR!IQ#5cz`#XG#^-{*eWda(6C>ldy2TKBf@Y2Dqrt957Vj@Iq1pSNyn-P*dPb#v>c z){U(jTGzL(YhByAruDPd)vcwipSG@QUD>*#b$RQu)}^f_txH-Lw=Qa3*t(!~e(Su} zxvihH&S{<9THHFTb!O{~*6FPuw|>-G)H=0wO6%m-!q!QxAGS_xozObIb!_Y0_$Tq% z@mcYi@fq>y@sHxu;zjYP@xu6|_=oX{@d@$q@p197@iFny@lo-S@e%Ri@nP|y@q+k} z_y_U9@j>x{@d5Gv@qY2%@m}%w;yvQ?;_t@0$GgR^M@!;YqnD#2Ye&@d?}h03=(%WF z^mO!O^muf5?XcRRwa21gM~_C2M0ZEWL`O$QMMp+2*I%l?SpRMPh5B#m&)1);KU;sM zzO4Rq{i*ts^(X3&*MD7qwEjr_SM`VM57mEJf3W^Q{r>uW^?U30)bFm}Rll=-NB#Et z&+E6`@_KdN(HbU@?a#(|AJqury={m1>jdQ9u+)={k^TSv4GZynY;w6&mhNb3i! zgIfo+4s0FJ+P^iwwO?!B);_JhTiKC=9A4QnvXXhYyP_VX!DWgubK}xA8P)x z`C#*b=KalIH1CRz^l$aQx(>gu+}FIfc~A51=3UJ@n|CyCZ~nY_Tl3cDEzO&oH#Ki) zUf;Z~d2REW=Fgf}HQOPZH7FK%Acys&ve^StJ{&7U;SX`bC& z+&rs!X7h~Z>CGQCPirn}p4vR6d2(}M^Q7hvn$+Z#V` z+}60YaZBUo#!ZbI8#gqrZ(P^7wsB44XN{{HOB+9JT-CU;aYf_u#$}C58%r9OG%jvj z)VQ#5LF4?!d5v=$KWUuPIJ>d9aaQBZ#u<&%8$WLRsBv0jQR9@x$&H1LlNvv4oY**_ zaeU*r#<7i~8%H&cY#h-zym46L(8hwsYxOtk|FSN>)`B}fdrtS{dQihETX@rgZ}j6u zTl#x!`6op@rQcLa+K;CNUcWvqnCmb4+u9aIz30_~E%a);UR1=rMzBS=1qsb9C+*y8 z7I82q;4zp}M722u#ZC{3=u;{;Em%zS6GWRu{g3^Fg44cW)iu(3Qq+s6Xy)I>gfWcQ zRb+mkJkz~TXN~%>+~-ttc}y^qEd6L&uqf!qWTQ89bu%7`l6*u^`ZG5pDB`r1C}m;L zw_Yhu#)Sdx(#R-dl-5WoPY7lvN#82*tPW4TYUY1IYJID$UNi)g##WgRIHE+48fL%# ziQ1ghx7UnSPenr`t*7W2Q$H!sUFK5~xG~=H4R3Zi*Pq$-J=)qV*rf1Cob{+Z7D~di#F-@yugV8l}JEY0C7mP@g&P#Zpkn+1*GLv6Dl9XymkFdsd9(DRG9lazi(tubS@ zEfiPuGlOVJo1fN*7W<|5ai$FDZWhc7)ICz?y9t{g=-~;!?`<_K7}Id+CtvjaIYO|) z+bXjnfZhLuivn@~Q;G`WW56c42*!ck^Hu--Vc+8oF%Km1l2@?I&3R|NS9@o@T;|Q( zxNfg{VS#~?_eID&0MS}`hc~ky5atx)T>*eR8n_B@GCCR@FdST}Ih4Y9mJ|kE%2s{$$NTJ$`s}OE{&=6MXEl8` zj2Z8&r8q`c#b@I9f|_qX(*>*f7dgo47N zf7gfr_-UVK0+Lb7lv=Lg(L@>ym`rc%eO1ZKKI;H{5k6`Ra z;Q{4vwo%f)-}A(y*z9PzXj=O0E@a5q*m+HH{#Q@cG`(Uz`mCYXUir6~3}fytyYBvN z_G$&+oUQ40Wi+2}_~3w*6b{ojs27rN4usJ7|_{Lns5GQ~XIoMtIk9Zf%DiY<8`j zqsl2T=m4!vDIrAUm_21?PaI7AaV9>3R8N4Y(c=Lprbn-w;7HMkLm->+N|Rwv3;p}V zlzs)iTIuDxfJSBPvgEL(UfGzL^kB0A`m|t@IA5lj#D1-)z2EoBZ1#uXh+*OVqLFX0 zQBjBMsXM8{<%^U{Ko_$&Ets5X-T?pqctpe=?Iq&}qZq6)qIFWCYu z=92p?6^+KG>5W%*p552DlEmtyI_5$^w^1mVv~^|^bIuqFq}oTxAy%4sWNrt=jmmsU zlW!f{85*tTB##A1EBSdoy`iN3sEf8V2hWi7Dyixo2=8i&05;s`1jZ!Po{}7fr8x?9N9 zu{|8CaG)lk3hJ)er1t93?UBO2u-uU)$tY6#K>y9w>=?*(Di84AjOMvz4DMf)wwO{!>$+EUgVdrykbnCU!FFXxo?nZ z|J~X4$;8fFuEzv>?+NEQ#$6!F|5q{~Uz7TN`P|LR_BL+GFONTb>C?e1<^e2l>3U#) zawPM!A|loqMwZ`f9h2UGB&1Uyhl0bHP?*tPopr89kh;z*YP7glF5UC+(@BSj8sB2L zfMDV==}4_6eyMsB8A(87^ghA5AqrjfK1GxX8i z@oTKG6B!GkCCwT0&O3f7 znArvAO_F9$6DbJ*8rdMkyVRh><>tovD=oEr3^j)!mylt5Cmhm(M3f`7>2g~`>M*lD z-jGd64_9oFTzrR3wG)(0sD;{GE$BrM60Rsm(V%1j=460ULo4^;&4KhZn zwT&tuN;I#UH6VrqAgacO!_KjBtZR)M3*^=dUt^~iGy~ftVxJ^%dO^9lwy#h!yXG;N zo&25j8xoITOC=@u!;i9&Y1x6tMOa7t7Cko!N?8uDv`AM>ZV8`1G~QKKdA@m4E` zF@ydGLf)4(iDgSUvSL&ms-bC0Z5vO?g&_BK9*|kf{9pUQhy1q}&`yo>{r*&#J2BNl z+ycx(FE!ufcrA41TmWF_W4gh{N`!V0+L#>lK(k-dieTF?dER6Lt(j2LVU>MI#64@1C6h}Gg{MMLJt9|=9a8o|uQ$x6?1i|esvwk;Zcz`l zhzsyF3_ZaZGC*}l3bmdPSjiF&8?%er4h9d)*+?2*8RRMJ{p2Y@1~-kC!$ZrFOUZG+ z0f%}#9y~#!*DN1>hFYntd}5#isZ@(vs?GAA-`dL>MwY$8q`dKp5S>TpNk{1-s3%>7 zS0#!uxDHoQd98)z+}buflsCG#zYU#L2IEJR!y-w!#A!(>Y!N^*LPGJOYiPJ=!U!;$ zL?duRd2u)tV%90-Wo?&f`8)~y6Jm&xslN^^FW&Y2Ym(B zWLKIS>_KN56U*9w<0sp)Gi*A}{VxWC6By=-Fd)sr;KCJPu;5IGlK;hEaP2B!K$?TW zLo2{wiGzVtrUm7+?aO6nqOXskK%w%KEJAc z9@T_)2&%HJH{TWoSBwVS@=7EgSW~^SMc+p(LeG==lu0UEl_|Asu||fb)NEu*%?fWd zrc}tZ#FruS>)ae-)MT}xgNW%hR>(Irsfu({!}2CoC9Y^vtuj_7RbVD_s%5MX?7AzC zaMT$@jUhw^Ci@k;zE1j=d|Oz8^3f|yGr*>wz#;3gyf)D?&^|7~%$z`AmBgxg&_>u( ziOHeZijYzt6=xngiPt5d#qeDvXg?XnwG^Z>t9wZzI9bz%PQ&IGq=V*9NSALug9~1% z-393i?UG>aT4`(7u_h;^V9@fM$qDeyReu~uvH=X&sDJwnJ zsaIF-)T=9YYT4>KwKN+*>eg&6Ahk4G0a7Gbr>yi?r*37*tN^K7vlSqaFy3C*L~I#y3` zh_y#P(^tWYiltSJ2wACITL>{9Y>)ORDNm?cOe8co@c>H+1DCX5J#exGEU}~vt5;PZ z`N@Bwl2l4bCCcp*WR9*4G}Gqc1mR=pR6?3;&loU5`8Sz-C_-VRk!2_u)Kt=et8nP< z|-y-s{0{gX#_N^h7C2BVYy-c z#UfzVHk97dUaaR{tj7z}-CwA=W9ZMGjKUtPL2Y1KsFnMDR~md$mNPBX$fPPUE%2wj zU>*jfd`oGta)hcuX|LSVmG+h|?Tt!XEnaeEC_xY132Lu#6QvEhGEf2v$Pg1Xv{BNU znKu0ujFVnvJy!138YhK=f*l5VGfkqyX$X%%xH7;N*Z{_G-N>iEbZzSA+a4F$r!X<=WNO%DtpL(*V+V$hPdI{3#KOIP@2WaH0gY1(r%#96%Nm@-bQ8y^&D z-VPwI9;Xwq4hw=gAM~&!Tk0l7VR|g-+CB}gnDGe;ly9x+64`3syIgUeg{J;--BzI7JLE6 z6~9EsY90>Rd%|K%XlrA)Expeqy&g^}>=n7(w6_s!-~$IFb~8*0Jc4D&9Ei9#kiq1| zFnlm0+E@X$9B0X-hJo`d(UH=g2dA_rXJyb{nUmJGzk-wIx;VdTrldV9n-Y|S7Y#Ra zjD%5t*eo^!`DVb)Yf_o=p&-%=#;vKrnysm0g$E9}G_;*-?<;?(_U3~K8sOgkAF9Q3 zs}>jk!CJh(YVn>wSc~%l2i4t!KNM6?uUf<#gwd`fca9;OotO9zz|=d;zz6EwN|V@7 ze!p#EpIMR2^l^V0`VLmqCjY-=bX2I1V6!qETB(-|>0PNL6hkw9v8M65bREHxwYn2CAXHgK|#NM46Ew9JDLM^z7bz@rgYiJlQ- zJ#}DXSw&~|(GuWbS;!k)li6?gTfIK99wa2BU~Hl=6>sDEy&Xrkd|cvmc1wP9*e%78 zfGV|qis(gaagpL4PsfY8-s{{_KUT*>(~qJFsrB*Qol~Sv=dI&o)B(7tHtEMW+Lb%O z@2Wqgyikb52%VVaFk`XN<4{;tR;0Kn@=Oaz@!QBVH^r=KJqD&v>N7PQR z^U@+rlNXdtPAe(eaww1@AlPxHH71FyRkXA~a+5y#1)xGqwzmW510dYPg;SFGfT+2L z6tSi2LchZNQZ)dK4&|wHX7y75o0bR2Nf@IpSuko1^3!jd8IDTHhj*AqyV4F`tB#`!TYaZn9rF(}j7#?HdW;kmF$fnH*f92pwr zu9H6Ge}Qv>HAFVXRo?$LTNTihFOxcO8xLo17W^H#G30-d;6;!1mM5${`9T!S2_Uly zEoBpz(ja9T%ZNN*a49J%e@zPId+oyS1Mc}894j9(p`=adJiOgH;3Q-W$&}YtEIF$$ zXD#zuU=^z*?(5YXn>lf9S|?TrD#Ug&bpH;^UFil!Tk|qR+Jh$R$s8ym*~L>Oav(w& zvbz7|;^&uNpViJ=X(O!1+&PL$xYgu3$fS6?ppf^&KlbrKr|xp^gM#Ai`99$H`?-B| z3kX2~wFvR8VnSHhhHId$5T;(9vXpkKzQrG|<(urV-V{5nvpDWNvAd=FmFlEIIo z5kKFFTOyO{(Ub!8D*yUNNcm};33c!g$B zc?2q;se08+iYfNW)qWO5rYOCU6dPGOLg1fSk#l&pkzV24XOIp482t}~Q(_%$=ioN4 zLgz8KVG%6X*oIX}(H`iRaLMN4z)%3VXb^(kl50=R-AmnJ~82u-cc2keWcNL!#^ z-i?A&+BjybWhd*HDrPvxv&K!;y~?1ux?wO^(2S_OiFV$p{y{)}DND_RdA({7RcDsG z;TP*E6GYpAQXm9=Ji9{Hqrt&U*RRR}p4ROMDQ4>G2x){;btA^WPRDSi35wxI*1ZB>9aK<-8Vi^Gon@QodW&(^D+` zkbk2;?3#25*b(Tqjz-M-5LaPAlG)_GfD&M{0KQEln+E9uoTe~y&kwt2oiay90<)$~ zaxrD|xpf9GNR{6=sXpaDiqxQ5Y-=5@lR+- zYTn1uxU7k~)Z{+Pb_d;n!!gE4>r|6AEw}@}q;Dt2t7pn0=$lDu<3t?sVIEW3}ItMX423N&nEd4#>kz%58&!#%{Cl?#1*`TwcQ1V zRMs7OxON8@geXD&Sx6B@Jod>zrxu9Y6lvYmz!T(^YKBM#?`>khH=&T(vDEnR)PnWH zvwmQhA)-ZQ%0X2>e$ZW~7I?Q9>xfP**bcwkLHE_1T0nm>E}y=+Qwzhwm5k2hvIzgc zy6NIwNjXQ{E|_QLDTEp%7L7O2PAhFTnpA~$7Xg#4Q!_AsV5yx1AjOHj5YKV3mj{Wx zDm%D~pp4xqhzN6o{73NzFjbU%VZYT{GvE(TR=JdSbFfN$h=8w^58;&1%t1c;3yJ`#od`4x z7Fu<_CUNI$0`-COHDdjz6`EoWwJm3K#KOcly^+=Ns<~#fT!qz<;_f(u9kS#JES36_Vg3B56@N5a6uK~z-FUGKre^2ZWjqkhlh zvWXg=q4>|;(KXBf42P)X2-0ux{iZdN2*(_RZ^oFA31x20SXh61kHzM0SI20wP(Z1E3oEef{XIEH9x@~MSluwL} z1dSIie(a~Ph8&D!?CShSX5$IOg)f{B{}NXjxf4;Q^3^`)mq*J#sGMxPZh88xzO)BA zKw)Q-%~Cm@4Ra@r1T*u$Wt~&HDliM*+>a&^s+2rU=I<1)j|t!3sk++eM&Hh)ieZwv za&IUttfNHWnyGBoa}RZ)DIGOmfLeK@>3?c=6mJ4KF`hGya`Tzo_*E-6k^R0V8>hv)q?urwq`(Oy04a{IBJ1b7r-d`IDxO z|7vm27(Iu{M1O+Uep}w$aJ`MDzHRj4_ZaIe-=V2fTduJzOQufUVEt~_eNJMz9!#;P z$;+kL!|1CRZ|h8*S|=@mwp*;r$gzcm}L}8Yc zM<`5_a-l-@f>RZ?;3-1FCg}>f6=Si&I4Lhz7$xPE3hPOEokF}{uUE+NpQCDo_`%(# zXR#U*dhIynI-wBon$|M>p>rjclaSw*<|`lJwpv8g4_asBe(q3V{>A%izXy`W*8QHNkL^pwjJLI zL5#7wUILI;LQr86&Pbw>7It{s#30*3xCSMUWs@Ya^5qj0-m+2MGlA+reU`q&!=5w* zs&U{dK86BPAPWWd$1_ax!VKzS3SGiDe30s|dT>^cu{Tn0R%L_&!-on5_P3c9P4N2~3$MS=wn!Jjo4A^nfWNr!i$USiF@OStfzj#~9f+r!E;5Ho;4~$7m|nv>M%1 z3>TB8V)&q`7+ZjE2EWIq0@bRfqSBPWB#uvndpRTygJ~FcLDK-V*vW0_uJy8gYPHK& zi}NiH>nXbLmThk|tZW0Iw9=?F=-i3#X0ogwx{aBP0irJ_WWTs?fGL5SVRXE zRNK?F!>JiEBDmm9a(!cOFk=_ImDIg5vfw+?^Fnrz5+4#fBw2*!rA-Q)(;yL@VIfl_ zZZRcyPPuE3S=TOuw393q=8u{429%gqMV{FI2(%+2erx3H%WwedcgXQYrWz4RotX;n zH_>=0L=u>(&-dZ9)Rz%JSGCD7D695{5kVX5_eSAq#F>z)7Dr5!vJIIi_fWBXdZ++; z0|R%sZf0Jo8lg>?N2Kd6FV~91<_H8?-F8eSU}qjbS6t)L#vK^?gO6Qwe57s3FQ2{a z*u$&ngZG_rU^FWWDCJcW_vPNKcIeeSgtkkmUb{Y}?>l2q#7a{{M9Y$iC*@_zYH3eg zcJP6*PTFuy!m@*pACJz;LYL7z;4CABX<5$cmt!pq%PWUXK5*X|XAOF(zE@3JvYH$g z!&ERR=0r-&!(6UdK7Y@Nq268LszgCo0j_|m7m<@X!5slnwVA?Ut#{wsM)SQQi_a8~ zc3%`=Z-%M3jlGu%bWHOEsD|I0SpI3bDfIk(TTdAX?z*i`IGYxEew5Fmx2GJ(0-oYA zj9mi>C|aWV!v!qjTs`PSxT6!$29blt@C`#-GX(%!V^L=@{e|u$?3jN)_@(aJ-4L+G zV3;3xnnP;#o#fIrg4&RTz%p2cgg{aQ$C1PO8{w3)@}^A-|Ea`NEH zTdGyZxpwcvI_lTLdFOpwe-p0XDXIqYD3INbPhJQ%GwrHTN6sVTOu!_OX`Bt$JOP99 zPFZAdj>Z{B9t;bsH%_lH%r+c}%80!lzNz?}tKjzrd=4l)zPGKpUll{UhTUu&z;20H z<6?V<-Et2r@v}mV5)RA3chr%ZZ+XeuYEJF1Z`LZ_Mha!$S=pf)wD zR-Dg=&MfrWrNnXh6vYhN$8{N}LlaG_w;U{QRfB`|ZvhW4ztitGX#Ip*}p6vbsllYw4VYC$7iLP>`h zq;1z9h+Nmd1sd=>QM6WGKPGaSJ73jHw0J-h|51~ttfRoddZ`}w*VI)f%nX;wIBz(< zn#LCSTCAp8i7+#yvoZlgLRm=6Vi=B#S!-Hde2A@U1uP+H2n`%_m9k}XD7GY6Bzn9Ez97wponZ#7xbPcM zgq{ueGbl%OeW#YQO<90R6Rbmym+A}}Y3{lahf1QdkWYTBiRUX!+iT)6aoaJA)zYvG zbzq~&pkr)a(T;RlWm9v$vv`-bd}OJXoReW^#}Q;Z(!N&s@i~ z!d|DqH<#{pq}hmyHVt*?o(>*?YSa56`_6O&Sr5WrdC9TgPc%4EOoeQ5m}a$2(gZH{?pqDyqf$P8ry?2vcOd+#ShWXh@pQgsiPz|MEM$4|fHVWZ%MTo+> zLIT)Lo+(X(2F+vBj1>YX&Szf!ix>|Ab)w*?0qxr*Zyb_hed^w4`v8;>3ek)&37`|w z0*|zv>;3^PRukH`;}dCy2IbARSQRgtGy6@Br+74~0Kah*XI@tUFqVPtW_X2)U%&$y zWmMI<{g88DVOq(+BKrC&*5dNpHfzR$dFbPuE>RqtuA&je0i)4_L0*%hvz4fn{QXnmc}29R7Oicwj78IO zpGsj?3K6tS*=+G+Ttk!A*jCTf>(3mmefLUqQWq^5Yh{OppaJFe@PFNk|Km_lt=!Fh zs04nAsnhI%JnBT#T}9h;tiD(N`h2#Osvw_YP^0-gac}8m-g4$i2UbW!Zg5I3`O111gfn#6`#VQ*i^0}Gw*2SBskZZSovQ9ZLz#(L@Rh;?T5u;;<3SLf& zqlsG6GPuzudbO6AUB}fY)P^fEbGi+k3ScF(K$UkPgVFx9a=*}^TSE5jOTL@W<6@WI>Oidy|L`riV0FDha5m3PFg-*q8 z+=^aEvfv6f!HyeYwLmOD2y_d?g30cwaKW@9a|dx^pmuOinVSVdBA6wg;1SmwA=STWNRBk!23OI`C1X`}V zhSeFzF9`cUlL5Cq)MPMDksg9?6eb*r&N%!cZ95}7VjG+$!^9Jv1r&Z&4?-y^PuXMR ziftHX6Ml_7$k)QMRrnRZNliw~psc6rwUgym(_M#c!`A+zy1Sw#W3&ev>~v7v!HyRr z*d;=SRrN*KG6Ef>xiQN2J3v=2r8$}8Rwl7@ma|Z#(oKC>0@Xl=qVH74Vz{D;;nFoM zV>%R6D*9|+%bn*0EuA=R7}Xk}lQ|)*NU)rabU?5$O`Gb`5iF#?|K~bV=h7oJSh&9|nlxkl^@Y6~6K$@aJf-nVk1PxID zOwqB^^|TSfr!*i=qgA#hPV>sua++?L*>(s&XGW62!)OO|YVB$V)I(*Bxssi`tPR*U zx?(Ka7KO|#bUSo<1JcbE7gAkWXVik&3VbCkuV7Lh*oJItRK^HC>FW)rGfQ0&?O0TM zjVF&?-Qy~UyaSv~IZWw3Y^?pmI3Y|9Lsr5B!``4g)wtG%0rL+@EhZ<@T$*~7{HM74+Syjy*1bgV2Za7wTWmOXL zz`x5~3StsuSZ#IH!^~&QJ=&0S567 zbWE9S-40y)(v+8|SaX5Uf3zahcY1 z2IAc?smWVo%z^k!tyKvAByr^Y?=G;WDLxfDrq@|*TWh1?F&`qeWfy)}Yv$JFR6Mk$ zh7;Lmv{*Lpo3PWCm2ae2GOsWk(Gd|a1K6lBm%Jrq6T3O*;k07dX(th*B2zZOnOILM z`-_R8>q`tZpL!0tX@x-Kq&(xkTxNpH4N9amO}kWjQpj;45S`RKxj-h|qHDvJ-GDY_ z`DgvFPk@K;WUkRDusu*gT5eWuUUXDPe-ey=>iWReQ~G{Y@1NmQ)(j=dfU5AO77T!6 z=VR;y-n-XI;fB6#P&7c(3n=lk)&agZp|4ArKj0_4Atnr}NWMcM9RU#oZy>W1I?_;z z%}pz ziEkD%Ee9FHEQ5@F0hiaGnV2M4rg4ZOh5NR=a>nWn^T!+ZfWV%Z;8*Dk`>FAK|o+4>7vu-*QD zm7tT^iZ`F7!!A3X)@xKewlwUzsL}Z~pjDE&ZFHckrUPAETz61#TG9BTwx#mJGkYGU zIr=L#SR?blW5*4R0}BD-U&!c>`bjW!@Z+F~X#wGoZ8NT*%F=_jDqFxj$|D=p z+@5FM9$-0>eFK|!?g0q7(!oAW9qOAOvQzT$jGB#GNFkFPUHc@uQDWQl>pI!U^wXp` z1Fqxeo5$S!$4N)yUTD(Y5|0iY#9txTinqk~W8D)ESRe-ai1oj3xn%c0-`P@ylGkDp z6h7&iERBK7vtk;s>76jM+oUL~;0s(TXbxd0)Tl$>2+=^N1y}ez0HD}XiqlF})b2dn zh|`+G{K@uq0fSvFq!uyT4X<%mN+1Cv=?&Fu`D*&LjL)m82P=jj7llAf= z_Ay0RbZAi3WNl`*=7|m4EZ9b01rG<`Ug0tYElk~)z!KJdMnO5Zx-*07dYl23o)BuM zfMYS5zo|v2z9W+;Ko6?`kyF8B7ZlWK_Z35#?54*;5D-q#jBPzm2w_qusgXfP4e?cE zaw*vcL?^Bss-^D(8wO|#mLhJ!k^n&nL=cFMZieB(+26@IymrHGl3Ve*5;CmIsvQ<~ zMtGykgR9Db(R)I>s?1_`Rhh-?sxpfex~fc|=aU(L!F`pPh2p?BK&Fiy4D?YO!@mkp z!(7Qk5I}G|sR*_#=AFduF=?1qggh%XUoY99%4ejpeo|4l^!1bVRxA&5zrnDEQLU4c z?(#YF4Toh_=SfA)YTQV-e&pQxLC_(%qry6Uy+fa74VYY}*Dt5bfr#ndSi$?erEDV~ zcPU!wVSa_rcM^2y#@Oqs82Rm@W(XrDJa_hyD}0N(9lYLDTzB13MK%r&Udv(+?V^-W zfhftN6V)PYLn1lI#=+|qv+=wtnh85;gtNZorjAPLOWGQeN4g{e76zDa0Zx8;LcUeN zZFLF?7feG$qJNt}-cTJ;pq%p|zi&tR*ndnY7HO`PyYGsHN|#pEBy-V%hz1U0rbiH= ztg`TtDe};P{A|C1pJfHGx^K$9*9#8jA0LS<-$v2`Op|pUN*7|)AT4(9Et6B8eS>o{ z7`~7$OyA#a+4pyeG%a#$9JJWh?arR8n(rdB4=Bl6muf2#bZVH|pf>uZlTVkHhKq2I z1#Y(8RSK$VZ>c-A8%hGV)3>$pd2Wg+QB5&08%(j`)NqPRI~GR9Y9}0IWRh3TC{2Vr z-8#NCio~`xzYJNNoZAXPVXzZ`ZiNwPPPr)@o6HrbNT#tTO$MXHv2XCq@XI3@wf>ZQ z&-F#NCQX4`k>eck8vKvT?@^nS(GAAh7#;{_rxw_gp499gp54Pi(5Bxnoi&rvX2>Lz zA+sOrHp#f$RPKTtx`0W=%eND7c&QPQFK5@#OWO|z zFLNRMo0%`}u9#XnF9g1tB_y z1nh=090RQXpqr=w+zbnYw{UYdLXQ9)r?t!4{F zmAg=7mTY6Nc0G$cRP(v9&WIP-XIrq}3nZ0>TLfF!N11!(6UFtG) z+q|i!$of7sxxV=)SEODno6}RtxAJP=LmjqOikh`jt-X~@Yu&oHrrIOz+_KPzT(It! zkD*Q0C3lrGmTdvBs#*{RE7@>_wG}%97=zhdN2^5crH1UYX13DPB=8HTI>tFg6fSXrt1;(mXQQkoh(oYZ6qb zg2EU2wH^A!hILoJEhy#$`gD8DesO;wt~A!2UK0qo(`!8fc+`mmhzYoNNKC-JgJTf- z#8;ODgg%I}$rs?MC(KniE%-9@bdP7B++~g=+_*gCx*zWHe`Y~ZIOlDA=ScuVaD|DL3>bl8*50B|? zVziq9#s@w-7Hq{g$Jpr5eCn%X#PrdzV9}QTPQ5?kHa@;MW;+@K^Kq!QO^C0KIknU~ zs+B`c1+S>LrzII`kX;)!t;uT|y6)`wXh+3d{0>vUvTWjVZjL&2i&;vjif-f5|C-$Z zl5&qU6Jx(`Tkn z6!M9M*Z`18J=EmxwIKni$CuYJQC&7DuVaIxlX}QmDF9YJs;d61!&hpCg)4!_ zpd+%w3Kt#-s^BO1p#{)RD3=2D^?z_mn*31+`c4th;B`wYOWx z$>XxG#1T5Hq`fs<7fUZikyrc?+#o{&C4eWNtP?M!MJ+9$&WiZ>D4)RHlucf8&ftEK zU>1vokmhYVY1B<837Sp`u|!9ANAlpNlbkl4m`GRQM6OMDgf+c&xjNF8NVAx#ewyw_ zy|;1LVTrV?u9DZnfXCuW`7WJicwQg78J-*_whz}kX>ee+;%w3L$r$F66BDdf*dO}_ z3bqcLDb_#hR%WmGecm+aT|xMsGT(6rMc%7>Ar$#jgl_jp^_dY*ln7s{_xszT`u>p5 z{)YVl`ahOpmlIDezmBKXWL37gTj2spMF{~3>yEt(y9o5b_7@StwBN9bwaqv3*I>sf zBfP3M8Gl>$D(hY&^*p;tq^Zv?0{nL-T3{OUaKt(kwm48Kksk!QgQKEk z1ajVz!l4xBJMB|KAQ3dwA&4z_kn5*@I}Cjc!D2@8mymJTOd2B5KAbDh4Q(!b zX~}?UHME$qY8XVhr3GO}x6f08Z`7Q=DKN(yVE7#gsjb1#hJE)WF?LnGwvSbUsJ3u> z8!Lptr~AyKeK4a@yuX`0`gAbM zD0P*t2O}yiyEk7m)khH1z4^o&ED(Z<;gSlO#bU|WNcE_p(=66ai?>Gi=EH1A#z}0m z1Qm_Cs^&izFHFKF+^*OBU)q4 zh&EPuz?ISIkJ#x-_3v*6ONYM9=M2>QyvbB3zMb!x%+goDg?!6GPAKByVaTQ}Oh`BO ztr&QCrO3U^Bty2x;ocQ%?^1T{UDcjrA90~JonkNj-Xw8|Ml~|&{K))~vOBx?uA+^& z_pU@%49Fur(lz}Vhp8Y)$~3$8Zp-rSgs*SM<@^)xxx4z#kI8j*(NdLc7cDi)=NHTB z$mhdfV-^~GemP*{#J&F2Lu7=g(sMp5uFtaZC8tqhTi+UQb7Zscjc)ya{2Eao@Orr~ zmFrvM^xWP0pKopPIN8>x-;nxXj(`QZ!dEH4*hRIwzGZ*5+ zG@3ev-9^+`SvSQeO`DD21U<%0M^S3hR;WbHgk3wQsw-Kr(MJ~o`8Gr3{cYW2=$t62 zQSe?ecWxo=T*2)0x1J(Ryt*R|$|_2g_tG3W@AhzT3gI!BFtIej79`j0l0?Xf(*el$ zin{Eh3WiC2f9CttF?EG6LCI`FN2OV;qaz|p=Y??a$cA@@YJrIaMb9UPD_1Czi3{gw>uvfbz@5)8X#HsY?{z+6bB41>>aP+D#S$g!c z7nE0ABO5>wqLxXQr1z` zyK}3CRSam1XR2yqc~cc{&b5l6(~6ns%H81Cg!)H=fNPNPT1yaZ$A6*Z$ujFf#!;l# zl{g0po|U=ot$ZqYSl9@<-G1+H`NsGpRKr}Uo%#UsGGX~A0sHZ8RD@``NnGpzrkcS0 zG21%1Ry|RxEx{~Qv&bAG)Re2uX$H@=m@>Y-y6RaQOvYg5aBsQJhx}H41-R{k&kWvX z8Xp7}K*$wD_N7Dgh+2`1SZ{;!DnclL6kS}VC|V+0E0R1m3-jdW9dc~`5crrMUGMn; zh`{9uWo-6K_APc$$o*#&IH?ITFp!#Ted$BHyd2Y-=>e$;)rbnQ$8dcTUFIt^E=>M= z;5)Ub{3K*HEzHVJhZ&cTzT_l-Bbk`>c^Q?gOQT;OX!IkC+!5W~u9XLVExCXJ$!M+WH&&BJ7{1NfGkwFIaunme`wxRhXA z8qu0!fYt@kV7mZFP@$!YZG`1AIFT~oxrmN0#BBU+;~zs4coW!y5sC;02BNH9 z^U{?sQ7pjPjaz2d5n%?aX2>!)c45oOW9m2Kh{U+sJBM#DaE5V=#QB|T>9EEvkjowh z6no(agwRWNbk>%P;{(%$Ad&wKuzpgM#T+%txl28u%If>yhLMvsg|h0B!IYqzT-v|#I3&L#)Cs#a%zFui0If#+Y9d*#Mqwt<^;2fh7OkGf32w2#8a&;V}j#Kpq#EQ3*(RdL| zk_X?HO%(>Pd}qxsbQ37)f7e6J0IE8$g`gQ+{wCXFY^Gq*-~)@Kpy3##p-~imH~&h? zCh2A5+=jY7q~WwY2+z@roQlX@d|8`6#YKyg0F)d z`wp{`TP0=qEwNRlw3qSh9l6`Wj;qw%%h$Yb!24BAG^O^E%+uo(r}ZOrpYyiNV!F!Z z@`p4JD~wFWD-?;GS~J^(NTK7wr5=D&)CbA~xkuMwQt4*PTvG7xqT^s)VE-}b+SVDA z%h5FWMLxI6jsj#o$^@W&2v#d#hf~0mDZnzNpm4!77i{8!&5OVpgF=t47)|Nd%2$!J zOYh@$Ukl4#lAfkmAfkoxs3l+zISeVIncc*ouloX&)%xSR>er<|) z@L^Cy)2V(<_ptH|s1fVLvX%Q5e03gML#4eC1~_c_uu(H;I8rT01IFXlVC&2#%Y0W^ zh&o(Y?vcy?$}L|H0)zw1Ji4?Mo(^)6kheq@A+x)h7x`6A$&>2_4r>|9VSU&IxQ(#~ zh&d1tUehQ`XkFW52<8+giW`XHip-6sLRiJPg%xfp3O-B8bc-B*SO!$SkVkh=_D!ZY zRH3}(8?X0fL!a@A7Qr$4EJC1#z@j&5uDQ}ZZ3sTt$u){?T=3V(J_oZMnSqDT_-Lq` z=g%1Buh6zgP~kyg!xHsFUWOvjIJQn@^7Q>{7>Ta2O$_L1J)>*+kdFg|oz*UoJj?K# zE~lj%RfT4$OB?fAd!F<(h5H2Q|Ht0DKwEO1^__LEuI($i z0U@z|Kpsjz-b?khxZx9t_gi0V+aa)uH+;HLb8Edb5 zuJbuuJRN!Qa*2GLDSw-t^NtPB-EPLX+}7yk8D4CL-5R2!){RYf&gLcPcNDwB?W$ zpB>~2q4xDF(I9>#;Q$sf64q?p@)C{)Vm*J77R#r^3L?8n-*~qRcJ)1Rsz-*+%MF^KD8!%10_!Wc|tTf5xn_ z{{Bg7E_mn?f(WzK2$I7u2{_N98bNNf1wl+=g6-yUhEgmkKdbh<5O~h>J zgBRhE;Exz+T+CAx%2M98DUgTcL}Ey8ijgN?&CEb%?}za+ zFVor%R6q1`+Y97+NVS2BJMu(Yx80IL?9`Lfu@gQdTBe)`-oY#76JZi?xpoLC z#?N{3K~~MkiI{CB2D>#U!VF^g8g7O!aqK)SPH@V2>-7q%Zzc^&T`r`KU(z<31mdl(zQllr_g`q>BSIGwqD&HpU z759KMl~FWeKq)gN`Y6PyWTd)ZkXr<}xllP<`8jd6auPl(TG}ZrPh7zqod~&YCd)G< zdnh-^$}lT3hcqx@VTCjaD=iQ;VYP#>XqgBLv#KI2WX23(ah?dPY6fA=HlyEj2@9bj zFC|vblm-BabQ5YM0aFN#_g4}j8NL$INjunbvt0#dTFEHZkWRFN-b6cKRpmC?0pCOa zGnM#@@>o}FEwqAZh@M@o04!K@4Q^rZQJbMiq>KHpv))#MlV0!!Q<70YAXtZkrOai_ z-=JVfSDYwF)d{jes!ovg`Y?&snjG=YG!QV5ewzZkcp0H5SsjcE^tFt~QyQ~YNw)FV z*p^}4nq~~K89R8Y@iSL;QRfr@o)Mo>_YaOG^7K)}{3bRj z-{gmwB9*X<_Fp?Z7_$of*4SPlz5hGU>HWzENiMQnny?9!LoWdV$6%R+O)5(lIZj8M z4txq*N;V{pOr_GedCpHuyOxsYVYTHm%E@L2)W>1V1N4Bh=%W^f6vZE86uGgGVyA3vNGW?;A%ybnp`aOwvQ##dSzmF} zPzN25N{$U1H6Y>17MKU{j{O;sPD^Y>3;rEa)MASla`LLy3(+*Cb-@*AgQ7Tmdmd^S zUjdJ7n2nfFdzsGtbB858OVtM#LP^Kbd*5ht<&6wAC)!U3_m1BBJusVm_&NrbStR2_ zYmF{mgn%UV{}uqqkAe%up5!MG@sO5Qd(}Pk`s8sA^5jw(UKoKYz|qN=eEcI2f56lZ znD{<5E!Fc1CZi!>Vgv%F7BES8o&x;j^&Xtj3Mh#EpdgjW%uI_24nOGt(i*+O3(025 zQ^_IfMf*fGT<&2E7geV5s?(!nPNgxkjGG!LWN|h-P)v_{pfqWeJ;nH7dxA{g^r+Zo zPNTwWW=4epn~VyInMS3PFu)Mtt{Q0VNHweLSx5H8-y~WKGw5JUA5*}WsV7|x&Zn%( zju!-X#BYpR?urM(Ph^{?;1*G2mHybzMU)kVtUV$_{E2dA^Nzuf3XnjY~M0vv-Ejiz)&*T2F`kXg$AGc_FbKF0p^R`() zA(6u;--9ATo3%9;>WN4#o3-*pp-mBbnHpXFa592nHqOrgc$IRLteyur{htH4u5Jf-&M?*411k1G z@3??I>tZ7OM4xpr5eGS|4eH!S`q%QtAE@N$kyZ6u^TeN zQfhbnhAc%n+C-h2Z#{EEb|%`~enUoxBD{P)ge>G!K8v~}e8gw#aX1!-<8V2zd(6PC z-Vh-V-UpM#fYTZ-Yd>KngQ{c|CoaN;ii-%-H5cKevWmCoB5dS<@-;ERM!n{I?Adp; z?R;!JTv7Q1I`T}U8V7W)j}p+a4>wXo*DL5C&~11eS}26wfR5tl6Bk}*XXqLaSI|N5 zY54rhMB!g13jZ=u_?L;ozf2VVWuove6NLuOVz2pD6NTHDC=zvEFm;l7GI*rr#8#~= zkpf}8YP*s9K71UF6>7u2;lC3K{G|LRTiAFL1DKEOkT;@sy!k zX5|WopS9bIkD{iD$e2=)2;`?3r#e~i37knpeixmczWdGg{0~Kp571m9_jXRdeJ5R*qm0;{)7Q`OjFyIQ)Js zVB`vGpTwE8VB8h76dhYAKZ$jvlzfh`MFn@SzIEI?jMB{S!#rl=NwsQ5*!I^obh)@*>+H$i>fLKo&b-4}}YmIs;{h_msMm?*hMeJn?t%SF0 zzlf&!jAExtpbE#Xh7k969coejZG@&8oC=Ca4MV-I@*&*N!DdH)rXi4jRV8sU6geHD zTnv)RO<9Osg*7NV zth^gF$L{hIn$JNeRv2Y;=13SfcdCqWzEFCTy;df1D0sxr(|9bDKSYt3Uuk7K zRbKg0y4Om;cCn09F&XEpkoD-I7w>2w#{Fv$$8muwn8g73&D!9uw|j)2ZhZ>rxVha^ zHgZ-x;HnWMZ>UFbL!+`We6qtmesvJwpuXdj0Mmm+J&bh=h|fNBB+)2#7k!5-!5#a< z*YZOaAq=T|55*P5CxZW)L-Tt`JrJ%%<)w-$D@r4MJ^D$Ks~E7TPmW+|Vx3cCR2%*3 zo*Mh{Ty)w$FEmM=aNK~Xr8FzKPT+o78;S%Lr;3y32*<8|!kNX{>qK(i09&on%5~#LIx<)m(HP=Xsvlv3;V$fXUEdUvhtTHV3JlymnesJeM;wYrJmC&a-hls?gL&( zaw!YGaT;y(!madySK{xLx`&$AJm!NRKa8;(Qw%qfd|B=G38Nx$bW)O~`8}nTpb|HH z$O}Nh)F2@Y+$=h&p=l$H|`+= zx-v>^ZC8#L^n~p^1KJDZ8Q4tq!^tX13@5)fy8%fK9DpDEeh%=WE;IdI0Ivbr!tkGE z;0v~8GDx;bp^PSiSzX{!1;MN?;HF@&5FAz?{_Zmj_<<)PgAD$*>I$zj@{A_j|Owy+bsd>ht0eKkWdlm7Y?GOh_G@j7Rd{RW%nXy=(;q2lHXcqh!}KZ(QGA=30pXii z;rK7J_z}8AaCu}s!?7);;H+~{s2qf+O+@v>)ua_P`cC5Td{^19&-r(ANlJVbVBj{H zP>P&)mQgM-cL_s>%*v8%nUJEyO6||z1!taDL;@T3S;U})piv07sf46aI5mf!mw*fD z!aYNQ#=%f{Q>_V!+I2KRzL+2xk1?_AXym6jK{y&YnHD)DJ8fkF4QF9QQ=XZp(ZD)5 zCv-piJo{M&SF?YAn*CoI(5mPvn3bc@fkHY!N=g!nUl(qG?38liLt<2FB@SCBb3SkiRGK1^IjCXb6~s&pBT}frBDjR!4OR;)FJ!HoHX#^Ae1> zh7iu0-l=S7?^NUA5W*i&oFdgSC={OrHk4Aa*6bVpLqw`lU|jWp5Z_G{JD7Z2 zkwn631XLdTs{GJo3CKmoQWep}xzEb1D+I4xOQ-NDw#q+vOD+pPN3mGI(5J#BzN6bq zEpjb!penB#b%>^T&E@%5Vo+yvpjfawutf=2c6vPT3(6;+3_bd;-$?VRU0L-B%5#&s;vD_^+<6%mi-S8HE+Vpr3?a$THVK9L$u`^w#L zvV5YP?wX;{%IV+Doa0vhF-KN@mVe0cN||uq&gz)Xd0ETFJ`N>?hLurum@@0y89Ad@ zIxNRwe;kg);V3=MuFtd{!Q@1JIl0>LZWH)TCUcLuw2E&AR|;iSS5>L?)VcFqyh0%x zNT)7_ogBwG6AevLTv3iG4l1O+c~w=?b6|zb8?(iFe7E*6wIIDhrp!Jjk~0QLM3oQ2$y}bnc&C`A z8s>0~S?3Y!)>cq=Ygi^)q>U{jlF&uTLmH;x!tI*X1YL{HKn}U5ESq z!4~WU#Gqtzh4fAvnm4n;pAapkgI3vN0psy2Q!W%|!_mO6>B2r)`$tJ)l^W=bmv|A$ zvHbLlU`5(za&e>_`FY&F#zv^Dm&fhvhrdXuEcdAt34BUPDjn%z&H<5cQv67f9@Ufg z@*51jI?Ku1=+q^NFEc(-KO7@U79~7~D$jDbvO7lGfxwstTfhCRQWM$*#3061_3^?a z;QFLQ>4d*yZU=8EpUf($@uY&|^SR4*Vnb52=}3csC+n2NNoMZX%q0a*r=^Air_JD& zm?$vuiD{|fh7zO;3~I{Z?9h{`E_#A23>X8=7@XGQZp2-EU^%MJaCYl(Fb+i=*5hz2 z4#)X?l|19dXNm(v7RQGWG?Y8vPc&69!lp2W%f|)n<1A;6?GUJR-mwvomjg{3Wha%Gq`@e0u~e)T7~~DhbGWqagy|&h%^xs%V6gMRL(_dNkay9*x-^ zPDWz^<_jq+0oyVg_K(aKDJ7sRvq$VmsxcaAe}IYl1i>SyME?X)M?LIivQX-g^xdr& zXpVgh2`XRUFww>|?3Bs9P$(^i=ZeL%)T|+vwrRyoD_T{QXOWo)A;2)%6X4>TtpKi+ zzx@b_rBpbn%3!XR{|lvDSB59cRTxRdR%_8Ajii~MO=fr_dF+yvbL)pKI!I0dWMG@( z3cx7e=`y7~TlbcGHt9+GZq~Sn-IU*-Z?feIc$;vFJEcKP0IjpwsZ86Tj7bXnV#Oq4 za;EBpQ)Iba3OgRC0-V=^bE@9Rz}#WFLCqZoA~Q&LD!)b-XSqXaI8BdkSkt2@tl70F zH^L?5cB!z)7&uGPU$1BV3TJBlj(l@Wt|uE(QkdA7^xieTcr*7&xf>RHH^&DBXKTEd zGs>lsYV#l?E&}3$Xo?wgaFZ85qzi23s)|um1}P2}d!@H+QYy!5s^piUO=`h9CY^4M zm&-qYOP=!jmdiK4mH1rtDl&oq)9shaMJ5HoAvUH^9*y7cr$5EhOXXYNny+VAFd3k{ z?XAjCxG^L7VMf1M(vyv0y3B-<`e75P#$0Lw2R00SM+>p0%-%inIVhg4MCfeOS*hB=Le$IS{Pa`u` zq?un+&n@%Ra^oqav@(kuZ8lVroyVrzjkB^K0TQbcVTa<-LfgN1QNeNko;j>qnJil4 ztav?&9>+&BIf2mv9u;1?1#8zt$S7mT>SCm{4_$dzY|WwSI67fUD;Hpf!{LEI{;RI8 z@XFiY{#JYmY@q^2o#KU~tT>|5_z?N*t+8H$jThy1(S3<&{}(0*i5S^w>ACNAuPIqrL^EFAOiXh>svez_tj-biBY)XNeugax8>URZ(F@>2M?rL`4OZ2~||!5^xc=bwvgC?2t0E5;PkX z6}UN7QGw!JRf9Aedj;HZ1L&62pH^{*e%zP=Y{R)A!@G9HfL5gCL!choMD$TPeqm=-cwwqEH3x{-ZCephD>Pi z*(yK9U_DMp%Acpo2~3MD4o35dRskM@i{&qEAG@J_u~kG}mN@j|FpR^&I23VMkHfJz z9LE`D%=$ZBOu~W9_<-rs+u6aW zGM39vjAh=Wax)yDl#Of^e0G$}jj6*zzyq?N3c0jMks7j3iH>`;afujWmebh$>f(Ky z<;6dbl{<_Q>e#}jQ+)cY-~gKR%3QDHgqPf)Ki6q16pmlztx))Jy|zL*55p20;QVWh z=4-MnH7u)!C#!~bgTUQ{kbT7!Ug`%2ho{gf-hxuad>%mh;=J@;9C6$dE6Lba1v3`J zv3-r#d@!V%-&p4u@(34O@*0Zdr@21AS-p-p!qAXb$@A)Gj|o@XAct9-c8LnMImAD@Z@P~JLS_8YbaRd; zPcuC=2~XbTy}y3g9VE!&d8RGTm5A42X4?bFR3oKOzlYF4rX}gH2Bi7D)M=N0MB!8P z)I~Wlk?vYc&;EUp44KCY_LR|7a4MgqstS>kuIVB#xVj-pw;%|PFq3iFA7PfGFX=;Q z=`sJLhpOT!WvtuW;Ne2Ewn^a~lD6oQIytqC}4Xa27D zjJ<5lLfjJL~+Ov5C4I^LO=Z;4HYws{1t&i+MAvpl7H#dFLtqH?GvSg zcxC?DdqfXy=wVq#d29HW`M8I^3iJ>JGD2}=Q4i1PV_fH%@j~@f7I2i>5^>9m`YUY$ zZp}9hN|c=hKDq^ORFWL9!)y0;%L(*I)!{AluSd2wdxz?0-#@k5KwVP@2meE0Ft0F3 zPq$yS#K&5%R7u(*e|fwAN^}Gr^(Xu9g~=4-q>Xyn*U}BHspxgvMX!IW#YW~)k3$Nb zD-7<9l-b782NZrxQNb&;%LU#-V-A>wis2oKq=N2|c>hHO9W`4rC|1xjWwgpedLOx= z_$9jxCUOfqfmI%UO$?~tu~`BtPsy~7UvXIl;$(Aq0hiZ$X!(j<7tl3pHqy(INf_IIaz1*}E9=B7~}_JR7dB3Y4@*Q@6&$k5>^9;{#B!}811 z3?0B7{Z)08rZ+?zH$CE}V#Kf1RcfeCUO+-XyrJk?+7rBlVF?a%KD~?`1Hazi2TOXe zgYNZHWbg&&Xm*Td)tjjhgthOx`-eZ-)|1@2 z6VI}TqH8@!j;hH}X!BkT#jj$I$S`9p7SmXy6Rq`AKrQZoeicnk%{2EKC-@tyJB$T! zI9@BS1RcHUD#sj!wt%}xa1;9nHvxG|{W9bX!vth~T_E2b)bm9IS(+3e9n|m{9{$`t z?g@|RZcU(YoYD2o^3RM%{Vu3oGdp_R9 zO_&?>R^Wjge#rAtd2;$h(bM*=F6l~Ml?t;I0z!*S+#x$!%6>qBgupdd^(Su89~Xd< zuDGPxzT=#UiIQm5B%d|sj7~K7(;dlG^iBgj)$YPWQ zGKyaC=QwTE6(u%g!#kBvf8wl#jK;-NUDlwqB%d%2^aq9Y4yMQxkAZVe@8YQoSU#Fg zXAX<#z!!ib*unO92zeyy?IJ4* znE+z>n1~Xq%bV;CnkmeJwW^j%GzOrHQohTpBYl)_t8Da}D4!4y^N61}B?2GocvM=U z$gas=LjAu)+}JA6sma&NU*ANUXRD)sx&Qvx_>+r%Qg2+3qx>;hS^j>0;CLmB)c>1?LR6XLSy%%J< zti2%1kE&@duKU@K{-bv;+{SRU%0K+vKlo<&cs3g@tqFAAagb+q(C0g9a*Dm+z$tMN1PRxeM?e zVP=+BB_wayOQvza5?AGE9%m-t@L;N8>9a-P%9;$*@@l=Cd%PG5Z4LgnJlEb(D)xpY zYuB$d|LL0K8n$rzF~_Q;p;nQBj)~uIs_xs=ok_&J%9n~bU$vhf5~AAA4?(g`S`8l) z?rJw9`=UipDg(q`xfz)1s5#SI&`w9qb#XRoo*G8f+?Fi;;w)kw+2FG|C64n4T=vcO zxNs~Nk~l(bq~{NlFx9%RDs!Jokcb^AH8?iWgp;_QvA0muDwr5UzsajxW1j7>cba$+ z1xp6F%=CGt5*_mN)C8?-m4rr1yfikXPiO<3803n&x2!rzfALHWx~}%D^ppSvpUyyS z7CTVpWowiLvqal5pM$c@vqX=mZrY8gC5pnrj|J?SEZTjNZ}KH(9F4pYrK|?=0Jl!u zqb;EVID>z_)b4}r{Jx@fbC&+e;S)U6E9RJk_-~XFh9hURP@q0AO;|=!^vnV$bWjy$?iM{ie3(nYULS>=fY^w%^5AAPQPjI-vi*2$2I4>QI=2N zi*dPqvs`*@v3&9u|M5@!+b8&M`Ri1$1LWP#W<|>}vu( z?i>bIq5JB4%d5XtU)usWXoOQ$K!^GV$Z*cHtD~&7^FP>I4WI^5uy-coA!sK<;+7+n z3r!$(i{H{eMIR8F&;~UH!lE{V5cahc4^ZaT(%p1(vwX)d$vEZjnZtN;C&&?bVzi6c zG!O$@@VX|Ls{Uy>t^uT)q*Rolen*U9^@!*;o-VTyIulqdx_3i;Xg2a8gHPoKC}d3m zpgTJERnzBU^&?Y7r!$AU`F+A_$s9S$Te@Uvl-cW6vK$?(l<5XkjY0bc1fQr(1BWgZ z)7A!orY;&9ht42lMP^qIs_ljG3J=_WlFctAG-n>ihvan75u{jdTp8@jKc5zI@Cuyb{X z;nE%KJ(&`eFP7`e7x!~uUluHcKVhJV_r}us_9*W{YzVC3So#&p%6LVZwF4$7+LW>= zSY~>ggXvOJkPU(~RkFaaAjX9n3cu!eHpXnB?;Dxy0Z6;y+AiAmO?;XRnANwSDn9rB z^7eE8jlcTB)5kyybD;$v34*IAN&H@>%#v!Jef0aa0#fHB?^rg{3Rk8=Sn?!jk^=_w(_WFH zYikt^Q@#uoGh404$86xU&f)?NFD0Fw!^=i{b$Gef4@OhYUZG1HsI@v?$#&wX+AT{DjL*y$-I{O;Y5uU9!!1EO=U%O!+^rnRRq?i5SMI8P17Bu#^u@` zN|8DYt7$Ua(u}vI+Kp3Gi9%?fV|Mc6S%VPEcfGetNM?ty^ji+JA4$LEGJ7cfW@&8s z;q<%U_s^!^>-_$B`hASwPo&>bg|>Y1y(w!sk$WO^;?B4^C5AN%_)kmHYEO-GLbcoN zG9r?+wA;L=8g&jHdV6F~;?!g+J4J)-L>d_y%4}02=I9DNi(jHhJ7RIMk-rIXULh?wv9L(s)FhB4 z6uh=~WA-}24X|Bag1DE?skp&&!cM=)1iW=q>@O1iYLo1WkCwlgNR2TspGv<)zQ3D( z4`*r41ST&os^jZW-A*x7?OVeTHq*NQP3$D9^%syvO@yLSE}>Y$kIK)z7kgrOugvcC z{3F^H5fZ+hUrffl{6!ln!_Uj}g>B;NQXFYUHdJn{F-cLC8L6e{R0@I!CD?+#%xjY< z+A2j6&?2$g#l&)w2H(15wdMNZN{T|enkV@w5h-784ga`vl^wliV!Af`EETmuBomn0 zYEj&+V)&0{;`mDUYT}R58mjk})M4g2=ISc1s#TaIR#6F1wLk21C;j@qoZ4)u97bL) z$Pu3_!(2|mw?ToNmJ9Y)>O5SP;V_B)Jj3Wi%g zdpCN0S<3wdO%0qNSVrM<5bfl}DtdG$~P9Wl1=0Fm*oIr0#m!X~Pwh zLBb~p&M9=0%Dsnse3ff5P>B1(hJyN`VEa}-RMPFV0m5nRgB0rxA3s^x%8!_;Xl=)Jm5{? z@_7MTXkHPTV$pt8#q`=l^^ENK`XoYsusK*~g#N5t z#emT9{apSiT^atoj3_JYKuss};h!j;L?1jjis@;&vIoaF_!HiT^6_*B0;VXudsQTa z9+5VdNWO&7ER=4i0Jw}e+nb>AFKe}T^DhJD#d80qWDSyNzXE~$zsw2bsyB<|-gr0? zP4#t#psO*WwQfq87k&Pz+{8(7Qv>;(l?@>8_`>iPREHj=EITES;Xr(6H$xnm2=xdx zhFAkB4&=d?7}SE4LZvm5G&BIp_&tlZhhMh)ek3A z9U^Cqt77I#03V|mfqu~sz)Mcmq{7~168dHdPrD3Y3+18#`sJ;cs~--~Khb8HOEL!8 zVhouGaLhj)?n|?jMRQWUOzljKU~62c;tl+yAS?U9o{&mVu{B!SQ!5P7%mS!Imnj@(boAzE)hYg)B$fu zWH%{J?OltVMZ`3#@}LOBVxmmwYw*x$O~$<*pAO%wVfLpaq+)GL>}ElPZv$jHcC#R7 zd%FJMRP1I^CJ~;D9b-3Z_#Cl{wYQ308aN|(NF%Ew9vwdGEt|{tkp`~FG}|YQR+yk< z6{)_95~}&xho@T^@A81kE%CwEDzF+w;ar3U}lh12JyLg8U5bSNm*Lb-U4(r~O3 zv}X)K0bu3cW!~}=7%q-|bstX1ll`?eDMDx=*T&f0niprUUjzRR7E~3dw%)8NPR*}z zv^GhNTf=vLe@bY3_?rZ8m5Dby8B-n_9|pdua)tH0^AeppJC2zorGGj*P8Vmh<5I)O zj)Pw~GtLdocWUxV=;?ynNOBAM0`m|dnQqUPe|u%12!Ui}P#vtf5P`Ls50X5QkmnKL zq@bJ&p+cEUa(g>e!9sdz+e;Rve>Ld;{}^MbP4j@#t}uI%C)D_93G z`TNeD*AfB>kf`+v{$wux-E(ZR?n}rLi5}L#sA?|DyI@KM1y?p%IZ){jRHpszoZZn| z547$h{|CaqP`>-~E!6~JCcM!;h?e%V%QrPs-q9-9lwNgjxtrmbpqRoTP0m(%X!y-~ z5`u4O-DfTv05QQz&o1exc{saUECU^PZ_fPhsgM25&I5`Z$G-~{bgb@t&Huz5h4}mr zhg0_v=PU9awmsvuS|v&!@Tt(t;kQz|590u#tclx^29y9qEb15A7ZWsKKPXJ`;VmUG zL`3j_0^xQat_Qk76{IL)?sifmfV%RB{ z-1CZO`CCDaoE!4gkQ>xyD*)zt~j{sCp~>QnaA zvjtX()$#zJ$&n`hfE~JgplIt8xjuoWL3o5n$w}w74fKip;kOzm`Xhh3e2s*pz)L>- z5nN$!mW<=7jj`rciCnI;oL@T?`4ir|9R?G?)i)GdR<#I9R9r?oV?Ql*Sdy0y zV(&?6>I`j28xuUBnjA_M6~cI{Br(#&i1V&SH5dXFX%b*~spSq}_+t!wPlz-!z3W&? z4bvBKaM9uPMGX@%9xc>Qoo;-MWHWWTrB37br%s(ZorcgMAKhWgNB`wMyZyfT&4W+p zEp2{8f2$A+v#UNU7;C4;Ud%W50FDMZA2H`nv>{A7+8X{EFpxlOQwQ7?u3(=A3TW{` zbpabp?62hB@JCze5mj+QQArlPie(zhd_)5{ZoBh{W)vP9vAT$b&3Ai4h|-@`p&L2S z>1;<#h*?@X2B5W3GU~aX>psedtsH4eZqQcbQMZ|Q75%!ua#y6{3H0bX>cR;-(M8&7 zYgBqZgBhit2n|}=$CTp_Y;-WrVqN>i$1{<8HvDf<0=z$?8g#VK{l9ecu5{kHS>4X) zCOx}^+L~G20N|W%0BaFUQBQe6o!ea~8HhhKIo-^ASnaq^-WDvlJ<1pvypWn##K9)1 zw??tExoN7oUusDSOfYBEb4Z|(IE*s9IigE;7R7JT0zO#);07E*`l(*TlQDC#C$jQb zB*Z&OyB|r~y6tbEt>^)ej%CK!D~}x&R-h`QIz=u7^U`g05AGGW$BFR3#WLUTBB{mL854(TG=aKJD#M6_FU}j3vI(oI1Lp zPI(W;lf*pkA1yKlta-!mV4KZA5E#T4a}Ok!p@M5qNe1keF$_uEe|NL#J?xkud{FfP{*JuWq9vvwZe-rU%Gn)XXD*)=W?%~DbFzWqGTr_bqU?< z{8_qB%G%)~BT@IKdqMZisC!}A$TL#v=>X^azs{Io&{ar@8-2RpKRm|Dx(lJRShARX z)DMa@(uvC4iU^ijWCrb_FrNa?$}Q_jQ1B7qs5*~o*3s2sK^0|~z?w~qV*$e4Qmqh- z@Q1W!-IG=?VkE&FX|`;K3Kgo{luCZc0-Smzj5IAFT@-JCapq=*wiRG~S`p)03lfdp z$Ru2nHQJR0h-zYsL2ejGh__ePDA!5hQqAA$dRU`WdtyzD`3|iaLFB67_M7S?F!xYp zAz!261F_PwG7|0=(Q_o{^<5k!J*@%aCk~RHs0tIpAW|!or&Qjx=+R!Ax$y;R$qnB) zmgU?}6>Yc&DtWXS+@C}xR^f2EQ{8@XB7cj6-N)@1aE0b9o{2W z+lD8lRgK&iQ|c+T_-wg&Zj(KHr3~DA9zMid_y((z^@)g-C6?J&>SuPE`~BBi=EC~B zCPea06it@25=JiEsuC(zdteaIvbJj#2oQjn8gEv5QOHIwcS)_|3cWgEV8tZ`MGg|| zG|gv3RHPS0w4H@Yl7|cc?WZMKG}B6^o>wxtS-!hw?cFt#;=PNHQXOMA&3e0Qwy?Wq zvg&pL+v4t;Ep2_5MtbrOF4BJZe#`y^t-s`E0c-g{P~BOaC)9fsr5w*G5OiPKYsSe? z?VGDfZnnH{V}Zi|6`bu3KJv1Bjd{wGeR7pfoaLf8_;`uzPe{}Se2S$F zmUBRcaDQad<_H>v+)v^9TT+~!1R3&HH?r50#cbK(3|4lhjzum=@!>yivF{D%S{w^q z^N`AKNyCLY^$Omo{1PV4CU0}{oCsgcyhtxt8kP=N?)u%Ht$z=|7^C+`Z6%o@y72d1mG9;XP$<1C4SOzOapHjxhH(6M; zq!~T@Ui!l4(Eh!_>M|&^y}gkg62$2oJjMl(23()Y$Ew$8&*owbsT=_Nt<m6JeSsaFPv4P+G%ZOtnTHwbx{-qo9da9 zxibMCgmIaImetG8jxqAQ3G%>@%hF|YVqE_oZS=#ReXI>^`1|;wOlN?=mMv6SJ zTaUj+9f${fuZ9FFAf#XYlKtL4ht4E>fmR|lFnsZY;8#_p=CuC2TB|L)mZ|M`xh?AP zoVK5-+P0(Zce^dVgE?*gUDX!9h2Hxnx24llZOh+7M-XRf)o9U&$K80fCGDJs?h@~Fxj zDlI6&R_JI=N$joL8OeJAa#!Vs3dX75?DQ_Z*S8iMRO@y-v z+0aI6m=^xSJhbTF4KaXHlJ652L1(^W!L+ef!!b+hDaSgF2NR( zMI3O$>f*6D9A^xxjahvCjK&?JfJ{2$MJ56}08|mMed(S_qS#kQ!J7Leh#{rjWRN+U z-t}Oy*qL>7X*Y$fH+K$zO_4``8}h)viEm@_MeR|aRpb%7drUW|$s-K78S>D@S@K8? zEAq%q9=Zs3(+m|&Gr-fd0yU&NY_=0r^Kh|Gw(S(v^i4Ig+IOUyzNsdf?MOAO&uvmo zu@9nA$v9~!UnmB~(A z6e$7W9GA+s8Hzf~wC?p{dsCDsB`ZITD`a{2Y7spvUHh9gMZi7!@=e`j{>G!YPdaj+ z@RMgca-a0Vzq9X~Q74oJy>IwN3lO>Mea7X)YzfQVu|mJd$wUNBplBxdWJ;y@UI zycuT8d1AIzGY~f0j1SCZwrq+xe2uh6ict$mQY?9)-8hg~xN*2ZC%vUKKj~ywopc`} zH;|Uwx^WO`;BdmVP$3%2jV`%pw|=;G<9Oa5M`=dCAvAfMp5^zd&WdH*Fit`(Kzm^i z7Z}0xctchm?-l#;CgZ&_Z@kq;V@-!AW6jTMtdlQ~v35@zV=ZwWBTppMkJsKnIf|Sa)t%-P@_UK6)=j&<2`9w8EW}9(7cf`9Iai~%5PpPbtyq1uv#AI#pq#ezS)WBoH z@HA5810DBlF{CBb-84y5qz$c#GW)d<{YJ`GY-O8UX#;h!Vw+oUR%~;A63Gmq7Q`l}i zOducl&#rc|JZnLGoV)b69CPSeV}MpjFCRYCD(J&Y+XruGYg;5j)dib7$u;2eSL0J` zBTdvRTJ9e}+qCM{?Ri&f-*}&0ZMtJ64mT)9Z1?1alejPrvl}%l@wn91B+=)_3-mH| z_R69|j+5cJ|AFyAt%%MF4n(kPC>WUpIeH||!>&D$yq#y&4S9HM|J0Z8YpXIwAr%aF zb3)JQ^QyTe2eQz`Cjf52-a?aB!?&!?8x^{s%@^+GH2TzzNRWf-2R;mEcC+agN_m^z2p@ z9coMlL|xuI(4VG z5atLx%(z4bMSBZn7=5-dO(VQZJx-*tU}T)k zzKKiK+hg1`8b-Kcy1-RYLrXh%6~Y0a?Z;7fL}3SX;e!AOA7nCMvCVFDBkkuIEaj;m zt{HByMVz%{3|7Bkn~bse3R`{vi6R8#*8vwRyIC0N5!b$1V+yb`pB2n^lfQw_Wwp8E&{*r+hh42@L0Ot&9M9Bsm;?E5_0Z57(zGM66*HWQL&4>9u*hn#v+ArGzNntrx;yQ-ZU6J>)b+R zP3*$47L7tWhYEFJoLJU3j28}r1kMV6z($Oro}xnG%LlU{n4&dQgd&SBVYle;l`HHM z*r#yn2k! zgFP`IJf<*at^w^BV+8Ff;NYo&(A3nRnMiPtxM!SW`?GVXmO5mVE7SqWy$1SvXG>m4 z)4jtF=BGvntg;dvI55Dufp&YgA|!W*kSUL-qrF=rD=6@wfKLKPZW}>FIjJq|lAZ`B z6F2bXt#hg$uG|||CHoRHL%5tfN32DCM2ClK3ML4*To6+sRZNp55}9yp!u|$Ix?b7H z{sSRA4Hd(R;sqmA-Ycwy>B0|_wB(4wvtu1#s;k9t__3U?M*dO84ABU~ce(N2c9|hw zoOdQ@T8YA8py#(W zPloKq3`Swre<*p!4n^h^onDR_Y=<0^c*?sG9SS!YZE=$+dVRv&0)q4w(f zgI>pTD7i(JgFNfZsY80A4r5r2I&|`>7S57o^i^KJEJbwOmZ)H|=>Ut>0hX)-x`Pfy z9Mm+XX9 zjvwZ@m*ayR#~jJx9>HW8RODD|1Zp+T={G~KJb-dhh^Gx(<#@E=kPP!DJk0zUYPiv* zBwCdmZTd6sVc@U|(A+pE2g5U$LW5NB8=pMcc@xG9=Gn=UAJ6=A4{=-=4+T--8Kx== zZzKnakC>N^0!F4i-y)nmN%lv)GsPkazV9Ir+TfjsmB#AJ>-Ky*tF?Udhp7@p3+!0p%@R1sz+x@Fq>m!f z=6;hMcP*907E!A-7Z=K(`Z?_ie=l!HAkTaHvzf{tnakGwB!9%SD+MMGKRh~VmWa>5 z?qhiknJtzBE=!rbhbO-tNMXA|0ByH~X_F^Lj$@$*)kyLKHwPVM+j6D;C0_^QS!I(> zhjz^q7mAbeAJdlCBx!_*0jpkghWKd5^C010u$R+7NQhb_!XcW=?6?IM;yJX!ppmpJ zS>)N3WD-^>S1cUcidbfpk`CC0Y;cKJbV2?^lZJ+WKz@eqLoD*SGh1h9#$ObS0vrIm zy&x>dcGJz^3O;e2aHh%PRfnLM-$-H|EXYXLnk&e_u15_{nno=Z6YVqvStkS;Z5g$2 zt7wf!CCIqWsL67~xT;4BeJlyG=F&h$kybo0Eyy|{$nb}F8e5Rr=6Tl5qOgv>B@TDR z;SFHkDhzOSBs}m7$zcRE3fhSD>8$)mb|bYXf()%c1exVsyPOtec(FoRVNNqfVo4m1 zjt=Xv&Zg)bHZV&#+&o(GMn%X6?N`Kdtwq(6!&n-=UkfYvjekgxfo2htoC9z~*$Wk& zi52!lTC6{bwMa`e79pUG(`tB^9|~?t7ng?Lkva=Q*wi!Vk$x8L%7)F1ln5@$N}ApY z?F6|U3s`t{x(ypkmSv|2j);Kw^1jBaPp{AhN!);R8g4k{-)|AFN}pGE^?Bh5K`BWb z+(8Ti18X8PJt}A?98ma>XIUFD%v| zSL4*=WpWKG$sY-Fg(Rsl7L!MQZvp|42x(mRE&3{O764~S;4D<&XpH@BkXD0(r4``x z1kNd3eFh1GIzXb2iQ)~CviGsyBx6m&y<&wRmbu_5&EGcq$qIx61u5mNfkx`A!WLw- z4vfj>UDOvjmYSfGi`M{sPX#)=hS#9)sX*UTV{)Nb3$SG<$3$&{t&gOM4=_hf)tKAy zPM}YySQvhX#FJ68feVQ)Q&{vEvu{C5!6>+}q3&IuUnfxpx7C((3!+1<;E^z=5FU#k z#t91cy2ny9MC80ifjoidlTcrLqVlC$@lfAcZl0j=Rd-wSNHYrX*aM zt$Xcp4W@zJ6q*b{}2^scrHY!p6d+10}>yMd&RIgTpYn|0TI#Uw^doLg_7z2 z4S$@n_720)JKAd#W_aE3KeGryQ@fA@;^!elt?3 zY!g(d@6S7^dL>I!oH>+m1`5qk^RxAxJtsb6NlwE z?2p5d;wp*OqXqjKAy4h;EEvO|j<~j5id=aaU#!x)`RWB*GCCpUK%l z#CLV3;$a(Uu|14waver{Z1{0?$*!A=k7jn>U?=E-Z=$%sh9EjBj(lwRA#4ikG{Drm zw)HZm4)iOoHeNzY(FqPHzX7i>XU70s-bJIq^#FlaoLCV6^+(yIL}>0UmuQwQgcA6< z7M8JJJ(Mm^u*<06O$DE=x_oT(6|#AZ0HuK)q0=Z_`bVv>v=Wgv19m0$A=}@XnRZ- z_cVU5@O!BgW~GVI9Q5oiPSMUg1-|C`(2v*Qejm8V7SBPbUg2H_|!ze0l?vY$P zr!m#S@atlgMRAy0&JzNVNfBc?wV8g`w)V?S3`DZJx=9df?xgX7h6n;)FTc{Tv3y3p zDBjDG8M&f_a(*^EQM{|^h2s5k0)!Xp%WE%`y{F-T;tkzzor7VtO6w^jRU%{d{FQiwZ3@a#thyp zGLR8;UD#=2JjW&Y@rIG-rgAQjpKgN>+0vk$ft@U7HAO3gkTA&os%RlNdP>IM5C@x! zh;xCo3~$B3Ptr0{X)I16ErXU@(lQvW$dqcjymwPToChEI99T=f@+vwQLu|@?egasd z5)yD_16bK}2&wbWQo>oW!gi}!`Qcw=6NO(i7rcNfhn+Sbl}s^7CSamVDt#7 zNOdp78^V<*zKB|*sezTfp5Ke+1@k(r5ZOi2HPDYW{ugnI5lF+rf>2>|dLISKWjZnq zj+`1n4 zr62KAbguNHlPTl&8zWmsqVFV&nt?}7lHzM#E%7h-QCsPMv4RzfAZ?>x z8XI8i@Mee+fQze=s$&9w_VS~{5foL7z`uyh4&#>-PJFFUu)x386@B)vV>h&q#joQx zw2w2IC(bg6C(fp~3J{s<0u3QG00;?x1F&LnP^Ay+hq5+sUuyGs89*B4UNpEM&Xa7p zC0k7~0Q{x#S}B9OR8aK-fWVX(2tTMK+P62IJ9G33JZ7^V2U~jT-6!2sSadB=}^RBJr2j>aNIA9N7vGH zPz}WEwR%CdOrU*}eX%a37RGtZ_PKO9?LQD?-xk?3{bWsG0q*CgwHee~g7R=SMv52wyXt%7~P1;jonKqS-4u2#J1k$;(!yZmZ@I~9^4 zq6pgxtK`D#cv;|$;c>VC%xMf%xr~D_2c$=b|5w}V13mHWrNn0$L598MU(&FH3-b$p zuIb7g(rDEgOuWNBv%R=4&fxS=N{%2WWFgIquqHa1-wv*=eqj$rRxB5)tXO_dvSK+2 z^~>Ik*$GVf!iE;*1omBJ#DeU36IfZk6LG@Ip$zFF{4b9c7HqSml!!1?Jzg8{8*zKI z$Kt)s?p%^~F(tKQmsn?YRVkO!8lnw|U^ZD4Zx>I7vPc-U5>Em9@{?L%q$g1PQ;p9# z0p(XrRC&lg#ge`GrlQC%YpC+jngwLQGs2!qpp9RQ1vpkZTtp*9YmNs2s5Z(at#((SG6mKA7$U00DJTj-dKNS9fZ`T#GX^*10oAa@X|Hn(dA{& zG6TT7oKBt?(#Al6OUq+2Z16e`N5jMCjiK-($+L$FeHY8U9SA5_5isCb%(bonpWS@3c033W4R>0S)x7J_XDq#$pZLCMdtBE7?ED@$ptf-nrbg9utxU> zFQFOt3;rC@V7b7I zqpsYW%MeRA=8Oc^Edcl?yOj$I`i=4uj=6LaSg7v^3yl-KEvuiy^@&C%orLsg+|kan=^1soK1p4EjP4>E z>GHUPxf>jt*_5D^{}ob5XBszEiGfQT_M(wAREGod!_A>Wfj8WHG*bG>0{Zzw9l)`&(Cup%EF-E)*(^Vxd6d3RO2z(^Tn#7LKfc;536Aq(Dsa$_i~X2+ z8{$Yz7zHC^{SwlLC3DKs`!eNBrLqo1S8|Kx{2b1Xj}%|#9fpoDY6>Sv&d+&7m*+fp zp*Z5|4Ja4g0nmsggzw^jK6_-_&-Spfl(ElLt$_^J*v~A4hm}7tavG@DC16Xl$vTz3#f1`ed~Y_r{L=D=3=;5>#3xTTGB~z zK!jPHpwC>+T*Spn|I%D!2{`?Mfs84%=RC?Lz+y|(KqYTL9;?T$Poa*A+1bIG2zJ-wM{p zL9EYdWVl3;q2R(i4H2rvogA{_C6a!4IYpy;EcsFawxq#H8G~t9C&R12**X)HgSJ#0 z>j&9CNLYbp!QnKg1l7U;*+C_ogy9() zp+*sO>WG-xHN)nI74>riUK3$+xyb1Tb}^T1Jqx^0ez~R6If^wM(vXu|plH=PbIPDD znI|C;GD2~Jj5iU#E4z1(RaiHr`p_|JOMHOb5vG319cfV>QbvC)E+*ecT*$@aXqobT zswKdbWtd$8Y^6G_8?Bl>xV4#rU0cgC!1P8vg;jfX`VXHs`6(=#-wWkJWyOFA$YFtk zmmGlnHu*LA6*`7ZiVj(9V7g!4w~3PiX@Pf2S*z+N(!<@9XylwSYK?Pch~8l*POFst zB_ z;V;>cL88xn{8yYY<^$<8OY(1%Jd2<)lYv-x2MlSRh=>KX(^g$sJ5bt=)!>7NMg=c6<2L!1$)@D@Cc?CtQ*GdRpMzDsLYUN!C3JX zoBz<6h;7J?X=X@r$@7#M?t&E#zeHFeo^0kdm7&UDg^=_#FI1_rXMq5|hA8zrm8YG>;|8odY9)^;GU0eoovu4VJ{L!<|F4f8vjw=g!#`OPb@(vE_N! zSg4rh(!FiDbf=udr2$ihpt!WBFr2hsdU23E6Vjrt@;E^?Ed9|y_0dX8)k4#HN;Z@Q zsR|kwqf-h@k1=qt8muMl*WqSndUkqz#LAEaX_dAhxr*M$!8x_;ZaX)p7L%neq=C}} z1%fJLgr1_JMj4AkrpoFnU%>_+Ow%4UnLSArs;)oi#Ub-*W@xTsw$0|$c29b72xC8$ z3GLk4Uig)LU_f+6NKOY*8+9n+upS4(F}kQyCN5XiW}@iAnK;}Yhdbl&EpfOj4pAaZ;5v+Uzf?%nGvMQvdQ?+>v@l!5QQ(T5#OmQaBU9cS4eVZu}ZJu?Q zpw>k0B~7L>75UbVo|;Z1qEW>_o*IQ4HxvakNYXXEAOjQ3Wi2zn(hfNp{&xw%l%EZ#^~ zKx1Fr$tW;s*6~M$X!X_O&!?`e=XWv$<Bs%84kf4qX;*QP;)yg@q__s4$ z;iRat#r(kzT2}4Kz(j;cMl01Jn!u%I^_a&=ax3b@@~A@+8dEmGCAGLi$b6`Xt(BkN z822dI*39lQwn~*ts;khvVI1nk!{D@bWxttSziz>y7t zS>Ronl-**F^eCcKGAVgiGAa2Ln6*jS4U_VUFez~~XoD?9EA)kfm07olS?9MePMdYA zDl0xgM=P_Aa&Gg?I(uIii#;;y3c^+X1Y;(w`h!NQMv*HrUXf=)v#*5t3eKwS)OcH% zuSVI#e5DEIYgguL&3PLccy1NK&U+8SEsX;1&mc^(J`5!LrSL*q3$iMS0uT z3DRM(mH!W(5rjDdjOs1*9dbGjA{M2iP3D9>&nm>P50T(222Kafz{7OW?>dt>orJup z?vPL-+cGuN$Td!q-&v{1o)c@zfhC}m=4w=&F@|$U#8%@TS&bITwi*#(JfTZc(Gd4l zL(!DWm?=bL6|F0)k)Nn&U0IEm{}FMc@2#B8B0SLikm<=TdxYYYV7`xPOO{0{1}PJ9A73Bk|XyG@@!+}Sbm zvqoG2PmO&7tWy(nf^^UV|HY^CTlnyAanOQ$_?H+^0CrQ6q|ppzN&@GmAah+;qDYc< zr;ddKd0xjv@X6Uh$IuFrvtw5sgX^Lo1ckX{<$FKjKE02FO5|?Si{~5crW7){U`VKK z3Wu!NrzAx?EB4#KCr6c0JaCvjEWXe_SF~_t5C2|HFa!pp@I7Y#foof5#u($=k|!8y zv^PMyJEz1bzS42-vDTPl7FaadrRicxSEQ?l;N4j{6 z4zP%oTm#7Q2(wP{PdQAS$eb|*8imT)fRPb)8A+$gbF}%vriVf7s&<^_OPe4J>}&W= zEjill{!_xSjQ z<^7xEqvEK(;4tiqrR3UxVfro;0+G0wGF~E+PTyiH#<|7|-L~hw1t@>;{{@} z!%;LvH)E>r&Uj&nNHL=Lf!m4L1}jX~zk zvb!WmePGm+G2Dyv{VqEdj8EO1`QK9?o82p~zVkJ+d*z*CuRLC*S=nQ|Jn;&00(A;J zm>|pm>qx_IrBxwVNKaPrENsIwqZ{1oc6pKguq0&ZVI-Dxhu<08gG&q&j22iKD?51U zYh<@^0dEST+S&FYs+r+x7^0e%64j#Ri8p1QsNPj}+dNTS+%O=`bgxu27kmC z$G`Lm;rM`63VTZ!)j@ghGzIpSD72(OGi5iJg6L^lQr0HjmKs;s<|OxT$PWf>*E7GJ zwGf>&TZK1-!^Gs9ji|9QpoUc4ey=%2-CplkrQ3~SD00t6WD2S*r#Z+I2vKG0?k}@$ zaRjk@1TG>^9Fvk{$n~6^y9lyKP-zPcl8Cs^CHla8!gCW^TEQt6M0L78eX6B~x+@su zV^BuefO-@-oa`!YBtw!FyvdSlzVZg?uy=?1NB$lutvGYS!z(L#v;3D18rY()JiO_o z*dvBtoq+n396(g-U~N%X9^U!|wjO%CmIW>pKC-26>@hMj*+|e6^j9>%^YSpVznkE} zXAIt_44!`1Nj2#t;%wE4mq}J9R|vfN8OezHB!TxS#o5+KFpwj{BeTZ1RfBafDr|a( z)g>A8b0Wj=P8;)ZVk;4>VAt@cio%WzPx(KU`xzRS4f$zjrVM#rh(@6j168vJVZXXu zs}1b`z<5Mtc&g$6k>R$OW7mc}gr(PLSx*%+Fb;}UnekN6kQpB`O_5>qapB8mJhiSc zR~nIFQVO4$qz^zPc$Sq83cVc2%)1)%3Tci5v6dC56@PtO6 za0p`9`$iRA=Fd{p5O1SUtjU`|3-95wN1aqjRRxLR^9mAcFjYm9v&x&$FZS4*fYRq6 zv2ep%U6qxTR0T%-6+WI6Q0tpZnr}*b9v8ffZ%<}b-{Eh+p`KN1oN8A6hRIgHwffkm zU^>y|a^LDw%xWcwS+*xQ2^a+5b(1)}kq$0cXEhK=&BjPgVq zs8~p7`lU-U%F*s<2>vbUL2@$<)~ho#d}(zCWKl_aT5dJU=dD88O<`DucAimgrbJ?6 z#I=#=LZgjxvzE0@!GKZDNUQQ_UnGD#qvmltF%c>~fB|8-vdhznR#!6t;!b1)R43fI z1P>X)KvbVsEM#|ZRD`z`4#=#ALqos&rLMhF5&uk9v?PkDbd8xq4pEa>9RZjT0m08V z%U_y^09N=gkoS4T}Cs6Kk2nRhQ{*vw_2U3sMLab{PCl-R*a7Rsc?b~y; z1VB?h?KF0Ovb_K>aMgGr?k@*veymms4*6(mE?yg|eARlut) zYs?Rk4S+|pNm$TYC&G8!9$j6up%m;OCe}*(ggE^AsLijb@#m9;uU zsxdp)uN14d9wyZg_3P^~ZIMhcuL9-WM%-%c+2rw?cHN`!!PWpNKvbVRgC5xjTlGi) ziG}SJ%U=YT%=qi*6aXF{Q=2;5B^kU;4!Q}R8b~XO2GW9)G|+hoGI(37C_*wx03@Up zyM$@CNCUvjAx#e?P>I`OivSfK5cvhd#fW=z#U|F?#B%q`L4A6>D*A*%q1Ci@7q4vj zpm(xoniA&zrf^;I!Xwaha80HkDkjq(R-joZ#vQYeYg#Z8d_3fD5@aEN8&a*-3&Oo# zH@k#j=}P{tRPJ>};Ijl}xOp*n6}?RConHo%KX;FJg7ufT7lQD#rw!{bH(=FR3`*Eq z?Vme5{ApAhXRJ^Quo{RXv50zlAckLzfxr<^OL$F+9VL7k2%s0u#Xtm(Obn&L|=H7 zR87ocITg)2C9%HKK(&gN?TBhtW{cn{m1|v?s$*0qR@6Ql{uJ&brTecoz?-KNuUL)U zERTvKTBBWQs>Cal=oOh)cd&4iS47POUUi3)q!Q~+vfqxvWLrT9R7U=Be4Cd8Q?Tj! z1HxH4nFfkaUk*^PX$0(+rDV(bn&lVv?OnzN?KedTzmfx9Gw>Xk>)ZWCF$R^QRx&f=IR z&m}yXAsf#laPaY-9$%qlPcD)qPp?evU2?r-YR^U3zNYwOt!6!dm$2Dnu_5aB75kG7 z3C0Qlsz7UUyqySt2Q36>CXzjwE_SAf?_7fL0S&<9vO)<2wDspNXeui7JjB{=y-Q}w z^GGY0a=H^txo&pJ@!P_bSrSijCYsFZBC9|FkT@yIidKqcGdwUg(oGw+HpkPWgpHIsUFd> zvR&ijl>-@h+w_c}LbuskA+t%h8xIMUmmUXI;ocptUa_rT3ZYpu5}~K&agtb<>)lSYth0o^qr=SL$7av}p1|c+xNP6!sHVy_Qmu#X@J{LGC(cT1*4C4x)H0n2Ab4k! zmz;f?4?D9b5F0_zijH;?Mq&NeT&khyOfxh5<`Wu%pe{i}w*Hrd5s{Avdj}m;k(rvE zS;uVSy(UVeaVL4*LrX8VbfsgigZ%sh8s95-r; z*No%FS;nyws{l_KN_dPv9u1|oH2H-rKXGc~6PD{)*@9u?pKP$1##Gp8=y%C!oBH=I zIc+j)D_Tt5A}ZFjE-c8_?%o};!aFcF$&Q}$Y>yuh;3^p5< zmzvdcK2B1ozs_UsmFmVeBTv$K`Q&4mk}$cb6r#}|W4FTqWBf%dcM8NV|?=7m1zqptw_K(Ny(ZC^S0t1+j&UJF!$&2Kv@La$k7QtA_aGA>I3FJ5T$Wd z>I3vF7rY}BI}cRlu-t(=BgbpVswjs|g~mv22N~SiuvL+;J6S38i~#~66M#rExNLF3 zf`2=UXV}Kn95BwCfv|mo2;iY7qLUBS^-_32$pnGkdT{nkZJ{Vqgir! z)hnPoo_h z+FWgVh?`duMq4&$XHgA}RulM1?PKBkmAiUU3G8%C`Qt5)N@Aywh`vdZ`;s%`RWO8P zSt{3&S_D~8tbx20($LdqHP^f_hLHsZt#_q|ownMh)fN~;D6L+2!Ozp|I3PTNfJU_t z`qns$+96nxS|c%rp!o*HL)e~`j3aF{ODyF0_+^p+l*LJz$s`&R=T(BT7?{$EIbd>$ z^W(lP*i4H(u=J?Xg(OC=EQUyXy_~_YWAI8P${uui8r3AIu&Tl)-g9Z8ZQY6d2pq8& z%|Tbo@3IeXm84@yI42~l#GrTPNa@LGb=gqi8{PKld|vW{{eJX$y{xftt%r}>GEzNfT-aR zCOi(S<#z|ZRGrWT;x@cUf;vMk2FN5hdb$0I&qA|&c))O8i9b!b<-BVhl64x3GU7Pj z=$wdi>4&s~22g~jE|H(ih--mh+Ea@2Mk`M@v7dfavhs$3so+)lPDl~)bDGu7=h-3y zH$b=i!0+VH33ZStfE9#H01OvMqh?kVKDmYfWmPz91(R46tX8596~EHkKFHf(0W)t~ zYQ8N7v-vib8l`$zW)&4q=t_=YfuwUA=p>ooML3o~O_3zW!>RH0)9#yzvblxggwRF(13$`;r0 z8KM1RkTh19KJQ8vT}GXbmFGjrA}|_>ssAr~?;ma1S>E^Uz0c2k&$)Nb%v?!Vn(=6# z!`L3el^9wT6d}Xxi)JLo3W4|+D{)u&Bkr2s(ely^1Hmz9u8@pr>a@6q71Dx@T^!`K zq!l%;v)UD>Rxw}Mhh=UzF3&%F<=lgx$z0bZs=Z;1qu*!h$*+1UB z_xnEY^FF_y=j~1v4{okAMXH`IcvTXRTBoIjY1t4sOc243b7VS zSLy&)hZ^^Q2riA0ukB0(bMYO0xLz11ugGSVHZ6o+{&^M?#%-Rvb5`(#u9*xgh#?!mei z(PqtOgpkciyK6X=nyv{uuhBJcd9<7YaSzs$x=h%7*Pt3K)IglWh#6@*asU{OfynI% zL<$O$ngkE-R?pxAQz<$UK2JiH%adek8g`L4f|W7K%9SqE0zduAZxq!ZQ2-GULlvZt z^>hVU5_I8>fA4pSvQ%kAVF^Yiu>~XmvptTFlNHjLQ2~qB4q<%k+ok=Qk8ZH=%I+Ix z>|YA9l>8_T9cn`mvx?}U>cqa@`MKFk#fsLlqZXz>LD0Wiy;7~dZAS9xQF`(I9No-f z0$Q57p_**97(Al{+8XZz(@Uf;evU(x2C_6~bjJ%oTh^`d3gYPesCE}qB~#(M>arh) zkJ50+wy&KSnzfKFgF3{ZXvS9+f4wm)iTRn9WjU1*@`R`(e;%406>U6$0X$X-*DlOf zIn^qOFeV)XhoFt=M6r&PxsE#}g5R({2@GhS(YkI zxhaM_d?1-L^o$^znl<#t2|J*z=?`$~g5(G5&|?m6Y~I(n68P-g5~q8_KgsaedAgh-nyUqA$K>dRqM52d~&1W>lhM)ijdplLE! z1n+bbI&*yj6y~Wf%KoXF1p+iLNDSx?MNuIQa|CF!9q+WqCQogQB%8|}n#mpMee&w; zhIA6yAN2`3e>}lrilyE>BZO>DQh#Qcf^SaKe~WUTByEF0qOD|Ou@eK7?WkiF*f@Ad7>S@_UrZbpg^NI@!vNZ29K6=aZ=CIKH3 zNbwmb;1ixgPvjm_pUu?3W+&hyr%F_f&$$a#HeJ;vFQ){}-9(Gvfg4og7bN}C8j|TG zAX%Rn+v*d~Z1YUhE4?5=@+)}0nOn~+FeIhZ(oax*`q)9HR(<#mEDSr%eAVxVg^||S zAW<6&>Crp^%YCg;k~o)ZU?FLZY&B7?2n*!~^UMn~>DnQy0YL^eZ5T#0*X{UJr3-z} z^n`#;Ns;65HnF(bicnx!^7C-%L21*V;96X}Fw?1)R)pxdw=0QjrIYeRGboe~C+alK znnCFqO+a(U6R@J_p%Wp|dn0VfOU0C^qwuNnL=&BAJa#A5;n{vY4gT7Er~yBnyOEy4 zUz?t?Rz%5DM+nwkx5Cq`hXLtJ5`caL{Lc zVlRAs0s^HiIfHC$r4(3fh>0O>Zy9dUQASM%obal~HAq6GTrba(5v)z)=K2yZ1*vpN z%2Jdez+Imb^i_cs_Ra+o^sOp!I9HW8sT1_ADqUMqI#7cCu8I&S8=drCx*-bg+InI%wB^ppwqrOlHSTGcB^#$#(D@u3nDO zt!Bpu>&M>kunt(m!#ZH=)7R)nTL%;-gE9OddNnc3S|E&N*BIuEnYFTT%jAFcmbm)} z+_h)wpw3t`1+R&4Q>A6FyEE1bKO#q(S+QSB2}Ia8$hMmnPw8ZD;1F9R@ux0_LlL$|J;-!>M^toim&@=jWb0^6`yDz2v`eBc4^BOJb=0r;= zooJJXWX6b3U!xxinAo|LT!D^^;x=iCJxywxldH+qmd5(T-kEd~HmCZI0n$2273f-) zMr=-bV{iJaxMp%`L8=~5ItiJ(K5=+j)2tEsYFumX7}v&-OG&HS z$@aDteNYGZoZCJx2Y3Tn3&YdoNUN<`r>3mfX|IF)FKf`v`ax)3ne`Fm;K>=oP#qMi znmw#PX}@q)ObRB*wF@(R#fIjGZ4A(H6DpNXVk?yT#3EkPOyF#t#LMQPQlsj_)Gx!_ z67ZyhU3@%zmwM_J@}O1pw96(q(gedjk9cZvj+aFh1}@a%9EWppj*}4QXt}cr!)|u( zNqdjO3AVJ|HZa{qoWo*gU>TT_=O_{_6nuvWrVi0^Y|obDJyG=x2^yp^!W!0+k%>%p z+Z1Uq0V-K5Tmvarh2G{1`9CnaL0r6$9W`>jYd9-!nLM)(i{7$!_F>UbK}DPZTVl+v zi$#yaCSSAY8wRVTo)#~@&M+1-Vgmn-4(uIc(}(=;pgcdBD^cV5j?>blGfp9*$GM6o zq-`5GTa}ONZZ7rlsYrkR@2}qPVxzRsI%2a@6|n>_M>VmU=c_&?=)p&PZA zT(}B9>|UYV5-OGAF|lxBeMJ?=3;oQWtdIC~vYXXKGkK%7XXj;CW?gP}kEzq&DdnUb zuvc%|?1uR(`)u;~ozf~bJQ|rPuyR*)x|aP?&aVg;%!3Wp0M(CoCqKgWD9Baa>Zu

~8s`y?R>lrL%yZJHJu$%kMj6HnEeF{6e?DrHhp`Ztu zi8kN4Q9b&no!8qCA$j2HhAP1!3`oDE*&AbfL`hZew3+vfnzia9pHg4TE@fJ)kEUbl zv{p}kwxjc;cW7RX(Xlmyn?uNQoGADFVwLB4#b~VFhu@?(1!aNJcd7Z@629RbuLxKIclYW zgKQas;h%P@@vQbjc4Jrf49z=g-c9I3sm#-$*3zB%oo@(K)v}dY8{FU?re?6x!3_+9 zO}On+P|^L}`oqW9SaG~y^7GWiD!X(wlPeplxX-2&nicVzFIs~(!>t2>(@8k4>l54V z>Jw|w%`=j(o0BB-d{K^T+Zm?>qR|y;Wg3BLHEY-(f0vk@A4PUzBI$L{z}Ev(Ddvy# z^`!Zv$R<%4VeM$_3$RDL!l4qWf<7{uj0?7Nq*eYbfP^y1&LDo9>^@xD&F-VZj96Hh zfGEre@>x(wHIzB2?LK^I`>v%gXkkXnXs0BP83t)i&CfOZ5WEc5S|R*x&uPP6q^s0i z&%p@w2_nw*FrMGmoU)c}72$)aCsvvy)3hX3+k;3!~y zod`OPgH%Gqi73~a(TP9CL3{!Su~$37*-0ZXV8SB`c^6xRT!syvH#ehtgecY;vda$I$9PJQnEoPgYWEg3IyEZ$8?9&)fT6QN<;JLlW?x3dGHS9e} z_UXpN2XPZ2wM@pcfSfN@a1id}bMGr13}VD>tSTaEb4=L}XZI1?tk%{z>#jGbt**CD zl7Ug0QKCauYwNCSCxMrHVuEcu{PzG@d_dLTYGH%x>RRh$y9r|KU~T4Is|jLkS7I!3 zN%)S#m8^ft?y8P(NOy^X1HZ);Bz=jL@e0-XLcn-fe^S`FFd`6yYZqqP)kD-iR5H(e z9k7y4BF&*bnHwhSfR*MM(beX}Q0_}5TS65H${-Yn5Aj{Z&{`#AQ(6vD$r7dIBq%K{4@PMZw4u;$C2-wo?$6DnEvULDmD`s^8n3xf##Zi>+F zRPttv2O`oD(@6-rVzPqlP_{g;I--DgDwKs5C0}&x%AF!j4oc?k9n}y2W>Nh(8=O;k zoKq62iY|Y z1$%KFRn){uXySH+q3{|+pkq}*A$=k(mLpM`Lr@9A4>qJYCB2cxa%L)4Y0F#LMU(4N z>|EoM>4UgYUbGm2#t^A}U%KlHx4({6FeM9+FO-N#{7|f@>_u3JFR#s9oZQQmV&U|L zm7W5iXc+-eqw-!L>|lWIMQYv0#(v~Yv^tM*cP&m&u@R(jn9VJjOyDt^?**lan%RVl z>uoEh%LKboc@t<`V=0W>A;uml*guHOn7A`V`@q211bWok1bV@&SAml3I;CiNLIQca zA{(th`LkxRpild=!4>OZ5wpuWbupc^5}*i@wF$evgP$m|SUn@+-@L%Ye?$xl5#~2j zVn@z0bppIr5VxQy@}IKwIK9BLxMJA-WowpR+8SfGz6&A(nd3_QHjm(D= z;-(X2_H@Jie0U>VNcA08pJ|>EA!tq#x)85}3n^8fVbs;_SE}3JmWHM7EI1!U(RlU$ zf_wFgZk}~A*5JJVMfAUD_kXc0jP4O{q~m5k;B*rGuTPBb^$Cn;?B|<}GMg8)`+qZ{ zcp_v8%Xh;gqJ`a)D41(JDB2{TNb!#8PWWD%W(^|g89}nSlX^nI+ zFA{~UKki6~`o!W>eS$KTPoja5kWD%y{_Jk1sONoTTpztdiI>{yBtD$W9#t@p|v z_jubCwp&L906=4-^jP9M3$$sC9&}b$_61#ycaPh(=4TI#ck(7(W40f6oUK*>pfliL z;OO&o>cXu4wvBe_(>Ajy#K>|d`+py(_rC(cgjQ(%Ztp!zDNQ^}Xg=|Qp4aI8uSgI{ z8nsvfed;ok2kX=Ffx4vS8cf$cza~IQ6|L=5XgyYZk5wau&LbKfg*o(%OparIgAFGV zG?G+Z%;ogFj{esqqDpFd;@U6*ll9nc%~>vT0I&>_sEvIlj}YhsJ+IGMhDO+oFEJ?! zf#!xnpfwCgLK*;KKHb{8CoXO?yBHK=JVWBTS7KMK^b$bAvV1cVE}N-Ny*i^pPEkqu z^<_Q8B)}dekx``62eJ+Vw-o< zOq1O@naocT)yCXSr)&g){OtX8C<0R`?0+G@PC2Xk>(<*H${5HmkO7^&dlZozyLQRu z&gPD=zjbmAfP7p^Vpf~Ds2uiICWz%Yp0PBs9n5DQT!LU@?kJME14kn>UeC3Z=Tkx( z>>sB^(VZM^U@xBp-~cLd$snZb#LT6 z#xKL`$F9`gMGNgPEd5}K*AEs;{jA1M89%4u=XCtsZSz#?(FfxC8{_BA@$;7Wxe!0t zTV-ps|E=qkCv06%eR>mO(pW?mZ@;h7y{1z8xUSSr^C36pmD(Zt)3Mxp%W`1jaVCX0 ztdPPWP4Ga#I)JG+_V;YeI&Fsqgl`_^g%Sgpw1zvD;r6vcjkUig>ob{umMbwEE1c}6 zS8WbuPobmto@INXL78Lm&8K5Te>yD+2io1G?L<%rFgb!VxY1F|fP!Mj@Lp8E{97yy zOevW2@SU^d{yrCOmN~C4p@n&^NbhD5sUmK!A|Akt|JX+yuv?Sx2X{8akU!Q&HZo1t zF3xze5L2P|&tzc^qOk4cvkY;{lE;+9O@?&ZUxx}$KBHn6e2ryum-|Fd{scqhx2l&J zCx4SJugO>$`$FmYwT$;)y|}ztWI4OY{r~r$_Rs6j5R4#yVnfkuY{fo z$Cf8g<)91`tSbbwGa2aAz#fB-!YM0Cgeb6iOm21yYPN$8z-a5ryKiiNK}IL||? zduUSvQSnyr>l56e$pgwA10>xEy{tJ&J^Wyf=DiRGk;V}Q?*80ADax0DyI4o)Z%o2# z)bYDuJ%Ia_1yH9_%dEpd*gCL3>rEHHaGNRF3aferRx#-z#2ZMO9#*&e!d2T3y*}Bc znEwqgR!@H*-?$^oHhdL-<$@k2Aw&D9^AzcDdLcrj>;paeOOLldg+mhvmmRHa@v(W< z10`4{p8-$qSLH12d#~L4rHp~8|I=?P`%g~S#SU=<4_}|kY*2)Puoo?TiQVhd*Hr`( zLcg#B%SQ32~!&+K*U!|#-BBW~&H$7~D6Ad3+B?eu-eA@s8(i z|8C%P-}H5+g8Zgeu^X4ZD_5;vNy|fTUdrd4K*LmLq95_9t#494!kfaz)0e9JO7--~ zjhE*VVVY6Y?--TerXftORFk(+FURn}fZ%oI zdIG`grt1a)zcmPA_<9ws_8LClkJotk&0DT-_<=jHq2%C|%~w)N%iharviFK>ZmG&P zDqo{{S`@0AW7`Q399!0TIQA(vr3(A{e8KM*XmCKj9r~N8(1H1OizZ1xq3}((^u-ai zn@$RBgHysJhgC^*8nl*@d?J!;Iw+p(f<~&=2w7%VRsA5%V5c|&y_OIpGCdx!DB*c< z`I=I*HlcYwyO+m`N^t{^UOjhA?><>`%EF8oM%l@VoTBWIBUo+q3;YzL>X-Rp8^zE6 zlRBwAuRaW~JvpaW>csT5qF1Lakl|#We1}PJ&@Xg7=$ATuI+*fv6j_8ni;xj+R1zE~ z($-f$%1#g~|!7IbQg#szPeTGJ+o&u$d0-%zyvUKFjrlcI@dq+OgD$i2-#&g(jK z9!)dA?jIulBr2+ckkIY!*+@27>P3_zm50DAt&Na*Z~|!$6qJuP1w0d{VeCYMlVt=5 zm@T>lsl%CSD||W$B&bi!bed+ugw{z4rP2$`bh_0^*m~NLT%UVrI&sgCc`GR^Y+w~t z*+v(c3L1>9nuxB~dNpxF)Qmzw>L&$>czCocz08_42M_yf)|ZkvADz~4GdioSO;05m z*8?(&*C#GW*)+Sx=*AWCSQwJ6G&3BJfv?`k7%UfrZ(dn!9)nKhv59yjv-Mi{PA4%% z&7DRrP%{mpbtn0ebSKFL#3Ok+!e{f^Aa1b2M9Qd7gAL+TjYq_erLrP&eTRLXYl_kk zW!gYn*i*i8{8mefN=nE9(CF!;hGYC(jW&ZlXXc zlfteW8S|)7ykeNwIcAIpjZmpEAKyY<(YG|gP*-g%(JgOp5!FTkxgNTD`!>1?os=Ai z)lfFGkOPBanxE}WvrsXS=|!84iZ&?<n_y}`s1V9LibHnhw zwgvsjkl)PX5+`A=*We^aRXCK-?G~Dn3WwHVNl`eIw!uj_*nO>=3fI_ZPU2zji;Z&| z%K@-aoMfRkvA{_@26Ga)+qUqU7h(*p$ky$Hm`{H6J0aqM1_38Y^oljLKQ!yOsa8)U z)3!}kb8ZpRZtBT_MBgnjwr9lBNcgu2LdhcLY+uOh91z7O!vTeI$Q^d2v9m9SZH<6a zCF6p=*no#L2T)&-EeisP+?=dnP=$^+#1Nb4WnM#j5dZ2vrHs_bFSaa*nTf?h|~1LY6z$=;;V*I5r- ziL3|rY@YQ%6S5v~@t|6ytOs?kB6Xq4lp2uWMO;FKk-(uY>bT2SDcE3Og0MLGQlWZ@ zkVFw4XG~x=L2ai9q;la?n8HwD3K$T%QjKKkuo00(w@SD|_P|sYLdQm7oFI(TxNycr z!1XqOp-Ew;InfN#i!R&>hfDxwD2t-BVLqS&w-Xg*V{-lh7l?{oBsoac zxrvHhBsT~*CnpgVOUs>6v5VEt^qqxv`p&{dU|#J^-&x#syXb>WOkJpN+ssILNfV`& zk*f3UIbGj?^ORP8^F}ks<_2k={ zHj%JX2V>J_9*oUNpdB+Zvj-QXH z4hvfe*U5^M0l7;)iyLBP@*0_7pp-y}ZEWF4B0xT}$vt`E@SgloVp(?s)^9oqRi(mQ z%?@*T0Ss)2s}i+B><}ks9a+L*n;mkh2%2r|uzn>3jp+a5v%(W~D{s0rP1db=Q@%}X zi3?0p@fYGAlT>`WKB((4NwhR=Akw5YJH;-<;Xu_pi(QCABqx3C_p+X#qMjgy0(gRC z1(ALQKsjtr5T_Stwc7;c%z5`DY<%>)oxI1K-;v>ApLMFu{E}EE9xn;uPvKLo)Rz1C zteD^JRD&zk=5yJlvbgLs4ycy(4dbYQ22V;~GPcFQqrpCq~obX@3(; zZ#}I~dt~bU_LuadyEs2+MR&J-SVP{t3PiTOVKnc?fH$DR7&NThJF>y{ZZN&MZYWG) z2#CM(=vVSfJag#EWp_tO$<>#$OI7FXmz&Wo;6tN*`o2aGZRZ~zjz&Xfa)Rq~^ca4~ ztNA<2>@4QrtJMepKy~%C>ffPdz=}Tg5WzuZ_VWCFd6|DZ^=X-ZFpDsmGZ(8{CHdsl zt&_j3Cn<89zdRp;8miD=<}dAJAJg0Dyv5;{bw~}lFY~`=fARaekF0Oj|E>bX`p)bA zGwwWB|C6Nm^l0=ktiHVHh+n*xA)Z0_^=C49+s7n*J33VsY-4Eju|SH^kqR3A&DC?N zV_rTdn;)rkR`i!sfyuLBbRL^_`H3PzjtquEfdZ!vrnbXO4si(9P`TY<2VZ39b zPxOo4)#8zt^rnNC^hgGR4``03UAU?S1elW+WB+Uy%FLbNlQ@6Y^T#nX_o`oVY~-N& zv~_{3`WS3zFnNt6;f3{2V|wP#cO0AXlRdINeCKqr&?_KH5Pi@JJBvAU9s*(4CC9&e zDbl@5!dxcrm}L(3az zJ_MEKrJbQdM0_++l!%X36)57P@>QKOj!wO*b1IHbzp8UOj_!U{hn)ji2ms*B#q`#U zLVS{2@|j_%+z{4znNNNq$BzL3r?g<-pHeE5)rIKcF#4NC0E&MofE%$Z{#lK)GJa0Q z&*}KVhDHzKQ9g`1q`_CGH<*Bcvvo}s+XjkbM>H77)#u?G+7I9(1!bz41mbiu;0Zxu z(rX=)>%{3~YM8Evj@eCdI+?G=XvECzJ^E1L3m-z%VeNL;Kc7urI|VQ?k5c-0S?G=# zQ#8v{_w|E;F-Gnmyi__X42RN^`*j>sHG(IKcsazZyxvN&BKhITIvZX(EAG33TvoSuOY|Sc69F$%40_p zff1IhqN{Q^sfP+3WA*?j>Y=&BmgKc*&Nm3P zgn4b|8;5iH*p{jD-DT<|v$Y={ZyW|@|8*~4Fxw&;PZU^MI|HX@qy=hn7^Zp)eP$AL z7aj>+Db625Rw{rF5mqxK9t!Qm+^oz7rZ?90@!w|WXG7lHGc08}V9g**X%c0t#2kd3 zfcIfL;-~EMUNnBpHHwvRuPMRjZL@zFcGqwdz$Le~*)BspIfR4uI`dPi=B#NYeI? zJ`R>n*1=CiA(5HNEH{^HX29Ih)00*2`{~@n7eN8?cEMJ{aU{2y6_nq9?$}1!n*cDM zDn6G_ZO@YB7xL}}-rG3b&uX@!?|==MkdP_RE}@8;rMj2>>XXsS{?=ahn_db42ox7( zP+h2gP;A}0&tmAb0-qN!V)9+2rZZ158XIbe9$38!^yjIgq+D$#A`iPX8JCqOa7XstB9GaZ`YNKqX|d3kA@tn zf&nq&&d?ChZE+;r;do=EUYQvY-vPsXW$_N)&9uL_W{=or`F=im5L7xT)rr5O50K?_ zHGf16m6SEhpNg_g#Ti|KuUSHb3|s7w9KOU$ir7h}_njiqA#uVrlT5L!SaU(h=Fw?Gw|D=lrL9YPp7Otc<@$-A!EUHgL!J%9cV;n1ED;rh6{)rC4;HdXc60^|NxZ_wI))eaA0Q)DK=vOFvHyVlTIZaE{l~y1YD&k%H~$WwHl6Y-k%%%u|{6S9pA<5}A7v_8QoiIyIB1gn%Cs2AAn zp7C1NXGaNcj1fUvqH+NaK+~a{OwFD7Db*2&INV*aMIri}cv5-E8;NzGOz;o|lp|py zo;9U#mMqXxS!9XX(LSq4PSUzktfnJZ?@EpejL6EZT8N-ZyggKnBg012RmYZ4VxS6p+aRz6c#PZW=$M)UG0Ev9Cb>T0 z^FXj}7GA*gj6H_+oixdtqH-*d2q_|OUMjmMThk|Nbj|`(k`!X5SCl9RG(ePt7SK{A z&Re!&@1r>awyJf!!B?q8w3e}*_2h3Cw}rS4`w2eOvmc9|z75NdQY4MiuB#wBDRR9= z{Wh`7dT79WVjW1|jj!_d>XY86I{JLD1@i?*cQnYad2KC=X2AqSX_{Sg!F&PTtOBR& z1vC2cpcsl5vr_JYMDg<rdDPU9)4Cvx5SO9ZTrh%DCZ;$t=;cr2w}e>>5GH ze1aLk7d@zb(G**gFB*a&Uo;do`J&Cy6xb#X%#ZfwVM^b*F?ro>rNYpW8bwyVriaFu zp3l$#r~s&G!N>03aI!NmwUfONVBTB9e(q$a2~Kvc7cAA_o|OL%imzxUOBS(0#E|t# zJrdwqc*`bC?mzne0#3tCo032^OuJ0Ql%NcBKVoBK)j&K)sGj_uOc!>(yX>FHDfDjg zzjImGAj5)%2p%L_)7QNKJ@fvi$Q{!uq$32$H2=7auOe2e1|`KZ-1kCyy-eN&VYO0{ zTSb`PJF0V1|#1elk*{u?Rs>9dR6bV}YDESwhKb4;2@XP&$%OI7C9}NJ6m{ zBqS7C?(|UA5(+o@Zc9SR+V+lYe|tykVM{0y0GOf5IU3Sqn8pW@v~1+Sc9!OebpZSs z^~Pb7Q@Sl~oD(ivyc)Jvj6NlYPtq+**?p}`inLSa!DMo+lyJ+1MvMIHSN6~%37e3_ zB3uYXkPs%o4l;jG`Cw<@jm z0e+aWyZEt8+OK{m1F0CBqRC->yjRZ8?&K#68IG-TMiI=g$GOD}MOy{xk(`*#wd|~f zC)68(S9vRG$iwQ{81itdJ~^DMYsl74EZb_8JTTj)TAA3*RV#WHsukQ|u3E*ii?7T0 zD9l{T?gKMZ`ZPf^_vs?;9@&aw9lo-l4xcS;FUy2n%(c|jYWOxETV+Kk@rl(|bi~V} zr*q^;=Db_mDK%q!8W$iR#x$z6#@e6!tIn+O!W3nI>-auEmi%fC^amogji>xY!E}9f z^#A1eXN(-Usk$$Ko2tOTg6tf{fFYX5&5#e_#27tM>UA(pRB7okaUI}q$`gqc2nc`~ z26On0C2VV#5Q-1wB;^7`!1+A<}0?UvXhkJ0IV8zr-W8&c_H4eWp_%agR+v_iBC?LHeG^UkPs`X+Q+>h8|l-1 z%DG6!)u~FGf4I-qQdU*cMOH;$Db+B4-YuDLTQWUe+?f>(>u{(hRA(*wk1Mex;@dFO z+^Hkt9!_FLlMcpV$-+d+VFq=6XMSRaqOT+>=nz-r*(Fji1e`zQh-3B7qT6J@ED|6L7cT9#_ zj|9%!48cmE#8b&@DJdjGSCl((T+6E4Yh4gwqG#xIl(!HU@`=cG(gEX6(gAf6BY>_+ zB4C3WuN~$;i8F>?`g8;d*Y89ZB1pKNmQ%$?`%L3}2>Z=~E8;aUlvG}yn3JRvMFcgI zAh?g4W}KvQ37W+;3GiazYoT0Q&KvYg-q{jO) zW>{u|dZ~RxS=aMZ0E4+A-Mu6G@jggkv zgyt5mnRV5#H*B^HO(ltJaOcm}dUQb^RE=~35tVR+Xf&Q3<$yF-$dUy>C96n=s;Sd% zs~SOC0IP0mR<(-FHi|0y3d~nEC(LeI)ts0vc{%DCEs5qNEs5JS$s$X;t?K&I^ZGly zliE(G-YVQbVG#5_V-N;To5b!jl5)7`Na%c`Pto~iB(b=g&hIi3sFRRZ!HLO&;XZAj zN*Hw;Es+sG=A2mzga&~HKVbq`FsL39W9d{LO#vYuOqJPa#b=J0e@f-1=gSlu1lJBm zkAtEh2w0br<935$O=?Xd4UuhBUa)GYeC!R{G`kj+cZpz@iI=^56szE&SQAI+*Egmg(FC|?YmIw}!#Cup;!okVfgLEV{buMmQDWe8kiH)q+}pQsi~T_HiUy&! zfg)1u(&(=j6tA%OmXIl{z646v#3Ed&B3%dWshDwK4S z{%)c1PxNt{*$~={08)8Sp<$m9ASg84@Og{?X`!YnAs2r<+bS2s(A)g|N5tRf%XmMq zy9V*DP;d8H^4ax3onUE!UCVe|zYYq_y(KV{ms+y8ZV62Dp4OC^tO<0YE7uekP*_X{ z`qZL^3^Nw%Gzgi}B5r^POGjF=*>TD0(Ge7M7W}k8Oq6Bqa9P}u5uV{NB;3Vfc|7#iZa8SJ<2^?2vT}w&TuKg$)`{sz8Bk3WJynU4nI-6};lSwyvuk`> zXa{lgtXh#0UUts&Av%Wb2Dt=eEYOZH%BXtHY?(eRSHFR}ENUFv%I2hSNPR+GfH~+8 z;XtH@=~R6mj(*vuI$sh0&{7eoW@0f{h-ZYTfR7IR0yfzFsVNIO!dI%P^GKX21M_Y@Q9BH;6( zXOnNkRvIJE2MhfEE50Gzjl_%mR!>8dWYpHPrSqLHi? z2LXuzLBEk1Tp#c*ajC5Oh{BF(LJ*Mj6Z>BbGY+}j#1N|>E$0LQ$<0_ddxGiP){M8M zAfV*j39lovAEY2#zpLe1Bzzd7XGcHiW%{8QhJIG#r;MLd5`EkNZ-RFNe{(GE8kM!CI+3K1Ki98PAd8|2ed9mY)AEDdG+ky zf>BOnpH$o4=w}WWiz()c49l~#MFSAGxgu@(=MyHlK9*}-}HpZb?oU;8jr>@ zg_1B!1|N`=1>8d{6qLXeS)iFFD-@CP!67en%Dz1IT*cnFd!5edfn>FK~m}J zFsjzW$*thejpM7p&{Cy9F)eoaGE3t5f4O-$pkRNtJvmxn8Z?e&W}2cfcAeJAopod% zUQaESdH7f_MfO#b6xml%2?&R4itJmONA{6)zei->b|1~GCv<@vH@wf`eT^^1Ven0O zpPewBZQ*^oxIMftHQXBB=Z3vHs&V`9nx1H_dl|qcj2MAEk`@HAqFN9`Gmm7oBbaeo zZGzvD(Fy``sQ3Bp#}F+#64DCreO5fxL|9VW4uUd3qEFM!`0FmQ3ZbAah-<%tdOCL8 z?9_plu1BXpOZvCRbaeKZ4!%bZ=U#=NaKUE-6?B;-HM*EJ%f@1fF!*2@*9`m=o9F+K_9C zN1IdZjViGi*}K6ZH>MN-?1i$8(|*ljpxe9*_0}>-zg&D6rT}vpY|Ms=oW>=U!Qgn1 z${Ffjx@)p3VWe)2I->oOc{!g`LtgBquD1|e;E9uxLf`-dfM0Sr)N4(t$U48AC{O_H znKpVk6j0AONWmAm6cnW0UcyQzS!{#x&LO3RvkO!tfCCkCX+6$&>sJUr;4QJx9;QFS z6;o*uw$2r2>70e1iE9=-DhN58ftBdq3Vv)>B)+6UnDy{6gt;zsUu!KO1VzQHSMMo9nlRtzuzw8}<*4|NzRO;d;rbARle z0sVD$rDRYbN(i9dDjX=zfJ?}SmMBCPLI}_Wx|$>a-@bo|bXA_lhAu%5=PW(c4`ZzI z2bUNgaZ5rpAj+-zvr&uGC4*98Hl^SkkS8j+|F{uj3f^S;ta&ApwRhq&e zGzD6qDfGZA1Un{7+7*Xf-l8dRj;5emHgz*Jh3(B`#*B1)AYB&nCNU?=hQ; zdvH8<;F0TUKAS2QU(e>yv$?fFGn<%BAj8{cQx~_-W@@-~Hr;UBY~rkq**v~uHWxjc za)0kTn^Jcu*5hXT&Sok~V|u6AJkD$`YBr&;s=@48HFwj|V$7_609ZY8o3R%X)IwNL?urAw>ix1N&8NiWg6B(m$K4tW z-d_toykJi}*h>&4xLbUBjtA{k-A}8!-Jrn(bI|@aJaDnKZ8;{X;Z{6w!)83X>3v12X65lz7as67+{+Nnh~@Q6b~~=Ns)qB zFwf>Y044Rt2F(3ej51;CX8W!fhbW4hGBVbL^Ltr1&*s2OVhNusys<(b_;irR^n>iD zA5!M^L%zIz%J?}IKcva)V&ur{C_PH_rq13NKW~nox5Uqd_<0za#efDb5%M1rnuH|4 zEQb|?CwJB&8fVSM3M??MO5ISi`Nj&KB*ajLB;J91ptOCC9K)6|N@gp?{K~e8-J1(_ zRuYHvtRznAm|tcW+onXe9ZIdN(ruMuYCR*ZuCmxa=C}25ZQP{S_eEc^8Bx>Nf<<1s z=j!VFcm|1w_r8xY=9Y6rh#*JHAq@|zzx%tC0h(MvY_G8Nn6ec8x&xcXy$wM`yBWA3g5gi%|5;i@IYDaMc|EOJ)Wilk*8llJI>W}{pb)Ue|1-XbG)}M!F zE`*Go)l}*sUAusCK#BnIOHa%fqQ03P5kSupl1b4^XhBPeLzd9OU*J6pIthA2%e|KnTbc6BxgapTzAVY+;d%)L z>oPxMGxCg8LDlxWki*dUA@eayibeJJ^VuQ#3`&k`XZWOIDrXB%O{ac=_3b48t4xV8 zv_tMM_Ugz)nko}%OQ8~J(abCpV##r9)sY0Qgg`GER!@|khyma!q zSgGrUmWVZ1fUEI!dQp1|(6y`a)D5^_{kpm0H$yzwJ zweY0mv6ZQJB6NXQO+>&qq=c~^Y>2Xoi*PQoE^GBIW-?84q=jwG(eoI#=QJ6Z#_K01 z+9ZSPDa|l;1cc03?u@W`!p|HHAWdN+ekryGXOkKyc@Kn`u(`{~ha+88uB^EfjR}9B zoYzUsP{j*Ql(&~9w(8G%m#uFIT&^Pa4MP77fvd2NSl1m4DgOBodMz?Y`7T1%_|ls0xxYu)~LB`h3PS;@1Q;IqvT2wmXiCY4xzQm zxPWh!uViSD`caGQ)!AYFusepfAo^37ix~`2+Nko1r|mn8&4w9;Gu!@yLstoB{Hb?W zlIy*%gtJbV#xMtvYizra=riUwbrx#rSYf465j~W2a<0ucSo);9n`)QLWbdQ9{_)Nv z>Mr&cceg`vjd^!v$U14>X_7W9ZV+w@J1wao5m=9 zBalrqV0cr73vu#0#LVg%$$coS;uROTz>gr0a}L{%%ojd7C4NHSwcL~VYU{M}n|1gj zzRHWT8Sk6?QxHXFn@qFUwFNQPTQQINGEP68VqXYTB2RN%RGGKDTU2C1YvP9LxDguOfPuGp zc#DBobD-|k244E&D|8P7Z+1s*;FWXQiwqOF=K^0Rh3}UM7Q7kHHCGwfs!T;3GO$%y zTkVdCfzjM%lk~vO(Sf%&GAqr)9$nKfK8Kq6)5CnpspYFsB36T<6o>#gGPMu2a|T>f zc<868b`Zf7m?()`jBxTL?i^PE&M1R`{Jb=pEmn`5BmPhZWe4hyB?vNdOs>^wlI;}3 zVndnAF@x}^=Epe#CnR*yg)u>nT+|UuhRLcvfyBMod3$okj%%+05T@!f)=Mk(!MmC6J2G}n zd;`6WZaQ?A>)ktZdRzyYuVsf*%;iWBh^7-|7Q4WyqW6JB(+RG}IEs24^Ooiqlt;*_ zpK`LkLpce&fQbM$+8v*g5^1B2C&bCgK(O?t)iHZ8JWpCl&4u!uvNO1%bdR1Q(QA2@ zQ_YIs5*1(cc4$t*0Vn4B6{=ez-?TP@I_#k<+#B*JLv800v1m--ic%DqDhfR46vgU( zT>%?7Q?S0EGRuW=lgU3Wl$F37O;SV>hrknf=>>Wb-WF1JF$9{4LrUj&I=-XYif-ll z;T*lQeS_ty(N`5|3KKa==bjh`}pPQ}mZ__>>inYz}tpLrmzzcGH^ z96xV~p9}HxFiZsB5|b)SQT(I%4)TRP>8iOQ(Swe|jpQ(B9J%lhi8yc}Nh-aTBUjXs zJzAJpEj8h7xBA!FIUQz`CoJqZ7mSbTE>qRHGyii_#{$tGiLR~yAPyxh{vlmcosLYB zc4;wQht%JQbog{4VT&lYxD#&Z`UKgAuGY`UzTKSIlZ2C@ME*rux_2rgEj_i914iv{ zvpn?esB+;)iRNQDP{+}-TbPre0-ZX|O4SG%-HIdMg{}=PMM~T2uN$JI&H>k zDZNhpPbV?f`h=dyGYCjXRrXk$XKc%lJ1KWK#yZegW48#0o7wa2lg>NT4uD6V4(F2b zBnojT8Bd}RkJVl?8fw9P74mc*%kyo;msn8|PDFnu&mtw8j&S_XA=6QENl|8THJdyQ z(N?Hga1}R@tIAQ}S`OXG7dunNqi1GGoOjgX7ag{!SB`$Ho3qVJPIiQ-WrzO&MuC%s z1LsI+GXXG^(p$(KK~vQRs%rlpbSAUtDT>1pt3rH^`}fUA#&}SeY2%e-F1ZEgvYHBH zv1k18$RY&wSHj(07svuHYfZ)!LA8f_lL!57+1Mg?1sP)XO11j7;6aS_ir&j2Pw(}* zu%EAfuSL5kyk%hNy&csw#w$f>Eq8zNc!$LVcBFAwyZ!nahsNU?J()(4SC=SYD~SUT zt%NV`tHlIiiH&&e}&wI(sxh8hXf3K?A3I6OpFHvJ*4O+I)H2tG*NH2WVz#aQ7nmX;+y9wmf(({%?W zOX)vLzL_MA2TV5Dy6G&NU2iQTXas|qrd^yeect}N+hRy479;xM5kU(;0V2l5 z;6XT@J(&wpwZ*)9-rYFd)!^lkM$oGm9(_h*xu4FI+17z``jLD_C%RCqNDOUdyG%?Dj5E;N)$bjOA4O8hS*3s(fc>qR)Z|BMN&38Pa-Xps+FB?x@{TK;( zX*k_Sm^g6+(QxpGnIrNCC9v#1wf;NVBSck?NVsPqDb|ult6Sf&q(oAEHa_MA0p5TI zMzsE|1Z5F(RKG`jkk8_1p`4j1di%MndJeN2{jmdw^h88@X`L2GhnBNS1%LJHYhA@d zA$^`q4<-p(RgomU>KD0Itt<4IDLqXcd-zh76OBdRs52*o!0uOqxbORY69XGz*7Q=q z56$pmS>8C@k(rMXFie5P!v=b6ZMCG6Rl=_@bby&_ypo>=96%rdN{q5Z8;=vIR|n*Z zrg36;1vGr&tmSZ@GDKwWW{66u?;Yn8DeA!ZKfg8 z16~Mm4{9|OfEdk~74stjAZR#GE9R=E{$9(bHZ|0M2O+yG>YBa`N7V=0kC!qM)Xy(% z93Bh0fbrLJ5$lrD&<5jL_OjH0uE{yJa2bLyNas}(@#Mm#2(x_bo@_0c(1kdAIXp|o z(l9ab{?cdy*F`m!^vU}q732y;27X|UzQCyUBBs))6mzH>Vl52kp6q2N1%|z5)Ptdve1%Gv zR}FXZyaESE5|6|SSP{IhVKad=TW4`8h&vNk>djTYWuDAkFvC?n#VvtHSgIPjtG*r4 zJ9SxFBIifT#ghb-m%!oJ=tp}J&O=WM(Ohd--e8S*qV0Zwe0M54hRmH@OqDrTqKZ8H)0~lYgP~3s~LvauErYF##=0s3r}kb{&Z)rX_?<3q>-dXom87!?_0QKqLup2tr0BA4@(8Yy$H!PNctpPdrFQ+8@eM zTJ;EP)>{*O+Qqf<$zSnBmZQK)L3W`vrh*m8yycAL3XzgxPFeDlO$XAyNe|U^$yo+b zmps$ed0lc&s7oHJAYM8ieW*zFt}&jrx=~F2imk6{|2<|a?dr!7qm(3!H%bpY_t&Y- zpt|w+nq(_xS5R5)=wS>?Ra!Vvw&Z4cIhu0llCi)KRHwQnPylfVtoGVwzc4I&IW*6R z7CSv1Vlne&KY#_v&xpK6o<&@iy{PWipF9%%f_@g7C>~z5$dz8QLP;Hw+hXz$kYn|B zM#G%xn+)ZzA_fgdPv64c9vbl##+BW#A-#{v?!lMzQjZyHytef0xcHzZse3le;Wn5c zBu5%JzRUeI@KvDivt`2V?>}# zRBc-y=s&3JK9XIF=T0OrJdU#Ja43(XL?7Gs>sV-e9EIO6_88>VXa-@cYXapKOzlj5 z5aF{0UF47*Jrm2l0llz!IFV^^fusZ&PEl=YiMBgBW?ll?vdOUJSgh;q-E1LyuqY1X~yknD-Y&E&Zy2z2s0a z<7|dm&N#~jERkJ#$vFgPyYiBwOV^f2TFMe>Bh5~4GvIH7?E3gn^KgwBK~%!v*L1W) zMNlBR+2|S+1m2eV-!IF9XYYoN2&)Fh)-yn1u z2>yZ+>u(UceYnim458aJp@U2#`e`XABJ?%5w!NO8NpyKfXT!(`#XJBZ+9LzAp(P<( zUmwYA9&We{)aD_~1N>Y_n;dq6RbU0%khh9Vw~m;LSVga973MO*Dmr2nyw|K^+x$qd zX=raD!6ukQLb(=`2*GBLt?(qjwixU6sd>%AX~;>Uv~~OI1Do(N$_OjHV+%r&(yMD` zY_3)qz)jT(Tfjvl*~1rzq9%d6$)ulNUz}R=aKQF+!$RAxt4ru*`oWlr*r9bRb1_&$ zRNzBTO@|UG;wm@ve_5&=TcA`q1r=dOK<`5Mi(I+kS2b4-#w@&L=O-o10b{u%S4#UN zkY?%d7~hcglkAoSdIhQKgFpebE6T3E->U(pkz9*@kfz=Wc^05Vv-K6>#*7w6e zYzPlomr>wrpY;?e$Q5L_o+1Sea5`Ss)nL-LC`Y5}^!G~z6%f4Nm83<2a4?Fw1Ric6 z1^#1z17wY7jXh<#BtyCMM9eG9J~W5=bPgT^y}5b%A#KuUS(nQZT!xq=>a$OX8PB5H zYcKkEqjX&=Kw4?x6C|!YiJdvU-Q(|6!`I8eUr~hOYV`;2>Q$%GSENN(|L!@oNs8vK z=kJ*f*N5LJ(=`N0HC?&-vFQNZ5Gp^%O1rxC(NpnY_q~Mh4cDK$or+=P`3)uL={LQG z?VhKaWG2^*!b|i+9U=V? zs->TkvGCV$68xj_e4FTrsu6*4G7R=q;(}}=8S;BX2KoStY?sKgGv&|`218XWA_NQv zKl%;shC7i1UeOuis5Lr)vAvZ@{TcRf1~jr}>lJzlo;)nl2&;^Vsg;e0&s zvLn{Cn($p9{w+ZC+>Gr)34L&{m^S%F-^%PjNF~10N2W6!e;8!$W6;1~Ui~K(JD^o} zu#pduWzClsCO@7tn+#{4y&jNZ5LYPapqvG75rAcUzV}DR(MJ#`$uyiGaHP!x)XYRF z?&u`#{h>P!c9IEW0GV?!c2{l<5CA5{lK&z@nf$Ucbr_Uqiv3qG(Ap7Ms!|GLX4Ck| zAA3%&J&0<)Va2vVsCUnI5EZ_MdJr7-pEruY8igRU#aLcXIF^=^Z=r%IODlFZ>nE?! zV=S+4%@0(!TY2`26yFwYBj$cZQONwC5Mg-;vXUKbg$d#$#`dAkkTaUepp1iDeO?Ct zURBc|kwG3{HQL$CE^KyLh(Jk&&!SypKp%}j&I94si$66xyDjdRI*sR*POB)qS4RLu z%qY7bxEyQ*NA_GHVC?S5C65?vd!H3j9Wk2s6(Z+C(%7`M;McOF7?BZA&qbh1pU<2fcqG z)h1qmp9rTa757kVjEZ}J;n1(8>2e22MgP;fZkK(Iz}G1K{5kJXuxJjoqwaH3fKr}4 zl!EztW$}cAUNQgRvH_Rz8n{-GlqG#>Yrt!^{<$m!Q8H3RHlgo4gWdS294(kGlw9~S zbgh)cMqmKGADkRuP66R^F1_92@${+m^r>jPwp(M|-O>1TYJ6Iaq2>2vU5+s9-3{j5 z#Rhl*R)1Et$9H^|lq@wF#}DO0)WKo(S1*YQqiL$ljDLtQV9)E^d*asVE)kti!I(@1 zT8Ecs-KVBUcbgLlCarmSsyr&Kp_vz?PJzSlclCBbnt4h6_4VtUm+~mn0+rF5#dW)K zisY(oW2)mWJ1{qwJfhSB*=YwV1To&AFGMPHtQa$9=+~IbxUlUe&v~LzM^w-$^DJ52G(ZYE=w0ei}eTOosfI$isBQ{!6t%Y>pq0%HRM+bfRL1E3wReA0JC8FODf3d zDlvb=NdU`r62S6Egh$PK#_NJrjtf$&h0TUlR84b$bzVD*+qJGj>!zKNM6dpT+12jR zQGq}wkfQ(8^pIc3Z4)nTAC7h%2+<4G`j8e$Pt?z`U?7ADH!=(TNs6gn&q7iCwfcH2 z6gG!1HXvf*2%Hl!ziBHGBkqF50)f-pksZm(l>V%KLw)((l#nFeoxCWMjl%*%(x>?@ z`n00#=Uy@n=Uy^S!b?U=cbkCv9Znj({sw$e&BL~LAn!#!44?i}NWiX;_IA>SbahH~ z@4gCvUO&|WG)h$lr_fIX84#o4vj{TCU>bzWSmy@*Vjj$mFg21GByL!UQ9SH4~$+Pemh_V&k73Xbi!O~;@dJwF^p*dWxH zupL-r_R<3TR>u10Xs8`pY{QzEpF9}ls?j*v5mOg5xIU&!9K|A+Mt$u-hN)DD2`W1>Ea?mK1(PPG{!z4 zQIbA7#7Au=8U(Mbcnf-$NL0$fP(cZ(5($8~o}{u8pP(En3OGPR%C6IGc^mf@Bi)kM z=z%UC2wtNX3VOwp7;@M1$B_$sRJ?OUEUG`v*EXhhM(DhBFa`RVMI{_wuGvl4s^z5b zhPHGnOGz|AN)l^BiUB$jH#p>SBl1X6;T)lff}BmWCw4ZI?jACfGaZvmE!k4y5-F(2 zP4iNHOP$2P;I#G56aDhg#{|;36Gs(c>q<$wOOf_1_nX}(dZ}2F7=PAORzEbatj^%~ zsKu>d?Dk8w6a~}6sDI@$PatcVI}_+u64_>*soErre)H+hIa+PzufNRCBbTbL zJl7#(E{+L=bYR@A7T+E(-rRgAHbtHC&C6O4=pWUQw^z66@nLyZrnSfY>xCL7_lb;oqPu06>M250CfNix(!%0+fdH{Ye$AchyjgT z&}F%7h3;Yty22A`dXwYwbqZGY3k|R?x4>#`!_jMot$BJvV#65lizX9Kfk1_>*O$whLv+2qT-Lc5 zG(@d-S#Qs_!@{#F385N{9xL*m>MzVwLM4`1;#sZA2P`sWRf*l@(MWu&Caf!TF_<|? zkD{EJmMMe*p=@vnN|33Eg&5rF;%!=QOAcWMlkA7YWr;KfN|KbPIt5k9(*4kTQMo3M z<#H`$FY9D~K3)Gwt`E3wNlCI-g-9o%PBa4fKp#)C7ocO&cgPz9n8<`@j|q~sc&INX z8#geT{2$cp^7-gzmx~1?N!!fw=Jhg#O*OnP78@)lfd1uz+OtU~?eRA4Zio4j;myV6 zW{)Jv7*g)U7Nw8&poBmch*=-?Hhi*#rM;0Ljd}vbbYa8vhfRd}uE6<+P}ndD)mf-* zb#xKlE1^qSs!1JPX!WODL<7Pb!ak;HN4^0M%+=8?JMsD~ix~oEfzy7k9MXAskqW(CC5^z?=5njUR0vdi>H2$VbIT2sS2u01t;x*T|F z_-Ot8_`0V?v!cBqAt_pX+5IzFZu$?1-;b)7vhbdoE^E@tEV3b&TUtYZr`DhXC0i|_ zEu~@S&API8zt$Ka&vT7IX}+Muv!76^Zg&rj0YO8Qqft{7n9f!#DT_kt!L|mC#vtv4 zN4J*r4wa>qmcdd^4Y%&v;)bU1jsI?m%}DIJd#YTP^*gJq*MZ$T+#w>h+w?ll(d(3V zgp>h>%bT~OnFv|vb!}gXX!jK!89HZ^>fglKWN|ZTM zoo~o)Zi-N_BKyt>gA&v<5PZ~ga)Q{sc{pMWrRI@@6$-!8u;NgB@j4T+(u3r8;b9{QNqNakL>Qf+ zibx@fC}N*YsNCosO|Dkgd62~!(=-I{`-LHR$0aIFej^93Z3yo=2Tk|LSQ8=Cb5XIP zL>Lh&Aj3!jNjVUa-Y@&Ht}}l|`_b>cxj1&Ut2!2)+FzvmQKdl~b#~MsDLW2*>R0~~ zIrt{MV+DPoApXkR=4CU?rqD91BW&(9`DpI+bOaH$13^g9mJW!wx0R!YJ_kK1@RV1t zkXl`UuuJ7=@+&gK-{Oz)N_1Io27Z$^Q(u|3rA@GbPmv;Su$Hos=)w_-Gw%{Hgbh1mxN6kmBjoVN)cMR^N$KErZL|MAYpU}lHB16O?-`*PLyK-*W7AbiGTf1$eL;__0K z=Xu7TO#cE@)I?3i|7@ai$Ym=2hgK5B|B!B@XkMo-nn%?VaU2T+7}f*gdRr@G&VU)m{|>~xAq!P~5u!S7VvP<5jo7IKK+Em!9e5MMuA30B*$ ze&*^q3Daupj%cpHS*Tm}+-pI`k}A@VQTF24^oRk2l?sOWQ>w~RdY>0Ic+tw@n4)kq zY97GucnQ`?S=-8W<#v|*W7hN@PBPADKKX~jeC?M)bAE8SVCPFtz(Wprtp_Fb<#;)c zSg85@^a}!^vYgueidU^RrI(@^g47ke7**fCaU}vb%OmIylvia^vGVfK8e1oUt>NWO za3nBUYqnQIMw2PXKrjq5K`})38VIy-EkYJOAOHZp@^(hbY~Id+hy9m0$vCA6!FcF?00a0scAr?=T)buop& zeLOqQY&u#rv232okv6 zm8wECG%SoBQx=44ea*{cwkZ5x7EEV{*IRqLr!d7Lbb96V9<}>+5RlK!&B{+-VWkP|7 z2>CL}5Ltl8l+(w>rFvpkr%EPVh+t%}e$){n?n^AJCW>I7p>DAEfD8nt8ImjgA~Evn zWxOUY_?N+xbIKi6Ysetx&OmFa`tv%BB>JN)ux2?M3J42VS;s)RUgeYT3m?4X$*vw1 z&lIGP@x(V@ou9N^QzG3FIBJFr<1GV zZXz}}(#cM%lbv}db+~sY!IXI?O=@Hwlzd_;r@&y>56h-EH z5eTf0Nx^?IG&44+l8L+}zvHE7+)KOMt#{)1NGIuvyr8Wto|r3(C-zhpr3<#bM`9n% zR?HJ+bnOvv4)HvgmVcVt`uJsii20xQ+P| z%~uf)d0^8IP)1*(2Mg_WPGlNvxL@7}h>-9~|iIQXN8tcx)Y=jt?C}36NwsEl0fqFFN39FFn|$ zM0ff3Vg-KCD{x`=)h7*Sx8)}P-7+khNoAb^0%qH7w=7nx{^NCU2ulDcC1?i@v9FkL z$2tic=xrhl2`#{(K?{dOMcQbj83{x}jnA-UK9Q1$OLOe;zc`%DPw3GwV`oIgIe-!j5Sj zG}Fo&Mjz3Xq!}sjK?xaR$JT>@dh^G;`J|-5l5`?5E=sCh63ra)T(Xn!%j%hqiFKjSBi$3@w^g>>TdX@#=Yt6Ewb+IjJ@?w_RQM#Vx zg=Ur)>REO}eB@;9mCHM3d13ci#?vi4-!{ws^n8{dptpUdk&dV}bW5wM9Mm%mf-O1j z^k9ILgTzYZe$$D`pIGr-rxVh%TQ7uXgPnL57~9OS%@k)D&Mq@7m%ueU1{K)5W2@CG zVvfbUAOAr*R9Oca|ouX6T96ALz5wUOwL+Y@rg=X=* zg!Z;(p{>%yd*QI`P2ztR-A(9W4Yk4)dZVNG58FIi{iHMAP=E0F@&c}+PpkjRHpOl> z`9E`~0Wcxm*{Yqt&?2=5gg8A}1PmY9f=AZuGOd0ulU@cmaVJXi_I|n?xgsI&p;kYa z30&hRpHfzKEi0xs>jkUqNX!qLVceLRZ+1lA?Nsk4d-GPNOV*|J&CSj3W2V045n0O? z9UuWLeoG}T3=fTPu5N}Vw7r=~M|fzA zdP!R2VaLzo>Zhwa)uB#x3IuFvLt8dz+i|m2hECPG(5XFDp}ivQz!CsD|6;u(?i^BE zooHKIH+s?YbE4Jz;@XL3ktXenTYnwfNZE-b1OKoLbcWebKV)_3M_vX9f-HOBe`Kf) zQ+Ycq=c&9MN01$9KvtomyqzLTMHCg(+OLCJjaOK%k?b^!*zlu)Y=@TYWt7Hm&3!Np z8V0%{{Y22~unBs_AExE#pjUi1eB8|y^r|PM;RR~MWl7ei!>yoK-EnEV`suo~T}M%` zkmQJZbvIL8J18X=fybdss+%lrNqAqzu7|BO3(O0O?FHHOa<>q)0c02=(<2=QK*9xK zXLjGGi5X3g$C*%aP$2t?O^Mu04|8u8~K_jE+Bt%A569Jw69*)UTdaBdnAI zm_oTg&KM%C20Qu@REw|YlXpbW_n>*2`9 zQV9C3lFEhn2%F|u17Sb=%L?mRIzSFY2ew)Z#&^&+utS_f=naGQOO(1iU{bKN^GqPr zjL6QT*iDtY9P<&X%#?_NC4HA7&nWBE9+#ya^?UL?w>jZQ{OxM>xlaiE-h9@s8nmZ2m4QV>){9m;3KQp zryxoa2qaxe7$V4uwY|k^4IRRdd;e^aiDq2Pl7a|8Rir_gTQ}u7tZ2ucY%YWAPxPWT#%P! zQvE1G)IZ17ym)N3X!2IUg1ZJo^{;BeCP5gX-qs_jxp+)wGVH?vBnit?fHm*B?EjAy z^848VuxrQ48|cm5^k(opdNXV+{bA3M1;|zrJ0v>EDcPLJ;?uzm34LtblAI&0E*q(Q zI~bi0=NKpDiT2ASNjG9NH;0 zCtRqhtt2!+eg}-L_B#&B<#s}r{M*t+3|W1ITE{`0!{_?D*~R5?*5_ZYKmCGGf&cfP z6&6i8dU*&kX0P#y)RisYgo1!7SbZdaEYVlFL4J?dME9{NHQm34^AqvletAyyD*654 z+_!-(e}D?u9aaDK2788j?63`DYpXAOAQxRic2kn|5OTnrbtyW$ycRCUO>j~IF88`*hPcE_Vu_(^I>k*~DH9PofuIig~OB}2p~ZEs?QrN41_B%SgD z;iIsC6n#-}g7ByAi}(vqPoU=f5T``9-7C-{&Itgnj_-4aE~+NU3eJV)SZRn*n)o(Wb>mr25?lep+l&KDTJy# z@tC4rh(W0CgyrBzL|bRZk#5aPCf^6GWNzg06#{qpgIq2C=!@bOm`u1H@gAaw_Jp#- znnSW2qQMDsMf3??3ANC%=Vw&lsC4rD+`6r&X8 zp*WKNkGpq)vg|7FJI~|3s%||_cUM2u)l#2()U--cwIqxXjU=FVqi!`456Q+J+l#e^ zSr9L+Dp^)Hjh1XnbOQop24|F52{EDj~_9(WN|eFhJ|IXv$-*$wzH&D=5bjHI0#fGF8(#$sUCh z47_dKS=+)&g)$kBpbOxkj8{5_GGQ@-l(Sn-!9l$ex`Lj-rsmu=^b82+CI}^)=EH|@ zx`CwfB-(DvYtmAho3xqSmlbRjv26-pvrTmjE*QnVG@RN zwv6bMLGMJI!&lCe-JwMITV$MuBo3#@QfVVfG9y=ar%_f}D56lC_37A3eb=3co#{@+ z&Wxenor68e4$(hr&Awl&l5(VNNu|Xj5s5ndX0CG=Xuo(jK3)Orl&6{H@B}f$RLqQz zS=vf0x|!&1k{Ed+8e1FGDBb_f{Gd9>Z4vdVysc7EhpSY~Pd?J7+OZ1d`dj=e6IirS zx6uG`IGYC8^L;u%nnRCaJy`B+w^uintL1j7_pk z7iuN8^Z*FyxJ?^(H4o&|>j|9)P4c*iP@r2VtQOBa*aU>g&V59K^>w2P8VvzT8?v}fVR%!Yh#)XRC9o=8>wW2>F|(?QV{ql8_X z5sqM26<~^plaF2wg(TX8L9b@4$870Nbjr5(u@j*NIQE91kELL{R+=hhF`u}RdsE_9OX#7@hlHzZ3 z>>*r4_fpwEtxSlp510xJ+qG{y49ZGrlq$tUHJ#?};HV4kYDh>uWpm?R*|1Q3uF9^| zG|ExX313#YlFM}+GKbQx-e@Q6Uj5kvm(=zAP@KeDdmy<$TWQ&vCrc(_)kGPl?Uw*I3-Th*5&I;-!@pSO?e5>7ui?{Hg;0QSJBv6blP91CXU764IB) z9~5gEg^0?rVGixsPL>sLBhOUG(s{=+>y3nC|}jf1=T4iBIGBa$g`l>X+yDN zQ0x>yvF>i&`IYP@aT&c1WMg0`Hwn$c1CMC_%N$pDcz?Xt(%FMJv-wX*WTyu4*@N~o zxS%@$BMA>blIuT}a`B&p59_z^UVC|rG7?zPXAX_l1nx%wbi%_l!++{R$DF9sj@M1T zX*pi~o7Psk$rFxRAICjdEVM9kX9!H}VsRQxVV+$y;#I~k_c7^MnHCN!VD(5i@H1dm zdRzD!>9t|=wxWku&GPAmF24)&;_v=z{~G)v`udA}qSGgl`q!ivz%!o`UxD7SL7qx( zSiU;h&Tppfvjk<%cWpNaQZ`W(MH(~Vx8Kf&gM^#kd^;sO+&pxeH-j(?e~06zXNtoC zf2pZ#-vtthtv6U?El!}3x%gczFY_ZvH`u4MFzy5V5cD;MW&9izUNO~6Ox6VMYI0M^ zj%u7RyTW9RezOw;g^;|J2R9Fwq5-0^Gy+4vY+2|f{7W%J_2`n6Od(qY80x5xNZey0 zB>KAvo?qJ{sWIO}S&uE%)sI*}3aX*pGK9&i9V zsXA1Oq^>A#2N#-3sgF>JSSgl{RjSMrtsa5|V#}*@T@P0f469sFg!$G`)QoQcp0rNM zp$2#`B0e4)DP8o15ZyF{Hv+;yZVk3MQJsl=O`^FiebTy#ST>V}u$pX*`De@CRC`4G z%fp$#a4G$;vUqU)u;j!zf zjy(oxZS^G&Z&PYO0u@1W%e`+3R&koafgSt`7D#Vf=2^BjhI&XaW)1TVe~u`=QAGq; zF%n!>-1y=cvvy3_CC)xLXU?vgIyGybCQ5a}=89dJC_FT*iy_9f1lVxbkwku1&i)vj z-Q35_sG@2%ljk;k$(#3fw)f`2qlwBP$%P9;LdP_>=VsVP#>m237dYIEGV`&$7 zgzsL(CUM5K!d-#aD(s%QgWT@WVjf~H6m}=BFt9s{^OGYiRst~17y_|Gpr>GfO}Zkb zgzLpNa&9iML348{9#J$tGfDX%sZi)%YutP#`*>a@uav2}nke~$+#zLB{Cu~`6RS*- z*gtR2{HDy~i)8qjKBugt+7CR$MteL_X6s>iEFr*f03khT*|f55@5j0H8=na6J5stmc`L|CBoeBSd2Rt*4ZBdPZs_ z-hF2ac2Tw%K7Bp?sVMt;%5YhtjOCTK%N~7kO-c$m&EH4>83T)Vz=t%F1~L+R-3*UT z6ufR=px8p5fua%7%t<{PRUvvez1=X~4b*E$aEv7`<}dyH-;P0qK83=ZiTGB_{{dOL1Z zW2?2&Oe^_QzsEQZTsN9Qw(ppV%JDb4)2b=$x3o_Ac)Z|b0tYL|){KzIcO!hmac{;T2SZ(Ndo&S8y(Amz6l^7aArAq$_CiB1H^~KxZUdqlhe0)o` zV@%J`@xB^4g*rl{dhvlLSJSoyj-nd2p|p_{9dd8ufM zz5Em8?B~!P!g)A8P^jU(y!{++|Fs-~`f)fqk1tVq2%tgXq&^eRWpW@%asOy*DovB+ zLWcS>yA5QPmGLn~YDuck^l2eEq+iJ7ymzG~D^}bQcC8Tg7(1vFct! z{5}nCFIWvbU4Mb75tUXQbZ@cTm1Mu z#%=c)rkjeeW^J=r8i*7F2PI)F5nya;Bj5y8ah+N6!=zl+mRd%7P5J{7`>cCR1}$mD z32|P|W0AZOKfl3gKoBMyzH#hpwW$Yd=}JbCwyGm3##rV_4AP}9$gX_D6wpPcASya? zW@rkkIaHlW>96KAXnFsnc+DP2hA3W)SD_3Tz;b13*i1kl>le1F^$+HE;T86p9YdUt zQEqD~mIgA5$-4>qpGEDY*4cI93ayQBdSPu#o|HQP{0Az&KQ^!6LuBKUydwK^Ld@9F*N8>P>Upg5WcYdTTy*=Zku)#iL2Q z!1aP<0?C7tBos%dl%32n2nbL1!7|5%Dbh0J7yZmTdV}qX#4v87)eA{iY{O(8S0~Kk zAiwh~>`HZyc~8Cx;)9R}5~KjR8t0uT;9sH%D1l2RvOSQ%&;TEXmjb$tu9MZ|Is$&S z-Y~D+i$d1X?wX1tpnuu`osivtU|}^aj=*o>oAyHCkm9St2_t`|OXY~Zx~}A$21`M% zDZmyhIC{fwc9~_OSMpVt+FXLP%Zh)gjSaxcnTDVwU2aRw3%7*-;=FLnBrn`z?xPv_ z#)kRV_Pj}5tsV84o;~WZ^|3G0^yrwpRIYJE?8J;v?(?GVWf6Yv7mZ^Vlf5j|OH-u8 z5*hNmaNFGd0FIhr--~r6i{Wj5&nj7*tYp!LDgh`~tKQVw4cn4MgRa@2?b!R_XYw?! zlP=mpJg{sf6-@+}H;L<+lWSk--o~Wez7BI#Fp*?Nz@vP+BdjQIJGx9>KzD~#ykNyc zl!&n{LzKQi0!C!+80s;Jq&rmlCVigh6XnPUpzEP~D~A&OEG>&@4wZ@ilNDOxjdOl! z+W4L3wY`&8(7Nu$s6e%pk$f+UNy`Ov9>)d_$7SLluM$4s~tJH=sjBMj*VLtd0qdL+ZYWvQ?(OMk!*C7lq$E7?iexi_)?Y9K_@mc}A=n@LdCwWG#6Y{2L( z8Zbf=Tq?DqEqZh*HhgC@e!0>V7Dn{>R6UUAVAU_?D^Qy6#!O|+?U&4T(l}rU6ZaTbCRGdTc7_4 z@*D&uvSVEy+ixYi!Z4z3J}M|kKk^-JND@`DQl~jc99QD!jFGQ98@?7!*`(O4)Q!2T zK|XF{FML_*OPE8%Epuuc8^Hr=iQEKU+_1*u2Td3;sz-dE z#nS^Q^9xj(hM~xwsy5Pb^ z^`J_?Xk=9_>`%_2mXvC!hqbwCpgCe|t%M$Tn+gS3~-%y#?rzh`c=FJObC`OR^;lx0BF`jQLwMLH^2IOn1uWG*{VufpnRs0IF6 zb~h0WVR2(yG(4qrn$eag59AgS&Prg|?T!qs&Zy z%*IwNNg#=7Ninl(1MJm?E8@1b5Pp0#8&M^0BMXXPdc`}g?o{4K(QrDNH@Q{A%p<)uHtF9L`CLsh%v;o&e= z#MvS^eAu2SukoDz6vZ1qU`VL-R=*+AilM=VVZQk~&8vw!*~4-^_vVc_pAte60RU`P zCN%?ejdkDEHQ{(&Qvwgt$=g3!tq=tOH$K-TE4r%8rnL`7^$<6r-{W$l*H zN#5!3bpk^m%@HligR-STd$RxAYf%GnFZlQ3aWQwi;+=|+2Yh)6EHpXKFXEJx8V45))#(c>-Mw% zTiCwX6zFc>zQn_@d9l5p%+F=p3%%Gf*w)#eZlBrSo86vomw%H#>D&@Aq;uPbA)nhi z44t_x!_b{8hM_m7Z1-~ucrxc$W0{$o8-`i7Y=)s2@|@W5yqNKVSn;A5aUnLmMdqs_ zX~H%j9hQKVM#WhEm@PDAvUJveDV^CaY}_%dwuauV;jIH1J5_ICi?&sC`u%QiFqoN5 z25Ck|S(~Oa16qnLkOX@~e&cAvGI61Tr;0 z96CQVx*S?nGFl^pl$-K5Mwj>-otmVu;#n;%&goB4d?>YFhmmI{$>>rvfo%a|DI=B1 zbuxYi=W8~aB(H-CF8K$eOTz))>Py_tLo(N1ihngb${#jPR~&>GNDS#Aqj+iHgiq~7 z)#=<-GwPR&F3ImImG%p!f5~EC|K|s?!)GcEMYd}<@s#X4v`KNb z{ws*EtKW6SpZ@KiKJwz%nKjr6cWSZM0e{cGes_3ZyNIGcn@Rb`OX^R6X8lQGjn(r; z5&Hx$8#+gFz4h(iXF|03a+}%j@+5!q3%{6Om7oy^!nFu(DErL)ysKdlUbkFz07|t; zENN<|TOKGcd7zQN`wsnt5M+8n@!=szt2vxicO5HnFdpOB+hsU>xqErENL_e$195A( zSb5{x`O#|6GR!@Jy%7`jP`UVE*?;h^yQ=+%U+}}GGN4W`%@^hV!;5!S7n%C`kR0!J zOSHv9KRmxxq8Jrap^O&vV=JPFgPZ5KcPZ#chUzG+Zm^W;IFw^*LJNAp6yPW<$fCUz zs>sbIWqMtVrO@eOqNexjbe+ngBrsq_>U>;YL}o&|y>Qpz?|d6U^CR<1<0aAZq7Otz zZrjCb!S@$^042!X*zMoCwFA3OP-szj%~I(8u>*U5*`0D=(?!pV*s4&u372H*LmVEX z*ZQ&XSSy1DUr(-q>gBY@+6odj6x?V13QkYZt)0HEXcUipK` z3&FCRqbE$ka0s^QK`67g;^hHDK@RifhAV`{vlIhmd)j_^iT?MYYS+K`DBhu&+?;-tqE0)*Xd^&=qlgprJ5@F6@$+XMqPJQ5`DD zd!gbW@(m}BROi_`NVrVj+CmWy*V%ANiatAWb^8Y8;#jofN32=W;KYursUAh%q|%F{ zSr{=;p{S(1rDc$Y(v6=|cu}J~!#J0HoXZpAG-Ux0wa2+^=8vL8}Wnl5fp_Vxi{cL<`@Nx!n`G77U9(m*Xt&6p0J3ySO!WLP~k zDSOXgP0qvnnjPqbQwSJ&IKc9RSjGB?pv*j6%A;CCQBoGr|7g(B-ItTwh~~LM+sI2r zGJQF@l}{*{Q&RLd7iNDFQt}c!^3&|C>-LO0)heWz55qDP94U7S3JT=M?uF*ptK6Ii zgxjpM5WtXG2Nbu=5iJNj{V50QwR67W_#LZWV@3ub1{PIC5vh9g zR;Qlr#ewY1IQ+r4b!=6lP*ju+nOQQxM`YY>TLR`&D91j9vSd6)n{HQ2*(DDm1{J-2-i6*BVK19y{J1O% z#bd5Ck;)aWvVP{4ew({PIb7M|Beo~C+ z^iPZo?N`*xV!Jg5n*#fsyglVca=pAR7+E-eSXkBBLQJ<3gRqWjIQ7t7E>eF?hE>TH zgW?^E7fe~r-aUl9sw|tN%%$BKjVK{ZgzyBmq8x$VYoVlhH6+GqPA4!=OtUYY%Dh8- zp-ok-0f zivN^bLjGXrK-09rEde?-ZizFZ1DiA3sDKY%a{?;J8xIdv&~AYy?)ZQY_pwi*QbK$^ zLUFx-AxO9NgE<_=<)VB9e!lSxZ>fR2Fo+UR0G~J_@WCeGPQaJ!K;~N&?Xp4?0ER&o zARG2lHem-fXv?k@Y8$g;53Kqq5LrbL+FgGA{UZJB`P z6UjO!IGgR7mE*JUh#M23T7xd|0ZN3bUnX@r>)3-jF?I|+UZ72WKe2KHMuHsx3npch zsXyprp$ZpC8spvC7XJ9#Y54rNQ=Yp=tGQ()R)@pBQQOO|LDJ+G(MI*8F*y+E$k0H5 z^Au4^)(V25-xo(^r9_2CNkoZowGitwf2h5;0{X{9Sk&qIQq|S$*Rw$#(zrEsfVgR= zX~5igqCH||q*fwRS*YxVN2Jw>jmes@HHX1N1bS5ae+aY^U13R-`+sPDzOf|~iUeVs zEdjaTJYN7q5e?;Dt>4_1ph&bO(4?U`vn62KQ?>-p@%W{>7`DW8F-_8DwnSd;cU$6A zV@r@`*&2=-#Gw#NyN15!x}t*OPXHUQXK) zR#4)2%8u~&3@X|Y2u=_o+7T7X9S)Q?9ItkY8=5T<(A>dt2}DyF9e-h;rc~#`Aee*_ z<&y=@JU--Xz_cK1o7FK~EA53ePePSdlRNgbp=<<_h7DCB!sDg4IRQ$=L$^mgppun5}nuLFXwHMW^oWQoNXv zq|`p{*-Faz{goceIrnpOulIU}GsB&lUJ`6f*Pt4$T3Iip3D&)w{!M=9`Zt04(M0DX zk&j(y*<^~U7my|fBDEMX)E*4UUg`xT-J%FE$O7F*3s+}=fEi%OzVIa&Sjsn=gSsPy zdjy(}2qh30UTag ztO%J8*q0QM76!VsxSMPoR4eIG7MmEQoy1Ec-eeTe0%1o|cEaEMqi@2rby^}HA!GD1 z12cW`X(3NCl1;$)S~F*M!-Zr0-ui#x@S)LuVS*KO2PQjQlhJ-FXbwyjWRRQGwr{Go zeO4PRXhQRj>py2wwB+x^28Z0HbebbGyp|=6#U1aRFhZom<3(!=|il+T+n&)8xpB}6(x*M1hn<-oJ zBD#dK(6&$p%4XfHlewbJ%IerJJZP93PslRU>w~#Khu)&XZ06yu&XHpEe{@$`nd0{?bZRW z?iz>zuNRH|g%^R8cSn!kL;sUxGT64MoS%7GInUMtaC}P6>*chZj|E-IYjcI1g;vnQ zRd7!B%ZonXDm8XAr@s!Xop4O}B~oi^*da=^^F(07<$e%u_H=d8;n_Fc{edbabSA$6 zP|m*PaC-9z9AhVmnM+TE-}<&C7L%NpCQrd`>z$Y_jCIOA1xL0wZ#IY3L!*`a5Y_v~ zw7a7JXqk4!$W=8jbW)y3Tb?nt_~H>y!EKp7>>J|XbRHGP$G#3i>u`0+QHae`cGZCz ztK~kR9W>aVtkU(7k|@etg)$f(jx6cG;!{Wy6k+Kxd|{bk)e8yDkz3Lx1mQ8gGAcFr znN$h3jM~t_#T_1#8!!tkgY{6|FrrkCeX#QU4Bbu0Y(4drFX70O)R6*e0D7By^d1Gq zm2wFvV8s?;Vg+)E0B?S^h1!mkD9$4R6sT5`ZVI{GNsmbXB_$jotC&ht-XyRAfH^g2 z4^@mk1dT%A5*p;u30D+FEy810YZAJZOJRe*qoh0XcF-qwN6JQY2cE11Dj7Y80&2Lb zogL2^J3IJBvl)GSE+%N9SG!Yw2vClzf2DC%a! zx|j*aQUjD6l!+p^3WPA@KsT2cRO;eyMs-mD+-}E$CSfa^OEu`|>5ypA;EBc4w^eH3 z$ass4H%Jhq=aAq9kVpjyZt=0Ozf;7{gF}Khn?NGn1QJ;r5@(3PgeW(IMB*J+g#UJc zp%^{zL6;b@Cq-YgNl=yn=<8{`4O^9`i|^TRVd%IIc=9QUgNZRm2Z$k$_<#O?2^BD4 z_*j<|QgMT-1$+}cu9B7#W)_$xZaUBi1!VSki+&3rH~G%?u~wYI|j$; z?`X4tO5_R|9nA|7OZLo4rG%>T&_5nJI-wT*+}-3>0B>%}4rWM)yb*XviApKH;?ezz zOV^Itx?HwtIZoELa>xx6rD`auSe4R&bIQYs%M#9%xr+$c6W4GjEt>Excf;^;vY1eoknVrmCXN$__KW3%7_%C^7fzX;I=3RP5 z^v}TEJK=Z#FPMMvsu2ioY#F_v$@ao8ZEdvEW@=BHxuyBoXCC@?*#hkA4<* zx0*K{JH`w}u=4*_jB?ps4noo#M~_I?EdSPb2wMDE;ug(!kD$ZZ7sXfPyZ{ezKO-B( z&)GU5Dh_{Wby7fYhX1LX4ulyxsQb`55c8aJj&eqiaxNTF!2LcEoKj}c0(a~&+XqI< z_@x&t?V*u2;7x%oxo+1NW)pTP+CQbeWXkr8YtiW}nXmk&q!LCp>W zP74Z!@{#{2gdvdD`UgRkMO-1dqW8}LyDm@8;Y*(0cN?g-+9Lk~`fuJj+R zX3R2*x)PO8qg~j4rYG{6=)$>Qx|Dud5mso2cQ^bK@(l2WxQ4d%Q9s;-lqWV6jRwD- zf?A7Ps*J|eKC@{1`Wet^vS!eEn;i@X%{B^4JjN&%(zye252=g99Sh4ijbTQ%0-RV) zOipdx2M`2g(T{V**8mZ`-5(2kWOLFOrdEu-$;HPk;*npL6sKZvr}N})MD%D?+R;Hy zK`n13R#U=DG(VUJZ)`~@7cxua=sNsXeCblJ+PXqiPWYk@n~Zz z6xabg^6+!KRS>`&_Km4 z@n>e9(Ebv$tKA^*>6AHULW)1x!WXqFuOhZR>i5&MYdVyAy~KvN6uWh&~%ikZ7QPsWCsOhrKuP~aY;oIue4Om zuLPkAR?F0fk!1!_t&B;1H0EKoYM>O^6>eh*m3{WbW5zX*yW+#eSNg+$-a}le3@2!z z{$$pCGBR)XN$Ep<9sBL)nI=k`vor2k0qxCo#TEN+CFXlu*d@L~PP2ZncsI(j zM%7boN~8cJJYx#)S(NIjV0`~U%b3!St5BY(k&%JR;*#XtYb|TpIQxemPs#Y9z$L2h zg|8-9=CG(7H;^uz)uRjRhPv$XOX-&tzYq_j-wxt8vg{W1r^o#LO@8@Nzr5BjxA^6D zxRA5~^$Q;nJ>d8sn`hP!grBU73uhUgF1_%ppZm*S2aA{Z&L{_A>BU|IZUV&O+THLs zh6C5ig1LKb22WO8j^If$%L*9MvIxn%6Vzoex>fIP5mPck`hhef#Am6NV3M%v_!Dn#GbOEpK+gg^bf0H6ufM0jhtFaG4UFD1! z|II>M#$8dIjObAL1sEjwB%x%Z(YZIzG%O287J^5gdwd`dl$Z6xQ({?PkQ`UO4(<)xXH1AJr98{A zRdv~P_0dP{lxQ5rj}W3_dJk(ZM__l+u!UzvK%#cp4hcKL>_tH4p*mHQgWR}}#2IQo zwh1Hm#ql{UjwjA|m;@M)`s6KI=gZpJx>=mpR4AsHCR1z>X(j~j{!w7xiQXyhaZ z0%JGAfY2A%M^Z0|NB1=>UGl1x#6W4>>V!iZf2>{Ro!VuNHkC9XwsT{bIU;w;WnQ<4 zE+9N@5>J@zEBMr=kvY1i3duNP*i4al**S;X*1@*5``jG-#+5yw27^%(i;d=I!i8&@ zMYWKNj{zBJix{3t=qJOIrxl*?^sWLoI0{&Y7Zn!-Ws6Uw7=ui`ZQGc%Jn*rU_~_Kas`l(g;9WOH|8bg_+EADcaDvk4Qn zMXMSPWwJc{S6lL}r#Pis+d=y%nU5#3Kl{qkW6P>!hr!=UG9*#6Z4ffX>V_%ohuA27 zgq#WIf>(jjW-IVUp@Ar;{&UVg3mybz7BIuYNy3tqh=m$rN|qBNW|0a2Ha>sS+Th=} zyf!;N07>j9ci0xW#kby!-f)UIVCV1hqFVE2Gq>xq&KP1%l{BmGsf1|nQpfN06eTem zPOgRY4nn5Ij!E%)q4=zR_4o*OSio5Y6rjPLPqagsii{BME{e4nu|S`t%`kX{Ovdqw znp%0Sb z_}#yPZq%`f3<^0;m@KeY8m%c>(tS&Jr*qlJnzW!_71!MXGHi*=kQ4e}9%6`m zUZ&-&#i)4395z!P5`fqTC1xYA`PXH4VGyltc@bcRgI~Bwv<4>||qxl`D7rMs?on{q?T$ zyw?G`;c(p%PmK~dijZ#qkM5@Hr2EYBPB%e1bq*wiKpaS*^en;2L%Ibe zB;ve)=b7L|<^>LyZ@-5XbX#qDka$>?MVpcDfea}RDxg7y{S9eU^s{~WptKgA&Q|+_ zq9DpZ5NgnSkk?%#DuEm<*2Pwf)*(auJJ%i>Ryz#f)y^M=wsw>|f6OROQ90nYhc%S- z+&XPFb4v`Po%Eqelmb3Wy^Psdn_-S?+E;L-KvGJAj2uG zIciQ=g^M&UYkExM;voWl#bUTIKsebrPuFJr3^i?nz8ShFs)8$0oBg4{oMe226!K8) z)JRIFKC*b`OiThcv|8V$(6nZA>n|36)nQILus_wW7z%BAU?ECDH9BGS! ze{^_@A&oDj+M=lOO%hYkg&9;in``c*&8vnpGEsq-U&r7j)U6HPDegH9+p)w^fSkBJ zfaLG+MuTVMKjOD06A0xL9AW>&Q{#1VA$BgqXWI}7z_x1mG-JF4ATedW#LPZ&vBzc# znHlNwWtWVs%%_1hamM6gj0h3ae`SnR%qkOlbY8%Q!eH>aT8}lyF2L9T34XvW9vbb) zB>+rZ?l|1Px7y*SL=bBXI5{#Asf&DPq%d93ezq)Lb%F*>=6R8YT6`>ozx)4~_*j?} z9}C4{4RpRPHy?95I*ISrSXwMw!jE6hh|3{ zsKpQ4^~0j16rw;UOhk?H4`LoG9pX z@rUr)cvHOc$S4b6{kZg7I+-mii}gXw)jXVrDE3*v5yP3@l*k<8RK845IRz5OK zP)1ofZ1lUDpfQUKrvm8~@dL|k!D2n~5OHT0xQZ(kE;m)JDPGuVAfXMrBwvbZXg5O> zzSBkH1Z)Yx0X8B=Mcb5hYq?Sv)gcW7ld`Gb+pTi_Mh6*z8j%aODJHAbTJ{b|Cj=_E z`YqF*ZA`QJVzERP90*=!BPBb5DdM^R`|j2Q@U9_SNTs~+f+D+0NbxJqG|n;Y+udCz7qD1-Ptxz4myt-e1){&c`Y#M!csw>3+mriF8erA z*nFuOdcACAU01T#qRzejFaGS!wwtaO-u?T(_U4~ipQn?kP8E4!WW-SHo(zD1R>hB_ zUmpS6&FloZ%~DiK741Q=3^LSgUc+21NZ%B;CcqK}!Fym3;K*If74`*fEq;pK6K1_D zgweC>$uGxQyZVfs(`3WozghlMqD9!QB`~qLOu*kQesGjp&_9tYNP9KQ9<`&@7W!) zwTUZw|AhQNUy4zpPZ~Sk_-az_!WKteuxe~~09!+}EK0)|MWvjCKnf!vJBd~5VC)H8 z0;|jw+?V%hvzb0nS}ww+!pf~{6+2;IUb^ReX>G?Dv<@AQuj@@Ybusv$dQN*dP;l+< zwgqY51cCLzj(J?CiT2BX82eKbsbN!IrYjfOt0gbwYK8t}uBwoQhoVHF368;GONSn8#x6RyRwn@Mg-t!kS{{(|O z&9S+tk#lMYw3Xcr|FyO->~iZ7UqteAm}$t^CJ3XlveZIrrUL#&(j75>g8Rx|(dkG}D)T%Or}_?2IJ z^v|<(=vb};d#?wuQD66pSA#+Fizet5z2c8hg;+bFe=J~;Wk=-Yo^LH^jRwlMiX$8* zXDmmt1>E<-qwn~ohtX}9=&_iou@Plug6d{tj0ML#5o1A{yijb@jqqP?6=U%VZtcNc zFO-z)MI2y*V9{E1I~OXhjaHyn@9dtJ*2gYbYF6z`7`9Bp@?)tJRfYJ;Z&ICfHENw2IasVA@8&_}&musE`-0 zhU-X|gMe~jANK=kbHYA&D6?(L8U7kZqDL^!`eDl+d_Km$e2jgZ9wF?5QP^audc!_m zFj<^YgcsYeFBkUVWUVKQl4ry|6?_(IP4n?2_H9!xIiw#)gZ+3QW|-NNgmkKBNJ9Zc z5{&V%1R(%-#{llO0UX~q0PY)r`2=$kD<1%JKaiVE02VfbK(_E|uVs(L^)7yb2^p~a z(*Q1wFGR><9eeB)s~Li<$behuIycXj9-OW%r#xh^Y3vj>GW@BfF+Q{Wz|F^z4um0q zYfP&+euZ&Pt55IuH90>WhJ;=&L!fcSqZhT9Pkwgh)B3pXqo@;nio!5)VUwzl2pi@& zxgK+oK*4C&Y7+&|;EEhm9De6ZAvp^xNTB{hO{o8mYV0+qIaRMuF!z(lo7L+Ro9D3J zHC~_CRc2>cpMX9mDy=x^qmDv#uXxFTS}+sDKu3%Z$N9-Ee0n(@+8+x}hW1;*5Q>Je&OGBBs`P-!BfMhtF#(?D!=Xw(Rg-0H6-M zOTw@GGAk8yur|g$@J_jA)vN7TV_eZ%E=*I_v>??gGmi&{G~!#phs0je1o`?7w1cl_ z1mvV|602X4A!lrZhf5d`pUwd)E(H?6D+*uRw-&zn7dYKbt3(2V){ia1f^2t=>bY1- zJVq@L&W~X|d-fCD=nwrv)_tG+^}q8+tb2Yr`ALW)V@E}J@2Q{E<-VLtiv0)*WXs_X z|77c}`m+}9`%LnaYis}Fxo>WyqPCTXRo19_OTwEk z{=4*6-R=sHe>T5$?LmpzOY_pJI`qFCdf&t3`td4A4O@RpA;QG$lLzni`q9ZRp&2fh z`ejwiTZtkEXiFCs(RE?PTo0iBn$;M2B%`Y#V&NP^jY0#=+_f+T5VO0q@W;K#I{b7sQ@RKA@sYC57I59bpBu&0L zmxh2YFa9yvhedYgzR1jMD}t6t_?MH@^r!;uN(tO93isphNf}>OJfhWlObI)7{XaA> z@y4dS%M7&)y_$-0^0_2LOb)}JTJb#Akx`!1YF}$!&J$tCJ2s7f+1_<2IL}JBxAk>< z*U`H?bgeC&e)Qk5ZvuomM~DBs-QnJJhgDEL1_V#EN70X?kh3)j-}pu*kJ`vWeIV^@ z`0uYw3r(f+zWP*3A``8rV%R9iYfkF0z&^aM@~vSFYW0s#Kr23|w}2 z@HnVaQ3$J0cFyhkbF1=a@`&v$^BY4@fhNi$NKj8IWVy7Ol-S^G(w4uqDX&NkyaljZNM4oXBiAqGL_oWdpkxrT%cTwIxSLt| zAGB|ID+OjX3~X~j$1G{wB%>K3CJ3X}s_Phliw-~;e+>ZVumuIce`}sN-Q!zu2*w9f zU#%3ssGo!80ejcKw{HZ&rh*8;e=8Qu_yj^93cZ&po+D<6!w_A&R|5e+Aev=YXd70R0 zrj68~Rk@w8dfIf?l-h)30QIknLW$QDn{!r23{zmuF-sF5iswnZc(qyt3y5+M&0;VM zbLCC|pUL}aXmd-2^G3svA0)Nga*H8(K`<3V0B2ZhmSPfVXUkgnki|}_R?@+FsFkP} z-;siC)QmL}KK%%`9gnvlb!kF{KWR9~x`jx#BY>?{^TIa_crgI>J(7G^HSHMtjI{SJ zu}M`-tkp#u#jRpB_{Q;^a9Y_U9W30yfLV)_z9h3?fKA;Zi5VV65?6|+=oUJ1iii(7 zsgw=e{!6*29@Y;=5zRM(OY;yZ;z|}MIJZay0fL>m_2-{k>t+d^d+X1qb;U!7qt%lE z`_GKe-cs2+%~fUSTahYQ0#@5l00Ubmw}dwpN5qEY!fjsq{J)72ici{H;o&rHqX}ja zZp|QiI#uWzlf=Y!oDUE@?Pzg(X`4fJ+~LGr*o=nHMAT?ahJKLi(HMOFVCYgm>=1j3 z500eGL!6Ayz=+EEa);m{^VNu9&H$sO+M59lh$1WnG-Hs|BUb>MkpiO?DRjJ*2p1=X z=oF@;Qne7RQasFn?W{})TbUhdKt(ZUNm234PJ)4?uC+zwq^OIT zn5!R*RGWtgh07UZBjy?nsb(LMiR=^ySpXddS=R59cQETg;?nQ7c{sgfP-{_$O!(n` zq8fd@$Jd7uaK?Hx{}>~y=nyQI1Kv3Ft_vt!m16;gtztv}f?-g^eYZl-!y~O zLmceeG*|#{gh%YkRyqrF-^yutjMxTan@}OC2C0ZCs7GT#Ah@Wtv`3Is3#}O4DvT8Y zSAtqx_EhX%*KD#pOqLr(BP3`|i+Dcv=)*-9hT3z4FjP12^-y%{q|E3!LTG`b(Vb*r z3r3Ebx^EC7J~(RD4}eAC*j7wy1zOi>Aw=^qiJGoE?exIY*Q^#fpJ$w9r-Hx1$FA@=TklO)iM76qoURRP8g zwpukkucnQ5^qH_;O13~+f9N#Ue5t_k_|WP!AtOd(^)E(a%{NV_)wHOli@p({GHC=* znF95u`;87Z?ze84P^U5!Ps1UW3s8=rEtW_BPhp<(KcUyt^FQg7$pi%y1Uzu^ zT8F+h=6*TDY2X19Ffz1J^I)Fm_@H@ao>&YX{e`-SRy_EHdQvT!{-3d6IBAm=!Z z1Q9yK2j@8TgK?bt!Dzbqrs2wxVUrw3L>)zt;;U{3y0hV=Hd1IUZKmExkxgp%{>3dY zCRB87p|GY11ELDsLNOce*1}+XElX13xZXW6qYMs{zbX3|Yiu;lPj+;1d*ehDH!uP1 z57)+tvrDx9VZ}EvX=9xu^VzVDovhAt&w?q!TXEn=j9d+_Q}Vmss|k~HVcy7ZXB^Ep z4W_i@_ajNrNru`iWCx)a^A?p>knm_{nAbF$_a|x1iEX$e-nq^0wKkz%E=WWfzpZt< z_#g*3+*+Jizes?#9<=SR`6ceRQ?ZE79DES?pZC#>&2s?QAD$6lEz)uw=a~SE{l=&} zb!X&J13*jF7AY`0YW^WEb`DYm`#hPDB4uW=H&EaXyxD{krAMnpBQ;{JgkI-TYp-1^ z%0Qz=!QP}sWhDn0t1iGQ_d#YFQ^s@>+{5c$xxkxJjg<@1uAs=BVL&ELzA{|}3Ju?2 z83kJi#Nhl7cmubUaXOKw6ahn-TdJ)Qe@%HYRKy8CRzJ6{Nr8&Gwti{UPktHe+Wt$_ zwe=7&<9vB7&ZKHfyf?~=HLaXMP=N)#WZrWExoj}9UVG(^H4e@I5N1K5Y-v=5G{&yN zZN{UT=TTKV|JJ<@Bd}q`2S>8{fmX@6?!{bVY`zgyHV>2h+cm}p>{vGfxOHmYJ4J$x zai`{3+fk=n=hA)S0*ntDJzf<5Mg17m56&u@Z`7&gA$IB>Sh&D#lHEEn8^)4d?i_2q zkYpDE+iw#1Bg$EfBSF7L=xdj!OLn%h;_A;8)PG>~+(1gAvIeNRaq0&fRZ~owQ|n

IbsY-~g+Osb8%J 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Ǵ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ޯ`x#}oImq(?5WM^RtVA1>l-1+U`%UE2Rl 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

Nj(Ca$cWF^KE1KeRyqzuxLjq*u0Bub+i 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

00thGJox890Ufbl-<|d;d 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[@sF%ydm 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 PHh^;|(lM Date: Thu, 11 Mar 2021 17:19:55 +0100 Subject: [PATCH 002/172] update sample app --- stream_chat_v1/ios/Notifications/Info.plist | 31 -- .../Notifications/NotificationService.swift | 182 ------------ .../Notifications/Notifications.entitlements | 10 - .../ios/Runner.xcodeproj/project.pbxproj | 281 ++++-------------- stream_chat_v1/pubspec.yaml | 18 +- 5 files changed, 65 insertions(+), 457 deletions(-) delete mode 100644 stream_chat_v1/ios/Notifications/Info.plist delete mode 100644 stream_chat_v1/ios/Notifications/NotificationService.swift delete mode 100644 stream_chat_v1/ios/Notifications/Notifications.entitlements diff --git a/stream_chat_v1/ios/Notifications/Info.plist b/stream_chat_v1/ios/Notifications/Info.plist deleted file mode 100644 index a225b5ca00..0000000000 --- a/stream_chat_v1/ios/Notifications/Info.plist +++ /dev/null @@ -1,31 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - Notifications - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - $(PRODUCT_BUNDLE_PACKAGE_TYPE) - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - NSExtension - - NSExtensionPointIdentifier - com.apple.usernotifications.service - NSExtensionPrincipalClass - $(PRODUCT_MODULE_NAME).NotificationService - - - diff --git a/stream_chat_v1/ios/Notifications/NotificationService.swift b/stream_chat_v1/ios/Notifications/NotificationService.swift deleted file mode 100644 index 976e8d6a92..0000000000 --- a/stream_chat_v1/ios/Notifications/NotificationService.swift +++ /dev/null @@ -1,182 +0,0 @@ -// -// NotificationService.swift -// Notifications -// -// Created by Salvatore Giordano on 25/03/2020. -// Copyright ยฉ 2020 The Chromium Authors. All rights reserved. -// - -import UserNotifications -//import StreamChatClient - -final class NotificationService: UNNotificationServiceExtension { - - var contentHandler: ((UNNotificationContent) -> Void)? - var bestAttemptContent: UNMutableNotificationContent? - - override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { - self.contentHandler = contentHandler - bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) - - guard let sharedDefaults = UserDefaults(suiteName: "group.io.getstream.flutter"), - let apiKey = sharedDefaults.string(forKey: "KEY_API_KEY"), - let userId = sharedDefaults.string(forKey: "KEY_USER_ID"), - let token = sharedDefaults.string(forKey: "KEY_TOKEN"), - let messageId = bestAttemptContent?.userInfo["message_id"] as? String else { - return - } - -// Client.config = .init(apiKey: apiKey, logOptions: .error) -// Client.shared.set(user: User(id: userId), token: token) { res in -// guard res.isConnected else { -// return -// } -// -// Client.shared.message(withId: messageId) { [weak self] res in -// if let message = res.value?.message, -// let channel = res.value?.channel { -// let messageWrapper = MessageWrapper(channel: channel, message: message) -// if let encodedData = try? JSONEncoder.stream.encode(messageWrapper), -// let encodedString = String(data: encodedData, encoding: .utf8) { -// let storedMessages = sharedDefaults.stringArray(forKey: "messageQueue") ?? [] -// sharedDefaults.setValue(storedMessages + [encodedString], forKey: "messageQueue") -// -// // Modify the notification content here... -// self?.bestAttemptContent?.title = "[modified] \(self?.bestAttemptContent?.title ?? "")" -// contentHandler(self?.bestAttemptContent ?? request.content) -// } -// Client.shared.disconnect() -// } -// } -// } - } - - override func serviceExtensionTimeWillExpire() { - if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent { - contentHandler(bestAttemptContent) - } - } -} - -//public struct MessageWrapper: Encodable { -// private enum CodingKeys: String, CodingKey { -// case id -// case channel -// case type -// case user -// case created = "created_at" -// case updated = "updated_at" -// case text -// case command -// case args -// case attachments -// case parentId = "parent_id" -// case showReplyInChannel = "show_in_channel" -// case mentionedUsers = "mentioned_users" -// } -// -// init(channel: Channel, message: Message) { -// id = message.id -// type = message.type -// user = message.user -// created = message.created -// updated = message.updated -// text = message.text -// command = message.command -// args = message.args -// attachments = message.attachments -// parentId = message.parentId -// showReplyInChannel = message.showReplyInChannel -// mentionedUsers = message.mentionedUsers -// extraData = message.extraData -// self.channel = ChannelWrapper(channel: channel) -// } -// -// /// A message id. -// public let id: String -// /// The channel cid. -// public let channel: ChannelWrapper? -// /// A message type (see `MessageType`). -// public let type: MessageType -// /// A user (see `User`). -// public let user: User -// /// A created date. -// public let created: Date -// /// A updated date. -// public let updated: Date -// /// A text. -// public let text: String -// /// A used command name. -// public let command: String? -// /// A used command args. -// public let args: String? -// /// Attachments (see `Attachment`). -// public let attachments: [Attachment] -// /// A parent message id. -// public let parentId: String? -// /// Check if this reply message needs to show in the channel. -// public let showReplyInChannel: Bool -// /// Mentioned users (see `User`). -// public let mentionedUsers: [User] -// /// An extra data for the message. -// public let extraData: Codable? -//} -// -//public struct ChannelWrapper: Encodable { -// /// Coding keys for the encoding. -// private enum CodingKeys: String, CodingKey { -// case id -// case cid -// case type -// case name -// case imageURL = "image" -// case members -// case lastMessageDate = "last_message_at" -// case createdBy = "created_by" -// case created = "created_at" -// case deleted = "deleted_at" -// case frozen -// } -// -// init(channel: Channel) { -// id = channel.id -// cid = channel.cid -// type = channel.type -// name = channel.name -// imageURL = channel.imageURL -// lastMessageDate = channel.lastMessageDate -// created = channel.created -// deleted = channel.deleted -// createdBy = channel.createdBy -// config = channel.config -// frozen = channel.frozen -// extraData = channel.extraData -// } -// -// /// A channel id. -// public let id: String -// /// A channel type + id. -// public let cid: ChannelId -// /// A channel type. -// public let type: ChannelType -// /// A channel name. -// public let name: String? -// /// An image of the channel. -// public let imageURL: URL? -// /// The last message date. -// public let lastMessageDate: Date? -// /// A channel created date. -// public let created: Date -// /// A channel deleted date. -// public let deleted: Date? -// /// A creator of the channel. -// public let createdBy: User? -// /// A config. -// public let config: Channel.Config -// /// Checks if the channel is frozen. -// public let frozen: Bool -// /// A list of user ids of the channel members. -// public let members = Set() -// /// An extra data for the channel. -// public let extraData: Codable? -//} diff --git a/stream_chat_v1/ios/Notifications/Notifications.entitlements b/stream_chat_v1/ios/Notifications/Notifications.entitlements deleted file mode 100644 index e5b7189037..0000000000 --- a/stream_chat_v1/ios/Notifications/Notifications.entitlements +++ /dev/null @@ -1,10 +0,0 @@ - - - - - com.apple.security.application-groups - - group.io.getstream.flutter - - - diff --git a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj index e3a96e702d..8cd3ed03df 100644 --- a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj +++ b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj @@ -7,27 +7,15 @@ objects = { /* Begin PBXBuildFile section */ - 0BC14C50242B5A7A0028DE94 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BC14C4F242B5A7A0028DE94 /* NotificationService.swift */; }; - 0BC14C54242B5A7A0028DE94 /* Notifications.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 0BC14C4D242B5A7A0028DE94 /* Notifications.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 6322551A583705BBA2F048DD /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC299D593714162503D904EB /* Pods_Runner.framework */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 78DFDA8BF7ADD8988BA9B2C9 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A4E5F7C8F1FB8AA92A6E2273 /* Pods_Runner.framework */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; /* End PBXBuildFile section */ -/* Begin PBXContainerItemProxy section */ - 0BC14C52242B5A7A0028DE94 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 97C146E61CF9000F007C117D /* Project object */; - proxyType = 1; - remoteGlobalIDString = 0BC14C4C242B5A7A0028DE94; - remoteInfo = Notifications; - }; -/* End PBXContainerItemProxy section */ - /* Begin PBXCopyFilesBuildPhase section */ 0BC14C55242B5A7A0028DE94 /* Embed App Extensions */ = { isa = PBXCopyFilesBuildPhase; @@ -35,7 +23,6 @@ dstPath = ""; dstSubfolderSpec = 13; files = ( - 0BC14C54242B5A7A0028DE94 /* Notifications.appex in Embed App Extensions */, ); name = "Embed App Extensions"; runOnlyForDeploymentPostprocessing = 0; @@ -53,20 +40,15 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 0BC14C4D242B5A7A0028DE94 /* Notifications.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = Notifications.appex; sourceTree = BUILT_PRODUCTS_DIR; }; - 0BC14C4F242B5A7A0028DE94 /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = ""; }; - 0BC14C51242B5A7A0028DE94 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 0BC14C5A242B5ED90028DE94 /* Notifications.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Notifications.entitlements; sourceTree = ""; }; 0BC14C5B242B5FF50028DE94 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 1DFB9D7CB4D2FBB0BD3BD534 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; - 34DDA6B7AEE7F881BA31E310 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 7069E97E2E50CF0E633E719F /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 887F9B6BDC8480C6B3628366 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 91C3AAF66766852887B9460F /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -74,46 +56,22 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - CC299D593714162503D904EB /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + A4E5F7C8F1FB8AA92A6E2273 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + ED2D4AF300CE6F2241B57624 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 0BC14C4A242B5A7A0028DE94 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; 97C146EB1CF9000F007C117D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 6322551A583705BBA2F048DD /* Pods_Runner.framework in Frameworks */, + 78DFDA8BF7ADD8988BA9B2C9 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 0BC14C4E242B5A7A0028DE94 /* Notifications */ = { - isa = PBXGroup; - children = ( - 0BC14C5A242B5ED90028DE94 /* Notifications.entitlements */, - 0BC14C4F242B5A7A0028DE94 /* NotificationService.swift */, - 0BC14C51242B5A7A0028DE94 /* Info.plist */, - ); - path = Notifications; - sourceTree = ""; - }; - 7771A729FBB96FF718254442 /* Frameworks */ = { - isa = PBXGroup; - children = ( - CC299D593714162503D904EB /* Pods_Runner.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( @@ -130,10 +88,9 @@ children = ( 97C146F01CF9000F007C117D /* Runner */, 9740EEB11CF90186004384FC /* Flutter */, - 0BC14C4E242B5A7A0028DE94 /* Notifications */, 97C146EF1CF9000F007C117D /* Products */, CF168B61BAB91958681C7C21 /* Pods */, - 7771A729FBB96FF718254442 /* Frameworks */, + F93B8F215F5456A6442CFA78 /* Frameworks */, ); sourceTree = ""; }; @@ -141,7 +98,6 @@ isa = PBXGroup; children = ( 97C146EE1CF9000F007C117D /* Runner.app */, - 0BC14C4D242B5A7A0028DE94 /* Notifications.appex */, ); name = Products; sourceTree = ""; @@ -173,38 +129,29 @@ CF168B61BAB91958681C7C21 /* Pods */ = { isa = PBXGroup; children = ( - 1DFB9D7CB4D2FBB0BD3BD534 /* Pods-Runner.debug.xcconfig */, - 7069E97E2E50CF0E633E719F /* Pods-Runner.release.xcconfig */, - 34DDA6B7AEE7F881BA31E310 /* Pods-Runner.profile.xcconfig */, + 91C3AAF66766852887B9460F /* Pods-Runner.debug.xcconfig */, + ED2D4AF300CE6F2241B57624 /* Pods-Runner.release.xcconfig */, + 887F9B6BDC8480C6B3628366 /* Pods-Runner.profile.xcconfig */, ); path = Pods; sourceTree = ""; }; + F93B8F215F5456A6442CFA78 /* Frameworks */ = { + isa = PBXGroup; + children = ( + A4E5F7C8F1FB8AA92A6E2273 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 0BC14C4C242B5A7A0028DE94 /* Notifications */ = { - isa = PBXNativeTarget; - buildConfigurationList = 0BC14C59242B5A7A0028DE94 /* Build configuration list for PBXNativeTarget "Notifications" */; - buildPhases = ( - 0BC14C49242B5A7A0028DE94 /* Sources */, - 0BC14C4A242B5A7A0028DE94 /* Frameworks */, - 0BC14C4B242B5A7A0028DE94 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Notifications; - productName = Notifications; - productReference = 0BC14C4D242B5A7A0028DE94 /* Notifications.appex */; - productType = "com.apple.product-type.app-extension"; - }; 97C146ED1CF9000F007C117D /* Runner */ = { isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - 22D055914083BAC1E72E76DD /* [CP] Check Pods Manifest.lock */, + A83A30E8FF0298FDB3189FB1 /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, @@ -212,12 +159,11 @@ 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 0BC14C55242B5A7A0028DE94 /* Embed App Extensions */, - 21997A6DA96DFFF3D7D29CC3 /* [CP] Embed Pods Frameworks */, + 5468FC796DAC9C565B3989B4 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); dependencies = ( - 0BC14C53242B5A7A0028DE94 /* PBXTargetDependency */, ); name = Runner; productName = Runner; @@ -234,11 +180,6 @@ LastUpgradeCheck = 1020; ORGANIZATIONNAME = "The Chromium Authors"; TargetAttributes = { - 0BC14C4C242B5A7A0028DE94 = { - CreatedOnToolsVersion = 11.4; - DevelopmentTeam = EHV7XZLAHA; - ProvisioningStyle = Manual; - }; 97C146ED1CF9000F007C117D = { CreatedOnToolsVersion = 7.3.1; DevelopmentTeam = EHV7XZLAHA; @@ -261,19 +202,11 @@ projectRoot = ""; targets = ( 97C146ED1CF9000F007C117D /* Runner */, - 0BC14C4C242B5A7A0028DE94 /* Notifications */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 0BC14C4B242B5A7A0028DE94 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; 97C146EC1CF9000F007C117D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -288,21 +221,32 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 21997A6DA96DFFF3D7D29CC3 /* [CP] Embed Pods Frameworks */ = { + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 5468FC796DAC9C565B3989B4 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", - "${BUILT_PRODUCTS_DIR}/Starscream-framework/Starscream.framework", - "${BUILT_PRODUCTS_DIR}/StreamChatClient-framework/StreamChatClient.framework", "${BUILT_PRODUCTS_DIR}/DKImagePickerController/DKImagePickerController.framework", "${BUILT_PRODUCTS_DIR}/DKPhotoGallery/DKPhotoGallery.framework", "${BUILT_PRODUCTS_DIR}/FMDB/FMDB.framework", "${BUILT_PRODUCTS_DIR}/SDWebImage/SDWebImage.framework", "${BUILT_PRODUCTS_DIR}/SwiftyGif/SwiftyGif.framework", - "${BUILT_PRODUCTS_DIR}/esys_flutter_share/esys_flutter_share.framework", "${BUILT_PRODUCTS_DIR}/file_picker/file_picker.framework", "${BUILT_PRODUCTS_DIR}/flutter_app_badger/flutter_app_badger.framework", "${BUILT_PRODUCTS_DIR}/flutter_keyboard_visibility/flutter_keyboard_visibility.framework", @@ -313,6 +257,7 @@ "${BUILT_PRODUCTS_DIR}/libwebp/libwebp.framework", "${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework", "${BUILT_PRODUCTS_DIR}/photo_manager/photo_manager.framework", + "${BUILT_PRODUCTS_DIR}/share_plus/share_plus.framework", "${BUILT_PRODUCTS_DIR}/shared_preferences/shared_preferences.framework", "${BUILT_PRODUCTS_DIR}/sqflite/sqflite.framework", "${BUILT_PRODUCTS_DIR}/sqlite3/sqlite3.framework", @@ -325,14 +270,11 @@ ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Starscream.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/StreamChatClient.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DKImagePickerController.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DKPhotoGallery.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FMDB.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImage.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftyGif.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/esys_flutter_share.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/file_picker.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_app_badger.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_keyboard_visibility.framework", @@ -343,6 +285,7 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libwebp.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/photo_manager.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/share_plus.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqflite.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqlite3.framework", @@ -358,67 +301,45 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - 22D055914083BAC1E72E76DD /* [CP] Check Pods Manifest.lock */ = { + 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - ); inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( ); + name = "Run Script"; outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; - 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + A83A30E8FF0298FDB3189FB1 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); - inputPaths = ( - ); - name = "Thin Binary"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; - }; - 9740EEB61CF901F6004384FC /* Run Script */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( + inputFileListPaths = ( ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( ); - name = "Run Script"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 0BC14C49242B5A7A0028DE94 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 0BC14C50242B5A7A0028DE94 /* NotificationService.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 97C146EA1CF9000F007C117D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -430,14 +351,6 @@ }; /* End PBXSourcesBuildPhase section */ -/* Begin PBXTargetDependency section */ - 0BC14C53242B5A7A0028DE94 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 0BC14C4C242B5A7A0028DE94 /* Notifications */; - targetProxy = 0BC14C52242B5A7A0028DE94 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - /* Begin PBXVariantGroup section */ 97C146FA1CF9000F007C117D /* Main.storyboard */ = { isa = PBXVariantGroup; @@ -458,90 +371,6 @@ /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ - 0BC14C56242B5A7A0028DE94 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_ENTITLEMENTS = Notifications/Notifications.entitlements; - CODE_SIGN_IDENTITY = "iPhone Distribution"; - CODE_SIGN_STYLE = Manual; - DEVELOPMENT_TEAM = EHV7XZLAHA; - ENABLE_BITCODE = NO; - GCC_C_LANGUAGE_STANDARD = gnu11; - INFOPLIST_FILE = Notifications/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 13.3; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter.Notifications; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter.Notifications"; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 0BC14C57242B5A7A0028DE94 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_ENTITLEMENTS = Notifications/Notifications.entitlements; - CODE_SIGN_IDENTITY = "iPhone Distribution"; - CODE_SIGN_STYLE = Manual; - DEVELOPMENT_TEAM = EHV7XZLAHA; - ENABLE_BITCODE = NO; - GCC_C_LANGUAGE_STANDARD = gnu11; - INFOPLIST_FILE = Notifications/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 13.3; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; - MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter.Notifications; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter.Notifications"; - SKIP_INSTALL = YES; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; - 0BC14C58242B5A7A0028DE94 /* Profile */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_ENTITLEMENTS = Notifications/Notifications.entitlements; - CODE_SIGN_IDENTITY = "iPhone Distribution"; - CODE_SIGN_STYLE = Manual; - DEVELOPMENT_TEAM = EHV7XZLAHA; - ENABLE_BITCODE = NO; - GCC_C_LANGUAGE_STANDARD = gnu11; - INFOPLIST_FILE = Notifications/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 13.3; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; - MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter.Notifications; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter.Notifications"; - SKIP_INSTALL = YES; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Profile; - }; 249021D3217E4FDB00AE95B9 /* Profile */ = { isa = XCBuildConfiguration; buildSettings = { @@ -801,16 +630,6 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 0BC14C59242B5A7A0028DE94 /* Build configuration list for PBXNativeTarget "Notifications" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 0BC14C56242B5A7A0028DE94 /* Debug */, - 0BC14C57242B5A7A0028DE94 /* Release */, - 0BC14C58242B5A7A0028DE94 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index 97b84d97c4..e975fc37b9 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -10,13 +10,13 @@ dependencies: flutter_app_badger: ^1.1.2 flutter: sdk: flutter - stream_chat_flutter: - git: + stream_chat_flutter: + git: url: https://github.com/GetStream/stream-chat-flutter.git ref: develop path: packages/stream_chat_flutter stream_chat_persistence: - git: + git: url: https://github.com/GetStream/stream-chat-flutter.git ref: develop path: packages/stream_chat_persistence @@ -28,6 +28,18 @@ dependencies: streaming_shared_preferences: ^1.0.2 lottie: ^0.7.0+1 +dependency_overrides: + stream_chat: + git: + url: https://github.com/GetStream/stream-chat-flutter.git + ref: develop + path: packages/stream_chat + stream_chat_flutter_core: + git: + url: https://github.com/GetStream/stream-chat-flutter.git + ref: develop + path: packages/stream_chat_flutter_core + dev_dependencies: flutter_launcher_icons: ^0.8.1 test: any From d82f8edc32f6bddcbcedf6d31bf18870bd837010 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 12 Mar 2021 13:32:57 +0100 Subject: [PATCH 003/172] update fastfile --- stream_chat_v1/ios/fastlane/Fastfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stream_chat_v1/ios/fastlane/Fastfile b/stream_chat_v1/ios/fastlane/Fastfile index ec2adc8166..15e7ecd1ff 100644 --- a/stream_chat_v1/ios/fastlane/Fastfile +++ b/stream_chat_v1/ios/fastlane/Fastfile @@ -40,7 +40,8 @@ platform :ios do firebase_app_distribution( app: "1:674907137625:ios:cafb9fb076a453c4d7f348", - groups: "ios-stream-testers" + groups: "ios-stream-testers", + skip_waiting_for_build_processing: true ) end end \ No newline at end of file From 4f19a353f5693e6bb06212470ac8ea303b0d8cbd Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 15 Mar 2021 14:45:19 +0100 Subject: [PATCH 004/172] fix action --- stream_chat_v1/ios/fastlane/Fastfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/stream_chat_v1/ios/fastlane/Fastfile b/stream_chat_v1/ios/fastlane/Fastfile index 15e7ecd1ff..ec2adc8166 100644 --- a/stream_chat_v1/ios/fastlane/Fastfile +++ b/stream_chat_v1/ios/fastlane/Fastfile @@ -40,8 +40,7 @@ platform :ios do firebase_app_distribution( app: "1:674907137625:ios:cafb9fb076a453c4d7f348", - groups: "ios-stream-testers", - skip_waiting_for_build_processing: true + groups: "ios-stream-testers" ) end end \ No newline at end of file From 846769dac4073a8f5a767b20cba173feeedb6c72 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 15 Mar 2021 15:10:06 +0100 Subject: [PATCH 005/172] Feat/testflight (#24) * feat: deploy app to testflight * test gh action * test gh action * test gh action * test gh action * test gh action * test gh action * test gh action * distribute external * distribute external * add changelog * bump version * bump version * bump version * fix actions * update action --- stream_chat_v1/ios/fastlane/Fastfile | 47 ++++++++++++++++++- stream_chat_v1/ios/fastlane/README.md | 10 ++++ .../fastlane/beta_gym_export_options.plist | 2 - stream_chat_v1/ios/fastlane/report.xml | 22 +++++++-- .../testflight_gym_export_options.plist | 13 +++++ stream_chat_v1/pubspec.yaml | 2 +- 6 files changed, 86 insertions(+), 10 deletions(-) create mode 100644 stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist diff --git a/stream_chat_v1/ios/fastlane/Fastfile b/stream_chat_v1/ios/fastlane/Fastfile index ec2adc8166..4ddcc995ff 100644 --- a/stream_chat_v1/ios/fastlane/Fastfile +++ b/stream_chat_v1/ios/fastlane/Fastfile @@ -13,13 +13,23 @@ lane :match_me do type: "adhoc", app_identifier: [ "io.getstream.flutter", - "io.getstream.flutter.Notifications" ], readonly: is_ci, force_for_new_devices: true ) end +desc "Installs all Certs and Profiles necessary for appstore" +lane :match_appstore do + match( + type: "appstore", + app_identifier: [ + "io.getstream.flutter", + ], + readonly: is_ci + ) +end + platform :ios do desc "Deploy build to Firebase" lane :deploy_to_firebase do @@ -43,4 +53,37 @@ platform :ios do groups: "ios-stream-testers" ) end -end \ No newline at end of file +end + +platform :ios do + desc "Deploy build to TestFlight" + lane :deploy_to_testflight do + match_appstore + + settings_to_override = { + :BUNDLE_IDENTIFIER => "io.getstream.flutter", + :PROVISIONING_PROFILE_SPECIFIER => "match AppStore io.getstream.flutter" + } + + gym( + workspace: "./Runner.xcworkspace", + scheme: "Runner", + export_method: "app-store", + export_options: "./fastlane/testflight_gym_export_options.plist", + silent: true, + clean: true, + xcargs: settings_to_override, + include_symbols: true, + output_directory: "./dist", + ) + + message = changelog_from_git_commits(commits_count: 10) + + upload_to_testflight( + groups: ['Public'], + distribute_external: true, + changelog: message, + reject_build_waiting_for_review: true + ) + end +end diff --git a/stream_chat_v1/ios/fastlane/README.md b/stream_chat_v1/ios/fastlane/README.md index e464ef2411..7658d642c6 100644 --- a/stream_chat_v1/ios/fastlane/README.md +++ b/stream_chat_v1/ios/fastlane/README.md @@ -20,6 +20,11 @@ or alternatively using `brew install fastlane` fastlane match_me ``` Installs all Certs and Profiles necessary for development and ad-hoc +### match_appstore +``` +fastlane match_appstore +``` +Installs all Certs and Profiles necessary for appstore ---- @@ -29,6 +34,11 @@ Installs all Certs and Profiles necessary for development and ad-hoc fastlane ios deploy_to_firebase ``` Deploy build to Firebase +### ios deploy_to_testflight +``` +fastlane ios deploy_to_testflight +``` +Deploy build to TestFlight ---- diff --git a/stream_chat_v1/ios/fastlane/beta_gym_export_options.plist b/stream_chat_v1/ios/fastlane/beta_gym_export_options.plist index 53c7409888..e88559ac2a 100644 --- a/stream_chat_v1/ios/fastlane/beta_gym_export_options.plist +++ b/stream_chat_v1/ios/fastlane/beta_gym_export_options.plist @@ -8,8 +8,6 @@ io.getstream.flutter match AdHoc io.getstream.flutter - io.getstream.flutter.Notifications - match AdHoc io.getstream.flutter.Notifications \ No newline at end of file diff --git a/stream_chat_v1/ios/fastlane/report.xml b/stream_chat_v1/ios/fastlane/report.xml index b6e7bdcbac..42d2518e8a 100644 --- a/stream_chat_v1/ios/fastlane/report.xml +++ b/stream_chat_v1/ios/fastlane/report.xml @@ -5,27 +5,39 @@ - + - + - + - + - + + + + + + + + + + + + + diff --git a/stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist b/stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist new file mode 100644 index 0000000000..2d09042589 --- /dev/null +++ b/stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist @@ -0,0 +1,13 @@ + + + + + iCloudContainerEnvironment + Production + provisioningProfiles + + io.getstream.flutter + match AppStore io.getstream.flutter + + + \ No newline at end of file diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index e975fc37b9..ba5f058c64 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -1,7 +1,7 @@ name: example description: A new Flutter project. publish_to: 'none' -version: 1.3.3 +version: 1.3.3+2 environment: sdk: ">=2.2.2 <3.0.0" From 0627bf4e2eaf15924021f0977cd458753a6dc557 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 15 Mar 2021 15:53:05 +0100 Subject: [PATCH 006/172] fix advanced options --- stream_chat_v1/lib/advanced_options_page.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stream_chat_v1/lib/advanced_options_page.dart b/stream_chat_v1/lib/advanced_options_page.dart index f3ea431be2..ed5e1b568c 100644 --- a/stream_chat_v1/lib/advanced_options_page.dart +++ b/stream_chat_v1/lib/advanced_options_page.dart @@ -272,7 +272,7 @@ class _AdvancedOptionsPageState extends State { )..chatPersistenceClient = chatPersistentClient; try { - await client.setUser( + await client.connectUser( User(id: userId, extraData: { 'name': username, }), @@ -292,6 +292,7 @@ class _AdvancedOptionsPageState extends State { key: kStreamToken, value: userToken, ); + await client.disconnect(); } catch (e) { var errorText = 'Error connecting, retry'; if (e is Map) { From 0fd7c2d227f7f549067a7b341630ba41737d61ab Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 15 Mar 2021 15:57:56 +0100 Subject: [PATCH 007/172] fix error capitalization --- stream_chat_v1/lib/advanced_options_page.dart | 26 ++++++++++++------- stream_chat_v1/lib/main.dart | 1 + 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/stream_chat_v1/lib/advanced_options_page.dart b/stream_chat_v1/lib/advanced_options_page.dart index ed5e1b568c..a654f3de13 100644 --- a/stream_chat_v1/lib/advanced_options_page.dart +++ b/stream_chat_v1/lib/advanced_options_page.dart @@ -75,7 +75,8 @@ class _AdvancedOptionsPageState extends State { validator: (value) { if (value.isEmpty) { setState(() { - _apiKeyError = 'Please enter the Chat API Key'; + _apiKeyError = + 'Please enter the Chat API Key'.toUpperCase(); }); return _apiKeyError; } @@ -101,8 +102,9 @@ class _AdvancedOptionsPageState extends State { fillColor: StreamChatTheme.of(context).colorTheme.whiteSmoke, filled: true, - labelText: - 'Chat API Key ${_apiKeyError != null ? ': $_apiKeyError' : ''}', + labelText: _apiKeyError != null + ? 'CHAT API KEY: $_apiKeyError' + : 'Chat API Key', ), textInputAction: TextInputAction.next, ), @@ -119,7 +121,8 @@ class _AdvancedOptionsPageState extends State { validator: (value) { if (value.isEmpty) { setState(() { - _userIdError = 'Please enter the User ID'; + _userIdError = + 'Please enter the User ID'.toUpperCase(); }); return _userIdError; } @@ -146,8 +149,9 @@ class _AdvancedOptionsPageState extends State { fillColor: StreamChatTheme.of(context).colorTheme.whiteSmoke, filled: true, - labelText: - 'User ID ${_userIdError != null ? ': $_userIdError' : ''}', + labelText: _userIdError != null + ? 'USER ID: $_userIdError' + : 'User ID', ), ), SizedBox(height: 8), @@ -163,7 +167,8 @@ class _AdvancedOptionsPageState extends State { validator: (value) { if (value.isEmpty) { setState(() { - _userTokenError = 'Please enter the user token'; + _userTokenError = + 'Please enter the user token'.toUpperCase(); }); return _userTokenError; } @@ -190,8 +195,9 @@ class _AdvancedOptionsPageState extends State { fillColor: StreamChatTheme.of(context).colorTheme.whiteSmoke, filled: true, - labelText: - 'User Token ${_userTokenError != null ? ': $_userTokenError' : ''}', + labelText: _userTokenError != null + ? 'USER TOKEN: $_userTokenError' + : 'User Token', ), ), SizedBox(height: 8), @@ -300,7 +306,7 @@ class _AdvancedOptionsPageState extends State { } Navigator.pop(context); setState(() { - _apiKeyError = errorText; + _apiKeyError = errorText.toUpperCase(); }); loading = false; await client.disconnect(); diff --git a/stream_chat_v1/lib/main.dart b/stream_chat_v1/lib/main.dart index 2fb2cf8b1b..0b219a120b 100644 --- a/stream_chat_v1/lib/main.dart +++ b/stream_chat_v1/lib/main.dart @@ -932,6 +932,7 @@ class _ChannelPageState extends State { ), MessageInput( focusNode: _focusNode, + actionsLocation: ActionsLocation.rightInside, quotedMessage: _quotedMessage, onQuotedMessageCleared: () { setState(() => _quotedMessage = null); From 01e547df01662ca265a787656f3b5325549c1c86 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 15 Mar 2021 16:35:18 +0100 Subject: [PATCH 008/172] fix cancel button --- stream_chat_v1/lib/group_info_screen.dart | 25 +++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/group_info_screen.dart index f0c7ff34f4..b76cc9b9d8 100644 --- a/stream_chat_v1/lib/group_info_screen.dart +++ b/stream_chat_v1/lib/group_info_screen.dart @@ -107,10 +107,11 @@ class _GroupInfoScreenState extends State { return Text( _getChannelName( - 2 * MediaQuery.of(context).size.width / 3, - members: snapshot.data, - extraData: state.data.channel.extraData, - maxFontSize: 16.0), + 2 * MediaQuery.of(context).size.width / 3, + members: snapshot.data, + extraData: state.data.channel.extraData, + maxFontSize: 16.0, + ), style: TextStyle( color: StreamChatTheme.of(context).colorTheme.black, fontSize: 16, @@ -376,8 +377,12 @@ class _GroupInfoScreenState extends State { child: StreamSvgIcon.closeSmall(), onTap: () { setState(() { - _nameController.text = - _getChannelName(MediaQuery.of(context).size.width); + _nameController.text = _getChannelName( + 2 * MediaQuery.of(context).size.width / 3, + members: channel.state.members, + extraData: channel.extraData, + maxFontSize: 16.0, + ); _focusNode.unfocus(); }); }, @@ -996,8 +1001,12 @@ class _GroupInfoScreenState extends State { ); } - String _getChannelName(double width, - {List members, Map extraData, double maxFontSize}) { + String _getChannelName( + double width, { + List members, + Map extraData, + double maxFontSize, + }) { String title; var client = StreamChat.of(context); if (extraData['name'] == null) { From efae0ca337e3ec1ae852067f57154e3856859943 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 15 Mar 2021 16:44:52 +0100 Subject: [PATCH 009/172] restore action location --- stream_chat_v1/lib/main.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/stream_chat_v1/lib/main.dart b/stream_chat_v1/lib/main.dart index 0b219a120b..2fb2cf8b1b 100644 --- a/stream_chat_v1/lib/main.dart +++ b/stream_chat_v1/lib/main.dart @@ -932,7 +932,6 @@ class _ChannelPageState extends State { ), MessageInput( focusNode: _focusNode, - actionsLocation: ActionsLocation.rightInside, quotedMessage: _quotedMessage, onQuotedMessageCleared: () { setState(() => _quotedMessage = null); From 5bd1db257e369311e628798cb7886ab4570c0de7 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 16 Mar 2021 17:14:03 +0100 Subject: [PATCH 010/172] Merge branch 'main' into develop --- stream_chat_v1/README.md | 2 + .../ios/Runner.xcodeproj/project.pbxproj | 39 +++++++++++++------ 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/stream_chat_v1/README.md b/stream_chat_v1/README.md index 834bc8d534..a7d543793d 100644 --- a/stream_chat_v1/README.md +++ b/stream_chat_v1/README.md @@ -22,6 +22,8 @@ It supports several advanced features like: - Markdown message formatting - Count for unread messages +![Features iOS](https://user-images.githubusercontent.com/20601437/110333493-eb023a80-8021-11eb-8fb1-b74f9ef37897.gif) + ## Getting Started Before running this project please ensure Flutter is installed and configured on your machine. If you're new to Flutter, please checkout the [official guide](https://flutter.dev/docs/get-started/install) with installation instructions for your OS. diff --git a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj index 8cd3ed03df..6c9b2931be 100644 --- a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj +++ b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 6322551A583705BBA2F048DD /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC299D593714162503D904EB /* Pods_Runner.framework */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 78DFDA8BF7ADD8988BA9B2C9 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A4E5F7C8F1FB8AA92A6E2273 /* Pods_Runner.framework */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; @@ -301,41 +302,55 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - 9740EEB61CF901F6004384FC /* Run Script */ = { + 22D055914083BAC1E72E76DD /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( ); - name = "Run Script"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; }; A83A30E8FF0298FDB3189FB1 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - ); inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( ); + inputPaths = ( + ); + name = "Run Script"; outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; /* End PBXShellScriptBuildPhase section */ From ea46213ffb2dcf1b706c2836e33e4724d22ed9ba Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 16 Mar 2021 17:55:04 +0100 Subject: [PATCH 011/172] update dependencies --- .../ios/Runner.xcodeproj/project.pbxproj | 34 +++++++++---------- stream_chat_v1/pubspec.yaml | 26 ++------------ 2 files changed, 20 insertions(+), 40 deletions(-) diff --git a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj index 6c9b2931be..012eabbd38 100644 --- a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj +++ b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj @@ -9,7 +9,6 @@ /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 6322551A583705BBA2F048DD /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC299D593714162503D904EB /* Pods_Runner.framework */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 78DFDA8BF7ADD8988BA9B2C9 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A4E5F7C8F1FB8AA92A6E2273 /* Pods_Runner.framework */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; @@ -152,7 +151,8 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - A83A30E8FF0298FDB3189FB1 /* [CP] Check Pods Manifest.lock */, + B03C7154EEC8CB4C6391A8CB /* [CP] Check Pods Manifest.lock */, + A83A30E8FF0298FDB3189FB1 /* Thin Binary */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, @@ -302,29 +302,21 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - 22D055914083BAC1E72E76DD /* [CP] Check Pods Manifest.lock */ = { + 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - ); inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( ); + name = "Run Script"; outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; - A83A30E8FF0298FDB3189FB1 /* [CP] Check Pods Manifest.lock */ = { + A83A30E8FF0298FDB3189FB1 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -338,19 +330,27 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; - 9740EEB61CF901F6004384FC /* Run Script */ = { + B03C7154EEC8CB4C6391A8CB /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( ); - name = "Run Script"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index ba5f058c64..afcb0cf4a0 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -1,7 +1,7 @@ name: example description: A new Flutter project. publish_to: 'none' -version: 1.3.3+2 +version: 1.5.0 environment: sdk: ">=2.2.2 <3.0.0" @@ -10,16 +10,8 @@ dependencies: flutter_app_badger: ^1.1.2 flutter: sdk: flutter - stream_chat_flutter: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop - path: packages/stream_chat_flutter - stream_chat_persistence: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop - path: packages/stream_chat_persistence + stream_chat_flutter: ^1.5.0 + stream_chat_persistence: ^1.5.0 flutter_local_notifications: ^2.0.2 flutter_svg: ^0.19.3 flutter_secure_storage: ^3.3.5 @@ -28,18 +20,6 @@ dependencies: streaming_shared_preferences: ^1.0.2 lottie: ^0.7.0+1 -dependency_overrides: - stream_chat: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop - path: packages/stream_chat - stream_chat_flutter_core: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop - path: packages/stream_chat_flutter_core - dev_dependencies: flutter_launcher_icons: ^0.8.1 test: any From 59366aa096dc6babb9b1c1d190a6d5791d7cd51b Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 16 Mar 2021 18:15:32 +0100 Subject: [PATCH 012/172] fix ios build --- stream_chat_v1/.gitignore | 46 ++ stream_chat_v1/.metadata | 10 + .../getstream/stream_chat_v1/MainActivity.kt | 6 + .../res/drawable-v21/launch_background.xml | 12 + .../app/src/main/res/values-night/styles.xml | 18 + .../ios/Runner.xcodeproj/project.pbxproj | 19 +- stream_chat_v1/macos/.gitignore | 6 + .../macos/Flutter/Flutter-Debug.xcconfig | 2 + .../macos/Flutter/Flutter-Release.xcconfig | 2 + .../macos/Runner.xcodeproj/project.pbxproj | 572 ++++++++++++++++++ .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 89 +++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + stream_chat_v1/macos/Runner/AppDelegate.swift | 9 + .../AppIcon.appiconset/Contents.json | 68 +++ .../AppIcon.appiconset/app_icon_1024.png | Bin 0 -> 46993 bytes .../AppIcon.appiconset/app_icon_128.png | Bin 0 -> 3276 bytes .../AppIcon.appiconset/app_icon_16.png | Bin 0 -> 1429 bytes .../AppIcon.appiconset/app_icon_256.png | Bin 0 -> 5933 bytes .../AppIcon.appiconset/app_icon_32.png | Bin 0 -> 1243 bytes .../AppIcon.appiconset/app_icon_512.png | Bin 0 -> 14800 bytes .../AppIcon.appiconset/app_icon_64.png | Bin 0 -> 1874 bytes .../macos/Runner/Base.lproj/MainMenu.xib | 339 +++++++++++ .../macos/Runner/Configs/AppInfo.xcconfig | 14 + .../macos/Runner/Configs/Debug.xcconfig | 2 + .../macos/Runner/Configs/Release.xcconfig | 2 + .../macos/Runner/Configs/Warnings.xcconfig | 13 + .../macos/Runner/DebugProfile.entitlements | 12 + stream_chat_v1/macos/Runner/Info.plist | 32 + .../macos/Runner/MainFlutterWindow.swift | 15 + .../macos/Runner/Release.entitlements | 8 + stream_chat_v1/test/widget_test.dart | 30 + 33 files changed, 1332 insertions(+), 17 deletions(-) create mode 100644 stream_chat_v1/.gitignore create mode 100644 stream_chat_v1/.metadata create mode 100644 stream_chat_v1/android/app/src/main/kotlin/io/getstream/stream_chat_v1/MainActivity.kt create mode 100644 stream_chat_v1/android/app/src/main/res/drawable-v21/launch_background.xml create mode 100644 stream_chat_v1/android/app/src/main/res/values-night/styles.xml create mode 100644 stream_chat_v1/macos/.gitignore create mode 100644 stream_chat_v1/macos/Flutter/Flutter-Debug.xcconfig create mode 100644 stream_chat_v1/macos/Flutter/Flutter-Release.xcconfig create mode 100644 stream_chat_v1/macos/Runner.xcodeproj/project.pbxproj create mode 100644 stream_chat_v1/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 stream_chat_v1/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 stream_chat_v1/macos/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 stream_chat_v1/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 stream_chat_v1/macos/Runner/AppDelegate.swift create mode 100644 stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png create mode 100644 stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png create mode 100644 stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png create mode 100644 stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png create mode 100644 stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png create mode 100644 stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png create mode 100644 stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png create mode 100644 stream_chat_v1/macos/Runner/Base.lproj/MainMenu.xib create mode 100644 stream_chat_v1/macos/Runner/Configs/AppInfo.xcconfig create mode 100644 stream_chat_v1/macos/Runner/Configs/Debug.xcconfig create mode 100644 stream_chat_v1/macos/Runner/Configs/Release.xcconfig create mode 100644 stream_chat_v1/macos/Runner/Configs/Warnings.xcconfig create mode 100644 stream_chat_v1/macos/Runner/DebugProfile.entitlements create mode 100644 stream_chat_v1/macos/Runner/Info.plist create mode 100644 stream_chat_v1/macos/Runner/MainFlutterWindow.swift create mode 100644 stream_chat_v1/macos/Runner/Release.entitlements create mode 100644 stream_chat_v1/test/widget_test.dart diff --git a/stream_chat_v1/.gitignore b/stream_chat_v1/.gitignore new file mode 100644 index 0000000000..0fa6b675c0 --- /dev/null +++ b/stream_chat_v1/.gitignore @@ -0,0 +1,46 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +/build/ + +# Web related +lib/generated_plugin_registrant.dart + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/stream_chat_v1/.metadata b/stream_chat_v1/.metadata new file mode 100644 index 0000000000..783bcdc2a3 --- /dev/null +++ b/stream_chat_v1/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: 8962f6dc68ec8e2206ac2fa874da4a453856c7d3 + channel: stable + +project_type: app diff --git a/stream_chat_v1/android/app/src/main/kotlin/io/getstream/stream_chat_v1/MainActivity.kt b/stream_chat_v1/android/app/src/main/kotlin/io/getstream/stream_chat_v1/MainActivity.kt new file mode 100644 index 0000000000..3b9195b570 --- /dev/null +++ b/stream_chat_v1/android/app/src/main/kotlin/io/getstream/stream_chat_v1/MainActivity.kt @@ -0,0 +1,6 @@ +package io.getstream.stream_chat_v1 + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} diff --git a/stream_chat_v1/android/app/src/main/res/drawable-v21/launch_background.xml b/stream_chat_v1/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 0000000000..f74085f3f6 --- /dev/null +++ b/stream_chat_v1/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/stream_chat_v1/android/app/src/main/res/values-night/styles.xml b/stream_chat_v1/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 0000000000..449a9f9308 --- /dev/null +++ b/stream_chat_v1/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj index 012eabbd38..8cd3ed03df 100644 --- a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj +++ b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj @@ -151,8 +151,7 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - B03C7154EEC8CB4C6391A8CB /* [CP] Check Pods Manifest.lock */, - A83A30E8FF0298FDB3189FB1 /* Thin Binary */, + A83A30E8FF0298FDB3189FB1 /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, @@ -316,21 +315,7 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; - A83A30E8FF0298FDB3189FB1 /* Thin Binary */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Thin Binary"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; - }; - B03C7154EEC8CB4C6391A8CB /* [CP] Check Pods Manifest.lock */ = { + A83A30E8FF0298FDB3189FB1 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( diff --git a/stream_chat_v1/macos/.gitignore b/stream_chat_v1/macos/.gitignore new file mode 100644 index 0000000000..d2fd377230 --- /dev/null +++ b/stream_chat_v1/macos/.gitignore @@ -0,0 +1,6 @@ +# Flutter-related +**/Flutter/ephemeral/ +**/Pods/ + +# Xcode-related +**/xcuserdata/ diff --git a/stream_chat_v1/macos/Flutter/Flutter-Debug.xcconfig b/stream_chat_v1/macos/Flutter/Flutter-Debug.xcconfig new file mode 100644 index 0000000000..4b81f9b2d2 --- /dev/null +++ b/stream_chat_v1/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/stream_chat_v1/macos/Flutter/Flutter-Release.xcconfig b/stream_chat_v1/macos/Flutter/Flutter-Release.xcconfig new file mode 100644 index 0000000000..5caa9d1579 --- /dev/null +++ b/stream_chat_v1/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/stream_chat_v1/macos/Runner.xcodeproj/project.pbxproj b/stream_chat_v1/macos/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..ce10a1fcd4 --- /dev/null +++ b/stream_chat_v1/macos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,572 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 51; + objects = { + +/* Begin PBXAggregateTarget section */ + 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; + buildPhases = ( + 33CC111E2044C6BF0003C045 /* ShellScript */, + ); + dependencies = ( + ); + name = "Flutter Assemble"; + productName = FLX; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC111A2044C6BA0003C045; + remoteInfo = FLX; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 33CC110E2044A8840003C045 /* Bundle Framework */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Bundle Framework"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* stream_chat_v1.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "stream_chat_v1.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; + 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; + 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; + 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 33BA886A226E78AF003329D5 /* Configs */ = { + isa = PBXGroup; + children = ( + 33E5194F232828860026EE4D /* AppInfo.xcconfig */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, + ); + path = Configs; + sourceTree = ""; + }; + 33CC10E42044A3C60003C045 = { + isa = PBXGroup; + children = ( + 33FAB671232836740065AC1E /* Runner */, + 33CEB47122A05771004F2AC0 /* Flutter */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* stream_chat_v1.app */, + ); + name = Products; + sourceTree = ""; + }; + 33CC11242044D66E0003C045 /* Resources */ = { + isa = PBXGroup; + children = ( + 33CC10F22044A3C60003C045 /* Assets.xcassets */, + 33CC10F42044A3C60003C045 /* MainMenu.xib */, + 33CC10F72044A3C60003C045 /* Info.plist */, + ); + name = Resources; + path = ..; + sourceTree = ""; + }; + 33CEB47122A05771004F2AC0 /* Flutter */ = { + isa = PBXGroup; + children = ( + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, + ); + path = Flutter; + sourceTree = ""; + }; + 33FAB671232836740065AC1E /* Runner */ = { + isa = PBXGroup; + children = ( + 33CC10F02044A3C60003C045 /* AppDelegate.swift */, + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33E51913231747F40026EE4D /* DebugProfile.entitlements */, + 33E51914231749380026EE4D /* Release.entitlements */, + 33CC11242044D66E0003C045 /* Resources */, + 33BA886A226E78AF003329D5 /* Configs */, + ); + path = Runner; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 33CC110E2044A8840003C045 /* Bundle Framework */, + 3399D490228B24CF009A79C7 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* stream_chat_v1.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 0930; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 33CC10EC2044A3C60003C045 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + 33CC111A2044C6BA0003C045 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33CC10E42044A3C60003C045; + productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33CC10EC2044A3C60003C045 /* Runner */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 33CC10EB2044A3C60003C045 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3399D490228B24CF009A79C7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; + }; + 33CC111E2044C6BF0003C045 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, + ); + outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 33CC10E92044A3C60003C045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; + targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 33CC10F52044A3C60003C045 /* Base */, + ); + name = MainMenu.xib; + path = Runner; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 338D0CE9231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Profile; + }; + 338D0CEA231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Profile; + }; + 338D0CEB231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + 33CC10F92044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33CC10FA2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 33CC10FC2044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 33CC10FD2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 33CC111C2044C6BA0003C045 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 33CC111D2044C6BA0003C045 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10F92044A3C60003C045 /* Debug */, + 33CC10FA2044A3C60003C045 /* Release */, + 338D0CE9231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10FC2044A3C60003C045 /* Debug */, + 33CC10FD2044A3C60003C045 /* Release */, + 338D0CEA231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC111C2044C6BA0003C045 /* Debug */, + 33CC111D2044C6BA0003C045 /* Release */, + 338D0CEB231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33CC10E52044A3C60003C045 /* Project object */; +} diff --git a/stream_chat_v1/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/stream_chat_v1/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000000..18d981003d --- /dev/null +++ b/stream_chat_v1/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/stream_chat_v1/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/stream_chat_v1/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000000..1961c76671 --- /dev/null +++ b/stream_chat_v1/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/stream_chat_v1/macos/Runner.xcworkspace/contents.xcworkspacedata b/stream_chat_v1/macos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000000..1d526a16ed --- /dev/null +++ b/stream_chat_v1/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/stream_chat_v1/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/stream_chat_v1/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000000..18d981003d --- /dev/null +++ b/stream_chat_v1/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/stream_chat_v1/macos/Runner/AppDelegate.swift b/stream_chat_v1/macos/Runner/AppDelegate.swift new file mode 100644 index 0000000000..d53ef64377 --- /dev/null +++ b/stream_chat_v1/macos/Runner/AppDelegate.swift @@ -0,0 +1,9 @@ +import Cocoa +import FlutterMacOS + +@NSApplicationMain +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } +} diff --git a/stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000000..a2ec33f19f --- /dev/null +++ b/stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_64.png", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_128.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_1024.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png new file mode 100644 index 0000000000000000000000000000000000000000..3c4935a7ca84f0976aca34b7f2895d65fb94d1ea GIT binary patch literal 46993 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 literal 0 HcmV?d00001 diff --git a/stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png new file mode 100644 index 0000000000000000000000000000000000000000..ed4cc16421680a50164ba74381b4b35ceaa0ccfc GIT binary patch literal 3276 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 N;OXk;vd$@?2>?>Ex^Vyi literal 0 HcmV?d00001 diff --git a/stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png new file mode 100644 index 0000000000000000000000000000000000000000..bcbf36df2f2aaaa0a63c7dabc94e600184229d0d GIT binary patch literal 5933 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 f$KZHO*s&vt|9^w-6P?|#0pRK8NSwWJ?9znhg z3{`3j3=J&|48MRv4KElNN(~qoUL`OvSj}Ky5HFasE6@fg!ItFh?!xdN1Q+aGJ{c&& zS>O>_%)r1c48n{Iv*t(u1=&kHeO=ifbFy+6aSK)V_AxLppYn8Z42d|rc6w}vOsL55 z`t&mC&y2@JTEyg!eDiFX^k#CC!jq%>erB=yHqUP0XcDOTw6ko}L zX;EmMrq(fKk*eygEuA616;0)>@A{TK|55PV@70 z$OfzS*(VJxQev3J?yY?O=ul(v`fp}?u9z`JK3ugibK>)DyCwImZOF4d{xK%%Ks1*} zv$oa)9anR%lXIBUqYnhLmT>VOzHfNP?ZwJNZ!5$s9M08RynIvaXw>@G^T9@r9^KH1 zVy??F&uuk)bH9Y4pQY!hP58i_H6 znl-NcuCpLV6ZWU;4C zu@9exF&OZi`Bovq_m%T+WhU2kvkz@^_LpycBvqm3bMpLw8X-Or5sL>0AKE1$(k_L=_Zc=CUq#=x1-QZf)G7nHu@fmsQ1eN_N3+nTEz`4HI4Z6uVlE zJH+X&det8JU?tO?upcM4Z=cV!JV;yF>FfL5Q$M|W_2Z!P`S=}Wzp|_1^#d%e?_H`> zV@%vA$+bFVqhw9`U;TfP|5|PD{||OiYdor8P*i??|NJcb%kzT_73*7WE?Ua5hAnR2 z=7WE=PhTlJ#ZeRznjTUb;`E(wkMZrj4e|Hilz-mK>9cZHQY**5TUPw~u}k;u73KI}xAx!0m-)GVia|x^d3p~s_9gh83jA&Ra<8rM%`>U3x69t&NzbwWY}7Ar?)FK#IZ0z|d0H0EkRO w3{9;}4Xg|ebq&m|3=9_N6z8I7$jwj5OsmAL;bP(Gi$Dzwp00i_>zopr02+f8CIA2c literal 0 HcmV?d00001 diff --git a/stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png new file mode 100644 index 0000000000000000000000000000000000000000..e71a726136a47ed24125c7efc79d68a4a01961b4 GIT binary patch literal 14800 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 + + + + + + + + + + + + + + + + + + + + + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/stream_chat_v1/macos/Runner/Configs/AppInfo.xcconfig b/stream_chat_v1/macos/Runner/Configs/AppInfo.xcconfig new file mode 100644 index 0000000000..66cfb8165f --- /dev/null +++ b/stream_chat_v1/macos/Runner/Configs/AppInfo.xcconfig @@ -0,0 +1,14 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = stream_chat_v1 + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = io.getstream.streamChatV1 + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright ยฉ 2021 io.getstream. All rights reserved. diff --git a/stream_chat_v1/macos/Runner/Configs/Debug.xcconfig b/stream_chat_v1/macos/Runner/Configs/Debug.xcconfig new file mode 100644 index 0000000000..36b0fd9464 --- /dev/null +++ b/stream_chat_v1/macos/Runner/Configs/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Debug.xcconfig" +#include "Warnings.xcconfig" diff --git a/stream_chat_v1/macos/Runner/Configs/Release.xcconfig b/stream_chat_v1/macos/Runner/Configs/Release.xcconfig new file mode 100644 index 0000000000..dff4f49561 --- /dev/null +++ b/stream_chat_v1/macos/Runner/Configs/Release.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Release.xcconfig" +#include "Warnings.xcconfig" diff --git a/stream_chat_v1/macos/Runner/Configs/Warnings.xcconfig b/stream_chat_v1/macos/Runner/Configs/Warnings.xcconfig new file mode 100644 index 0000000000..42bcbf4780 --- /dev/null +++ b/stream_chat_v1/macos/Runner/Configs/Warnings.xcconfig @@ -0,0 +1,13 @@ +WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings +GCC_WARN_UNDECLARED_SELECTOR = YES +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_PRAGMA_PACK = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +CLANG_WARN_COMMA = YES +GCC_WARN_STRICT_SELECTOR_MATCH = YES +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +GCC_WARN_SHADOW = YES +CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/stream_chat_v1/macos/Runner/DebugProfile.entitlements b/stream_chat_v1/macos/Runner/DebugProfile.entitlements new file mode 100644 index 0000000000..dddb8a30c8 --- /dev/null +++ b/stream_chat_v1/macos/Runner/DebugProfile.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.network.server + + + diff --git a/stream_chat_v1/macos/Runner/Info.plist b/stream_chat_v1/macos/Runner/Info.plist new file mode 100644 index 0000000000..4789daa6a4 --- /dev/null +++ b/stream_chat_v1/macos/Runner/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/stream_chat_v1/macos/Runner/MainFlutterWindow.swift b/stream_chat_v1/macos/Runner/MainFlutterWindow.swift new file mode 100644 index 0000000000..2722837ec9 --- /dev/null +++ b/stream_chat_v1/macos/Runner/MainFlutterWindow.swift @@ -0,0 +1,15 @@ +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController.init() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } +} diff --git a/stream_chat_v1/macos/Runner/Release.entitlements b/stream_chat_v1/macos/Runner/Release.entitlements new file mode 100644 index 0000000000..852fa1a472 --- /dev/null +++ b/stream_chat_v1/macos/Runner/Release.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.app-sandbox + + + diff --git a/stream_chat_v1/test/widget_test.dart b/stream_chat_v1/test/widget_test.dart new file mode 100644 index 0000000000..2d257c02ef --- /dev/null +++ b/stream_chat_v1/test/widget_test.dart @@ -0,0 +1,30 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility that Flutter provides. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:stream_chat_v1/main.dart'; + +void main() { + testWidgets('Counter increments smoke test', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(MyApp()); + + // Verify that our counter starts at 0. + expect(find.text('0'), findsOneWidget); + expect(find.text('1'), findsNothing); + + // Tap the '+' icon and trigger a frame. + await tester.tap(find.byIcon(Icons.add)); + await tester.pump(); + + // Verify that our counter has incremented. + expect(find.text('0'), findsNothing); + expect(find.text('1'), findsOneWidget); + }); +} From c134ec7bc49b677d8f2bdc8a28d9572a7623fbdc Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 16 Mar 2021 18:22:01 +0100 Subject: [PATCH 013/172] update dependencies --- stream_chat_v1/pubspec.yaml | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index afcb0cf4a0..f0e9e65636 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -10,8 +10,16 @@ dependencies: flutter_app_badger: ^1.1.2 flutter: sdk: flutter - stream_chat_flutter: ^1.5.0 - stream_chat_persistence: ^1.5.0 + stream_chat_flutter: + git: + url: https://github.com/GetStream/stream-chat-flutter.git + ref: develop + path: packages/stream_chat_flutter + stream_chat_persistence: + git: + url: https://github.com/GetStream/stream-chat-flutter.git + ref: develop + path: packages/stream_chat_persistence flutter_local_notifications: ^2.0.2 flutter_svg: ^0.19.3 flutter_secure_storage: ^3.3.5 @@ -20,6 +28,18 @@ dependencies: streaming_shared_preferences: ^1.0.2 lottie: ^0.7.0+1 +dependency_overrides: + stream_chat: + git: + url: https://github.com/GetStream/stream-chat-flutter.git + ref: develop + path: packages/stream_chat + stream_chat_flutter_core: + git: + url: https://github.com/GetStream/stream-chat-flutter.git + ref: develop + path: packages/stream_chat_flutter_core + dev_dependencies: flutter_launcher_icons: ^0.8.1 test: any From 8cc7273f2814f1f72d2f8d1317fc78fb882b4070 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 29 Mar 2021 12:38:36 +0200 Subject: [PATCH 014/172] move file and media screens to sample app --- .../lib/channel_file_display_screen.dart | 180 +++++++++++++ .../lib/channel_media_display_screen.dart | 249 ++++++++++++++++++ stream_chat_v1/lib/chat_info_screen.dart | 2 + stream_chat_v1/lib/group_info_screen.dart | 2 + 4 files changed, 433 insertions(+) create mode 100644 stream_chat_v1/lib/channel_file_display_screen.dart create mode 100644 stream_chat_v1/lib/channel_media_display_screen.dart diff --git a/stream_chat_v1/lib/channel_file_display_screen.dart b/stream_chat_v1/lib/channel_file_display_screen.dart new file mode 100644 index 0000000000..2779ba3422 --- /dev/null +++ b/stream_chat_v1/lib/channel_file_display_screen.dart @@ -0,0 +1,180 @@ +import 'package:flutter/material.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; + +class ChannelFileDisplayScreen extends StatefulWidget { + /// The sorting used for the channels matching the filters. + /// Sorting is based on field and direction, multiple sorting options can be provided. + /// You can sort based on last_updated, last_message_at, updated_at, created_at or member_count. + /// Direction can be ascending or descending. + final List sortOptions; + + /// Pagination parameters + /// limit: the number of users to return (max is 30) + /// offset: the offset (max is 1000) + /// message_limit: how many messages should be included to each channel + final PaginationParams paginationParams; + + /// The builder used when the file list is empty. + final WidgetBuilder emptyBuilder; + + const ChannelFileDisplayScreen({ + this.sortOptions, + this.paginationParams, + this.emptyBuilder, + }); + + @override + _ChannelFileDisplayScreenState createState() => + _ChannelFileDisplayScreenState(); +} + +class _ChannelFileDisplayScreenState extends State { + @override + void initState() { + super.initState(); + final messageSearchBloc = MessageSearchBloc.of(context); + messageSearchBloc.search( + filter: { + 'cid': { + r'$in': [StreamChannel.of(context).channel.cid] + } + }, + messageFilter: { + 'attachments.type': { + r'$in': ['file'], + }, + }, + sort: widget.sortOptions, + pagination: widget.paginationParams, + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: StreamChatTheme.of(context).colorTheme.white, + appBar: AppBar( + brightness: Theme.of(context).brightness, + elevation: 1, + centerTitle: true, + title: Text( + 'Files', + style: TextStyle( + color: StreamChatTheme.of(context).colorTheme.black, + fontSize: 16.0), + ), + leading: Center( + child: InkWell( + onTap: () { + Navigator.of(context).pop(); + }, + child: Container( + width: 24.0, + height: 24.0, + child: StreamSvgIcon.left( + color: StreamChatTheme.of(context).colorTheme.black, + size: 24.0, + ), + ), + ), + ), + backgroundColor: StreamChatTheme.of(context).colorTheme.white, + ), + body: _buildMediaGrid(), + ); + } + + Widget _buildMediaGrid() { + final messageSearchBloc = MessageSearchBloc.of(context); + + return StreamBuilder>( + builder: (context, snapshot) { + if (snapshot.data == null) { + return Center( + child: const CircularProgressIndicator(), + ); + } + + if (snapshot.data.isEmpty) { + if (widget.emptyBuilder != null) { + return widget.emptyBuilder(context); + } + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + StreamSvgIcon.files( + size: 136.0, + color: StreamChatTheme.of(context).colorTheme.greyGainsboro, + ), + SizedBox(height: 16.0), + Text( + 'No Files', + style: TextStyle( + fontSize: 14.0, + color: StreamChatTheme.of(context).colorTheme.black, + ), + ), + SizedBox(height: 8.0), + Text( + 'Files sent in this chat will appear here', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 14.0, + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(0.5), + ), + ), + ], + ), + ); + } + + final media = {}; + + for (var item in snapshot.data) { + item.message.attachments.where((e) => e.type == 'file').forEach((e) { + media[e] = item.message; + }); + } + + return LazyLoadScrollView( + onEndOfPage: () => messageSearchBloc.loadMore( + filter: { + 'cid': { + r'$in': [StreamChannel.of(context).channel.cid] + } + }, + messageFilter: { + 'attachments.type': { + r'$in': ['file'] + }, + }, + sort: widget.sortOptions, + pagination: widget.paginationParams.copyWith( + offset: messageSearchBloc.messageResponses?.length ?? 0, + ), + ), + child: ListView.builder( + itemBuilder: (context, position) { + return Padding( + padding: const EdgeInsets.all(1.0), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: FileAttachment( + message: media.values.toList()[position], + attachment: media.keys.toList()[position], + ), + ), + ); + }, + itemCount: media.length, + ), + ); + }, + stream: messageSearchBloc.messagesStream, + ); + } +} diff --git a/stream_chat_v1/lib/channel_media_display_screen.dart b/stream_chat_v1/lib/channel_media_display_screen.dart new file mode 100644 index 0000000000..e09b122102 --- /dev/null +++ b/stream_chat_v1/lib/channel_media_display_screen.dart @@ -0,0 +1,249 @@ +import 'package:flutter/material.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; +import 'package:video_player/video_player.dart'; + +class ChannelMediaDisplayScreen extends StatefulWidget { + /// The sorting used for the channels matching the filters. + /// Sorting is based on field and direction, multiple sorting options can be provided. + /// You can sort based on last_updated, last_message_at, updated_at, created_at or member_count. + /// Direction can be ascending or descending. + final List sortOptions; + + /// Pagination parameters + /// limit: the number of users to return (max is 30) + /// offset: the offset (max is 1000) + /// message_limit: how many messages should be included to each channel + final PaginationParams paginationParams; + + /// The builder used when the file list is empty. + final WidgetBuilder emptyBuilder; + + final ShowMessageCallback onShowMessage; + + const ChannelMediaDisplayScreen({ + this.sortOptions, + this.paginationParams, + this.emptyBuilder, + this.onShowMessage, + }); + + @override + _ChannelMediaDisplayScreenState createState() => + _ChannelMediaDisplayScreenState(); +} + +class _ChannelMediaDisplayScreenState extends State { + Map controllerCache = {}; + + @override + void initState() { + super.initState(); + final messageSearchBloc = MessageSearchBloc.of(context); + messageSearchBloc.search( + filter: { + 'cid': { + r'$in': [StreamChannel.of(context).channel.cid], + } + }, + messageFilter: { + 'attachments.type': { + r'$in': ['image', 'video'] + }, + }, + sort: widget.sortOptions, + pagination: widget.paginationParams, + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: StreamChatTheme.of(context).colorTheme.white, + appBar: AppBar( + brightness: Theme.of(context).brightness, + elevation: 1, + centerTitle: true, + title: Text( + 'Photos & Videos', + style: TextStyle( + color: StreamChatTheme.of(context).colorTheme.black, + fontSize: 16.0, + ), + ), + leading: Center( + child: InkWell( + onTap: () { + Navigator.of(context).pop(); + }, + child: Container( + width: 24.0, + height: 24.0, + child: StreamSvgIcon.left( + color: StreamChatTheme.of(context).colorTheme.black, + size: 24.0, + ), + ), + ), + ), + backgroundColor: StreamChatTheme.of(context).colorTheme.white, + ), + body: _buildMediaGrid(), + ); + } + + Widget _buildMediaGrid() { + final messageSearchBloc = MessageSearchBloc.of(context); + + return StreamBuilder>( + builder: (context, snapshot) { + if (snapshot.data == null) { + return Center( + child: const CircularProgressIndicator(), + ); + } + + if (snapshot.data.isEmpty) { + if (widget.emptyBuilder != null) { + return widget.emptyBuilder(context); + } + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + StreamSvgIcon.pictures( + size: 136.0, + color: StreamChatTheme.of(context).colorTheme.greyGainsboro, + ), + SizedBox(height: 16.0), + Text( + 'No Media', + style: TextStyle( + fontSize: 14.0, + color: StreamChatTheme.of(context).colorTheme.black, + ), + ), + SizedBox(height: 8.0), + Text( + 'Photos or video sent in this chat will \nappear here', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 14.0, + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(0.5), + ), + ), + ], + ), + ); + } + + final media = <_AssetPackage>[]; + + for (var item in snapshot.data) { + item.message.attachments + .where((e) => + (e.type == 'image' || e.type == 'video') && + e.ogScrapeUrl == null) + .forEach((e) { + VideoPlayerController controller; + if (e.type == 'video') { + var cachedController = controllerCache[e.assetUrl]; + + if (cachedController == null) { + controller = VideoPlayerController.network(e.assetUrl); + controller.initialize(); + controllerCache[e.assetUrl] = controller; + } else { + controller = cachedController; + } + } + media.add(_AssetPackage(e, item.message, controller)); + }); + } + + return LazyLoadScrollView( + onEndOfPage: () => messageSearchBloc.loadMore( + filter: { + 'cid': { + r'$in': [StreamChannel.of(context).channel.cid] + } + }, + messageFilter: { + 'attachments.type': { + r'$in': ['image', 'video'] + }, + }, + sort: widget.sortOptions, + pagination: widget.paginationParams.copyWith( + offset: messageSearchBloc.messageResponses?.length ?? 0, + ), + ), + child: GridView.builder( + gridDelegate: + SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3), + itemBuilder: (context, position) { + var channel = StreamChannel.of(context).channel; + return Padding( + padding: const EdgeInsets.all(1.0), + child: InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => StreamChannel( + channel: channel, + child: FullScreenMedia( + mediaAttachments: + media.map((e) => e.attachment).toList(), + startIndex: position, + message: media[position].message, + sentAt: media[position].message.createdAt, + userName: media[position].message.user.name, + onShowMessage: widget.onShowMessage, + ), + ), + ), + ); + }, + child: media[position].attachment.type == 'image' + ? IgnorePointer( + child: ImageAttachment( + attachment: media[position].attachment, + message: media[position].message, + showTitle: false, + size: Size( + MediaQuery.of(context).size.width * 0.8, + MediaQuery.of(context).size.height * 0.3, + ), + ), + ) + : VideoPlayer(media[position].videoPlayer), + ), + ); + }, + itemCount: media.length, + ), + ); + }, + stream: messageSearchBloc.messagesStream, + ); + } + + @override + void dispose() { + super.dispose(); + for (var c in controllerCache.values) { + c.dispose(); + } + } +} + +class _AssetPackage { + Attachment attachment; + Message message; + VideoPlayerController videoPlayer; + + _AssetPackage(this.attachment, this.message, this.videoPlayer); +} diff --git a/stream_chat_v1/lib/chat_info_screen.dart b/stream_chat_v1/lib/chat_info_screen.dart index 5c8441ed05..1668132d2e 100644 --- a/stream_chat_v1/lib/chat_info_screen.dart +++ b/stream_chat_v1/lib/chat_info_screen.dart @@ -1,3 +1,5 @@ +import 'package:example/channel_file_display_screen.dart'; +import 'package:example/channel_media_display_screen.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:jiffy/jiffy.dart'; diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/group_info_screen.dart index b76cc9b9d8..cfcdea63c3 100644 --- a/stream_chat_v1/lib/group_info_screen.dart +++ b/stream_chat_v1/lib/group_info_screen.dart @@ -1,5 +1,7 @@ import 'dart:async'; +import 'package:example/channel_file_display_screen.dart'; +import 'package:example/channel_media_display_screen.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:jiffy/jiffy.dart'; From 3a3259d3fd66807a1e7a406fe4c9437f3c31a4ea Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 30 Mar 2021 10:11:27 +0200 Subject: [PATCH 015/172] move app config to separate file and use a production version on master github actions --- stream_chat_v1/.gitignore | 1 + stream_chat_v1/lib/app_config.dart | 81 ++++++++++++++++++++++++ stream_chat_v1/lib/choose_user_page.dart | 80 +---------------------- stream_chat_v1/pubspec.yaml | 20 ++---- 4 files changed, 88 insertions(+), 94 deletions(-) create mode 100644 stream_chat_v1/lib/app_config.dart diff --git a/stream_chat_v1/.gitignore b/stream_chat_v1/.gitignore index 0fa6b675c0..114843e11f 100644 --- a/stream_chat_v1/.gitignore +++ b/stream_chat_v1/.gitignore @@ -44,3 +44,4 @@ app.*.map.json /android/app/debug /android/app/profile /android/app/release +lib/production_app_config.dart diff --git a/stream_chat_v1/lib/app_config.dart b/stream_chat_v1/lib/app_config.dart new file mode 100644 index 0000000000..c5fbe67171 --- /dev/null +++ b/stream_chat_v1/lib/app_config.dart @@ -0,0 +1,81 @@ +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; + +const kDefaultStreamApiKey = 'kv7mcsxr24p8'; + +final defaultUsers = { + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoic2FsdmF0b3JlIn0.pgiJz7sIc7iP29BHKFwe3nLm5-OaR_1l2P-SlgiC9a8': + User( + id: 'salvatore', + extraData: { + 'name': 'Salvatore Giordano', + 'image': + 'https://avatars.githubusercontent.com/u/20601437?s=460&u=3f66c22a7483980624804054ae7f357cf102c784&v=4', + }, + ), + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoic2FoaWwifQ.WnIUoB5gR2kcAsFhiDvkiD6zdHXZ-VSU2aQWWkhsvfo': + User( + id: 'sahil', + extraData: { + 'name': 'Sahil Kumar', + 'image': + 'https://avatars.githubusercontent.com/u/25670178?s=400&u=30ded3784d8d2310c5748f263fd5e6433c119aa1&v=4', + }, + ), + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiYmVuIn0.nAz2sNFGQwY7rl2Og2z3TGHUsdpnN53tOsUglJFvLmg': + User( + id: 'ben', + extraData: { + 'name': 'Ben Golden', + 'image': 'https://avatars.githubusercontent.com/u/1581974?s=400&v=4', + }, + ), + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoidGhpZXJyeSJ9.lEq6TrZtHzjoNtf7HHRufUPyGo_pa8vg4_XhEBp4ckY': + User( + id: 'thierry', + extraData: { + 'name': 'Thierry Schellenbach', + 'image': + 'https://avatars.githubusercontent.com/u/265409?s=400&u=2d0e3bb1820db992066196bff7b004f0eee8e28d&v=4', + }, + ), + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoidG9tbWFzbyJ9.GLSI0ESshERMo2WjUpysD709NEtn1zmGimUN2an7g9o': + User( + id: 'tommaso', + extraData: { + 'name': 'Tommaso Barbugli', + 'image': 'https://avatars.githubusercontent.com/u/88735?s=400&v=4', + }, + ), + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiZGV2ZW4ifQ.z3zI4PqJnNhc-1o-VKcmb6BnnQ0oxFNCRHwEulHqcWc': + User( + id: 'deven', + extraData: { + 'name': 'Deven Joshi', + 'image': + 'https://avatars.githubusercontent.com/u/26357843?s=400&u=0c61d890866e67bf69f58878be58915e9bfd39ee&v=4', + }, + ), + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoibmVldmFzaCJ9.3EdHegTxibrz3A9cTiKmpEyawwcCVB8FXnoFzr4eKvw': + User( + id: 'neevash', + extraData: { + 'name': 'Neevash Ramdial', + 'image': + 'https://avatars.githubusercontent.com/u/25674767?s=400&u=1d7333baf7dd9d143db8bfcdb31a838b89cfff9c&v=4', + }, + ), + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoicWF0ZXN0MSJ9.fnelU7HcP7QoEEsCGteNlF1fppofzNlrnpDQuIgeKCU': + User( + id: 'qatest1', + extraData: { + 'name': 'QA test 1', + }, + ), + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoicWF0ZXN0MiJ9.vSCqAEbs2WVmMWsOsa7065Fsjq-rsTih6qsHPynl7XM': + User( + id: 'qatest2', + extraData: { + 'name': 'QA test 2', + }, + ), +}; diff --git a/stream_chat_v1/lib/choose_user_page.dart b/stream_chat_v1/lib/choose_user_page.dart index b796e5e873..8cb0cad1cc 100644 --- a/stream_chat_v1/lib/choose_user_page.dart +++ b/stream_chat_v1/lib/choose_user_page.dart @@ -1,3 +1,4 @@ +import 'package:example/default_users.dart'; import 'package:example/stream_version.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -10,88 +11,11 @@ import 'routes/routes.dart'; const kStreamApiKey = 'STREAM_API_KEY'; const kStreamUserId = 'STREAM_USER_ID'; const kStreamToken = 'STREAM_TOKEN'; -const kDefaultStreamApiKey = 'kv7mcsxr24p8'; class ChooseUserPage extends StatelessWidget { @override Widget build(BuildContext context) { - final users = { - 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoic2FsdmF0b3JlIn0.pgiJz7sIc7iP29BHKFwe3nLm5-OaR_1l2P-SlgiC9a8': - User( - id: 'salvatore', - extraData: { - 'name': 'Salvatore Giordano', - 'image': - 'https://avatars.githubusercontent.com/u/20601437?s=460&u=3f66c22a7483980624804054ae7f357cf102c784&v=4', - }, - ), - 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoic2FoaWwifQ.WnIUoB5gR2kcAsFhiDvkiD6zdHXZ-VSU2aQWWkhsvfo': - User( - id: 'sahil', - extraData: { - 'name': 'Sahil Kumar', - 'image': - 'https://avatars.githubusercontent.com/u/25670178?s=400&u=30ded3784d8d2310c5748f263fd5e6433c119aa1&v=4', - }, - ), - 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiYmVuIn0.nAz2sNFGQwY7rl2Og2z3TGHUsdpnN53tOsUglJFvLmg': - User( - id: 'ben', - extraData: { - 'name': 'Ben Golden', - 'image': 'https://avatars.githubusercontent.com/u/1581974?s=400&v=4', - }, - ), - 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoidGhpZXJyeSJ9.lEq6TrZtHzjoNtf7HHRufUPyGo_pa8vg4_XhEBp4ckY': - User( - id: 'thierry', - extraData: { - 'name': 'Thierry Schellenbach', - 'image': - 'https://avatars.githubusercontent.com/u/265409?s=400&u=2d0e3bb1820db992066196bff7b004f0eee8e28d&v=4', - }, - ), - 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoidG9tbWFzbyJ9.GLSI0ESshERMo2WjUpysD709NEtn1zmGimUN2an7g9o': - User( - id: 'tommaso', - extraData: { - 'name': 'Tommaso Barbugli', - 'image': 'https://avatars.githubusercontent.com/u/88735?s=400&v=4', - }, - ), - 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiZGV2ZW4ifQ.z3zI4PqJnNhc-1o-VKcmb6BnnQ0oxFNCRHwEulHqcWc': - User( - id: 'deven', - extraData: { - 'name': 'Deven Joshi', - 'image': - 'https://avatars.githubusercontent.com/u/26357843?s=400&u=0c61d890866e67bf69f58878be58915e9bfd39ee&v=4', - }, - ), - 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoibmVldmFzaCJ9.3EdHegTxibrz3A9cTiKmpEyawwcCVB8FXnoFzr4eKvw': - User( - id: 'neevash', - extraData: { - 'name': 'Neevash Ramdial', - 'image': - 'https://avatars.githubusercontent.com/u/25674767?s=400&u=1d7333baf7dd9d143db8bfcdb31a838b89cfff9c&v=4', - }, - ), - 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoicWF0ZXN0MSJ9.fnelU7HcP7QoEEsCGteNlF1fppofzNlrnpDQuIgeKCU': - User( - id: 'qatest1', - extraData: { - 'name': 'QA test 1', - }, - ), - 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoicWF0ZXN0MiJ9.vSCqAEbs2WVmMWsOsa7065Fsjq-rsTih6qsHPynl7XM': - User( - id: 'qatest2', - extraData: { - 'name': 'QA test 2', - }, - ), - }; + final users = defaultUsers; return Scaffold( backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index f0e9e65636..002200625a 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -11,15 +11,9 @@ dependencies: flutter: sdk: flutter stream_chat_flutter: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop - path: packages/stream_chat_flutter + path: ../../../stream-chat-flutter/packages/stream_chat_flutter stream_chat_persistence: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop - path: packages/stream_chat_persistence + path: ../../../stream-chat-flutter/packages/stream_chat_persistence flutter_local_notifications: ^2.0.2 flutter_svg: ^0.19.3 flutter_secure_storage: ^3.3.5 @@ -30,15 +24,9 @@ dependencies: dependency_overrides: stream_chat: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop - path: packages/stream_chat + path: ../../../stream-chat-flutter/packages/stream_chat stream_chat_flutter_core: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop - path: packages/stream_chat_flutter_core + path: ../../../stream-chat-flutter/packages/stream_chat_flutter_core dev_dependencies: flutter_launcher_icons: ^0.8.1 From dc7fbb6bc265859c64dec026dee95ff199ce30a7 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 30 Mar 2021 10:18:56 +0200 Subject: [PATCH 016/172] update files --- stream_chat_v1/lib/choose_user_page.dart | 2 +- stream_chat_v1/lib/main.dart | 1 + stream_chat_v1/pubspec.yaml | 20 ++++++++++++++++---- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/stream_chat_v1/lib/choose_user_page.dart b/stream_chat_v1/lib/choose_user_page.dart index 8cb0cad1cc..a6dd5e1ca4 100644 --- a/stream_chat_v1/lib/choose_user_page.dart +++ b/stream_chat_v1/lib/choose_user_page.dart @@ -1,4 +1,4 @@ -import 'package:example/default_users.dart'; +import 'package:example/app_config.dart'; import 'package:example/stream_version.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; diff --git a/stream_chat_v1/lib/main.dart b/stream_chat_v1/lib/main.dart index 2fb2cf8b1b..4e93955800 100644 --- a/stream_chat_v1/lib/main.dart +++ b/stream_chat_v1/lib/main.dart @@ -15,6 +15,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:stream_chat_persistence/stream_chat_persistence.dart'; import 'package:streaming_shared_preferences/streaming_shared_preferences.dart'; +import 'app_config.dart'; import 'notifications_service.dart'; import 'routes/app_routes.dart'; import 'routes/routes.dart'; diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index 002200625a..f0e9e65636 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -11,9 +11,15 @@ dependencies: flutter: sdk: flutter stream_chat_flutter: - path: ../../../stream-chat-flutter/packages/stream_chat_flutter + git: + url: https://github.com/GetStream/stream-chat-flutter.git + ref: develop + path: packages/stream_chat_flutter stream_chat_persistence: - path: ../../../stream-chat-flutter/packages/stream_chat_persistence + git: + url: https://github.com/GetStream/stream-chat-flutter.git + ref: develop + path: packages/stream_chat_persistence flutter_local_notifications: ^2.0.2 flutter_svg: ^0.19.3 flutter_secure_storage: ^3.3.5 @@ -24,9 +30,15 @@ dependencies: dependency_overrides: stream_chat: - path: ../../../stream-chat-flutter/packages/stream_chat + git: + url: https://github.com/GetStream/stream-chat-flutter.git + ref: develop + path: packages/stream_chat stream_chat_flutter_core: - path: ../../../stream-chat-flutter/packages/stream_chat_flutter_core + git: + url: https://github.com/GetStream/stream-chat-flutter.git + ref: develop + path: packages/stream_chat_flutter_core dev_dependencies: flutter_launcher_icons: ^0.8.1 From 7544058565530b159487f8683f4bc0c2eb568635 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 30 Mar 2021 10:26:46 +0200 Subject: [PATCH 017/172] fix build --- .../lib/channel_file_display_screen.dart | 180 ------------- .../lib/channel_media_display_screen.dart | 249 ------------------ stream_chat_v1/lib/chat_info_screen.dart | 2 - stream_chat_v1/lib/group_info_screen.dart | 2 - 4 files changed, 433 deletions(-) delete mode 100644 stream_chat_v1/lib/channel_file_display_screen.dart delete mode 100644 stream_chat_v1/lib/channel_media_display_screen.dart diff --git a/stream_chat_v1/lib/channel_file_display_screen.dart b/stream_chat_v1/lib/channel_file_display_screen.dart deleted file mode 100644 index 2779ba3422..0000000000 --- a/stream_chat_v1/lib/channel_file_display_screen.dart +++ /dev/null @@ -1,180 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:stream_chat_flutter/stream_chat_flutter.dart'; - -class ChannelFileDisplayScreen extends StatefulWidget { - /// The sorting used for the channels matching the filters. - /// Sorting is based on field and direction, multiple sorting options can be provided. - /// You can sort based on last_updated, last_message_at, updated_at, created_at or member_count. - /// Direction can be ascending or descending. - final List sortOptions; - - /// Pagination parameters - /// limit: the number of users to return (max is 30) - /// offset: the offset (max is 1000) - /// message_limit: how many messages should be included to each channel - final PaginationParams paginationParams; - - /// The builder used when the file list is empty. - final WidgetBuilder emptyBuilder; - - const ChannelFileDisplayScreen({ - this.sortOptions, - this.paginationParams, - this.emptyBuilder, - }); - - @override - _ChannelFileDisplayScreenState createState() => - _ChannelFileDisplayScreenState(); -} - -class _ChannelFileDisplayScreenState extends State { - @override - void initState() { - super.initState(); - final messageSearchBloc = MessageSearchBloc.of(context); - messageSearchBloc.search( - filter: { - 'cid': { - r'$in': [StreamChannel.of(context).channel.cid] - } - }, - messageFilter: { - 'attachments.type': { - r'$in': ['file'], - }, - }, - sort: widget.sortOptions, - pagination: widget.paginationParams, - ); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: StreamChatTheme.of(context).colorTheme.white, - appBar: AppBar( - brightness: Theme.of(context).brightness, - elevation: 1, - centerTitle: true, - title: Text( - 'Files', - style: TextStyle( - color: StreamChatTheme.of(context).colorTheme.black, - fontSize: 16.0), - ), - leading: Center( - child: InkWell( - onTap: () { - Navigator.of(context).pop(); - }, - child: Container( - width: 24.0, - height: 24.0, - child: StreamSvgIcon.left( - color: StreamChatTheme.of(context).colorTheme.black, - size: 24.0, - ), - ), - ), - ), - backgroundColor: StreamChatTheme.of(context).colorTheme.white, - ), - body: _buildMediaGrid(), - ); - } - - Widget _buildMediaGrid() { - final messageSearchBloc = MessageSearchBloc.of(context); - - return StreamBuilder>( - builder: (context, snapshot) { - if (snapshot.data == null) { - return Center( - child: const CircularProgressIndicator(), - ); - } - - if (snapshot.data.isEmpty) { - if (widget.emptyBuilder != null) { - return widget.emptyBuilder(context); - } - return Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - StreamSvgIcon.files( - size: 136.0, - color: StreamChatTheme.of(context).colorTheme.greyGainsboro, - ), - SizedBox(height: 16.0), - Text( - 'No Files', - style: TextStyle( - fontSize: 14.0, - color: StreamChatTheme.of(context).colorTheme.black, - ), - ), - SizedBox(height: 8.0), - Text( - 'Files sent in this chat will appear here', - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 14.0, - color: StreamChatTheme.of(context) - .colorTheme - .black - .withOpacity(0.5), - ), - ), - ], - ), - ); - } - - final media = {}; - - for (var item in snapshot.data) { - item.message.attachments.where((e) => e.type == 'file').forEach((e) { - media[e] = item.message; - }); - } - - return LazyLoadScrollView( - onEndOfPage: () => messageSearchBloc.loadMore( - filter: { - 'cid': { - r'$in': [StreamChannel.of(context).channel.cid] - } - }, - messageFilter: { - 'attachments.type': { - r'$in': ['file'] - }, - }, - sort: widget.sortOptions, - pagination: widget.paginationParams.copyWith( - offset: messageSearchBloc.messageResponses?.length ?? 0, - ), - ), - child: ListView.builder( - itemBuilder: (context, position) { - return Padding( - padding: const EdgeInsets.all(1.0), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: FileAttachment( - message: media.values.toList()[position], - attachment: media.keys.toList()[position], - ), - ), - ); - }, - itemCount: media.length, - ), - ); - }, - stream: messageSearchBloc.messagesStream, - ); - } -} diff --git a/stream_chat_v1/lib/channel_media_display_screen.dart b/stream_chat_v1/lib/channel_media_display_screen.dart deleted file mode 100644 index e09b122102..0000000000 --- a/stream_chat_v1/lib/channel_media_display_screen.dart +++ /dev/null @@ -1,249 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -import 'package:video_player/video_player.dart'; - -class ChannelMediaDisplayScreen extends StatefulWidget { - /// The sorting used for the channels matching the filters. - /// Sorting is based on field and direction, multiple sorting options can be provided. - /// You can sort based on last_updated, last_message_at, updated_at, created_at or member_count. - /// Direction can be ascending or descending. - final List sortOptions; - - /// Pagination parameters - /// limit: the number of users to return (max is 30) - /// offset: the offset (max is 1000) - /// message_limit: how many messages should be included to each channel - final PaginationParams paginationParams; - - /// The builder used when the file list is empty. - final WidgetBuilder emptyBuilder; - - final ShowMessageCallback onShowMessage; - - const ChannelMediaDisplayScreen({ - this.sortOptions, - this.paginationParams, - this.emptyBuilder, - this.onShowMessage, - }); - - @override - _ChannelMediaDisplayScreenState createState() => - _ChannelMediaDisplayScreenState(); -} - -class _ChannelMediaDisplayScreenState extends State { - Map controllerCache = {}; - - @override - void initState() { - super.initState(); - final messageSearchBloc = MessageSearchBloc.of(context); - messageSearchBloc.search( - filter: { - 'cid': { - r'$in': [StreamChannel.of(context).channel.cid], - } - }, - messageFilter: { - 'attachments.type': { - r'$in': ['image', 'video'] - }, - }, - sort: widget.sortOptions, - pagination: widget.paginationParams, - ); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: StreamChatTheme.of(context).colorTheme.white, - appBar: AppBar( - brightness: Theme.of(context).brightness, - elevation: 1, - centerTitle: true, - title: Text( - 'Photos & Videos', - style: TextStyle( - color: StreamChatTheme.of(context).colorTheme.black, - fontSize: 16.0, - ), - ), - leading: Center( - child: InkWell( - onTap: () { - Navigator.of(context).pop(); - }, - child: Container( - width: 24.0, - height: 24.0, - child: StreamSvgIcon.left( - color: StreamChatTheme.of(context).colorTheme.black, - size: 24.0, - ), - ), - ), - ), - backgroundColor: StreamChatTheme.of(context).colorTheme.white, - ), - body: _buildMediaGrid(), - ); - } - - Widget _buildMediaGrid() { - final messageSearchBloc = MessageSearchBloc.of(context); - - return StreamBuilder>( - builder: (context, snapshot) { - if (snapshot.data == null) { - return Center( - child: const CircularProgressIndicator(), - ); - } - - if (snapshot.data.isEmpty) { - if (widget.emptyBuilder != null) { - return widget.emptyBuilder(context); - } - return Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - StreamSvgIcon.pictures( - size: 136.0, - color: StreamChatTheme.of(context).colorTheme.greyGainsboro, - ), - SizedBox(height: 16.0), - Text( - 'No Media', - style: TextStyle( - fontSize: 14.0, - color: StreamChatTheme.of(context).colorTheme.black, - ), - ), - SizedBox(height: 8.0), - Text( - 'Photos or video sent in this chat will \nappear here', - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 14.0, - color: StreamChatTheme.of(context) - .colorTheme - .black - .withOpacity(0.5), - ), - ), - ], - ), - ); - } - - final media = <_AssetPackage>[]; - - for (var item in snapshot.data) { - item.message.attachments - .where((e) => - (e.type == 'image' || e.type == 'video') && - e.ogScrapeUrl == null) - .forEach((e) { - VideoPlayerController controller; - if (e.type == 'video') { - var cachedController = controllerCache[e.assetUrl]; - - if (cachedController == null) { - controller = VideoPlayerController.network(e.assetUrl); - controller.initialize(); - controllerCache[e.assetUrl] = controller; - } else { - controller = cachedController; - } - } - media.add(_AssetPackage(e, item.message, controller)); - }); - } - - return LazyLoadScrollView( - onEndOfPage: () => messageSearchBloc.loadMore( - filter: { - 'cid': { - r'$in': [StreamChannel.of(context).channel.cid] - } - }, - messageFilter: { - 'attachments.type': { - r'$in': ['image', 'video'] - }, - }, - sort: widget.sortOptions, - pagination: widget.paginationParams.copyWith( - offset: messageSearchBloc.messageResponses?.length ?? 0, - ), - ), - child: GridView.builder( - gridDelegate: - SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3), - itemBuilder: (context, position) { - var channel = StreamChannel.of(context).channel; - return Padding( - padding: const EdgeInsets.all(1.0), - child: InkWell( - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => StreamChannel( - channel: channel, - child: FullScreenMedia( - mediaAttachments: - media.map((e) => e.attachment).toList(), - startIndex: position, - message: media[position].message, - sentAt: media[position].message.createdAt, - userName: media[position].message.user.name, - onShowMessage: widget.onShowMessage, - ), - ), - ), - ); - }, - child: media[position].attachment.type == 'image' - ? IgnorePointer( - child: ImageAttachment( - attachment: media[position].attachment, - message: media[position].message, - showTitle: false, - size: Size( - MediaQuery.of(context).size.width * 0.8, - MediaQuery.of(context).size.height * 0.3, - ), - ), - ) - : VideoPlayer(media[position].videoPlayer), - ), - ); - }, - itemCount: media.length, - ), - ); - }, - stream: messageSearchBloc.messagesStream, - ); - } - - @override - void dispose() { - super.dispose(); - for (var c in controllerCache.values) { - c.dispose(); - } - } -} - -class _AssetPackage { - Attachment attachment; - Message message; - VideoPlayerController videoPlayer; - - _AssetPackage(this.attachment, this.message, this.videoPlayer); -} diff --git a/stream_chat_v1/lib/chat_info_screen.dart b/stream_chat_v1/lib/chat_info_screen.dart index 1668132d2e..5c8441ed05 100644 --- a/stream_chat_v1/lib/chat_info_screen.dart +++ b/stream_chat_v1/lib/chat_info_screen.dart @@ -1,5 +1,3 @@ -import 'package:example/channel_file_display_screen.dart'; -import 'package:example/channel_media_display_screen.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:jiffy/jiffy.dart'; diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/group_info_screen.dart index cfcdea63c3..b76cc9b9d8 100644 --- a/stream_chat_v1/lib/group_info_screen.dart +++ b/stream_chat_v1/lib/group_info_screen.dart @@ -1,7 +1,5 @@ import 'dart:async'; -import 'package:example/channel_file_display_screen.dart'; -import 'package:example/channel_media_display_screen.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:jiffy/jiffy.dart'; From 5e454be61b750ba5f245ed45c8356d8cf5db1eac Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 30 Mar 2021 10:37:07 +0200 Subject: [PATCH 018/172] bump version --- stream_chat_v1/pubspec.yaml | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index f0e9e65636..4bc3ee2303 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -1,7 +1,7 @@ name: example description: A new Flutter project. publish_to: 'none' -version: 1.5.0 +version: 1.5.1 environment: sdk: ">=2.2.2 <3.0.0" @@ -10,16 +10,8 @@ dependencies: flutter_app_badger: ^1.1.2 flutter: sdk: flutter - stream_chat_flutter: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop - path: packages/stream_chat_flutter - stream_chat_persistence: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop - path: packages/stream_chat_persistence + stream_chat_flutter: ^1.5.0 + stream_chat_persistence: ^1.5.0 flutter_local_notifications: ^2.0.2 flutter_svg: ^0.19.3 flutter_secure_storage: ^3.3.5 @@ -28,18 +20,6 @@ dependencies: streaming_shared_preferences: ^1.0.2 lottie: ^0.7.0+1 -dependency_overrides: - stream_chat: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop - path: packages/stream_chat - stream_chat_flutter_core: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop - path: packages/stream_chat_flutter_core - dev_dependencies: flutter_launcher_icons: ^0.8.1 test: any From 9b16040ca4b2874e343539e93ae855868572bdc2 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 30 Mar 2021 11:27:05 +0200 Subject: [PATCH 019/172] update action --- stream_chat_v1/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index 4bc3ee2303..a77b679153 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -1,7 +1,7 @@ name: example description: A new Flutter project. publish_to: 'none' -version: 1.5.1 +version: 1.5.2 environment: sdk: ">=2.2.2 <3.0.0" From 479bd20f0706d83286d5e65dc4489ab1dc15a8e6 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 30 Mar 2021 12:04:58 +0200 Subject: [PATCH 020/172] update fastlane --- stream_chat_v1/ios/fastlane/Fastfile | 2 +- stream_chat_v1/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/stream_chat_v1/ios/fastlane/Fastfile b/stream_chat_v1/ios/fastlane/Fastfile index 4ddcc995ff..91aacbf548 100644 --- a/stream_chat_v1/ios/fastlane/Fastfile +++ b/stream_chat_v1/ios/fastlane/Fastfile @@ -1,4 +1,4 @@ -fastlane_version "2.162.0" +fastlane_version "2.179.0" default_platform :ios before_all do diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index a77b679153..5d47cca84a 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -1,7 +1,7 @@ name: example description: A new Flutter project. publish_to: 'none' -version: 1.5.2 +version: 1.5.3 environment: sdk: ">=2.2.2 <3.0.0" From c2bc7620ff5086c92aa6ca5bd94ad7d307ca2a59 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 30 Mar 2021 12:15:42 +0200 Subject: [PATCH 021/172] update fastlane --- stream_chat_v1/ios/Gemfile.lock | 88 +++++++++++++++++++++------------ 1 file changed, 56 insertions(+), 32 deletions(-) diff --git a/stream_chat_v1/ios/Gemfile.lock b/stream_chat_v1/ios/Gemfile.lock index dc0ee04fca..d4fa45b334 100644 --- a/stream_chat_v1/ios/Gemfile.lock +++ b/stream_chat_v1/ios/Gemfile.lock @@ -1,27 +1,28 @@ GEM remote: https://rubygems.org/ specs: - CFPropertyList (3.0.2) + CFPropertyList (3.0.3) addressable (2.7.0) public_suffix (>= 2.0.2, < 5.0) + artifactory (3.0.15) atomos (0.1.3) - aws-eventstream (1.1.0) - aws-partitions (1.380.0) - aws-sdk-core (3.109.1) + aws-eventstream (1.1.1) + aws-partitions (1.437.0) + aws-sdk-core (3.113.1) aws-eventstream (~> 1, >= 1.0.2) aws-partitions (~> 1, >= 1.239.0) aws-sigv4 (~> 1.1) jmespath (~> 1.0) - aws-sdk-kms (1.39.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-kms (1.43.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.83.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-s3 (1.93.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.1) - aws-sigv4 (1.2.2) + aws-sigv4 (1.2.3) aws-eventstream (~> 1, >= 1.0.2) - babosa (1.0.3) + babosa (1.0.4) claide (1.0.3) colored (1.2) colored2 (3.1.2) @@ -29,24 +30,28 @@ GEM highline (~> 1.7.2) declarative (0.0.20) declarative-option (0.1.0) - digest-crc (0.6.1) - rake (~> 13.0) + digest-crc (0.6.3) + rake (>= 12.0.0, < 14.0.0) domain_name (0.5.20190701) unf (>= 0.0.5, < 1.0.0) dotenv (2.7.6) - emoji_regex (3.0.0) - excon (0.76.0) - faraday (1.0.1) + emoji_regex (3.2.2) + excon (0.79.0) + faraday (1.3.0) + faraday-net_http (~> 1.0) multipart-post (>= 1.2, < 3) + ruby2_keywords faraday-cookie_jar (0.0.7) faraday (>= 0.8.0) http-cookie (~> 1.0.0) + faraday-net_http (1.0.1) faraday_middleware (1.0.0) faraday (~> 1.0) - fastimage (2.2.0) - fastlane (2.162.0) + fastimage (2.2.3) + fastlane (2.179.0) CFPropertyList (>= 2.3, < 4.0.0) addressable (>= 2.3, < 3.0.0) + artifactory (~> 3.0) aws-sdk-s3 (~> 1.0) babosa (>= 1.0.3, < 2.0.0) bundler (>= 1.12.0, < 3.0.0) @@ -67,6 +72,7 @@ GEM jwt (>= 2.1.0, < 3) mini_magick (>= 4.9.4, < 5.0.0) multipart-post (~> 2.0.0) + naturally (~> 2.2) plist (>= 3.1.0, < 4.0.0) rubyzip (>= 2.0.0, < 3.0.0) security (= 0.1.3) @@ -90,20 +96,35 @@ GEM representable (~> 3.0) retriable (>= 2.0, < 4.0) signet (~> 0.12) - google-cloud-core (1.5.0) + google-apis-core (0.3.0) + addressable (~> 2.5, >= 2.5.1) + googleauth (~> 0.14) + httpclient (>= 2.8.1, < 3.0) + mini_mime (~> 1.0) + representable (~> 3.0) + retriable (>= 2.0, < 4.0) + rexml + signet (~> 0.14) + webrick + google-apis-iamcredentials_v1 (0.2.0) + google-apis-core (~> 0.1) + google-apis-storage_v1 (0.3.0) + google-apis-core (~> 0.1) + google-cloud-core (1.6.0) google-cloud-env (~> 1.0) google-cloud-errors (~> 1.0) - google-cloud-env (1.3.3) + google-cloud-env (1.5.0) faraday (>= 0.17.3, < 2.0) - google-cloud-errors (1.0.1) - google-cloud-storage (1.29.1) + google-cloud-errors (1.1.0) + google-cloud-storage (1.31.0) addressable (~> 2.5) digest-crc (~> 0.4) - google-api-client (~> 0.33) + google-apis-iamcredentials_v1 (~> 0.1) + google-apis-storage_v1 (~> 0.1) google-cloud-core (~> 1.2) googleauth (~> 0.9) mini_mime (~> 1.0) - googleauth (0.13.1) + googleauth (0.16.0) faraday (>= 0.17.3, < 2.0) jwt (>= 1.4, < 3.0) memoist (~> 0.16) @@ -115,28 +136,30 @@ GEM domain_name (~> 0.5) httpclient (2.8.3) jmespath (1.4.0) - json (2.3.1) + json (2.5.1) jwt (2.2.2) memoist (0.16.2) - mini_magick (4.10.1) - mini_mime (1.0.2) + mini_magick (4.11.0) + mini_mime (1.0.3) multi_json (1.15.0) multipart-post (2.0.0) nanaimo (0.3.0) - naturally (2.2.0) + naturally (2.2.1) os (1.1.1) - plist (3.5.0) + plist (3.6.0) public_suffix (4.0.6) - rake (13.0.1) + rake (13.0.3) representable (3.0.4) declarative (< 0.1.0) declarative-option (< 0.2.0) uber (< 0.2.0) retriable (3.1.2) + rexml (3.2.4) rouge (2.0.7) + ruby2_keywords (0.0.4) rubyzip (2.3.0) security (0.1.3) - signet (0.14.0) + signet (0.15.0) addressable (~> 2.3) faraday (>= 0.17.3, < 2.0) jwt (>= 1.5, < 3.0) @@ -157,8 +180,9 @@ GEM unf_ext unf_ext (0.0.7.7) unicode-display_width (1.7.0) + webrick (1.7.0) word_wrap (1.0.0) - xcodeproj (1.18.0) + xcodeproj (1.19.0) CFPropertyList (>= 2.3.3, < 4.0) atomos (~> 0.1.3) claide (>= 1.0.2, < 2.0) @@ -166,7 +190,7 @@ GEM nanaimo (~> 0.3.0) xcpretty (0.3.0) rouge (~> 2.0.7) - xcpretty-travis-formatter (1.0.0) + xcpretty-travis-formatter (1.0.1) xcpretty (~> 0.2, >= 0.0.7) PLATFORMS From 4b8e8e241979c39e93a58b34dc76618f36a58af7 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 6 Apr 2021 16:06:16 +0200 Subject: [PATCH 022/172] bump version --- stream_chat_v1/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index f0e9e65636..a45698addb 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -1,7 +1,7 @@ name: example description: A new Flutter project. publish_to: 'none' -version: 1.5.0 +version: 1.5.4 environment: sdk: ">=2.2.2 <3.0.0" From cc09b57a1046037293242edac6a88a7664722e8d Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 8 Apr 2021 16:54:50 +0200 Subject: [PATCH 023/172] add channel file and media display screens --- .../lib/channel_file_display_screen.dart | 180 +++++++++++++ .../lib/channel_media_display_screen.dart | 249 ++++++++++++++++++ stream_chat_v1/lib/chat_info_screen.dart | 2 + stream_chat_v1/lib/group_info_screen.dart | 2 + 4 files changed, 433 insertions(+) create mode 100644 stream_chat_v1/lib/channel_file_display_screen.dart create mode 100644 stream_chat_v1/lib/channel_media_display_screen.dart diff --git a/stream_chat_v1/lib/channel_file_display_screen.dart b/stream_chat_v1/lib/channel_file_display_screen.dart new file mode 100644 index 0000000000..a3e1c6703a --- /dev/null +++ b/stream_chat_v1/lib/channel_file_display_screen.dart @@ -0,0 +1,180 @@ +import 'package:flutter/material.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; + +class ChannelFileDisplayScreen extends StatefulWidget { + /// The sorting used for the channels matching the filters. + /// Sorting is based on field and direction, multiple sorting options can be provided. + /// You can sort based on last_updated, last_message_at, updated_at, created_at or member_count. + /// Direction can be ascending or descending. + final List sortOptions; + + /// Pagination parameters + /// limit: the number of users to return (max is 30) + /// offset: the offset (max is 1000) + /// message_limit: how many messages should be included to each channel + final PaginationParams paginationParams; + + /// The builder used when the file list is empty. + final WidgetBuilder emptyBuilder; + + const ChannelFileDisplayScreen({ + this.sortOptions, + this.paginationParams, + this.emptyBuilder, + }); + + @override + _ChannelFileDisplayScreenState createState() => + _ChannelFileDisplayScreenState(); +} + +class _ChannelFileDisplayScreenState extends State { + @override + void initState() { + super.initState(); + final messageSearchBloc = MessageSearchBloc.of(context); + messageSearchBloc.search( + filter: { + 'cid': { + r'$in': [StreamChannel.of(context).channel.cid] + } + }, + messageFilter: { + 'attachments.type': { + r'$in': ['file'], + }, + }, + sort: widget.sortOptions, + pagination: widget.paginationParams, + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: StreamChatTheme.of(context).colorTheme.white, + appBar: AppBar( + brightness: Theme.of(context).brightness, + elevation: 1, + centerTitle: true, + title: Text( + 'Files', + style: TextStyle( + color: StreamChatTheme.of(context).colorTheme.black, + fontSize: 16.0), + ), + leading: Center( + child: InkWell( + onTap: () { + Navigator.of(context).pop(); + }, + child: Container( + width: 24.0, + height: 24.0, + child: StreamSvgIcon.left( + color: StreamChatTheme.of(context).colorTheme.black, + size: 24.0, + ), + ), + ), + ), + backgroundColor: StreamChatTheme.of(context).colorTheme.white, + ), + body: _buildMediaGrid(), + ); + } + + Widget _buildMediaGrid() { + final messageSearchBloc = MessageSearchBloc.of(context); + + return StreamBuilder>( + builder: (context, snapshot) { + if (snapshot.data == null) { + return Center( + child: const CircularProgressIndicator(), + ); + } + + if (snapshot.data.isEmpty) { + if (widget.emptyBuilder != null) { + return widget.emptyBuilder(context); + } + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + StreamSvgIcon.files( + size: 136.0, + color: StreamChatTheme.of(context).colorTheme.greyGainsboro, + ), + SizedBox(height: 16.0), + Text( + 'No Files', + style: TextStyle( + fontSize: 14.0, + color: StreamChatTheme.of(context).colorTheme.black, + ), + ), + SizedBox(height: 8.0), + Text( + 'Files sent in this chat will appear here', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 14.0, + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(0.5), + ), + ), + ], + ), + ); + } + + final media = {}; + + for (var item in snapshot.data) { + item.message.attachments.where((e) => e.type == 'file').forEach((e) { + media[e] = item.message; + }); + } + + return LazyLoadScrollView( + onEndOfPage: () => messageSearchBloc.search( + filter: { + 'cid': { + r'$in': [StreamChannel.of(context).channel.cid] + } + }, + messageFilter: { + 'attachments.type': { + r'$in': ['file'] + }, + }, + sort: widget.sortOptions, + pagination: widget.paginationParams.copyWith( + offset: messageSearchBloc.messageResponses?.length ?? 0, + ), + ), + child: ListView.builder( + itemBuilder: (context, position) { + return Padding( + padding: const EdgeInsets.all(1.0), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: FileAttachment( + message: media.values.toList()[position], + attachment: media.keys.toList()[position], + ), + ), + ); + }, + itemCount: media.length, + ), + ); + }, + stream: messageSearchBloc.messagesStream, + ); + } +} diff --git a/stream_chat_v1/lib/channel_media_display_screen.dart b/stream_chat_v1/lib/channel_media_display_screen.dart new file mode 100644 index 0000000000..a0ed072e07 --- /dev/null +++ b/stream_chat_v1/lib/channel_media_display_screen.dart @@ -0,0 +1,249 @@ +import 'package:flutter/material.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; +import 'package:video_player/video_player.dart'; + +class ChannelMediaDisplayScreen extends StatefulWidget { + /// The sorting used for the channels matching the filters. + /// Sorting is based on field and direction, multiple sorting options can be provided. + /// You can sort based on last_updated, last_message_at, updated_at, created_at or member_count. + /// Direction can be ascending or descending. + final List sortOptions; + + /// Pagination parameters + /// limit: the number of users to return (max is 30) + /// offset: the offset (max is 1000) + /// message_limit: how many messages should be included to each channel + final PaginationParams paginationParams; + + /// The builder used when the file list is empty. + final WidgetBuilder emptyBuilder; + + final ShowMessageCallback onShowMessage; + + const ChannelMediaDisplayScreen({ + this.sortOptions, + this.paginationParams, + this.emptyBuilder, + this.onShowMessage, + }); + + @override + _ChannelMediaDisplayScreenState createState() => + _ChannelMediaDisplayScreenState(); +} + +class _ChannelMediaDisplayScreenState extends State { + Map controllerCache = {}; + + @override + void initState() { + super.initState(); + final messageSearchBloc = MessageSearchBloc.of(context); + messageSearchBloc.search( + filter: { + 'cid': { + r'$in': [StreamChannel.of(context).channel.cid], + } + }, + messageFilter: { + 'attachments.type': { + r'$in': ['image', 'video'] + }, + }, + sort: widget.sortOptions, + pagination: widget.paginationParams, + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: StreamChatTheme.of(context).colorTheme.white, + appBar: AppBar( + brightness: Theme.of(context).brightness, + elevation: 1, + centerTitle: true, + title: Text( + 'Photos & Videos', + style: TextStyle( + color: StreamChatTheme.of(context).colorTheme.black, + fontSize: 16.0, + ), + ), + leading: Center( + child: InkWell( + onTap: () { + Navigator.of(context).pop(); + }, + child: Container( + width: 24.0, + height: 24.0, + child: StreamSvgIcon.left( + color: StreamChatTheme.of(context).colorTheme.black, + size: 24.0, + ), + ), + ), + ), + backgroundColor: StreamChatTheme.of(context).colorTheme.white, + ), + body: _buildMediaGrid(), + ); + } + + Widget _buildMediaGrid() { + final messageSearchBloc = MessageSearchBloc.of(context); + + return StreamBuilder>( + builder: (context, snapshot) { + if (snapshot.data == null) { + return Center( + child: const CircularProgressIndicator(), + ); + } + + if (snapshot.data.isEmpty) { + if (widget.emptyBuilder != null) { + return widget.emptyBuilder(context); + } + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + StreamSvgIcon.pictures( + size: 136.0, + color: StreamChatTheme.of(context).colorTheme.greyGainsboro, + ), + SizedBox(height: 16.0), + Text( + 'No Media', + style: TextStyle( + fontSize: 14.0, + color: StreamChatTheme.of(context).colorTheme.black, + ), + ), + SizedBox(height: 8.0), + Text( + 'Photos or video sent in this chat will \nappear here', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 14.0, + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(0.5), + ), + ), + ], + ), + ); + } + + final media = <_AssetPackage>[]; + + for (var item in snapshot.data) { + item.message.attachments + .where((e) => + (e.type == 'image' || e.type == 'video') && + e.ogScrapeUrl == null) + .forEach((e) { + VideoPlayerController controller; + if (e.type == 'video') { + var cachedController = controllerCache[e.assetUrl]; + + if (cachedController == null) { + controller = VideoPlayerController.network(e.assetUrl); + controller.initialize(); + controllerCache[e.assetUrl] = controller; + } else { + controller = cachedController; + } + } + media.add(_AssetPackage(e, item.message, controller)); + }); + } + + return LazyLoadScrollView( + onEndOfPage: () => messageSearchBloc.search( + filter: { + 'cid': { + r'$in': [StreamChannel.of(context).channel.cid] + } + }, + messageFilter: { + 'attachments.type': { + r'$in': ['image', 'video'] + }, + }, + sort: widget.sortOptions, + pagination: widget.paginationParams.copyWith( + offset: messageSearchBloc.messageResponses?.length ?? 0, + ), + ), + child: GridView.builder( + gridDelegate: + SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3), + itemBuilder: (context, position) { + var channel = StreamChannel.of(context).channel; + return Padding( + padding: const EdgeInsets.all(1.0), + child: InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => StreamChannel( + channel: channel, + child: FullScreenMedia( + mediaAttachments: + media.map((e) => e.attachment).toList(), + startIndex: position, + message: media[position].message, + sentAt: media[position].message.createdAt, + userName: media[position].message.user.name, + onShowMessage: widget.onShowMessage, + ), + ), + ), + ); + }, + child: media[position].attachment.type == 'image' + ? IgnorePointer( + child: ImageAttachment( + attachment: media[position].attachment, + message: media[position].message, + showTitle: false, + size: Size( + MediaQuery.of(context).size.width * 0.8, + MediaQuery.of(context).size.height * 0.3, + ), + ), + ) + : VideoPlayer(media[position].videoPlayer), + ), + ); + }, + itemCount: media.length, + ), + ); + }, + stream: messageSearchBloc.messagesStream, + ); + } + + @override + void dispose() { + super.dispose(); + for (var c in controllerCache.values) { + c.dispose(); + } + } +} + +class _AssetPackage { + Attachment attachment; + Message message; + VideoPlayerController videoPlayer; + + _AssetPackage(this.attachment, this.message, this.videoPlayer); +} diff --git a/stream_chat_v1/lib/chat_info_screen.dart b/stream_chat_v1/lib/chat_info_screen.dart index 5c8441ed05..38fbb707ef 100644 --- a/stream_chat_v1/lib/chat_info_screen.dart +++ b/stream_chat_v1/lib/chat_info_screen.dart @@ -3,6 +3,8 @@ import 'package:flutter/material.dart'; import 'package:jiffy/jiffy.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; +import 'channel_file_display_screen.dart'; +import 'channel_media_display_screen.dart'; import 'main.dart'; import 'routes/routes.dart'; diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/group_info_screen.dart index b76cc9b9d8..efe1808c01 100644 --- a/stream_chat_v1/lib/group_info_screen.dart +++ b/stream_chat_v1/lib/group_info_screen.dart @@ -7,6 +7,8 @@ import 'package:stream_chat_flutter/src/option_list_tile.dart'; import 'package:stream_chat_flutter/src/stream_svg_icon.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; +import 'channel_file_display_screen.dart'; +import 'channel_media_display_screen.dart'; import 'chat_info_screen.dart'; import 'main.dart'; import 'routes/routes.dart'; From ffb0724d1724b4f7a0781e3915206ef42db03cd3 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 3 May 2021 11:05:22 +0200 Subject: [PATCH 024/172] update fastlane configs --- stream_chat_v1/ios/fastlane/Fastfile | 2 +- .../fastlane/beta_gym_export_options.plist | 2 +- stream_chat_v1/ios/fastlane/report.xml | 22 +++++-------------- 3 files changed, 7 insertions(+), 19 deletions(-) diff --git a/stream_chat_v1/ios/fastlane/Fastfile b/stream_chat_v1/ios/fastlane/Fastfile index 4ddcc995ff..98d4536d4d 100644 --- a/stream_chat_v1/ios/fastlane/Fastfile +++ b/stream_chat_v1/ios/fastlane/Fastfile @@ -62,7 +62,7 @@ platform :ios do settings_to_override = { :BUNDLE_IDENTIFIER => "io.getstream.flutter", - :PROVISIONING_PROFILE_SPECIFIER => "match AppStore io.getstream.flutter" + :PROVISIONING_PROFILE_SPECIFIER => "match AppStore io.getstream.flutter 1620032657" } gym( diff --git a/stream_chat_v1/ios/fastlane/beta_gym_export_options.plist b/stream_chat_v1/ios/fastlane/beta_gym_export_options.plist index e88559ac2a..372152802c 100644 --- a/stream_chat_v1/ios/fastlane/beta_gym_export_options.plist +++ b/stream_chat_v1/ios/fastlane/beta_gym_export_options.plist @@ -7,7 +7,7 @@ provisioningProfiles io.getstream.flutter - match AdHoc io.getstream.flutter + match AdHoc io.getstream.flutter 1620032657 \ No newline at end of file diff --git a/stream_chat_v1/ios/fastlane/report.xml b/stream_chat_v1/ios/fastlane/report.xml index 42d2518e8a..268d605f5a 100644 --- a/stream_chat_v1/ios/fastlane/report.xml +++ b/stream_chat_v1/ios/fastlane/report.xml @@ -5,39 +5,27 @@ - + - + - + - + - - - - - - - - - - - - - + From fe91b20d5da6a8dfb98014f1619c0a11f89dab0d Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 3 May 2021 11:39:38 +0200 Subject: [PATCH 025/172] fix build --- stream_chat_v1/ios/Gemfile.lock | 2 +- .../ios/Runner.xcodeproj/project.pbxproj | 6 +++--- stream_chat_v1/ios/fastlane/report.xml | 20 ++++++++++++++----- stream_chat_v1/pubspec.yaml | 2 +- 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/stream_chat_v1/ios/Gemfile.lock b/stream_chat_v1/ios/Gemfile.lock index dc0ee04fca..2fb075724b 100644 --- a/stream_chat_v1/ios/Gemfile.lock +++ b/stream_chat_v1/ios/Gemfile.lock @@ -80,7 +80,7 @@ GEM xcodeproj (>= 1.13.0, < 2.0.0) xcpretty (~> 0.3.0) xcpretty-travis-formatter (>= 0.0.3) - fastlane-plugin-firebase_app_distribution (0.2.3) + fastlane-plugin-firebase_app_distribution (0.2.7) gh_inspector (1.1.3) google-api-client (0.38.0) addressable (~> 2.5, >= 2.5.1) diff --git a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj index 8cd3ed03df..ccb925f581 100644 --- a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj +++ b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj @@ -447,7 +447,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter"; + PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter 1620032657"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; @@ -586,7 +586,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter"; + PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter 1620032657"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -620,7 +620,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter"; + PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter 1620032657"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; diff --git a/stream_chat_v1/ios/fastlane/report.xml b/stream_chat_v1/ios/fastlane/report.xml index 268d605f5a..55d4f11d97 100644 --- a/stream_chat_v1/ios/fastlane/report.xml +++ b/stream_chat_v1/ios/fastlane/report.xml @@ -5,27 +5,37 @@ - + - + - + - + - + + + + + + + + + + + diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index a45698addb..35af177fbb 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -1,7 +1,7 @@ name: example description: A new Flutter project. publish_to: 'none' -version: 1.5.4 +version: 1.5.4+1 environment: sdk: ">=2.2.2 <3.0.0" From 4636c6fa61a395104d57261ad048091de0fd44bf Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Wed, 12 May 2021 16:54:44 +0200 Subject: [PATCH 026/172] upgrade dependencies --- .../lib/channel_file_display_screen.dart | 36 ++++++++-------- .../lib/channel_media_display_screen.dart | 41 +++++++++---------- stream_chat_v1/lib/chat_info_screen.dart | 27 ++++++------ stream_chat_v1/lib/group_info_screen.dart | 27 +++++++----- stream_chat_v1/lib/main.dart | 40 ++++++++---------- stream_chat_v1/lib/new_chat_screen.dart | 23 +++++------ stream_chat_v1/lib/new_group_chat_screen.dart | 12 ++---- stream_chat_v1/lib/routes/app_routes.dart | 9 ++-- stream_chat_v1/pubspec.yaml | 18 ++++---- stream_chat_v1/test/widget_test.dart | 30 -------------- 10 files changed, 112 insertions(+), 151 deletions(-) delete mode 100644 stream_chat_v1/test/widget_test.dart diff --git a/stream_chat_v1/lib/channel_file_display_screen.dart b/stream_chat_v1/lib/channel_file_display_screen.dart index a3e1c6703a..cbd5264c03 100644 --- a/stream_chat_v1/lib/channel_file_display_screen.dart +++ b/stream_chat_v1/lib/channel_file_display_screen.dart @@ -34,16 +34,14 @@ class _ChannelFileDisplayScreenState extends State { super.initState(); final messageSearchBloc = MessageSearchBloc.of(context); messageSearchBloc.search( - filter: { - 'cid': { - r'$in': [StreamChannel.of(context).channel.cid] - } - }, - messageFilter: { - 'attachments.type': { - r'$in': ['file'], - }, - }, + filter: Filter.in_( + 'cid', + [StreamChannel.of(context).channel.cid], + ), + messageFilter: Filter.in_( + 'attachments.type', + ['file'], + ), sort: widget.sortOptions, pagination: widget.paginationParams, ); @@ -142,16 +140,14 @@ class _ChannelFileDisplayScreenState extends State { return LazyLoadScrollView( onEndOfPage: () => messageSearchBloc.search( - filter: { - 'cid': { - r'$in': [StreamChannel.of(context).channel.cid] - } - }, - messageFilter: { - 'attachments.type': { - r'$in': ['file'] - }, - }, + filter: Filter.in_( + 'cid', + [StreamChannel.of(context).channel.cid], + ), + messageFilter: Filter.in_( + 'attachments.type', + ['file'], + ), sort: widget.sortOptions, pagination: widget.paginationParams.copyWith( offset: messageSearchBloc.messageResponses?.length ?? 0, diff --git a/stream_chat_v1/lib/channel_media_display_screen.dart b/stream_chat_v1/lib/channel_media_display_screen.dart index a0ed072e07..2bf0fb1107 100644 --- a/stream_chat_v1/lib/channel_media_display_screen.dart +++ b/stream_chat_v1/lib/channel_media_display_screen.dart @@ -20,7 +20,10 @@ class ChannelMediaDisplayScreen extends StatefulWidget { final ShowMessageCallback onShowMessage; + final MessageTheme messageTheme; + const ChannelMediaDisplayScreen({ + @required this.messageTheme, this.sortOptions, this.paginationParams, this.emptyBuilder, @@ -40,16 +43,14 @@ class _ChannelMediaDisplayScreenState extends State { super.initState(); final messageSearchBloc = MessageSearchBloc.of(context); messageSearchBloc.search( - filter: { - 'cid': { - r'$in': [StreamChannel.of(context).channel.cid], - } - }, - messageFilter: { - 'attachments.type': { - r'$in': ['image', 'video'] - }, - }, + filter: Filter.in_( + 'cid', + [StreamChannel.of(context).channel.cid], + ), + messageFilter: Filter.in_( + 'attachments.type', + ['image', 'video'], + ), sort: widget.sortOptions, pagination: widget.paginationParams, ); @@ -165,16 +166,14 @@ class _ChannelMediaDisplayScreenState extends State { return LazyLoadScrollView( onEndOfPage: () => messageSearchBloc.search( - filter: { - 'cid': { - r'$in': [StreamChannel.of(context).channel.cid] - } - }, - messageFilter: { - 'attachments.type': { - r'$in': ['image', 'video'] - }, - }, + filter: Filter.in_( + 'cid', + [StreamChannel.of(context).channel.cid], + ), + messageFilter: Filter.in_( + 'attachments.type', + ['image', 'video'], + ), sort: widget.sortOptions, pagination: widget.paginationParams.copyWith( offset: messageSearchBloc.messageResponses?.length ?? 0, @@ -199,7 +198,6 @@ class _ChannelMediaDisplayScreenState extends State { media.map((e) => e.attachment).toList(), startIndex: position, message: media[position].message, - sentAt: media[position].message.createdAt, userName: media[position].message.user.name, onShowMessage: widget.onShowMessage, ), @@ -217,6 +215,7 @@ class _ChannelMediaDisplayScreenState extends State { MediaQuery.of(context).size.width * 0.8, MediaQuery.of(context).size.height * 0.3, ), + messageTheme: widget.messageTheme, ), ) : VideoPlayer(media[position].videoPlayer), diff --git a/stream_chat_v1/lib/chat_info_screen.dart b/stream_chat_v1/lib/chat_info_screen.dart index 38fbb707ef..99611c8b27 100644 --- a/stream_chat_v1/lib/chat_info_screen.dart +++ b/stream_chat_v1/lib/chat_info_screen.dart @@ -13,7 +13,13 @@ class ChatInfoScreen extends StatefulWidget { /// User in consideration final User user; - const ChatInfoScreen({Key key, this.user}) : super(key: key); + final MessageTheme messageTheme; + + const ChatInfoScreen({ + Key key, + @required this.messageTheme, + this.user, + }) : super(key: key); @override _ChatInfoScreenState createState() => _ChatInfoScreenState(); @@ -217,6 +223,7 @@ class _ChatInfoScreenState extends State { channel: channel, child: MessageSearchBloc( child: ChannelMediaDisplayScreen( + messageTheme: widget.messageTheme, sortOptions: [ SortOption( 'created_at', @@ -445,20 +452,10 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { ), body: StreamBuilder>( stream: chat.client.queryChannels( - filter: { - r'$and': [ - { - 'members': { - r'$in': [widget.otherUser.id], - }, - }, - { - 'members': { - r'$in': [widget.mainUser.id], - }, - } - ], - }, + filter: Filter.and([ + Filter.in_('members', [widget.otherUser.id]), + Filter.in_('members', [widget.mainUser.id]), + ]), ), builder: (context, snapshot) { if (!snapshot.hasData) { diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/group_info_screen.dart index efe1808c01..d84826c97c 100644 --- a/stream_chat_v1/lib/group_info_screen.dart +++ b/stream_chat_v1/lib/group_info_screen.dart @@ -14,6 +14,13 @@ import 'main.dart'; import 'routes/routes.dart'; class GroupInfoScreen extends StatefulWidget { + final MessageTheme messageTheme; + + const GroupInfoScreen({ + Key key, + @required this.messageTheme, + }) : super(key: key); + @override _GroupInfoScreenState createState() => _GroupInfoScreenState(); } @@ -502,6 +509,7 @@ class _GroupInfoScreenState extends State { channel: channel, child: MessageSearchBloc( child: ChannelMediaDisplayScreen( + messageTheme: widget.messageTheme, sortOptions: [ SortOption( 'created_at', @@ -657,18 +665,16 @@ class _GroupInfoScreenState extends State { pagination: PaginationParams( limit: 25, ), - filter: { - if (_searchController.text.isNotEmpty) - 'name': { - r'$autocomplete': _userNameQuery, - }, - 'id': { - r'$nin': [ + filter: Filter.and( + [ + if (_searchController.text.isNotEmpty) + Filter.autoComplete('name', _userNameQuery), + Filter.notIn('id', [ StreamChat.of(context).user.id, ...channel.state.members.map((e) => e.userId), - ], - }, - }, + ]), + ], + ), sort: [ SortOption( 'name', @@ -848,6 +854,7 @@ class _GroupInfoScreenState extends State { builder: (context) => StreamChannel( channel: c, child: ChatInfoScreen( + messageTheme: widget.messageTheme, user: user, ), ), diff --git a/stream_chat_v1/lib/main.dart b/stream_chat_v1/lib/main.dart index 4e93955800..4610d551b6 100644 --- a/stream_chat_v1/lib/main.dart +++ b/stream_chat_v1/lib/main.dart @@ -498,16 +498,12 @@ class UserMentionPage extends StatelessWidget { final user = StreamChat.of(context).user; return MessageSearchBloc( child: MessageSearchListView( - filters: { - 'members': { - r'$in': [user.id], - }, - }, - messageFilters: { - 'mentioned_users.id': { - r'$contains': user.id, - }, - }, + filters: Filter.in_('members', [user.id]), + messageFilters: Filter.custom( + operator: 'contains', + key: 'mentioned_users.id', + value: user.id, + ), sortOptions: [ SortOption( 'created_at', @@ -651,11 +647,7 @@ class _ChannelListPageState extends State { ? MessageSearchListView( showErrorTile: true, messageQuery: _channelQuery, - filters: { - 'members': { - r'$in': [user.id] - }, - }, + filters: Filter.in_('members', [user.id]), sortOptions: [ SortOption( 'created_at', @@ -720,11 +712,7 @@ class _ChannelListPageState extends State { Navigator.pushNamed(context, Routes.NEW_CHAT); }, swipeToAction: true, - filter: { - 'members': { - r'$in': [user.id], - }, - }, + filter: Filter.in_('members', [user.id]), options: { 'presence': true, }, @@ -741,6 +729,8 @@ class _ChannelListPageState extends State { builder: (context) => StreamChannel( channel: channel, child: ChatInfoScreen( + messageTheme: StreamChatTheme.of(context) + .ownMessageTheme, user: channel.state.members .where((m) => m.userId != @@ -757,7 +747,10 @@ class _ChannelListPageState extends State { MaterialPageRoute( builder: (context) => StreamChannel( channel: channel, - child: GroupInfoScreen(), + child: GroupInfoScreen( + messageTheme: StreamChatTheme.of(context) + .ownMessageTheme, + ), ), ), ); @@ -843,6 +836,7 @@ class _ChannelPageState extends State { MaterialPageRoute( builder: (context) => StreamChannel( child: ChatInfoScreen( + messageTheme: StreamChatTheme.of(context).ownMessageTheme, user: otherUser.user, ), channel: channel, @@ -859,7 +853,9 @@ class _ChannelPageState extends State { context, MaterialPageRoute( builder: (context) => StreamChannel( - child: GroupInfoScreen(), + child: GroupInfoScreen( + messageTheme: StreamChatTheme.of(context).ownMessageTheme, + ), channel: channel, ), ), diff --git a/stream_chat_v1/lib/new_chat_screen.dart b/stream_chat_v1/lib/new_chat_screen.dart index d4a68887d3..fac0ed0745 100644 --- a/stream_chat_v1/lib/new_chat_screen.dart +++ b/stream_chat_v1/lib/new_chat_screen.dart @@ -70,13 +70,13 @@ class _NewChatScreenState extends State { 'state': false, 'watch': false, }, - filter: { - 'members': [ + filter: Filter.and([ + Filter.equal('members', [ ..._selectedUsers.map((e) => e.id), chatState.user.id, - ], - 'distinct': true, - }, + ]), + Filter.equal('distinct', true), + ]), messageLimit: 0, paginationParams: PaginationParams( limit: 1, @@ -308,15 +308,12 @@ class _NewChatScreenState extends State { pagination: PaginationParams( limit: 25, ), - filter: { + filter: Filter.and([ if (_userNameQuery.isNotEmpty) - 'name': { - r'$autocomplete': _userNameQuery, - }, - 'id': { - r'$ne': StreamChat.of(context).user.id, - }, - }, + Filter.autoComplete('name', _userNameQuery), + Filter.notEqual( + 'id', StreamChat.of(context).user.id), + ]), sort: [ SortOption( 'name', diff --git a/stream_chat_v1/lib/new_group_chat_screen.dart b/stream_chat_v1/lib/new_group_chat_screen.dart index 209d37292b..9944572b85 100644 --- a/stream_chat_v1/lib/new_group_chat_screen.dart +++ b/stream_chat_v1/lib/new_group_chat_screen.dart @@ -244,15 +244,11 @@ class _NewGroupChatScreenState extends State { pagination: PaginationParams( limit: 25, ), - filter: { + filter: Filter.and([ if (_userNameQuery.isNotEmpty) - 'name': { - r'$autocomplete': _userNameQuery, - }, - 'id': { - r'$ne': StreamChat.of(context).user.id, - } - }, + Filter.autoComplete('name', _userNameQuery), + Filter.notEqual('id', StreamChat.of(context).user.id), + ]), sort: [ SortOption( 'name', diff --git a/stream_chat_v1/lib/routes/app_routes.dart b/stream_chat_v1/lib/routes/app_routes.dart index c641b048ca..1be8bf7b82 100644 --- a/stream_chat_v1/lib/routes/app_routes.dart +++ b/stream_chat_v1/lib/routes/app_routes.dart @@ -74,16 +74,19 @@ class AppRoutes { case Routes.CHAT_INFO_SCREEN: return MaterialPageRoute( settings: const RouteSettings(name: Routes.CHAT_INFO_SCREEN), - builder: (_) { + builder: (context) { return ChatInfoScreen( user: args, + messageTheme: StreamChatTheme.of(context).ownMessageTheme, ); }); case Routes.GROUP_INFO_SCREEN: return MaterialPageRoute( settings: const RouteSettings(name: Routes.GROUP_INFO_SCREEN), - builder: (_) { - return GroupInfoScreen(); + builder: (context) { + return GroupInfoScreen( + messageTheme: StreamChatTheme.of(context).ownMessageTheme, + ); }); // Default case, should not reach here. default: diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index 35af177fbb..464d2353ad 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -7,7 +7,7 @@ environment: sdk: ">=2.2.2 <3.0.0" dependencies: - flutter_app_badger: ^1.1.2 + flutter_app_badger: ^1.2.0 flutter: sdk: flutter stream_chat_flutter: @@ -20,13 +20,13 @@ dependencies: url: https://github.com/GetStream/stream-chat-flutter.git ref: develop path: packages/stream_chat_persistence - flutter_local_notifications: ^2.0.2 - flutter_svg: ^0.19.3 - flutter_secure_storage: ^3.3.5 - yaml: ^2.2.1 - uuid: ^2.2.2 - streaming_shared_preferences: ^1.0.2 - lottie: ^0.7.0+1 + flutter_local_notifications: ^5.0.0+4 + flutter_svg: ^0.22.0 + flutter_secure_storage: ^4.2.0 + yaml: ^3.1.0 + uuid: ^3.0.4 + streaming_shared_preferences: ^2.0.0 + lottie: ^1.0.1 dependency_overrides: stream_chat: @@ -41,7 +41,7 @@ dependency_overrides: path: packages/stream_chat_flutter_core dev_dependencies: - flutter_launcher_icons: ^0.8.1 + flutter_launcher_icons: ^0.9.0 test: any flutter: diff --git a/stream_chat_v1/test/widget_test.dart b/stream_chat_v1/test/widget_test.dart deleted file mode 100644 index 2d257c02ef..0000000000 --- a/stream_chat_v1/test/widget_test.dart +++ /dev/null @@ -1,30 +0,0 @@ -// This is a basic Flutter widget test. -// -// To perform an interaction with a widget in your test, use the WidgetTester -// utility that Flutter provides. For example, you can send tap and scroll -// gestures. You can also use WidgetTester to find child widgets in the widget -// tree, read text, and verify that the values of widget properties are correct. - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import 'package:stream_chat_v1/main.dart'; - -void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(MyApp()); - - // Verify that our counter starts at 0. - expect(find.text('0'), findsOneWidget); - expect(find.text('1'), findsNothing); - - // Tap the '+' icon and trigger a frame. - await tester.tap(find.byIcon(Icons.add)); - await tester.pump(); - - // Verify that our counter has incremented. - expect(find.text('0'), findsNothing); - expect(find.text('1'), findsOneWidget); - }); -} From d7a018b362d4d622828fd5549adb0526ff80880e Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Wed, 12 May 2021 17:01:51 +0200 Subject: [PATCH 027/172] migrate sample app --- stream_chat_v1/lib/advanced_options_page.dart | 14 +- .../lib/channel_file_display_screen.dart | 18 +-- .../lib/channel_media_display_screen.dart | 36 ++--- stream_chat_v1/lib/chat_info_screen.dart | 64 ++++---- .../lib/chips_input_text_field.dart | 20 +-- .../lib/group_chat_details_screen.dart | 16 +- stream_chat_v1/lib/group_info_screen.dart | 120 +++++++-------- stream_chat_v1/lib/main.dart | 142 +++++++++--------- stream_chat_v1/lib/new_chat_screen.dart | 36 ++--- stream_chat_v1/lib/new_group_chat_screen.dart | 16 +- stream_chat_v1/lib/notifications_service.dart | 8 +- stream_chat_v1/lib/routes/app_routes.dart | 8 +- stream_chat_v1/lib/search_text_field.dart | 16 +- stream_chat_v1/lib/stream_version.dart | 4 +- stream_chat_v1/pubspec.yaml | 3 +- 15 files changed, 261 insertions(+), 260 deletions(-) diff --git a/stream_chat_v1/lib/advanced_options_page.dart b/stream_chat_v1/lib/advanced_options_page.dart index a654f3de13..b4a4326336 100644 --- a/stream_chat_v1/lib/advanced_options_page.dart +++ b/stream_chat_v1/lib/advanced_options_page.dart @@ -17,13 +17,13 @@ class _AdvancedOptionsPageState extends State { final _formKey = GlobalKey(); final TextEditingController _apiKeyController = TextEditingController(); - String _apiKeyError; + String? _apiKeyError; final TextEditingController _userIdController = TextEditingController(); - String _userIdError; + String? _userIdError; final TextEditingController _userTokenController = TextEditingController(); - String _userTokenError; + String? _userTokenError; final TextEditingController _usernameController = TextEditingController(); @@ -73,7 +73,7 @@ class _AdvancedOptionsPageState extends State { } }, validator: (value) { - if (value.isEmpty) { + if (value!.isEmpty) { setState(() { _apiKeyError = 'Please enter the Chat API Key'.toUpperCase(); @@ -119,7 +119,7 @@ class _AdvancedOptionsPageState extends State { } }, validator: (value) { - if (value.isEmpty) { + if (value!.isEmpty) { setState(() { _userIdError = 'Please enter the User ID'.toUpperCase(); @@ -165,7 +165,7 @@ class _AdvancedOptionsPageState extends State { }, controller: _userTokenController, validator: (value) { - if (value.isEmpty) { + if (value!.isEmpty) { setState(() { _userTokenError = 'Please enter the user token'.toUpperCase(); @@ -243,7 +243,7 @@ class _AdvancedOptionsPageState extends State { if (loading) { return; } - if (_formKey.currentState.validate()) { + if (_formKey.currentState!.validate()) { final apiKey = _apiKeyController.text; final userId = _userIdController.text; final userToken = _userTokenController.text; diff --git a/stream_chat_v1/lib/channel_file_display_screen.dart b/stream_chat_v1/lib/channel_file_display_screen.dart index cbd5264c03..806f184e7b 100644 --- a/stream_chat_v1/lib/channel_file_display_screen.dart +++ b/stream_chat_v1/lib/channel_file_display_screen.dart @@ -6,16 +6,16 @@ class ChannelFileDisplayScreen extends StatefulWidget { /// Sorting is based on field and direction, multiple sorting options can be provided. /// You can sort based on last_updated, last_message_at, updated_at, created_at or member_count. /// Direction can be ascending or descending. - final List sortOptions; + final List? sortOptions; /// Pagination parameters /// limit: the number of users to return (max is 30) /// offset: the offset (max is 1000) /// message_limit: how many messages should be included to each channel - final PaginationParams paginationParams; + final PaginationParams? paginationParams; /// The builder used when the file list is empty. - final WidgetBuilder emptyBuilder; + final WidgetBuilder? emptyBuilder; const ChannelFileDisplayScreen({ this.sortOptions, @@ -36,7 +36,7 @@ class _ChannelFileDisplayScreenState extends State { messageSearchBloc.search( filter: Filter.in_( 'cid', - [StreamChannel.of(context).channel.cid], + [StreamChannel.of(context).channel.cid!], ), messageFilter: Filter.in_( 'attachments.type', @@ -93,9 +93,9 @@ class _ChannelFileDisplayScreenState extends State { ); } - if (snapshot.data.isEmpty) { + if (snapshot.data!.isEmpty) { if (widget.emptyBuilder != null) { - return widget.emptyBuilder(context); + return widget.emptyBuilder!(context); } return Center( child: Column( @@ -132,7 +132,7 @@ class _ChannelFileDisplayScreenState extends State { final media = {}; - for (var item in snapshot.data) { + for (var item in snapshot.data!) { item.message.attachments.where((e) => e.type == 'file').forEach((e) { media[e] = item.message; }); @@ -142,14 +142,14 @@ class _ChannelFileDisplayScreenState extends State { onEndOfPage: () => messageSearchBloc.search( filter: Filter.in_( 'cid', - [StreamChannel.of(context).channel.cid], + [StreamChannel.of(context).channel.cid!], ), messageFilter: Filter.in_( 'attachments.type', ['file'], ), sort: widget.sortOptions, - pagination: widget.paginationParams.copyWith( + pagination: widget.paginationParams!.copyWith( offset: messageSearchBloc.messageResponses?.length ?? 0, ), ), diff --git a/stream_chat_v1/lib/channel_media_display_screen.dart b/stream_chat_v1/lib/channel_media_display_screen.dart index 2bf0fb1107..5c33622136 100644 --- a/stream_chat_v1/lib/channel_media_display_screen.dart +++ b/stream_chat_v1/lib/channel_media_display_screen.dart @@ -7,23 +7,23 @@ class ChannelMediaDisplayScreen extends StatefulWidget { /// Sorting is based on field and direction, multiple sorting options can be provided. /// You can sort based on last_updated, last_message_at, updated_at, created_at or member_count. /// Direction can be ascending or descending. - final List sortOptions; + final List? sortOptions; /// Pagination parameters /// limit: the number of users to return (max is 30) /// offset: the offset (max is 1000) /// message_limit: how many messages should be included to each channel - final PaginationParams paginationParams; + final PaginationParams? paginationParams; /// The builder used when the file list is empty. - final WidgetBuilder emptyBuilder; + final WidgetBuilder? emptyBuilder; - final ShowMessageCallback onShowMessage; + final ShowMessageCallback? onShowMessage; final MessageTheme messageTheme; const ChannelMediaDisplayScreen({ - @required this.messageTheme, + required this.messageTheme, this.sortOptions, this.paginationParams, this.emptyBuilder, @@ -36,7 +36,7 @@ class ChannelMediaDisplayScreen extends StatefulWidget { } class _ChannelMediaDisplayScreenState extends State { - Map controllerCache = {}; + Map controllerCache = {}; @override void initState() { @@ -45,7 +45,7 @@ class _ChannelMediaDisplayScreenState extends State { messageSearchBloc.search( filter: Filter.in_( 'cid', - [StreamChannel.of(context).channel.cid], + [StreamChannel.of(context).channel.cid!], ), messageFilter: Filter.in_( 'attachments.type', @@ -103,9 +103,9 @@ class _ChannelMediaDisplayScreenState extends State { ); } - if (snapshot.data.isEmpty) { + if (snapshot.data!.isEmpty) { if (widget.emptyBuilder != null) { - return widget.emptyBuilder(context); + return widget.emptyBuilder!(context); } return Center( child: Column( @@ -142,18 +142,18 @@ class _ChannelMediaDisplayScreenState extends State { final media = <_AssetPackage>[]; - for (var item in snapshot.data) { + for (var item in snapshot.data!) { item.message.attachments .where((e) => (e.type == 'image' || e.type == 'video') && e.ogScrapeUrl == null) .forEach((e) { - VideoPlayerController controller; + VideoPlayerController? controller; if (e.type == 'video') { var cachedController = controllerCache[e.assetUrl]; if (cachedController == null) { - controller = VideoPlayerController.network(e.assetUrl); + controller = VideoPlayerController.network(e.assetUrl!); controller.initialize(); controllerCache[e.assetUrl] = controller; } else { @@ -168,14 +168,14 @@ class _ChannelMediaDisplayScreenState extends State { onEndOfPage: () => messageSearchBloc.search( filter: Filter.in_( 'cid', - [StreamChannel.of(context).channel.cid], + [StreamChannel.of(context).channel.cid!], ), messageFilter: Filter.in_( 'attachments.type', ['image', 'video'], ), sort: widget.sortOptions, - pagination: widget.paginationParams.copyWith( + pagination: widget.paginationParams!.copyWith( offset: messageSearchBloc.messageResponses?.length ?? 0, ), ), @@ -198,7 +198,7 @@ class _ChannelMediaDisplayScreenState extends State { media.map((e) => e.attachment).toList(), startIndex: position, message: media[position].message, - userName: media[position].message.user.name, + userName: media[position].message.user!.name, onShowMessage: widget.onShowMessage, ), ), @@ -218,7 +218,7 @@ class _ChannelMediaDisplayScreenState extends State { messageTheme: widget.messageTheme, ), ) - : VideoPlayer(media[position].videoPlayer), + : VideoPlayer(media[position].videoPlayer!), ), ); }, @@ -234,7 +234,7 @@ class _ChannelMediaDisplayScreenState extends State { void dispose() { super.dispose(); for (var c in controllerCache.values) { - c.dispose(); + c!.dispose(); } } } @@ -242,7 +242,7 @@ class _ChannelMediaDisplayScreenState extends State { class _AssetPackage { Attachment attachment; Message message; - VideoPlayerController videoPlayer; + VideoPlayerController? videoPlayer; _AssetPackage(this.attachment, this.message, this.videoPlayer); } diff --git a/stream_chat_v1/lib/chat_info_screen.dart b/stream_chat_v1/lib/chat_info_screen.dart index 99611c8b27..8a09f4374c 100644 --- a/stream_chat_v1/lib/chat_info_screen.dart +++ b/stream_chat_v1/lib/chat_info_screen.dart @@ -1,3 +1,4 @@ +import 'package:collection/collection.dart' show IterableExtension; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:jiffy/jiffy.dart'; @@ -11,13 +12,13 @@ import 'routes/routes.dart'; /// Detail screen for a 1:1 chat correspondence class ChatInfoScreen extends StatefulWidget { /// User in consideration - final User user; + final User? user; final MessageTheme messageTheme; const ChatInfoScreen({ - Key key, - @required this.messageTheme, + Key? key, + required this.messageTheme, this.user, }) : super(key: key); @@ -26,7 +27,7 @@ class ChatInfoScreen extends StatefulWidget { } class _ChatInfoScreenState extends State { - ValueNotifier mutedBool = ValueNotifier(false); + ValueNotifier mutedBool = ValueNotifier(false); @override void initState() { @@ -54,9 +55,8 @@ class _ChatInfoScreenState extends State { if ([ 'admin', 'owner', - ].contains(channel.state.members - .firstWhere((m) => m.userId == channel.client.state.user.id, - orElse: () => null) + ].contains(channel.state!.members + .firstWhereOrNull((m) => m.userId == channel.client.state.user!.id) ?.role)) _buildDeleteListTile(), ], @@ -76,7 +76,7 @@ class _ChatInfoScreenState extends State { Padding( padding: const EdgeInsets.all(16.0), child: UserAvatar( - user: widget.user, + user: widget.user!, constraints: BoxConstraints( maxWidth: 72.0, maxHeight: 72.0, @@ -86,19 +86,19 @@ class _ChatInfoScreenState extends State { ), ), Text( - widget.user.name, + widget.user!.name, style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold), ), SizedBox(height: 7.0), _buildConnectedTitleState(), SizedBox(height: 15.0), OptionListTile( - title: '@${widget.user.id}', + title: '@${widget.user!.id}', tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow, trailing: Padding( padding: const EdgeInsets.symmetric(horizontal: 8.0), child: Text( - widget.user.name, + widget.user!.name, style: TextStyle( color: StreamChatTheme.of(context) .colorTheme @@ -161,15 +161,15 @@ class _ChatInfoScreenState extends State { ), trailing: snapshot.data == null ? CircularProgressIndicator() - : ValueListenableBuilder( + : ValueListenableBuilder( valueListenable: mutedBool, builder: (context, value, _) { return CupertinoSwitch( - value: value, + value: value!, onChanged: (val) { mutedBool.value = val; - if (snapshot.data) { + if (snapshot.data!) { channel.channel.unmute(); } else { channel.channel.mute(); @@ -394,7 +394,7 @@ class _ChatInfoScreenState extends State { return Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - if (widget.user.online) + if (widget.user!.online) Material( type: MaterialType.circle, child: Container( @@ -411,7 +411,7 @@ class _ChatInfoScreenState extends State { color: StreamChatTheme.of(context).colorTheme.white, ), alternativeWidget, - if (widget.user.online) + if (widget.user!.online) SizedBox( width: 24.0, ), @@ -421,8 +421,8 @@ class _ChatInfoScreenState extends State { } class _SharedGroupsScreen extends StatefulWidget { - final User mainUser; - final User otherUser; + final User? mainUser; + final User? otherUser; _SharedGroupsScreen(this.mainUser, this.otherUser); @@ -453,8 +453,8 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { body: StreamBuilder>( stream: chat.client.queryChannels( filter: Filter.and([ - Filter.in_('members', [widget.otherUser.id]), - Filter.in_('members', [widget.mainUser.id]), + Filter.in_('members', [widget.otherUser!.id]), + Filter.in_('members', [widget.mainUser!.id]), ]), ), builder: (context, snapshot) { @@ -464,7 +464,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { ); } - if (snapshot.data.isEmpty) { + if (snapshot.data!.isEmpty) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -498,11 +498,11 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { ); } - final channels = snapshot.data + final channels = snapshot.data! .where((c) => - c.state.members.any((m) => - m.userId != widget.mainUser.id && - m.userId != widget.otherUser.id) || + c.state!.members.any((m) => + m.userId != widget.mainUser!.id && + m.userId != widget.otherUser!.id) || !c.isDistinct) .toList(); @@ -522,24 +522,24 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { Widget _buildListTile(Channel channel) { var extraData = channel.extraData; - var members = channel.state.members; + var members = channel.state!.members; var textStyle = TextStyle(fontSize: 14.0, fontWeight: FontWeight.bold); return Container( height: 64.0, child: LayoutBuilder(builder: (context, constraints) { - String title; + String? title; if (extraData['name'] == null) { final otherMembers = members.where( - (member) => member.userId != StreamChat.of(context).user.id); + (member) => member.userId != StreamChat.of(context).user!.id); if (otherMembers.isNotEmpty) { final maxWidth = constraints.maxWidth; - final maxChars = maxWidth / textStyle.fontSize; + final maxChars = maxWidth / textStyle.fontSize!; var currentChars = 0; final currentMembers = []; otherMembers.forEach((element) { - final newLength = currentChars + element.user.name.length; + final newLength = currentChars + element.user!.name.length; if (newLength < maxChars) { currentChars = newLength; currentMembers.add(element); @@ -549,7 +549,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { final exceedingMembers = otherMembers.length - currentMembers.length; title = - '${currentMembers.map((e) => e.user.name).join(', ')} ${exceedingMembers > 0 ? '+ $exceedingMembers' : ''}'; + '${currentMembers.map((e) => e.user!.name).join(', ')} ${exceedingMembers > 0 ? '+ $exceedingMembers' : ''}'; } else { title = 'No title'; } @@ -572,7 +572,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { ), Expanded( child: Text( - title, + title!, style: textStyle, )), Padding( diff --git a/stream_chat_v1/lib/chips_input_text_field.dart b/stream_chat_v1/lib/chips_input_text_field.dart index 0fc079182e..c36e4ae114 100644 --- a/stream_chat_v1/lib/chips_input_text_field.dart +++ b/stream_chat_v1/lib/chips_input_text_field.dart @@ -6,18 +6,18 @@ typedef OnChipAdded = void Function(T chip); typedef OnChipRemoved = void Function(T chip); class ChipsInputTextField extends StatefulWidget { - final TextEditingController controller; - final FocusNode focusNode; - final ValueChanged onInputChanged; + final TextEditingController? controller; + final FocusNode? focusNode; + final ValueChanged? onInputChanged; final ChipBuilder chipBuilder; - final OnChipAdded onChipAdded; - final OnChipRemoved onChipRemoved; + final OnChipAdded? onChipAdded; + final OnChipRemoved? onChipRemoved; final String hint; const ChipsInputTextField({ - Key key, - @required this.chipBuilder, - @required this.controller, + Key? key, + required this.chipBuilder, + required this.controller, this.onInputChanged, this.focusNode, this.onChipAdded, @@ -35,7 +35,7 @@ class ChipInputTextFieldState extends State> { void addItem(T item) { setState(() => _chips.add(item)); - if (widget.onChipAdded != null) widget.onChipAdded(item); + if (widget.onChipAdded != null) widget.onChipAdded!(item); } void removeItem(T item) { @@ -43,7 +43,7 @@ class ChipInputTextFieldState extends State> { _chips.remove(item); if (_chips.isEmpty) resumeItemAddition(); }); - if (widget.onChipRemoved != null) widget.onChipRemoved(item); + if (widget.onChipRemoved != null) widget.onChipRemoved!(item); } void pauseItemAddition() { diff --git a/stream_chat_v1/lib/group_chat_details_screen.dart b/stream_chat_v1/lib/group_chat_details_screen.dart index afc9d12f7a..1819fe8cc9 100644 --- a/stream_chat_v1/lib/group_chat_details_screen.dart +++ b/stream_chat_v1/lib/group_chat_details_screen.dart @@ -6,11 +6,11 @@ import 'main.dart'; import 'routes/routes.dart'; class GroupChatDetailsScreen extends StatefulWidget { - final List selectedUsers; + final List? selectedUsers; const GroupChatDetailsScreen({ - Key key, - @required this.selectedUsers, + Key? key, + required this.selectedUsers, }) : super(key: key); @override @@ -20,14 +20,14 @@ class GroupChatDetailsScreen extends StatefulWidget { class _GroupChatDetailsScreenState extends State { final _selectedUsers = []; - TextEditingController _groupNameController; + TextEditingController? _groupNameController; bool _isGroupNameEmpty = true; int get _totalUsers => _selectedUsers.length; void _groupNameListener() { - final name = _groupNameController.text; + final name = _groupNameController!.text; if (mounted) { setState(() { _isGroupNameEmpty = name.isEmpty; @@ -38,7 +38,7 @@ class _GroupChatDetailsScreenState extends State { @override void initState() { super.initState(); - _selectedUsers.addAll(widget.selectedUsers); + _selectedUsers.addAll(widget.selectedUsers!); _groupNameController = TextEditingController() ..addListener(_groupNameListener); } @@ -124,13 +124,13 @@ class _GroupChatDetailsScreenState extends State { ? null : () async { try { - final groupName = _groupNameController.text; + final groupName = _groupNameController!.text; final client = StreamChat.of(context).client; final channel = client.channel('messaging', id: Uuid().v4(), extraData: { 'members': [ - client.state.user.id, + client.state.user!.id, ..._selectedUsers.map((e) => e.id), ], 'name': groupName, diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/group_info_screen.dart index d84826c97c..00e396688e 100644 --- a/stream_chat_v1/lib/group_info_screen.dart +++ b/stream_chat_v1/lib/group_info_screen.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:collection/collection.dart' show IterableExtension; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:jiffy/jiffy.dart'; @@ -17,8 +18,8 @@ class GroupInfoScreen extends StatefulWidget { final MessageTheme messageTheme; const GroupInfoScreen({ - Key key, - @required this.messageTheme, + Key? key, + required this.messageTheme, }) : super(key: key); @override @@ -26,29 +27,29 @@ class GroupInfoScreen extends StatefulWidget { } class _GroupInfoScreenState extends State { - TextEditingController _nameController; + TextEditingController? _nameController; - TextEditingController _searchController; + TextEditingController? _searchController; String _userNameQuery = ''; - Timer _debounce; - Function modalSetStateCallback; + Timer? _debounce; + Function? modalSetStateCallback; final FocusNode _focusNode = FocusNode(); bool listExpanded = false; - ValueNotifier mutedBool = ValueNotifier(false); + ValueNotifier mutedBool = ValueNotifier(false); void _userNameListener() { - if (_searchController.text == _userNameQuery) { + if (_searchController!.text == _userNameQuery) { return; } - if (_debounce?.isActive ?? false) _debounce.cancel(); + if (_debounce?.isActive ?? false) _debounce!.cancel(); _debounce = Timer(const Duration(milliseconds: 350), () { if (mounted && modalSetStateCallback != null) { - modalSetStateCallback(() { - _userNameQuery = _searchController.text; + modalSetStateCallback!(() { + _userNameQuery = _searchController!.text; }); } }); @@ -62,7 +63,7 @@ class _GroupInfoScreenState extends State { TextEditingValue(text: channel.channel.extraData['name'] ?? '')); _searchController = TextEditingController()..addListener(_userNameListener); - _nameController.addListener(() { + _nameController!.addListener(() { setState(() {}); }); mutedBool = ValueNotifier(StreamChannel.of(context).channel.isMuted); @@ -73,7 +74,7 @@ class _GroupInfoScreenState extends State { var channel = StreamChannel.of(context); return StreamBuilder>( - stream: channel.channel.state.membersStream, + stream: channel.channel.state!.membersStream, builder: (context, snapshot) { if (!snapshot.hasData) { return Container( @@ -82,9 +83,8 @@ class _GroupInfoScreenState extends State { ); } - var userMember = snapshot.data.firstWhere( - (e) => e.user.id == StreamChat.of(context).user.id, - orElse: () => null, + var userMember = snapshot.data!.firstWhereOrNull( + (e) => e.user!.id == StreamChat.of(context).user!.id, ); var isOwner = userMember?.role == 'owner'; @@ -118,9 +118,9 @@ class _GroupInfoScreenState extends State { _getChannelName( 2 * MediaQuery.of(context).size.width / 3, members: snapshot.data, - extraData: state.data.channel.extraData, + extraData: state.data!.channel!.extraData, maxFontSize: 16.0, - ), + )!, style: TextStyle( color: StreamChatTheme.of(context).colorTheme.black, fontSize: 16, @@ -133,7 +133,7 @@ class _GroupInfoScreenState extends State { height: 3.0, ), Text( - '${channel.channel.memberCount} Members, ${snapshot?.data?.where((e) => e.user.online)?.length ?? 0} Online', + '${channel.channel.memberCount} Members, ${snapshot.data?.where((e) => e.user!.online).length ?? 0} Online', style: TextStyle( color: StreamChatTheme.of(context) .colorTheme @@ -165,7 +165,7 @@ class _GroupInfoScreenState extends State { ), body: ListView( children: [ - _buildMembers(snapshot.data), + _buildMembers(snapshot.data!), Container( height: 8.0, color: StreamChatTheme.of(context).colorTheme.greyGainsboro, @@ -204,9 +204,8 @@ class _GroupInfoScreenState extends State { return Material( child: InkWell( onTap: () { - final userMember = groupMembers.firstWhere( - (e) => e.user.id == StreamChat.of(context).user.id, - orElse: () => null, + final userMember = groupMembers.firstWhereOrNull( + (e) => e.user!.id == StreamChat.of(context).user!.id, ); _showUserInfoModal(member.user, userMember?.role == 'owner'); }, @@ -220,7 +219,7 @@ class _GroupInfoScreenState extends State { padding: const EdgeInsets.symmetric( horizontal: 8.0, vertical: 12.0), child: UserAvatar( - user: member.user, + user: member.user!, constraints: BoxConstraints( maxHeight: 40.0, maxWidth: 40.0), ), @@ -231,14 +230,14 @@ class _GroupInfoScreenState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ Text( - member.user.name, + member.user!.name, style: TextStyle(fontWeight: FontWeight.bold), ), SizedBox( height: 1.0, ), Text( - _getLastSeen(member.user), + _getLastSeen(member.user!), style: TextStyle( color: StreamChatTheme.of(context) .colorTheme @@ -378,7 +377,7 @@ class _GroupInfoScreenState extends State { ), ), if ((channelName == null) || - (channelName != _nameController.text.trim())) + (channelName != _nameController!.text.trim())) Row( mainAxisSize: MainAxisSize.min, children: [ @@ -386,12 +385,12 @@ class _GroupInfoScreenState extends State { child: StreamSvgIcon.closeSmall(), onTap: () { setState(() { - _nameController.text = _getChannelName( + _nameController!.text = _getChannelName( 2 * MediaQuery.of(context).size.width / 3, - members: channel.state.members, + members: channel.state!.members, extraData: channel.extraData, maxFontSize: 16.0, - ); + )!; _focusNode.unfocus(); }); }, @@ -406,10 +405,10 @@ class _GroupInfoScreenState extends State { ), onTap: () { StreamChannel.of(context).channel.update({ - 'name': _nameController.text.trim(), + 'name': _nameController!.text.trim(), }).catchError((err) { setState(() { - _nameController.text = channelName; + _nameController!.text = channelName; _focusNode.unfocus(); }); }); @@ -464,15 +463,15 @@ class _GroupInfoScreenState extends State { ), trailing: snapshot.data == null ? CircularProgressIndicator() - : ValueListenableBuilder( + : ValueListenableBuilder( valueListenable: mutedBool, builder: (context, value, _) { return CupertinoSwitch( - value: value, + value: value!, onChanged: (val) { mutedBool.value = val; - if (snapshot.data) { + if (snapshot.data!) { channel.channel.unmute(); } else { channel.channel.mute(); @@ -617,7 +616,7 @@ class _GroupInfoScreenState extends State { ); if (res == true) { final channel = StreamChannel.of(context).channel; - await channel.removeMembers([StreamChat.of(context).user.id]); + await channel.removeMembers([StreamChat.of(context).user!.id]); Navigator.pop(context); } }, @@ -655,7 +654,7 @@ class _GroupInfoScreenState extends State { child: UserListView( selectedUsers: {}, onUserTap: (user, _) async { - _searchController.clear(); + _searchController!.clear(); await channel.addMembers([user.id]); Navigator.pop(context); @@ -667,11 +666,12 @@ class _GroupInfoScreenState extends State { ), filter: Filter.and( [ - if (_searchController.text.isNotEmpty) + if (_searchController!.text.isNotEmpty) Filter.autoComplete('name', _userNameQuery), Filter.notIn('id', [ - StreamChat.of(context).user.id, - ...channel.state.members.map((e) => e.userId), + StreamChat.of(context).user!.id, + ...channel.state!.members.map(((e) => e.userId!) + as Object Function(Member)), ]), ], ), @@ -784,7 +784,7 @@ class _GroupInfoScreenState extends State { ); } - void _showUserInfoModal(User user, bool isUserAdmin) { + void _showUserInfoModal(User? user, bool isUserAdmin) { var channel = StreamChannel.of(context).channel; showModalBottomSheet( @@ -804,7 +804,7 @@ class _GroupInfoScreenState extends State { ), Center( child: Text( - user.name, + user!.name, style: TextStyle( fontSize: 16.0, fontWeight: FontWeight.bold, @@ -814,7 +814,7 @@ class _GroupInfoScreenState extends State { SizedBox( height: 5.0, ), - _buildConnectedTitleState(user), + _buildConnectedTitleState(user)!, Center( child: Padding( padding: const EdgeInsets.all(16.0), @@ -828,7 +828,7 @@ class _GroupInfoScreenState extends State { ), ), ), - if (StreamChat.of(context).user.id != user.id) + if (StreamChat.of(context).user!.id != user.id) _buildModalListTile( context, StreamSvgIcon.user( @@ -842,7 +842,7 @@ class _GroupInfoScreenState extends State { var c = client.channel('messaging', extraData: { 'members': [ user.id, - StreamChat.of(context).user.id, + StreamChat.of(context).user!.id, ], }); @@ -862,7 +862,7 @@ class _GroupInfoScreenState extends State { ); }, ), - if (StreamChat.of(context).user.id != user.id) + if (StreamChat.of(context).user!.id != user.id) _buildModalListTile( context, StreamSvgIcon.message( @@ -876,7 +876,7 @@ class _GroupInfoScreenState extends State { var c = client.channel('messaging', extraData: { 'members': [ user.id, - StreamChat.of(context).user.id, + StreamChat.of(context).user!.id, ], }); @@ -894,7 +894,7 @@ class _GroupInfoScreenState extends State { }, ), if (!channel.isDistinct && - StreamChat.of(context).user.id != user.id && + StreamChat.of(context).user!.id != user.id && isUserAdmin) _buildModalListTile( context, @@ -906,7 +906,7 @@ class _GroupInfoScreenState extends State { // TODO: Add make owner implementation (Remaining from backend) }), if (!channel.isDistinct && - StreamChat.of(context).user.id != user.id && + StreamChat.of(context).user!.id != user.id && isUserAdmin) _buildModalListTile( context, @@ -941,7 +941,7 @@ class _GroupInfoScreenState extends State { ); } - Widget _buildConnectedTitleState(User user) { + Widget? _buildConnectedTitleState(User? user) { var alternativeWidget; final otherMember = user; @@ -973,7 +973,7 @@ class _GroupInfoScreenState extends State { Widget _buildModalListTile( BuildContext context, Widget leading, String title, VoidCallback onTap, - {Color color}) { + {Color? color}) { color ??= StreamChatTheme.of(context).colorTheme.black; return Material( @@ -1010,24 +1010,24 @@ class _GroupInfoScreenState extends State { ); } - String _getChannelName( + String? _getChannelName( double width, { - List members, - Map extraData, - double maxFontSize, + List? members, + required Map extraData, + double? maxFontSize, }) { - String title; + String? title; var client = StreamChat.of(context); if (extraData['name'] == null) { final otherMembers = - members.where((member) => member.user.id != client.user.id); + members!.where((member) => member.user!.id != client.user!.id); if (otherMembers.isNotEmpty) { final maxWidth = width; - final maxChars = maxWidth / maxFontSize; + final maxChars = maxWidth / maxFontSize!; var currentChars = 0; final currentMembers = []; otherMembers.forEach((element) { - final newLength = currentChars + element.user.name.length; + final newLength = currentChars + element.user!.name.length; if (newLength < maxChars) { currentChars = newLength; currentMembers.add(element); @@ -1036,7 +1036,7 @@ class _GroupInfoScreenState extends State { final exceedingMembers = otherMembers.length - currentMembers.length; title = - '${currentMembers.map((e) => e.user.name).join(', ')} ${exceedingMembers > 0 ? '+ $exceedingMembers' : ''}'; + '${currentMembers.map((e) => e.user!.name).join(', ')} ${exceedingMembers > 0 ? '+ $exceedingMembers' : ''}'; } else { title = 'No title'; } diff --git a/stream_chat_v1/lib/main.dart b/stream_chat_v1/lib/main.dart index 4610d551b6..8b982e4ef5 100644 --- a/stream_chat_v1/lib/main.dart +++ b/stream_chat_v1/lib/main.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:collection/collection.dart' show IterableExtension; import 'package:example/chat_info_screen.dart'; import 'package:example/choose_user_page.dart'; import 'package:example/group_info_screen.dart'; @@ -38,15 +39,15 @@ class MyApp extends StatefulWidget { } class _MyAppState extends State with TickerProviderStateMixin { - InitData _initData; + InitData? _initData; bool _animCompleted = false; - Animation _animation, _scaleAnimation; - AnimationController _animationController, _scaleAnimationController; - Animation _colorAnimation; - int timeOfStartMs; + Animation? _animation, _scaleAnimation; + AnimationController? _animationController, _scaleAnimationController; + Animation? _colorAnimation; + late int timeOfStartMs; Future _initConnection() async { - String apiKey, userId, token; + String? apiKey, userId, token; if (!kIsWeb) { final secureStorage = FlutterSecureStorage(); @@ -84,7 +85,7 @@ class _MyAppState extends State with TickerProviderStateMixin { begin: 1.0, end: 1.5, ).animate(CurvedAnimation( - parent: _scaleAnimationController, + parent: _scaleAnimationController!, curve: Curves.easeInOutBack, )); @@ -98,21 +99,21 @@ class _MyAppState extends State with TickerProviderStateMixin { begin: 0.0, end: 1000.0, ).animate(CurvedAnimation( - parent: _animationController, + parent: _animationController!, curve: Curves.easeInOut, )); _colorAnimation = ColorTween( begin: Color(0xff005FFF), end: Color(0xff005FFF), ).animate(CurvedAnimation( - parent: _animationController, + parent: _animationController!, curve: Curves.easeInOut, )); _colorAnimation = ColorTween( begin: Color(0xff005FFF), end: Colors.transparent, ).animate(CurvedAnimation( - parent: _animationController, + parent: _animationController!, curve: Curves.easeInOut, )); } @@ -132,22 +133,22 @@ class _MyAppState extends State with TickerProviderStateMixin { var now = DateTime.now().millisecondsSinceEpoch; if (now - timeOfStartMs > 1500) { - SchedulerBinding.instance.addPostFrameCallback((timeStamp) { - _scaleAnimationController.forward().whenComplete(() { - _animationController.forward(); + SchedulerBinding.instance!.addPostFrameCallback((timeStamp) { + _scaleAnimationController?.forward().whenComplete(() { + _animationController?.forward(); }); }); } else { Future.delayed(Duration(milliseconds: 1500)).then((value) { - _scaleAnimationController.forward().whenComplete(() { - _animationController.forward(); + _scaleAnimationController?.forward().whenComplete(() { + _animationController?.forward(); }); }); } if (!kIsWeb) { - _initData.client.state?.totalUnreadCountStream?.listen((count) { - if (count > 0) { + _initData!.client.state.totalUnreadCountStream.listen((count) { + if (count! > 0) { FlutterAppBadger.updateBadgeCount(count); } else { FlutterAppBadger.removeBadge(); @@ -156,7 +157,7 @@ class _MyAppState extends State with TickerProviderStateMixin { } }, ); - _animationController.addStatusListener((status) { + _animationController?.addStatusListener((status) { if (status == AnimationStatus.completed) { setState(() { _animCompleted = true; @@ -174,20 +175,20 @@ class _MyAppState extends State with TickerProviderStateMixin { alignment: Alignment.center, children: [ AnimatedBuilder( - animation: _scaleAnimation, + animation: _scaleAnimation!, builder: (context, _) { return Transform.scale( - scale: _scaleAnimation.value, + scale: _scaleAnimation!.value, child: AnimatedBuilder( - animation: _colorAnimation, + animation: _colorAnimation!, builder: (context, snapshot) { return Container( alignment: Alignment.center, constraints: BoxConstraints.expand(), color: _colorAnimation == null ? Color(0xff005FFF) - : _colorAnimation.value, - child: !_animationController.isAnimating + : _colorAnimation!.value, + child: !_animationController!.isAnimating ? Lottie.asset( 'assets/floating_boat.json', alignment: Alignment.center, @@ -199,16 +200,16 @@ class _MyAppState extends State with TickerProviderStateMixin { }, ), AnimatedBuilder( - animation: _animation, + animation: _animation!, builder: (context, snapshot) { return Transform.scale( - scale: _animation.value, + scale: _animation!.value, child: Container( width: 1.0, height: 1.0, decoration: BoxDecoration( color: Colors.white - .withOpacity(1 - _animationController.value), + .withOpacity(1 - _animationController!.value), shape: BoxShape.circle, ), ), @@ -227,19 +228,19 @@ class _MyAppState extends State with TickerProviderStateMixin { children: [ if (_initData != null) PreferenceBuilder( - preference: _initData.preferences.getInt( + preference: _initData!.preferences.getInt( 'theme', defaultValue: 0, ), builder: (context, snapshot) => MaterialApp( builder: (context, child) { return StreamChat( - client: _initData.client, - onBackgroundEventReceived: (e) => - showLocalNotification(e, _initData.client.state.user.id), + client: _initData!.client, + onBackgroundEventReceived: (e) => showLocalNotification( + e, _initData!.client.state.user!.id), child: Builder( builder: (context) => AnnotatedRegion( - child: child, + child: child!, value: SystemUiOverlayStyle( systemNavigationBarColor: StreamChatTheme.of(context).colorTheme.white, @@ -260,7 +261,7 @@ class _MyAppState extends State with TickerProviderStateMixin { 1: ThemeMode.light, }[snapshot], onGenerateRoute: AppRoutes.generateRoute, - initialRoute: _initData.client.state.user == null + initialRoute: _initData!.client.state.user == null ? Routes.CHOOSE_USER : Routes.HOME, ), @@ -319,7 +320,7 @@ class _HomePageState extends State { @override Widget build(BuildContext context) { - final user = StreamChat.of(context).user; + final user = StreamChat.of(context).user!; return Scaffold( backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, appBar: ChannelListHeader( @@ -495,7 +496,7 @@ class _HomePageState extends State { class UserMentionPage extends StatelessWidget { @override Widget build(BuildContext context) { - final user = StreamChat.of(context).user; + final user = StreamChat.of(context).user!; return MessageSearchBloc( child: MessageSearchListView( filters: Filter.in_('members', [user.id]), @@ -555,8 +556,8 @@ class UserMentionPage extends StatelessWidget { final client = StreamChat.of(context).client; final message = messageResponse.message; final channel = client.channel( - messageResponse.channel.type, - id: messageResponse.channel.id, + messageResponse.channel!.type, + id: messageResponse.channel!.id, ); if (channel.state == null) { await channel.watch(); @@ -581,20 +582,20 @@ class ChannelListPage extends StatefulWidget { } class _ChannelListPageState extends State { - TextEditingController _controller; + TextEditingController? _controller; String _channelQuery = ''; bool _isSearchActive = false; - Timer _debounce; + Timer? _debounce; void _channelQueryListener() { - if (_debounce?.isActive ?? false) _debounce.cancel(); + if (_debounce?.isActive ?? false) _debounce!.cancel(); _debounce = Timer(const Duration(milliseconds: 350), () { if (mounted) { setState(() { - _channelQuery = _controller.text; + _channelQuery = _controller!.text; _isSearchActive = _channelQuery.isNotEmpty; }); } @@ -620,7 +621,7 @@ class _ChannelListPageState extends State { return WillPopScope( onWillPop: () async { if (_isSearchActive) { - _controller.clear(); + _controller!.clear(); setState(() => _isSearchActive = false); return false; } @@ -647,7 +648,7 @@ class _ChannelListPageState extends State { ? MessageSearchListView( showErrorTile: true, messageQuery: _channelQuery, - filters: Filter.in_('members', [user.id]), + filters: Filter.in_('members', [user!.id]), sortOptions: [ SortOption( 'created_at', @@ -691,8 +692,8 @@ class _ChannelListPageState extends State { final client = StreamChat.of(context).client; final message = messageResponse.message; final channel = client.channel( - messageResponse.channel.type, - id: messageResponse.channel.id, + messageResponse.channel!.type, + id: messageResponse.channel!.id, ); if (channel.state == null) { await channel.watch(); @@ -712,7 +713,7 @@ class _ChannelListPageState extends State { Navigator.pushNamed(context, Routes.NEW_CHAT); }, swipeToAction: true, - filter: Filter.in_('members', [user.id]), + filter: Filter.in_('members', [user!.id]), options: { 'presence': true, }, @@ -731,10 +732,10 @@ class _ChannelListPageState extends State { child: ChatInfoScreen( messageTheme: StreamChatTheme.of(context) .ownMessageTheme, - user: channel.state.members + user: channel.state!.members .where((m) => m.userId != - channel.client.state.user.id) + channel.client.state.user!.id) .first .user, ), @@ -767,8 +768,8 @@ class _ChannelListPageState extends State { } class ChannelPageArgs { - final Channel channel; - final Message initialMessage; + final Channel? channel; + final Message? initialMessage; const ChannelPageArgs({ this.channel, @@ -777,12 +778,12 @@ class ChannelPageArgs { } class ChannelPage extends StatefulWidget { - final int initialScrollIndex; - final double initialAlignment; + final int? initialScrollIndex; + final double? initialAlignment; final bool highlightInitialMessage; const ChannelPage({ - Key key, + Key? key, this.initialScrollIndex, this.initialAlignment, this.highlightInitialMessage = false, @@ -793,8 +794,8 @@ class ChannelPage extends StatefulWidget { } class _ChannelPageState extends State { - Message _quotedMessage; - FocusNode _focusNode; + Message? _quotedMessage; + FocusNode? _focusNode; @override void initState() { @@ -804,14 +805,14 @@ class _ChannelPageState extends State { @override void dispose() { - _focusNode.dispose(); + _focusNode!.dispose(); super.dispose(); } void _reply(Message message) { setState(() => _quotedMessage = message); - WidgetsBinding.instance.addPostFrameCallback((timeStamp) { - _focusNode.requestFocus(); + WidgetsBinding.instance!.addPostFrameCallback((timeStamp) { + _focusNode!.requestFocus(); }); } @@ -826,9 +827,8 @@ class _ChannelPageState extends State { if (channel.memberCount == 2 && channel.isDistinct) { final currentUser = StreamChat.of(context).user; - final otherUser = channel.state.members.firstWhere( - (element) => element.user.id != currentUser.id, - orElse: () => null, + final otherUser = channel.state!.members.firstWhereOrNull( + (element) => element.user!.id != currentUser!.id, ); if (otherUser != null) { final pop = await Navigator.push( @@ -932,7 +932,7 @@ class _ChannelPageState extends State { quotedMessage: _quotedMessage, onQuotedMessageCleared: () { setState(() => _quotedMessage = null); - _focusNode.unfocus(); + _focusNode!.unfocus(); }, ), ], @@ -942,12 +942,12 @@ class _ChannelPageState extends State { } class ThreadPage extends StatefulWidget { - final Message parent; - final int initialScrollIndex; - final double initialAlignment; + final Message? parent; + final int? initialScrollIndex; + final double? initialAlignment; ThreadPage({ - Key key, + Key? key, this.parent, this.initialScrollIndex, this.initialAlignment, @@ -958,7 +958,7 @@ class ThreadPage extends StatefulWidget { } class _ThreadPageState extends State { - Message _quotedMessage; + Message? _quotedMessage; FocusNode _focusNode = FocusNode(); @override @@ -969,7 +969,7 @@ class _ThreadPageState extends State { void _reply(Message message) { setState(() => _quotedMessage = message); - WidgetsBinding.instance.addPostFrameCallback((timeStamp) { + WidgetsBinding.instance!.addPostFrameCallback((timeStamp) { _focusNode.requestFocus(); }); } @@ -979,7 +979,7 @@ class _ThreadPageState extends State { return Scaffold( backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, appBar: ThreadHeader( - parent: widget.parent, + parent: widget.parent!, ), body: Column( children: [ @@ -992,7 +992,7 @@ class _ThreadPageState extends State { onReplyTap: _reply, ), ), - if (widget.parent.type != 'deleted') + if (widget.parent!.type != 'deleted') MessageInput( parentMessage: widget.parent, focusNode: _focusNode, @@ -1017,8 +1017,8 @@ class InitData { class HolePainter extends CustomPainter { HolePainter({ - @required this.color, - @required this.holeSize, + required this.color, + required this.holeSize, }); Color color; diff --git a/stream_chat_v1/lib/new_chat_screen.dart b/stream_chat_v1/lib/new_chat_screen.dart index fac0ed0745..2213db4976 100644 --- a/stream_chat_v1/lib/new_chat_screen.dart +++ b/stream_chat_v1/lib/new_chat_screen.dart @@ -16,9 +16,9 @@ class _NewChatScreenState extends State { final _chipInputTextFieldStateKey = GlobalKey>(); - TextEditingController _controller; + late TextEditingController _controller; - ChipInputTextFieldState get _chipInputTextFieldState => + ChipInputTextFieldState? get _chipInputTextFieldState => _chipInputTextFieldStateKey.currentState; String _userNameQuery = ''; @@ -30,14 +30,14 @@ class _NewChatScreenState extends State { bool _isSearchActive = false; - Channel channel; + Channel? channel; - Timer _debounce; + Timer? _debounce; bool _showUserList = true; void _userNameListener() { - if (_debounce?.isActive ?? false) _debounce.cancel(); + if (_debounce?.isActive ?? false) _debounce!.cancel(); _debounce = Timer(const Duration(milliseconds: 350), () { if (mounted) setState(() { @@ -73,7 +73,7 @@ class _NewChatScreenState extends State { filter: Filter.and([ Filter.equal('members', [ ..._selectedUsers.map((e) => e.id), - chatState.user.id, + chatState.user!.id, ]), Filter.equal('distinct', true), ]), @@ -86,14 +86,14 @@ class _NewChatScreenState extends State { final _channelExisted = res.length == 1; if (_channelExisted) { channel = res.first; - await channel.watch(); + await channel!.watch(); } else { channel = chatState.client.channel( 'messaging', extraData: { 'members': [ ..._selectedUsers.map((e) => e.id), - chatState.user.id, + chatState.user!.id, ], }, ); @@ -110,9 +110,9 @@ class _NewChatScreenState extends State { void dispose() { _searchFocusNode.dispose(); _messageInputFocusNode.dispose(); - _controller?.clear(); - _controller?.removeListener(_userNameListener); - _controller?.dispose(); + _controller.clear(); + _controller.removeListener(_userNameListener); + _controller.dispose(); super.dispose(); } @@ -158,7 +158,7 @@ class _NewChatScreenState extends State { message: statusString, child: StreamChannel( showLoading: false, - channel: channel, + channel: channel!, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -169,7 +169,7 @@ class _NewChatScreenState extends State { chipBuilder: (context, user) { return GestureDetector( onTap: () { - _chipInputTextFieldState.removeItem(user); + _chipInputTextFieldState?.removeItem(user); _searchFocusNode.requestFocus(); }, child: Stack( @@ -299,10 +299,10 @@ class _NewChatScreenState extends State { _controller.clear(); if (!_selectedUsers.contains(user)) { _chipInputTextFieldState - ..addItem(user) + ?..addItem(user) ..pauseItemAddition(); } else { - _chipInputTextFieldState.removeItem(user); + _chipInputTextFieldState!.removeItem(user); } }, pagination: PaginationParams( @@ -312,7 +312,7 @@ class _NewChatScreenState extends State { if (_userNameQuery.isNotEmpty) Filter.autoComplete('name', _userNameQuery), Filter.notEqual( - 'id', StreamChat.of(context).user.id), + 'id', StreamChat.of(context).user!.id), ]), sort: [ SortOption( @@ -367,7 +367,7 @@ class _NewChatScreenState extends State { ), ) : FutureBuilder( - future: channel.initialized, + future: channel!.initialized, builder: (context, snapshot) { if (snapshot.data == true) { return MessageListView(); @@ -391,7 +391,7 @@ class _NewChatScreenState extends State { MessageInput( focusNode: _messageInputFocusNode, preMessageSending: (message) async { - await channel.watch(); + await channel!.watch(); return message; }, onMessageSent: (m) { diff --git a/stream_chat_v1/lib/new_group_chat_screen.dart b/stream_chat_v1/lib/new_group_chat_screen.dart index 9944572b85..0db780ee65 100644 --- a/stream_chat_v1/lib/new_group_chat_screen.dart +++ b/stream_chat_v1/lib/new_group_chat_screen.dart @@ -12,7 +12,7 @@ class NewGroupChatScreen extends StatefulWidget { } class _NewGroupChatScreenState extends State { - TextEditingController _controller; + TextEditingController? _controller; String _userNameQuery = ''; @@ -20,14 +20,14 @@ class _NewGroupChatScreenState extends State { bool _isSearchActive = false; - Timer _debounce; + Timer? _debounce; void _userNameListener() { - if (_debounce?.isActive ?? false) _debounce.cancel(); + if (_debounce?.isActive ?? false) _debounce!.cancel(); _debounce = Timer(const Duration(milliseconds: 350), () { if (mounted) { setState(() { - _userNameQuery = _controller.text; + _userNameQuery = _controller!.text; _isSearchActive = _userNameQuery.isNotEmpty; }); } @@ -80,7 +80,7 @@ class _NewGroupChatScreenState extends State { setState(() { _selectedUsers ..clear() - ..addAll(updatedList); + ..addAll(updatedList as Iterable); }); } }, @@ -247,7 +247,7 @@ class _NewGroupChatScreenState extends State { filter: Filter.and([ if (_userNameQuery.isNotEmpty) Filter.autoComplete('name', _userNameQuery), - Filter.notEqual('id', StreamChat.of(context).user.id), + Filter.notEqual('id', StreamChat.of(context).user!.id), ]), sort: [ SortOption( @@ -311,8 +311,8 @@ class _HeaderDelegate extends SliverPersistentHeaderDelegate { final double height; const _HeaderDelegate({ - @required this.child, - @required this.height, + required this.child, + required this.height, }); @override diff --git a/stream_chat_v1/lib/notifications_service.dart b/stream_chat_v1/lib/notifications_service.dart index c72ac19f7e..56f6ad7c7b 100644 --- a/stream_chat_v1/lib/notifications_service.dart +++ b/stream_chat_v1/lib/notifications_service.dart @@ -7,7 +7,7 @@ void showLocalNotification(Event event, String currentUserId) async { EventType.messageNew, EventType.notificationMessageNew, ].contains(event.type) || - event.user.id == currentUserId) { + event.user!.id == currentUserId) { return; } if (event.message == null) return; @@ -21,9 +21,9 @@ void showLocalNotification(Event event, String currentUserId) async { ); await flutterLocalNotificationsPlugin.initialize(initializationSettings); await flutterLocalNotificationsPlugin.show( - event.message.id.hashCode, - event.message.user.name, - event.message.text, + event.message!.id.hashCode, + event.message!.user!.name, + event.message!.text, NotificationDetails( android: AndroidNotificationDetails( 'message channel', diff --git a/stream_chat_v1/lib/routes/app_routes.dart b/stream_chat_v1/lib/routes/app_routes.dart index 1be8bf7b82..a8ce5832ea 100644 --- a/stream_chat_v1/lib/routes/app_routes.dart +++ b/stream_chat_v1/lib/routes/app_routes.dart @@ -12,7 +12,7 @@ import '../group_info_screen.dart'; class AppRoutes { /// Add entry for new route here - static Route generateRoute(RouteSettings settings) { + static Route? generateRoute(RouteSettings settings) { final args = settings.arguments; switch (settings.name) { case Routes.APP: @@ -44,7 +44,7 @@ class AppRoutes { builder: (_) { final arg = args as ChannelPageArgs; return StreamChannel( - channel: arg.channel, + channel: arg.channel!, initialMessageId: arg.initialMessage?.id, child: ChannelPage( highlightInitialMessage: arg.initialMessage != null, @@ -68,7 +68,7 @@ class AppRoutes { settings: const RouteSettings(name: Routes.NEW_GROUP_CHAT_DETAILS), builder: (_) { return GroupChatDetailsScreen( - selectedUsers: args, + selectedUsers: args as List?, ); }); case Routes.CHAT_INFO_SCREEN: @@ -76,7 +76,7 @@ class AppRoutes { settings: const RouteSettings(name: Routes.CHAT_INFO_SCREEN), builder: (context) { return ChatInfoScreen( - user: args, + user: args as User?, messageTheme: StreamChatTheme.of(context).ownMessageTheme, ); }); diff --git a/stream_chat_v1/lib/search_text_field.dart b/stream_chat_v1/lib/search_text_field.dart index 9628ddba94..c3850c2c44 100644 --- a/stream_chat_v1/lib/search_text_field.dart +++ b/stream_chat_v1/lib/search_text_field.dart @@ -2,15 +2,15 @@ import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; class SearchTextField extends StatelessWidget { - final TextEditingController controller; - final ValueChanged onChanged; + final TextEditingController? controller; + final ValueChanged? onChanged; final String hintText; - final VoidCallback onTap; + final VoidCallback? onTap; final bool showCloseButton; const SearchTextField({ - Key key, - @required this.controller, + Key? key, + required this.controller, this.onChanged, this.onTap, this.hintText = 'Search', @@ -76,11 +76,11 @@ class SearchTextField extends StatelessWidget { ), splashRadius: 24, onPressed: () { - if (controller.text.isNotEmpty) { + if (controller!.text.isNotEmpty) { Future.microtask( () => [ - controller.clear(), - if (onChanged != null) onChanged(''), + controller!.clear(), + if (onChanged != null) onChanged!(''), ], ); } diff --git a/stream_chat_v1/lib/stream_version.dart b/stream_chat_v1/lib/stream_version.dart index b3f926bea9..0458d759a1 100644 --- a/stream_chat_v1/lib/stream_version.dart +++ b/stream_chat_v1/lib/stream_version.dart @@ -5,7 +5,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; class StreamVersion extends StatelessWidget { const StreamVersion({ - Key key, + Key? key, }) : super(key: key); @override @@ -20,7 +20,7 @@ class StreamVersion extends StatelessWidget { return SizedBox(); } - final pubspec = snapshot.data; + final pubspec = snapshot.data!; final yaml = loadYaml(pubspec); final streamChatDep = yaml['packages']['stream_chat_flutter']['version']; diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index 464d2353ad..9f1f30db3a 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -4,7 +4,7 @@ publish_to: 'none' version: 1.5.4+1 environment: - sdk: ">=2.2.2 <3.0.0" + sdk: '>=2.12.0 <3.0.0' dependencies: flutter_app_badger: ^1.2.0 @@ -27,6 +27,7 @@ dependencies: uuid: ^3.0.4 streaming_shared_preferences: ^2.0.0 lottie: ^1.0.1 + collection: ^1.15.0-nullsafety.4 dependency_overrides: stream_chat: From c5737efed5fd96a1af5eda3d1deb1eb9fd09f883 Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Mon, 17 May 2021 14:40:50 +0530 Subject: [PATCH 028/172] removed deprecated uses, fmt --- stream_chat_v1/lib/advanced_options_page.dart | 24 ++++++++++++------- stream_chat_v1/lib/chat_info_screen.dart | 3 ++- .../lib/group_chat_details_screen.dart | 2 +- stream_chat_v1/lib/stream_version.dart | 2 +- 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/stream_chat_v1/lib/advanced_options_page.dart b/stream_chat_v1/lib/advanced_options_page.dart index b4a4326336..29fe27070d 100644 --- a/stream_chat_v1/lib/advanced_options_page.dart +++ b/stream_chat_v1/lib/advanced_options_page.dart @@ -221,14 +221,22 @@ class _AdvancedOptionsPageState extends State { ), ), Spacer(), - RaisedButton( - color: Theme.of(context).brightness == Brightness.light - ? StreamChatTheme.of(context).colorTheme.accentBlue - : Colors.white, - elevation: 0, - padding: const EdgeInsets.symmetric(vertical: 16), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(26), + ElevatedButton( + style: ButtonStyle( + backgroundColor: MaterialStateProperty.all( + Theme.of(context).brightness == Brightness.light + ? StreamChatTheme.of(context) + .colorTheme + .accentBlue + : Colors.white), + elevation: MaterialStateProperty.all(0), + padding: MaterialStateProperty.all( + const EdgeInsets.symmetric(vertical: 16)), + shape: MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(26), + ), + ), ), child: Text( 'Login', diff --git a/stream_chat_v1/lib/chat_info_screen.dart b/stream_chat_v1/lib/chat_info_screen.dart index 8a09f4374c..2ba2839258 100644 --- a/stream_chat_v1/lib/chat_info_screen.dart +++ b/stream_chat_v1/lib/chat_info_screen.dart @@ -56,7 +56,8 @@ class _ChatInfoScreenState extends State { 'admin', 'owner', ].contains(channel.state!.members - .firstWhereOrNull((m) => m.userId == channel.client.state.user!.id) + .firstWhereOrNull( + (m) => m.userId == channel.client.state.user!.id) ?.role)) _buildDeleteListTile(), ], diff --git a/stream_chat_v1/lib/group_chat_details_screen.dart b/stream_chat_v1/lib/group_chat_details_screen.dart index 1819fe8cc9..a1a92b83ed 100644 --- a/stream_chat_v1/lib/group_chat_details_screen.dart +++ b/stream_chat_v1/lib/group_chat_details_screen.dart @@ -306,7 +306,7 @@ class _GroupChatDetailsScreenState extends State { Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - FlatButton( + TextButton( child: Text( 'OK', style: StreamChatTheme.of(context) diff --git a/stream_chat_v1/lib/stream_version.dart b/stream_chat_v1/lib/stream_version.dart index 0458d759a1..740181390d 100644 --- a/stream_chat_v1/lib/stream_version.dart +++ b/stream_chat_v1/lib/stream_version.dart @@ -26,7 +26,7 @@ class StreamVersion extends StatelessWidget { yaml['packages']['stream_chat_flutter']['version']; return Text( - 'Stream SDK v ${streamChatDep}', + 'Stream SDK v $streamChatDep', style: TextStyle( fontSize: 14, color: StreamChatTheme.of(context).colorTheme.greyGainsboro, From 371ea32edb09cd7ba877e9b33cdee2af1b3e62dd Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 17 May 2021 13:56:28 +0200 Subject: [PATCH 029/172] fix new chat filter --- stream_chat_v1/lib/new_chat_screen.dart | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/stream_chat_v1/lib/new_chat_screen.dart b/stream_chat_v1/lib/new_chat_screen.dart index 2213db4976..d708b00a96 100644 --- a/stream_chat_v1/lib/new_chat_screen.dart +++ b/stream_chat_v1/lib/new_chat_screen.dart @@ -70,13 +70,13 @@ class _NewChatScreenState extends State { 'state': false, 'watch': false, }, - filter: Filter.and([ - Filter.equal('members', [ + filter: Filter.raw(value: { + 'members': [ ..._selectedUsers.map((e) => e.id), chatState.user!.id, - ]), - Filter.equal('distinct', true), - ]), + ], + 'distinct': true, + }), messageLimit: 0, paginationParams: PaginationParams( limit: 1, From 04afa39ad2f0e28b40e637a02169108047356d42 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 17 May 2021 15:23:06 +0200 Subject: [PATCH 030/172] fix mentions filter --- stream_chat_v1/lib/main.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stream_chat_v1/lib/main.dart b/stream_chat_v1/lib/main.dart index 8b982e4ef5..ecd995785a 100644 --- a/stream_chat_v1/lib/main.dart +++ b/stream_chat_v1/lib/main.dart @@ -58,7 +58,7 @@ class _MyAppState extends State with TickerProviderStateMixin { final client = StreamChatClient( apiKey ?? kDefaultStreamApiKey, - logLevel: Level.SEVERE, + logLevel: Level.INFO, )..chatPersistenceClient = chatPersistentClient; if (userId != null) { @@ -501,7 +501,7 @@ class UserMentionPage extends StatelessWidget { child: MessageSearchListView( filters: Filter.in_('members', [user.id]), messageFilters: Filter.custom( - operator: 'contains', + operator: r'$contains', key: 'mentioned_users.id', value: user.id, ), From e89965dd3b52f6ab87c6952992f7598c67a23e11 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 20 May 2021 14:40:35 +0200 Subject: [PATCH 031/172] add modal before removing member and remove make owner (not yet in backend) --- stream_chat_v1/lib/group_info_screen.dart | 41 ++++++++++++++--------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/group_info_screen.dart index 00e396688e..76938fb6b2 100644 --- a/stream_chat_v1/lib/group_info_screen.dart +++ b/stream_chat_v1/lib/group_info_screen.dart @@ -670,8 +670,9 @@ class _GroupInfoScreenState extends State { Filter.autoComplete('name', _userNameQuery), Filter.notIn('id', [ StreamChat.of(context).user!.id, - ...channel.state!.members.map(((e) => e.userId!) - as Object Function(Member)), + ...channel.state!.members + .map(((e) => e.userId)) + .whereType(), ]), ], ), @@ -893,18 +894,18 @@ class _GroupInfoScreenState extends State { ); }, ), - if (!channel.isDistinct && - StreamChat.of(context).user!.id != user.id && - isUserAdmin) - _buildModalListTile( - context, - StreamSvgIcon.iconUserSettings( - color: StreamChatTheme.of(context).colorTheme.grey, - size: 24.0, - ), - 'Make Owner', () { - // TODO: Add make owner implementation (Remaining from backend) - }), + // if (!channel.isDistinct && + // StreamChat.of(context).user!.id != user.id && + // isUserAdmin) + // _buildModalListTile( + // context, + // StreamSvgIcon.iconUserSettings( + // color: StreamChatTheme.of(context).colorTheme.grey, + // size: 24.0, + // ), + // 'Make Owner', () { + // // TODO: Add make owner implementation (Remaining from backend) + // }), if (!channel.isDistinct && StreamChat.of(context).user!.id != user.id && isUserAdmin) @@ -915,7 +916,17 @@ class _GroupInfoScreenState extends State { size: 24.0, ), 'Remove From Group', () async { - await channel.removeMembers([user.id]); + final res = await showConfirmationDialog( + context, + title: 'Remove member', + okText: 'REMOVE', + question: 'Are you sure you want to remove this member?', + cancelText: 'CANCEL', + ); + + if (res == true) { + await channel.removeMembers([user.id]); + } Navigator.pop(context); }, color: StreamChatTheme.of(context).colorTheme.accentRed), _buildModalListTile( From 6271b425d6f7a275910a4b95d7f237e578bdf924 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 20 May 2021 15:33:01 +0200 Subject: [PATCH 032/172] fix modal adding safearea --- stream_chat_v1/lib/group_info_screen.dart | 254 +++++++++++----------- 1 file changed, 130 insertions(+), 124 deletions(-) diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/group_info_screen.dart index 76938fb6b2..3e964b27be 100644 --- a/stream_chat_v1/lib/group_info_screen.dart +++ b/stream_chat_v1/lib/group_info_screen.dart @@ -787,158 +787,164 @@ class _GroupInfoScreenState extends State { void _showUserInfoModal(User? user, bool isUserAdmin) { var channel = StreamChannel.of(context).channel; + final color = StreamChatTheme.of(context).colorTheme.white; showModalBottomSheet( context: context, clipBehavior: Clip.antiAlias, isScrollControlled: true, + backgroundColor: color, builder: (context) { - return StreamChannel( - channel: channel, - child: Material( - color: StreamChatTheme.of(context).colorTheme.white, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - SizedBox( - height: 24.0, - ), - Center( - child: Text( - user!.name, - style: TextStyle( - fontSize: 16.0, - fontWeight: FontWeight.bold, - ), + return SafeArea( + child: StreamChannel( + channel: channel, + child: Material( + color: color, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + height: 24.0, ), - ), - SizedBox( - height: 5.0, - ), - _buildConnectedTitleState(user)!, - Center( - child: Padding( - padding: const EdgeInsets.all(16.0), - child: UserAvatar( - user: user, - constraints: BoxConstraints( - maxHeight: 64.0, - minHeight: 64.0, + Center( + child: Text( + user!.name, + style: TextStyle( + fontSize: 16.0, + fontWeight: FontWeight.bold, ), - borderRadius: BorderRadius.circular(32.0), ), ), - ), - if (StreamChat.of(context).user!.id != user.id) - _buildModalListTile( - context, - StreamSvgIcon.user( - color: StreamChatTheme.of(context).colorTheme.grey, - size: 24.0, + SizedBox( + height: 5.0, + ), + _buildConnectedTitleState(user)!, + Center( + child: Padding( + padding: const EdgeInsets.all(16.0), + child: UserAvatar( + user: user, + constraints: BoxConstraints( + maxHeight: 64.0, + minHeight: 64.0, + ), + borderRadius: BorderRadius.circular(32.0), + ), ), - 'View info', - () async { - var client = StreamChat.of(context).client; + ), + if (StreamChat.of(context).user!.id != user.id) + _buildModalListTile( + context, + StreamSvgIcon.user( + color: StreamChatTheme.of(context).colorTheme.grey, + size: 24.0, + ), + 'View info', + () async { + var client = StreamChat.of(context).client; - var c = client.channel('messaging', extraData: { - 'members': [ - user.id, - StreamChat.of(context).user!.id, - ], - }); + var c = client.channel('messaging', extraData: { + 'members': [ + user.id, + StreamChat.of(context).user!.id, + ], + }); - await c.watch(); + await c.watch(); - await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => StreamChannel( - channel: c, - child: ChatInfoScreen( - messageTheme: widget.messageTheme, - user: user, + await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => StreamChannel( + channel: c, + child: ChatInfoScreen( + messageTheme: widget.messageTheme, + user: user, + ), ), ), - ), - ); - }, - ), - if (StreamChat.of(context).user!.id != user.id) - _buildModalListTile( - context, - StreamSvgIcon.message( - color: StreamChatTheme.of(context).colorTheme.grey, - size: 24.0, + ); + }, ), - 'Message', - () async { - var client = StreamChat.of(context).client; + if (StreamChat.of(context).user!.id != user.id) + _buildModalListTile( + context, + StreamSvgIcon.message( + color: StreamChatTheme.of(context).colorTheme.grey, + size: 24.0, + ), + 'Message', + () async { + var client = StreamChat.of(context).client; - var c = client.channel('messaging', extraData: { - 'members': [ - user.id, - StreamChat.of(context).user!.id, - ], - }); + var c = client.channel('messaging', extraData: { + 'members': [ + user.id, + StreamChat.of(context).user!.id, + ], + }); - await c.watch(); + await c.watch(); - await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => StreamChannel( - channel: c, - child: ChannelPage(), + await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => StreamChannel( + channel: c, + child: ChannelPage(), + ), ), + ); + }, + ), + // if (!channel.isDistinct && + // StreamChat.of(context).user!.id != user.id && + // isUserAdmin) + // _buildModalListTile( + // context, + // StreamSvgIcon.iconUserSettings( + // color: StreamChatTheme.of(context).colorTheme.grey, + // size: 24.0, + // ), + // 'Make Owner', () { + // // TODO: Add make owner implementation (Remaining from backend) + // }), + if (!channel.isDistinct && + StreamChat.of(context).user!.id != user.id && + isUserAdmin) + _buildModalListTile( + context, + StreamSvgIcon.userRemove( + color: + StreamChatTheme.of(context).colorTheme.accentRed, + size: 24.0, ), + 'Remove From Group', () async { + final res = await showConfirmationDialog( + context, + title: 'Remove member', + okText: 'REMOVE', + question: + 'Are you sure you want to remove this member?', + cancelText: 'CANCEL', ); - }, - ), - // if (!channel.isDistinct && - // StreamChat.of(context).user!.id != user.id && - // isUserAdmin) - // _buildModalListTile( - // context, - // StreamSvgIcon.iconUserSettings( - // color: StreamChatTheme.of(context).colorTheme.grey, - // size: 24.0, - // ), - // 'Make Owner', () { - // // TODO: Add make owner implementation (Remaining from backend) - // }), - if (!channel.isDistinct && - StreamChat.of(context).user!.id != user.id && - isUserAdmin) + + if (res == true) { + await channel.removeMembers([user.id]); + } + Navigator.pop(context); + }, color: StreamChatTheme.of(context).colorTheme.accentRed), _buildModalListTile( context, - StreamSvgIcon.userRemove( - color: StreamChatTheme.of(context).colorTheme.accentRed, + StreamSvgIcon.closeSmall( + color: StreamChatTheme.of(context).colorTheme.grey, size: 24.0, ), - 'Remove From Group', () async { - final res = await showConfirmationDialog( - context, - title: 'Remove member', - okText: 'REMOVE', - question: 'Are you sure you want to remove this member?', - cancelText: 'CANCEL', - ); - - if (res == true) { - await channel.removeMembers([user.id]); - } + 'Cancel', () { Navigator.pop(context); - }, color: StreamChatTheme.of(context).colorTheme.accentRed), - _buildModalListTile( - context, - StreamSvgIcon.closeSmall( - color: StreamChatTheme.of(context).colorTheme.grey, - size: 24.0, - ), - 'Cancel', () { - Navigator.pop(context); - }), - ], + }), + ], + ), ), ), ); From 7dcb3244fe5e57f866477d1751547a006fd6ab1b Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Fri, 28 May 2021 20:17:59 +0530 Subject: [PATCH 033/172] feat: Added pinned message screen. TODO: Add new logo --- stream_chat_v1/lib/chat_info_screen.dart | 60 +++++ stream_chat_v1/lib/group_info_screen.dart | 60 +++++ .../lib/pinned_messages_screen.dart | 232 ++++++++++++++++++ 3 files changed, 352 insertions(+) create mode 100644 stream_chat_v1/lib/pinned_messages_screen.dart diff --git a/stream_chat_v1/lib/chat_info_screen.dart b/stream_chat_v1/lib/chat_info_screen.dart index 2ba2839258..1974e94dfc 100644 --- a/stream_chat_v1/lib/chat_info_screen.dart +++ b/stream_chat_v1/lib/chat_info_screen.dart @@ -6,6 +6,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'channel_file_display_screen.dart'; import 'channel_media_display_screen.dart'; +import 'pinned_messages_screen.dart'; import 'main.dart'; import 'routes/routes.dart'; @@ -199,6 +200,65 @@ class _ChatInfoScreenState extends State { // ), // onTap: () {}, // ), + OptionListTile( + title: 'Pinned Messages', + tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + titleTextStyle: StreamChatTheme.of(context).textTheme.body, + leading: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: StreamSvgIcon.pictures( + size: 36.0, + color: + StreamChatTheme.of(context).colorTheme.black.withOpacity(0.5), + ), + ), + trailing: StreamSvgIcon.right( + color: StreamChatTheme.of(context).colorTheme.grey, + ), + onTap: () { + final channel = StreamChannel.of(context).channel; + + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => StreamChannel( + channel: channel, + child: MessageSearchBloc( + child: PinnedMessagesScreen( + messageTheme: widget.messageTheme, + sortOptions: [ + SortOption( + 'created_at', + direction: SortOption.ASC, + ), + ], + paginationParams: PaginationParams(limit: 20), + onShowMessage: (m, c) async { + final client = StreamChat.of(context).client; + final message = m; + final channel = client.channel( + c.type, + id: c.id, + ); + if (channel.state == null) { + await channel.watch(); + } + Navigator.pushNamed( + context, + Routes.CHANNEL_PAGE, + arguments: ChannelPageArgs( + channel: channel, + initialMessage: message, + ), + ); + }, + ), + ), + ), + ), + ); + }, + ), OptionListTile( title: 'Photos & Videos', tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow, diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/group_info_screen.dart index 3e964b27be..18db05b3fc 100644 --- a/stream_chat_v1/lib/group_info_screen.dart +++ b/stream_chat_v1/lib/group_info_screen.dart @@ -10,6 +10,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'channel_file_display_screen.dart'; import 'channel_media_display_screen.dart'; +import 'pinned_messages_screen.dart'; import 'chat_info_screen.dart'; import 'main.dart'; import 'routes/routes.dart'; @@ -482,6 +483,65 @@ class _GroupInfoScreenState extends State { onTap: () {}, ); }), + OptionListTile( + title: 'Pinned Messages', + tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + titleTextStyle: StreamChatTheme.of(context).textTheme.body, + leading: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: StreamSvgIcon.pictures( + size: 32.0, + color: + StreamChatTheme.of(context).colorTheme.black.withOpacity(0.5), + ), + ), + trailing: StreamSvgIcon.right( + color: StreamChatTheme.of(context).colorTheme.grey, + ), + onTap: () { + final channel = StreamChannel.of(context).channel; + + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => StreamChannel( + channel: channel, + child: MessageSearchBloc( + child: PinnedMessagesScreen( + messageTheme: widget.messageTheme, + sortOptions: [ + SortOption( + 'created_at', + direction: SortOption.ASC, + ), + ], + paginationParams: PaginationParams(limit: 20), + onShowMessage: (m, c) async { + final client = StreamChat.of(context).client; + final message = m; + final channel = client.channel( + c.type, + id: c.id, + ); + if (channel.state == null) { + await channel.watch(); + } + Navigator.pushNamed( + context, + Routes.CHANNEL_PAGE, + arguments: ChannelPageArgs( + channel: channel, + initialMessage: message, + ), + ); + }, + ), + ), + ), + ), + ); + }, + ), OptionListTile( tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow, separatorColor: StreamChatTheme.of(context).colorTheme.greyGainsboro, diff --git a/stream_chat_v1/lib/pinned_messages_screen.dart b/stream_chat_v1/lib/pinned_messages_screen.dart new file mode 100644 index 0000000000..5f8174b729 --- /dev/null +++ b/stream_chat_v1/lib/pinned_messages_screen.dart @@ -0,0 +1,232 @@ +import 'package:flutter/material.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; +import 'package:video_player/video_player.dart'; + +class PinnedMessagesScreen extends StatefulWidget { + /// The sorting used for the channels matching the filters. + /// Sorting is based on field and direction, multiple sorting options can be provided. + /// You can sort based on last_updated, last_message_at, updated_at, created_at or member_count. + /// Direction can be ascending or descending. + final List? sortOptions; + + /// Pagination parameters + /// limit: the number of users to return (max is 30) + /// offset: the offset (max is 1000) + /// message_limit: how many messages should be included to each channel + final PaginationParams? paginationParams; + + /// The builder used when the file list is empty. + final WidgetBuilder? emptyBuilder; + + final ShowMessageCallback? onShowMessage; + + final MessageTheme messageTheme; + + const PinnedMessagesScreen({ + required this.messageTheme, + this.sortOptions, + this.paginationParams, + this.emptyBuilder, + this.onShowMessage, + }); + + @override + _PinnedMessagesScreenState createState() => _PinnedMessagesScreenState(); +} + +class _PinnedMessagesScreenState extends State { + Map controllerCache = {}; + + @override + void initState() { + super.initState(); + final messageSearchBloc = MessageSearchBloc.of(context); + messageSearchBloc.search( + filter: Filter.in_( + 'cid', + [StreamChannel.of(context).channel.cid!], + ), + messageFilter: Filter.equal( + 'pinned', + true, + ), + sort: widget.sortOptions, + pagination: widget.paginationParams, + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: StreamChatTheme.of(context).colorTheme.white, + appBar: AppBar( + brightness: Theme.of(context).brightness, + elevation: 1, + centerTitle: true, + title: Text( + 'Pinned Messages', + style: TextStyle( + color: StreamChatTheme.of(context).colorTheme.black, + fontSize: 16.0, + ), + ), + leading: Center( + child: InkWell( + onTap: () { + Navigator.of(context).pop(); + }, + child: Container( + width: 24.0, + height: 24.0, + child: StreamSvgIcon.left( + color: StreamChatTheme.of(context).colorTheme.black, + size: 24.0, + ), + ), + ), + ), + backgroundColor: StreamChatTheme.of(context).colorTheme.white, + ), + body: _buildMediaGrid(), + ); + } + + Widget _buildMediaGrid() { + final messageSearchBloc = MessageSearchBloc.of(context); + + return StreamBuilder>( + builder: (context, snapshot) { + if (snapshot.data == null) { + return Center( + child: const CircularProgressIndicator(), + ); + } + + if (snapshot.data!.isEmpty) { + if (widget.emptyBuilder != null) { + return widget.emptyBuilder!(context); + } + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + StreamSvgIcon.message( + size: 136.0, + color: StreamChatTheme.of(context).colorTheme.greyGainsboro, + ), + SizedBox(height: 16.0), + Text( + 'No pinned items', + style: TextStyle( + fontSize: 17.0, + color: StreamChatTheme.of(context).colorTheme.black, + fontWeight: FontWeight.bold, + ), + ), + SizedBox(height: 8.0), + RichText( + textAlign: TextAlign.center, + text: TextSpan(children: [ + TextSpan( + text: 'Long-press an important message and\nchoose ', + style: TextStyle( + fontSize: 14.0, + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(0.5), + ), + ), + TextSpan( + text: 'Pin to conversation', + style: TextStyle( + fontSize: 14.0, + fontWeight: FontWeight.bold, + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(0.5), + ), + ), + ]), + ), + ], + ), + ); + } + + var data = snapshot.data ?? []; + + return LazyLoadScrollView( + onEndOfPage: () => messageSearchBloc.search( + filter: Filter.in_( + 'cid', + [StreamChannel.of(context).channel.cid!], + ), + messageFilter: Filter.equal( + 'pinned', + true, + ), + sort: widget.sortOptions, + pagination: widget.paginationParams!.copyWith( + offset: messageSearchBloc.messageResponses?.length ?? 0, + ), + ), + child: ListView.builder( + itemBuilder: (context, position) { + var user = data[position].message.user!; + var attachments = data[position].message.attachments; + var text = data[position].message.text ?? ''; + + return ListTile( + leading: UserAvatar( + user: user, + constraints: BoxConstraints( + maxWidth: 56.0, + minHeight: 56.0, + ), + borderRadius: BorderRadius.circular(28), + ), + title: Text( + user.name, + style: TextStyle( + color: StreamChatTheme.of(context).colorTheme.black, + fontWeight: FontWeight.bold), + ), + subtitle: Text( + text != '' + ? text + : (attachments.isNotEmpty + ? '${attachments.length} attachment${attachments.length > 1 ? 's' : ''}' + : ''), + ), + onTap: () { + widget.onShowMessage?.call(data[position].message, + StreamChannel.of(context).channel); + }, + ); + }, + itemCount: snapshot.data!.length, + ), + ); + }, + stream: messageSearchBloc.messagesStream, + ); + } + + @override + void dispose() { + super.dispose(); + for (var c in controllerCache.values) { + c!.dispose(); + } + } +} + +class _AssetPackage { + Attachment attachment; + Message message; + VideoPlayerController? videoPlayer; + + _AssetPackage(this.attachment, this.message, this.videoPlayer); +} From 99160d07011162308c0d0e9c8f6503f6e32ab791 Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Fri, 28 May 2021 20:20:12 +0530 Subject: [PATCH 034/172] rfac: remove asset package --- stream_chat_v1/lib/pinned_messages_screen.dart | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/stream_chat_v1/lib/pinned_messages_screen.dart b/stream_chat_v1/lib/pinned_messages_screen.dart index 5f8174b729..c6ef9a2631 100644 --- a/stream_chat_v1/lib/pinned_messages_screen.dart +++ b/stream_chat_v1/lib/pinned_messages_screen.dart @@ -221,12 +221,4 @@ class _PinnedMessagesScreenState extends State { c!.dispose(); } } -} - -class _AssetPackage { - Attachment attachment; - Message message; - VideoPlayerController? videoPlayer; - - _AssetPackage(this.attachment, this.message, this.videoPlayer); -} +} \ No newline at end of file From c1ad6eb2d22b9fd67182687840a8dace33811b64 Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Fri, 11 Jun 2021 13:49:08 +0530 Subject: [PATCH 035/172] fix: changed pin logo --- stream_chat_v1/lib/pinned_messages_screen.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stream_chat_v1/lib/pinned_messages_screen.dart b/stream_chat_v1/lib/pinned_messages_screen.dart index c6ef9a2631..acfdb2db16 100644 --- a/stream_chat_v1/lib/pinned_messages_screen.dart +++ b/stream_chat_v1/lib/pinned_messages_screen.dart @@ -110,7 +110,7 @@ class _PinnedMessagesScreenState extends State { child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - StreamSvgIcon.message( + StreamSvgIcon.pin( size: 136.0, color: StreamChatTheme.of(context).colorTheme.greyGainsboro, ), From efca2a7c2c7892202c0fa0c899813ab4100525cc Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Fri, 11 Jun 2021 13:52:36 +0530 Subject: [PATCH 036/172] fix: changed pin logo --- stream_chat_v1/lib/chat_info_screen.dart | 2 +- stream_chat_v1/lib/group_info_screen.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/stream_chat_v1/lib/chat_info_screen.dart b/stream_chat_v1/lib/chat_info_screen.dart index 1974e94dfc..b0d18d99a4 100644 --- a/stream_chat_v1/lib/chat_info_screen.dart +++ b/stream_chat_v1/lib/chat_info_screen.dart @@ -206,7 +206,7 @@ class _ChatInfoScreenState extends State { titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: StreamSvgIcon.pictures( + child: StreamSvgIcon.pin( size: 36.0, color: StreamChatTheme.of(context).colorTheme.black.withOpacity(0.5), diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/group_info_screen.dart index 18db05b3fc..dda7eb8076 100644 --- a/stream_chat_v1/lib/group_info_screen.dart +++ b/stream_chat_v1/lib/group_info_screen.dart @@ -489,7 +489,7 @@ class _GroupInfoScreenState extends State { titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( padding: const EdgeInsets.symmetric(horizontal: 12.0), - child: StreamSvgIcon.pictures( + child: StreamSvgIcon.pin( size: 32.0, color: StreamChatTheme.of(context).colorTheme.black.withOpacity(0.5), From 7b5c7cf729c1c2a07289dbb3c0cb4ad01970c347 Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Fri, 11 Jun 2021 16:24:50 +0530 Subject: [PATCH 037/172] fix: icon sizes --- stream_chat_v1/lib/chat_info_screen.dart | 4 ++-- stream_chat_v1/lib/group_info_screen.dart | 4 ++-- stream_chat_v1/lib/pinned_messages_screen.dart | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/stream_chat_v1/lib/chat_info_screen.dart b/stream_chat_v1/lib/chat_info_screen.dart index b0d18d99a4..eca16bb84a 100644 --- a/stream_chat_v1/lib/chat_info_screen.dart +++ b/stream_chat_v1/lib/chat_info_screen.dart @@ -205,9 +205,9 @@ class _ChatInfoScreenState extends State { tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow, titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), + padding: const EdgeInsets.symmetric(horizontal: 22.0), child: StreamSvgIcon.pin( - size: 36.0, + size: 24.0, color: StreamChatTheme.of(context).colorTheme.black.withOpacity(0.5), ), diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/group_info_screen.dart index dda7eb8076..6c4575780a 100644 --- a/stream_chat_v1/lib/group_info_screen.dart +++ b/stream_chat_v1/lib/group_info_screen.dart @@ -488,9 +488,9 @@ class _GroupInfoScreenState extends State { tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow, titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( - padding: const EdgeInsets.symmetric(horizontal: 12.0), + padding: const EdgeInsets.symmetric(horizontal: 16.0), child: StreamSvgIcon.pin( - size: 32.0, + size: 24.0, color: StreamChatTheme.of(context).colorTheme.black.withOpacity(0.5), ), diff --git a/stream_chat_v1/lib/pinned_messages_screen.dart b/stream_chat_v1/lib/pinned_messages_screen.dart index acfdb2db16..82dd532d02 100644 --- a/stream_chat_v1/lib/pinned_messages_screen.dart +++ b/stream_chat_v1/lib/pinned_messages_screen.dart @@ -182,8 +182,8 @@ class _PinnedMessagesScreenState extends State { leading: UserAvatar( user: user, constraints: BoxConstraints( - maxWidth: 56.0, - minHeight: 56.0, + maxWidth: 40.0, + minHeight: 40.0, ), borderRadius: BorderRadius.circular(28), ), @@ -221,4 +221,4 @@ class _PinnedMessagesScreenState extends State { c!.dispose(); } } -} \ No newline at end of file +} From b55d8f86afdcba6e37ade93b1b4f3848c669f594 Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Fri, 11 Jun 2021 16:29:43 +0530 Subject: [PATCH 038/172] fix: Added pin permissions --- stream_chat_v1/lib/main.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stream_chat_v1/lib/main.dart b/stream_chat_v1/lib/main.dart index ecd995785a..c4d16b115c 100644 --- a/stream_chat_v1/lib/main.dart +++ b/stream_chat_v1/lib/main.dart @@ -898,6 +898,7 @@ class _ChannelPageState extends State { ), ); }, + pinPermissions: ['owner', 'admin', 'member'], ), Positioned( bottom: 0, @@ -990,6 +991,7 @@ class _ThreadPageState extends State { initialAlignment: widget.initialAlignment, onMessageSwiped: _reply, onReplyTap: _reply, + pinPermissions: ['owner', 'admin', 'member'], ), ), if (widget.parent!.type != 'deleted') From b91270d8d69a016df91c8e80f54c1b218b391e7f Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 11 Jun 2021 16:06:01 +0200 Subject: [PATCH 039/172] Update pubspec.yaml --- stream_chat_v1/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index 9f1f30db3a..69062833c9 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -1,7 +1,7 @@ name: example description: A new Flutter project. publish_to: 'none' -version: 1.5.4+1 +version: 1.6.0 environment: sdk: '>=2.12.0 <3.0.0' From c9887e099c4e5562a3127fbd63f408acc27d1b84 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 18 Jun 2021 11:59:31 +0200 Subject: [PATCH 040/172] add web build with production config to nightly --- stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj index ccb925f581..417fb0bdeb 100644 --- a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj +++ b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj @@ -245,8 +245,10 @@ "${BUILT_PRODUCTS_DIR}/DKImagePickerController/DKImagePickerController.framework", "${BUILT_PRODUCTS_DIR}/DKPhotoGallery/DKPhotoGallery.framework", "${BUILT_PRODUCTS_DIR}/FMDB/FMDB.framework", + "${BUILT_PRODUCTS_DIR}/Reachability/Reachability.framework", "${BUILT_PRODUCTS_DIR}/SDWebImage/SDWebImage.framework", "${BUILT_PRODUCTS_DIR}/SwiftyGif/SwiftyGif.framework", + "${BUILT_PRODUCTS_DIR}/connectivity_plus/connectivity_plus.framework", "${BUILT_PRODUCTS_DIR}/file_picker/file_picker.framework", "${BUILT_PRODUCTS_DIR}/flutter_app_badger/flutter_app_badger.framework", "${BUILT_PRODUCTS_DIR}/flutter_keyboard_visibility/flutter_keyboard_visibility.framework", @@ -273,8 +275,10 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DKImagePickerController.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DKPhotoGallery.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FMDB.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Reachability.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImage.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftyGif.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/connectivity_plus.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/file_picker.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_app_badger.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_keyboard_visibility.framework", From a4855de97dd117a7f95022b2d3b5e2e5732fc3ba Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 18 Jun 2021 12:16:26 +0200 Subject: [PATCH 041/172] build canvas kit --- stream_chat_v1/pubspec.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index 69062833c9..3e1f7caeb6 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -44,7 +44,8 @@ dependency_overrides: dev_dependencies: flutter_launcher_icons: ^0.9.0 test: any - + build_runner: ^2.0.4 + build_web_compilers: ^3.0.0 flutter: assets: - assets/ From 138f5b7f93e7c5d26cd4bece15934ae45bf54417 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 18 Jun 2021 12:54:39 +0200 Subject: [PATCH 042/172] try different action --- stream_chat_v1/pubspec.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index 3e1f7caeb6..59ce3062cc 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -44,8 +44,6 @@ dependency_overrides: dev_dependencies: flutter_launcher_icons: ^0.9.0 test: any - build_runner: ^2.0.4 - build_web_compilers: ^3.0.0 flutter: assets: - assets/ From bd14ebea8ff1e9ede6e61457d5bc4a11723af23c Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 21 Jun 2021 20:34:34 +0200 Subject: [PATCH 043/172] align with main repo --- stream_chat_v1/lib/advanced_options_page.dart | 4 ++-- stream_chat_v1/lib/chat_info_screen.dart | 6 +++--- stream_chat_v1/lib/choose_user_page.dart | 2 +- stream_chat_v1/lib/group_info_screen.dart | 11 ++++++----- stream_chat_v1/lib/main.dart | 13 +++++-------- stream_chat_v1/lib/new_chat_screen.dart | 6 ++---- stream_chat_v1/pubspec.yaml | 8 ++++---- 7 files changed, 23 insertions(+), 27 deletions(-) diff --git a/stream_chat_v1/lib/advanced_options_page.dart b/stream_chat_v1/lib/advanced_options_page.dart index 29fe27070d..3882580d9d 100644 --- a/stream_chat_v1/lib/advanced_options_page.dart +++ b/stream_chat_v1/lib/advanced_options_page.dart @@ -306,7 +306,7 @@ class _AdvancedOptionsPageState extends State { key: kStreamToken, value: userToken, ); - await client.disconnect(); + client.closeConnection(); } catch (e) { var errorText = 'Error connecting, retry'; if (e is Map) { @@ -317,7 +317,7 @@ class _AdvancedOptionsPageState extends State { _apiKeyError = errorText.toUpperCase(); }); loading = false; - await client.disconnect(); + client.closeConnection(); return; } loading = false; diff --git a/stream_chat_v1/lib/chat_info_screen.dart b/stream_chat_v1/lib/chat_info_screen.dart index eca16bb84a..0fbd4ea761 100644 --- a/stream_chat_v1/lib/chat_info_screen.dart +++ b/stream_chat_v1/lib/chat_info_screen.dart @@ -6,8 +6,8 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'channel_file_display_screen.dart'; import 'channel_media_display_screen.dart'; -import 'pinned_messages_screen.dart'; import 'main.dart'; +import 'pinned_messages_screen.dart'; import 'routes/routes.dart'; /// Detail screen for a 1:1 chat correspondence @@ -615,7 +615,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { title = 'No title'; } } else { - title = extraData['name']; + title = extraData['name'] as String; } return Column( @@ -633,7 +633,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { ), Expanded( child: Text( - title!, + title, style: textStyle, )), Padding( diff --git a/stream_chat_v1/lib/choose_user_page.dart b/stream_chat_v1/lib/choose_user_page.dart index a6dd5e1ca4..7c882e3877 100644 --- a/stream_chat_v1/lib/choose_user_page.dart +++ b/stream_chat_v1/lib/choose_user_page.dart @@ -90,7 +90,7 @@ class ChooseUserPage extends StatelessWidget { ); final client = StreamChat.of(context).client; - client.apiKey = kDefaultStreamApiKey; + // client.apiKey = kDefaultStreamApiKey; await client.connectUser( user, token, diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/group_info_screen.dart index 6c4575780a..5ec1ec2069 100644 --- a/stream_chat_v1/lib/group_info_screen.dart +++ b/stream_chat_v1/lib/group_info_screen.dart @@ -10,9 +10,9 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'channel_file_display_screen.dart'; import 'channel_media_display_screen.dart'; -import 'pinned_messages_screen.dart'; import 'chat_info_screen.dart'; import 'main.dart'; +import 'pinned_messages_screen.dart'; import 'routes/routes.dart'; class GroupInfoScreen extends StatefulWidget { @@ -61,7 +61,9 @@ class _GroupInfoScreenState extends State { super.initState(); var channel = StreamChannel.of(context); _nameController = TextEditingController.fromValue( - TextEditingValue(text: channel.channel.extraData['name'] ?? '')); + TextEditingValue( + text: (channel.channel.extraData['name'] as String?) ?? ''), + ); _searchController = TextEditingController()..addListener(_userNameListener); _nameController!.addListener(() { @@ -333,7 +335,7 @@ class _GroupInfoScreenState extends State { Widget _buildNameTile() { var channel = StreamChannel.of(context).channel; - var channelName = channel.extraData['name'] ?? ''; + var channelName = (channel.extraData['name'] as String?) ?? ''; return Material( color: StreamChatTheme.of(context).colorTheme.whiteSnow, @@ -377,8 +379,7 @@ class _GroupInfoScreenState extends State { ), ), ), - if ((channelName == null) || - (channelName != _nameController!.text.trim())) + if (channelName != _nameController!.text.trim()) Row( mainAxisSize: MainAxisSize.min, children: [ diff --git a/stream_chat_v1/lib/main.dart b/stream_chat_v1/lib/main.dart index c4d16b115c..b0a0327ed0 100644 --- a/stream_chat_v1/lib/main.dart +++ b/stream_chat_v1/lib/main.dart @@ -61,7 +61,7 @@ class _MyAppState extends State with TickerProviderStateMixin { logLevel: Level.INFO, )..chatPersistenceClient = chatPersistentClient; - if (userId != null) { + if (userId != null && token != null) { await client.connectUser( User(id: userId), token, @@ -148,7 +148,7 @@ class _MyAppState extends State with TickerProviderStateMixin { if (!kIsWeb) { _initData!.client.state.totalUnreadCountStream.listen((count) { - if (count! > 0) { + if (count > 0) { FlutterAppBadger.updateBadgeCount(count); } else { FlutterAppBadger.removeBadge(); @@ -235,6 +235,7 @@ class _MyAppState extends State with TickerProviderStateMixin { builder: (context, snapshot) => MaterialApp( builder: (context, child) { return StreamChat( + backgroundKeepAlive: Duration(seconds: 5), client: _initData!.client, onBackgroundEventReceived: (e) => showLocalNotification( e, _initData!.client.state.user!.id), @@ -445,9 +446,7 @@ class _HomePageState extends State { await secureStorage.deleteAll(); } - StreamChat.of(context).client.disconnect( - clearUser: true, - ); + StreamChat.of(context).client.disconnectUser(); await Navigator.pushReplacementNamed( context, @@ -714,9 +713,7 @@ class _ChannelListPageState extends State { }, swipeToAction: true, filter: Filter.in_('members', [user!.id]), - options: { - 'presence': true, - }, + presence: true, pagination: PaginationParams( limit: 20, ), diff --git a/stream_chat_v1/lib/new_chat_screen.dart b/stream_chat_v1/lib/new_chat_screen.dart index d708b00a96..e70c492ecf 100644 --- a/stream_chat_v1/lib/new_chat_screen.dart +++ b/stream_chat_v1/lib/new_chat_screen.dart @@ -66,10 +66,8 @@ class _NewChatScreenState extends State { final chatState = StreamChat.of(context); final res = await chatState.client.queryChannelsOnline( - options: { - 'state': false, - 'watch': false, - }, + state: false, + watch: false, filter: Filter.raw(value: { 'members': [ ..._selectedUsers.map((e) => e.id), diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index 59ce3062cc..9c82d91b04 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -13,12 +13,12 @@ dependencies: stream_chat_flutter: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop + ref: ref/segregate-api-layer path: packages/stream_chat_flutter stream_chat_persistence: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop + ref: ref/segregate-api-layer path: packages/stream_chat_persistence flutter_local_notifications: ^5.0.0+4 flutter_svg: ^0.22.0 @@ -33,12 +33,12 @@ dependency_overrides: stream_chat: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop + ref: ref/segregate-api-layer path: packages/stream_chat stream_chat_flutter_core: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop + ref: ref/segregate-api-layer path: packages/stream_chat_flutter_core dev_dependencies: From 704fa848944357bc4e99be08d0cb443dd01b4592 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 21 Jun 2021 20:38:43 +0200 Subject: [PATCH 044/172] extract main.dart widgets --- stream_chat_v1/lib/channel_list_page.dart | 199 +++++ stream_chat_v1/lib/channel_page.dart | 183 +++++ stream_chat_v1/lib/chat_info_screen.dart | 2 +- .../lib/group_chat_details_screen.dart | 2 +- stream_chat_v1/lib/group_info_screen.dart | 2 +- stream_chat_v1/lib/home_page.dart | 241 ++++++ stream_chat_v1/lib/main.dart | 738 ------------------ stream_chat_v1/lib/new_chat_screen.dart | 2 +- stream_chat_v1/lib/routes/app_routes.dart | 26 +- stream_chat_v1/lib/thread_page.dart | 70 ++ stream_chat_v1/lib/user_mentions_page.dart | 88 +++ 11 files changed, 800 insertions(+), 753 deletions(-) create mode 100644 stream_chat_v1/lib/channel_list_page.dart create mode 100644 stream_chat_v1/lib/channel_page.dart create mode 100644 stream_chat_v1/lib/home_page.dart create mode 100644 stream_chat_v1/lib/thread_page.dart create mode 100644 stream_chat_v1/lib/user_mentions_page.dart diff --git a/stream_chat_v1/lib/channel_list_page.dart b/stream_chat_v1/lib/channel_list_page.dart new file mode 100644 index 0000000000..c6529d5022 --- /dev/null +++ b/stream_chat_v1/lib/channel_list_page.dart @@ -0,0 +1,199 @@ +import 'dart:async'; + +import 'package:example/routes/routes.dart'; +import 'package:example/search_text_field.dart'; +import 'package:flutter/material.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; + +import 'channel_page.dart'; +import 'chat_info_screen.dart'; +import 'group_info_screen.dart'; + +class ChannelListPage extends StatefulWidget { + @override + _ChannelListPageState createState() => _ChannelListPageState(); +} + +class _ChannelListPageState extends State { + TextEditingController? _controller; + + String _channelQuery = ''; + + bool _isSearchActive = false; + + Timer? _debounce; + + void _channelQueryListener() { + if (_debounce?.isActive ?? false) _debounce!.cancel(); + _debounce = Timer(const Duration(milliseconds: 350), () { + if (mounted) { + setState(() { + _channelQuery = _controller!.text; + _isSearchActive = _channelQuery.isNotEmpty; + }); + } + }); + } + + @override + void initState() { + super.initState(); + _controller = TextEditingController()..addListener(_channelQueryListener); + } + + @override + void dispose() { + _controller?.removeListener(_channelQueryListener); + _controller?.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final user = StreamChat.of(context).user; + return WillPopScope( + onWillPop: () async { + if (_isSearchActive) { + _controller!.clear(); + setState(() => _isSearchActive = false); + return false; + } + return true; + }, + child: ChannelsBloc( + child: MessageSearchBloc( + child: NestedScrollView( + floatHeaderSlivers: true, + headerSliverBuilder: (_, __) => [ + SliverToBoxAdapter( + child: SearchTextField( + controller: _controller, + showCloseButton: _isSearchActive, + ), + ), + ], + body: AnimatedSwitcher( + duration: const Duration(milliseconds: 350), + child: GestureDetector( + behavior: HitTestBehavior.opaque, + onPanDown: (_) => FocusScope.of(context).unfocus(), + child: _isSearchActive + ? MessageSearchListView( + showErrorTile: true, + messageQuery: _channelQuery, + filters: Filter.in_('members', [user!.id]), + sortOptions: [ + SortOption( + 'created_at', + direction: SortOption.ASC, + ), + ], + pullToRefresh: false, + paginationParams: PaginationParams(limit: 20), + emptyBuilder: (_) { + return LayoutBuilder( + builder: (context, viewportConstraints) { + return SingleChildScrollView( + physics: AlwaysScrollableScrollPhysics(), + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: viewportConstraints.maxHeight, + ), + child: Center( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(24), + child: StreamSvgIcon.search( + size: 96, + color: Colors.grey, + ), + ), + Text( + 'No results...', + ), + ], + ), + ), + ), + ); + }, + ); + }, + onItemTap: (messageResponse) async { + FocusScope.of(context).requestFocus(FocusNode()); + final client = StreamChat.of(context).client; + final message = messageResponse.message; + final channel = client.channel( + messageResponse.channel!.type, + id: messageResponse.channel!.id, + ); + if (channel.state == null) { + await channel.watch(); + } + Navigator.pushNamed( + context, + Routes.CHANNEL_PAGE, + arguments: ChannelPageArgs( + channel: channel, + initialMessage: message, + ), + ); + }, + ) + : ChannelListView( + onStartChatPressed: () { + Navigator.pushNamed(context, Routes.NEW_CHAT); + }, + swipeToAction: true, + filter: Filter.in_('members', [user!.id]), + presence: true, + pagination: PaginationParams( + limit: 20, + ), + channelWidget: ChannelPage(), + onViewInfoTap: (channel) { + Navigator.pop(context); + if (channel.memberCount == 2 && channel.isDistinct) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => StreamChannel( + channel: channel, + child: ChatInfoScreen( + messageTheme: StreamChatTheme.of(context) + .ownMessageTheme, + user: channel.state!.members + .where((m) => + m.userId != + channel.client.state.user!.id) + .first + .user, + ), + ), + ), + ); + } else { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => StreamChannel( + channel: channel, + child: GroupInfoScreen( + messageTheme: StreamChatTheme.of(context) + .ownMessageTheme, + ), + ), + ), + ); + } + }, + ), + ), + ), + ), + ), + ), + ); + } +} diff --git a/stream_chat_v1/lib/channel_page.dart b/stream_chat_v1/lib/channel_page.dart new file mode 100644 index 0000000000..1ff592cb2d --- /dev/null +++ b/stream_chat_v1/lib/channel_page.dart @@ -0,0 +1,183 @@ +import 'package:collection/collection.dart'; +import 'package:example/routes/routes.dart'; +import 'package:example/thread_page.dart'; +import 'package:flutter/material.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; + +import 'chat_info_screen.dart'; +import 'group_info_screen.dart'; + +class ChannelPageArgs { + final Channel? channel; + final Message? initialMessage; + + const ChannelPageArgs({ + this.channel, + this.initialMessage, + }); +} + +class ChannelPage extends StatefulWidget { + final int? initialScrollIndex; + final double? initialAlignment; + final bool highlightInitialMessage; + + const ChannelPage({ + Key? key, + this.initialScrollIndex, + this.initialAlignment, + this.highlightInitialMessage = false, + }) : super(key: key); + + @override + _ChannelPageState createState() => _ChannelPageState(); +} + +class _ChannelPageState extends State { + Message? _quotedMessage; + FocusNode? _focusNode; + + @override + void initState() { + _focusNode = FocusNode(); + super.initState(); + } + + @override + void dispose() { + _focusNode!.dispose(); + super.dispose(); + } + + void _reply(Message message) { + setState(() => _quotedMessage = message); + WidgetsBinding.instance!.addPostFrameCallback((timeStamp) { + _focusNode!.requestFocus(); + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + appBar: ChannelHeader( + showTypingIndicator: false, + onImageTap: () async { + var channel = StreamChannel.of(context).channel; + + if (channel.memberCount == 2 && channel.isDistinct) { + final currentUser = StreamChat.of(context).user; + final otherUser = channel.state!.members.firstWhereOrNull( + (element) => element.user!.id != currentUser!.id, + ); + if (otherUser != null) { + final pop = await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => StreamChannel( + child: ChatInfoScreen( + messageTheme: StreamChatTheme.of(context).ownMessageTheme, + user: otherUser.user, + ), + channel: channel, + ), + ), + ); + + if (pop == true) { + Navigator.pop(context); + } + } + } else { + await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => StreamChannel( + child: GroupInfoScreen( + messageTheme: StreamChatTheme.of(context).ownMessageTheme, + ), + channel: channel, + ), + ), + ); + } + }, + ), + body: Column( + children: [ + Expanded( + child: Stack( + children: [ + MessageListView( + initialScrollIndex: widget.initialScrollIndex, + initialAlignment: widget.initialAlignment, + highlightInitialMessage: widget.highlightInitialMessage, + onMessageSwiped: _reply, + onReplyTap: _reply, + threadBuilder: (_, parentMessage) { + return ThreadPage( + parent: parentMessage, + ); + }, + onShowMessage: (m, c) async { + final client = StreamChat.of(context).client; + final message = m; + final channel = client.channel( + c.type, + id: c.id, + ); + if (channel.state == null) { + await channel.watch(); + } + Navigator.pushReplacementNamed( + context, + Routes.CHANNEL_PAGE, + arguments: ChannelPageArgs( + channel: channel, + initialMessage: message, + ), + ); + }, + pinPermissions: ['owner', 'admin', 'member'], + ), + Positioned( + bottom: 0, + left: 0, + right: 0, + child: Container( + alignment: Alignment.centerLeft, + color: StreamChatTheme.of(context) + .colorTheme + .whiteSnow + .withOpacity(.9), + child: TypingIndicator( + alignment: Alignment.centerLeft, + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 4, + ), + style: StreamChatTheme.of(context) + .textTheme + .footnote + .copyWith( + color: + StreamChatTheme.of(context).colorTheme.grey), + ), + ), + ), + ], + ), + ), + MessageInput( + focusNode: _focusNode, + quotedMessage: _quotedMessage, + onQuotedMessageCleared: () { + setState(() => _quotedMessage = null); + _focusNode!.unfocus(); + }, + ), + ], + ), + ); + } +} diff --git a/stream_chat_v1/lib/chat_info_screen.dart b/stream_chat_v1/lib/chat_info_screen.dart index 0fbd4ea761..6517ef3609 100644 --- a/stream_chat_v1/lib/chat_info_screen.dart +++ b/stream_chat_v1/lib/chat_info_screen.dart @@ -6,7 +6,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'channel_file_display_screen.dart'; import 'channel_media_display_screen.dart'; -import 'main.dart'; +import 'channel_page.dart'; import 'pinned_messages_screen.dart'; import 'routes/routes.dart'; diff --git a/stream_chat_v1/lib/group_chat_details_screen.dart b/stream_chat_v1/lib/group_chat_details_screen.dart index a1a92b83ed..c59f74439e 100644 --- a/stream_chat_v1/lib/group_chat_details_screen.dart +++ b/stream_chat_v1/lib/group_chat_details_screen.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:uuid/uuid.dart'; -import 'main.dart'; +import 'channel_page.dart'; import 'routes/routes.dart'; class GroupChatDetailsScreen extends StatefulWidget { diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/group_info_screen.dart index 5ec1ec2069..1d9572eecb 100644 --- a/stream_chat_v1/lib/group_info_screen.dart +++ b/stream_chat_v1/lib/group_info_screen.dart @@ -10,8 +10,8 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'channel_file_display_screen.dart'; import 'channel_media_display_screen.dart'; +import 'channel_page.dart'; import 'chat_info_screen.dart'; -import 'main.dart'; import 'pinned_messages_screen.dart'; import 'routes/routes.dart'; diff --git a/stream_chat_v1/lib/home_page.dart b/stream_chat_v1/lib/home_page.dart new file mode 100644 index 0000000000..af5f68d863 --- /dev/null +++ b/stream_chat_v1/lib/home_page.dart @@ -0,0 +1,241 @@ +import 'package:example/routes/routes.dart'; +import 'package:example/user_mentions_page.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; +import 'package:streaming_shared_preferences/streaming_shared_preferences.dart'; + +import 'channel_list_page.dart'; + +class HomePage extends StatefulWidget { + @override + _HomePageState createState() => _HomePageState(); +} + +class _HomePageState extends State { + int _currentIndex = 0; + + bool _isSelected(int index) => _currentIndex == index; + + List get _navBarItems { + return [ + BottomNavigationBarItem( + icon: Stack( + clipBehavior: Clip.none, + children: [ + StreamSvgIcon.message( + color: _isSelected(0) + ? StreamChatTheme.of(context).colorTheme.black + : Colors.grey, + ), + Positioned( + top: -3, + right: -16, + child: UnreadIndicator(), + ), + ], + ), + label: 'Chats', + ), + BottomNavigationBarItem( + icon: Stack( + clipBehavior: Clip.none, + children: [ + StreamSvgIcon.mentions( + color: _isSelected(1) + ? StreamChatTheme.of(context).colorTheme.black + : Colors.grey, + ), + ], + ), + label: 'Mentions', + ), + ]; + } + + @override + Widget build(BuildContext context) { + final user = StreamChat.of(context).user!; + return Scaffold( + backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + appBar: ChannelListHeader( + onNewChatButtonTap: () { + Navigator.pushNamed(context, Routes.NEW_CHAT); + }, + preNavigationCallback: () { + FocusScope.of(context).requestFocus(FocusNode()); + }, + ), + drawer: LeftDrawer( + user: user, + ), + drawerEdgeDragWidth: 50, + bottomNavigationBar: BottomNavigationBar( + backgroundColor: StreamChatTheme.of(context).colorTheme.white, + currentIndex: _currentIndex, + items: _navBarItems, + selectedLabelStyle: StreamChatTheme.of(context).textTheme.footnoteBold, + unselectedLabelStyle: + StreamChatTheme.of(context).textTheme.footnoteBold, + type: BottomNavigationBarType.fixed, + selectedItemColor: StreamChatTheme.of(context).colorTheme.black, + unselectedItemColor: Colors.grey, + onTap: (index) { + setState(() => _currentIndex = index); + }, + ), + body: IndexedStack( + index: _currentIndex, + children: [ + ChannelListPage(), + UserMentionsPage(), + ], + ), + ); + } +} + +class LeftDrawer extends StatelessWidget { + const LeftDrawer({ + Key? key, + required this.user, + }) : super(key: key); + + final User user; + + @override + Widget build(BuildContext context) { + return Drawer( + child: Container( + color: StreamChatTheme.of(context).colorTheme.white, + child: SafeArea( + child: Padding( + padding: EdgeInsets.only( + top: MediaQuery.of(context).viewPadding.top + 8, + ), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.only( + bottom: 20.0, + left: 8, + ), + child: Row( + children: [ + UserAvatar( + user: user, + showOnlineStatus: false, + constraints: BoxConstraints.tight(Size.fromRadius(20)), + ), + Padding( + padding: const EdgeInsets.only(left: 16.0), + child: Text( + user.name, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + ), + ListTile( + leading: StreamSvgIcon.penWrite( + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(.5), + ), + onTap: () { + Navigator.popAndPushNamed( + context, + Routes.NEW_CHAT, + ); + }, + title: Text( + 'New direct message', + style: TextStyle( + fontSize: 14.5, + ), + ), + ), + ListTile( + leading: StreamSvgIcon.contacts( + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(.5), + ), + onTap: () { + Navigator.popAndPushNamed( + context, + Routes.NEW_GROUP_CHAT, + ); + }, + title: Text( + 'New group', + style: TextStyle( + fontSize: 14.5, + ), + ), + ), + Expanded( + child: Container( + alignment: Alignment.bottomCenter, + child: ListTile( + onTap: () async { + Navigator.pop(context); + + if (!kIsWeb) { + final secureStorage = FlutterSecureStorage(); + await secureStorage.deleteAll(); + } + + StreamChat.of(context).client.disconnectUser(); + + await Navigator.pushNamedAndRemoveUntil( + context, + Routes.APP, + ModalRoute.withName(Routes.APP), + ); + }, + leading: StreamSvgIcon.user( + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(.5), + ), + title: Text( + 'Sign out', + style: TextStyle( + fontSize: 14.5, + ), + ), + trailing: IconButton( + icon: StreamSvgIcon.iconMoon( + size: 24, + ), + color: StreamChatTheme.of(context).colorTheme.grey, + onPressed: () async { + final sp = await StreamingSharedPreferences.instance; + sp.setInt( + 'theme', + Theme.of(context).brightness == Brightness.dark + ? 1 + : -1, + ); + }, + ), + ), + ), + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/stream_chat_v1/lib/main.dart b/stream_chat_v1/lib/main.dart index b0a0327ed0..05af49cc3e 100644 --- a/stream_chat_v1/lib/main.dart +++ b/stream_chat_v1/lib/main.dart @@ -1,9 +1,6 @@ import 'dart:async'; -import 'package:collection/collection.dart' show IterableExtension; -import 'package:example/chat_info_screen.dart'; import 'package:example/choose_user_page.dart'; -import 'package:example/group_info_screen.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -20,7 +17,6 @@ import 'app_config.dart'; import 'notifications_service.dart'; import 'routes/app_routes.dart'; import 'routes/routes.dart'; -import 'search_text_field.dart'; final chatPersistentClient = StreamChatPersistenceClient( logLevel: Level.SEVERE, @@ -273,740 +269,6 @@ class _MyAppState extends State with TickerProviderStateMixin { } } -class HomePage extends StatefulWidget { - @override - _HomePageState createState() => _HomePageState(); -} - -class _HomePageState extends State { - int _currentIndex = 0; - - bool _isSelected(int index) => _currentIndex == index; - - List get _navBarItems { - return [ - BottomNavigationBarItem( - icon: Stack( - clipBehavior: Clip.none, - children: [ - StreamSvgIcon.message( - color: _isSelected(0) - ? StreamChatTheme.of(context).colorTheme.black - : Colors.grey, - ), - Positioned( - top: -3, - right: -16, - child: UnreadIndicator(), - ), - ], - ), - label: 'Chats', - ), - BottomNavigationBarItem( - icon: Stack( - clipBehavior: Clip.none, - children: [ - StreamSvgIcon.mentions( - color: _isSelected(1) - ? StreamChatTheme.of(context).colorTheme.black - : Colors.grey, - ), - ], - ), - label: 'Mentions', - ), - ]; - } - - @override - Widget build(BuildContext context) { - final user = StreamChat.of(context).user!; - return Scaffold( - backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, - appBar: ChannelListHeader( - onNewChatButtonTap: () { - Navigator.pushNamed(context, Routes.NEW_CHAT); - }, - preNavigationCallback: () { - FocusScope.of(context).requestFocus(FocusNode()); - }, - ), - drawer: _buildDrawer(context, user), - drawerEdgeDragWidth: 50, - bottomNavigationBar: BottomNavigationBar( - backgroundColor: StreamChatTheme.of(context).colorTheme.white, - currentIndex: _currentIndex, - items: _navBarItems, - selectedLabelStyle: StreamChatTheme.of(context).textTheme.footnoteBold, - unselectedLabelStyle: - StreamChatTheme.of(context).textTheme.footnoteBold, - type: BottomNavigationBarType.fixed, - selectedItemColor: StreamChatTheme.of(context).colorTheme.black, - unselectedItemColor: Colors.grey, - onTap: (index) { - setState(() => _currentIndex = index); - }, - ), - body: IndexedStack( - index: _currentIndex, - children: [ - ChannelListPage(), - UserMentionPage(), - ], - ), - ); - } - - Drawer _buildDrawer(BuildContext context, User user) { - return Drawer( - child: Container( - color: StreamChatTheme.of(context).colorTheme.white, - child: SafeArea( - child: Padding( - padding: EdgeInsets.only( - top: MediaQuery.of(context).viewPadding.top + 8, - ), - child: Column( - children: [ - Padding( - padding: const EdgeInsets.only( - bottom: 20.0, - left: 8, - ), - child: Row( - children: [ - UserAvatar( - user: user, - showOnlineStatus: false, - constraints: BoxConstraints.tight(Size.fromRadius(20)), - ), - Padding( - padding: const EdgeInsets.only(left: 16.0), - child: Text( - user.name, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - ), - ), - ), - ], - ), - ), - ListTile( - leading: StreamSvgIcon.penWrite( - color: StreamChatTheme.of(context) - .colorTheme - .black - .withOpacity(.5), - ), - onTap: () { - Navigator.popAndPushNamed( - context, - Routes.NEW_CHAT, - ); - }, - title: Text( - 'New direct message', - style: TextStyle( - fontSize: 14.5, - ), - ), - ), - ListTile( - leading: StreamSvgIcon.contacts( - color: StreamChatTheme.of(context) - .colorTheme - .black - .withOpacity(.5), - ), - onTap: () { - Navigator.popAndPushNamed( - context, - Routes.NEW_GROUP_CHAT, - ); - }, - title: Text( - 'New group', - style: TextStyle( - fontSize: 14.5, - ), - ), - ), - Expanded( - child: Container( - alignment: Alignment.bottomCenter, - child: ListTile( - onTap: () async { - Navigator.pop(context); - - if (!kIsWeb) { - final secureStorage = FlutterSecureStorage(); - await secureStorage.deleteAll(); - } - - StreamChat.of(context).client.disconnectUser(); - - await Navigator.pushReplacementNamed( - context, - Routes.CHOOSE_USER, - ); - }, - leading: StreamSvgIcon.user( - color: StreamChatTheme.of(context) - .colorTheme - .black - .withOpacity(.5), - ), - title: Text( - 'Sign out', - style: TextStyle( - fontSize: 14.5, - ), - ), - trailing: IconButton( - icon: StreamSvgIcon.iconMoon( - size: 24, - ), - color: StreamChatTheme.of(context).colorTheme.grey, - onPressed: () async { - final sp = await StreamingSharedPreferences.instance; - sp.setInt( - 'theme', - Theme.of(context).brightness == Brightness.dark - ? 1 - : -1, - ); - }, - ), - ), - ), - ), - ], - ), - ), - ), - ), - ); - } -} - -class UserMentionPage extends StatelessWidget { - @override - Widget build(BuildContext context) { - final user = StreamChat.of(context).user!; - return MessageSearchBloc( - child: MessageSearchListView( - filters: Filter.in_('members', [user.id]), - messageFilters: Filter.custom( - operator: r'$contains', - key: 'mentioned_users.id', - value: user.id, - ), - sortOptions: [ - SortOption( - 'created_at', - direction: SortOption.ASC, - ), - ], - paginationParams: PaginationParams(limit: 20), - showResultCount: false, - emptyBuilder: (_) { - return LayoutBuilder( - builder: (context, viewportConstraints) { - return SingleChildScrollView( - physics: AlwaysScrollableScrollPhysics(), - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: viewportConstraints.maxHeight, - ), - child: Center( - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(24), - child: StreamSvgIcon.mentions( - size: 96, - color: StreamChatTheme.of(context) - .colorTheme - .greyGainsboro, - ), - ), - Text( - 'No mentions exist yet...', - style: StreamChatTheme.of(context) - .textTheme - .body - .copyWith( - color: - StreamChatTheme.of(context).colorTheme.grey, - ), - ), - ], - ), - ), - ), - ); - }, - ); - }, - onItemTap: (messageResponse) async { - final client = StreamChat.of(context).client; - final message = messageResponse.message; - final channel = client.channel( - messageResponse.channel!.type, - id: messageResponse.channel!.id, - ); - if (channel.state == null) { - await channel.watch(); - } - Navigator.pushNamed( - context, - Routes.CHANNEL_PAGE, - arguments: ChannelPageArgs( - channel: channel, - initialMessage: message, - ), - ); - }, - ), - ); - } -} - -class ChannelListPage extends StatefulWidget { - @override - _ChannelListPageState createState() => _ChannelListPageState(); -} - -class _ChannelListPageState extends State { - TextEditingController? _controller; - - String _channelQuery = ''; - - bool _isSearchActive = false; - - Timer? _debounce; - - void _channelQueryListener() { - if (_debounce?.isActive ?? false) _debounce!.cancel(); - _debounce = Timer(const Duration(milliseconds: 350), () { - if (mounted) { - setState(() { - _channelQuery = _controller!.text; - _isSearchActive = _channelQuery.isNotEmpty; - }); - } - }); - } - - @override - void initState() { - super.initState(); - _controller = TextEditingController()..addListener(_channelQueryListener); - } - - @override - void dispose() { - _controller?.removeListener(_channelQueryListener); - _controller?.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - final user = StreamChat.of(context).user; - return WillPopScope( - onWillPop: () async { - if (_isSearchActive) { - _controller!.clear(); - setState(() => _isSearchActive = false); - return false; - } - return true; - }, - child: ChannelsBloc( - child: MessageSearchBloc( - child: NestedScrollView( - floatHeaderSlivers: true, - headerSliverBuilder: (_, __) => [ - SliverToBoxAdapter( - child: SearchTextField( - controller: _controller, - showCloseButton: _isSearchActive, - ), - ), - ], - body: AnimatedSwitcher( - duration: const Duration(milliseconds: 350), - child: GestureDetector( - behavior: HitTestBehavior.opaque, - onPanDown: (_) => FocusScope.of(context).unfocus(), - child: _isSearchActive - ? MessageSearchListView( - showErrorTile: true, - messageQuery: _channelQuery, - filters: Filter.in_('members', [user!.id]), - sortOptions: [ - SortOption( - 'created_at', - direction: SortOption.ASC, - ), - ], - pullToRefresh: false, - paginationParams: PaginationParams(limit: 20), - emptyBuilder: (_) { - return LayoutBuilder( - builder: (context, viewportConstraints) { - return SingleChildScrollView( - physics: AlwaysScrollableScrollPhysics(), - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: viewportConstraints.maxHeight, - ), - child: Center( - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(24), - child: StreamSvgIcon.search( - size: 96, - color: Colors.grey, - ), - ), - Text( - 'No results...', - ), - ], - ), - ), - ), - ); - }, - ); - }, - onItemTap: (messageResponse) async { - FocusScope.of(context).requestFocus(FocusNode()); - final client = StreamChat.of(context).client; - final message = messageResponse.message; - final channel = client.channel( - messageResponse.channel!.type, - id: messageResponse.channel!.id, - ); - if (channel.state == null) { - await channel.watch(); - } - Navigator.pushNamed( - context, - Routes.CHANNEL_PAGE, - arguments: ChannelPageArgs( - channel: channel, - initialMessage: message, - ), - ); - }, - ) - : ChannelListView( - onStartChatPressed: () { - Navigator.pushNamed(context, Routes.NEW_CHAT); - }, - swipeToAction: true, - filter: Filter.in_('members', [user!.id]), - presence: true, - pagination: PaginationParams( - limit: 20, - ), - channelWidget: ChannelPage(), - onViewInfoTap: (channel) { - Navigator.pop(context); - if (channel.memberCount == 2 && channel.isDistinct) { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => StreamChannel( - channel: channel, - child: ChatInfoScreen( - messageTheme: StreamChatTheme.of(context) - .ownMessageTheme, - user: channel.state!.members - .where((m) => - m.userId != - channel.client.state.user!.id) - .first - .user, - ), - ), - ), - ); - } else { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => StreamChannel( - channel: channel, - child: GroupInfoScreen( - messageTheme: StreamChatTheme.of(context) - .ownMessageTheme, - ), - ), - ), - ); - } - }, - ), - ), - ), - ), - ), - ), - ); - } -} - -class ChannelPageArgs { - final Channel? channel; - final Message? initialMessage; - - const ChannelPageArgs({ - this.channel, - this.initialMessage, - }); -} - -class ChannelPage extends StatefulWidget { - final int? initialScrollIndex; - final double? initialAlignment; - final bool highlightInitialMessage; - - const ChannelPage({ - Key? key, - this.initialScrollIndex, - this.initialAlignment, - this.highlightInitialMessage = false, - }) : super(key: key); - - @override - _ChannelPageState createState() => _ChannelPageState(); -} - -class _ChannelPageState extends State { - Message? _quotedMessage; - FocusNode? _focusNode; - - @override - void initState() { - _focusNode = FocusNode(); - super.initState(); - } - - @override - void dispose() { - _focusNode!.dispose(); - super.dispose(); - } - - void _reply(Message message) { - setState(() => _quotedMessage = message); - WidgetsBinding.instance!.addPostFrameCallback((timeStamp) { - _focusNode!.requestFocus(); - }); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, - appBar: ChannelHeader( - showTypingIndicator: false, - onImageTap: () async { - var channel = StreamChannel.of(context).channel; - - if (channel.memberCount == 2 && channel.isDistinct) { - final currentUser = StreamChat.of(context).user; - final otherUser = channel.state!.members.firstWhereOrNull( - (element) => element.user!.id != currentUser!.id, - ); - if (otherUser != null) { - final pop = await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => StreamChannel( - child: ChatInfoScreen( - messageTheme: StreamChatTheme.of(context).ownMessageTheme, - user: otherUser.user, - ), - channel: channel, - ), - ), - ); - - if (pop == true) { - Navigator.pop(context); - } - } - } else { - await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => StreamChannel( - child: GroupInfoScreen( - messageTheme: StreamChatTheme.of(context).ownMessageTheme, - ), - channel: channel, - ), - ), - ); - } - }, - ), - body: Column( - children: [ - Expanded( - child: Stack( - children: [ - MessageListView( - initialScrollIndex: widget.initialScrollIndex, - initialAlignment: widget.initialAlignment, - highlightInitialMessage: widget.highlightInitialMessage, - onMessageSwiped: _reply, - onReplyTap: _reply, - threadBuilder: (_, parentMessage) { - return ThreadPage( - parent: parentMessage, - ); - }, - onShowMessage: (m, c) async { - final client = StreamChat.of(context).client; - final message = m; - final channel = client.channel( - c.type, - id: c.id, - ); - if (channel.state == null) { - await channel.watch(); - } - Navigator.pushReplacementNamed( - context, - Routes.CHANNEL_PAGE, - arguments: ChannelPageArgs( - channel: channel, - initialMessage: message, - ), - ); - }, - pinPermissions: ['owner', 'admin', 'member'], - ), - Positioned( - bottom: 0, - left: 0, - right: 0, - child: Container( - alignment: Alignment.centerLeft, - color: StreamChatTheme.of(context) - .colorTheme - .whiteSnow - .withOpacity(.9), - child: TypingIndicator( - alignment: Alignment.centerLeft, - padding: const EdgeInsets.symmetric( - horizontal: 8, - vertical: 4, - ), - style: StreamChatTheme.of(context) - .textTheme - .footnote - .copyWith( - color: - StreamChatTheme.of(context).colorTheme.grey), - ), - ), - ), - ], - ), - ), - MessageInput( - focusNode: _focusNode, - quotedMessage: _quotedMessage, - onQuotedMessageCleared: () { - setState(() => _quotedMessage = null); - _focusNode!.unfocus(); - }, - ), - ], - ), - ); - } -} - -class ThreadPage extends StatefulWidget { - final Message? parent; - final int? initialScrollIndex; - final double? initialAlignment; - - ThreadPage({ - Key? key, - this.parent, - this.initialScrollIndex, - this.initialAlignment, - }) : super(key: key); - - @override - _ThreadPageState createState() => _ThreadPageState(); -} - -class _ThreadPageState extends State { - Message? _quotedMessage; - FocusNode _focusNode = FocusNode(); - - @override - void dispose() { - _focusNode.dispose(); - super.dispose(); - } - - void _reply(Message message) { - setState(() => _quotedMessage = message); - WidgetsBinding.instance!.addPostFrameCallback((timeStamp) { - _focusNode.requestFocus(); - }); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, - appBar: ThreadHeader( - parent: widget.parent!, - ), - body: Column( - children: [ - Expanded( - child: MessageListView( - parentMessage: widget.parent, - initialScrollIndex: widget.initialScrollIndex, - initialAlignment: widget.initialAlignment, - onMessageSwiped: _reply, - onReplyTap: _reply, - pinPermissions: ['owner', 'admin', 'member'], - ), - ), - if (widget.parent!.type != 'deleted') - MessageInput( - parentMessage: widget.parent, - focusNode: _focusNode, - quotedMessage: _quotedMessage, - onQuotedMessageCleared: () { - setState(() => _quotedMessage = null); - _focusNode.unfocus(); - }, - ), - ], - ), - ); - } -} - class InitData { final StreamChatClient client; final StreamingSharedPreferences preferences; diff --git a/stream_chat_v1/lib/new_chat_screen.dart b/stream_chat_v1/lib/new_chat_screen.dart index e70c492ecf..1d7f0246a2 100644 --- a/stream_chat_v1/lib/new_chat_screen.dart +++ b/stream_chat_v1/lib/new_chat_screen.dart @@ -3,8 +3,8 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; +import 'channel_page.dart'; import 'chips_input_text_field.dart'; -import 'main.dart'; import 'routes/routes.dart'; class NewChatScreen extends StatefulWidget { diff --git a/stream_chat_v1/lib/routes/app_routes.dart b/stream_chat_v1/lib/routes/app_routes.dart index a8ce5832ea..4bc157edf5 100644 --- a/stream_chat_v1/lib/routes/app_routes.dart +++ b/stream_chat_v1/lib/routes/app_routes.dart @@ -1,14 +1,17 @@ -import 'routes.dart'; import 'package:flutter/material.dart'; -import '../choose_user_page.dart'; -import '../advanced_options_page.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -import '../main.dart'; -import '../group_chat_details_screen.dart'; -import '../new_group_chat_screen.dart'; -import '../new_chat_screen.dart'; + +import '../advanced_options_page.dart'; +import '../channel_page.dart'; import '../chat_info_screen.dart'; +import '../choose_user_page.dart'; +import '../group_chat_details_screen.dart'; import '../group_info_screen.dart'; +import '../home_page.dart'; +import '../main.dart'; +import '../new_chat_screen.dart'; +import '../new_group_chat_screen.dart'; +import 'routes.dart'; class AppRoutes { /// Add entry for new route here @@ -42,12 +45,13 @@ class AppRoutes { return MaterialPageRoute( settings: const RouteSettings(name: Routes.CHANNEL_PAGE), builder: (_) { - final arg = args as ChannelPageArgs; + final channelPageArgs = args as ChannelPageArgs; return StreamChannel( - channel: arg.channel!, - initialMessageId: arg.initialMessage?.id, + channel: channelPageArgs.channel!, + initialMessageId: channelPageArgs.initialMessage?.id, child: ChannelPage( - highlightInitialMessage: arg.initialMessage != null, + highlightInitialMessage: + channelPageArgs.initialMessage != null, ), ); }); diff --git a/stream_chat_v1/lib/thread_page.dart b/stream_chat_v1/lib/thread_page.dart new file mode 100644 index 0000000000..b9799c7911 --- /dev/null +++ b/stream_chat_v1/lib/thread_page.dart @@ -0,0 +1,70 @@ +import 'package:flutter/material.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; + +class ThreadPage extends StatefulWidget { + final Message? parent; + final int? initialScrollIndex; + final double? initialAlignment; + + ThreadPage({ + Key? key, + this.parent, + this.initialScrollIndex, + this.initialAlignment, + }) : super(key: key); + + @override + _ThreadPageState createState() => _ThreadPageState(); +} + +class _ThreadPageState extends State { + Message? _quotedMessage; + FocusNode _focusNode = FocusNode(); + + @override + void dispose() { + _focusNode.dispose(); + super.dispose(); + } + + void _reply(Message message) { + setState(() => _quotedMessage = message); + WidgetsBinding.instance!.addPostFrameCallback((timeStamp) { + _focusNode.requestFocus(); + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + appBar: ThreadHeader( + parent: widget.parent!, + ), + body: Column( + children: [ + Expanded( + child: MessageListView( + parentMessage: widget.parent, + initialScrollIndex: widget.initialScrollIndex, + initialAlignment: widget.initialAlignment, + onMessageSwiped: _reply, + onReplyTap: _reply, + pinPermissions: ['owner', 'admin', 'member'], + ), + ), + if (widget.parent!.type != 'deleted') + MessageInput( + parentMessage: widget.parent, + focusNode: _focusNode, + quotedMessage: _quotedMessage, + onQuotedMessageCleared: () { + setState(() => _quotedMessage = null); + _focusNode.unfocus(); + }, + ), + ], + ), + ); + } +} diff --git a/stream_chat_v1/lib/user_mentions_page.dart b/stream_chat_v1/lib/user_mentions_page.dart new file mode 100644 index 0000000000..837aa19151 --- /dev/null +++ b/stream_chat_v1/lib/user_mentions_page.dart @@ -0,0 +1,88 @@ +import 'package:example/routes/routes.dart'; +import 'package:flutter/material.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; + +import 'channel_page.dart'; + +class UserMentionsPage extends StatelessWidget { + @override + Widget build(BuildContext context) { + final user = StreamChat.of(context).user!; + return MessageSearchBloc( + child: MessageSearchListView( + filters: Filter.in_('members', [user.id]), + messageFilters: Filter.custom( + operator: r'$contains', + key: 'mentioned_users.id', + value: user.id, + ), + sortOptions: [ + SortOption( + 'created_at', + direction: SortOption.ASC, + ), + ], + paginationParams: PaginationParams(limit: 20), + showResultCount: false, + emptyBuilder: (_) { + return LayoutBuilder( + builder: (context, viewportConstraints) { + return SingleChildScrollView( + physics: AlwaysScrollableScrollPhysics(), + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: viewportConstraints.maxHeight, + ), + child: Center( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(24), + child: StreamSvgIcon.mentions( + size: 96, + color: StreamChatTheme.of(context) + .colorTheme + .greyGainsboro, + ), + ), + Text( + 'No mentions exist yet...', + style: StreamChatTheme.of(context) + .textTheme + .body + .copyWith( + color: + StreamChatTheme.of(context).colorTheme.grey, + ), + ), + ], + ), + ), + ), + ); + }, + ); + }, + onItemTap: (messageResponse) async { + final client = StreamChat.of(context).client; + final message = messageResponse.message; + final channel = client.channel( + messageResponse.channel!.type, + id: messageResponse.channel!.id, + ); + if (channel.state == null) { + await channel.watch(); + } + Navigator.pushNamed( + context, + Routes.CHANNEL_PAGE, + arguments: ChannelPageArgs( + channel: channel, + initialMessage: message, + ), + ); + }, + ), + ); + } +} From a968d63e5cea629c89eea1606091b4586e5ffe25 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 22 Jun 2021 12:52:11 +0200 Subject: [PATCH 045/172] refactor home page --- stream_chat_v1/lib/advanced_options_page.dart | 9 +- stream_chat_v1/lib/channel_list.dart | 199 +++++++++ stream_chat_v1/lib/channel_list_page.dart | 398 +++++++++++------- .../lib/channel_media_display_screen.dart | 16 +- stream_chat_v1/lib/choose_user_page.dart | 10 +- stream_chat_v1/lib/home_page.dart | 236 +---------- stream_chat_v1/lib/main.dart | 240 ++--------- .../lib/pinned_messages_screen.dart | 16 +- stream_chat_v1/lib/routes/app_routes.dart | 12 +- stream_chat_v1/lib/routes/routes.dart | 1 + stream_chat_v1/lib/splash_screen.dart | 122 ++++++ stream_chat_v1/pubspec.yaml | 20 +- 12 files changed, 638 insertions(+), 641 deletions(-) create mode 100644 stream_chat_v1/lib/channel_list.dart create mode 100644 stream_chat_v1/lib/splash_screen.dart diff --git a/stream_chat_v1/lib/advanced_options_page.dart b/stream_chat_v1/lib/advanced_options_page.dart index 3882580d9d..4a97c68a77 100644 --- a/stream_chat_v1/lib/advanced_options_page.dart +++ b/stream_chat_v1/lib/advanced_options_page.dart @@ -1,3 +1,4 @@ +import 'package:example/home_page.dart'; import 'package:example/routes/routes.dart'; import 'package:example/stream_version.dart'; import 'package:flutter/material.dart'; @@ -306,7 +307,6 @@ class _AdvancedOptionsPageState extends State { key: kStreamToken, value: userToken, ); - client.closeConnection(); } catch (e) { var errorText = 'Error connecting, retry'; if (e is Map) { @@ -317,15 +317,14 @@ class _AdvancedOptionsPageState extends State { _apiKeyError = errorText.toUpperCase(); }); loading = false; - client.closeConnection(); return; } loading = false; await Navigator.pushNamedAndRemoveUntil( context, - Routes.APP, - ModalRoute.withName(Routes.APP), - arguments: client, + Routes.HOME, + ModalRoute.withName(Routes.HOME), + arguments: HomePageArgs(client), ); } }, diff --git a/stream_chat_v1/lib/channel_list.dart b/stream_chat_v1/lib/channel_list.dart new file mode 100644 index 0000000000..e88c9a1630 --- /dev/null +++ b/stream_chat_v1/lib/channel_list.dart @@ -0,0 +1,199 @@ +import 'dart:async'; + +import 'package:example/routes/routes.dart'; +import 'package:example/search_text_field.dart'; +import 'package:flutter/material.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; + +import 'channel_page.dart'; +import 'chat_info_screen.dart'; +import 'group_info_screen.dart'; + +class ChannelList extends StatefulWidget { + @override + _ChannelList createState() => _ChannelList(); +} + +class _ChannelList extends State { + TextEditingController? _controller; + + String _channelQuery = ''; + + bool _isSearchActive = false; + + Timer? _debounce; + + void _channelQueryListener() { + if (_debounce?.isActive ?? false) _debounce!.cancel(); + _debounce = Timer(const Duration(milliseconds: 350), () { + if (mounted) { + setState(() { + _channelQuery = _controller!.text; + _isSearchActive = _channelQuery.isNotEmpty; + }); + } + }); + } + + @override + void initState() { + super.initState(); + _controller = TextEditingController()..addListener(_channelQueryListener); + } + + @override + void dispose() { + _controller?.removeListener(_channelQueryListener); + _controller?.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final user = StreamChat.of(context).user; + return WillPopScope( + onWillPop: () async { + if (_isSearchActive) { + _controller!.clear(); + setState(() => _isSearchActive = false); + return false; + } + return true; + }, + child: ChannelsBloc( + child: MessageSearchBloc( + child: NestedScrollView( + floatHeaderSlivers: true, + headerSliverBuilder: (_, __) => [ + SliverToBoxAdapter( + child: SearchTextField( + controller: _controller, + showCloseButton: _isSearchActive, + ), + ), + ], + body: AnimatedSwitcher( + duration: const Duration(milliseconds: 350), + child: GestureDetector( + behavior: HitTestBehavior.opaque, + onPanDown: (_) => FocusScope.of(context).unfocus(), + child: _isSearchActive + ? MessageSearchListView( + showErrorTile: true, + messageQuery: _channelQuery, + filters: Filter.in_('members', [user!.id]), + sortOptions: [ + SortOption( + 'created_at', + direction: SortOption.ASC, + ), + ], + pullToRefresh: false, + paginationParams: PaginationParams(limit: 20), + emptyBuilder: (_) { + return LayoutBuilder( + builder: (context, viewportConstraints) { + return SingleChildScrollView( + physics: AlwaysScrollableScrollPhysics(), + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: viewportConstraints.maxHeight, + ), + child: Center( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(24), + child: StreamSvgIcon.search( + size: 96, + color: Colors.grey, + ), + ), + Text( + 'No results...', + ), + ], + ), + ), + ), + ); + }, + ); + }, + onItemTap: (messageResponse) async { + FocusScope.of(context).requestFocus(FocusNode()); + final client = StreamChat.of(context).client; + final message = messageResponse.message; + final channel = client.channel( + messageResponse.channel!.type, + id: messageResponse.channel!.id, + ); + if (channel.state == null) { + await channel.watch(); + } + Navigator.pushNamed( + context, + Routes.CHANNEL_PAGE, + arguments: ChannelPageArgs( + channel: channel, + initialMessage: message, + ), + ); + }, + ) + : ChannelListView( + onStartChatPressed: () { + Navigator.pushNamed(context, Routes.NEW_CHAT); + }, + swipeToAction: true, + filter: Filter.in_('members', [user!.id]), + presence: true, + pagination: PaginationParams( + limit: 20, + ), + channelWidget: ChannelPage(), + onViewInfoTap: (channel) { + Navigator.pop(context); + if (channel.memberCount == 2 && channel.isDistinct) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => StreamChannel( + channel: channel, + child: ChatInfoScreen( + messageTheme: StreamChatTheme.of(context) + .ownMessageTheme, + user: channel.state!.members + .where((m) => + m.userId != + channel.client.state.user!.id) + .first + .user, + ), + ), + ), + ); + } else { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => StreamChannel( + channel: channel, + child: GroupInfoScreen( + messageTheme: StreamChatTheme.of(context) + .ownMessageTheme, + ), + ), + ), + ); + } + }, + ), + ), + ), + ), + ), + ), + ); + } +} diff --git a/stream_chat_v1/lib/channel_list_page.dart b/stream_chat_v1/lib/channel_list_page.dart index c6529d5022..baf6ecac17 100644 --- a/stream_chat_v1/lib/channel_list_page.dart +++ b/stream_chat_v1/lib/channel_list_page.dart @@ -1,195 +1,277 @@ import 'dart:async'; import 'package:example/routes/routes.dart'; -import 'package:example/search_text_field.dart'; +import 'package:example/user_mentions_page.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_app_badger/flutter_app_badger.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; +import 'package:streaming_shared_preferences/streaming_shared_preferences.dart'; -import 'channel_page.dart'; -import 'chat_info_screen.dart'; -import 'group_info_screen.dart'; +import 'channel_list.dart'; class ChannelListPage extends StatefulWidget { + const ChannelListPage({ + Key? key, + }) : super(key: key); + @override _ChannelListPageState createState() => _ChannelListPageState(); } class _ChannelListPageState extends State { - TextEditingController? _controller; - - String _channelQuery = ''; + int _currentIndex = 0; - bool _isSearchActive = false; + bool _isSelected(int index) => _currentIndex == index; - Timer? _debounce; + List get _navBarItems { + return [ + BottomNavigationBarItem( + icon: Stack( + clipBehavior: Clip.none, + children: [ + StreamSvgIcon.message( + color: _isSelected(0) + ? StreamChatTheme.of(context).colorTheme.black + : Colors.grey, + ), + Positioned( + top: -3, + right: -16, + child: UnreadIndicator(), + ), + ], + ), + label: 'Chats', + ), + BottomNavigationBarItem( + icon: Stack( + clipBehavior: Clip.none, + children: [ + StreamSvgIcon.mentions( + color: _isSelected(1) + ? StreamChatTheme.of(context).colorTheme.black + : Colors.grey, + ), + ], + ), + label: 'Mentions', + ), + ]; + } - void _channelQueryListener() { - if (_debounce?.isActive ?? false) _debounce!.cancel(); - _debounce = Timer(const Duration(milliseconds: 350), () { - if (mounted) { - setState(() { - _channelQuery = _controller!.text; - _isSearchActive = _channelQuery.isNotEmpty; - }); - } - }); + @override + Widget build(BuildContext context) { + final user = StreamChat.of(context).user; + if (user == null) { + return Offstage(); + } + return Scaffold( + backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + appBar: ChannelListHeader( + onNewChatButtonTap: () { + Navigator.pushNamed(context, Routes.NEW_CHAT); + }, + preNavigationCallback: () { + FocusScope.of(context).requestFocus(FocusNode()); + }, + ), + drawer: LeftDrawer( + user: user, + ), + drawerEdgeDragWidth: 50, + bottomNavigationBar: BottomNavigationBar( + backgroundColor: StreamChatTheme.of(context).colorTheme.white, + currentIndex: _currentIndex, + items: _navBarItems, + selectedLabelStyle: StreamChatTheme.of(context).textTheme.footnoteBold, + unselectedLabelStyle: + StreamChatTheme.of(context).textTheme.footnoteBold, + type: BottomNavigationBarType.fixed, + selectedItemColor: StreamChatTheme.of(context).colorTheme.black, + unselectedItemColor: Colors.grey, + onTap: (index) { + setState(() => _currentIndex = index); + }, + ), + body: IndexedStack( + index: _currentIndex, + children: [ + ChannelList(), + UserMentionsPage(), + ], + ), + ); } + StreamSubscription? badgeListener; + @override void initState() { + if (!kIsWeb) { + badgeListener = StreamChat.of(context) + .client + .state + .totalUnreadCountStream + .listen((count) { + if (count > 0) { + FlutterAppBadger.updateBadgeCount(count); + } else { + FlutterAppBadger.removeBadge(); + } + }); + } super.initState(); - _controller = TextEditingController()..addListener(_channelQueryListener); } @override void dispose() { - _controller?.removeListener(_channelQueryListener); - _controller?.dispose(); + badgeListener?.cancel(); super.dispose(); } +} + +class LeftDrawer extends StatelessWidget { + const LeftDrawer({ + Key? key, + required this.user, + }) : super(key: key); + + final User user; @override Widget build(BuildContext context) { - final user = StreamChat.of(context).user; - return WillPopScope( - onWillPop: () async { - if (_isSearchActive) { - _controller!.clear(); - setState(() => _isSearchActive = false); - return false; - } - return true; - }, - child: ChannelsBloc( - child: MessageSearchBloc( - child: NestedScrollView( - floatHeaderSlivers: true, - headerSliverBuilder: (_, __) => [ - SliverToBoxAdapter( - child: SearchTextField( - controller: _controller, - showCloseButton: _isSearchActive, - ), - ), - ], - body: AnimatedSwitcher( - duration: const Duration(milliseconds: 350), - child: GestureDetector( - behavior: HitTestBehavior.opaque, - onPanDown: (_) => FocusScope.of(context).unfocus(), - child: _isSearchActive - ? MessageSearchListView( - showErrorTile: true, - messageQuery: _channelQuery, - filters: Filter.in_('members', [user!.id]), - sortOptions: [ - SortOption( - 'created_at', - direction: SortOption.ASC, + return Drawer( + child: Container( + color: StreamChatTheme.of(context).colorTheme.white, + child: SafeArea( + child: Padding( + padding: EdgeInsets.only( + top: MediaQuery.of(context).viewPadding.top + 8, + ), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.only( + bottom: 20.0, + left: 8, + ), + child: Row( + children: [ + UserAvatar( + user: user, + showOnlineStatus: false, + constraints: BoxConstraints.tight(Size.fromRadius(20)), + ), + Padding( + padding: const EdgeInsets.only(left: 16.0), + child: Text( + user.name, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, ), - ], - pullToRefresh: false, - paginationParams: PaginationParams(limit: 20), - emptyBuilder: (_) { - return LayoutBuilder( - builder: (context, viewportConstraints) { - return SingleChildScrollView( - physics: AlwaysScrollableScrollPhysics(), - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: viewportConstraints.maxHeight, - ), - child: Center( - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(24), - child: StreamSvgIcon.search( - size: 96, - color: Colors.grey, - ), - ), - Text( - 'No results...', - ), - ], - ), - ), - ), - ); - }, - ); - }, - onItemTap: (messageResponse) async { - FocusScope.of(context).requestFocus(FocusNode()); - final client = StreamChat.of(context).client; - final message = messageResponse.message; - final channel = client.channel( - messageResponse.channel!.type, - id: messageResponse.channel!.id, - ); - if (channel.state == null) { - await channel.watch(); - } - Navigator.pushNamed( - context, - Routes.CHANNEL_PAGE, - arguments: ChannelPageArgs( - channel: channel, - initialMessage: message, - ), - ); - }, - ) - : ChannelListView( - onStartChatPressed: () { - Navigator.pushNamed(context, Routes.NEW_CHAT); - }, - swipeToAction: true, - filter: Filter.in_('members', [user!.id]), - presence: true, - pagination: PaginationParams( - limit: 20, ), - channelWidget: ChannelPage(), - onViewInfoTap: (channel) { - Navigator.pop(context); - if (channel.memberCount == 2 && channel.isDistinct) { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => StreamChannel( - channel: channel, - child: ChatInfoScreen( - messageTheme: StreamChatTheme.of(context) - .ownMessageTheme, - user: channel.state!.members - .where((m) => - m.userId != - channel.client.state.user!.id) - .first - .user, - ), - ), - ), - ); - } else { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => StreamChannel( - channel: channel, - child: GroupInfoScreen( - messageTheme: StreamChatTheme.of(context) - .ownMessageTheme, - ), - ), - ), - ); - } + ), + ], + ), + ), + ListTile( + leading: StreamSvgIcon.penWrite( + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(.5), + ), + onTap: () { + Navigator.popAndPushNamed( + context, + Routes.NEW_CHAT, + ); + }, + title: Text( + 'New direct message', + style: TextStyle( + fontSize: 14.5, + ), + ), + ), + ListTile( + leading: StreamSvgIcon.contacts( + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(.5), + ), + onTap: () { + Navigator.popAndPushNamed( + context, + Routes.NEW_GROUP_CHAT, + ); + }, + title: Text( + 'New group', + style: TextStyle( + fontSize: 14.5, + ), + ), + ), + Expanded( + child: Container( + alignment: Alignment.bottomCenter, + child: ListTile( + onTap: () async { + Navigator.pop(context); + + if (!kIsWeb) { + final secureStorage = FlutterSecureStorage(); + await secureStorage.deleteAll(); + } + + final client = StreamChat.of(context).client; + client.disconnectUser(); + await client.dispose(); + + await Navigator.of( + context, + rootNavigator: true, + ).pushNamedAndRemoveUntil( + Routes.CHOOSE_USER, + ModalRoute.withName(Routes.CHOOSE_USER), + ); + }, + leading: StreamSvgIcon.user( + color: StreamChatTheme.of(context) + .colorTheme + .black + .withOpacity(.5), + ), + title: Text( + 'Sign out', + style: TextStyle( + fontSize: 14.5, + ), + ), + trailing: IconButton( + icon: StreamSvgIcon.iconMoon( + size: 24, + ), + color: StreamChatTheme.of(context).colorTheme.grey, + onPressed: () async { + final sp = await StreamingSharedPreferences.instance; + sp.setInt( + 'theme', + Theme.of(context).brightness == Brightness.dark + ? 1 + : -1, + ); }, ), - ), + ), + ), + ), + ], ), ), ), diff --git a/stream_chat_v1/lib/channel_media_display_screen.dart b/stream_chat_v1/lib/channel_media_display_screen.dart index 5c33622136..15f8fd69d5 100644 --- a/stream_chat_v1/lib/channel_media_display_screen.dart +++ b/stream_chat_v1/lib/channel_media_display_screen.dart @@ -71,21 +71,7 @@ class _ChannelMediaDisplayScreenState extends State { fontSize: 16.0, ), ), - leading: Center( - child: InkWell( - onTap: () { - Navigator.of(context).pop(); - }, - child: Container( - width: 24.0, - height: 24.0, - child: StreamSvgIcon.left( - color: StreamChatTheme.of(context).colorTheme.black, - size: 24.0, - ), - ), - ), - ), + leading: StreamBackButton(), backgroundColor: StreamChatTheme.of(context).colorTheme.white, ), body: _buildMediaGrid(), diff --git a/stream_chat_v1/lib/choose_user_page.dart b/stream_chat_v1/lib/choose_user_page.dart index 7c882e3877..e7be235ff7 100644 --- a/stream_chat_v1/lib/choose_user_page.dart +++ b/stream_chat_v1/lib/choose_user_page.dart @@ -1,4 +1,5 @@ import 'package:example/app_config.dart'; +import 'package:example/home_page.dart'; import 'package:example/stream_version.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -6,6 +7,7 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; +import 'main.dart'; import 'routes/routes.dart'; const kStreamApiKey = 'STREAM_API_KEY'; @@ -89,8 +91,11 @@ class ChooseUserPage extends StatelessWidget { ), ); - final client = StreamChat.of(context).client; - // client.apiKey = kDefaultStreamApiKey; + final client = StreamChatClient( + kDefaultStreamApiKey, + logLevel: Level.INFO, + )..chatPersistenceClient = chatPersistentClient; + await client.connectUser( user, token, @@ -115,6 +120,7 @@ class ChooseUserPage extends StatelessWidget { context, Routes.HOME, ModalRoute.withName(Routes.HOME), + arguments: HomePageArgs(client), ); }, leading: UserAvatar( diff --git a/stream_chat_v1/lib/home_page.dart b/stream_chat_v1/lib/home_page.dart index af5f68d863..7746729c02 100644 --- a/stream_chat_v1/lib/home_page.dart +++ b/stream_chat_v1/lib/home_page.dart @@ -1,240 +1,30 @@ +import 'package:example/routes/app_routes.dart'; import 'package:example/routes/routes.dart'; -import 'package:example/user_mentions_page.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -import 'package:streaming_shared_preferences/streaming_shared_preferences.dart'; -import 'channel_list_page.dart'; +class HomePageArgs { + final StreamChatClient chatClient; -class HomePage extends StatefulWidget { - @override - _HomePageState createState() => _HomePageState(); -} - -class _HomePageState extends State { - int _currentIndex = 0; - - bool _isSelected(int index) => _currentIndex == index; - - List get _navBarItems { - return [ - BottomNavigationBarItem( - icon: Stack( - clipBehavior: Clip.none, - children: [ - StreamSvgIcon.message( - color: _isSelected(0) - ? StreamChatTheme.of(context).colorTheme.black - : Colors.grey, - ), - Positioned( - top: -3, - right: -16, - child: UnreadIndicator(), - ), - ], - ), - label: 'Chats', - ), - BottomNavigationBarItem( - icon: Stack( - clipBehavior: Clip.none, - children: [ - StreamSvgIcon.mentions( - color: _isSelected(1) - ? StreamChatTheme.of(context).colorTheme.black - : Colors.grey, - ), - ], - ), - label: 'Mentions', - ), - ]; - } - - @override - Widget build(BuildContext context) { - final user = StreamChat.of(context).user!; - return Scaffold( - backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, - appBar: ChannelListHeader( - onNewChatButtonTap: () { - Navigator.pushNamed(context, Routes.NEW_CHAT); - }, - preNavigationCallback: () { - FocusScope.of(context).requestFocus(FocusNode()); - }, - ), - drawer: LeftDrawer( - user: user, - ), - drawerEdgeDragWidth: 50, - bottomNavigationBar: BottomNavigationBar( - backgroundColor: StreamChatTheme.of(context).colorTheme.white, - currentIndex: _currentIndex, - items: _navBarItems, - selectedLabelStyle: StreamChatTheme.of(context).textTheme.footnoteBold, - unselectedLabelStyle: - StreamChatTheme.of(context).textTheme.footnoteBold, - type: BottomNavigationBarType.fixed, - selectedItemColor: StreamChatTheme.of(context).colorTheme.black, - unselectedItemColor: Colors.grey, - onTap: (index) { - setState(() => _currentIndex = index); - }, - ), - body: IndexedStack( - index: _currentIndex, - children: [ - ChannelListPage(), - UserMentionsPage(), - ], - ), - ); - } + HomePageArgs(this.chatClient); } -class LeftDrawer extends StatelessWidget { - const LeftDrawer({ +class HomePage extends StatelessWidget { + HomePage({ Key? key, - required this.user, + required this.chatClient, }) : super(key: key); - final User user; + final StreamChatClient chatClient; @override Widget build(BuildContext context) { - return Drawer( - child: Container( - color: StreamChatTheme.of(context).colorTheme.white, - child: SafeArea( - child: Padding( - padding: EdgeInsets.only( - top: MediaQuery.of(context).viewPadding.top + 8, - ), - child: Column( - children: [ - Padding( - padding: const EdgeInsets.only( - bottom: 20.0, - left: 8, - ), - child: Row( - children: [ - UserAvatar( - user: user, - showOnlineStatus: false, - constraints: BoxConstraints.tight(Size.fromRadius(20)), - ), - Padding( - padding: const EdgeInsets.only(left: 16.0), - child: Text( - user.name, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - ), - ), - ), - ], - ), - ), - ListTile( - leading: StreamSvgIcon.penWrite( - color: StreamChatTheme.of(context) - .colorTheme - .black - .withOpacity(.5), - ), - onTap: () { - Navigator.popAndPushNamed( - context, - Routes.NEW_CHAT, - ); - }, - title: Text( - 'New direct message', - style: TextStyle( - fontSize: 14.5, - ), - ), - ), - ListTile( - leading: StreamSvgIcon.contacts( - color: StreamChatTheme.of(context) - .colorTheme - .black - .withOpacity(.5), - ), - onTap: () { - Navigator.popAndPushNamed( - context, - Routes.NEW_GROUP_CHAT, - ); - }, - title: Text( - 'New group', - style: TextStyle( - fontSize: 14.5, - ), - ), - ), - Expanded( - child: Container( - alignment: Alignment.bottomCenter, - child: ListTile( - onTap: () async { - Navigator.pop(context); - - if (!kIsWeb) { - final secureStorage = FlutterSecureStorage(); - await secureStorage.deleteAll(); - } - - StreamChat.of(context).client.disconnectUser(); - - await Navigator.pushNamedAndRemoveUntil( - context, - Routes.APP, - ModalRoute.withName(Routes.APP), - ); - }, - leading: StreamSvgIcon.user( - color: StreamChatTheme.of(context) - .colorTheme - .black - .withOpacity(.5), - ), - title: Text( - 'Sign out', - style: TextStyle( - fontSize: 14.5, - ), - ), - trailing: IconButton( - icon: StreamSvgIcon.iconMoon( - size: 24, - ), - color: StreamChatTheme.of(context).colorTheme.grey, - onPressed: () async { - final sp = await StreamingSharedPreferences.instance; - sp.setInt( - 'theme', - Theme.of(context).brightness == Brightness.dark - ? 1 - : -1, - ); - }, - ), - ), - ), - ), - ], - ), - ), - ), + return StreamChat( + client: chatClient, + child: Navigator( + onGenerateRoute: AppRoutes.generateRoute, + initialRoute: Routes.CHANNEL_LIST_PAGE, ), ); } diff --git a/stream_chat_v1/lib/main.dart b/stream_chat_v1/lib/main.dart index 05af49cc3e..e53e8c04d9 100644 --- a/stream_chat_v1/lib/main.dart +++ b/stream_chat_v1/lib/main.dart @@ -1,20 +1,18 @@ import 'dart:async'; import 'package:example/choose_user_page.dart'; +import 'package:example/home_page.dart'; +import 'package:example/splash_screen.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; -import 'package:flutter/services.dart'; -import 'package:flutter_app_badger/flutter_app_badger.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; -import 'package:lottie/lottie.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:stream_chat_persistence/stream_chat_persistence.dart'; import 'package:streaming_shared_preferences/streaming_shared_preferences.dart'; import 'app_config.dart'; -import 'notifications_service.dart'; import 'routes/app_routes.dart'; import 'routes/routes.dart'; @@ -24,8 +22,6 @@ final chatPersistentClient = StreamChatPersistenceClient( ); void main() async { - WidgetsFlutterBinding.ensureInitialized(); - runApp(MyApp()); } @@ -34,13 +30,9 @@ class MyApp extends StatefulWidget { _MyAppState createState() => _MyAppState(); } -class _MyAppState extends State with TickerProviderStateMixin { +class _MyAppState extends State + with SplashScreenStateMixin, TickerProviderStateMixin { InitData? _initData; - bool _animCompleted = false; - Animation? _animation, _scaleAnimation; - AnimationController? _animationController, _scaleAnimationController; - Animation? _colorAnimation; - late int timeOfStartMs; Future _initConnection() async { String? apiKey, userId, token; @@ -69,56 +61,9 @@ class _MyAppState extends State with TickerProviderStateMixin { return InitData(client, prefs); } - void _createAnimations() { - _scaleAnimationController = AnimationController( - vsync: this, - value: 0, - duration: Duration( - milliseconds: 500, - ), - ); - _scaleAnimation = Tween( - begin: 1.0, - end: 1.5, - ).animate(CurvedAnimation( - parent: _scaleAnimationController!, - curve: Curves.easeInOutBack, - )); - - _animationController = AnimationController( - vsync: this, - duration: Duration( - milliseconds: 1000, - ), - ); - _animation = Tween( - begin: 0.0, - end: 1000.0, - ).animate(CurvedAnimation( - parent: _animationController!, - curve: Curves.easeInOut, - )); - _colorAnimation = ColorTween( - begin: Color(0xff005FFF), - end: Color(0xff005FFF), - ).animate(CurvedAnimation( - parent: _animationController!, - curve: Curves.easeInOut, - )); - _colorAnimation = ColorTween( - begin: Color(0xff005FFF), - end: Colors.transparent, - ).animate(CurvedAnimation( - parent: _animationController!, - curve: Curves.easeInOut, - )); - } - @override void initState() { - timeOfStartMs = DateTime.now().millisecondsSinceEpoch; - - _createAnimations(); + final timeOfStartMs = DateTime.now().millisecondsSinceEpoch; _initConnection().then( (initData) { @@ -126,97 +71,23 @@ class _MyAppState extends State with TickerProviderStateMixin { _initData = initData; }); - var now = DateTime.now().millisecondsSinceEpoch; + final now = DateTime.now().millisecondsSinceEpoch; if (now - timeOfStartMs > 1500) { SchedulerBinding.instance!.addPostFrameCallback((timeStamp) { - _scaleAnimationController?.forward().whenComplete(() { - _animationController?.forward(); - }); + forwardAnimations(); }); } else { Future.delayed(Duration(milliseconds: 1500)).then((value) { - _scaleAnimationController?.forward().whenComplete(() { - _animationController?.forward(); - }); - }); - } - - if (!kIsWeb) { - _initData!.client.state.totalUnreadCountStream.listen((count) { - if (count > 0) { - FlutterAppBadger.updateBadgeCount(count); - } else { - FlutterAppBadger.removeBadge(); - } + forwardAnimations(); }); } }, ); - _animationController?.addStatusListener((status) { - if (status == AnimationStatus.completed) { - setState(() { - _animCompleted = true; - }); - } - }); super.initState(); } - Widget _buildAnimation() { - return MaterialApp( - home: Stack( - clipBehavior: Clip.none, - alignment: Alignment.center, - children: [ - AnimatedBuilder( - animation: _scaleAnimation!, - builder: (context, _) { - return Transform.scale( - scale: _scaleAnimation!.value, - child: AnimatedBuilder( - animation: _colorAnimation!, - builder: (context, snapshot) { - return Container( - alignment: Alignment.center, - constraints: BoxConstraints.expand(), - color: _colorAnimation == null - ? Color(0xff005FFF) - : _colorAnimation!.value, - child: !_animationController!.isAnimating - ? Lottie.asset( - 'assets/floating_boat.json', - alignment: Alignment.center, - ) - : SizedBox(), - ); - }), - ); - }, - ), - AnimatedBuilder( - animation: _animation!, - builder: (context, snapshot) { - return Transform.scale( - scale: _animation!.value, - child: Container( - width: 1.0, - height: 1.0, - decoration: BoxDecoration( - color: Colors.white - .withOpacity(1 - _animationController!.value), - shape: BoxShape.circle, - ), - ), - ); - }, - ), - ], - ), - ); - } - @override Widget build(BuildContext context) { return Stack( @@ -229,27 +100,6 @@ class _MyAppState extends State with TickerProviderStateMixin { defaultValue: 0, ), builder: (context, snapshot) => MaterialApp( - builder: (context, child) { - return StreamChat( - backgroundKeepAlive: Duration(seconds: 5), - client: _initData!.client, - onBackgroundEventReceived: (e) => showLocalNotification( - e, _initData!.client.state.user!.id), - child: Builder( - builder: (context) => AnnotatedRegion( - child: child!, - value: SystemUiOverlayStyle( - systemNavigationBarColor: - StreamChatTheme.of(context).colorTheme.white, - systemNavigationBarIconBrightness: - Theme.of(context).brightness == Brightness.dark - ? Brightness.light - : Brightness.dark, - ), - ), - ), - ); - }, theme: ThemeData.light(), darkTheme: ThemeData.dark(), themeMode: { @@ -257,13 +107,38 @@ class _MyAppState extends State with TickerProviderStateMixin { 0: ThemeMode.system, 1: ThemeMode.light, }[snapshot], + builder: (context, child) => StreamChatTheme( + data: StreamChatThemeData( + brightness: Theme.of(context).brightness, + ), + child: child!, + ), onGenerateRoute: AppRoutes.generateRoute, + onGenerateInitialRoutes: (initialRouteName) { + if (initialRouteName == Routes.HOME) { + return [ + AppRoutes.generateRoute( + RouteSettings( + name: Routes.HOME, + arguments: HomePageArgs(_initData!.client), + ), + )! + ]; + } + return [ + AppRoutes.generateRoute( + RouteSettings( + name: Routes.CHOOSE_USER, + ), + )! + ]; + }, initialRoute: _initData!.client.state.user == null ? Routes.CHOOSE_USER : Routes.HOME, ), ), - if (!_animCompleted) _buildAnimation(), + if (!animationCompleted) buildAnimation(), ], ); } @@ -275,50 +150,3 @@ class InitData { InitData(this.client, this.preferences); } - -class HolePainter extends CustomPainter { - HolePainter({ - required this.color, - required this.holeSize, - }); - - Color color; - double holeSize; - - @override - void paint(Canvas canvas, Size size) { - double radius = holeSize / 2; - Rect rect = Rect.fromLTWH(0, 0, size.width, size.height); - Rect outerCircleRect = Rect.fromCircle( - center: Offset(size.width / 2, size.height / 2), radius: radius); - Rect innerCircleRect = Rect.fromCircle( - center: Offset(size.width / 2, size.height / 2), radius: radius / 2); - - Path transparentHole = Path.combine( - PathOperation.difference, - Path()..addRect(rect), - Path() - ..addOval(outerCircleRect) - ..close(), - ); - - Path halfTransparentRing = Path.combine( - PathOperation.difference, - Path() - ..addOval(outerCircleRect) - ..close(), - Path() - ..addOval(innerCircleRect) - ..close(), - ); - - canvas.drawPath(transparentHole, Paint()..color = color); - canvas.drawPath( - halfTransparentRing, Paint()..color = color.withOpacity(0.5)); - } - - @override - bool shouldRepaint(CustomPainter oldDelegate) { - return true; - } -} diff --git a/stream_chat_v1/lib/pinned_messages_screen.dart b/stream_chat_v1/lib/pinned_messages_screen.dart index 82dd532d02..d8f756be0a 100644 --- a/stream_chat_v1/lib/pinned_messages_screen.dart +++ b/stream_chat_v1/lib/pinned_messages_screen.dart @@ -70,21 +70,7 @@ class _PinnedMessagesScreenState extends State { fontSize: 16.0, ), ), - leading: Center( - child: InkWell( - onTap: () { - Navigator.of(context).pop(); - }, - child: Container( - width: 24.0, - height: 24.0, - child: StreamSvgIcon.left( - color: StreamChatTheme.of(context).colorTheme.black, - size: 24.0, - ), - ), - ), - ), + leading: StreamBackButton(), backgroundColor: StreamChatTheme.of(context).colorTheme.white, ), body: _buildMediaGrid(), diff --git a/stream_chat_v1/lib/routes/app_routes.dart b/stream_chat_v1/lib/routes/app_routes.dart index 4bc157edf5..145fa8e6e2 100644 --- a/stream_chat_v1/lib/routes/app_routes.dart +++ b/stream_chat_v1/lib/routes/app_routes.dart @@ -1,3 +1,4 @@ +import 'package:example/channel_list_page.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; @@ -28,7 +29,10 @@ class AppRoutes { return MaterialPageRoute( settings: const RouteSettings(name: Routes.HOME), builder: (_) { - return HomePage(); + final homePageArgs = args as HomePageArgs; + return HomePage( + chatClient: homePageArgs.chatClient, + ); }); case Routes.CHOOSE_USER: return MaterialPageRoute( @@ -92,6 +96,12 @@ class AppRoutes { messageTheme: StreamChatTheme.of(context).ownMessageTheme, ); }); + case Routes.CHANNEL_LIST_PAGE: + return MaterialPageRoute( + settings: const RouteSettings(name: Routes.CHANNEL_LIST_PAGE), + builder: (context) { + return ChannelListPage(); + }); // Default case, should not reach here. default: return null; diff --git a/stream_chat_v1/lib/routes/routes.dart b/stream_chat_v1/lib/routes/routes.dart index 2280ca306b..239bd282b0 100644 --- a/stream_chat_v1/lib/routes/routes.dart +++ b/stream_chat_v1/lib/routes/routes.dart @@ -10,4 +10,5 @@ class Routes { static const String NEW_GROUP_CHAT_DETAILS = '/new_group_chat_details'; static const String CHAT_INFO_SCREEN = '/chat_info_screen'; static const String GROUP_INFO_SCREEN = '/group_info_screen'; + static const String CHANNEL_LIST_PAGE = '/channel_list_page'; } diff --git a/stream_chat_v1/lib/splash_screen.dart b/stream_chat_v1/lib/splash_screen.dart new file mode 100644 index 0000000000..2c8922898d --- /dev/null +++ b/stream_chat_v1/lib/splash_screen.dart @@ -0,0 +1,122 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:lottie/lottie.dart'; + +mixin SplashScreenStateMixin on State + implements TickerProvider { + late Animation animation, scaleAnimation; + late AnimationController _animationController, _scaleAnimationController; + late Animation colorAnimation; + bool animationCompleted = false; + + void _createAnimations() { + _scaleAnimationController = AnimationController( + vsync: this, + value: 0, + duration: Duration( + milliseconds: 500, + ), + ); + scaleAnimation = Tween( + begin: 1.0, + end: 1.5, + ).animate(CurvedAnimation( + parent: _scaleAnimationController, + curve: Curves.easeInOutBack, + )); + + _animationController = AnimationController( + vsync: this, + duration: Duration( + milliseconds: 1000, + ), + ); + animation = Tween( + begin: 0.0, + end: 1000.0, + ).animate(CurvedAnimation( + parent: _animationController, + curve: Curves.easeInOut, + )); + colorAnimation = ColorTween( + begin: Color(0xff005FFF), + end: Color(0xff005FFF), + ).animate(CurvedAnimation( + parent: _animationController, + curve: Curves.easeInOut, + )); + colorAnimation = ColorTween( + begin: Color(0xff005FFF), + end: Colors.transparent, + ).animate(CurvedAnimation( + parent: _animationController, + curve: Curves.easeInOut, + )); + } + + void forwardAnimations() { + _scaleAnimationController.forward().whenComplete(() { + _animationController.forward(); + }); + } + + Widget buildAnimation() => Stack( + clipBehavior: Clip.none, + alignment: Alignment.center, + children: [ + AnimatedBuilder( + animation: scaleAnimation, + builder: (context, _) { + return Transform.scale( + scale: scaleAnimation.value, + child: AnimatedBuilder( + animation: colorAnimation, + builder: (context, snapshot) { + return Container( + alignment: Alignment.center, + constraints: BoxConstraints.expand(), + color: colorAnimation.value, + child: !_animationController.isAnimating + ? Lottie.asset( + 'assets/floating_boat.json', + alignment: Alignment.center, + ) + : SizedBox(), + ); + }), + ); + }, + ), + AnimatedBuilder( + animation: animation, + builder: (context, snapshot) { + return Transform.scale( + scale: animation.value, + child: Container( + width: 1.0, + height: 1.0, + decoration: BoxDecoration( + color: Colors.white + .withOpacity(1 - _animationController.value), + shape: BoxShape.circle, + ), + ), + ); + }, + ), + ], + ); + + @override + void initState() { + _createAnimations(); + _animationController.addStatusListener((status) { + if (status == AnimationStatus.completed) { + setState(() { + animationCompleted = true; + }); + } + }); + super.initState(); + } +} diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index 9c82d91b04..8c0528bb0c 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -11,15 +11,9 @@ dependencies: flutter: sdk: flutter stream_chat_flutter: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: ref/segregate-api-layer - path: packages/stream_chat_flutter + path: ../../../stream-chat-flutter/packages/stream_chat_flutter stream_chat_persistence: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: ref/segregate-api-layer - path: packages/stream_chat_persistence + path: ../../../stream-chat-flutter/packages/stream_chat_persistence flutter_local_notifications: ^5.0.0+4 flutter_svg: ^0.22.0 flutter_secure_storage: ^4.2.0 @@ -31,15 +25,9 @@ dependencies: dependency_overrides: stream_chat: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: ref/segregate-api-layer - path: packages/stream_chat + path: ../../../stream-chat-flutter/packages/stream_chat stream_chat_flutter_core: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: ref/segregate-api-layer - path: packages/stream_chat_flutter_core + path: ../../../stream-chat-flutter/packages/stream_chat_flutter_core dev_dependencies: flutter_launcher_icons: ^0.9.0 From a779283c8f999c67a99e30aea4d2fa287d4a805a Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 22 Jun 2021 14:47:54 +0200 Subject: [PATCH 046/172] restore dependencies --- stream_chat_v1/pubspec.yaml | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index 8c0528bb0c..59ce3062cc 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -11,9 +11,15 @@ dependencies: flutter: sdk: flutter stream_chat_flutter: - path: ../../../stream-chat-flutter/packages/stream_chat_flutter + git: + url: https://github.com/GetStream/stream-chat-flutter.git + ref: develop + path: packages/stream_chat_flutter stream_chat_persistence: - path: ../../../stream-chat-flutter/packages/stream_chat_persistence + git: + url: https://github.com/GetStream/stream-chat-flutter.git + ref: develop + path: packages/stream_chat_persistence flutter_local_notifications: ^5.0.0+4 flutter_svg: ^0.22.0 flutter_secure_storage: ^4.2.0 @@ -25,9 +31,15 @@ dependencies: dependency_overrides: stream_chat: - path: ../../../stream-chat-flutter/packages/stream_chat + git: + url: https://github.com/GetStream/stream-chat-flutter.git + ref: develop + path: packages/stream_chat stream_chat_flutter_core: - path: ../../../stream-chat-flutter/packages/stream_chat_flutter_core + git: + url: https://github.com/GetStream/stream-chat-flutter.git + ref: develop + path: packages/stream_chat_flutter_core dev_dependencies: flutter_launcher_icons: ^0.9.0 From 20e69843d4bb7df9e5c19f98443ec07ce669d935 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Wed, 23 Jun 2021 19:23:02 +0200 Subject: [PATCH 047/172] fix android build --- stream_chat_v1/android/gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stream_chat_v1/android/gradle/wrapper/gradle-wrapper.properties b/stream_chat_v1/android/gradle/wrapper/gradle-wrapper.properties index 4a4c204382..c0a81d1105 100644 --- a/stream_chat_v1/android/gradle/wrapper/gradle-wrapper.properties +++ b/stream_chat_v1/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip From c4547594f3f918a145ff033e8faded6ddb455fb3 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 29 Jun 2021 13:31:31 +0200 Subject: [PATCH 048/172] fix modals using nearest navigator --- stream_chat_v1/lib/group_chat_details_screen.dart | 1 + stream_chat_v1/lib/group_info_screen.dart | 2 ++ 2 files changed, 3 insertions(+) diff --git a/stream_chat_v1/lib/group_chat_details_screen.dart b/stream_chat_v1/lib/group_chat_details_screen.dart index c59f74439e..f4b15ef962 100644 --- a/stream_chat_v1/lib/group_chat_details_screen.dart +++ b/stream_chat_v1/lib/group_chat_details_screen.dart @@ -266,6 +266,7 @@ class _GroupChatDetailsScreenState extends State { void _showErrorAlert() { showModalBottomSheet( + useRootNavigator: false, backgroundColor: StreamChatTheme.of(context).colorTheme.white, context: context, shape: RoundedRectangleBorder( diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/group_info_screen.dart index 1d9572eecb..639175eaf4 100644 --- a/stream_chat_v1/lib/group_info_screen.dart +++ b/stream_chat_v1/lib/group_info_screen.dart @@ -690,6 +690,7 @@ class _GroupInfoScreenState extends State { var channel = StreamChannel.of(context).channel; showDialog( + useRootNavigator: false, context: context, barrierColor: StreamChatTheme.of(context).colorTheme.overlay, builder: (context) { @@ -851,6 +852,7 @@ class _GroupInfoScreenState extends State { final color = StreamChatTheme.of(context).colorTheme.white; showModalBottomSheet( + useRootNavigator: false, context: context, clipBehavior: Clip.antiAlias, isScrollControlled: true, From 8544a00c69ac1fd20493da01bbd0da42c77a8f29 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 29 Jun 2021 13:31:49 +0200 Subject: [PATCH 049/172] bump version --- stream_chat_v1/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index 59ce3062cc..6d39645007 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -1,7 +1,7 @@ name: example description: A new Flutter project. publish_to: 'none' -version: 1.6.0 +version: 1.6.1 environment: sdk: '>=2.12.0 <3.0.0' From ead166f1cc84365e5e542d1a12f8bad63f1b5762 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 29 Jun 2021 14:53:17 +0200 Subject: [PATCH 050/172] fix physical button navigation on android --- stream_chat_v1/lib/home_page.dart | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/stream_chat_v1/lib/home_page.dart b/stream_chat_v1/lib/home_page.dart index 7746729c02..abe14f1049 100644 --- a/stream_chat_v1/lib/home_page.dart +++ b/stream_chat_v1/lib/home_page.dart @@ -17,14 +17,22 @@ class HomePage extends StatelessWidget { }) : super(key: key); final StreamChatClient chatClient; + final GlobalKey _navigatorKey = GlobalKey(); @override Widget build(BuildContext context) { return StreamChat( client: chatClient, - child: Navigator( - onGenerateRoute: AppRoutes.generateRoute, - initialRoute: Routes.CHANNEL_LIST_PAGE, + child: WillPopScope( + onWillPop: () async { + final canPop = await _navigatorKey.currentState?.maybePop() ?? false; + return !canPop; + }, + child: Navigator( + key: _navigatorKey, + onGenerateRoute: AppRoutes.generateRoute, + initialRoute: Routes.CHANNEL_LIST_PAGE, + ), ), ); } From c4193c9039ecced172305ecd07148049753a89b4 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 1 Jul 2021 08:55:12 +0200 Subject: [PATCH 051/172] fix homepage --- stream_chat_v1/lib/home_page.dart | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/stream_chat_v1/lib/home_page.dart b/stream_chat_v1/lib/home_page.dart index abe14f1049..828230fd58 100644 --- a/stream_chat_v1/lib/home_page.dart +++ b/stream_chat_v1/lib/home_page.dart @@ -10,19 +10,25 @@ class HomePageArgs { HomePageArgs(this.chatClient); } -class HomePage extends StatelessWidget { +class HomePage extends StatefulWidget { HomePage({ Key? key, required this.chatClient, }) : super(key: key); final StreamChatClient chatClient; + + @override + _HomePageState createState() => _HomePageState(); +} + +class _HomePageState extends State { final GlobalKey _navigatorKey = GlobalKey(); @override Widget build(BuildContext context) { return StreamChat( - client: chatClient, + client: widget.chatClient, child: WillPopScope( onWillPop: () async { final canPop = await _navigatorKey.currentState?.maybePop() ?? false; From 1f70d3e901f14412a8edde1494d8dab4c1fc118a Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 1 Jul 2021 09:28:01 +0200 Subject: [PATCH 052/172] update color names with develop ones --- stream_chat_v1/lib/advanced_options_page.dart | 66 +++-- .../lib/channel_file_display_screen.dart | 15 +- stream_chat_v1/lib/channel_list.dart | 246 +++++++++--------- stream_chat_v1/lib/channel_list_page.dart | 23 +- .../lib/channel_media_display_screen.dart | 13 +- stream_chat_v1/lib/channel_page.dart | 9 +- stream_chat_v1/lib/chat_info_screen.dart | 100 +++---- .../lib/chips_input_text_field.dart | 10 +- stream_chat_v1/lib/choose_user_page.dart | 28 +- .../lib/group_chat_details_screen.dart | 42 +-- stream_chat_v1/lib/group_info_screen.dart | 155 ++++++----- stream_chat_v1/lib/main.dart | 6 +- stream_chat_v1/lib/new_chat_screen.dart | 24 +- stream_chat_v1/lib/new_group_chat_screen.dart | 25 +- .../lib/pinned_messages_screen.dart | 19 +- stream_chat_v1/lib/search_text_field.dart | 9 +- stream_chat_v1/lib/stream_version.dart | 2 +- stream_chat_v1/lib/thread_page.dart | 2 +- stream_chat_v1/lib/user_mentions_page.dart | 10 +- 19 files changed, 430 insertions(+), 374 deletions(-) diff --git a/stream_chat_v1/lib/advanced_options_page.dart b/stream_chat_v1/lib/advanced_options_page.dart index 4a97c68a77..3fd9a95ba6 100644 --- a/stream_chat_v1/lib/advanced_options_page.dart +++ b/stream_chat_v1/lib/advanced_options_page.dart @@ -33,22 +33,20 @@ class _AdvancedOptionsPageState extends State { @override Widget build(BuildContext context) { return Scaffold( - backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, appBar: AppBar( - backgroundColor: StreamChatTheme.of(context).colorTheme.white, + backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, elevation: 1, centerTitle: true, brightness: Theme.of(context).brightness, title: Text( 'Advanced Options', - style: StreamChatTheme.of(context) - .textTheme - .headlineBold - .copyWith(color: StreamChatTheme.of(context).colorTheme.black), + style: StreamChatTheme.of(context).textTheme.headlineBold.copyWith( + color: StreamChatTheme.of(context).colorTheme.textHighEmphasis), ), leading: IconButton( icon: StreamSvgIcon.left( - color: StreamChatTheme.of(context).colorTheme.black, + color: StreamChatTheme.of(context).colorTheme.textHighEmphasis, ), onPressed: () { Navigator.pop(context); @@ -85,7 +83,9 @@ class _AdvancedOptionsPageState extends State { }, style: TextStyle( fontSize: 14, - color: StreamChatTheme.of(context).colorTheme.black, + color: StreamChatTheme.of(context) + .colorTheme + .textHighEmphasis, ), decoration: InputDecoration( errorStyle: TextStyle(height: 0, fontSize: 0), @@ -93,15 +93,16 @@ class _AdvancedOptionsPageState extends State { fontSize: 14, fontWeight: FontWeight.bold, color: _apiKeyError != null - ? StreamChatTheme.of(context).colorTheme.accentRed - : StreamChatTheme.of(context).colorTheme.grey, + ? StreamChatTheme.of(context).colorTheme.accentError + : StreamChatTheme.of(context) + .colorTheme + .textLowEmphasis, ), border: UnderlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: BorderSide.none, ), - fillColor: - StreamChatTheme.of(context).colorTheme.whiteSmoke, + fillColor: StreamChatTheme.of(context).colorTheme.inputBg, filled: true, labelText: _apiKeyError != null ? 'CHAT API KEY: $_apiKeyError' @@ -131,7 +132,9 @@ class _AdvancedOptionsPageState extends State { }, style: TextStyle( fontSize: 14, - color: StreamChatTheme.of(context).colorTheme.black, + color: StreamChatTheme.of(context) + .colorTheme + .textHighEmphasis, ), textInputAction: TextInputAction.next, decoration: InputDecoration( @@ -140,15 +143,16 @@ class _AdvancedOptionsPageState extends State { fontWeight: FontWeight.bold, fontSize: 14, color: _userIdError != null - ? StreamChatTheme.of(context).colorTheme.accentRed - : StreamChatTheme.of(context).colorTheme.grey, + ? StreamChatTheme.of(context).colorTheme.accentError + : StreamChatTheme.of(context) + .colorTheme + .textLowEmphasis, ), border: UnderlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: BorderSide.none, ), - fillColor: - StreamChatTheme.of(context).colorTheme.whiteSmoke, + fillColor: StreamChatTheme.of(context).colorTheme.inputBg, filled: true, labelText: _userIdError != null ? 'USER ID: $_userIdError' @@ -177,7 +181,9 @@ class _AdvancedOptionsPageState extends State { }, style: TextStyle( fontSize: 14, - color: StreamChatTheme.of(context).colorTheme.black, + color: StreamChatTheme.of(context) + .colorTheme + .textHighEmphasis, ), textInputAction: TextInputAction.next, decoration: InputDecoration( @@ -186,15 +192,16 @@ class _AdvancedOptionsPageState extends State { fontWeight: FontWeight.bold, fontSize: 14, color: _userTokenError != null - ? StreamChatTheme.of(context).colorTheme.accentRed - : StreamChatTheme.of(context).colorTheme.grey, + ? StreamChatTheme.of(context).colorTheme.accentError + : StreamChatTheme.of(context) + .colorTheme + .textLowEmphasis, ), border: UnderlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: BorderSide.none, ), - fillColor: - StreamChatTheme.of(context).colorTheme.whiteSmoke, + fillColor: StreamChatTheme.of(context).colorTheme.inputBg, filled: true, labelText: _userTokenError != null ? 'USER TOKEN: $_userTokenError' @@ -209,14 +216,15 @@ class _AdvancedOptionsPageState extends State { labelStyle: TextStyle( fontSize: 14, fontWeight: FontWeight.bold, - color: StreamChatTheme.of(context).colorTheme.grey, + color: StreamChatTheme.of(context) + .colorTheme + .textLowEmphasis, ), border: UnderlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: BorderSide.none, ), - fillColor: - StreamChatTheme.of(context).colorTheme.whiteSmoke, + fillColor: StreamChatTheme.of(context).colorTheme.inputBg, filled: true, labelText: 'Username (optional)', ), @@ -228,7 +236,7 @@ class _AdvancedOptionsPageState extends State { Theme.of(context).brightness == Brightness.light ? StreamChatTheme.of(context) .colorTheme - .accentBlue + .accentPrimary : Colors.white), elevation: MaterialStateProperty.all(0), padding: MaterialStateProperty.all( @@ -244,7 +252,9 @@ class _AdvancedOptionsPageState extends State { style: TextStyle( fontSize: 16, color: Theme.of(context).brightness != Brightness.light - ? StreamChatTheme.of(context).colorTheme.accentBlue + ? StreamChatTheme.of(context) + .colorTheme + .accentPrimary : Colors.white, ), ), @@ -270,7 +280,7 @@ class _AdvancedOptionsPageState extends State { borderRadius: BorderRadius.circular(16), color: StreamChatTheme.of(context) .colorTheme - .white, + .barsBg, ), height: 100, width: 100, diff --git a/stream_chat_v1/lib/channel_file_display_screen.dart b/stream_chat_v1/lib/channel_file_display_screen.dart index 806f184e7b..2cffbc88a8 100644 --- a/stream_chat_v1/lib/channel_file_display_screen.dart +++ b/stream_chat_v1/lib/channel_file_display_screen.dart @@ -50,7 +50,7 @@ class _ChannelFileDisplayScreenState extends State { @override Widget build(BuildContext context) { return Scaffold( - backgroundColor: StreamChatTheme.of(context).colorTheme.white, + backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, appBar: AppBar( brightness: Theme.of(context).brightness, elevation: 1, @@ -58,7 +58,7 @@ class _ChannelFileDisplayScreenState extends State { title: Text( 'Files', style: TextStyle( - color: StreamChatTheme.of(context).colorTheme.black, + color: StreamChatTheme.of(context).colorTheme.textHighEmphasis, fontSize: 16.0), ), leading: Center( @@ -70,13 +70,13 @@ class _ChannelFileDisplayScreenState extends State { width: 24.0, height: 24.0, child: StreamSvgIcon.left( - color: StreamChatTheme.of(context).colorTheme.black, + color: StreamChatTheme.of(context).colorTheme.textHighEmphasis, size: 24.0, ), ), ), ), - backgroundColor: StreamChatTheme.of(context).colorTheme.white, + backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, ), body: _buildMediaGrid(), ); @@ -103,14 +103,15 @@ class _ChannelFileDisplayScreenState extends State { children: [ StreamSvgIcon.files( size: 136.0, - color: StreamChatTheme.of(context).colorTheme.greyGainsboro, + color: StreamChatTheme.of(context).colorTheme.disabled, ), SizedBox(height: 16.0), Text( 'No Files', style: TextStyle( fontSize: 14.0, - color: StreamChatTheme.of(context).colorTheme.black, + color: + StreamChatTheme.of(context).colorTheme.textHighEmphasis, ), ), SizedBox(height: 8.0), @@ -121,7 +122,7 @@ class _ChannelFileDisplayScreenState extends State { fontSize: 14.0, color: StreamChatTheme.of(context) .colorTheme - .black + .textHighEmphasis .withOpacity(0.5), ), ), diff --git a/stream_chat_v1/lib/channel_list.dart b/stream_chat_v1/lib/channel_list.dart index e88c9a1630..c31fabb469 100644 --- a/stream_chat_v1/lib/channel_list.dart +++ b/stream_chat_v1/lib/channel_list.dart @@ -60,137 +60,137 @@ class _ChannelList extends State { } return true; }, - child: ChannelsBloc( - child: MessageSearchBloc( - child: NestedScrollView( - floatHeaderSlivers: true, - headerSliverBuilder: (_, __) => [ - SliverToBoxAdapter( - child: SearchTextField( - controller: _controller, - showCloseButton: _isSearchActive, - ), - ), - ], - body: AnimatedSwitcher( - duration: const Duration(milliseconds: 350), - child: GestureDetector( - behavior: HitTestBehavior.opaque, - onPanDown: (_) => FocusScope.of(context).unfocus(), - child: _isSearchActive - ? MessageSearchListView( - showErrorTile: true, - messageQuery: _channelQuery, - filters: Filter.in_('members', [user!.id]), - sortOptions: [ - SortOption( - 'created_at', - direction: SortOption.ASC, - ), - ], - pullToRefresh: false, - paginationParams: PaginationParams(limit: 20), - emptyBuilder: (_) { - return LayoutBuilder( - builder: (context, viewportConstraints) { - return SingleChildScrollView( - physics: AlwaysScrollableScrollPhysics(), - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: viewportConstraints.maxHeight, - ), - child: Center( - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(24), - child: StreamSvgIcon.search( - size: 96, - color: Colors.grey, - ), - ), - Text( - 'No results...', + child: NestedScrollView( + floatHeaderSlivers: true, + headerSliverBuilder: (_, __) => [ + SliverToBoxAdapter( + child: SearchTextField( + controller: _controller, + showCloseButton: _isSearchActive, + ), + ), + ], + body: AnimatedSwitcher( + duration: const Duration(milliseconds: 350), + child: GestureDetector( + behavior: HitTestBehavior.opaque, + onPanDown: (_) => FocusScope.of(context).unfocus(), + child: _isSearchActive + ? MessageSearchBloc( + child: MessageSearchListView( + showErrorTile: true, + messageQuery: _channelQuery, + filters: Filter.in_('members', [user!.id]), + sortOptions: [ + SortOption( + 'created_at', + direction: SortOption.ASC, + ), + ], + pullToRefresh: false, + paginationParams: PaginationParams(limit: 20), + emptyBuilder: (_) { + return LayoutBuilder( + builder: (context, viewportConstraints) { + return SingleChildScrollView( + physics: AlwaysScrollableScrollPhysics(), + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: viewportConstraints.maxHeight, + ), + child: Center( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(24), + child: StreamSvgIcon.search( + size: 96, + color: Colors.grey, ), - ], - ), + ), + Text( + 'No results...', + ), + ], ), ), - ); - }, - ); - }, - onItemTap: (messageResponse) async { - FocusScope.of(context).requestFocus(FocusNode()); - final client = StreamChat.of(context).client; - final message = messageResponse.message; - final channel = client.channel( - messageResponse.channel!.type, - id: messageResponse.channel!.id, - ); - if (channel.state == null) { - await channel.watch(); - } - Navigator.pushNamed( + ), + ); + }, + ); + }, + onItemTap: (messageResponse) async { + FocusScope.of(context).requestFocus(FocusNode()); + final client = StreamChat.of(context).client; + final message = messageResponse.message; + final channel = client.channel( + messageResponse.channel!.type, + id: messageResponse.channel!.id, + ); + if (channel.state == null) { + await channel.watch(); + } + Navigator.pushNamed( + context, + Routes.CHANNEL_PAGE, + arguments: ChannelPageArgs( + channel: channel, + initialMessage: message, + ), + ); + }, + ), + ) + : ChannelsBloc( + child: ChannelListView( + onStartChatPressed: () { + Navigator.pushNamed(context, Routes.NEW_CHAT); + }, + swipeToAction: true, + filter: Filter.in_('members', [user!.id]), + presence: true, + pagination: PaginationParams( + limit: 20, + ), + channelWidget: ChannelPage(), + onViewInfoTap: (channel) { + Navigator.pop(context); + if (channel.memberCount == 2 && channel.isDistinct) { + Navigator.push( context, - Routes.CHANNEL_PAGE, - arguments: ChannelPageArgs( - channel: channel, - initialMessage: message, - ), - ); - }, - ) - : ChannelListView( - onStartChatPressed: () { - Navigator.pushNamed(context, Routes.NEW_CHAT); - }, - swipeToAction: true, - filter: Filter.in_('members', [user!.id]), - presence: true, - pagination: PaginationParams( - limit: 20, - ), - channelWidget: ChannelPage(), - onViewInfoTap: (channel) { - Navigator.pop(context); - if (channel.memberCount == 2 && channel.isDistinct) { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => StreamChannel( - channel: channel, - child: ChatInfoScreen( - messageTheme: StreamChatTheme.of(context) - .ownMessageTheme, - user: channel.state!.members - .where((m) => - m.userId != - channel.client.state.user!.id) - .first - .user, - ), + MaterialPageRoute( + builder: (context) => StreamChannel( + channel: channel, + child: ChatInfoScreen( + messageTheme: StreamChatTheme.of(context) + .ownMessageTheme, + user: channel.state!.members + .where((m) => + m.userId != + channel.client.state.user!.id) + .first + .user, ), ), - ); - } else { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => StreamChannel( - channel: channel, - child: GroupInfoScreen( - messageTheme: StreamChatTheme.of(context) - .ownMessageTheme, - ), + ), + ); + } else { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => StreamChannel( + channel: channel, + child: GroupInfoScreen( + messageTheme: StreamChatTheme.of(context) + .ownMessageTheme, ), ), - ); - } - }, - ), - ), - ), + ), + ); + } + }, + ), + ), ), ), ), diff --git a/stream_chat_v1/lib/channel_list_page.dart b/stream_chat_v1/lib/channel_list_page.dart index baf6ecac17..5379062c45 100644 --- a/stream_chat_v1/lib/channel_list_page.dart +++ b/stream_chat_v1/lib/channel_list_page.dart @@ -33,7 +33,7 @@ class _ChannelListPageState extends State { children: [ StreamSvgIcon.message( color: _isSelected(0) - ? StreamChatTheme.of(context).colorTheme.black + ? StreamChatTheme.of(context).colorTheme.textHighEmphasis : Colors.grey, ), Positioned( @@ -51,7 +51,7 @@ class _ChannelListPageState extends State { children: [ StreamSvgIcon.mentions( color: _isSelected(1) - ? StreamChatTheme.of(context).colorTheme.black + ? StreamChatTheme.of(context).colorTheme.textHighEmphasis : Colors.grey, ), ], @@ -68,7 +68,7 @@ class _ChannelListPageState extends State { return Offstage(); } return Scaffold( - backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, appBar: ChannelListHeader( onNewChatButtonTap: () { Navigator.pushNamed(context, Routes.NEW_CHAT); @@ -82,14 +82,15 @@ class _ChannelListPageState extends State { ), drawerEdgeDragWidth: 50, bottomNavigationBar: BottomNavigationBar( - backgroundColor: StreamChatTheme.of(context).colorTheme.white, + backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, currentIndex: _currentIndex, items: _navBarItems, selectedLabelStyle: StreamChatTheme.of(context).textTheme.footnoteBold, unselectedLabelStyle: StreamChatTheme.of(context).textTheme.footnoteBold, type: BottomNavigationBarType.fixed, - selectedItemColor: StreamChatTheme.of(context).colorTheme.black, + selectedItemColor: + StreamChatTheme.of(context).colorTheme.textHighEmphasis, unselectedItemColor: Colors.grey, onTap: (index) { setState(() => _currentIndex = index); @@ -144,7 +145,7 @@ class LeftDrawer extends StatelessWidget { Widget build(BuildContext context) { return Drawer( child: Container( - color: StreamChatTheme.of(context).colorTheme.white, + color: StreamChatTheme.of(context).colorTheme.barsBg, child: SafeArea( child: Padding( padding: EdgeInsets.only( @@ -181,7 +182,7 @@ class LeftDrawer extends StatelessWidget { leading: StreamSvgIcon.penWrite( color: StreamChatTheme.of(context) .colorTheme - .black + .textHighEmphasis .withOpacity(.5), ), onTap: () { @@ -201,7 +202,7 @@ class LeftDrawer extends StatelessWidget { leading: StreamSvgIcon.contacts( color: StreamChatTheme.of(context) .colorTheme - .black + .textHighEmphasis .withOpacity(.5), ), onTap: () { @@ -244,7 +245,7 @@ class LeftDrawer extends StatelessWidget { leading: StreamSvgIcon.user( color: StreamChatTheme.of(context) .colorTheme - .black + .textHighEmphasis .withOpacity(.5), ), title: Text( @@ -257,7 +258,9 @@ class LeftDrawer extends StatelessWidget { icon: StreamSvgIcon.iconMoon( size: 24, ), - color: StreamChatTheme.of(context).colorTheme.grey, + color: StreamChatTheme.of(context) + .colorTheme + .textLowEmphasis, onPressed: () async { final sp = await StreamingSharedPreferences.instance; sp.setInt( diff --git a/stream_chat_v1/lib/channel_media_display_screen.dart b/stream_chat_v1/lib/channel_media_display_screen.dart index 15f8fd69d5..f2ad261ada 100644 --- a/stream_chat_v1/lib/channel_media_display_screen.dart +++ b/stream_chat_v1/lib/channel_media_display_screen.dart @@ -59,7 +59,7 @@ class _ChannelMediaDisplayScreenState extends State { @override Widget build(BuildContext context) { return Scaffold( - backgroundColor: StreamChatTheme.of(context).colorTheme.white, + backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, appBar: AppBar( brightness: Theme.of(context).brightness, elevation: 1, @@ -67,12 +67,12 @@ class _ChannelMediaDisplayScreenState extends State { title: Text( 'Photos & Videos', style: TextStyle( - color: StreamChatTheme.of(context).colorTheme.black, + color: StreamChatTheme.of(context).colorTheme.textHighEmphasis, fontSize: 16.0, ), ), leading: StreamBackButton(), - backgroundColor: StreamChatTheme.of(context).colorTheme.white, + backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, ), body: _buildMediaGrid(), ); @@ -99,14 +99,15 @@ class _ChannelMediaDisplayScreenState extends State { children: [ StreamSvgIcon.pictures( size: 136.0, - color: StreamChatTheme.of(context).colorTheme.greyGainsboro, + color: StreamChatTheme.of(context).colorTheme.disabled, ), SizedBox(height: 16.0), Text( 'No Media', style: TextStyle( fontSize: 14.0, - color: StreamChatTheme.of(context).colorTheme.black, + color: + StreamChatTheme.of(context).colorTheme.textHighEmphasis, ), ), SizedBox(height: 8.0), @@ -117,7 +118,7 @@ class _ChannelMediaDisplayScreenState extends State { fontSize: 14.0, color: StreamChatTheme.of(context) .colorTheme - .black + .textHighEmphasis .withOpacity(0.5), ), ), diff --git a/stream_chat_v1/lib/channel_page.dart b/stream_chat_v1/lib/channel_page.dart index 1ff592cb2d..0bdb6b6846 100644 --- a/stream_chat_v1/lib/channel_page.dart +++ b/stream_chat_v1/lib/channel_page.dart @@ -59,7 +59,7 @@ class _ChannelPageState extends State { @override Widget build(BuildContext context) { return Scaffold( - backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, appBar: ChannelHeader( showTypingIndicator: false, onImageTap: () async { @@ -148,7 +148,7 @@ class _ChannelPageState extends State { alignment: Alignment.centerLeft, color: StreamChatTheme.of(context) .colorTheme - .whiteSnow + .appBg .withOpacity(.9), child: TypingIndicator( alignment: Alignment.centerLeft, @@ -160,8 +160,9 @@ class _ChannelPageState extends State { .textTheme .footnote .copyWith( - color: - StreamChatTheme.of(context).colorTheme.grey), + color: StreamChatTheme.of(context) + .colorTheme + .textLowEmphasis), ), ), ), diff --git a/stream_chat_v1/lib/chat_info_screen.dart b/stream_chat_v1/lib/chat_info_screen.dart index 6517ef3609..013851b3e7 100644 --- a/stream_chat_v1/lib/chat_info_screen.dart +++ b/stream_chat_v1/lib/chat_info_screen.dart @@ -40,18 +40,18 @@ class _ChatInfoScreenState extends State { Widget build(BuildContext context) { final channel = StreamChannel.of(context).channel; return Scaffold( - backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, body: ListView( children: [ _buildUserHeader(), Container( height: 8.0, - color: StreamChatTheme.of(context).colorTheme.greyGainsboro, + color: StreamChatTheme.of(context).colorTheme.disabled, ), _buildOptionListTiles(), Container( height: 8.0, - color: StreamChatTheme.of(context).colorTheme.greyGainsboro, + color: StreamChatTheme.of(context).colorTheme.disabled, ), if ([ 'admin', @@ -68,7 +68,7 @@ class _ChatInfoScreenState extends State { Widget _buildUserHeader() { return Material( - color: StreamChatTheme.of(context).colorTheme.whiteSnow, + color: StreamChatTheme.of(context).colorTheme.appBg, child: SafeArea( child: Stack( children: [ @@ -96,7 +96,7 @@ class _ChatInfoScreenState extends State { SizedBox(height: 15.0), OptionListTile( title: '@${widget.user!.id}', - tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + tileColor: StreamChatTheme.of(context).colorTheme.appBg, trailing: Padding( padding: const EdgeInsets.symmetric(horizontal: 8.0), child: Text( @@ -104,7 +104,7 @@ class _ChatInfoScreenState extends State { style: TextStyle( color: StreamChatTheme.of(context) .colorTheme - .black + .textHighEmphasis .withOpacity(0.5), fontSize: 16.0), ), @@ -134,7 +134,7 @@ class _ChatInfoScreenState extends State { // title: 'Notifications', // leading: StreamSvgIcon.Icon_notification( // size: 24.0, - // color: StreamChatTheme.of(context).colorTheme.black.withOpacity(0.5), + // color: StreamChatTheme.of(context).colorTheme.textHighEmphasis.withOpacity(0.5), // ), // trailing: CupertinoSwitch( // value: true, @@ -148,7 +148,7 @@ class _ChatInfoScreenState extends State { mutedBool.value = snapshot.data; return OptionListTile( - tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + tileColor: StreamChatTheme.of(context).colorTheme.appBg, title: 'Mute user', titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( @@ -157,7 +157,7 @@ class _ChatInfoScreenState extends State { size: 24.0, color: StreamChatTheme.of(context) .colorTheme - .black + .textHighEmphasis .withOpacity(0.5), ), ), @@ -186,7 +186,7 @@ class _ChatInfoScreenState extends State { // title: 'Block User', // leading: StreamSvgIcon.Icon_user_delete( // size: 24.0, - // color: StreamChatTheme.of(context).colorTheme.black.withOpacity(0.5), + // color: StreamChatTheme.of(context).colorTheme.textHighEmphasis.withOpacity(0.5), // ), // trailing: CupertinoSwitch( // value: widget.user.banned, @@ -202,18 +202,20 @@ class _ChatInfoScreenState extends State { // ), OptionListTile( title: 'Pinned Messages', - tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + tileColor: StreamChatTheme.of(context).colorTheme.appBg, titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( padding: const EdgeInsets.symmetric(horizontal: 22.0), child: StreamSvgIcon.pin( size: 24.0, - color: - StreamChatTheme.of(context).colorTheme.black.withOpacity(0.5), + color: StreamChatTheme.of(context) + .colorTheme + .textHighEmphasis + .withOpacity(0.5), ), ), trailing: StreamSvgIcon.right( - color: StreamChatTheme.of(context).colorTheme.grey, + color: StreamChatTheme.of(context).colorTheme.textLowEmphasis, ), onTap: () { final channel = StreamChannel.of(context).channel; @@ -261,18 +263,20 @@ class _ChatInfoScreenState extends State { ), OptionListTile( title: 'Photos & Videos', - tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + tileColor: StreamChatTheme.of(context).colorTheme.appBg, titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), child: StreamSvgIcon.pictures( size: 36.0, - color: - StreamChatTheme.of(context).colorTheme.black.withOpacity(0.5), + color: StreamChatTheme.of(context) + .colorTheme + .textHighEmphasis + .withOpacity(0.5), ), ), trailing: StreamSvgIcon.right( - color: StreamChatTheme.of(context).colorTheme.grey, + color: StreamChatTheme.of(context).colorTheme.textLowEmphasis, ), onTap: () { final channel = StreamChannel.of(context).channel; @@ -320,18 +324,20 @@ class _ChatInfoScreenState extends State { ), OptionListTile( title: 'Files', - tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + tileColor: StreamChatTheme.of(context).colorTheme.appBg, titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( padding: const EdgeInsets.symmetric(horizontal: 18.0), child: StreamSvgIcon.files( size: 32.0, - color: - StreamChatTheme.of(context).colorTheme.black.withOpacity(0.5), + color: StreamChatTheme.of(context) + .colorTheme + .textHighEmphasis + .withOpacity(0.5), ), ), trailing: StreamSvgIcon.right( - color: StreamChatTheme.of(context).colorTheme.grey, + color: StreamChatTheme.of(context).colorTheme.textLowEmphasis, ), onTap: () { final channel = StreamChannel.of(context).channel; @@ -359,18 +365,20 @@ class _ChatInfoScreenState extends State { ), OptionListTile( title: 'Shared groups', - tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + tileColor: StreamChatTheme.of(context).colorTheme.appBg, titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( padding: const EdgeInsets.symmetric(horizontal: 22.0), child: StreamSvgIcon.iconGroup( size: 24.0, - color: - StreamChatTheme.of(context).colorTheme.black.withOpacity(0.5), + color: StreamChatTheme.of(context) + .colorTheme + .textHighEmphasis + .withOpacity(0.5), ), ), trailing: StreamSvgIcon.right( - color: StreamChatTheme.of(context).colorTheme.grey, + color: StreamChatTheme.of(context).colorTheme.textLowEmphasis, ), onTap: () { Navigator.push( @@ -387,21 +395,21 @@ class _ChatInfoScreenState extends State { Widget _buildDeleteListTile() { return OptionListTile( title: 'Delete Conversation', - tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + tileColor: StreamChatTheme.of(context).colorTheme.appBg, titleTextStyle: StreamChatTheme.of(context).textTheme.body.copyWith( - color: StreamChatTheme.of(context).colorTheme.accentRed, + color: StreamChatTheme.of(context).colorTheme.accentError, ), leading: Padding( padding: const EdgeInsets.symmetric(horizontal: 22.0), child: StreamSvgIcon.delete( - color: StreamChatTheme.of(context).colorTheme.accentRed, + color: StreamChatTheme.of(context).colorTheme.accentError, size: 24.0, ), ), onTap: () { _showDeleteDialog(); }, - titleColor: StreamChatTheme.of(context).colorTheme.accentRed, + titleColor: StreamChatTheme.of(context).colorTheme.accentError, ); } @@ -413,7 +421,7 @@ class _ChatInfoScreenState extends State { question: 'Are you sure you want to delete this conversation?', cancelText: 'CANCEL', icon: StreamSvgIcon.delete( - color: StreamChatTheme.of(context).colorTheme.accentRed, + color: StreamChatTheme.of(context).colorTheme.accentError, ), ); var channel = StreamChannel.of(context).channel; @@ -437,7 +445,7 @@ class _ChatInfoScreenState extends State { style: TextStyle( color: StreamChatTheme.of(context) .colorTheme - .black + .textHighEmphasis .withOpacity(0.5)), ); } else { @@ -446,7 +454,7 @@ class _ChatInfoScreenState extends State { style: TextStyle( color: StreamChatTheme.of(context) .colorTheme - .black + .textHighEmphasis .withOpacity(0.5)), ); } @@ -466,10 +474,10 @@ class _ChatInfoScreenState extends State { ), child: Material( shape: CircleBorder(), - color: StreamChatTheme.of(context).colorTheme.accentGreen, + color: StreamChatTheme.of(context).colorTheme.accentInfo, ), ), - color: StreamChatTheme.of(context).colorTheme.white, + color: StreamChatTheme.of(context).colorTheme.barsBg, ), alternativeWidget, if (widget.user!.online) @@ -497,7 +505,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { var chat = StreamChat.of(context); return Scaffold( - backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, appBar: AppBar( brightness: Theme.of(context).brightness, elevation: 1, @@ -505,11 +513,11 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { title: Text( 'Shared Groups', style: TextStyle( - color: StreamChatTheme.of(context).colorTheme.black, + color: StreamChatTheme.of(context).colorTheme.textHighEmphasis, fontSize: 16.0), ), leading: StreamBackButton(), - backgroundColor: StreamChatTheme.of(context).colorTheme.white, + backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, ), body: StreamBuilder>( stream: chat.client.queryChannels( @@ -532,14 +540,16 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { children: [ StreamSvgIcon.message( size: 136.0, - color: StreamChatTheme.of(context).colorTheme.greyGainsboro, + color: StreamChatTheme.of(context).colorTheme.disabled, ), SizedBox(height: 16.0), Text( 'No Shared Groups', style: TextStyle( fontSize: 14.0, - color: StreamChatTheme.of(context).colorTheme.black, + color: StreamChatTheme.of(context) + .colorTheme + .textHighEmphasis, ), ), SizedBox(height: 8.0), @@ -550,7 +560,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { fontSize: 14.0, color: StreamChatTheme.of(context) .colorTheme - .black + .textHighEmphasis .withOpacity(0.5), ), ), @@ -643,7 +653,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { style: TextStyle( color: StreamChatTheme.of(context) .colorTheme - .black + .textHighEmphasis .withOpacity(0.5)), ), ) @@ -652,8 +662,10 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { ), Container( height: 1.0, - color: - StreamChatTheme.of(context).colorTheme.black.withOpacity(.08), + color: StreamChatTheme.of(context) + .colorTheme + .textHighEmphasis + .withOpacity(.08), ), ], ); diff --git a/stream_chat_v1/lib/chips_input_text_field.dart b/stream_chat_v1/lib/chips_input_text_field.dart index c36e4ae114..a67895e770 100644 --- a/stream_chat_v1/lib/chips_input_text_field.dart +++ b/stream_chat_v1/lib/chips_input_text_field.dart @@ -66,7 +66,7 @@ class ChipInputTextFieldState extends State> { onTap: _pauseItemAddition ? resumeItemAddition : null, child: Material( elevation: 1, - color: StreamChatTheme.of(context).colorTheme.white, + color: StreamChatTheme.of(context).colorTheme.barsBg, child: Container( child: Padding( padding: const EdgeInsets.fromLTRB(16, 16, 16, 16), @@ -82,7 +82,7 @@ class ChipInputTextFieldState extends State> { .copyWith( color: StreamChatTheme.of(context) .colorTheme - .black + .textHighEmphasis .withOpacity(.5)), ), ), @@ -119,7 +119,7 @@ class ChipInputTextFieldState extends State> { .copyWith( color: StreamChatTheme.of(context) .colorTheme - .black + .textHighEmphasis .withOpacity(.5)), ), ), @@ -134,14 +134,14 @@ class ChipInputTextFieldState extends State> { ? StreamSvgIcon.user( color: StreamChatTheme.of(context) .colorTheme - .black + .textHighEmphasis .withOpacity(0.5), size: 24, ) : StreamSvgIcon.userAdd( color: StreamChatTheme.of(context) .colorTheme - .black + .textHighEmphasis .withOpacity(0.5), size: 24, ), diff --git a/stream_chat_v1/lib/choose_user_page.dart b/stream_chat_v1/lib/choose_user_page.dart index e7be235ff7..f50ae5592e 100644 --- a/stream_chat_v1/lib/choose_user_page.dart +++ b/stream_chat_v1/lib/choose_user_page.dart @@ -20,7 +20,7 @@ class ChooseUserPage extends StatelessWidget { final users = defaultUsers; return Scaffold( - backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, body: SafeArea( child: Column( crossAxisAlignment: CrossAxisAlignment.center, @@ -34,7 +34,7 @@ class ChooseUserPage extends StatelessWidget { child: SvgPicture.asset( 'assets/logo.svg', height: 40, - color: StreamChatTheme.of(context).colorTheme.accentBlue, + color: StreamChatTheme.of(context).colorTheme.accentPrimary, ), ), ), @@ -56,7 +56,7 @@ class ChooseUserPage extends StatelessWidget { separatorBuilder: (context, i) { return Container( height: 1, - color: StreamChatTheme.of(context).colorTheme.greyWhisper, + color: StreamChatTheme.of(context).colorTheme.borders, ); }, itemCount: users.length + 1, @@ -80,7 +80,7 @@ class ChooseUserPage extends StatelessWidget { borderRadius: BorderRadius.circular(16), color: StreamChatTheme.of(context) .colorTheme - .white, + .barsBg, ), height: 100, width: 100, @@ -94,7 +94,7 @@ class ChooseUserPage extends StatelessWidget { final client = StreamChatClient( kDefaultStreamApiKey, logLevel: Level.INFO, - )..chatPersistenceClient = chatPersistentClient; + ); await client.connectUser( user, @@ -142,13 +142,13 @@ class ChooseUserPage extends StatelessWidget { .copyWith( color: StreamChatTheme.of(context) .colorTheme - .grey, + .textLowEmphasis, ), ), trailing: StreamSvgIcon.arrowRight( color: StreamChatTheme.of(context) .colorTheme - .accentBlue, + .accentPrimary, ), ); }), @@ -158,11 +158,12 @@ class ChooseUserPage extends StatelessWidget { }, leading: CircleAvatar( child: StreamSvgIcon.settings( - color: StreamChatTheme.of(context).colorTheme.black, + color: StreamChatTheme.of(context) + .colorTheme + .textHighEmphasis, ), - backgroundColor: StreamChatTheme.of(context) - .colorTheme - .greyWhisper, + backgroundColor: + StreamChatTheme.of(context).colorTheme.borders, ), title: Text( 'Advanced Options', @@ -174,8 +175,9 @@ class ChooseUserPage extends StatelessWidget { .textTheme .footnote .copyWith( - color: - StreamChatTheme.of(context).colorTheme.grey, + color: StreamChatTheme.of(context) + .colorTheme + .textLowEmphasis, ), ), trailing: SvgPicture.asset( diff --git a/stream_chat_v1/lib/group_chat_details_screen.dart b/stream_chat_v1/lib/group_chat_details_screen.dart index f4b15ef962..a2f51ed1da 100644 --- a/stream_chat_v1/lib/group_chat_details_screen.dart +++ b/stream_chat_v1/lib/group_chat_details_screen.dart @@ -59,16 +59,16 @@ class _GroupChatDetailsScreenState extends State { return false; }, child: Scaffold( - backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, appBar: AppBar( brightness: Theme.of(context).brightness, elevation: 1, - backgroundColor: StreamChatTheme.of(context).colorTheme.white, + backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, leading: const StreamBackButton(), title: Text( 'Name of Group Chat', style: TextStyle( - color: StreamChatTheme.of(context).colorTheme.black, + color: StreamChatTheme.of(context).colorTheme.textHighEmphasis, fontSize: 16, ), ), @@ -83,7 +83,9 @@ class _GroupChatDetailsScreenState extends State { 'NAME', style: TextStyle( fontSize: 12, - color: StreamChatTheme.of(context).colorTheme.grey, + color: StreamChatTheme.of(context) + .colorTheme + .textLowEmphasis, ), ), SizedBox(width: 16), @@ -101,7 +103,9 @@ class _GroupChatDetailsScreenState extends State { hintText: 'Choose a group chat name', hintStyle: TextStyle( fontSize: 14, - color: StreamChatTheme.of(context).colorTheme.grey, + color: StreamChatTheme.of(context) + .colorTheme + .textLowEmphasis, ), ), ), @@ -117,8 +121,8 @@ class _GroupChatDetailsScreenState extends State { icon: StreamSvgIcon.check( size: 24, color: _isGroupNameEmpty - ? StreamChatTheme.of(context).colorTheme.grey - : StreamChatTheme.of(context).colorTheme.accentBlue, + ? StreamChatTheme.of(context).colorTheme.textLowEmphasis + : StreamChatTheme.of(context).colorTheme.accentPrimary, ), onPressed: _isGroupNameEmpty ? null @@ -188,7 +192,9 @@ class _GroupChatDetailsScreenState extends State { child: Text( '$_totalUsers ${_totalUsers > 1 ? 'Members' : 'Member'}', style: TextStyle( - color: StreamChatTheme.of(context).colorTheme.grey, + color: StreamChatTheme.of(context) + .colorTheme + .textLowEmphasis, ), ), ), @@ -201,9 +207,7 @@ class _GroupChatDetailsScreenState extends State { itemCount: _selectedUsers.length + 1, separatorBuilder: (_, __) => Container( height: 1, - color: StreamChatTheme.of(context) - .colorTheme - .greyWhisper, + color: StreamChatTheme.of(context).colorTheme.borders, ), itemBuilder: (_, index) { if (index == _selectedUsers.length) { @@ -211,7 +215,7 @@ class _GroupChatDetailsScreenState extends State { height: 1, color: StreamChatTheme.of(context) .colorTheme - .greyWhisper, + .borders, ); } final user = _selectedUsers[index]; @@ -237,7 +241,7 @@ class _GroupChatDetailsScreenState extends State { Icons.clear_rounded, color: StreamChatTheme.of(context) .colorTheme - .black, + .textHighEmphasis, ), padding: const EdgeInsets.all(0), splashRadius: 24, @@ -267,7 +271,7 @@ class _GroupChatDetailsScreenState extends State { void _showErrorAlert() { showModalBottomSheet( useRootNavigator: false, - backgroundColor: StreamChatTheme.of(context).colorTheme.white, + backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, context: context, shape: RoundedRectangleBorder( borderRadius: BorderRadius.only( @@ -282,7 +286,7 @@ class _GroupChatDetailsScreenState extends State { height: 26.0, ), StreamSvgIcon.error( - color: StreamChatTheme.of(context).colorTheme.accentRed, + color: StreamChatTheme.of(context).colorTheme.accentError, size: 24.0, ), SizedBox( @@ -300,8 +304,10 @@ class _GroupChatDetailsScreenState extends State { height: 36.0, ), Container( - color: - StreamChatTheme.of(context).colorTheme.black.withOpacity(.08), + color: StreamChatTheme.of(context) + .colorTheme + .textHighEmphasis + .withOpacity(.08), height: 1.0, ), Row( @@ -316,7 +322,7 @@ class _GroupChatDetailsScreenState extends State { .copyWith( color: StreamChatTheme.of(context) .colorTheme - .accentBlue), + .accentPrimary), ), onPressed: () { Navigator.of(context).pop(); diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/group_info_screen.dart index 639175eaf4..4193213c98 100644 --- a/stream_chat_v1/lib/group_info_screen.dart +++ b/stream_chat_v1/lib/group_info_screen.dart @@ -81,7 +81,7 @@ class _GroupInfoScreenState extends State { builder: (context, snapshot) { if (!snapshot.hasData) { return Container( - color: StreamChatTheme.of(context).colorTheme.greyGainsboro, + color: StreamChatTheme.of(context).colorTheme.disabled, child: Center(child: CircularProgressIndicator()), ); } @@ -92,12 +92,12 @@ class _GroupInfoScreenState extends State { var isOwner = userMember?.role == 'owner'; return Scaffold( - backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, appBar: AppBar( brightness: Theme.of(context).brightness, elevation: 1.0, toolbarHeight: 56.0, - backgroundColor: StreamChatTheme.of(context).colorTheme.white, + backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, leading: StreamBackButton(), title: Column( children: [ @@ -108,8 +108,9 @@ class _GroupInfoScreenState extends State { return Text( 'Loading...', style: TextStyle( - color: - StreamChatTheme.of(context).colorTheme.black, + color: StreamChatTheme.of(context) + .colorTheme + .textHighEmphasis, fontSize: 16, ), maxLines: 1, @@ -125,7 +126,9 @@ class _GroupInfoScreenState extends State { maxFontSize: 16.0, )!, style: TextStyle( - color: StreamChatTheme.of(context).colorTheme.black, + color: StreamChatTheme.of(context) + .colorTheme + .textHighEmphasis, fontSize: 16, ), maxLines: 1, @@ -140,7 +143,7 @@ class _GroupInfoScreenState extends State { style: TextStyle( color: StreamChatTheme.of(context) .colorTheme - .black + .textHighEmphasis .withOpacity(0.5), fontSize: 12.0, ), @@ -160,7 +163,7 @@ class _GroupInfoScreenState extends State { child: StreamSvgIcon.userAdd( color: StreamChatTheme.of(context) .colorTheme - .accentBlue), + .accentPrimary), ), ), ), @@ -171,7 +174,7 @@ class _GroupInfoScreenState extends State { _buildMembers(snapshot.data!), Container( height: 8.0, - color: StreamChatTheme.of(context).colorTheme.greyGainsboro, + color: StreamChatTheme.of(context).colorTheme.disabled, ), if (isOwner) _buildNameTile(), _buildOptionListTiles(), @@ -244,7 +247,7 @@ class _GroupInfoScreenState extends State { style: TextStyle( color: StreamChatTheme.of(context) .colorTheme - .black + .textHighEmphasis .withOpacity(0.5)), ), ], @@ -257,7 +260,7 @@ class _GroupInfoScreenState extends State { style: TextStyle( color: StreamChatTheme.of(context) .colorTheme - .black + .textHighEmphasis .withOpacity(0.5)), ), ), @@ -267,13 +270,13 @@ class _GroupInfoScreenState extends State { height: 1.0, color: StreamChatTheme.of(context) .colorTheme - .greyGainsboro, + .disabled, ), ], ), ), ), - color: StreamChatTheme.of(context).colorTheme.whiteSnow, + color: StreamChatTheme.of(context).colorTheme.appBg, ); }, ), @@ -285,7 +288,7 @@ class _GroupInfoScreenState extends State { }); }, child: Material( - color: StreamChatTheme.of(context).colorTheme.whiteSnow, + color: StreamChatTheme.of(context).colorTheme.appBg, child: Container( height: 65.0, child: Column( @@ -297,8 +300,9 @@ class _GroupInfoScreenState extends State { padding: const EdgeInsets.symmetric( horizontal: 21.0, vertical: 12.0), child: StreamSvgIcon.down( - color: - StreamChatTheme.of(context).colorTheme.grey, + color: StreamChatTheme.of(context) + .colorTheme + .textLowEmphasis, ), ), Expanded( @@ -311,7 +315,7 @@ class _GroupInfoScreenState extends State { style: TextStyle( color: StreamChatTheme.of(context) .colorTheme - .grey), + .textLowEmphasis), ), ], ), @@ -321,8 +325,7 @@ class _GroupInfoScreenState extends State { ), Container( height: 1.0, - color: - StreamChatTheme.of(context).colorTheme.greyGainsboro, + color: StreamChatTheme.of(context).colorTheme.disabled, ), ], ), @@ -338,7 +341,7 @@ class _GroupInfoScreenState extends State { var channelName = (channel.extraData['name'] as String?) ?? ''; return Material( - color: StreamChatTheme.of(context).colorTheme.whiteSnow, + color: StreamChatTheme.of(context).colorTheme.appBg, child: Container( height: 56.0, alignment: Alignment.center, @@ -351,7 +354,7 @@ class _GroupInfoScreenState extends State { style: StreamChatTheme.of(context).textTheme.footnote.copyWith( color: StreamChatTheme.of(context) .colorTheme - .black + .textHighEmphasis .withOpacity(0.5)), ), ), @@ -362,7 +365,8 @@ class _GroupInfoScreenState extends State { child: TextField( focusNode: _focusNode, controller: _nameController, - cursorColor: StreamChatTheme.of(context).colorTheme.black, + cursorColor: + StreamChatTheme.of(context).colorTheme.textHighEmphasis, decoration: InputDecoration.collapsed( hintText: 'Add a group name', hintStyle: StreamChatTheme.of(context) @@ -371,7 +375,7 @@ class _GroupInfoScreenState extends State { .copyWith( color: StreamChatTheme.of(context) .colorTheme - .black + .textHighEmphasis .withOpacity(0.5))), style: TextStyle( fontWeight: FontWeight.bold, @@ -401,8 +405,9 @@ class _GroupInfoScreenState extends State { padding: const EdgeInsets.only(right: 16.0, left: 8.0), child: InkWell( child: StreamSvgIcon.check( - color: - StreamChatTheme.of(context).colorTheme.accentBlue, + color: StreamChatTheme.of(context) + .colorTheme + .accentPrimary, size: 24.0, ), onTap: () { @@ -434,7 +439,7 @@ class _GroupInfoScreenState extends State { // title: 'Notifications', // leading: StreamSvgIcon.Icon_notification( // size: 24.0, - // color: StreamChatTheme.of(context).colorTheme.black.withOpacity(0.5), + // color: StreamChatTheme.of(context).colorTheme.textHighEmphasis.withOpacity(0.5), // ), // trailing: CupertinoSwitch( // value: true, @@ -448,9 +453,8 @@ class _GroupInfoScreenState extends State { mutedBool.value = snapshot.data; return OptionListTile( - tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow, - separatorColor: - StreamChatTheme.of(context).colorTheme.greyGainsboro, + tileColor: StreamChatTheme.of(context).colorTheme.appBg, + separatorColor: StreamChatTheme.of(context).colorTheme.disabled, title: 'Mute group', titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( @@ -459,7 +463,7 @@ class _GroupInfoScreenState extends State { size: 24.0, color: StreamChatTheme.of(context) .colorTheme - .black + .textHighEmphasis .withOpacity(0.5), ), ), @@ -486,18 +490,20 @@ class _GroupInfoScreenState extends State { }), OptionListTile( title: 'Pinned Messages', - tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + tileColor: StreamChatTheme.of(context).colorTheme.appBg, titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), child: StreamSvgIcon.pin( size: 24.0, - color: - StreamChatTheme.of(context).colorTheme.black.withOpacity(0.5), + color: StreamChatTheme.of(context) + .colorTheme + .textHighEmphasis + .withOpacity(0.5), ), ), trailing: StreamSvgIcon.right( - color: StreamChatTheme.of(context).colorTheme.grey, + color: StreamChatTheme.of(context).colorTheme.textLowEmphasis, ), onTap: () { final channel = StreamChannel.of(context).channel; @@ -544,20 +550,22 @@ class _GroupInfoScreenState extends State { }, ), OptionListTile( - tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow, - separatorColor: StreamChatTheme.of(context).colorTheme.greyGainsboro, + tileColor: StreamChatTheme.of(context).colorTheme.appBg, + separatorColor: StreamChatTheme.of(context).colorTheme.disabled, title: 'Photos & Videos', titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( padding: const EdgeInsets.symmetric(horizontal: 12.0), child: StreamSvgIcon.pictures( size: 32.0, - color: - StreamChatTheme.of(context).colorTheme.black.withOpacity(0.5), + color: StreamChatTheme.of(context) + .colorTheme + .textHighEmphasis + .withOpacity(0.5), ), ), trailing: StreamSvgIcon.right( - color: StreamChatTheme.of(context).colorTheme.grey, + color: StreamChatTheme.of(context).colorTheme.textLowEmphasis, ), onTap: () { var channel = StreamChannel.of(context).channel; @@ -604,20 +612,22 @@ class _GroupInfoScreenState extends State { }, ), OptionListTile( - tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow, - separatorColor: StreamChatTheme.of(context).colorTheme.greyGainsboro, + tileColor: StreamChatTheme.of(context).colorTheme.appBg, + separatorColor: StreamChatTheme.of(context).colorTheme.disabled, title: 'Files', titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( padding: const EdgeInsets.symmetric(horizontal: 12.0), child: StreamSvgIcon.files( size: 32.0, - color: - StreamChatTheme.of(context).colorTheme.black.withOpacity(0.5), + color: StreamChatTheme.of(context) + .colorTheme + .textHighEmphasis + .withOpacity(0.5), ), ), trailing: StreamSvgIcon.right( - color: StreamChatTheme.of(context).colorTheme.grey, + color: StreamChatTheme.of(context).colorTheme.textLowEmphasis, ), onTap: () { var channel = StreamChannel.of(context).channel; @@ -645,9 +655,8 @@ class _GroupInfoScreenState extends State { ), if (!channel.channel.isDistinct) OptionListTile( - tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow, - separatorColor: - StreamChatTheme.of(context).colorTheme.greyGainsboro, + tileColor: StreamChatTheme.of(context).colorTheme.appBg, + separatorColor: StreamChatTheme.of(context).colorTheme.disabled, title: 'Leave Group', titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( @@ -656,7 +665,7 @@ class _GroupInfoScreenState extends State { size: 24.0, color: StreamChatTheme.of(context) .colorTheme - .black + .textHighEmphasis .withOpacity(0.5), ), ), @@ -672,7 +681,7 @@ class _GroupInfoScreenState extends State { question: 'Are you sure you want to leave this conversation?', cancelText: 'CANCEL', icon: StreamSvgIcon.userRemove( - color: StreamChatTheme.of(context).colorTheme.accentRed, + color: StreamChatTheme.of(context).colorTheme.accentError, ), ); if (res == true) { @@ -762,7 +771,7 @@ class _GroupInfoScreenState extends State { size: 96, color: StreamChatTheme.of(context) .colorTheme - .grey, + .textLowEmphasis, ), ), Text( @@ -800,28 +809,28 @@ class _GroupInfoScreenState extends State { height: 36, child: TextField( controller: _searchController, - cursorColor: theme.colorTheme.black, + cursorColor: theme.colorTheme.textHighEmphasis, autofocus: true, decoration: InputDecoration( hintText: 'Search', hintStyle: theme.textTheme.body.copyWith( - color: theme.colorTheme.grey, + color: theme.colorTheme.textLowEmphasis, ), prefixIconConstraints: BoxConstraints.tight(Size(40, 24)), prefixIcon: StreamSvgIcon.search( - color: theme.colorTheme.black, + color: theme.colorTheme.textHighEmphasis, size: 24, ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(24.0), borderSide: BorderSide( - color: theme.colorTheme.greyWhisper, + color: theme.colorTheme.borders, ), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(24.0), borderSide: BorderSide( - color: theme.colorTheme.greyWhisper, + color: theme.colorTheme.borders, )), contentPadding: const EdgeInsets.all(0), ), @@ -831,7 +840,7 @@ class _GroupInfoScreenState extends State { SizedBox(width: 16.0), IconButton( icon: StreamSvgIcon.closeSmall( - color: theme.colorTheme.grey, + color: theme.colorTheme.textLowEmphasis, ), constraints: BoxConstraints.tightFor( height: 24, @@ -849,7 +858,7 @@ class _GroupInfoScreenState extends State { void _showUserInfoModal(User? user, bool isUserAdmin) { var channel = StreamChannel.of(context).channel; - final color = StreamChatTheme.of(context).colorTheme.white; + final color = StreamChatTheme.of(context).colorTheme.barsBg; showModalBottomSheet( useRootNavigator: false, @@ -899,7 +908,9 @@ class _GroupInfoScreenState extends State { _buildModalListTile( context, StreamSvgIcon.user( - color: StreamChatTheme.of(context).colorTheme.grey, + color: StreamChatTheme.of(context) + .colorTheme + .textLowEmphasis, size: 24.0, ), 'View info', @@ -933,7 +944,9 @@ class _GroupInfoScreenState extends State { _buildModalListTile( context, StreamSvgIcon.message( - color: StreamChatTheme.of(context).colorTheme.grey, + color: StreamChatTheme.of(context) + .colorTheme + .textLowEmphasis, size: 24.0, ), 'Message', @@ -966,7 +979,7 @@ class _GroupInfoScreenState extends State { // _buildModalListTile( // context, // StreamSvgIcon.iconUserSettings( - // color: StreamChatTheme.of(context).colorTheme.grey, + // color: StreamChatTheme.of(context).colorTheme.textLowEmphasis, // size: 24.0, // ), // 'Make Owner', () { @@ -978,8 +991,8 @@ class _GroupInfoScreenState extends State { _buildModalListTile( context, StreamSvgIcon.userRemove( - color: - StreamChatTheme.of(context).colorTheme.accentRed, + color: StreamChatTheme.of(context) + .colorTheme.accentError, size: 24.0, ), 'Remove From Group', () async { @@ -996,11 +1009,15 @@ class _GroupInfoScreenState extends State { await channel.removeMembers([user.id]); } Navigator.pop(context); - }, color: StreamChatTheme.of(context).colorTheme.accentRed), + }, + color: StreamChatTheme.of(context) + .colorTheme.accentError), _buildModalListTile( context, StreamSvgIcon.closeSmall( - color: StreamChatTheme.of(context).colorTheme.grey, + color: StreamChatTheme.of(context) + .colorTheme + .textLowEmphasis, size: 24.0, ), 'Cancel', () { @@ -1033,7 +1050,7 @@ class _GroupInfoScreenState extends State { style: TextStyle( color: StreamChatTheme.of(context) .colorTheme - .black + .textHighEmphasis .withOpacity(0.5)), ); } else { @@ -1042,7 +1059,7 @@ class _GroupInfoScreenState extends State { style: TextStyle( color: StreamChatTheme.of(context) .colorTheme - .black + .textHighEmphasis .withOpacity(0.5)), ); } @@ -1054,17 +1071,17 @@ class _GroupInfoScreenState extends State { Widget _buildModalListTile( BuildContext context, Widget leading, String title, VoidCallback onTap, {Color? color}) { - color ??= StreamChatTheme.of(context).colorTheme.black; + color ??= StreamChatTheme.of(context).colorTheme.textHighEmphasis; return Material( - color: StreamChatTheme.of(context).colorTheme.white, + color: StreamChatTheme.of(context).colorTheme.barsBg, child: InkWell( onTap: onTap, child: Column( children: [ Container( height: 1.0, - color: StreamChatTheme.of(context).colorTheme.greyGainsboro, + color: StreamChatTheme.of(context).colorTheme.disabled, ), Container( height: 64.0, diff --git a/stream_chat_v1/lib/main.dart b/stream_chat_v1/lib/main.dart index e53e8c04d9..e17ef4a5df 100644 --- a/stream_chat_v1/lib/main.dart +++ b/stream_chat_v1/lib/main.dart @@ -18,7 +18,7 @@ import 'routes/routes.dart'; final chatPersistentClient = StreamChatPersistenceClient( logLevel: Level.SEVERE, - connectionMode: ConnectionMode.background, + connectionMode: ConnectionMode.regular, ); void main() async { @@ -46,8 +46,8 @@ class _MyAppState extends State final client = StreamChatClient( apiKey ?? kDefaultStreamApiKey, - logLevel: Level.INFO, - )..chatPersistenceClient = chatPersistentClient; + logLevel: Level.SEVERE, + ); if (userId != null && token != null) { await client.connectUser( diff --git a/stream_chat_v1/lib/new_chat_screen.dart b/stream_chat_v1/lib/new_chat_screen.dart index 1d7f0246a2..41a1ded871 100644 --- a/stream_chat_v1/lib/new_chat_screen.dart +++ b/stream_chat_v1/lib/new_chat_screen.dart @@ -117,18 +117,16 @@ class _NewChatScreenState extends State { @override Widget build(BuildContext context) { return Scaffold( - backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, appBar: AppBar( brightness: Theme.of(context).brightness, elevation: 0, - backgroundColor: StreamChatTheme.of(context).colorTheme.white, + backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, leading: const StreamBackButton(), title: Text( 'New Chat', - style: StreamChatTheme.of(context) - .textTheme - .headlineBold - .copyWith(color: StreamChatTheme.of(context).colorTheme.black), + style: StreamChatTheme.of(context).textTheme.headlineBold.copyWith( + color: StreamChatTheme.of(context).colorTheme.textHighEmphasis), ), centerTitle: true, ), @@ -177,7 +175,7 @@ class _NewChatScreenState extends State { decoration: BoxDecoration( color: StreamChatTheme.of(context) .colorTheme - .greyGainsboro, + .disabled, borderRadius: BorderRadius.circular(12), ), padding: const EdgeInsets.only(left: 24), @@ -189,7 +187,7 @@ class _NewChatScreenState extends State { style: TextStyle( color: StreamChatTheme.of(context) .colorTheme - .black, + .textHighEmphasis, ), ), ), @@ -240,7 +238,7 @@ class _NewChatScreenState extends State { child: StreamSvgIcon.contacts( color: StreamChatTheme.of(context) .colorTheme - .accentBlue, + .accentPrimary, size: 24, ), ), @@ -279,7 +277,7 @@ class _NewChatScreenState extends State { .copyWith( color: StreamChatTheme.of(context) .colorTheme - .black + .textHighEmphasis .withOpacity(.5))), ), ), @@ -350,7 +348,7 @@ class _NewChatScreenState extends State { color: StreamChatTheme .of(context) .colorTheme - .black + .textHighEmphasis .withOpacity(.5)), ), ], @@ -378,7 +376,7 @@ class _NewChatScreenState extends State { fontSize: 12, color: StreamChatTheme.of(context) .colorTheme - .black + .textHighEmphasis .withOpacity(.5), ), ), @@ -396,7 +394,7 @@ class _NewChatScreenState extends State { Navigator.pushNamedAndRemoveUntil( context, Routes.CHANNEL_PAGE, - ModalRoute.withName(Routes.HOME), + ModalRoute.withName(Routes.CHANNEL_LIST_PAGE), arguments: ChannelPageArgs(channel: channel), ); }, diff --git a/stream_chat_v1/lib/new_group_chat_screen.dart b/stream_chat_v1/lib/new_group_chat_screen.dart index 0db780ee65..414606fc05 100644 --- a/stream_chat_v1/lib/new_group_chat_screen.dart +++ b/stream_chat_v1/lib/new_group_chat_screen.dart @@ -51,15 +51,15 @@ class _NewGroupChatScreenState extends State { @override Widget build(BuildContext context) { return Scaffold( - backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, appBar: AppBar( elevation: 1, - backgroundColor: StreamChatTheme.of(context).colorTheme.white, + backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, leading: const StreamBackButton(), title: Text( 'Add Group Members', style: TextStyle( - color: StreamChatTheme.of(context).colorTheme.black, + color: StreamChatTheme.of(context).colorTheme.textHighEmphasis, fontSize: 16, ), ), @@ -68,7 +68,7 @@ class _NewGroupChatScreenState extends State { if (_selectedUsers.isNotEmpty) IconButton( icon: StreamSvgIcon.arrowRight( - color: StreamChatTheme.of(context).colorTheme.accentBlue, + color: StreamChatTheme.of(context).colorTheme.accentPrimary, ), onPressed: () async { final updatedList = await Navigator.pushNamed( @@ -159,18 +159,18 @@ class _NewGroupChatScreenState extends State { decoration: BoxDecoration( color: StreamChatTheme.of(context) .colorTheme - .white, + .appBg, shape: BoxShape.circle, border: Border.all( color: StreamChatTheme.of(context) .colorTheme - .whiteSnow, + .appBg, ), ), child: StreamSvgIcon.close( color: StreamChatTheme.of(context) .colorTheme - .black, + .textHighEmphasis, size: 24, ), ), @@ -212,8 +212,9 @@ class _NewGroupChatScreenState extends State { ? 'Matches for \"$_userNameQuery\"' : 'On the platform', style: TextStyle( - color: - StreamChatTheme.of(context).colorTheme.grey, + color: StreamChatTheme.of(context) + .colorTheme + .textLowEmphasis, ), ), ), @@ -273,7 +274,7 @@ class _NewGroupChatScreenState extends State { size: 96, color: StreamChatTheme.of(context) .colorTheme - .grey, + .textLowEmphasis, ), ), Text( @@ -284,7 +285,7 @@ class _NewGroupChatScreenState extends State { .copyWith( color: StreamChatTheme.of(context) .colorTheme - .grey, + .textLowEmphasis, ), ), ], @@ -319,7 +320,7 @@ class _HeaderDelegate extends SliverPersistentHeaderDelegate { Widget build( BuildContext context, double shrinkOffset, bool overlapsContent) { return Container( - color: StreamChatTheme.of(context).colorTheme.white, + color: StreamChatTheme.of(context).colorTheme.barsBg, child: child, ); } diff --git a/stream_chat_v1/lib/pinned_messages_screen.dart b/stream_chat_v1/lib/pinned_messages_screen.dart index d8f756be0a..11287bb6ad 100644 --- a/stream_chat_v1/lib/pinned_messages_screen.dart +++ b/stream_chat_v1/lib/pinned_messages_screen.dart @@ -58,7 +58,7 @@ class _PinnedMessagesScreenState extends State { @override Widget build(BuildContext context) { return Scaffold( - backgroundColor: StreamChatTheme.of(context).colorTheme.white, + backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, appBar: AppBar( brightness: Theme.of(context).brightness, elevation: 1, @@ -66,12 +66,12 @@ class _PinnedMessagesScreenState extends State { title: Text( 'Pinned Messages', style: TextStyle( - color: StreamChatTheme.of(context).colorTheme.black, + color: StreamChatTheme.of(context).colorTheme.textHighEmphasis, fontSize: 16.0, ), ), leading: StreamBackButton(), - backgroundColor: StreamChatTheme.of(context).colorTheme.white, + backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, ), body: _buildMediaGrid(), ); @@ -98,14 +98,15 @@ class _PinnedMessagesScreenState extends State { children: [ StreamSvgIcon.pin( size: 136.0, - color: StreamChatTheme.of(context).colorTheme.greyGainsboro, + color: StreamChatTheme.of(context).colorTheme.disabled, ), SizedBox(height: 16.0), Text( 'No pinned items', style: TextStyle( fontSize: 17.0, - color: StreamChatTheme.of(context).colorTheme.black, + color: + StreamChatTheme.of(context).colorTheme.textHighEmphasis, fontWeight: FontWeight.bold, ), ), @@ -119,7 +120,7 @@ class _PinnedMessagesScreenState extends State { fontSize: 14.0, color: StreamChatTheme.of(context) .colorTheme - .black + .textHighEmphasis .withOpacity(0.5), ), ), @@ -130,7 +131,7 @@ class _PinnedMessagesScreenState extends State { fontWeight: FontWeight.bold, color: StreamChatTheme.of(context) .colorTheme - .black + .textHighEmphasis .withOpacity(0.5), ), ), @@ -176,7 +177,9 @@ class _PinnedMessagesScreenState extends State { title: Text( user.name, style: TextStyle( - color: StreamChatTheme.of(context).colorTheme.black, + color: StreamChatTheme.of(context) + .colorTheme + .textHighEmphasis, fontWeight: FontWeight.bold), ), subtitle: Text( diff --git a/stream_chat_v1/lib/search_text_field.dart b/stream_chat_v1/lib/search_text_field.dart index c3850c2c44..7641a7b3f4 100644 --- a/stream_chat_v1/lib/search_text_field.dart +++ b/stream_chat_v1/lib/search_text_field.dart @@ -22,9 +22,9 @@ class SearchTextField extends StatelessWidget { return Container( height: 36, decoration: BoxDecoration( - color: StreamChatTheme.of(context).colorTheme.white, + color: StreamChatTheme.of(context).colorTheme.barsBg, border: Border.all( - color: StreamChatTheme.of(context).colorTheme.greyWhisper, + color: StreamChatTheme.of(context).colorTheme.borders, ), borderRadius: BorderRadius.circular(24), ), @@ -48,7 +48,8 @@ class SearchTextField extends StatelessWidget { right: 8, ), child: StreamSvgIcon.search( - color: StreamChatTheme.of(context).colorTheme.black, + color: + StreamChatTheme.of(context).colorTheme.textHighEmphasis, size: 24, ), ), @@ -56,7 +57,7 @@ class SearchTextField extends StatelessWidget { hintStyle: StreamChatTheme.of(context).textTheme.body.copyWith( color: StreamChatTheme.of(context) .colorTheme - .black + .textHighEmphasis .withOpacity(.5)), contentPadding: const EdgeInsets.all(0), border: OutlineInputBorder( diff --git a/stream_chat_v1/lib/stream_version.dart b/stream_chat_v1/lib/stream_version.dart index 740181390d..89004f7563 100644 --- a/stream_chat_v1/lib/stream_version.dart +++ b/stream_chat_v1/lib/stream_version.dart @@ -29,7 +29,7 @@ class StreamVersion extends StatelessWidget { 'Stream SDK v $streamChatDep', style: TextStyle( fontSize: 14, - color: StreamChatTheme.of(context).colorTheme.greyGainsboro, + color: StreamChatTheme.of(context).colorTheme.disabled, ), ); }, diff --git a/stream_chat_v1/lib/thread_page.dart b/stream_chat_v1/lib/thread_page.dart index b9799c7911..d1fbd3c2eb 100644 --- a/stream_chat_v1/lib/thread_page.dart +++ b/stream_chat_v1/lib/thread_page.dart @@ -37,7 +37,7 @@ class _ThreadPageState extends State { @override Widget build(BuildContext context) { return Scaffold( - backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, + backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, appBar: ThreadHeader( parent: widget.parent!, ), diff --git a/stream_chat_v1/lib/user_mentions_page.dart b/stream_chat_v1/lib/user_mentions_page.dart index 837aa19151..d02bd1c6f4 100644 --- a/stream_chat_v1/lib/user_mentions_page.dart +++ b/stream_chat_v1/lib/user_mentions_page.dart @@ -40,9 +40,8 @@ class UserMentionsPage extends StatelessWidget { padding: const EdgeInsets.all(24), child: StreamSvgIcon.mentions( size: 96, - color: StreamChatTheme.of(context) - .colorTheme - .greyGainsboro, + color: + StreamChatTheme.of(context).colorTheme.disabled, ), ), Text( @@ -51,8 +50,9 @@ class UserMentionsPage extends StatelessWidget { .textTheme .body .copyWith( - color: - StreamChatTheme.of(context).colorTheme.grey, + color: StreamChatTheme.of(context) + .colorTheme + .textLowEmphasis, ), ), ], From 4b6bcc97ee44927983f5d77c06bdb2029dc57463 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 6 Jul 2021 17:12:35 +0200 Subject: [PATCH 053/172] update fastlane --- stream_chat_v1/ios/fastlane/Fastfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stream_chat_v1/ios/fastlane/Fastfile b/stream_chat_v1/ios/fastlane/Fastfile index 98d4536d4d..2d46198a85 100644 --- a/stream_chat_v1/ios/fastlane/Fastfile +++ b/stream_chat_v1/ios/fastlane/Fastfile @@ -1,4 +1,4 @@ -fastlane_version "2.162.0" +fastlane_version "2.187.0" default_platform :ios before_all do From a7db4948b7f4811bd2754e7af2c7c0fd3f612086 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 6 Jul 2021 18:04:39 +0200 Subject: [PATCH 054/172] update fastlane --- stream_chat_v1/ios/Gemfile.lock | 141 +++++++++++++++++++------------- 1 file changed, 86 insertions(+), 55 deletions(-) diff --git a/stream_chat_v1/ios/Gemfile.lock b/stream_chat_v1/ios/Gemfile.lock index 2fb075724b..477eef6c05 100644 --- a/stream_chat_v1/ios/Gemfile.lock +++ b/stream_chat_v1/ios/Gemfile.lock @@ -1,57 +1,73 @@ GEM remote: https://rubygems.org/ specs: - CFPropertyList (3.0.2) - addressable (2.7.0) + CFPropertyList (3.0.3) + addressable (2.8.0) public_suffix (>= 2.0.2, < 5.0) + artifactory (3.0.15) atomos (0.1.3) - aws-eventstream (1.1.0) - aws-partitions (1.380.0) - aws-sdk-core (3.109.1) + aws-eventstream (1.1.1) + aws-partitions (1.473.0) + aws-sdk-core (3.115.0) aws-eventstream (~> 1, >= 1.0.2) aws-partitions (~> 1, >= 1.239.0) aws-sigv4 (~> 1.1) jmespath (~> 1.0) - aws-sdk-kms (1.39.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-kms (1.44.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.83.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-s3 (1.96.1) + aws-sdk-core (~> 3, >= 3.112.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.1) - aws-sigv4 (1.2.2) + aws-sigv4 (1.2.3) aws-eventstream (~> 1, >= 1.0.2) - babosa (1.0.3) + babosa (1.0.4) claide (1.0.3) colored (1.2) colored2 (3.1.2) - commander-fastlane (4.4.6) - highline (~> 1.7.2) + commander (4.6.0) + highline (~> 2.0.0) declarative (0.0.20) - declarative-option (0.1.0) - digest-crc (0.6.1) - rake (~> 13.0) + digest-crc (0.6.3) + rake (>= 12.0.0, < 14.0.0) domain_name (0.5.20190701) unf (>= 0.0.5, < 1.0.0) dotenv (2.7.6) - emoji_regex (3.0.0) - excon (0.76.0) - faraday (1.0.1) + emoji_regex (3.2.2) + excon (0.83.0) + faraday (1.5.0) + faraday-em_http (~> 1.0) + faraday-em_synchrony (~> 1.0) + faraday-excon (~> 1.1) + faraday-httpclient (~> 1.0.1) + faraday-net_http (~> 1.0) + faraday-net_http_persistent (~> 1.1) + faraday-patron (~> 1.0) multipart-post (>= 1.2, < 3) + ruby2_keywords (>= 0.0.4) faraday-cookie_jar (0.0.7) faraday (>= 0.8.0) http-cookie (~> 1.0.0) + faraday-em_http (1.0.0) + faraday-em_synchrony (1.0.0) + faraday-excon (1.1.0) + faraday-httpclient (1.0.1) + faraday-net_http (1.0.1) + faraday-net_http_persistent (1.1.0) + faraday-patron (1.0.0) faraday_middleware (1.0.0) faraday (~> 1.0) - fastimage (2.2.0) - fastlane (2.162.0) + fastimage (2.2.4) + fastlane (2.187.0) CFPropertyList (>= 2.3, < 4.0.0) addressable (>= 2.3, < 3.0.0) + artifactory (~> 3.0) aws-sdk-s3 (~> 1.0) babosa (>= 1.0.3, < 2.0.0) bundler (>= 1.12.0, < 3.0.0) colored - commander-fastlane (>= 4.4.6, < 5.0.0) + commander (~> 4.6) dotenv (>= 2.1.1, < 3.0.0) emoji_regex (>= 0.1, < 4.0) excon (>= 0.71.0, < 1.0.0) @@ -60,18 +76,19 @@ GEM faraday_middleware (~> 1.0) fastimage (>= 2.1.0, < 3.0.0) gh_inspector (>= 1.1.2, < 2.0.0) - google-api-client (>= 0.37.0, < 0.39.0) - google-cloud-storage (>= 1.15.0, < 2.0.0) - highline (>= 1.7.2, < 2.0.0) + google-apis-androidpublisher_v3 (~> 0.1) + google-apis-playcustomapp_v1 (~> 0.1) + google-cloud-storage (~> 1.31) + highline (~> 2.0) json (< 3.0.0) jwt (>= 2.1.0, < 3) mini_magick (>= 4.9.4, < 5.0.0) multipart-post (~> 2.0.0) + naturally (~> 2.2) plist (>= 3.1.0, < 4.0.0) rubyzip (>= 2.0.0, < 3.0.0) security (= 0.1.3) simctl (~> 1.6.3) - slack-notifier (>= 2.0.0, < 3.0.0) terminal-notifier (>= 2.0.0, < 3.0.0) terminal-table (>= 1.4.5, < 2.0.0) tty-screen (>= 0.6.3, < 1.0.0) @@ -82,61 +99,73 @@ GEM xcpretty-travis-formatter (>= 0.0.3) fastlane-plugin-firebase_app_distribution (0.2.7) gh_inspector (1.1.3) - google-api-client (0.38.0) + google-apis-androidpublisher_v3 (0.8.0) + google-apis-core (>= 0.4, < 2.a) + google-apis-core (0.4.0) addressable (~> 2.5, >= 2.5.1) - googleauth (~> 0.9) - httpclient (>= 2.8.1, < 3.0) + googleauth (>= 0.16.2, < 2.a) + httpclient (>= 2.8.1, < 3.a) mini_mime (~> 1.0) representable (~> 3.0) - retriable (>= 2.0, < 4.0) - signet (~> 0.12) - google-cloud-core (1.5.0) + retriable (>= 2.0, < 4.a) + rexml + webrick + google-apis-iamcredentials_v1 (0.6.0) + google-apis-core (>= 0.4, < 2.a) + google-apis-playcustomapp_v1 (0.5.0) + google-apis-core (>= 0.4, < 2.a) + google-apis-storage_v1 (0.6.0) + google-apis-core (>= 0.4, < 2.a) + google-cloud-core (1.6.0) google-cloud-env (~> 1.0) google-cloud-errors (~> 1.0) - google-cloud-env (1.3.3) + google-cloud-env (1.5.0) faraday (>= 0.17.3, < 2.0) - google-cloud-errors (1.0.1) - google-cloud-storage (1.29.1) + google-cloud-errors (1.1.0) + google-cloud-storage (1.34.0) addressable (~> 2.5) digest-crc (~> 0.4) - google-api-client (~> 0.33) - google-cloud-core (~> 1.2) - googleauth (~> 0.9) + google-apis-iamcredentials_v1 (~> 0.1) + google-apis-storage_v1 (~> 0.1) + google-cloud-core (~> 1.6) + googleauth (>= 0.16.2, < 2.a) mini_mime (~> 1.0) - googleauth (0.13.1) + googleauth (0.16.2) faraday (>= 0.17.3, < 2.0) jwt (>= 1.4, < 3.0) memoist (~> 0.16) multi_json (~> 1.11) os (>= 0.9, < 2.0) signet (~> 0.14) - highline (1.7.10) - http-cookie (1.0.3) + highline (2.0.3) + http-cookie (1.0.4) domain_name (~> 0.5) httpclient (2.8.3) jmespath (1.4.0) - json (2.3.1) - jwt (2.2.2) + json (2.5.1) + jwt (2.2.3) memoist (0.16.2) - mini_magick (4.10.1) - mini_mime (1.0.2) + mini_magick (4.11.0) + mini_mime (1.1.0) multi_json (1.15.0) multipart-post (2.0.0) nanaimo (0.3.0) - naturally (2.2.0) + naturally (2.2.1) os (1.1.1) - plist (3.5.0) + plist (3.6.0) public_suffix (4.0.6) - rake (13.0.1) - representable (3.0.4) + rake (13.0.4) + representable (3.1.1) declarative (< 0.1.0) - declarative-option (< 0.2.0) + trailblazer-option (>= 0.1.1, < 0.2.0) uber (< 0.2.0) retriable (3.1.2) + rexml (3.2.5) rouge (2.0.7) - rubyzip (2.3.0) + ruby2_keywords (0.0.4) + rubyzip (2.3.2) security (0.1.3) - signet (0.14.0) + signet (0.15.0) addressable (~> 2.3) faraday (>= 0.17.3, < 2.0) jwt (>= 1.5, < 3.0) @@ -144,10 +173,10 @@ GEM simctl (1.6.8) CFPropertyList naturally - slack-notifier (2.3.2) terminal-notifier (2.0.0) terminal-table (1.8.0) unicode-display_width (~> 1.1, >= 1.1.1) + trailblazer-option (0.1.1) tty-cursor (0.7.1) tty-screen (0.8.1) tty-spinner (0.9.3) @@ -157,16 +186,18 @@ GEM unf_ext unf_ext (0.0.7.7) unicode-display_width (1.7.0) + webrick (1.7.0) word_wrap (1.0.0) - xcodeproj (1.18.0) + xcodeproj (1.20.0) CFPropertyList (>= 2.3.3, < 4.0) atomos (~> 0.1.3) claide (>= 1.0.2, < 2.0) colored2 (~> 3.1) nanaimo (~> 0.3.0) + rexml (~> 3.2.4) xcpretty (0.3.0) rouge (~> 2.0.7) - xcpretty-travis-formatter (1.0.0) + xcpretty-travis-formatter (1.0.1) xcpretty (~> 0.2, >= 0.0.7) PLATFORMS From a1aac27e065abdc3cce0209389d817c1c01b24df Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 6 Jul 2021 18:34:25 +0200 Subject: [PATCH 055/172] update fastlane --- stream_chat_v1/ios/Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stream_chat_v1/ios/Gemfile.lock b/stream_chat_v1/ios/Gemfile.lock index 477eef6c05..06d690f33b 100644 --- a/stream_chat_v1/ios/Gemfile.lock +++ b/stream_chat_v1/ios/Gemfile.lock @@ -97,7 +97,7 @@ GEM xcodeproj (>= 1.13.0, < 2.0.0) xcpretty (~> 0.3.0) xcpretty-travis-formatter (>= 0.0.3) - fastlane-plugin-firebase_app_distribution (0.2.7) + fastlane-plugin-firebase_app_distribution (0.2.9) gh_inspector (1.1.3) google-apis-androidpublisher_v3 (0.8.0) google-apis-core (>= 0.4, < 2.a) From dae763a4510f56adeb0fe46bd681e1eb4c9f6692 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 19 Jul 2021 16:32:50 +0200 Subject: [PATCH 056/172] align with latest stable --- stream_chat_v1/lib/channel_page.dart | 44 +++++++++++++----------- stream_chat_v1/lib/chat_info_screen.dart | 2 +- stream_chat_v1/lib/choose_user_page.dart | 1 - stream_chat_v1/lib/thread_page.dart | 6 +++- 4 files changed, 30 insertions(+), 23 deletions(-) diff --git a/stream_chat_v1/lib/channel_page.dart b/stream_chat_v1/lib/channel_page.dart index 0bdb6b6846..571a54db47 100644 --- a/stream_chat_v1/lib/channel_page.dart +++ b/stream_chat_v1/lib/channel_page.dart @@ -113,31 +113,35 @@ class _ChannelPageState extends State { initialAlignment: widget.initialAlignment, highlightInitialMessage: widget.highlightInitialMessage, onMessageSwiped: _reply, - onReplyTap: _reply, + messageBuilder: (context, details, messages, defaultMessage) { + return defaultMessage.copyWith( + onReplyTap: _reply, + onShowMessage: (m, c) async { + final client = StreamChat.of(context).client; + final message = m; + final channel = client.channel( + c.type, + id: c.id, + ); + if (channel.state == null) { + await channel.watch(); + } + Navigator.pushReplacementNamed( + context, + Routes.CHANNEL_PAGE, + arguments: ChannelPageArgs( + channel: channel, + initialMessage: message, + ), + ); + }, + ); + }, threadBuilder: (_, parentMessage) { return ThreadPage( parent: parentMessage, ); }, - onShowMessage: (m, c) async { - final client = StreamChat.of(context).client; - final message = m; - final channel = client.channel( - c.type, - id: c.id, - ); - if (channel.state == null) { - await channel.watch(); - } - Navigator.pushReplacementNamed( - context, - Routes.CHANNEL_PAGE, - arguments: ChannelPageArgs( - channel: channel, - initialMessage: message, - ), - ); - }, pinPermissions: ['owner', 'admin', 'member'], ), Positioned( diff --git a/stream_chat_v1/lib/chat_info_screen.dart b/stream_chat_v1/lib/chat_info_screen.dart index 013851b3e7..6c6bb1ec07 100644 --- a/stream_chat_v1/lib/chat_info_screen.dart +++ b/stream_chat_v1/lib/chat_info_screen.dart @@ -635,7 +635,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { children: [ Padding( padding: const EdgeInsets.all(8.0), - child: ChannelImage( + child: ChannelAvatar( channel: channel, constraints: BoxConstraints(maxWidth: 40.0, maxHeight: 40.0), diff --git a/stream_chat_v1/lib/choose_user_page.dart b/stream_chat_v1/lib/choose_user_page.dart index f50ae5592e..e487acd455 100644 --- a/stream_chat_v1/lib/choose_user_page.dart +++ b/stream_chat_v1/lib/choose_user_page.dart @@ -7,7 +7,6 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -import 'main.dart'; import 'routes/routes.dart'; const kStreamApiKey = 'STREAM_API_KEY'; diff --git a/stream_chat_v1/lib/thread_page.dart b/stream_chat_v1/lib/thread_page.dart index d1fbd3c2eb..5d032f8b14 100644 --- a/stream_chat_v1/lib/thread_page.dart +++ b/stream_chat_v1/lib/thread_page.dart @@ -49,7 +49,11 @@ class _ThreadPageState extends State { initialScrollIndex: widget.initialScrollIndex, initialAlignment: widget.initialAlignment, onMessageSwiped: _reply, - onReplyTap: _reply, + messageBuilder: (context, details, messages, defaultMessage) { + return defaultMessage.copyWith( + onReplyTap: _reply, + ); + }, pinPermissions: ['owner', 'admin', 'member'], ), ), From 52a8d629401fda05269974fcd260b927c098ecf6 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 19 Jul 2021 16:40:32 +0200 Subject: [PATCH 057/172] update pubspec --- stream_chat_v1/pubspec.yaml | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index 9dd7471fdd..dd6906309a 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -1,7 +1,7 @@ name: example description: A new Flutter project. publish_to: 'none' -version: 1.6.1 +version: 1.7.0 environment: sdk: '>=2.12.0 <3.0.0' @@ -10,16 +10,8 @@ dependencies: flutter_app_badger: ^1.2.0 flutter: sdk: flutter - stream_chat_flutter: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop - path: packages/stream_chat_flutter - stream_chat_persistence: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop - path: packages/stream_chat_persistence + stream_chat_flutter: ^2.0.0 + stream_chat_persistence: ^2.0.0 flutter_local_notifications: ^5.0.0+4 flutter_svg: ^0.22.0 flutter_secure_storage: ^4.2.0 From d7dd9c9396c8ac5bc542908e22890713d1f549e5 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 19 Jul 2021 17:43:17 +0200 Subject: [PATCH 058/172] fix android build --- stream_chat_v1/android/app/build.gradle | 4 ++-- stream_chat_v1/android/build.gradle | 4 ++-- .../android/gradle/wrapper/gradle-wrapper.properties | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/stream_chat_v1/android/app/build.gradle b/stream_chat_v1/android/app/build.gradle index e91ca1bbe0..ce7eeeea5f 100644 --- a/stream_chat_v1/android/app/build.gradle +++ b/stream_chat_v1/android/app/build.gradle @@ -26,7 +26,7 @@ apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - compileSdkVersion 29 + compileSdkVersion 30 ndkVersion '21.4.7075529' sourceSets { @@ -41,7 +41,7 @@ android { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.example.example" minSdkVersion 21 - targetSdkVersion 29 + targetSdkVersion 30 versionCode flutterVersionCode.toInteger() versionName flutterVersionName testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/stream_chat_v1/android/build.gradle b/stream_chat_v1/android/build.gradle index 8c57e18a0f..aeb95a68c9 100644 --- a/stream_chat_v1/android/build.gradle +++ b/stream_chat_v1/android/build.gradle @@ -1,12 +1,12 @@ buildscript { - ext.kotlin_version = '1.3.50' + ext.kotlin_version = '1.5.20' repositories { google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.6.2' + classpath 'com.android.tools.build:gradle:4.2.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'com.google.gms:google-services:4.3.2' } diff --git a/stream_chat_v1/android/gradle/wrapper/gradle-wrapper.properties b/stream_chat_v1/android/gradle/wrapper/gradle-wrapper.properties index c0a81d1105..bdbde4da10 100644 --- a/stream_chat_v1/android/gradle/wrapper/gradle-wrapper.properties +++ b/stream_chat_v1/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.9-all.zip From 08c17ca6fb2077604227ed74e8257908f513a50b Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 20 Jul 2021 11:31:53 +0200 Subject: [PATCH 059/172] use persistence storage --- stream_chat_v1/lib/choose_user_page.dart | 3 ++- stream_chat_v1/lib/main.dart | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/stream_chat_v1/lib/choose_user_page.dart b/stream_chat_v1/lib/choose_user_page.dart index e487acd455..7a4f2638be 100644 --- a/stream_chat_v1/lib/choose_user_page.dart +++ b/stream_chat_v1/lib/choose_user_page.dart @@ -7,6 +7,7 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; +import 'main.dart'; import 'routes/routes.dart'; const kStreamApiKey = 'STREAM_API_KEY'; @@ -93,7 +94,7 @@ class ChooseUserPage extends StatelessWidget { final client = StreamChatClient( kDefaultStreamApiKey, logLevel: Level.INFO, - ); + )..chatPersistenceClient = chatPersistentClient; await client.connectUser( user, diff --git a/stream_chat_v1/lib/main.dart b/stream_chat_v1/lib/main.dart index e17ef4a5df..bdbee244be 100644 --- a/stream_chat_v1/lib/main.dart +++ b/stream_chat_v1/lib/main.dart @@ -47,7 +47,7 @@ class _MyAppState extends State final client = StreamChatClient( apiKey ?? kDefaultStreamApiKey, logLevel: Level.SEVERE, - ); + )..chatPersistenceClient = chatPersistentClient; if (userId != null && token != null) { await client.connectUser( From c360aa787df50cad6f00f0ff9980fc0eadadbdd3 Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Wed, 28 Jul 2021 12:43:30 +0530 Subject: [PATCH 060/172] added filters to MessageListView --- stream_chat_v1/lib/channel_page.dart | 9 +++++++++ stream_chat_v1/lib/group_info_screen.dart | 11 +++++------ stream_chat_v1/lib/thread_page.dart | 9 +++++++++ 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/stream_chat_v1/lib/channel_page.dart b/stream_chat_v1/lib/channel_page.dart index 571a54db47..51a2c56675 100644 --- a/stream_chat_v1/lib/channel_page.dart +++ b/stream_chat_v1/lib/channel_page.dart @@ -113,6 +113,7 @@ class _ChannelPageState extends State { initialAlignment: widget.initialAlignment, highlightInitialMessage: widget.highlightInitialMessage, onMessageSwiped: _reply, + messageFilter: defaultFilter, messageBuilder: (context, details, messages, defaultMessage) { return defaultMessage.copyWith( onReplyTap: _reply, @@ -185,4 +186,12 @@ class _ChannelPageState extends State { ), ); } + + bool defaultFilter(Message m) { + var _currentUser = StreamChat.of(context).currentUser; + final isMyMessage = m.user?.id == _currentUser?.id; + final isDeletedOrShadowed = m.isDeleted == true || m.shadowed == true; + if (isDeletedOrShadowed && !isMyMessage) return false; + return true; + } } diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/group_info_screen.dart index 4193213c98..c3ea08706b 100644 --- a/stream_chat_v1/lib/group_info_screen.dart +++ b/stream_chat_v1/lib/group_info_screen.dart @@ -268,9 +268,7 @@ class _GroupInfoScreenState extends State { ), Container( height: 1.0, - color: StreamChatTheme.of(context) - .colorTheme - .disabled, + color: StreamChatTheme.of(context).colorTheme.disabled, ), ], ), @@ -992,7 +990,8 @@ class _GroupInfoScreenState extends State { context, StreamSvgIcon.userRemove( color: StreamChatTheme.of(context) - .colorTheme.accentError, + .colorTheme + .accentError, size: 24.0, ), 'Remove From Group', () async { @@ -1010,8 +1009,8 @@ class _GroupInfoScreenState extends State { } Navigator.pop(context); }, - color: StreamChatTheme.of(context) - .colorTheme.accentError), + color: + StreamChatTheme.of(context).colorTheme.accentError), _buildModalListTile( context, StreamSvgIcon.closeSmall( diff --git a/stream_chat_v1/lib/thread_page.dart b/stream_chat_v1/lib/thread_page.dart index 5d032f8b14..5e9b22782c 100644 --- a/stream_chat_v1/lib/thread_page.dart +++ b/stream_chat_v1/lib/thread_page.dart @@ -49,6 +49,7 @@ class _ThreadPageState extends State { initialScrollIndex: widget.initialScrollIndex, initialAlignment: widget.initialAlignment, onMessageSwiped: _reply, + messageFilter: defaultFilter, messageBuilder: (context, details, messages, defaultMessage) { return defaultMessage.copyWith( onReplyTap: _reply, @@ -71,4 +72,12 @@ class _ThreadPageState extends State { ), ); } + + bool defaultFilter(Message m) { + var _currentUser = StreamChat.of(context).currentUser; + final isMyMessage = m.user?.id == _currentUser?.id; + final isDeletedOrShadowed = m.isDeleted == true || m.shadowed == true; + if (isDeletedOrShadowed && !isMyMessage) return false; + return true; + } } From 8f249b5c6e211c7c56049e359e660d61ba059d3b Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Wed, 28 Jul 2021 13:00:53 +0530 Subject: [PATCH 061/172] fixed deps --- stream_chat_v1/pubspec.yaml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index dd6906309a..f1aa4a2aa1 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -10,8 +10,16 @@ dependencies: flutter_app_badger: ^1.2.0 flutter: sdk: flutter - stream_chat_flutter: ^2.0.0 - stream_chat_persistence: ^2.0.0 + stream_chat_flutter: + git: + url: https://github.com/GetStream/stream-chat-flutter.git + ref: develop + path: packages/stream_chat_flutter + stream_chat_persistence: + git: + url: https://github.com/GetStream/stream-chat-flutter.git + ref: develop + path: packages/stream_chat_persistence flutter_local_notifications: ^5.0.0+4 flutter_svg: ^0.22.0 flutter_secure_storage: ^4.2.0 From 35a54c4c9925d7acae6dbd5930c7d98cb25dab70 Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Wed, 28 Jul 2021 13:03:21 +0530 Subject: [PATCH 062/172] fixed deps --- stream_chat_v1/pubspec.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index f1aa4a2aa1..cc9a05e027 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -32,6 +32,19 @@ dependencies: dev_dependencies: flutter_launcher_icons: ^0.9.0 test: any + +dependency_overrides: + stream_chat: + git: + url: https://github.com/GetStream/stream-chat-flutter.git + ref: develop + path: packages/stream_chat + stream_chat_flutter_core: + git: + url: https://github.com/GetStream/stream-chat-flutter.git + ref: develop + path: packages/stream_chat_flutter_core + flutter: assets: - assets/ From 608bd808608c37edb68ebebdc44e529ec5d60c60 Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Wed, 28 Jul 2021 13:13:11 +0530 Subject: [PATCH 063/172] added visible footnote --- stream_chat_v1/lib/channel_page.dart | 3 +++ stream_chat_v1/lib/thread_page.dart | 3 +++ 2 files changed, 6 insertions(+) diff --git a/stream_chat_v1/lib/channel_page.dart b/stream_chat_v1/lib/channel_page.dart index 51a2c56675..557e6c933b 100644 --- a/stream_chat_v1/lib/channel_page.dart +++ b/stream_chat_v1/lib/channel_page.dart @@ -136,6 +136,9 @@ class _ChannelPageState extends State { ), ); }, + deletedBottomRowBuilder: (context, message) { + return VisibleFootnote(); + }, ); }, threadBuilder: (_, parentMessage) { diff --git a/stream_chat_v1/lib/thread_page.dart b/stream_chat_v1/lib/thread_page.dart index 5e9b22782c..6292a1ee56 100644 --- a/stream_chat_v1/lib/thread_page.dart +++ b/stream_chat_v1/lib/thread_page.dart @@ -53,6 +53,9 @@ class _ThreadPageState extends State { messageBuilder: (context, details, messages, defaultMessage) { return defaultMessage.copyWith( onReplyTap: _reply, + deletedBottomRowBuilder: (context, message) { + return VisibleFootnote(); + }, ); }, pinPermissions: ['owner', 'admin', 'member'], From 1f5c7e03aea3b221a06b51c493dd6fb61a2cb78d Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Wed, 28 Jul 2021 13:14:10 +0530 Subject: [PATCH 064/172] added const --- stream_chat_v1/lib/channel_page.dart | 2 +- stream_chat_v1/lib/thread_page.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/stream_chat_v1/lib/channel_page.dart b/stream_chat_v1/lib/channel_page.dart index 557e6c933b..cb72680ee3 100644 --- a/stream_chat_v1/lib/channel_page.dart +++ b/stream_chat_v1/lib/channel_page.dart @@ -137,7 +137,7 @@ class _ChannelPageState extends State { ); }, deletedBottomRowBuilder: (context, message) { - return VisibleFootnote(); + return const VisibleFootnote(); }, ); }, diff --git a/stream_chat_v1/lib/thread_page.dart b/stream_chat_v1/lib/thread_page.dart index 6292a1ee56..5e9d4fc54a 100644 --- a/stream_chat_v1/lib/thread_page.dart +++ b/stream_chat_v1/lib/thread_page.dart @@ -54,7 +54,7 @@ class _ThreadPageState extends State { return defaultMessage.copyWith( onReplyTap: _reply, deletedBottomRowBuilder: (context, message) { - return VisibleFootnote(); + return const VisibleFootnote(); }, ); }, From 994c429ab7bf641c7841b467ce4c6cc2460d56ef Mon Sep 17 00:00:00 2001 From: sonykurian96 Date: Wed, 28 Jul 2021 21:19:09 +0530 Subject: [PATCH 065/172] fixed deprecation issues --- stream_chat_v1/lib/channel_list.dart | 4 ++-- stream_chat_v1/lib/channel_list_page.dart | 2 +- stream_chat_v1/lib/channel_page.dart | 2 +- stream_chat_v1/lib/chat_info_screen.dart | 6 +++--- .../lib/group_chat_details_screen.dart | 2 +- stream_chat_v1/lib/group_info_screen.dart | 20 +++++++++---------- stream_chat_v1/lib/main.dart | 2 +- stream_chat_v1/lib/new_chat_screen.dart | 6 +++--- stream_chat_v1/lib/new_group_chat_screen.dart | 2 +- stream_chat_v1/lib/user_mentions_page.dart | 2 +- 10 files changed, 24 insertions(+), 24 deletions(-) diff --git a/stream_chat_v1/lib/channel_list.dart b/stream_chat_v1/lib/channel_list.dart index c31fabb469..e0545185d4 100644 --- a/stream_chat_v1/lib/channel_list.dart +++ b/stream_chat_v1/lib/channel_list.dart @@ -50,7 +50,7 @@ class _ChannelList extends State { @override Widget build(BuildContext context) { - final user = StreamChat.of(context).user; + final user = StreamChat.of(context).currentUser; return WillPopScope( onWillPop: () async { if (_isSearchActive) { @@ -167,7 +167,7 @@ class _ChannelList extends State { user: channel.state!.members .where((m) => m.userId != - channel.client.state.user!.id) + channel.client.state.currentUser!.id) .first .user, ), diff --git a/stream_chat_v1/lib/channel_list_page.dart b/stream_chat_v1/lib/channel_list_page.dart index 5379062c45..76df0fb4bc 100644 --- a/stream_chat_v1/lib/channel_list_page.dart +++ b/stream_chat_v1/lib/channel_list_page.dart @@ -63,7 +63,7 @@ class _ChannelListPageState extends State { @override Widget build(BuildContext context) { - final user = StreamChat.of(context).user; + final user = StreamChat.of(context).currentUser; if (user == null) { return Offstage(); } diff --git a/stream_chat_v1/lib/channel_page.dart b/stream_chat_v1/lib/channel_page.dart index 571a54db47..e67c49360a 100644 --- a/stream_chat_v1/lib/channel_page.dart +++ b/stream_chat_v1/lib/channel_page.dart @@ -66,7 +66,7 @@ class _ChannelPageState extends State { var channel = StreamChannel.of(context).channel; if (channel.memberCount == 2 && channel.isDistinct) { - final currentUser = StreamChat.of(context).user; + final currentUser = StreamChat.of(context).currentUser; final otherUser = channel.state!.members.firstWhereOrNull( (element) => element.user!.id != currentUser!.id, ); diff --git a/stream_chat_v1/lib/chat_info_screen.dart b/stream_chat_v1/lib/chat_info_screen.dart index 6c6bb1ec07..0f7a8a9954 100644 --- a/stream_chat_v1/lib/chat_info_screen.dart +++ b/stream_chat_v1/lib/chat_info_screen.dart @@ -58,7 +58,7 @@ class _ChatInfoScreenState extends State { 'owner', ].contains(channel.state!.members .firstWhereOrNull( - (m) => m.userId == channel.client.state.user!.id) + (m) => m.userId == channel.client.state.currentUser!.id) ?.role)) _buildDeleteListTile(), ], @@ -385,7 +385,7 @@ class _ChatInfoScreenState extends State { context, MaterialPageRoute( builder: (context) => _SharedGroupsScreen( - StreamChat.of(context).user, widget.user))); + StreamChat.of(context).currentUser, widget.user))); }, ), ], @@ -603,7 +603,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { String? title; if (extraData['name'] == null) { final otherMembers = members.where( - (member) => member.userId != StreamChat.of(context).user!.id); + (member) => member.userId != StreamChat.of(context).currentUser!.id); if (otherMembers.isNotEmpty) { final maxWidth = constraints.maxWidth; final maxChars = maxWidth / textStyle.fontSize!; diff --git a/stream_chat_v1/lib/group_chat_details_screen.dart b/stream_chat_v1/lib/group_chat_details_screen.dart index a2f51ed1da..b61bf665b0 100644 --- a/stream_chat_v1/lib/group_chat_details_screen.dart +++ b/stream_chat_v1/lib/group_chat_details_screen.dart @@ -134,7 +134,7 @@ class _GroupChatDetailsScreenState extends State { id: Uuid().v4(), extraData: { 'members': [ - client.state.user!.id, + client.state.currentUser!.id, ..._selectedUsers.map((e) => e.id), ], 'name': groupName, diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/group_info_screen.dart index 4193213c98..02957b4cce 100644 --- a/stream_chat_v1/lib/group_info_screen.dart +++ b/stream_chat_v1/lib/group_info_screen.dart @@ -87,7 +87,7 @@ class _GroupInfoScreenState extends State { } var userMember = snapshot.data!.firstWhereOrNull( - (e) => e.user!.id == StreamChat.of(context).user!.id, + (e) => e.user!.id == StreamChat.of(context).currentUser!.id, ); var isOwner = userMember?.role == 'owner'; @@ -211,7 +211,7 @@ class _GroupInfoScreenState extends State { child: InkWell( onTap: () { final userMember = groupMembers.firstWhereOrNull( - (e) => e.user!.id == StreamChat.of(context).user!.id, + (e) => e.user!.id == StreamChat.of(context).currentUser!.id, ); _showUserInfoModal(member.user, userMember?.role == 'owner'); }, @@ -686,7 +686,7 @@ class _GroupInfoScreenState extends State { ); if (res == true) { final channel = StreamChannel.of(context).channel; - await channel.removeMembers([StreamChat.of(context).user!.id]); + await channel.removeMembers([StreamChat.of(context).currentUser!.id]); Navigator.pop(context); } }, @@ -740,7 +740,7 @@ class _GroupInfoScreenState extends State { if (_searchController!.text.isNotEmpty) Filter.autoComplete('name', _userNameQuery), Filter.notIn('id', [ - StreamChat.of(context).user!.id, + StreamChat.of(context).currentUser!.id, ...channel.state!.members .map(((e) => e.userId)) .whereType(), @@ -904,7 +904,7 @@ class _GroupInfoScreenState extends State { ), ), ), - if (StreamChat.of(context).user!.id != user.id) + if (StreamChat.of(context).currentUser!.id != user.id) _buildModalListTile( context, StreamSvgIcon.user( @@ -920,7 +920,7 @@ class _GroupInfoScreenState extends State { var c = client.channel('messaging', extraData: { 'members': [ user.id, - StreamChat.of(context).user!.id, + StreamChat.of(context).currentUser!.id, ], }); @@ -940,7 +940,7 @@ class _GroupInfoScreenState extends State { ); }, ), - if (StreamChat.of(context).user!.id != user.id) + if (StreamChat.of(context).currentUser!.id != user.id) _buildModalListTile( context, StreamSvgIcon.message( @@ -956,7 +956,7 @@ class _GroupInfoScreenState extends State { var c = client.channel('messaging', extraData: { 'members': [ user.id, - StreamChat.of(context).user!.id, + StreamChat.of(context).currentUser!.id, ], }); @@ -986,7 +986,7 @@ class _GroupInfoScreenState extends State { // // TODO: Add make owner implementation (Remaining from backend) // }), if (!channel.isDistinct && - StreamChat.of(context).user!.id != user.id && + StreamChat.of(context).currentUser!.id != user.id && isUserAdmin) _buildModalListTile( context, @@ -1117,7 +1117,7 @@ class _GroupInfoScreenState extends State { var client = StreamChat.of(context); if (extraData['name'] == null) { final otherMembers = - members!.where((member) => member.user!.id != client.user!.id); + members!.where((member) => member.user!.id != client.currentUser!.id); if (otherMembers.isNotEmpty) { final maxWidth = width; final maxChars = maxWidth / maxFontSize!; diff --git a/stream_chat_v1/lib/main.dart b/stream_chat_v1/lib/main.dart index bdbee244be..b25c857948 100644 --- a/stream_chat_v1/lib/main.dart +++ b/stream_chat_v1/lib/main.dart @@ -133,7 +133,7 @@ class _MyAppState extends State )! ]; }, - initialRoute: _initData!.client.state.user == null + initialRoute: _initData!.client.state.currentUser == null ? Routes.CHOOSE_USER : Routes.HOME, ), diff --git a/stream_chat_v1/lib/new_chat_screen.dart b/stream_chat_v1/lib/new_chat_screen.dart index 41a1ded871..7315c71d3b 100644 --- a/stream_chat_v1/lib/new_chat_screen.dart +++ b/stream_chat_v1/lib/new_chat_screen.dart @@ -71,7 +71,7 @@ class _NewChatScreenState extends State { filter: Filter.raw(value: { 'members': [ ..._selectedUsers.map((e) => e.id), - chatState.user!.id, + chatState.currentUser!.id, ], 'distinct': true, }), @@ -91,7 +91,7 @@ class _NewChatScreenState extends State { extraData: { 'members': [ ..._selectedUsers.map((e) => e.id), - chatState.user!.id, + chatState.currentUser!.id, ], }, ); @@ -308,7 +308,7 @@ class _NewChatScreenState extends State { if (_userNameQuery.isNotEmpty) Filter.autoComplete('name', _userNameQuery), Filter.notEqual( - 'id', StreamChat.of(context).user!.id), + 'id', StreamChat.of(context).currentUser!.id), ]), sort: [ SortOption( diff --git a/stream_chat_v1/lib/new_group_chat_screen.dart b/stream_chat_v1/lib/new_group_chat_screen.dart index 414606fc05..1b21ec56e6 100644 --- a/stream_chat_v1/lib/new_group_chat_screen.dart +++ b/stream_chat_v1/lib/new_group_chat_screen.dart @@ -248,7 +248,7 @@ class _NewGroupChatScreenState extends State { filter: Filter.and([ if (_userNameQuery.isNotEmpty) Filter.autoComplete('name', _userNameQuery), - Filter.notEqual('id', StreamChat.of(context).user!.id), + Filter.notEqual('id', StreamChat.of(context).currentUser!.id), ]), sort: [ SortOption( diff --git a/stream_chat_v1/lib/user_mentions_page.dart b/stream_chat_v1/lib/user_mentions_page.dart index d02bd1c6f4..0128787f61 100644 --- a/stream_chat_v1/lib/user_mentions_page.dart +++ b/stream_chat_v1/lib/user_mentions_page.dart @@ -7,7 +7,7 @@ import 'channel_page.dart'; class UserMentionsPage extends StatelessWidget { @override Widget build(BuildContext context) { - final user = StreamChat.of(context).user!; + final user = StreamChat.of(context).currentUser!; return MessageSearchBloc( child: MessageSearchListView( filters: Filter.in_('members', [user.id]), From bf001a08002bd0ecba6361cc242175f28582a23e Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Wed, 18 Aug 2021 11:01:34 +0200 Subject: [PATCH 066/172] fix user avatar constraints --- .../lib/channel_media_display_screen.dart | 2 +- stream_chat_v1/lib/chat_info_screen.dart | 8 +++---- stream_chat_v1/lib/group_info_screen.dart | 21 ++++++++++++------- .../lib/pinned_messages_screen.dart | 8 +++---- 4 files changed, 22 insertions(+), 17 deletions(-) diff --git a/stream_chat_v1/lib/channel_media_display_screen.dart b/stream_chat_v1/lib/channel_media_display_screen.dart index f2ad261ada..b65df624b1 100644 --- a/stream_chat_v1/lib/channel_media_display_screen.dart +++ b/stream_chat_v1/lib/channel_media_display_screen.dart @@ -20,7 +20,7 @@ class ChannelMediaDisplayScreen extends StatefulWidget { final ShowMessageCallback? onShowMessage; - final MessageTheme messageTheme; + final MessageThemeData messageTheme; const ChannelMediaDisplayScreen({ required this.messageTheme, diff --git a/stream_chat_v1/lib/chat_info_screen.dart b/stream_chat_v1/lib/chat_info_screen.dart index 0f7a8a9954..1ac7156bd5 100644 --- a/stream_chat_v1/lib/chat_info_screen.dart +++ b/stream_chat_v1/lib/chat_info_screen.dart @@ -15,7 +15,7 @@ class ChatInfoScreen extends StatefulWidget { /// User in consideration final User? user; - final MessageTheme messageTheme; + final MessageThemeData messageTheme; const ChatInfoScreen({ Key? key, @@ -79,9 +79,9 @@ class _ChatInfoScreenState extends State { padding: const EdgeInsets.all(16.0), child: UserAvatar( user: widget.user!, - constraints: BoxConstraints( - maxWidth: 72.0, - maxHeight: 72.0, + constraints: BoxConstraints.tightFor( + width: 72.0, + height: 72.0, ), borderRadius: BorderRadius.circular(36.0), showOnlineStatus: false, diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/group_info_screen.dart index c6d3969d44..8564afe624 100644 --- a/stream_chat_v1/lib/group_info_screen.dart +++ b/stream_chat_v1/lib/group_info_screen.dart @@ -16,7 +16,7 @@ import 'pinned_messages_screen.dart'; import 'routes/routes.dart'; class GroupInfoScreen extends StatefulWidget { - final MessageTheme messageTheme; + final MessageThemeData messageTheme; const GroupInfoScreen({ Key? key, @@ -223,11 +223,15 @@ class _GroupInfoScreenState extends State { children: [ Padding( padding: const EdgeInsets.symmetric( - horizontal: 8.0, vertical: 12.0), + horizontal: 8.0, + vertical: 12.0, + ), child: UserAvatar( user: member.user!, - constraints: BoxConstraints( - maxHeight: 40.0, maxWidth: 40.0), + constraints: BoxConstraints.tightFor( + height: 40.0, + width: 40.0, + ), ), ), Expanded( @@ -684,7 +688,8 @@ class _GroupInfoScreenState extends State { ); if (res == true) { final channel = StreamChannel.of(context).channel; - await channel.removeMembers([StreamChat.of(context).currentUser!.id]); + await channel + .removeMembers([StreamChat.of(context).currentUser!.id]); Navigator.pop(context); } }, @@ -894,9 +899,9 @@ class _GroupInfoScreenState extends State { padding: const EdgeInsets.all(16.0), child: UserAvatar( user: user, - constraints: BoxConstraints( - maxHeight: 64.0, - minHeight: 64.0, + constraints: BoxConstraints.tightFor( + height: 64.0, + width: 64.0, ), borderRadius: BorderRadius.circular(32.0), ), diff --git a/stream_chat_v1/lib/pinned_messages_screen.dart b/stream_chat_v1/lib/pinned_messages_screen.dart index 11287bb6ad..f88270a5cb 100644 --- a/stream_chat_v1/lib/pinned_messages_screen.dart +++ b/stream_chat_v1/lib/pinned_messages_screen.dart @@ -20,7 +20,7 @@ class PinnedMessagesScreen extends StatefulWidget { final ShowMessageCallback? onShowMessage; - final MessageTheme messageTheme; + final MessageThemeData messageTheme; const PinnedMessagesScreen({ required this.messageTheme, @@ -168,9 +168,9 @@ class _PinnedMessagesScreenState extends State { return ListTile( leading: UserAvatar( user: user, - constraints: BoxConstraints( - maxWidth: 40.0, - minHeight: 40.0, + constraints: BoxConstraints.tightFor( + width: 40.0, + height: 40.0, ), borderRadius: BorderRadius.circular(28), ), From 593d3eb205e183d9375bcc77f49d4f604b8918bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20Braun?= Date: Wed, 18 Aug 2021 11:40:06 +0200 Subject: [PATCH 067/172] Add adaptive icons for Android and update app name --- .../android/app/src/main/AndroidManifest.xml | 3 ++- .../res/drawable/ic_launcher_foreground.xml | 18 ++++++++++++++++++ .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 +++++ .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 +++++ .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 5905 -> 4323 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 4323 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 3283 -> 2628 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 2628 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 8478 -> 6191 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 6191 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 15150 -> 9719 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 9719 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 21173 -> 14197 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 14197 bytes .../res/values/ic_launcher_background.xml | 4 ++++ 15 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 stream_chat_v1/android/app/src/main/res/drawable/ic_launcher_foreground.xml create mode 100644 stream_chat_v1/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 stream_chat_v1/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 stream_chat_v1/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 stream_chat_v1/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 stream_chat_v1/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 stream_chat_v1/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 stream_chat_v1/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 stream_chat_v1/android/app/src/main/res/values/ic_launcher_background.xml diff --git a/stream_chat_v1/android/app/src/main/AndroidManifest.xml b/stream_chat_v1/android/app/src/main/AndroidManifest.xml index 0492c6da87..fb4ab7f7c1 100644 --- a/stream_chat_v1/android/app/src/main/AndroidManifest.xml +++ b/stream_chat_v1/android/app/src/main/AndroidManifest.xml @@ -10,8 +10,9 @@ + + + + + diff --git a/stream_chat_v1/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/stream_chat_v1/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000000..7353dbd1fd --- /dev/null +++ b/stream_chat_v1/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/stream_chat_v1/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/stream_chat_v1/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000000..7353dbd1fd --- /dev/null +++ b/stream_chat_v1/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/stream_chat_v1/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/stream_chat_v1/android/app/src/main/res/mipmap-hdpi/ic_launcher.png index 91797672c7ce9b88327a8f87325cb5895ca0c0d4..818a3c804bc92eee150317fdcfb8e378947fd732 100644 GIT binary patch literal 4323 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 R7z6+S002ovPDHLkV1jwwX;1(F literal 5905 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 diff --git a/stream_chat_v1/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/stream_chat_v1/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..818a3c804bc92eee150317fdcfb8e378947fd732 GIT binary patch literal 4323 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 R7z6+S002ovPDHLkV1jwwX;1(F literal 0 HcmV?d00001 diff --git a/stream_chat_v1/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/stream_chat_v1/android/app/src/main/res/mipmap-mdpi/ic_launcher.png index 103da98b58d1b062818d94e10cae84e7c85d04cf..38bf9b8031b3507b789b9b8670e8c5b4f3cc5f14 100644 GIT binary patch delta 2620 zcmV-C3d8l&8N?KjBYz4DNklCx6|frcfMTuO~rmP2cZL z7Lr3HQOnTBEKW*LY1CP{s5>j}@hpoS$$ ztzgAHp5YzZpe_2?rC9>O)LViP%_NrrxJ#vb-R4RLXd{&S>|z@(x;dhcrV}5}t@})R z+JGnu0qs>89)BH`qHSl!0sKj0k()9)gj}a37hB|IqrpAC zgM%=JiJkYZ`g}GJlvLl7S{PC)4;o~GG2)8tr%v5eKXtyFYSUQtGL>9)q@1PC24VG! z710!mH-DTfl8&+0`M61%TK_iudE*u9gc;NcmB-YG9k&EwX0algaM@)W{RoDl*Mz4u z&H7N&%Uk6>^nIh1XQ7tV*pkUXn1f1FTFowQ93%HJ>Wi{9)zynG+1>;*VPP6y_NlUR zfw5Z)#Dw#AnnrGJ6vGU(G_;wqLDR)5O~qyA>VMXBp-P_NU1f*EJ1ZtZC2!O?_u;>iMFk+n&>O>+dw(YJkvM*8q7(J~;>pen;Gv%6&oz-;ol&1Xu8o*y^+Hpj{~mpsAol-eZIxd@az|9su+guSgrT-BT!iVFR{S?$&h3*tt?8@8J`^ z!vX-!Q!W&%yO(qf1TgBzZ7QwqT%-U{%TW$7G9Mq(wBTb+ALeUXyiLH~w@A}xUw_N! zjajMbrp$%|z&lU~ZF5YH^msv2@0T>qH#W0COK&eJ6!-`S(-%WpJQ*J_%xCA`Xn1^`8yhyN)3VW;;jO+&Ke z{%7+wow_K#BCZ`)028Y!RMOVF0)GJv-+Sk^0)S$q3QIMeI4{X(J^#Tonw~V(=94cp zeUPWg^|rjX=K${GpEOsSy$(-nN}QuNI6`StLc`hf#(1QK;Zbik2GyPsOi;ha{u05P0yP(;I3Ihp?^DmuPMuv z)`P{84<}7h|L2S(b=qo8ou-HT4GSQ(^1K@SX3szXchByq(yAjSv0YLA-ujy)8b&?z zy`=-^3m_yT7BuIdSoL)MC=h^Bt<{8zJb$Cm zjy451kDS!>?f(LG8jBNXFn@8iHZ{@n_dY699DBQb{&cAKbsOL({e|q>4OX zf@<%hSLPa_7HAVX@+BoDGrKBn z!7f{g7V6QX&-xl-D{s10 z83Z0$RV@|I=F`htiL@G0!*{>Hn1i+w53U}otG;P{6Dlab&dXF;Q|79J(FsA6RY5NmK=-kr4XGV#vwYqo37<0g{ zl@nU*RKoTEvw%g)0_b+TIf%Ax+fti0Z8!)#lUb6|+ka|Oy@xALN_nm7zsSkh1{O5% zVapN;qJw&9$7@`3F?}du5r8#Du{|j9RU=DlYinu!`t`JI*)mpCDS+R31S>w5O|P1G zh1AfGmNKS@)Cm(l>0^qzsF4RY@EJ6NumZ*$M4wr*!n#AY6n5HRm#pEI99{4SbH=pJOoeU@Q&t zz9Eqny0y`s>fwDG&2CkK;H2`zT%E$zBR_D!2WXR=i;=&BG02L010o#}L^sDnhKH#Y zHS7%BY_dT7z{OU|#Tv)Z&9B2J`@UiDmN1I+Mg3ZSY3sm2iCbBR1Y&2~e6q7uOTMz`k1oUwX-SmnYcj6dNH2`7SS$)5(TvL5t z*f^)O(8bttByCu1Z1-g!>?_)YZH!0_2BkWwxE~I1-2d)eHTs`>Rmz1*9zkBg5fIN# zh=1}|KWT$iHRWQZ8hvyx+c37+W>j@PW-%ipPTCs%vC-bDN6I6P2iDC~$)9gFG|1;Y z%lNXhDz*F~EAAgZecaG5A8oj;>0|oh%K~h)6`Knq{BZGIN#K7b5DdQA14uWceN=qs zfvVHcA*%bBU$f#K&+ty#pe_2ysVZz^)-|kRW(1YO`Bf`lo>;Sk|9@!bQ{3ZO9Jj$q eimOZPJpVrqELb;^nSmhy0000I}F5 delta 3280 zcmV;>3@`J<6w?`yBYzB;)0;IO#=SV)U+(Em@;kDMh!(%Nm*nQK^Emb-oD;B=OX(e zD(Uxo@AvL~_nvdV|2hBj-_GT5FYxpPXEcKK9_i=f6B5D7f`5mJUHgRca{oY^*vFG+ z#BzEY!&{A~a}HZ7PLx7UZmFueYYN<5wNj}dQTcj!_nZ{1 z@Q<3tx%L^NGdLKYVPGMATi#9tak5JMogncKfa~Z87CeFnvAk7%>8!Eji_goQzDcvH zuT?{>{(}V&dw)V67~tpo@SLU6!0EH}CXw945Y|SX&~C-MJuvj6Gx7|iAz^IqwB8c81c7n&N zv7u8Rn_8T;Xu9^onQTDQVYAx`;5B~sa~{1{r0J|OWtWld7>te!8Te56-jg@F$3|ED zl=x*wH+LvN!0`F6%X+WgptnNQwH$8`0~xSxL96%3b=HMNr?w=ucVD{#1Pq_|x^!?t zqRHANnty&*AkP+24gth!6`k7JrVwoi;EJAqo;^htw0gsXBwr6R;UF8lZbMI{ zIAKiE7rS6$j25+KdDlFEa8*1s^+lXX+Q7-YLj1(4zC+A3B<=!;854Fak|U^x80FO# za3UUl9#U-orxHs*sAAMH49Z9wQ?-kvw=9--5i|ZiknPjVwM9(Kis6 zO!F+3d?aKJ6W;j5f*E5aU_~63q?*Vq@Q4`Xgnw0k zHDJkh8#u0c5I`9?NT)WtgB)1E^A6Z~36wP$Q;)I6#*JWM7tsx@}fp$J+dOO}us6&eNu1ArOh6v!{LV){B0th|i0 zwA2j4V>^s?9W}1I3}zlt@miGEwr?(P7!;WH zfe!musNkYt@XaqZ$T%lLB~cHX)q-lZ5yOI5M25*RG(<`IuWPqvw+6Y_<*m|g%AKn( zeKZBVG35x0h=B%-9jL&!Cx2^j=r^7$L}$D=U52ku=&}2l1v;G>5rgaGe{EA0u2ed= zOTHdOH)NQ-z8brid0>2)3P}g5!HIcH8zaKwVcl^$*Mi;0&DeXq3iF3CX8AiO9t|7um!Lrm!N$|r3qo86f7ko3GwCF_Z zHf>$hTcnu3Rf}Cqx?$t1DvVoFgBqh8drttnj+x22Fe54)cx9p+!u!)vv*7zPb`bN> zYPzXT^L7&=2aE7rxPJtLdUeOv16u63Z|O~7!vWxfeYF_dkH@p4 zq==j8jDx4BirHbeS>RwD2=ZbPMO0+cNEMDSnVB?VfWzUyOJhgj(S8!Vw6+#ynnoi*OO>2eos$ih(Glpt74uA; zDrLmE;hiW~9Lv6mOXV%hDIGE1j7LK`Vnrlyca8d&?XONZo>lasMv!GebCy-9pEcLIyVgOn~0yD>MDyHR%HNWegr z7iyKa!GE6ri7;-E0TYHPNZ7#Pe6gK)Ung4U#LoYkk?^*fsECAgPC^bbol>hXuaa9T zc07k#F*UTrIE)Imps#;po^U(z6m*PdJ>iV?`!!Ix$oQi2lSepH#pP0)`cf98AwzE` zfQYbKw9SMey~TJoTuHtlR>y+!%31{XkYV9uN`Hvzl3n--_2&fB>PfrA1an$W8^CFFa@{2P#8 z!3vg(l1oWR!L(`9(7%8GR^-FO!&^4xe}6xbo@%Wvucjw;KAL3r*9y0-=|wj!ENy$` zuEtT~VHZ7DcT80!GBOg&mMs&=Q#|$5Qy4XBRI7FxtLFBKvwDM|3e z^p^^F;bQi0F)?v#ttM?_KTSKOHOHbei)Z+U?>VWz5B1T)YPk?vf40y=$iC|5ovw+v zxHy3{O;zngh@x_XZsMdDW|&M`OMlZoTE(f_lFV#f_t;tTpw+ug_n|_aS*XP0%hXst zO-91>`qYGhudknQq$i2er{C-C@f(-Vx>|TGyJh>_&6Jj?{v}ZMR-E=y-FxDemlD32POMIaQ_k6?yZ; zmp8xfom)Kc}dx$9^^q*wYs`Q zU%4Jx$?GLvBmKO6`iv9FgNM>mWyi1EsSZ? diff --git a/stream_chat_v1/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/stream_chat_v1/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..38bf9b8031b3507b789b9b8670e8c5b4f3cc5f14 GIT binary patch literal 2628 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 FV1hlikk|kK literal 15150 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 diff --git a/stream_chat_v1/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/stream_chat_v1/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..bd5086fc46fed00127c20cd98d76372f6bc5981f GIT binary patch literal 9719 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 FV1hlikk|kK literal 0 HcmV?d00001 diff --git a/stream_chat_v1/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/stream_chat_v1/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index fc254c2599eae9c57035df9afa482e4a3fddf8c8..6a602c324673cce1bfcc909227ee84295c5eb2ec 100644 GIT binary patch literal 14197 zcmY*=WmKF`%kpjhvdvOZI-QC?@{_j2a z+;cxX^L&}fWRm%1l1U~;O+^6{jT8+40AMO9%4)p+JO2B?$gi!&q9Y0bARwwFE2ZUY za%7C+OVB%?lPZs@h$EYX8!PLNDkrSyl0U<%B|CLcZ?rIN$`S2P@J9DAw$)M!!fFhG zBrQup_9hKsbYJgwvgefeYj?7;#OQ@WGj{xPCEdNpj)xyc0-f5ZWd)Wz|GxkK8@6hB zV=GVswA+?W!G?4Td@j6*a5MS7;naaJ1zxvd>&b2hU);P|6)A$*u8sd#&Ezh8kakb< z;$>4vvDHp_caX$YhokiEha&0GK(M#DM1X5_$cE34TbomTBe;WG;$!AfQ=Qr_VZ3$r zl2|=Hsj_oHJ+WU4R}mMDL|<^*$SK9cjYi}M#sjemXO_)?87J{ik`mNMvi9zkQ<6Z! znbrAkk0y=9jXtC=?17AJ3z|cG|>f(=Zf`=Dvt-1<7MrJp=zbp zx%s|{lz7>rXf=WDnp}lNNCH}zjSZTG`=s^PJnG2X9CE4Tu~qMBL5sF-%g5|f=YQMB zPhKrkWIT{26&EgibKCEe{PA?D#KD%0tC83k6o6u`bAe&MYHK*-lPoSKfi`P^Feg*&iVavBSl8kxJfziz?Y)UP8O|R^) zn$%?`P_lC&{&OB}K0vD{vuvMkf_1iIxewX<2lwoxrY8RMS2N&=vw!-VAb8u`Zw)+B zOsRhp4fxP*7%+uusTC2|iznWH?(B_cv=$d3VfTst#CcK%YinUs?RZZ%WIlTv&w� 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 literal 21173 zcmV)TK(W7xP)yC^9lK z=mDM{tl^7ZWD8gMM#X4@d&VktLGh}PZm~*DV1ytD~ z6$C-S{+i>Q9AF3CI9L=;tI>FFw?U-~DzX*tE97m(xsJk}*}S>_sb!{)p- z`)s*u518|}A0y|;C!2!_EEC#U^a?7BA1`3xLMIV6Ss2_P3joEeSqhhyrv#y7=cSLl z{9@X8MGZ;uNw}?FVq#*?=!l?poJ!+oun0&X}QJqDpW}gNB#+%LZept`shP^b-s!=o%=@J=%*hJA1Xe)t^7=G z@zH~a4sEMA`pt&&%>Ua8tMxef#6bjFx&;N&(&$D;hgr^=@8SBv^(z2XnqHtp$f(lt zp}uX#_4Q5s=RZ0nwHp{88{V08%^?WI2CINFdUZi?lDi=nS8Bafe*Qk;J(7Dw^axB#f6&+K zbNi_?g$EBDI=s%X_v2ND%!QlC845uKT{P(wWMts3=aJ$16M*sKl`d^awLH`GI$dC# zE@}D=-U;`Q9MU&@fZ3r5E;0Z`WlkL1Zi0h%@(KlEnn-d&aLRb7M8yslx0{kb0v%Q8 zy+|(%7MoMB6q%j*#R8QIPOVX?gZ#oeCwC9;9FjippIYVDMXR?Kt}ov4+Ha1`AO19( zOS0TX1|?}5koSCDSH9M8eF#96w&&eCIK(e;+OW9(FO3`6Eiygd!1)xE0UHlki49*t zoKlXM?u6`Ay(>6nCE1%ds5B@AW_l5i+5zEQu~{Gj;XDFCq0^{?TeXZC-K)#TqeFe> zRxI6^lTotcKa0u_e7p>FWT3)8L6yXHGAdl#0zhngwsFLnb!mH_m>bgq`^=d%Xh540 zW?mnbTLi4!X{I(j@3LSBb(GX86(clFs@XjaYEDrWbL?5nWQ54fHabt95unj1eOkrG z+#Jz$?#;gHxAT|&wP#83`iH);6zp2Zl!Q1csF z`wyFTcW`KUN_HW!#D-gjjdD)h^@n_+eE4&oOouM-o;1K_AR z2!n|i_8zU^52=*CUAp&vXv|>KJwGkq`gQRiL*KMo%T82Ajz9$AD$X=ty#m0(nU$f; z$mp?~p15Ub$^$3z72edTwL6>+0fhLR^6GuYD+^8_ZD->-;owOle=JMk)vafr`&$n$ zzU`;qx6aG?rOzDlojevA6GO{aW%%^!BZp+}hz;%)l0I+xxN(!7&Mnu4FW*Lp&x^zd z9n!B$+uqXL_I;Eu-R|&2T0T81*bk6~uF1E$^Bd-tb7km4z<2>??S1=o&C?J{mO#(V1 zC{-0^r||c_3O+J8sPkPf{>iMtx z@0|A1?8AAg&}CbUPL5S3$Tt2J0!Q2aY_Zk3Y_ou*b}@I1`phz9!MxX>E8a2dbC<$u z_M<`bC68q5iw)Sa=Zu{9liEg&ShdRnlf_E3zM}cw`*j6c7{%dWrqOZwtSV&G)S2`5 z_q}h#whvoB0$5I=nfnIKlSDMC;0kR9c6s8CDKlPw_du2^G-D^R^Et`EmC>9)9c5}3 zt=UoGY~M0!6=^7{^}XXKoqlgf|G0Zs?ywLi z*UCdScbYpmD3r>>r;L1dzB2TVNB_HE$?C__vKJ;lO8V4@W@r*MBSNvH7EM+;)By=y zCcm`#t72PF=M`IM23JW-kmW?y)dJF26=p$LwyDCI(j)2KoB9@|d_Akvo%Yh4Jz$&@ z_~w#4YaRk1+WRzy<_PTk_@oD)n)At;y}VCuVTFUVW%Ia484U$Tv+p|&S2&_W{X6~h zovaOCzW>yNC41gkz_RyrqFXcY3$8r5#ByaCE)$~0tbKj-u+(Q3Z#2PT1usW1a#PIeN4V7MLf+<}EY`%RT$@!*b%c#-6|1Ft3 zkWHRz1w;x=RtThTo#_KppE((q({|JQ(RY!)H-Oa>;fguOS5g2(he)T38~@_z#WrPV z_YHdu#N<(3X`z&HdB98}+Q(hmMvWQ&@BFw$FT~vfSWe>#I>%RvZ0v#6>VVD8>wrDEMPMRW@o!#pdr0>g(ypwQ2|H#{Ge}4a&^jl0h8B5WGLeNwKP)Yt7 zudi9WWV2Pp$nRRMK*se9PC>aqIH9K8_~6;}u}vuiO(6i4W)FS9rCTWZc|j(>j4Dte z;GL8kObDJDIJ&9Kq021*th7NFmDc~UH<{U^mNmbOnjr~+Mg8cUwLiZ5RQh0ZZpH>& z<~+gW6aaSP8jW}I<8S`8WXTq*RwloUx*?iFOE+6}lrwML?VD<|8Ta8b3c+O&fLXI< zDQ1Zo-k510EyN z+5LTHNS;l39 z=oD8t2KS4(`-h#=SCt=_`vV&34_rD~tLAgY-23#rk5}v_c0ZlUc*UnV%ea;y5RPrw zXK@l=bM9MH=WZm2vKuqExG@4i4S#3vf9B5Hm#q#onrythbcu}14gm_2ndf(%(gyXO zkvnhm2T?=VgK}>30gH3$Lo?r;bNB2&$f2{BVhUY~ z08rD1Z!tORox{1RK%>zr*ZIh3dQely#Pj>JwLxv}%zEeeH*pgQHyg~uh6#Wx`QROy zK4f@m?1bO{Hp=9eapgd`cR16?4<8UaA#YXsm&Uv`D;k<0tG@tLB^@+lA6@wFwj&O~ zl>n0=PO%z=OT3C?NeUJIAoI@Um48@N+q{H)8?Ew zamouHt$lC-IZ{~PQJ}s8z+(Q<04Ml%9&h>b>@BdgRWm~u4d=Uz|L zcNDldiL11K{McbV9$2}<;uKh=r>y>EG#^k-9yx7s-ZHGmgCG2ikI11@^$CmCM*x`i zj~cz{Uzr68z0K}$h`-1vLq>Cgz}f6Pf3iTUiyX80nY^ESKTw|xaot3&lAwff!&4?N z-%hkYWbH4bd4h8DC>aID4efE~hd<*D)MFI5m;gw&|KleM6dF6#{<7^aquD~>>|_+k zETp5r7BUL-y67lSJDIB_CzjY%lUMAp2(s-jqq&1}^w?>OFm7n~NgpoP&4$^WQ`aa^ zw*UZ+(Dbh#$SPKN+ibG-zZ{@LtgKQz34ycNc}G^U);n^*_YdW*9P_-ZM4|x#AjVK> zWu5<+vE%O9bkr`$aevQ&CeRgRv)BQi2fVdlzZvJ0+t(wY^HPpy+k_D#2HibxC0-|o z47KG2Y8HU>bT-q=zsu7T%I*5_3ZoqN_Y^4c%gsPV;ZbmEKhj$&lv)eH`6M7JSPA}$ z{$$)W0s)E&qm3`K`-BJed}%`QwpZp8PS;p2T{EdOGH3!p(SP_8(@vigh;mZMML!;Z zf*6%&ONgeg$i)0-6EP`GZ2ny*W6=LuGjj3@5gi#K3xNkfD|a$;ox%;H9)4iawpae^ z;`9Z$Pyk%jbh@DA-qA5(-S%%cIyrf!SEE5yNO3tad5U+Scv*kwy{bOz+KPj5p&t6N z79s>CLM#j61UxPz5s}h0+o<}kvDc4z3!lu&cv5PpN$07=0&G6@YCCa(LTD$ znv@JnN`CqsCF!xUB}wodydEW9JrL+4JI0LxpnB7OBvGZ`mj^XF2bRdYCXd=L8e?SoGr)Uabzo78s_ z-RNFQ%zXF;ygYX;V%znDGQ^;<@o^>^Yr^Uzcx1Z0qi@%R+Do zU{#`y0)xUkpzZX*rF-7~(#7@j1wb-?f_uC)I-j@-3esD$?r%6$#Fo#_Ed-~HLgsuu zJ4PMZhGbG$d4x+~et1%Yu4j7S@R1{kiEk^91eXBH<-#%ueo50uQvq-{gG2!kJ!5(> zXmCpSfb|Eg9348Y)D2&)ppI-#ffbz72-D(Nc8rEH71e^sQuxz-M5rz#^fT$$uJ^U@ zn~;E^fmFCK$As| z{xlSnsQIO&u`3S4ys9@lCWSWLA=EM&D7XuSfE{xQQ2GD#(BJGtPQDpYp*lHH)-Z4; zi=8*|K7qb1Z|P^q{Ar2Ac_sjh7A<1U9+33tkU|4Bf8@wpLqN54g&D9FZo-Kl)7deq zrK|r$h(zY>LIIiQ1Pn+NrQ-~FfAX9Y0~3`O2o3$dbj-9g0lGn3k*`ihsK1;eXb32$ zDYt!-9vVaiK;pdQ1F+hkKgy}A(4eVQ$%{>AbC^+cOnR>9~s0D7&QBd9MZr;AFQ zT<7GZfw@aqWdk!LRaGG&uU7FfAstTcu~NsGlf$3&10{9-@pbs*r9tT5q2`JaceAJU z{T4XQ`RLrD>bo>wzDhOmVIy|hCaLkUaiyEcjca{2MDK& z%Pi>8GpvJ`e{4%@*_jiR`zk3U0fN1T1U?Q)(4dQ*(Y}3<{|y?#$B~1 zx}^7y%(r3vhE0fX*Be=x2QSP9JFN(fYK8plBj`M%J@$N{W#q4ZPANw)eV7XSPN(DR zA2%VUO^O^Dss|{yODhQ16YlI+e)y~JDfg+`VoldMu|tnygFvH0+(mQs*EtyZPaQ$~ zq#pS3S+TUUu0+?Te>m{jg1->kexQq}HGPqT*#^Y6Y=@%pd~cTUVlM%|0HFzP=LSt<%}`$GWn?^fS8ZQcUaa_-*-m%#2IL%eSd7 z5Eu6x!P?ifh@RRJIcKsE9UCVLL0ur+E;ZQDv0YGm@-BpIh0Ji(h4p9$wZ_+KH`b80 zX&k7NCUv@!>^NMpJE8Kws{Q6Jb}Z3#j@XGx9g4qqWqE68F)0L^QzT&MjCBZzPZz7I zgo_u#Nq--c&=+rfx*8p02V+A23tckzyg|;Fdg#aaBl~PAqQe84eU5;u{I6$D|Nwn~7VX3F{4SuZG9$>GwlgrQxm@RwChxA?Vin!fv7Dugnqr90A=;yU9KJ zA~HzXB$H`4cM`jHxayy~h|D(fpN))gHal2d6MYqk?*k{XJe+2-*&*Y1iy4tf1Yn~$0z{@K8_Z(OgeR^;AH3WM7>f^Mcv?q{?-vb&SwL2S zfU~6n3d(@I5+{2tH43m;Odz9=`0%`i+@u5SP6Vo6)uQ0gSA`@vq7Z4+3f4GOyXrLO zmlx0%rIL&|Zneb1B?=BbX9;nhoF%(Zv}^!7RvY=HWBQwqg7ayMF#k)_V)WkVv-!lN zq3``0kiRq)e!7}-1k$nmpSvLR=CvsEN`argVb8~2tG%aCkv8N>8@jg{-M3N_J0wDr z8xU-az~D`;eFy12yLgPFX(dkVL!$6FrIvJ`H#B4m@bMyTq$QglLi`no3E~hP!olAg zSiaqfg)0t29gu(!U(W~u<#;){MQzND$=La-m4+lChwS3XT;vQw0$mGfIiz zFoB_S9RyBP*_DFhW9BwQRws}Ie?8qevM}J zgr<-P3AMv>i=DI@5c%YIVL9n^BB2!)1L;>2N|}}-e=NmXIK_D*j=*_ADA|TZ@7#>U zxQi#cI!?F1X*iCU_ymtQq?C72K?>wLqTxL%3&vmLYD|<#=+aVwFJB#usV^)A7u1Ut z=2dEAN@S)aT+hlB1JTGTO5_0OwJHSrX&ISA{Ke}=6A}mcafl(Wq2x7`k~@&AR0N)c zq%0&MrKV&s(ft2?CIR=nwio{K9UAWw5RR9d9B3P@X|YcnWXbdR2SgkzaCjsGEZVwC z%$z9BfO5BqYeHSlu+$KhPIMjK37u%(GMr=E#X$wfpY2sx#L=Xfj5>M6;)p}v)A}4b z(yZI>z@t-!VMHy{8QsI5qyBA0=Fwe(c!+x$tgw19VQfhS9hZ9wp1nd zPaB4B|8k&zVh{p|)@1}HP}8VNpYQg8D%|^a z5L;M)`2&r)Il^(Pm4}y?Zv=T4p;GxqNAn7ekJWAh>I~A=57aJX=7tLwJ7G-`f%>3M z!EyUcG-+x-kB^paF2QMC(>F9V9jt`ZV$XhK$BNY(5!<%UWeG*nb4EwUBKy=K^nS7< zHoskSqD;cSC#l)i7*HZt+THGfiE8gJMr4nGj8@dusJl1n0~!gUT3PR-@{Nj7X@k4O zTkQ1y>Db6M`qsT@n>)&|d?$~ax+z5|ZuCuGh|3{3>}?IB&c!CQd`&d%dtdy8n6{~x zH4e|hqb)jM&#rB_>%Ct1`q2v$WfG)&u1y;QSBS_BfZ%$tqq$B9<{bEXEW|4~3Fj5s zfKG8LP8SwOJ$eYtQExPuGw9y|V_zwN>6Zv*{xoz(6uU(?V%F9{mx4oEb- zUS5rmRs)+P^vHyuO%MFip>Px6rbJC)YVH#HO>he;q&#k6OGkPv z+)cPnInU{%VpW>JPBApf;VICYj39n#PF4YK_*Ve_eAP8nqhXD3u|})ZY_9(rqS+b? zsWiFB01Ui;4SZt;dNfvj(d!c-h-lLvGe7tf?PCXFREp8?b0&I>z@CCwi#r zp^YR#IY%7P%}03RyeZJVh9pp9G@H9^>+Yb{CkO8S95LgzLlM%4#oU{Eatc){f$;+| z;px?EwK?|%w=Rb2%7dc1uT+x~X$WY0Y&zmZsSy~^k%OO(tG5!A!o0gP1$?`34PrcA z@yaoWTB#3i4@FLIWapgj|ZX%o~)=#L)VJ-;19LkHH zlajF9yVZF$?iX7ggnlG-;!RzZYy)aJe{IL{ee1CCa2eFz5#Y38pe{B|gs~Vm zD{NJY@ogH*r}1rd0JOw25Ag%pI2PZI2~w~mO)z;MAHuN`3|go*w0rHQgu5RTc$_?Luvm%GRo0?o?d~MXi8mJzjT(s_DJgj4u5Rd8ZE}#a9)jtfPw70v z!ZOC8ewRnV&}%uYWx*O`^0WMGQT_CzfV)IK&yL0(F`TE zuZQ(evJDuF`70cly~vLI>|>-K^zaK!K!A@}Y-e)_>~H9`X-Jk%Jh51v$j-MRJ5Q=P zab-B2g!N7f>^Vy@`_-420Mz8LyLU|Y$1Jdv&?QRRH;c+kmM9BWBgY;B{g?uneh#fQ zawUzxzir{MVBTza#f^2P!6}(FuEdy*g|RuZukq4DttXpG>=W7#8kLw)E}#j;vQxCS z25po3;-v{{jO%y40+ITTqCTUJ#Ep;taNx+kO^9vV`!cmL$CVi@@Q?29t5SP;>+LLf z?@afL|9QfdO2Qpj>N=Xgq-l6vmQL!zzI2kkl z&yMd_7NGp>89*D0z@Q-Ziz~FVX-L+GRzI*ntd=}BJ*S_m38=sTr;q-P`5(>1)PIN< zx`6zs>X_T-*l=*)c2=(39LO($`CO3!$Uc*Wm?_@K{z_l-Dif|Y|K>3b!u(&v-0!xc zO@|)DA#|&ka{cG73Z-APp*1vyk~|2OJaGPrm_EKWW=+(v_I8JKUH4LqvH!8+MlzZ| zbd#z^;gmQ*71k4PtwTus<;kbG!)E97Du;vDiEo9=BLNT_L=`#!-S0b4HRrW@=eYLA z_EF)%k8SYk{vmqacpqCGZ8*{V?%$;$EJ|)_|IeSUAzL(7?25q5@9o&L|2RsBhNp#S zkwL1;+Ic}LNpyjRXHOm3goh`mR+7IaNSA&22RjxoS=VfrDP-Z%*f?Zo9zgmFNm%pm zx@VNVeYXbtvwC3d#$AXd3aa|5a}w!k+vOFSAyga(N6g9o-QzHOay(KJ&evd4pHN7B zweEluvlrU1_KyWnhNWWhb8Tz9clVHI(1ao)TwU3@E_+~sgO2umy>uX$a9SLzusi zgtr#k@!F3LGhnh(v0kryD{j7euN0>^R8VJsLlMJPgWzQU0Smw zzXT=(EfcYM^Ap!sNkFLoM0cfYPI|{i1nnew zhNR2f&XvkutrD6*04V6gM#r|m-klrq`KmPBJ4jjMOebk5EdDVHfj1pPcwASM8G)Zx zoy4ML2IxbR@a#Aho*paSw$zyJBg#|cGrAqmOCgzPiNeBTEL{|Rw1}W+Ewv`6-)?Pr{JsqWuR?TIvyWY_l&Y5pK9Sfz6G*#3lJ6> zigWq-V#Lj-1@0Qr7OzgyFh{f|xVPCyOC3b%*ioEwfVdP|X#83uJUp5BUKYG`n;J%| z_#+{-xJ`n4SbXClCw}~GEn?dCZ!#rAxvwI<-(Yug7--*`sUykZAtes&Nu=V_4CF@ZHMEmW(?L~0Ys;rl0vbN6IC@hxKT z3Nd32?_3T=XetiQt$jM9bWgNUuIJqwppPC1t>)@kh>9wk@Kyux{5yXlDSi+Jcd2DY znae3QF7ktJ$T6Hdm5H7yz3}qwG5ANPx|3_G_we{-GmrHLoj7(P8-lHbD3}C9w@9oM zFltssglO^NR~2~SqvOoU=G1z&ZfciS9J|K-WK@X_;V|f_P`=~KVEV~lT-T<$o$7l3*hn?LSk)INPG%u0I+isKwd)nZ9bqEcWdHFJ-1_`! zaJndrO^d)Qcc{^-nu#QxYiu7S+fJSxg;o*b#cGR`NJ1DodN&jSUBzE&xeBzuJLp`8 zfcSwJ`RE!P`ri#TR>>;dax+E0b!S?-Hf>Mw-fwn%^t%H&XHF9-GY~S9hS7w=KPVbL zx@dMTXEk4oRR#omK@pP3J~LazU&-8gs1!T*;6-S_?{3r^4k7g;ocBc5Or| z20px}a;jhTQVB^QXf4p>acNlaE1hi8=>l!zu3_kea79Q5R_t`>WCZ;XmtL=8hoG80XgR?5EbTA zs|I2w5-+Z|>24zZx+W99tSE*$xC@>er^2(ejJR3>m^9){AFg5>&>3(1WXEfZ?8wdB z4UX8V)kCVy0SZ^lo-S-qUV09KixhPAT<_mNiV*3j?#YR8*DIZ&E+ zfJK0!TlEkXOD)gH637a1t_N)kHgB5P_f{H#5Nxg~m;wufvY(k&=-BEX)O6Cid^AZ2 zuM|`&rCFs>3nr`m;$OZTVE#aK3{D^3g13L^$9_nz#*m#9t@zOox*OKQ=$FE5$&0n! z1tt=RiB!bnmHCJ8%I6BSYu6sL$f!VnkBdSghI>+n`Vw?Ip4Yo7q?(^c4D5IW2L-VE zsC53C5K^LwMaBxP5RAvj1Nfj%_m-G-TP#u&&yV6r&*U!ft9J7&lfG*&9VyJFrhH{!LI4jl(sr;eP1|cL+k1#(C{Jh0`q@xC1A%spfH5d%Aloql{_neA+ zK^uu6f8yh*t9-jA1Gzc7&1h1U(j;g=q?z*p{O_mE1Eg=-Js9#t!j-NBi>-9&C>2*pu(~hQq|M-gHb0 z8;SI!09UI>Dlvx3RIcBF*o<*s>_O@wYdr2~V@f|VQY2q*7xJCGC`H<`KM^+XE&$H07raj_ z{zuQ)(esd-m?p##12;kF1OK;H17B>^5{h)rK#>A1PLU*vgYyzag*Z`_PH0L9y!?1) z_;`Yh_8zKvjnZc%EZBrpP79?ugyQfHAa@A?FCVd^2IcqlSbSXkqbT>WTf^J8%j4Ar z=W`r7g+n2x^|g{F;1A~SErZm=EO_cuFW4|kUOO}jRX^;JFBIVL7(<3tG0M@@q0=-) z5@7x>7hwLcEOhGJmCy-0czUpDI)Uf-pJ(mpb~!Z?{!2!Mtq0SgEGLW3I(xZ0)BSW! z7!_($oa?kHSVW&tI#CrBZu*=MlHg-qHd=ekj{-w}lz(v5L{)tPCVfYG3K?a{DEGo+ zU18DdvT6YYg!CPCIlvN3Il|It_WHv--EL+MppmDeCx|hz4+Q`A?zd+|C9-ZWXF#2Q zK9|>(WoIg6(kZsyP#}gzyTSII2Vl>mBjNtuCYB2_3XPs$8U{W8u?raYVa?9su1=8{ zV7M!6T)}|;@SO5cSKOi^qgATC%a3B@D>(?%kFJ~#Y z_VbV?Bbt9i42$$v9IK2}cavw7S0V2^rcKY#_rs zQY5)2IJpJ@!tZg~o@#L0f)vCc4?j6m3&s^&S?q&Qz})WB!!wV=!* zG{Vk>P@G^war)5r%n4y4q)`VmN?Et=aQTm+5Y(>fAkuLyS!hqM!Egx4xM9Dd%ZnB8 z=dr;s{^Ki$)LYdbVB&6{=Wm+=*5v^cV0NM(W@MmSQ9|TM+gVbM4SCL82 zzkWpq%lGw$G$J&9?L92c8LLyIKw>unY4fble!U2vE!RV6$8Izisb=?PX;eTU z(;?g}ic=Fbj7ofrlC&c*Va!nY`RyvJXiDL32PDOk6yXWtXQ{S#hi-3{!>uc)=$r)p zCe3Cy6?U}7zm>bdh@izC{+^I}{Upr(W1!d{-&CrEVPwc(r?<7e#y*DkleScTS-3SzREM3FFE zdq-R{{PlMpFmB;A1^FZ57~_PGDT*}jh3bNi`_vSEgt6d#PH5Epbz0(JUmz6685C|r z@Y{RQ_v(w{Gz7e->A70sWM73_>xWYMAzf#4sg6#kBloH4En9e_!YLf>2Xu~tNwfEW zd(beNPt-IeUIwIyk3XooUYWyM)?xtnu^R%4;|Sj`902i9{4bbdJz%C>~o z+o5gDKo0J`cPJb>ZYb<%p&43A!M5nEqC}DK^l-Fdy}Ce3E*ZK{ z?S_|QFTtxFo`#c)LZDj!E5@HqSXOE71A!eHy1rHdnrlCRVBZPseD8xmZy9agT|tH) zOUy6OH4jS2{VO;NMLP!9+rYS~Sh8dZy!P5_;N#;18jZ$e=N*i`vqTe%i;F?6R>P%B zmmn-Gj9jChzAl}s1dI-@oEHVp|9da^cez(=cHJ201;NRlgOnU?GI^$^Of)b3`W0V4 zzXuqGP6jmfdMysL3&y`Xg+V&R3J>WAbY z7O98>Uyu$$MK)!(2MMo@ zfcZZiZuAP7DC16!0N2l+xrEQD0;tk=UvP2221Hgf08|16!zEw{Jolet@N^vwwj^P~ z82-%3!(sl?qqKkK?eqtvt`Zem@&o6W(PmH}bAjOlg5i_rLTVL_OY4T!b$^W&!gyZ{ zx8im&C6cCJY&|4Rv~>Uvcb6vRBGH=Y#N#k`S`_p!tl?lu;g>8w0+}5>aLBi^u0w0m_rNUT{{-!IQO$ zNRTnmVq$)f(jk~Oq$>EM{?I7K&41d}57N@J!Oz#*qM=dabmL5nnv`6llLmer!idw` zx7K3W#(i-lih)JrW9F8_qSs{5H&pyGoOByHvmBOBlhZ{-jOmCJMZyU77O1eBf+YN>PoFkR_z}h#0db!r z?UmEt!rY7ilyN6ABCFH)C*X5&1js&n1vKgsxgBpcksxExtWjSN+R0)1(tb1|P+w>i z=MU^3$btf;H;v&pH#Eu`(tbsXlSU{`E-)_LVe0rWVu@t6+Ax~xi?e9E7Ct3ZCNDh! zbOmR?dHO4r@1Ye>IKB-AyzCBg??LeH7@nqA;5C_wB1z?)n2R)jy@t>vZDqQ)!X=1a zvnk;BVXsa>tAw*=Eb-b{)D(VmfWqImZ{J3J#+de=SQHBVU)~3d`yewsVvGP04nbsH zm3{IGzJfmyUVd(7cK&5IXP*ICc`9O3nA_kIH4ijZBBT#2UbzpZJp3R{Junp-m0sKO zWj`48&K_{@GOSt^nYpN>IK%>H<(3eNgIS{zH@>SJdT z$%!dx#-n#&56I@6Kv5&=$$CbDi<>7Dm+IluU*gHeL+37CX!->TyQyR0InEkuN4IMk z1L;KDpK-;YOgsCkCxs#Vp8eZb~sHiB2jg1B6wH0x0BSyTT*9%tY35cLwA!vgw#;gWg zn8f9H)CbbC)!^$TtCJ(LhWcQf&?+rLijxBj5tMgd=uUfH)}$e(C=PZ^n7>{NMVS|A zUXR>06ui89iTfK(REfDSrlrofiyeNqak_Rxxk!@ZjNRC9v~uvOzMvd!kX3XRwthW` zJ~yX}v^i)D?XjfrBaD6PXCDcNH9N0@e_+SDs|AT{V>4mp)n5SD>w_Bu;|5#H_6&zf_w)5O*h*XF5A8>h>vM~&7U`%>aS{o|!IXv| znDbo6%IJs$Qxpe#;~>R3dCpK#MJSG6PRGE{Dgiil6L%B-FdFm21xelLN_X9^J z#=TEvzaL9bpVqSc#*jvVU#H1n&0lI-v|~D=#RxJP$2rUOn&QiAj^QgP`#eNP2?e9Dpa^<(uUZ4PIrPU`EPu6Q8LkH>AF(|n z784=YH@=_b_hP(=y(ql!%}#tS$vjnnn6+y$^a&-2>*E}Fb%BGz&RwO}w{D4;8IT%m z{jnhyUVr3%(+#$aTCJ#d_OJGN<9#LJ$7O$Tl4->r^b3+`X`YW?C^$PX^mtmWK)=tp zkfSl6pJPqrHL)^kxuuG*#-gqkBlIxksqn^QV&of~X{-X+g771x>%tj!*1?yScham`ff0x-^Ind+(vn-h zA^#Vo&_AN;mlwmKET~jzai=q4+k5&ynwnKcXb{u-(qRTF8*D8+K>UIGXbQ49;l9>r z&xeOIRS?ry823;5?QbnzwNYzyG1N`b6hK5*_sU~5Cbnnow8t36_cGAO5t1{?fpJz~ zFC$%mwyyr^k{r^bGCmXd}P|TZ~&jX!mU0 z4Yq1R8VOn(O$|Cr*Or`%g%S?c-vdm4DTkgx;+Hoj%47-4-`tYOrUKJKl2eO;XYFw` zWZHWGb87wnt%e%(2T@G{V)yOSp+j7Jap^W^eqo-Yy`5)Sh4p2J)&*Kc)=mzoi8o>F zd@ooxvvz~6I~7@l+vwD3zKTn8VPmXPA?7e;?v?aK3t zFD}^%NPk2bul!7PdLu@I@T?2A@4xu*ON+h0%QHrAPIDhtPb5^>y87k_tBAX zUoXz)diys9lJi$whC`jHj=_53aGO88Sd#W^+_(|r?cnY0UAb>vP%4#BT3QO{&Ygo^ zy?RwEi8L3|2ne#v;P(gyvwigFQHYF;G`U}6p%=v1zps})o1B_?T9qG<$#0B7 zwyVK3wTX)2AU0OJ`_J!wc;Fu&|Cp6$l{GT;LR?UfgMw0DcrH4gT&XiKEXK&Kc%k1W zfC?`w2Zf_29r|n2Jra*0{d-!5k+?nRjV9u_HnqW2}_| zg#oicJ;+FaX|fIc4mOLrN++c^)A9wtCGr|_g(TrO^}n%}-&`CzbO?qF8PcfFG=$U~ zL9bDC;#};?vWm`rzM8&R!}*n9S^-377~d=2vSs(Oh>>GvoxQ5mF;<)*S{I~LV$2bj z+14P|D3}s%o=!G!keDgdy^|5@5`Kg&2)`tq*E2NwkU&>HX5DJ!{>31!hFZ(|1JtDe z2%Id4j%G3rPWV1(Y{}b~?RbX@E!a#*)D-UEV30{@=`^MToVpCak%woAg-E^gE|M!m{z>xP(Hj_KouK-A;RI1c$PU>9NyVgdbt( zw<=^70_&#Gs?Tp3_BDvsU#QFaBN|cwaTEYZT=&<>75xT8PD!{yMgeFW1#AH*wpdSG znv(%Hv-}~{hpBALYcA@VkTO^Jjs1w*NPDD7Fx{D3z+XAM@;CArTYA)M{Sgfda^)y6 z@UzfIbuV5^=H(Tdwo$-VKz}4w4nObK!rbQ@nQIMVh_t3JuxQaDm^yW8!^buf{^Q4w z!+-$;8hw0o!E<7r(&3BxvWnvq=YSd3pMI{vZ#EhQ)^9(#xL-uXyYbiBd;wblr96(I zuw;j*0Gv^UoVlp!5St_X2vi=N1Bi%-xUIr(D1bss&;Pi1F*?3UV21Tam?y-7fHPrC z+Q!KFPd=!6>87L1U8%CYd4anT(u81o(s{^NMuLZvSm@K(fHn%hM2BjQ2z5c407L6P zXwV=ya^y%;E}=mP0_b!MgPGPJVV(k1CCTNiUj6Ib`=5C2tE2Hs9oSH+ z^xX`)gemU|(|%IJis`Z@r(PTT0_G}#1Wa{6{vQ_?N1rz(+07KFV6tMDhlj_#KbQQ^ z0W+;X!h9Mdjsk4%{?`}Tj~e@`x2IcJcD~xCa)jjfRhQW?CMuy4U4z}yc}R?Ygn`3iuez_@WN#KfrAe)Y`s zmp=J>$F{>2*55y+4b)1yIWka`T>;a6R>L>{lvyl8wy{cpG-%+!fpkQ$#0bEN7s7;e z>-R4CuO2sU92a9KcsB=)b7aMAI<7Qh-_BhJQ`U6v9Qf>|o29tYLE9)`<-j^&SMM-b zvi1^D0I{K$rCOsmRtb(BJ61UoGzVk^(Gex$3JMBV-@1Gn>wUQx6B(cNq4AL%(Yau+ zuLyegiDjAxk}^5BvI?QiA+`Zv1Fd3S4v$1vz+cgFi`GdrWh59eVg&5lx38&()Dz*y z0~UCAc%b!Xqls)ro8kBxqbUj?wUtZ%<@=967&B?k(tRgsShP(6tQ=Su;O8F!+Q;ah}SPe*|u(CBe5Edg`0yGQUV(DC)@VfvuFPTVuZ3u z$?i>`%reXnA6@7-`TbwCXVY`rsE{oHC&q9+t@Kh3x=$^Ki{B|sHWqH)F{+e6nm4Fx zKYSmR;K2tUqzQL5KW_q3+q?p@&lJPsCMWtfM**Z6;*=#{zVqhzx4!#h=W(Uh7HbCX zHqb_50fCTs`4miEGyr~lQ&z2Wo+Tg&aYM!M()+u2@2)o$+xR17GhjLAY5bJ2W3#Ufi` z_HX?b_|`)U^CP`HoOeY8qfHurgt@#JwC zhzii`B0tMe6~hFXTA6a;`_HDm`rJF;tlDyz`U7oL$jX5dB#s1wVCkA;aQx~3IQFHY zQuv!giO|7q>TGX~QAjsxKJYufdEiy@_ySnS`XekUpmc~Ti2wHY4V$0tJ!0g&9~?ek zLi_=~O$lrOR0%ruhxmjW;5fz&E-dkb5Fe&;!9kX>oNrJcB*B-2fAxV1&D+c6cIq2z zKi6gL`yC8R8(HdjmK9FXAK=qB51Vl#BrU907r)2Pw>iZ&1L_zDg+f}c7P?J{gXhOY zz|yy>vPV%7jMq}OB&4|rXNs;N4>wSWdD|9f?IJJwHs{{Wi|pF4cwiH>2>J^IYbfWERBab%M{QzJd`fE zDy^$*R{#++L~Dw<&=QLF%mM=>i~g?@lbW0B0^2z>DY7;6);^ z?(KqMcsK|5_F$oZCl)&Svb5~d7-;rz_04M;dN_Vn53%t&*ndF)eaTfy=^4ik;2YG9 z@P9$?pkUdD`pZ>czCU6#k)3$3V8q81ZntwvBSWh6*hAmU7(RB|{Qa9YAFbeNJ#m{7 z*c4C^u%-al;PP+pMqY8F{Z{jfb?|3w8f@C5#N}v!uBgSzfZ@oF;!4d##?|DXM%-9C zVC-Cgwf6zvz%C%;7|;+6(+h&$UcoV=Bjp;D6;=9yLtx>Ek14c7bcRk}m!%%q{>_XL zPrW^V--fNn+LXYSA+=k_eydn;&oKU#8ENQ0sI}D_5#vHJbonZ>6OZ`}dV%gIDHUpt zlRd|bij-?nM#|C-Y=;&Qet?!y0EDOnX|Y=u&Xkm(+^&rd**>VlT*Ec3*@##$+D})j ze>)04%M#(&plqOwKnn>!K+7orqDl#74IeXo{{EOP$0{6(OLcA0p*s*}g=+*s=iHA$_u%J~JfmL!E^Tu{x?|Awl(yWVy9LDXYdZxx@jd*? zlE0Yf{kTR`cn(@Y_yJl+0T5IP@WK~P@fmHk&O^yd zlU4>#2a)d^oL%d&WmcpBmC(YtaU8_NlqRnUe|1&-q}Yk?{_ypsG)22Bx7tPnD+eJq zI$hTwC%#9JHs{xc|C(NKcEKw8j`*9lnzLIMtWg2P8e`EfV2dv&CYu z`}sY7;&KI)s-50HZu&yK<{srrdgk zNaToy7I@{iPW;dRi5vZ*UwMA=%ujFRIC>@AEH(6iZ_6cWT?l&gXTw4q`7mE?&Wa`f z{V4y$oF5Huij>ESTj*P_0#re32$w+V zy~}qdDBbb(wCDSF;$Zus@VjciliTCfcTsDf7V4a$-}OQt?G?uGZ$i=BKfC#pcL)$4%vCv8&% z%K`;or?cZ&J}ktE_j6HYty}lg=ehePTyBuwh^J(FbF=+@|}Ym`HtTD()E8G{bBQlK?^|a z%P&QEbk@xE>w@hmfCSo&4uzXK!5L{A2K{TvHrK_Tk8Ypw^uq&RyqU|&uO*=(=&&zQ zn~%_VP>wI>IlgnSBOl_WFWa#5@bW#|9{IYWqWGF&ACA^R##m>B#~j$M0#F!60|PCp zs3^LTzH!LpCEJ|7@gBYFjVB+9criJjbH16Th7zS3dlNBjQKN<+=mouAaB{TcItJMD z9X#~K>$e|Wx#zD37gki1Truoq6xy_HyJF)CV1Pu6#Ap$tRx2;2t{*)0r){oZIS={n zpHGZ_@+GC-$v-(ufb^U)fsE8TL0sh6wtqd#fmjf|P9U7o$HSft_GQ6^FH769W8?B& z`zHNVUS4?1upehw7{w;(jw#$33Lrs>78w+wyu9dU`Q8^kT)G#&bno|{XCoeZbK*k- zd?J!^fltn$ks}@LM0{5|&Dh0HkIfjs(cX>=^s(myya4iYvX1|~X34VL!#wW&{>4!vdyg*BIC*E}0i@-qK&{pp zl!3jIQ!NZaFMv$OaenO_I6qGSd#)^d_rdd9;*PwxQkl9Z)@Xm8-pe~s@Fm=t3LrsL z1To$EnP+g3Z(VuLnFHw?1|9fu19-Xgc;iv`duELrHPk;UN69#0_p{8L3Q(yvdg4^* z1?n%L-(ahw15!ghIeEhCL167=cC3$=J=e|^z}s0+?mwNr@65(e))gl#!D95>%8y}G zXYE=sq;i_Of-B{MsnOJ&WowxIF%E9y3 ze%!3OuxPJJRgi4-S7Z?9hLbjiO125;0X9hX< zdgFl}-NJ_T4EO3@s#e$)C;?C*ij-<7uh0?_A?R4Tm>c;+A22OAQV@kELXPd!sIX&g z32|f;a-MN>mUFI70IrSz?v9{IO3Au-{^XVYB?;f{Ex8_pOS9)1eGyB9o-tT^oxw2N zRk-^UK!Wk8fPO-3EN)1da!V4|Zow`6Px4GI@8lBlj|itOFAnYAt=oX^VIEz8b97Nw z0AE}Npd_2BTu=UMfG{VNO6qLyb^yR;e_(qA8{4wJC9csr(Umd05&Qrij9qm(o>3v zLVuT7dsDc36~GvhuYjl;8Bi*;P*HKc`0}r~{hq#=?%{3k-M_QUZ+H)T-x1+~9s7p) zx$_;|{M~%?jJqr~ z2C==GxGiRw=&`XDxN)|R zHU+2&zQlj@SvdJ@4!npzs_J$k}@Y^IrD^ za54`+nMb&nR+aDR=+nnZ&&r*M4iH-ncH|&-MA=xwG4FdJ( Y0}DkpjhvdvOZI-QC?@{_j2a z+;cxX^L&}fWRm%1l1U~;O+^6{jT8+40AMO9%4)p+JO2B?$gi!&q9Y0bARwwFE2ZUY za%7C+OVB%?lPZs@h$EYX8!PLNDkrSyl0U<%B|CLcZ?rIN$`S2P@J9DAw$)M!!fFhG zBrQup_9hKsbYJgwvgefeYj?7;#OQ@WGj{xPCEdNpj)xyc0-f5ZWd)Wz|GxkK8@6hB zV=GVswA+?W!G?4Td@j6*a5MS7;naaJ1zxvd>&b2hU);P|6)A$*u8sd#&Ezh8kakb< z;$>4vvDHp_caX$YhokiEha&0GK(M#DM1X5_$cE34TbomTBe;WG;$!AfQ=Qr_VZ3$r zl2|=Hsj_oHJ+WU4R}mMDL|<^*$SK9cjYi}M#sjemXO_)?87J{ik`mNMvi9zkQ<6Z! znbrAkk0y=9jXtC=?17AJ3z|cG|>f(=Zf`=Dvt-1<7MrJp=zbp zx%s|{lz7>rXf=WDnp}lNNCH}zjSZTG`=s^PJnG2X9CE4Tu~qMBL5sF-%g5|f=YQMB zPhKrkWIT{26&EgibKCEe{PA?D#KD%0tC83k6o6u`bAe&MYHK*-lPoSKfi`P^Feg*&iVavBSl8kxJfziz?Y)UP8O|R^) zn$%?`P_lC&{&OB}K0vD{vuvMkf_1iIxewX<2lwoxrY8RMS2N&=vw!-VAb8u`Zw)+B zOsRhp4fxP*7%+uusTC2|iznWH?(B_cv=$d3VfTst#CcK%YinUs?RZZ%WIlTv&w� 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 literal 0 HcmV?d00001 diff --git a/stream_chat_v1/android/app/src/main/res/values/ic_launcher_background.xml b/stream_chat_v1/android/app/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 0000000000..c5d819c5f7 --- /dev/null +++ b/stream_chat_v1/android/app/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #005FFF + \ No newline at end of file From 0f8605ef89e286a273d74af806fbe7de1b959ced Mon Sep 17 00:00:00 2001 From: Gordon Hayes Date: Mon, 23 Aug 2021 14:17:49 +0200 Subject: [PATCH 068/172] feat: add localizations --- stream_chat_v1/ios/Runner/Info.plist | 5 + stream_chat_v1/lib/advanced_options_page.dart | 37 +- .../lib/channel_file_display_screen.dart | 7 +- stream_chat_v1/lib/channel_list.dart | 4 +- stream_chat_v1/lib/channel_list_page.dart | 11 +- .../lib/channel_media_display_screen.dart | 7 +- stream_chat_v1/lib/chat_info_screen.dart | 35 +- .../lib/chips_input_text_field.dart | 3 +- stream_chat_v1/lib/choose_user_page.dart | 11 +- .../lib/group_chat_details_screen.dart | 22 +- stream_chat_v1/lib/group_info_screen.dart | 70 +-- stream_chat_v1/lib/localizations.dart | 558 ++++++++++++++++++ stream_chat_v1/lib/main.dart | 12 + stream_chat_v1/lib/new_chat_screen.dart | 25 +- stream_chat_v1/lib/new_group_chat_screen.dart | 20 +- stream_chat_v1/lib/notifications_service.dart | 9 +- .../lib/pinned_messages_screen.dart | 11 +- stream_chat_v1/lib/stream_version.dart | 3 +- stream_chat_v1/lib/user_mentions_page.dart | 3 +- stream_chat_v1/pubspec.yaml | 15 + 20 files changed, 745 insertions(+), 123 deletions(-) create mode 100644 stream_chat_v1/lib/localizations.dart diff --git a/stream_chat_v1/ios/Runner/Info.plist b/stream_chat_v1/ios/Runner/Info.plist index d9f250b76c..a1b83010c3 100644 --- a/stream_chat_v1/ios/Runner/Info.plist +++ b/stream_chat_v1/ios/Runner/Info.plist @@ -62,5 +62,10 @@ UIStatusBarHidden + CFBundleLocalizations + + en + it + \ No newline at end of file diff --git a/stream_chat_v1/lib/advanced_options_page.dart b/stream_chat_v1/lib/advanced_options_page.dart index 3fd9a95ba6..f6f6f9faea 100644 --- a/stream_chat_v1/lib/advanced_options_page.dart +++ b/stream_chat_v1/lib/advanced_options_page.dart @@ -1,4 +1,5 @@ import 'package:example/home_page.dart'; +import 'package:example/localizations.dart'; import 'package:example/routes/routes.dart'; import 'package:example/stream_version.dart'; import 'package:flutter/material.dart'; @@ -40,7 +41,7 @@ class _AdvancedOptionsPageState extends State { centerTitle: true, brightness: Theme.of(context).brightness, title: Text( - 'Advanced Options', + AppLocalizations.of(context).advancedOptions, style: StreamChatTheme.of(context).textTheme.headlineBold.copyWith( color: StreamChatTheme.of(context).colorTheme.textHighEmphasis), ), @@ -74,8 +75,9 @@ class _AdvancedOptionsPageState extends State { validator: (value) { if (value!.isEmpty) { setState(() { - _apiKeyError = - 'Please enter the Chat API Key'.toUpperCase(); + _apiKeyError = AppLocalizations.of(context) + .apiKeyError + .toUpperCase(); }); return _apiKeyError; } @@ -105,8 +107,8 @@ class _AdvancedOptionsPageState extends State { fillColor: StreamChatTheme.of(context).colorTheme.inputBg, filled: true, labelText: _apiKeyError != null - ? 'CHAT API KEY: $_apiKeyError' - : 'Chat API Key', + ? '${AppLocalizations.of(context).chatApiKey.toUpperCase()}: $_apiKeyError' + : AppLocalizations.of(context).chatApiKey, ), textInputAction: TextInputAction.next, ), @@ -123,8 +125,9 @@ class _AdvancedOptionsPageState extends State { validator: (value) { if (value!.isEmpty) { setState(() { - _userIdError = - 'Please enter the User ID'.toUpperCase(); + _userIdError = AppLocalizations.of(context) + .userIdError + .toUpperCase(); }); return _userIdError; } @@ -155,8 +158,8 @@ class _AdvancedOptionsPageState extends State { fillColor: StreamChatTheme.of(context).colorTheme.inputBg, filled: true, labelText: _userIdError != null - ? 'USER ID: $_userIdError' - : 'User ID', + ? '${AppLocalizations.of(context).userId.toUpperCase()}: $_userIdError' + : AppLocalizations.of(context).userId, ), ), SizedBox(height: 8), @@ -172,8 +175,9 @@ class _AdvancedOptionsPageState extends State { validator: (value) { if (value!.isEmpty) { setState(() { - _userTokenError = - 'Please enter the user token'.toUpperCase(); + _userTokenError = AppLocalizations.of(context) + .userTokenError + .toUpperCase(); }); return _userTokenError; } @@ -204,8 +208,8 @@ class _AdvancedOptionsPageState extends State { fillColor: StreamChatTheme.of(context).colorTheme.inputBg, filled: true, labelText: _userTokenError != null - ? 'USER TOKEN: $_userTokenError' - : 'User Token', + ? '${AppLocalizations.of(context).userToken.toUpperCase()}: $_userTokenError' + : AppLocalizations.of(context).userToken, ), ), SizedBox(height: 8), @@ -226,7 +230,7 @@ class _AdvancedOptionsPageState extends State { ), fillColor: StreamChatTheme.of(context).colorTheme.inputBg, filled: true, - labelText: 'Username (optional)', + labelText: AppLocalizations.of(context).usernameOptional, ), ), Spacer(), @@ -248,7 +252,7 @@ class _AdvancedOptionsPageState extends State { ), ), child: Text( - 'Login', + AppLocalizations.of(context).login, style: TextStyle( fontSize: 16, color: Theme.of(context).brightness != Brightness.light @@ -318,7 +322,8 @@ class _AdvancedOptionsPageState extends State { value: userToken, ); } catch (e) { - var errorText = 'Error connecting, retry'; + var errorText = + AppLocalizations.of(context).errorConnecting; if (e is Map) { errorText = e['message'] ?? errorText; } diff --git a/stream_chat_v1/lib/channel_file_display_screen.dart b/stream_chat_v1/lib/channel_file_display_screen.dart index 2cffbc88a8..33394cf29b 100644 --- a/stream_chat_v1/lib/channel_file_display_screen.dart +++ b/stream_chat_v1/lib/channel_file_display_screen.dart @@ -1,3 +1,4 @@ +import 'package:example/localizations.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; @@ -56,7 +57,7 @@ class _ChannelFileDisplayScreenState extends State { elevation: 1, centerTitle: true, title: Text( - 'Files', + AppLocalizations.of(context).files, style: TextStyle( color: StreamChatTheme.of(context).colorTheme.textHighEmphasis, fontSize: 16.0), @@ -107,7 +108,7 @@ class _ChannelFileDisplayScreenState extends State { ), SizedBox(height: 16.0), Text( - 'No Files', + AppLocalizations.of(context).noFiles, style: TextStyle( fontSize: 14.0, color: @@ -116,7 +117,7 @@ class _ChannelFileDisplayScreenState extends State { ), SizedBox(height: 8.0), Text( - 'Files sent in this chat will appear here', + AppLocalizations.of(context).filesAppearHere, textAlign: TextAlign.center, style: TextStyle( fontSize: 14.0, diff --git a/stream_chat_v1/lib/channel_list.dart b/stream_chat_v1/lib/channel_list.dart index e0545185d4..5bac6cf755 100644 --- a/stream_chat_v1/lib/channel_list.dart +++ b/stream_chat_v1/lib/channel_list.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:example/localizations.dart'; import 'package:example/routes/routes.dart'; import 'package:example/search_text_field.dart'; import 'package:flutter/material.dart'; @@ -67,6 +68,7 @@ class _ChannelList extends State { child: SearchTextField( controller: _controller, showCloseButton: _isSearchActive, + hintText: AppLocalizations.of(context).search, ), ), ], @@ -109,7 +111,7 @@ class _ChannelList extends State { ), ), Text( - 'No results...', + AppLocalizations.of(context).noResults, ), ], ), diff --git a/stream_chat_v1/lib/channel_list_page.dart b/stream_chat_v1/lib/channel_list_page.dart index 76df0fb4bc..f29f96ac8e 100644 --- a/stream_chat_v1/lib/channel_list_page.dart +++ b/stream_chat_v1/lib/channel_list_page.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:example/localizations.dart'; import 'package:example/routes/routes.dart'; import 'package:example/user_mentions_page.dart'; import 'package:flutter/foundation.dart'; @@ -43,7 +44,7 @@ class _ChannelListPageState extends State { ), ], ), - label: 'Chats', + label: AppLocalizations.of(context).chats, ), BottomNavigationBarItem( icon: Stack( @@ -56,7 +57,7 @@ class _ChannelListPageState extends State { ), ], ), - label: 'Mentions', + label: AppLocalizations.of(context).mentions, ), ]; } @@ -192,7 +193,7 @@ class LeftDrawer extends StatelessWidget { ); }, title: Text( - 'New direct message', + AppLocalizations.of(context).newDirectMessage, style: TextStyle( fontSize: 14.5, ), @@ -212,7 +213,7 @@ class LeftDrawer extends StatelessWidget { ); }, title: Text( - 'New group', + AppLocalizations.of(context).newGroup, style: TextStyle( fontSize: 14.5, ), @@ -249,7 +250,7 @@ class LeftDrawer extends StatelessWidget { .withOpacity(.5), ), title: Text( - 'Sign out', + AppLocalizations.of(context).signOut, style: TextStyle( fontSize: 14.5, ), diff --git a/stream_chat_v1/lib/channel_media_display_screen.dart b/stream_chat_v1/lib/channel_media_display_screen.dart index b65df624b1..94357182b6 100644 --- a/stream_chat_v1/lib/channel_media_display_screen.dart +++ b/stream_chat_v1/lib/channel_media_display_screen.dart @@ -1,3 +1,4 @@ +import 'package:example/localizations.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:video_player/video_player.dart'; @@ -65,7 +66,7 @@ class _ChannelMediaDisplayScreenState extends State { elevation: 1, centerTitle: true, title: Text( - 'Photos & Videos', + AppLocalizations.of(context).photosAndVideos, style: TextStyle( color: StreamChatTheme.of(context).colorTheme.textHighEmphasis, fontSize: 16.0, @@ -103,7 +104,7 @@ class _ChannelMediaDisplayScreenState extends State { ), SizedBox(height: 16.0), Text( - 'No Media', + AppLocalizations.of(context).noMedia, style: TextStyle( fontSize: 14.0, color: @@ -112,7 +113,7 @@ class _ChannelMediaDisplayScreenState extends State { ), SizedBox(height: 8.0), Text( - 'Photos or video sent in this chat will \nappear here', + AppLocalizations.of(context).photosOrVideosWillAppearHere, textAlign: TextAlign.center, style: TextStyle( fontSize: 14.0, diff --git a/stream_chat_v1/lib/chat_info_screen.dart b/stream_chat_v1/lib/chat_info_screen.dart index 1ac7156bd5..9190479c01 100644 --- a/stream_chat_v1/lib/chat_info_screen.dart +++ b/stream_chat_v1/lib/chat_info_screen.dart @@ -1,4 +1,5 @@ import 'package:collection/collection.dart' show IterableExtension; +import 'package:example/localizations.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:jiffy/jiffy.dart'; @@ -149,7 +150,7 @@ class _ChatInfoScreenState extends State { return OptionListTile( tileColor: StreamChatTheme.of(context).colorTheme.appBg, - title: 'Mute user', + title: AppLocalizations.of(context).muteUser, titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( padding: const EdgeInsets.symmetric(horizontal: 22.0), @@ -201,7 +202,7 @@ class _ChatInfoScreenState extends State { // onTap: () {}, // ), OptionListTile( - title: 'Pinned Messages', + title: AppLocalizations.of(context).pinnedMessages, tileColor: StreamChatTheme.of(context).colorTheme.appBg, titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( @@ -262,7 +263,7 @@ class _ChatInfoScreenState extends State { }, ), OptionListTile( - title: 'Photos & Videos', + title: AppLocalizations.of(context).photosAndVideos, tileColor: StreamChatTheme.of(context).colorTheme.appBg, titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( @@ -323,7 +324,7 @@ class _ChatInfoScreenState extends State { }, ), OptionListTile( - title: 'Files', + title: AppLocalizations.of(context).files, tileColor: StreamChatTheme.of(context).colorTheme.appBg, titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( @@ -364,7 +365,7 @@ class _ChatInfoScreenState extends State { }, ), OptionListTile( - title: 'Shared groups', + title: AppLocalizations.of(context).sharedGroups, tileColor: StreamChatTheme.of(context).colorTheme.appBg, titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( @@ -416,10 +417,10 @@ class _ChatInfoScreenState extends State { void _showDeleteDialog() async { final res = await showConfirmationDialog( context, - title: 'Delete Conversation', - okText: 'DELETE', - question: 'Are you sure you want to delete this conversation?', - cancelText: 'CANCEL', + title: AppLocalizations.of(context).deleteConversationTitle, + okText: AppLocalizations.of(context).delete.toUpperCase(), + question: AppLocalizations.of(context).deleteConversationAreYouSure, + cancelText: AppLocalizations.of(context).cancel.toUpperCase(), icon: StreamSvgIcon.delete( color: StreamChatTheme.of(context).colorTheme.accentError, ), @@ -441,7 +442,7 @@ class _ChatInfoScreenState extends State { if (otherMember != null) { if (otherMember.online) { alternativeWidget = Text( - 'Online', + AppLocalizations.of(context).online, style: TextStyle( color: StreamChatTheme.of(context) .colorTheme @@ -450,7 +451,7 @@ class _ChatInfoScreenState extends State { ); } else { alternativeWidget = Text( - 'Last seen ${Jiffy(otherMember.lastActive).fromNow()}', + '${AppLocalizations.of(context).lastSeen} ${Jiffy(otherMember.lastActive).fromNow()}', style: TextStyle( color: StreamChatTheme.of(context) .colorTheme @@ -511,7 +512,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { elevation: 1, centerTitle: true, title: Text( - 'Shared Groups', + AppLocalizations.of(context).sharedGroups, style: TextStyle( color: StreamChatTheme.of(context).colorTheme.textHighEmphasis, fontSize: 16.0), @@ -544,7 +545,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { ), SizedBox(height: 16.0), Text( - 'No Shared Groups', + AppLocalizations.of(context).noSharedGroups, style: TextStyle( fontSize: 14.0, color: StreamChatTheme.of(context) @@ -554,7 +555,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { ), SizedBox(height: 8.0), Text( - 'Group shared with User will appear here.', + AppLocalizations.of(context).groupSharedWithUserAppearHere, textAlign: TextAlign.center, style: TextStyle( fontSize: 14.0, @@ -602,8 +603,8 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { child: LayoutBuilder(builder: (context, constraints) { String? title; if (extraData['name'] == null) { - final otherMembers = members.where( - (member) => member.userId != StreamChat.of(context).currentUser!.id); + final otherMembers = members.where((member) => + member.userId != StreamChat.of(context).currentUser!.id); if (otherMembers.isNotEmpty) { final maxWidth = constraints.maxWidth; final maxChars = maxWidth / textStyle.fontSize!; @@ -649,7 +650,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { Padding( padding: const EdgeInsets.all(8.0), child: Text( - '${channel.memberCount} members', + '${channel.memberCount} ${AppLocalizations.of(context).members.toLowerCase()}', style: TextStyle( color: StreamChatTheme.of(context) .colorTheme diff --git a/stream_chat_v1/lib/chips_input_text_field.dart b/stream_chat_v1/lib/chips_input_text_field.dart index a67895e770..73149c4e2e 100644 --- a/stream_chat_v1/lib/chips_input_text_field.dart +++ b/stream_chat_v1/lib/chips_input_text_field.dart @@ -1,3 +1,4 @@ +import 'package:example/localizations.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; @@ -75,7 +76,7 @@ class ChipInputTextFieldState extends State> { Padding( padding: const EdgeInsets.symmetric(vertical: 4.0), child: Text( - 'TO:', + '${AppLocalizations.of(context).to.toUpperCase()}:', style: StreamChatTheme.of(context) .textTheme .footnote diff --git a/stream_chat_v1/lib/choose_user_page.dart b/stream_chat_v1/lib/choose_user_page.dart index 7a4f2638be..7d3ce51667 100644 --- a/stream_chat_v1/lib/choose_user_page.dart +++ b/stream_chat_v1/lib/choose_user_page.dart @@ -1,5 +1,6 @@ import 'package:example/app_config.dart'; import 'package:example/home_page.dart'; +import 'package:example/localizations.dart'; import 'package:example/stream_version.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -41,12 +42,12 @@ class ChooseUserPage extends StatelessWidget { Padding( padding: const EdgeInsets.only(bottom: 13.0), child: Text( - 'Welcome to Stream Chat', + AppLocalizations.of(context).welcomeToStreamChat, style: StreamChatTheme.of(context).textTheme.title, ), ), Text( - 'Select a user to try the Flutter SDK:', + '${AppLocalizations.of(context).selectUserToTryFlutterSDK}:', style: StreamChatTheme.of(context).textTheme.body, ), Expanded( @@ -135,7 +136,7 @@ class ChooseUserPage extends StatelessWidget { StreamChatTheme.of(context).textTheme.bodyBold, ), subtitle: Text( - 'Stream test account', + AppLocalizations.of(context).streamTestAccount, style: StreamChatTheme.of(context) .textTheme .footnote @@ -166,11 +167,11 @@ class ChooseUserPage extends StatelessWidget { StreamChatTheme.of(context).colorTheme.borders, ), title: Text( - 'Advanced Options', + AppLocalizations.of(context).advancedOptions, style: StreamChatTheme.of(context).textTheme.bodyBold, ), subtitle: Text( - 'Custom settings', + AppLocalizations.of(context).customSettings, style: StreamChatTheme.of(context) .textTheme .footnote diff --git a/stream_chat_v1/lib/group_chat_details_screen.dart b/stream_chat_v1/lib/group_chat_details_screen.dart index b61bf665b0..6b899375a6 100644 --- a/stream_chat_v1/lib/group_chat_details_screen.dart +++ b/stream_chat_v1/lib/group_chat_details_screen.dart @@ -1,3 +1,4 @@ +import 'package:example/localizations.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:uuid/uuid.dart'; @@ -66,7 +67,7 @@ class _GroupChatDetailsScreenState extends State { backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, leading: const StreamBackButton(), title: Text( - 'Name of Group Chat', + AppLocalizations.of(context).nameOfGroupChat, style: TextStyle( color: StreamChatTheme.of(context).colorTheme.textHighEmphasis, fontSize: 16, @@ -80,7 +81,7 @@ class _GroupChatDetailsScreenState extends State { child: Row( children: [ Text( - 'NAME', + AppLocalizations.of(context).name.toUpperCase(), style: TextStyle( fontSize: 12, color: StreamChatTheme.of(context) @@ -100,7 +101,8 @@ class _GroupChatDetailsScreenState extends State { errorBorder: InputBorder.none, disabledBorder: InputBorder.none, contentPadding: const EdgeInsets.all(0), - hintText: 'Choose a group chat name', + hintText: + AppLocalizations.of(context).chooseAGroupChatName, hintStyle: TextStyle( fontSize: 14, color: StreamChatTheme.of(context) @@ -161,14 +163,14 @@ class _GroupChatDetailsScreenState extends State { switch (status) { case ConnectionStatus.connected: - statusString = 'Connected'; + statusString = AppLocalizations.of(context).connected; showStatus = false; break; case ConnectionStatus.connecting: - statusString = 'Reconnecting...'; + statusString = AppLocalizations.of(context).reconnecting; break; case ConnectionStatus.disconnected: - statusString = 'Disconnected'; + statusString = AppLocalizations.of(context).disconnected; break; } return InfoTile( @@ -190,7 +192,7 @@ class _GroupChatDetailsScreenState extends State { horizontal: 8, ), child: Text( - '$_totalUsers ${_totalUsers > 1 ? 'Members' : 'Member'}', + '$_totalUsers ${_totalUsers > 1 ? AppLocalizations.of(context).members : AppLocalizations.of(context).member}', style: TextStyle( color: StreamChatTheme.of(context) .colorTheme @@ -293,13 +295,13 @@ class _GroupChatDetailsScreenState extends State { height: 26.0, ), Text( - 'Something went wrong', + AppLocalizations.of(context).somethingWentWrongErrorMessage, style: StreamChatTheme.of(context).textTheme.headlineBold, ), SizedBox( height: 7.0, ), - Text('The operation couldn\'t be completed.'), + Text(AppLocalizations.of(context).operationCouldNotBeCompleted), SizedBox( height: 36.0, ), @@ -315,7 +317,7 @@ class _GroupChatDetailsScreenState extends State { children: [ TextButton( child: Text( - 'OK', + AppLocalizations.of(context).ok, style: StreamChatTheme.of(context) .textTheme .bodyBold diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/group_info_screen.dart index 8564afe624..9b1c881954 100644 --- a/stream_chat_v1/lib/group_info_screen.dart +++ b/stream_chat_v1/lib/group_info_screen.dart @@ -1,11 +1,10 @@ import 'dart:async'; import 'package:collection/collection.dart' show IterableExtension; +import 'package:example/localizations.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:jiffy/jiffy.dart'; -import 'package:stream_chat_flutter/src/option_list_tile.dart'; -import 'package:stream_chat_flutter/src/stream_svg_icon.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'channel_file_display_screen.dart'; @@ -106,7 +105,7 @@ class _GroupInfoScreenState extends State { builder: (context, state) { if (!state.hasData) { return Text( - 'Loading...', + AppLocalizations.of(context).loading, style: TextStyle( color: StreamChatTheme.of(context) .colorTheme @@ -139,7 +138,7 @@ class _GroupInfoScreenState extends State { height: 3.0, ), Text( - '${channel.channel.memberCount} Members, ${snapshot.data?.where((e) => e.user!.online).length ?? 0} Online', + '${channel.channel.memberCount} ${AppLocalizations.of(context).members}, ${snapshot.data?.where((e) => e.user!.online).length ?? 0} ${AppLocalizations.of(context).online}', style: TextStyle( color: StreamChatTheme.of(context) .colorTheme @@ -260,7 +259,9 @@ class _GroupInfoScreenState extends State { Padding( padding: const EdgeInsets.all(8.0), child: Text( - member.role == 'owner' ? 'Owner' : '', + member.role == 'owner' + ? AppLocalizations.of(context).owner + : '', style: TextStyle( color: StreamChatTheme.of(context) .colorTheme @@ -313,7 +314,7 @@ class _GroupInfoScreenState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ Text( - '${members.length - groupMembersLength} more', + '${members.length - groupMembersLength} ${AppLocalizations.of(context).more}', style: TextStyle( color: StreamChatTheme.of(context) .colorTheme @@ -352,7 +353,7 @@ class _GroupInfoScreenState extends State { Padding( padding: const EdgeInsets.all(7.0), child: Text( - 'NAME', + AppLocalizations.of(context).name.toUpperCase(), style: StreamChatTheme.of(context).textTheme.footnote.copyWith( color: StreamChatTheme.of(context) .colorTheme @@ -370,7 +371,7 @@ class _GroupInfoScreenState extends State { cursorColor: StreamChatTheme.of(context).colorTheme.textHighEmphasis, decoration: InputDecoration.collapsed( - hintText: 'Add a group name', + hintText: AppLocalizations.of(context).addAGroupName, hintStyle: StreamChatTheme.of(context) .textTheme .bodyBold @@ -457,7 +458,7 @@ class _GroupInfoScreenState extends State { return OptionListTile( tileColor: StreamChatTheme.of(context).colorTheme.appBg, separatorColor: StreamChatTheme.of(context).colorTheme.disabled, - title: 'Mute group', + title: AppLocalizations.of(context).muteGroup, titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), @@ -491,7 +492,7 @@ class _GroupInfoScreenState extends State { ); }), OptionListTile( - title: 'Pinned Messages', + title: AppLocalizations.of(context).pinnedMessages, tileColor: StreamChatTheme.of(context).colorTheme.appBg, titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( @@ -554,7 +555,7 @@ class _GroupInfoScreenState extends State { OptionListTile( tileColor: StreamChatTheme.of(context).colorTheme.appBg, separatorColor: StreamChatTheme.of(context).colorTheme.disabled, - title: 'Photos & Videos', + title: AppLocalizations.of(context).photosAndVideos, titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( padding: const EdgeInsets.symmetric(horizontal: 12.0), @@ -616,7 +617,7 @@ class _GroupInfoScreenState extends State { OptionListTile( tileColor: StreamChatTheme.of(context).colorTheme.appBg, separatorColor: StreamChatTheme.of(context).colorTheme.disabled, - title: 'Files', + title: AppLocalizations.of(context).files, titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( padding: const EdgeInsets.symmetric(horizontal: 12.0), @@ -659,7 +660,7 @@ class _GroupInfoScreenState extends State { OptionListTile( tileColor: StreamChatTheme.of(context).colorTheme.appBg, separatorColor: StreamChatTheme.of(context).colorTheme.disabled, - title: 'Leave Group', + title: AppLocalizations.of(context).leaveGroup, titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), @@ -678,10 +679,11 @@ class _GroupInfoScreenState extends State { onTap: () async { final res = await showConfirmationDialog( context, - title: 'Leave conversation', - okText: 'LEAVE', - question: 'Are you sure you want to leave this conversation?', - cancelText: 'CANCEL', + title: AppLocalizations.of(context).leaveConversation, + okText: AppLocalizations.of(context).leave.toUpperCase(), + question: + AppLocalizations.of(context).leaveConversationAreYouSure, + cancelText: AppLocalizations.of(context).cancel.toUpperCase(), icon: StreamSvgIcon.userRemove( color: StreamChatTheme.of(context).colorTheme.accentError, ), @@ -777,8 +779,8 @@ class _GroupInfoScreenState extends State { .textLowEmphasis, ), ), - Text( - 'No user matches these keywords...'), + Text(AppLocalizations.of(context) + .noUserMatchesTheseKeywords), ], ), ), @@ -815,7 +817,7 @@ class _GroupInfoScreenState extends State { cursorColor: theme.colorTheme.textHighEmphasis, autofocus: true, decoration: InputDecoration( - hintText: 'Search', + hintText: AppLocalizations.of(context).search, hintStyle: theme.textTheme.body.copyWith( color: theme.colorTheme.textLowEmphasis, ), @@ -916,7 +918,7 @@ class _GroupInfoScreenState extends State { .textLowEmphasis, size: 24.0, ), - 'View info', + AppLocalizations.of(context).viewInfo, () async { var client = StreamChat.of(context).client; @@ -952,7 +954,7 @@ class _GroupInfoScreenState extends State { .textLowEmphasis, size: 24.0, ), - 'Message', + AppLocalizations.of(context).message, () async { var client = StreamChat.of(context).client; @@ -999,14 +1001,16 @@ class _GroupInfoScreenState extends State { .accentError, size: 24.0, ), - 'Remove From Group', () async { + AppLocalizations.of(context).removeFromGroup, () async { final res = await showConfirmationDialog( context, - title: 'Remove member', - okText: 'REMOVE', + title: AppLocalizations.of(context).removeMember, + okText: + AppLocalizations.of(context).remove.toUpperCase(), question: - 'Are you sure you want to remove this member?', - cancelText: 'CANCEL', + AppLocalizations.of(context).removeMemberAreYouSure, + cancelText: + AppLocalizations.of(context).cancel.toUpperCase(), ); if (res == true) { @@ -1024,7 +1028,7 @@ class _GroupInfoScreenState extends State { .textLowEmphasis, size: 24.0, ), - 'Cancel', () { + AppLocalizations.of(context).cancel, () { Navigator.pop(context); }), ], @@ -1050,7 +1054,7 @@ class _GroupInfoScreenState extends State { if (otherMember != null) { if (otherMember.online) { alternativeWidget = Text( - 'Online', + AppLocalizations.of(context).online, style: TextStyle( color: StreamChatTheme.of(context) .colorTheme @@ -1059,7 +1063,7 @@ class _GroupInfoScreenState extends State { ); } else { alternativeWidget = Text( - 'Last seen ${Jiffy(otherMember.lastActive).fromNow()}', + '${AppLocalizations.of(context).lastSeen} ${Jiffy(otherMember.lastActive).fromNow()}', style: TextStyle( color: StreamChatTheme.of(context) .colorTheme @@ -1139,7 +1143,7 @@ class _GroupInfoScreenState extends State { title = '${currentMembers.map((e) => e.user!.name).join(', ')} ${exceedingMembers > 0 ? '+ $exceedingMembers' : ''}'; } else { - title = 'No title'; + title = AppLocalizations.of(context).noTitle; } } else { title = extraData['name']; @@ -1149,9 +1153,9 @@ class _GroupInfoScreenState extends State { String _getLastSeen(User user) { if (user.online) { - return 'Online'; + return AppLocalizations.of(context).online; } else { - return 'Last seen ${Jiffy(user.lastActive).fromNow()}'; + return '${AppLocalizations.of(context).lastSeen} ${Jiffy(user.lastActive).fromNow()}'; } } } diff --git a/stream_chat_v1/lib/localizations.dart b/stream_chat_v1/lib/localizations.dart new file mode 100644 index 0000000000..adff28dbdd --- /dev/null +++ b/stream_chat_v1/lib/localizations.dart @@ -0,0 +1,558 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +class AppLocalizations { + static const _localizedValues = >{ + 'en': { + 'add_a_group_name': 'Add a group name', + 'add_group_members': 'Add Group Members', + 'advanced_options': 'Advanced Options', + 'api_key_error': 'Please enter the Chat API Key', + 'attachment': 'attachment', + 'attachments': 'attachments', + 'cancel': 'Cancel', + 'chat_api_key': 'Chat API Key', + 'chats': 'Chats', + 'choose_a_group_chat_name': 'Choose a group chat name', + 'connected': 'Connected', + 'create_a_group': 'Create a Group', + 'custom_settings': 'Custom settings', + 'delete': 'Delete', + 'delete_conversation_are_you_sure': + 'Are you sure you want to delete this conversation?', + 'delete_conversation_title': 'Delete Conversation', + 'disconnected': 'Disconnected', + 'error_connecting': 'Error connecting, retry', + 'files': 'Files', + 'files_appear_here': 'Files sent in this chat will appear here', + 'group_shared_with_user_appear_here': + 'Group shared with User will appear here.', + 'last_seen': 'Last seen', + 'leave': 'Leave', + 'leave_conversation': 'Leave conversation', + 'leave_conversation_are_you_sure': + 'Are you sure you want to leave this conversation?', + 'leave_group': 'Leave Group', + 'loading': 'Loading...', + 'login': 'Login', + 'long_press_message': 'Long-press an important message and\nchoose', + 'matches_for': 'Matches for', + 'member': 'Member', + 'members': 'Members', + 'mentions': 'Mentions', + 'message': 'Message', + 'message_channel_description': 'Channel used for showing messages', + 'message_channel_name': 'Message channel', + 'more': 'more', + 'mute_group': 'Mute group', + 'mute_user': 'Mute user', + 'name': 'Name', + 'name_of_group_chat': 'Name of Group Chat', + 'new_chat': 'New Chat', + 'new_direct_message': 'New direct message', + 'new_group': 'New group', + 'no_chats_here_yet': 'No chats here yet...', + 'no_files': 'No Files', + 'no_media': 'No Media', + 'no_mentions_exist_yet': 'No mentions exist yet...', + 'no_pinned_items': 'No pinned items', + 'no_results': 'No results...', + 'no_shared_groups': 'No Shared Groups', + 'no_title': 'No title', + 'no_user_matches_these_keywords': 'No user matches these keywords...', + 'ok': 'OK', + 'online': 'Online', + 'on_the_platform': 'On the platform', + 'operation_could_not_be_completed': + 'The operation couldn\'t be completed.', + 'owner': 'Owner', + 'photos_and_videos': 'Photos & Videos', + 'photos_or_videos_will_appear_here': + 'Photos or videos sent in this chat will \nappear here', + 'pinned_messages': 'Pinned Messages', + 'pin_to_conversation': 'Pin to conversation', + 'reconnecting': 'Reconnecting...', + 'remove': 'Remove', + 'remove_from_group': 'Remove From Group', + 'remove_member': 'Remove member', + 'remove_member_are_you_sure': + 'Are you sure you want to remove this member?', + 'search': 'Search', + 'select_user_to_try_flutter_sdk': 'Select a user to try the Flutter SDK', + 'shared_groups': 'Shared Groups', + 'sign_out': 'Sign out', + 'something_went_wrong_error_message': 'Something went wrong', + 'stream_sdk': 'Stream SDK', + 'stream_test_account': 'Stream test account', + 'to': 'To', + 'type_a_name_hint': 'Type a name', + 'user_id': 'User ID', + 'user_id_error': 'Please enter the User ID', + 'username_optional': 'Username (optional)', + 'user_token': 'User Token', + 'user_token_error': 'Please enter the user token', + 'view_info': 'View info', + 'welcome_to_stream_chat': 'Welcome to Stream Chat', + }, + // TODO convert EN to IT + 'it': { + 'add_a_group_name': 'Add a group name', + 'add_group_members': 'Add Group Members', + 'advanced_options': 'Advanced Options', + 'api_key_error': 'Please enter the Chat API Key', + 'attachment': 'attachment', + 'attachments': 'attachments', + 'cancel': 'Cancel', + 'chat_api_key': 'Chat API Key', + 'chats': 'Chats', + 'choose_a_group_chat_name': 'Choose a group chat name', + 'connected': 'Connected', + 'create_a_group': 'Create a Group', + 'custom_settings': 'Custom settings', + 'delete': 'Delete', + 'delete_conversation_are_you_sure': + 'Are you sure you want to delete this conversation?', + 'delete_conversation_title': 'Delete Conversation', + 'disconnected': 'Disconnected', + 'error_connecting': 'Error connecting, retry', + 'files': 'Files', + 'files_appear_here': 'Files sent in this chat will appear here', + 'group_shared_with_user_appear_here': + 'Group shared with User will appear here.', + 'last_seen': 'Last seen', + 'leave': 'Leave', + 'leave_conversation': 'Leave conversation', + 'leave_conversation_are_you_sure': + 'Are you sure you want to leave this conversation?', + 'leave_group': 'Leave Group', + 'loading': 'Loading...', + 'login': 'Login', + 'long_press_message': 'Long-press an important message and\nchoose', + 'matches_for': 'Matches for', + 'member': 'Member', + 'members': 'Members', + 'mentions': 'Mentions', + 'message': 'Message', + 'message_channel_description': 'Channel used for showing messages', + 'message_channel_name': 'Message channel', + 'more': 'more', + 'mute_group': 'Mute group', + 'mute_user': 'Mute user', + 'name': 'Name', + 'name_of_group_chat': 'Name of Group Chat', + 'new_chat': 'New Chat', + 'new_direct_message': 'New direct message', + 'new_group': 'New group', + 'no_chats_here_yet': 'No chats here yet...', + 'no_files': 'No Files', + 'no_media': 'No Media', + 'no_mentions_exist_yet': 'No mentions exist yet...', + 'no_pinned_items': 'No pinned items', + 'no_results': 'No results...', + 'no_shared_groups': 'No Shared Groups', + 'no_title': 'No title', + 'no_user_matches_these_keywords': 'No user matches these keywords...', + 'ok': 'OK', + 'online': 'Online', + 'on_the_platform': 'On the platform', + 'operation_could_not_be_completed': + 'The operation couldn\'t be completed.', + 'owner': 'Owner', + 'photos_and_videos': 'Photos & Videos', + 'photos_or_videos_will_appear_here': + 'Photos or videos sent in this chat will \nappear here', + 'pinned_messages': 'Pinned Messages', + 'pin_to_conversation': 'Pin to conversation', + 'reconnecting': 'Reconnecting...', + 'remove': 'Remove', + 'remove_from_group': 'Remove From Group', + 'remove_member': 'Remove member', + 'remove_member_are_you_sure': + 'Are you sure you want to remove this member?', + 'search': 'Search', + 'select_user_to_try_flutter_sdk': 'Select a user to try the Flutter SDK', + 'shared_groups': 'Shared Groups', + 'sign_out': 'Sign out', + 'something_went_wrong_error_message': 'Something went wrong', + 'stream_sdk': 'Stream SDK', + 'stream_test_account': 'Stream test account', + 'to': 'To', + 'type_a_name_hint': 'Type a name', + 'user_id': 'User ID', + 'user_id_error': 'Please enter the User ID', + 'username_optional': 'Username (optional)', + 'user_token': 'User Token', + 'user_token_error': 'Please enter the user token', + 'view_info': 'View info', + 'welcome_to_stream_chat': 'Welcome to Stream Chat', + }, + }; + + final Locale locale; + + AppLocalizations(this.locale); + + String get addAGroupName { + return _localizedValues[locale.languageCode]!['add_a_group_name']!; + } + + String get addGroupMembers { + return _localizedValues[locale.languageCode]!['add_group_members']!; + } + + String get advancedOptions { + return _localizedValues[locale.languageCode]!['advanced_options']!; + } + + String get apiKeyError { + return _localizedValues[locale.languageCode]!['api_key_error']!; + } + + String get attachment { + return _localizedValues[locale.languageCode]!['attachment']!; + } + + String get attachments { + return _localizedValues[locale.languageCode]!['attachments']!; + } + + String get cancel { + return _localizedValues[locale.languageCode]!['cancel']!; + } + + String get chatApiKey { + return _localizedValues[locale.languageCode]!['chat_api_key']!; + } + + String get chats { + return _localizedValues[locale.languageCode]!['chats']!; + } + + String get chooseAGroupChatName { + return _localizedValues[locale.languageCode]!['choose_a_group_chat_name']!; + } + + String get connected { + return _localizedValues[locale.languageCode]!['connected']!; + } + + String get createAGroup { + return _localizedValues[locale.languageCode]!['create_a_group']!; + } + + String get customSettings { + return _localizedValues[locale.languageCode]!['custom_settings']!; + } + + String get delete { + return _localizedValues[locale.languageCode]!['delete']!; + } + + String get deleteConversationAreYouSure { + return _localizedValues[locale.languageCode]![ + 'delete_conversation_are_you_sure']!; + } + + String get deleteConversationTitle { + return _localizedValues[locale.languageCode]!['delete_conversation_title']!; + } + + String get disconnected { + return _localizedValues[locale.languageCode]!['disconnected']!; + } + + String get errorConnecting { + return _localizedValues[locale.languageCode]!['error_connecting']!; + } + + String get files { + return _localizedValues[locale.languageCode]!['files']!; + } + + String get filesAppearHere { + return _localizedValues[locale.languageCode]!['files_appear_here']!; + } + + String get groupSharedWithUserAppearHere { + return _localizedValues[locale.languageCode]![ + 'group_shared_with_user_appear_here']!; + } + + String get lastSeen { + return _localizedValues[locale.languageCode]!['last_seen']!; + } + + String get leave { + return _localizedValues[locale.languageCode]!['leave']!; + } + + String get leaveConversation { + return _localizedValues[locale.languageCode]!['leave_conversation']!; + } + + String get leaveConversationAreYouSure { + return _localizedValues[locale.languageCode]![ + 'leave_conversation_are_you_sure']!; + } + + String get leaveGroup { + return _localizedValues[locale.languageCode]!['leave_group']!; + } + + String get loading { + return _localizedValues[locale.languageCode]!['loading']!; + } + + String get login { + return _localizedValues[locale.languageCode]!['login']!; + } + + String get longPressMessage { + return _localizedValues[locale.languageCode]!['long_press_message']!; + } + + String get matchesFor { + return _localizedValues[locale.languageCode]!['matches_for']!; + } + + String get member { + return _localizedValues[locale.languageCode]!['member']!; + } + + String get members { + return _localizedValues[locale.languageCode]!['members']!; + } + + String get mentions { + return _localizedValues[locale.languageCode]!['mentions']!; + } + + String get message { + return _localizedValues[locale.languageCode]!['message']!; + } + + String get messageChannelDescription { + return _localizedValues[locale.languageCode]![ + 'message_channel_description']!; + } + + String get messageChannelName { + return _localizedValues[locale.languageCode]!['message_channel_name']!; + } + + String get more { + return _localizedValues[locale.languageCode]!['more']!; + } + + String get muteGroup { + return _localizedValues[locale.languageCode]!['mute_group']!; + } + + String get muteUser { + return _localizedValues[locale.languageCode]!['mute_user']!; + } + + String get name { + return _localizedValues[locale.languageCode]!['name']!; + } + + String get nameOfGroupChat { + return _localizedValues[locale.languageCode]!['name_of_group_chat']!; + } + + String get newChat { + return _localizedValues[locale.languageCode]!['new_chat']!; + } + + String get newDirectMessage { + return _localizedValues[locale.languageCode]!['new_direct_message']!; + } + + String get newGroup { + return _localizedValues[locale.languageCode]!['new_group']!; + } + + String get noChatsHereYet { + return _localizedValues[locale.languageCode]!['no_chats_here_yet']!; + } + + String get noFiles { + return _localizedValues[locale.languageCode]!['no_files']!; + } + + String get noMedia { + return _localizedValues[locale.languageCode]!['no_media']!; + } + + String get noMentionsExistYet { + return _localizedValues[locale.languageCode]!['no_mentions_exist_yet']!; + } + + String get noPinnedItems { + return _localizedValues[locale.languageCode]!['no_pinned_items']!; + } + + String get noResults { + return _localizedValues[locale.languageCode]!['no_results']!; + } + + String get noSharedGroups { + return _localizedValues[locale.languageCode]!['no_shared_groups']!; + } + + String get noTitle { + return _localizedValues[locale.languageCode]!['no_title']!; + } + + String get noUserMatchesTheseKeywords { + return _localizedValues[locale.languageCode]![ + 'no_user_matches_these_keywords']!; + } + + String get ok { + return _localizedValues[locale.languageCode]!['ok']!; + } + + String get online { + return _localizedValues[locale.languageCode]!['online']!; + } + + String get onThePlatorm { + return _localizedValues[locale.languageCode]!['on_the_platform']!; + } + + String get operationCouldNotBeCompleted { + return _localizedValues[locale.languageCode]![ + 'operation_could_not_be_completed']!; + } + + String get owner { + return _localizedValues[locale.languageCode]!['owner']!; + } + + String get photosAndVideos { + return _localizedValues[locale.languageCode]!['photos_and_videos']!; + } + + String get photosOrVideosWillAppearHere { + return _localizedValues[locale.languageCode]![ + 'photos_or_videos_will_appear_here']!; + } + + String get pinnedMessages { + return _localizedValues[locale.languageCode]!['pinned_messages']!; + } + + String get pinToConversation { + return _localizedValues[locale.languageCode]!['pin_to_conversation']!; + } + + String get reconnecting { + return _localizedValues[locale.languageCode]!['reconnecting']!; + } + + String get remove { + return _localizedValues[locale.languageCode]!['remove']!; + } + + String get removeFromGroup { + return _localizedValues[locale.languageCode]!['remove_from_group']!; + } + + String get removeMember { + return _localizedValues[locale.languageCode]!['remove_member']!; + } + + String get removeMemberAreYouSure { + return _localizedValues[locale.languageCode]![ + 'remove_member_are_you_sure']!; + } + + String get search { + return _localizedValues[locale.languageCode]!['search']!; + } + + String get selectUserToTryFlutterSDK { + return _localizedValues[locale.languageCode]![ + 'select_user_to_try_flutter_sdk']!; + } + + String get sharedGroups { + return _localizedValues[locale.languageCode]!['shared_groups']!; + } + + String get signOut { + return _localizedValues[locale.languageCode]!['sign_out']!; + } + + String get somethingWentWrongErrorMessage { + return _localizedValues[locale.languageCode]![ + 'something_went_wrong_error_message']!; + } + + String get streamSDK { + return _localizedValues[locale.languageCode]!['stream_sdk']!; + } + + String get streamTestAccount { + return _localizedValues[locale.languageCode]!['stream_test_account']!; + } + + String get to { + return _localizedValues[locale.languageCode]!['to']!; + } + + String get typeANameHint { + return _localizedValues[locale.languageCode]!['type_a_name_hint']!; + } + + String get userId { + return _localizedValues[locale.languageCode]!['user_id']!; + } + + String get userIdError { + return _localizedValues[locale.languageCode]!['user_id_error']!; + } + + String get usernameOptional { + return _localizedValues[locale.languageCode]!['username_optional']!; + } + + String get userToken { + return _localizedValues[locale.languageCode]!['user_token']!; + } + + String get userTokenError { + return _localizedValues[locale.languageCode]!['user_token_error']!; + } + + String get viewInfo { + return _localizedValues[locale.languageCode]!['view_info']!; + } + + String get welcomeToStreamChat { + return _localizedValues[locale.languageCode]!['welcome_to_stream_chat']!; + } + + static List languages() => _localizedValues.keys.toList(); + + static AppLocalizations of(BuildContext context) { + return Localizations.of(context, AppLocalizations)!; + } +} + +class AppLocalizationsDelegate extends LocalizationsDelegate { + const AppLocalizationsDelegate(); + + @override + bool isSupported(Locale locale) => + AppLocalizations.languages().contains(locale.languageCode); + + @override + Future load(Locale locale) { + return SynchronousFuture(AppLocalizations(locale)); + } + + @override + bool shouldReload(AppLocalizationsDelegate old) => false; +} diff --git a/stream_chat_v1/lib/main.dart b/stream_chat_v1/lib/main.dart index b25c857948..fc4ed9b076 100644 --- a/stream_chat_v1/lib/main.dart +++ b/stream_chat_v1/lib/main.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:example/choose_user_page.dart'; import 'package:example/home_page.dart'; +import 'package:example/localizations.dart'; import 'package:example/splash_screen.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; @@ -9,6 +10,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; +import 'package:stream_chat_localizations/stream_chat_localizations.dart'; import 'package:stream_chat_persistence/stream_chat_persistence.dart'; import 'package:streaming_shared_preferences/streaming_shared_preferences.dart'; @@ -107,6 +109,16 @@ class _MyAppState extends State 0: ThemeMode.system, 1: ThemeMode.light, }[snapshot], + supportedLocales: const [ + Locale('en'), + Locale('it'), + ], + localizationsDelegates: const [ + AppLocalizationsDelegate(), + GlobalStreamChatLocalizations.delegate, + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + ], builder: (context, child) => StreamChatTheme( data: StreamChatThemeData( brightness: Theme.of(context).brightness, diff --git a/stream_chat_v1/lib/new_chat_screen.dart b/stream_chat_v1/lib/new_chat_screen.dart index 7315c71d3b..c0829d07f7 100644 --- a/stream_chat_v1/lib/new_chat_screen.dart +++ b/stream_chat_v1/lib/new_chat_screen.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:example/localizations.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; @@ -124,7 +125,7 @@ class _NewChatScreenState extends State { backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, leading: const StreamBackButton(), title: Text( - 'New Chat', + AppLocalizations.of(context).newChat, style: StreamChatTheme.of(context).textTheme.headlineBold.copyWith( color: StreamChatTheme.of(context).colorTheme.textHighEmphasis), ), @@ -137,14 +138,14 @@ class _NewChatScreenState extends State { switch (status) { case ConnectionStatus.connected: - statusString = 'Connected'; + statusString = AppLocalizations.of(context).connected; showStatus = false; break; case ConnectionStatus.connecting: - statusString = 'Reconnecting...'; + statusString = AppLocalizations.of(context).reconnecting; break; case ConnectionStatus.disconnected: - statusString = 'Disconnected'; + statusString = AppLocalizations.of(context).disconnected; break; } return InfoTile( @@ -162,6 +163,7 @@ class _NewChatScreenState extends State { key: _chipInputTextFieldStateKey, controller: _controller, focusNode: _searchFocusNode, + hint: AppLocalizations.of(context).typeANameHint, chipBuilder: (context, user) { return GestureDetector( onTap: () { @@ -245,7 +247,7 @@ class _NewChatScreenState extends State { ), SizedBox(width: 8), Text( - 'Create a Group', + AppLocalizations.of(context).createAGroup, style: StreamChatTheme.of(context) .textTheme .bodyBold, @@ -269,8 +271,8 @@ class _NewChatScreenState extends State { ), child: Text( _isSearchActive - ? "Matches for \"$_userNameQuery\"" - : 'On the platform', + ? '${AppLocalizations.of(context).matchesFor} "$_userNameQuery"' + : AppLocalizations.of(context).onThePlatorm, style: StreamChatTheme.of(context) .textTheme .footnote @@ -307,8 +309,8 @@ class _NewChatScreenState extends State { filter: Filter.and([ if (_userNameQuery.isNotEmpty) Filter.autoComplete('name', _userNameQuery), - Filter.notEqual( - 'id', StreamChat.of(context).currentUser!.id), + Filter.notEqual('id', + StreamChat.of(context).currentUser!.id), ]), sort: [ SortOption( @@ -339,7 +341,8 @@ class _NewChatScreenState extends State { ), ), Text( - 'No user matches these keywords...', + AppLocalizations.of(context) + .noUserMatchesTheseKeywords, style: StreamChatTheme.of( context) .textTheme @@ -371,7 +374,7 @@ class _NewChatScreenState extends State { return Center( child: Text( - 'No chats here yet...', + AppLocalizations.of(context).noChatsHereYet, style: TextStyle( fontSize: 12, color: StreamChatTheme.of(context) diff --git a/stream_chat_v1/lib/new_group_chat_screen.dart b/stream_chat_v1/lib/new_group_chat_screen.dart index 1b21ec56e6..c9c7c0840d 100644 --- a/stream_chat_v1/lib/new_group_chat_screen.dart +++ b/stream_chat_v1/lib/new_group_chat_screen.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:example/localizations.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; @@ -57,7 +58,7 @@ class _NewGroupChatScreenState extends State { backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, leading: const StreamBackButton(), title: Text( - 'Add Group Members', + AppLocalizations.of(context).addGroupMembers, style: TextStyle( color: StreamChatTheme.of(context).colorTheme.textHighEmphasis, fontSize: 16, @@ -94,14 +95,14 @@ class _NewGroupChatScreenState extends State { switch (status) { case ConnectionStatus.connected: - statusString = 'Connected'; + statusString = AppLocalizations.of(context).connected; showStatus = false; break; case ConnectionStatus.connecting: - statusString = 'Reconnecting...'; + statusString = AppLocalizations.of(context).reconnecting; break; case ConnectionStatus.disconnected: - statusString = 'Disconnected'; + statusString = AppLocalizations.of(context).disconnected; break; } return InfoTile( @@ -117,6 +118,7 @@ class _NewGroupChatScreenState extends State { SliverToBoxAdapter( child: SearchTextField( controller: _controller, + hintText: AppLocalizations.of(context).search, ), ), if (_selectedUsers.isNotEmpty) @@ -209,8 +211,8 @@ class _NewGroupChatScreenState extends State { ), child: Text( _isSearchActive - ? 'Matches for \"$_userNameQuery\"' - : 'On the platform', + ? '${AppLocalizations.of(context).matchesFor} \"$_userNameQuery\"' + : AppLocalizations.of(context).onThePlatorm, style: TextStyle( color: StreamChatTheme.of(context) .colorTheme @@ -248,7 +250,8 @@ class _NewGroupChatScreenState extends State { filter: Filter.and([ if (_userNameQuery.isNotEmpty) Filter.autoComplete('name', _userNameQuery), - Filter.notEqual('id', StreamChat.of(context).currentUser!.id), + Filter.notEqual( + 'id', StreamChat.of(context).currentUser!.id), ]), sort: [ SortOption( @@ -278,7 +281,8 @@ class _NewGroupChatScreenState extends State { ), ), Text( - 'No user matches these keywords...', + AppLocalizations.of(context) + .noUserMatchesTheseKeywords, style: StreamChatTheme.of(context) .textTheme .footnote diff --git a/stream_chat_v1/lib/notifications_service.dart b/stream_chat_v1/lib/notifications_service.dart index 56f6ad7c7b..d9ad7c50e6 100644 --- a/stream_chat_v1/lib/notifications_service.dart +++ b/stream_chat_v1/lib/notifications_service.dart @@ -1,8 +1,11 @@ +import 'package:example/localizations.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart' hide Message; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -void showLocalNotification(Event event, String currentUserId) async { +void showLocalNotification( + Event event, String currentUserId, BuildContext context) async { if (![ EventType.messageNew, EventType.notificationMessageNew, @@ -27,8 +30,8 @@ void showLocalNotification(Event event, String currentUserId) async { NotificationDetails( android: AndroidNotificationDetails( 'message channel', - 'Message channel', - 'Channel used for showing messages', + AppLocalizations.of(context).messageChannelName, + AppLocalizations.of(context).messageChannelDescription, priority: Priority.high, importance: Importance.high, ), diff --git a/stream_chat_v1/lib/pinned_messages_screen.dart b/stream_chat_v1/lib/pinned_messages_screen.dart index f88270a5cb..bfbb2f6b34 100644 --- a/stream_chat_v1/lib/pinned_messages_screen.dart +++ b/stream_chat_v1/lib/pinned_messages_screen.dart @@ -1,3 +1,4 @@ +import 'package:example/localizations.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:video_player/video_player.dart'; @@ -64,7 +65,7 @@ class _PinnedMessagesScreenState extends State { elevation: 1, centerTitle: true, title: Text( - 'Pinned Messages', + AppLocalizations.of(context).pinnedMessages, style: TextStyle( color: StreamChatTheme.of(context).colorTheme.textHighEmphasis, fontSize: 16.0, @@ -102,7 +103,7 @@ class _PinnedMessagesScreenState extends State { ), SizedBox(height: 16.0), Text( - 'No pinned items', + AppLocalizations.of(context).noPinnedItems, style: TextStyle( fontSize: 17.0, color: @@ -115,7 +116,7 @@ class _PinnedMessagesScreenState extends State { textAlign: TextAlign.center, text: TextSpan(children: [ TextSpan( - text: 'Long-press an important message and\nchoose ', + text: '${AppLocalizations.of(context).longPressMessage} ', style: TextStyle( fontSize: 14.0, color: StreamChatTheme.of(context) @@ -125,7 +126,7 @@ class _PinnedMessagesScreenState extends State { ), ), TextSpan( - text: 'Pin to conversation', + text: AppLocalizations.of(context).pinToConversation, style: TextStyle( fontSize: 14.0, fontWeight: FontWeight.bold, @@ -186,7 +187,7 @@ class _PinnedMessagesScreenState extends State { text != '' ? text : (attachments.isNotEmpty - ? '${attachments.length} attachment${attachments.length > 1 ? 's' : ''}' + ? '${attachments.length} ${attachments.length > 1 ? AppLocalizations.of(context).attachments : AppLocalizations.of(context).attachment}' : ''), ), onTap: () { diff --git a/stream_chat_v1/lib/stream_version.dart b/stream_chat_v1/lib/stream_version.dart index 89004f7563..47d4651fc1 100644 --- a/stream_chat_v1/lib/stream_version.dart +++ b/stream_chat_v1/lib/stream_version.dart @@ -1,3 +1,4 @@ +import 'package:example/localizations.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:yaml/yaml.dart'; @@ -26,7 +27,7 @@ class StreamVersion extends StatelessWidget { yaml['packages']['stream_chat_flutter']['version']; return Text( - 'Stream SDK v $streamChatDep', + '${AppLocalizations.of(context).streamSDK} v $streamChatDep', style: TextStyle( fontSize: 14, color: StreamChatTheme.of(context).colorTheme.disabled, diff --git a/stream_chat_v1/lib/user_mentions_page.dart b/stream_chat_v1/lib/user_mentions_page.dart index 0128787f61..b10df76bf6 100644 --- a/stream_chat_v1/lib/user_mentions_page.dart +++ b/stream_chat_v1/lib/user_mentions_page.dart @@ -1,3 +1,4 @@ +import 'package:example/localizations.dart'; import 'package:example/routes/routes.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; @@ -45,7 +46,7 @@ class UserMentionsPage extends StatelessWidget { ), ), Text( - 'No mentions exist yet...', + AppLocalizations.of(context).noMentionsExistYet, style: StreamChatTheme.of(context) .textTheme .body diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index cc9a05e027..55bf8024bf 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -20,6 +20,11 @@ dependencies: url: https://github.com/GetStream/stream-chat-flutter.git ref: develop path: packages/stream_chat_persistence + stream_chat_localizations: + git: + url: https://github.com/GetStream/stream-chat-flutter.git + ref: develop + path: packages/stream_chat_localizations flutter_local_notifications: ^5.0.0+4 flutter_svg: ^0.22.0 flutter_secure_storage: ^4.2.0 @@ -44,6 +49,16 @@ dependency_overrides: url: https://github.com/GetStream/stream-chat-flutter.git ref: develop path: packages/stream_chat_flutter_core + stream_chat_localizations: + git: + url: https://github.com/GetStream/stream-chat-flutter.git + ref: develop + path: packages/stream_chat_localizations + stream_chat_flutter: + git: + url: https://github.com/GetStream/stream-chat-flutter.git + ref: develop + path: packages/stream_chat_flutter flutter: assets: From c25591b25c06692c326757094c59fbeb1b52851b Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 24 Aug 2021 17:44:10 +0200 Subject: [PATCH 069/172] feat(localization): added italian strings --- stream_chat_v1/lib/localizations.dart | 154 +++++++++++++------------- 1 file changed, 77 insertions(+), 77 deletions(-) diff --git a/stream_chat_v1/lib/localizations.dart b/stream_chat_v1/lib/localizations.dart index adff28dbdd..c0a46c05e0 100644 --- a/stream_chat_v1/lib/localizations.dart +++ b/stream_chat_v1/lib/localizations.dart @@ -94,97 +94,97 @@ class AppLocalizations { 'view_info': 'View info', 'welcome_to_stream_chat': 'Welcome to Stream Chat', }, - // TODO convert EN to IT 'it': { - 'add_a_group_name': 'Add a group name', - 'add_group_members': 'Add Group Members', - 'advanced_options': 'Advanced Options', - 'api_key_error': 'Please enter the Chat API Key', - 'attachment': 'attachment', - 'attachments': 'attachments', - 'cancel': 'Cancel', + 'add_a_group_name': 'Aggiungi un nome al gruppo', + 'add_group_members': 'Aggiungi un membro', + 'advanced_options': 'Opzioni Avanzate', + 'api_key_error': 'Per favore inserisci l\'API Key', + 'attachment': 'allegato', + 'attachments': 'allegati', + 'cancel': 'Annulla', 'chat_api_key': 'Chat API Key', - 'chats': 'Chats', - 'choose_a_group_chat_name': 'Choose a group chat name', - 'connected': 'Connected', - 'create_a_group': 'Create a Group', - 'custom_settings': 'Custom settings', - 'delete': 'Delete', + 'chats': 'Conversazioni', + 'choose_a_group_chat_name': 'Scegli un nome per il gruppo', + 'connected': 'Connesso', + 'create_a_group': 'Crea un Gruppo', + 'custom_settings': 'Opzioni Personalizzate', + 'delete': 'Cancella', 'delete_conversation_are_you_sure': - 'Are you sure you want to delete this conversation?', - 'delete_conversation_title': 'Delete Conversation', - 'disconnected': 'Disconnected', - 'error_connecting': 'Error connecting, retry', - 'files': 'Files', - 'files_appear_here': 'Files sent in this chat will appear here', + 'Sei sicuro di voler eliminare la conversazione?', + 'delete_conversation_title': 'Elimina Conversazione', + 'disconnected': 'Disconnesso', + 'error_connecting': 'Errore durante la connessione, riprova', + 'files': 'File', + 'files_appear_here': 'I file inviati in questa chat compariranno qui', 'group_shared_with_user_appear_here': - 'Group shared with User will appear here.', - 'last_seen': 'Last seen', - 'leave': 'Leave', - 'leave_conversation': 'Leave conversation', + 'I gruppi in comune con quest\'utente compariranno qui', + 'last_seen': 'Ultimo accesso', + 'leave': 'Lascia', + 'leave_conversation': 'Lascia conversazione', 'leave_conversation_are_you_sure': - 'Are you sure you want to leave this conversation?', - 'leave_group': 'Leave Group', - 'loading': 'Loading...', + 'Sei sicuro di voler lasciare questa conversazione?', + 'leave_group': 'Lascia Gruppo', + 'loading': 'Caricamento...', 'login': 'Login', - 'long_press_message': 'Long-press an important message and\nchoose', - 'matches_for': 'Matches for', - 'member': 'Member', - 'members': 'Members', - 'mentions': 'Mentions', - 'message': 'Message', - 'message_channel_description': 'Channel used for showing messages', - 'message_channel_name': 'Message channel', - 'more': 'more', - 'mute_group': 'Mute group', - 'mute_user': 'Mute user', - 'name': 'Name', - 'name_of_group_chat': 'Name of Group Chat', - 'new_chat': 'New Chat', - 'new_direct_message': 'New direct message', - 'new_group': 'New group', - 'no_chats_here_yet': 'No chats here yet...', - 'no_files': 'No Files', - 'no_media': 'No Media', - 'no_mentions_exist_yet': 'No mentions exist yet...', - 'no_pinned_items': 'No pinned items', - 'no_results': 'No results...', - 'no_shared_groups': 'No Shared Groups', - 'no_title': 'No title', - 'no_user_matches_these_keywords': 'No user matches these keywords...', + 'long_press_message': 'Premi a lungo su un messaggio importante e scegli', + 'matches_for': 'Risultati per', + 'member': 'Membro', + 'members': 'Membri', + 'mentions': 'Menzioni', + 'message': 'Messaggi', + 'message_channel_description': 'Canale usato per mostrare i messaggi', + 'message_channel_name': 'Invia un messaggio al canale', + 'more': 'altro', + 'mute_group': 'Silenzia gruppo', + 'mute_user': 'Silenzia utente', + 'name': 'Nome', + 'name_of_group_chat': 'Nome del gruppo', + 'new_chat': 'Nuova conversazione', + 'new_direct_message': 'Nuovo messaggio diretto', + 'new_group': 'Nuovo gruppo', + 'no_chats_here_yet': 'Ancora nessun messaggio...', + 'no_files': 'Nessun File', + 'no_media': 'Nessun Media', + 'no_mentions_exist_yet': 'Ancora nessuna menzione...', + 'no_pinned_items': 'Nessun messaggio in evidenza', + 'no_results': 'Nessun risultato...', + 'no_shared_groups': 'Nessun gruppo in comune', + 'no_title': 'Nessun titolo', + 'no_user_matches_these_keywords': 'Nessun utente per questa ricerca...', 'ok': 'OK', 'online': 'Online', - 'on_the_platform': 'On the platform', + 'on_the_platform': 'Sulla piattaforma', 'operation_could_not_be_completed': - 'The operation couldn\'t be completed.', - 'owner': 'Owner', - 'photos_and_videos': 'Photos & Videos', + 'Non รฉ stato possibile completare l\'operazione.', + 'owner': 'Proprietario', + 'photos_and_videos': 'Foto & Video', 'photos_or_videos_will_appear_here': - 'Photos or videos sent in this chat will \nappear here', - 'pinned_messages': 'Pinned Messages', - 'pin_to_conversation': 'Pin to conversation', - 'reconnecting': 'Reconnecting...', - 'remove': 'Remove', - 'remove_from_group': 'Remove From Group', - 'remove_member': 'Remove member', + 'Foto or video inviati in questa chat \ncompariranno qui', + 'pinned_messages': 'Messaggi in evidenza', + 'pin_to_conversation': 'Metti in evidenza', + 'reconnecting': 'Riconnessione...', + 'remove': 'Rimuovi', + 'remove_from_group': 'Rimuovi Dal Gruppo', + 'remove_member': 'Rimuovi membro', 'remove_member_are_you_sure': - 'Are you sure you want to remove this member?', - 'search': 'Search', - 'select_user_to_try_flutter_sdk': 'Select a user to try the Flutter SDK', - 'shared_groups': 'Shared Groups', + 'Sei sicuro di voler rimuovere questo membro?', + 'search': 'Cerca', + 'select_user_to_try_flutter_sdk': + 'Selezione un utente per provare l\'SDK Flutter', + 'shared_groups': 'Gruppi in comune', 'sign_out': 'Sign out', - 'something_went_wrong_error_message': 'Something went wrong', + 'something_went_wrong_error_message': 'Qualcosa รฉ andato storto', 'stream_sdk': 'Stream SDK', - 'stream_test_account': 'Stream test account', - 'to': 'To', - 'type_a_name_hint': 'Type a name', + 'stream_test_account': 'Account di test', + 'to': 'A', + 'type_a_name_hint': 'Scrivi un nome', 'user_id': 'User ID', - 'user_id_error': 'Please enter the User ID', - 'username_optional': 'Username (optional)', - 'user_token': 'User Token', - 'user_token_error': 'Please enter the user token', - 'view_info': 'View info', - 'welcome_to_stream_chat': 'Welcome to Stream Chat', + 'user_id_error': 'Per favore inserisci l\'ID dell\'utente', + 'username_optional': 'Username (opzionale)', + 'user_token': 'Token Utente', + 'user_token_error': 'Per favore inserisci il token', + 'view_info': 'Vedi info', + 'welcome_to_stream_chat': 'Benvenuto in Stream Chat', }, }; From 8fa53f53ce81f0a587bb5d061edd045d5a30af0f Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 24 Aug 2021 17:51:47 +0200 Subject: [PATCH 070/172] update deps --- stream_chat_v1/pubspec.yaml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index 55bf8024bf..b236a85e80 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -49,11 +49,6 @@ dependency_overrides: url: https://github.com/GetStream/stream-chat-flutter.git ref: develop path: packages/stream_chat_flutter_core - stream_chat_localizations: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop - path: packages/stream_chat_localizations stream_chat_flutter: git: url: https://github.com/GetStream/stream-chat-flutter.git From 4ec5c0edadea477d53f4642a5bee23745b5ea3cc Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 26 Aug 2021 10:22:54 +0200 Subject: [PATCH 071/172] chore(stream_chat_v1): update dependencies --- stream_chat_v1/lib/localizations.dart | 2 +- stream_chat_v1/pubspec.yaml | 35 +++------------------------ 2 files changed, 4 insertions(+), 33 deletions(-) diff --git a/stream_chat_v1/lib/localizations.dart b/stream_chat_v1/lib/localizations.dart index c0a46c05e0..3af45038b3 100644 --- a/stream_chat_v1/lib/localizations.dart +++ b/stream_chat_v1/lib/localizations.dart @@ -170,7 +170,7 @@ class AppLocalizations { 'Sei sicuro di voler rimuovere questo membro?', 'search': 'Cerca', 'select_user_to_try_flutter_sdk': - 'Selezione un utente per provare l\'SDK Flutter', + 'Seleziona un utente per provare l\'SDK Flutter', 'shared_groups': 'Gruppi in comune', 'sign_out': 'Sign out', 'something_went_wrong_error_message': 'Qualcosa รฉ andato storto', diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index b236a85e80..036abdea54 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -10,21 +10,9 @@ dependencies: flutter_app_badger: ^1.2.0 flutter: sdk: flutter - stream_chat_flutter: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop - path: packages/stream_chat_flutter - stream_chat_persistence: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop - path: packages/stream_chat_persistence - stream_chat_localizations: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop - path: packages/stream_chat_localizations + stream_chat_flutter: ^2.2.0 + stream_chat_persistence: ^2.2.0 + stream_chat_localizations: ^1.1.0 flutter_local_notifications: ^5.0.0+4 flutter_svg: ^0.22.0 flutter_secure_storage: ^4.2.0 @@ -38,23 +26,6 @@ dev_dependencies: flutter_launcher_icons: ^0.9.0 test: any -dependency_overrides: - stream_chat: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop - path: packages/stream_chat - stream_chat_flutter_core: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop - path: packages/stream_chat_flutter_core - stream_chat_flutter: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop - path: packages/stream_chat_flutter - flutter: assets: - assets/ From 4f487994cf6d5866fc33077a3db3abf64beafe9a Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 30 Aug 2021 10:17:02 +0200 Subject: [PATCH 072/172] feat(stream_chat_v1): implement foreground notifications --- stream_chat_v1/lib/channel_list.dart | 10 +++- stream_chat_v1/lib/home_page.dart | 56 +++++++++++++++++++++++ stream_chat_v1/lib/routes/app_routes.dart | 28 +++++++----- 3 files changed, 82 insertions(+), 12 deletions(-) diff --git a/stream_chat_v1/lib/channel_list.dart b/stream_chat_v1/lib/channel_list.dart index 5bac6cf755..0586b92c33 100644 --- a/stream_chat_v1/lib/channel_list.dart +++ b/stream_chat_v1/lib/channel_list.dart @@ -145,6 +145,15 @@ class _ChannelList extends State { ) : ChannelsBloc( child: ChannelListView( + onChannelTap: (channel, _) { + Navigator.pushNamed( + context, + Routes.CHANNEL_PAGE, + arguments: ChannelPageArgs( + channel: channel, + ), + ); + }, onStartChatPressed: () { Navigator.pushNamed(context, Routes.NEW_CHAT); }, @@ -154,7 +163,6 @@ class _ChannelList extends State { pagination: PaginationParams( limit: 20, ), - channelWidget: ChannelPage(), onViewInfoTap: (channel) { Navigator.pop(context); if (channel.memberCount == 2 && channel.isDistinct) { diff --git a/stream_chat_v1/lib/home_page.dart b/stream_chat_v1/lib/home_page.dart index 828230fd58..2345423e19 100644 --- a/stream_chat_v1/lib/home_page.dart +++ b/stream_chat_v1/lib/home_page.dart @@ -1,9 +1,56 @@ +import 'dart:async'; + +import 'package:example/channel_page.dart'; +import 'package:example/notifications_service.dart'; import 'package:example/routes/app_routes.dart'; import 'package:example/routes/routes.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; +class MyObserver extends NavigatorObserver { + Route? currentRoute; + late final StreamSubscription _subscription; + + MyObserver(StreamChatClient client, BuildContext context) { + _subscription = client.on(EventType.messageNew).listen((event) { + final channelId = event.channelId; + if (currentRoute?.settings.name == Routes.CHANNEL_PAGE) { + final args = currentRoute?.settings.arguments as ChannelPageArgs; + if (args.channel?.id == channelId) { + return; + } + } + + showLocalNotification(event, client.state.currentUser!.id, context); + }); + } + + @override + void didPop(Route route, Route? previousRoute) { + currentRoute = route; + } + + @override + void didPush(Route route, Route? previousRoute) { + currentRoute = route; + } + + @override + void didRemove(Route route, Route? previousRoute) { + currentRoute = route; + } + + @override + void didReplace({Route? newRoute, Route? oldRoute}) { + currentRoute = newRoute; + } + + void dispose() { + _subscription.cancel(); + } +} + class HomePageArgs { final StreamChatClient chatClient; @@ -24,6 +71,7 @@ class HomePage extends StatefulWidget { class _HomePageState extends State { final GlobalKey _navigatorKey = GlobalKey(); + MyObserver? _observer; @override Widget build(BuildContext context) { @@ -38,8 +86,16 @@ class _HomePageState extends State { key: _navigatorKey, onGenerateRoute: AppRoutes.generateRoute, initialRoute: Routes.CHANNEL_LIST_PAGE, + observers: [_observer!], ), ), ); } + + @override + void didChangeDependencies() { + _observer?.dispose(); + _observer = MyObserver(widget.chatClient, context); + super.didChangeDependencies(); + } } diff --git a/stream_chat_v1/lib/routes/app_routes.dart b/stream_chat_v1/lib/routes/app_routes.dart index 145fa8e6e2..a9beedc02e 100644 --- a/stream_chat_v1/lib/routes/app_routes.dart +++ b/stream_chat_v1/lib/routes/app_routes.dart @@ -21,13 +21,13 @@ class AppRoutes { switch (settings.name) { case Routes.APP: return MaterialPageRoute( - settings: const RouteSettings(name: Routes.APP), + settings: RouteSettings(arguments: args, name: Routes.APP), builder: (_) { return MyApp(); }); case Routes.HOME: return MaterialPageRoute( - settings: const RouteSettings(name: Routes.HOME), + settings: RouteSettings(arguments: args, name: Routes.HOME), builder: (_) { final homePageArgs = args as HomePageArgs; return HomePage( @@ -36,18 +36,19 @@ class AppRoutes { }); case Routes.CHOOSE_USER: return MaterialPageRoute( - settings: const RouteSettings(name: Routes.CHOOSE_USER), + settings: RouteSettings(arguments: args, name: Routes.CHOOSE_USER), builder: (_) { return ChooseUserPage(); }); case Routes.ADVANCED_OPTIONS: return MaterialPageRoute( - settings: const RouteSettings(name: Routes.ADVANCED_OPTIONS), + settings: + RouteSettings(arguments: args, name: Routes.ADVANCED_OPTIONS), builder: (_) => AdvancedOptionsPage(), ); case Routes.CHANNEL_PAGE: return MaterialPageRoute( - settings: const RouteSettings(name: Routes.CHANNEL_PAGE), + settings: RouteSettings(arguments: args, name: Routes.CHANNEL_PAGE), builder: (_) { final channelPageArgs = args as ChannelPageArgs; return StreamChannel( @@ -61,19 +62,21 @@ class AppRoutes { }); case Routes.NEW_CHAT: return MaterialPageRoute( - settings: const RouteSettings(name: Routes.NEW_CHAT), + settings: RouteSettings(arguments: args, name: Routes.NEW_CHAT), builder: (_) { return NewChatScreen(); }); case Routes.NEW_GROUP_CHAT: return MaterialPageRoute( - settings: const RouteSettings(name: Routes.NEW_GROUP_CHAT), + settings: + RouteSettings(arguments: args, name: Routes.NEW_GROUP_CHAT), builder: (_) { return NewGroupChatScreen(); }); case Routes.NEW_GROUP_CHAT_DETAILS: return MaterialPageRoute( - settings: const RouteSettings(name: Routes.NEW_GROUP_CHAT_DETAILS), + settings: RouteSettings( + arguments: args, name: Routes.NEW_GROUP_CHAT_DETAILS), builder: (_) { return GroupChatDetailsScreen( selectedUsers: args as List?, @@ -81,7 +84,8 @@ class AppRoutes { }); case Routes.CHAT_INFO_SCREEN: return MaterialPageRoute( - settings: const RouteSettings(name: Routes.CHAT_INFO_SCREEN), + settings: + RouteSettings(arguments: args, name: Routes.CHAT_INFO_SCREEN), builder: (context) { return ChatInfoScreen( user: args as User?, @@ -90,7 +94,8 @@ class AppRoutes { }); case Routes.GROUP_INFO_SCREEN: return MaterialPageRoute( - settings: const RouteSettings(name: Routes.GROUP_INFO_SCREEN), + settings: + RouteSettings(arguments: args, name: Routes.GROUP_INFO_SCREEN), builder: (context) { return GroupInfoScreen( messageTheme: StreamChatTheme.of(context).ownMessageTheme, @@ -98,7 +103,8 @@ class AppRoutes { }); case Routes.CHANNEL_LIST_PAGE: return MaterialPageRoute( - settings: const RouteSettings(name: Routes.CHANNEL_LIST_PAGE), + settings: + RouteSettings(arguments: args, name: Routes.CHANNEL_LIST_PAGE), builder: (context) { return ChannelListPage(); }); From 2d530c9eeb1bbfa7496fa11a4ade170194e24413 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 30 Aug 2021 10:21:40 +0200 Subject: [PATCH 073/172] use notification.message_new event --- stream_chat_v1/lib/home_page.dart | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/stream_chat_v1/lib/home_page.dart b/stream_chat_v1/lib/home_page.dart index 2345423e19..2567802651 100644 --- a/stream_chat_v1/lib/home_page.dart +++ b/stream_chat_v1/lib/home_page.dart @@ -13,7 +13,12 @@ class MyObserver extends NavigatorObserver { late final StreamSubscription _subscription; MyObserver(StreamChatClient client, BuildContext context) { - _subscription = client.on(EventType.messageNew).listen((event) { + _subscription = client + .on( + EventType.messageNew, + EventType.notificationMessageNew, + ) + .listen((event) { final channelId = event.channelId; if (currentRoute?.settings.name == Routes.CHANNEL_PAGE) { final args = currentRoute?.settings.arguments as ChannelPageArgs; From 31c172622cb298d3aa80f004f6600d2ba0a3a508 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 30 Aug 2021 10:24:07 +0200 Subject: [PATCH 074/172] add user check --- stream_chat_v1/lib/home_page.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/stream_chat_v1/lib/home_page.dart b/stream_chat_v1/lib/home_page.dart index 2567802651..803a80f533 100644 --- a/stream_chat_v1/lib/home_page.dart +++ b/stream_chat_v1/lib/home_page.dart @@ -19,6 +19,9 @@ class MyObserver extends NavigatorObserver { EventType.notificationMessageNew, ) .listen((event) { + if (event.message?.user?.id == client.state.currentUser?.id) { + return; + } final channelId = event.channelId; if (currentRoute?.settings.name == Routes.CHANNEL_PAGE) { final args = currentRoute?.settings.arguments as ChannelPageArgs; From 8be3c1f9c6b2f405b1a21f69e12d66092701beeb Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Wed, 1 Sep 2021 10:55:18 +0200 Subject: [PATCH 075/172] feat(stream_chat_v1): open channel on foreground notification press --- stream_chat_v1/lib/home_page.dart | 13 +++++-- stream_chat_v1/lib/notifications_service.dart | 37 ++++++++++++++++++- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/stream_chat_v1/lib/home_page.dart b/stream_chat_v1/lib/home_page.dart index 803a80f533..a53dd2c74c 100644 --- a/stream_chat_v1/lib/home_page.dart +++ b/stream_chat_v1/lib/home_page.dart @@ -12,7 +12,10 @@ class MyObserver extends NavigatorObserver { Route? currentRoute; late final StreamSubscription _subscription; - MyObserver(StreamChatClient client, BuildContext context) { + MyObserver( + StreamChatClient client, + GlobalKey navigatorKey, + ) { _subscription = client .on( EventType.messageNew, @@ -30,7 +33,11 @@ class MyObserver extends NavigatorObserver { } } - showLocalNotification(event, client.state.currentUser!.id, context); + showLocalNotification( + event, + client.state.currentUser!.id, + navigatorKey.currentState!.context, + ); }); } @@ -103,7 +110,7 @@ class _HomePageState extends State { @override void didChangeDependencies() { _observer?.dispose(); - _observer = MyObserver(widget.chatClient, context); + _observer = MyObserver(widget.chatClient, _navigatorKey); super.didChangeDependencies(); } } diff --git a/stream_chat_v1/lib/notifications_service.dart b/stream_chat_v1/lib/notifications_service.dart index d9ad7c50e6..86d6268711 100644 --- a/stream_chat_v1/lib/notifications_service.dart +++ b/stream_chat_v1/lib/notifications_service.dart @@ -1,11 +1,16 @@ +import 'package:example/channel_page.dart'; import 'package:example/localizations.dart'; +import 'package:example/routes/routes.dart'; import 'package:flutter/material.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart' hide Message; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; void showLocalNotification( - Event event, String currentUserId, BuildContext context) async { + Event event, + String currentUserId, + BuildContext context, +) async { if (![ EventType.messageNew, EventType.notificationMessageNew, @@ -22,7 +27,34 @@ void showLocalNotification( android: initializationSettingsAndroid, iOS: initializationSettingsIOS, ); - await flutterLocalNotificationsPlugin.initialize(initializationSettings); + await flutterLocalNotificationsPlugin.initialize( + initializationSettings, + onSelectNotification: (channelCid) async { + if (channelCid != null) { + final client = StreamChat.of(context).client; + var channel = client.state.channels[channelCid]; + + if (channel == null) { + final splits = channelCid.split(':'); + final type = splits[0]; + final id = splits[1]; + channel = client.channel( + type, + id: id, + ); + await channel.watch(); + } + + Navigator.pushNamed( + context, + Routes.CHANNEL_PAGE, + arguments: ChannelPageArgs( + channel: channel, + ), + ); + } + }, + ); await flutterLocalNotificationsPlugin.show( event.message!.id.hashCode, event.message!.user!.name, @@ -37,5 +69,6 @@ void showLocalNotification( ), iOS: IOSNotificationDetails(), ), + payload: '${event.channelType}:${event.channelId}', ); } From 50a3c517adf01defefbe137ae2b9fddda757ac5f Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 6 Sep 2021 10:24:38 +0200 Subject: [PATCH 076/172] chore: update fastlane --- stream_chat_v1/ios/fastlane/Fastfile | 3 ++- .../ios/fastlane/testflight_gym_export_options.plist | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/stream_chat_v1/ios/fastlane/Fastfile b/stream_chat_v1/ios/fastlane/Fastfile index 2d46198a85..100453c6e8 100644 --- a/stream_chat_v1/ios/fastlane/Fastfile +++ b/stream_chat_v1/ios/fastlane/Fastfile @@ -62,7 +62,7 @@ platform :ios do settings_to_override = { :BUNDLE_IDENTIFIER => "io.getstream.flutter", - :PROVISIONING_PROFILE_SPECIFIER => "match AppStore io.getstream.flutter 1620032657" + :PROVISIONING_PROFILE_SPECIFIER => "match AppStore io.getstream.flutter 1630915713" } gym( @@ -83,6 +83,7 @@ platform :ios do groups: ['Public'], distribute_external: true, changelog: message, + username: 'salvatore@getstrea.io', reject_build_waiting_for_review: true ) end diff --git a/stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist b/stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist index 2d09042589..65a11c89f1 100644 --- a/stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist +++ b/stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist @@ -7,7 +7,7 @@ provisioningProfiles io.getstream.flutter - match AppStore io.getstream.flutter + match AppStore io.getstream.flutter 1630915713 \ No newline at end of file From e70290af00c36b6acd045b2779604a1bc4ee1b57 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 6 Sep 2021 11:04:46 +0200 Subject: [PATCH 077/172] chore: update fastlane --- stream_chat_v1/ios/fastlane/Fastfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stream_chat_v1/ios/fastlane/Fastfile b/stream_chat_v1/ios/fastlane/Fastfile index 100453c6e8..fbe4989343 100644 --- a/stream_chat_v1/ios/fastlane/Fastfile +++ b/stream_chat_v1/ios/fastlane/Fastfile @@ -83,7 +83,7 @@ platform :ios do groups: ['Public'], distribute_external: true, changelog: message, - username: 'salvatore@getstrea.io', + username: 'salvatore@getstream.io', reject_build_waiting_for_review: true ) end From 7a2e49debc779a7c05b5c596aad8368c36129f35 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 6 Sep 2021 11:23:46 +0200 Subject: [PATCH 078/172] chore: update fastlane --- stream_chat_v1/ios/fastlane/Fastfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stream_chat_v1/ios/fastlane/Fastfile b/stream_chat_v1/ios/fastlane/Fastfile index fbe4989343..011f6b1587 100644 --- a/stream_chat_v1/ios/fastlane/Fastfile +++ b/stream_chat_v1/ios/fastlane/Fastfile @@ -26,7 +26,7 @@ lane :match_appstore do app_identifier: [ "io.getstream.flutter", ], - readonly: is_ci + readonly: false ) end From a767f97545a59c6c11c3cf58d890ba922f5e7547 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 6 Sep 2021 12:02:21 +0200 Subject: [PATCH 079/172] chore: update fastlane --- stream_chat_v1/ios/fastlane/Fastfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stream_chat_v1/ios/fastlane/Fastfile b/stream_chat_v1/ios/fastlane/Fastfile index 011f6b1587..fbe4989343 100644 --- a/stream_chat_v1/ios/fastlane/Fastfile +++ b/stream_chat_v1/ios/fastlane/Fastfile @@ -26,7 +26,7 @@ lane :match_appstore do app_identifier: [ "io.getstream.flutter", ], - readonly: false + readonly: is_ci ) end From fde630fe979200750bdd93a775a7bf2bb177b8b3 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 6 Sep 2021 12:35:13 +0200 Subject: [PATCH 080/172] chore: update fastlane --- stream_chat_v1/ios/fastlane/Fastfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stream_chat_v1/ios/fastlane/Fastfile b/stream_chat_v1/ios/fastlane/Fastfile index fbe4989343..011f6b1587 100644 --- a/stream_chat_v1/ios/fastlane/Fastfile +++ b/stream_chat_v1/ios/fastlane/Fastfile @@ -26,7 +26,7 @@ lane :match_appstore do app_identifier: [ "io.getstream.flutter", ], - readonly: is_ci + readonly: false ) end From 91374d7487401c31fe57e9eaf94d8dfce7a4989e Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 6 Sep 2021 12:53:07 +0200 Subject: [PATCH 081/172] chore: update fastlane --- stream_chat_v1/ios/fastlane/Fastfile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/stream_chat_v1/ios/fastlane/Fastfile b/stream_chat_v1/ios/fastlane/Fastfile index 011f6b1587..aab8fbe59d 100644 --- a/stream_chat_v1/ios/fastlane/Fastfile +++ b/stream_chat_v1/ios/fastlane/Fastfile @@ -60,19 +60,19 @@ platform :ios do lane :deploy_to_testflight do match_appstore - settings_to_override = { - :BUNDLE_IDENTIFIER => "io.getstream.flutter", - :PROVISIONING_PROFILE_SPECIFIER => "match AppStore io.getstream.flutter 1630915713" - } + # settings_to_override = { + # :BUNDLE_IDENTIFIER => "io.getstream.flutter", + # :PROVISIONING_PROFILE_SPECIFIER => "match AppStore io.getstream.flutter 1630915713" + # } gym( workspace: "./Runner.xcworkspace", scheme: "Runner", export_method: "app-store", - export_options: "./fastlane/testflight_gym_export_options.plist", + # export_options: "./fastlane/testflight_gym_export_options.plist", silent: true, clean: true, - xcargs: settings_to_override, + # xcargs: settings_to_override, include_symbols: true, output_directory: "./dist", ) From f47a4aa1336ac8c7f520c564acf935f667fb4ce1 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 6 Sep 2021 13:15:05 +0200 Subject: [PATCH 082/172] chore: update fastlane --- stream_chat_v1/ios/fastlane/Fastfile | 14 +++++++------- .../fastlane/testflight_gym_export_options.plist | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/stream_chat_v1/ios/fastlane/Fastfile b/stream_chat_v1/ios/fastlane/Fastfile index aab8fbe59d..c0df993e0f 100644 --- a/stream_chat_v1/ios/fastlane/Fastfile +++ b/stream_chat_v1/ios/fastlane/Fastfile @@ -26,7 +26,7 @@ lane :match_appstore do app_identifier: [ "io.getstream.flutter", ], - readonly: false + readonly: is_ci ) end @@ -60,19 +60,19 @@ platform :ios do lane :deploy_to_testflight do match_appstore - # settings_to_override = { - # :BUNDLE_IDENTIFIER => "io.getstream.flutter", - # :PROVISIONING_PROFILE_SPECIFIER => "match AppStore io.getstream.flutter 1630915713" - # } + settings_to_override = { + :BUNDLE_IDENTIFIER => "io.getstream.flutter", + :PROVISIONING_PROFILE_SPECIFIER => "match AppStore io.getstream.flutter 1630916072" + } gym( workspace: "./Runner.xcworkspace", scheme: "Runner", export_method: "app-store", - # export_options: "./fastlane/testflight_gym_export_options.plist", + export_options: "./fastlane/testflight_gym_export_options.plist", silent: true, clean: true, - # xcargs: settings_to_override, + xcargs: settings_to_override, include_symbols: true, output_directory: "./dist", ) diff --git a/stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist b/stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist index 65a11c89f1..1c4d3dca93 100644 --- a/stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist +++ b/stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist @@ -7,7 +7,7 @@ provisioningProfiles io.getstream.flutter - match AppStore io.getstream.flutter 1630915713 + match AppStore io.getstream.flutter 1630916072 \ No newline at end of file From 5fa61d5454f37d9cc789d7ea2b954f665cfad7db Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Tue, 5 Oct 2021 16:23:30 +0530 Subject: [PATCH 083/172] chore: migrate to latest dependencies --- .../lib/channel_file_display_screen.dart | 6 +++--- stream_chat_v1/lib/channel_list.dart | 6 ++---- .../lib/channel_media_display_screen.dart | 6 +++--- stream_chat_v1/lib/chat_info_screen.dart | 3 --- stream_chat_v1/lib/group_info_screen.dart | 5 +---- stream_chat_v1/lib/new_chat_screen.dart | 4 +--- stream_chat_v1/lib/new_group_chat_screen.dart | 4 +--- stream_chat_v1/lib/pinned_messages_screen.dart | 6 +++--- stream_chat_v1/lib/user_mentions_page.dart | 2 +- stream_chat_v1/pubspec.yaml | 14 +++++++------- 10 files changed, 22 insertions(+), 34 deletions(-) diff --git a/stream_chat_v1/lib/channel_file_display_screen.dart b/stream_chat_v1/lib/channel_file_display_screen.dart index 33394cf29b..c6bd84cbab 100644 --- a/stream_chat_v1/lib/channel_file_display_screen.dart +++ b/stream_chat_v1/lib/channel_file_display_screen.dart @@ -13,14 +13,14 @@ class ChannelFileDisplayScreen extends StatefulWidget { /// limit: the number of users to return (max is 30) /// offset: the offset (max is 1000) /// message_limit: how many messages should be included to each channel - final PaginationParams? paginationParams; + final PaginationParams paginationParams; /// The builder used when the file list is empty. final WidgetBuilder? emptyBuilder; const ChannelFileDisplayScreen({ this.sortOptions, - this.paginationParams, + this.paginationParams = const PaginationParams(limit: 20), this.emptyBuilder, }); @@ -151,7 +151,7 @@ class _ChannelFileDisplayScreenState extends State { ['file'], ), sort: widget.sortOptions, - pagination: widget.paginationParams!.copyWith( + pagination: widget.paginationParams.copyWith( offset: messageSearchBloc.messageResponses?.length ?? 0, ), ), diff --git a/stream_chat_v1/lib/channel_list.dart b/stream_chat_v1/lib/channel_list.dart index 0586b92c33..d675fba384 100644 --- a/stream_chat_v1/lib/channel_list.dart +++ b/stream_chat_v1/lib/channel_list.dart @@ -90,7 +90,7 @@ class _ChannelList extends State { ), ], pullToRefresh: false, - paginationParams: PaginationParams(limit: 20), + limit: 20, emptyBuilder: (_) { return LayoutBuilder( builder: (context, viewportConstraints) { @@ -160,9 +160,7 @@ class _ChannelList extends State { swipeToAction: true, filter: Filter.in_('members', [user!.id]), presence: true, - pagination: PaginationParams( - limit: 20, - ), + limit: 20, onViewInfoTap: (channel) { Navigator.pop(context); if (channel.memberCount == 2 && channel.isDistinct) { diff --git a/stream_chat_v1/lib/channel_media_display_screen.dart b/stream_chat_v1/lib/channel_media_display_screen.dart index 94357182b6..d7fc81b492 100644 --- a/stream_chat_v1/lib/channel_media_display_screen.dart +++ b/stream_chat_v1/lib/channel_media_display_screen.dart @@ -14,7 +14,7 @@ class ChannelMediaDisplayScreen extends StatefulWidget { /// limit: the number of users to return (max is 30) /// offset: the offset (max is 1000) /// message_limit: how many messages should be included to each channel - final PaginationParams? paginationParams; + final PaginationParams paginationParams; /// The builder used when the file list is empty. final WidgetBuilder? emptyBuilder; @@ -26,7 +26,7 @@ class ChannelMediaDisplayScreen extends StatefulWidget { const ChannelMediaDisplayScreen({ required this.messageTheme, this.sortOptions, - this.paginationParams, + this.paginationParams = const PaginationParams(limit: 20), this.emptyBuilder, this.onShowMessage, }); @@ -163,7 +163,7 @@ class _ChannelMediaDisplayScreenState extends State { ['image', 'video'], ), sort: widget.sortOptions, - pagination: widget.paginationParams!.copyWith( + pagination: widget.paginationParams.copyWith( offset: messageSearchBloc.messageResponses?.length ?? 0, ), ), diff --git a/stream_chat_v1/lib/chat_info_screen.dart b/stream_chat_v1/lib/chat_info_screen.dart index 9190479c01..3ef0814a9a 100644 --- a/stream_chat_v1/lib/chat_info_screen.dart +++ b/stream_chat_v1/lib/chat_info_screen.dart @@ -235,7 +235,6 @@ class _ChatInfoScreenState extends State { direction: SortOption.ASC, ), ], - paginationParams: PaginationParams(limit: 20), onShowMessage: (m, c) async { final client = StreamChat.of(context).client; final message = m; @@ -296,7 +295,6 @@ class _ChatInfoScreenState extends State { direction: SortOption.ASC, ), ], - paginationParams: PaginationParams(limit: 20), onShowMessage: (m, c) async { final client = StreamChat.of(context).client; final message = m; @@ -356,7 +354,6 @@ class _ChatInfoScreenState extends State { direction: SortOption.ASC, ), ], - paginationParams: PaginationParams(limit: 20), ), ), ), diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/group_info_screen.dart index 9b1c881954..eb28936c69 100644 --- a/stream_chat_v1/lib/group_info_screen.dart +++ b/stream_chat_v1/lib/group_info_screen.dart @@ -525,7 +525,6 @@ class _GroupInfoScreenState extends State { direction: SortOption.ASC, ), ], - paginationParams: PaginationParams(limit: 20), onShowMessage: (m, c) async { final client = StreamChat.of(context).client; final message = m; @@ -737,9 +736,7 @@ class _GroupInfoScreenState extends State { setState(() {}); }, crossAxisCount: 4, - pagination: PaginationParams( - limit: 25, - ), + limit: 25, filter: Filter.and( [ if (_searchController!.text.isNotEmpty) diff --git a/stream_chat_v1/lib/new_chat_screen.dart b/stream_chat_v1/lib/new_chat_screen.dart index c0829d07f7..461aa7cf26 100644 --- a/stream_chat_v1/lib/new_chat_screen.dart +++ b/stream_chat_v1/lib/new_chat_screen.dart @@ -303,9 +303,7 @@ class _NewChatScreenState extends State { _chipInputTextFieldState!.removeItem(user); } }, - pagination: PaginationParams( - limit: 25, - ), + limit: 25, filter: Filter.and([ if (_userNameQuery.isNotEmpty) Filter.autoComplete('name', _userNameQuery), diff --git a/stream_chat_v1/lib/new_group_chat_screen.dart b/stream_chat_v1/lib/new_group_chat_screen.dart index c9c7c0840d..2d0842ab24 100644 --- a/stream_chat_v1/lib/new_group_chat_screen.dart +++ b/stream_chat_v1/lib/new_group_chat_screen.dart @@ -244,9 +244,7 @@ class _NewGroupChatScreenState extends State { }); } }, - pagination: PaginationParams( - limit: 25, - ), + limit: 25, filter: Filter.and([ if (_userNameQuery.isNotEmpty) Filter.autoComplete('name', _userNameQuery), diff --git a/stream_chat_v1/lib/pinned_messages_screen.dart b/stream_chat_v1/lib/pinned_messages_screen.dart index bfbb2f6b34..da335bab11 100644 --- a/stream_chat_v1/lib/pinned_messages_screen.dart +++ b/stream_chat_v1/lib/pinned_messages_screen.dart @@ -14,7 +14,7 @@ class PinnedMessagesScreen extends StatefulWidget { /// limit: the number of users to return (max is 30) /// offset: the offset (max is 1000) /// message_limit: how many messages should be included to each channel - final PaginationParams? paginationParams; + final PaginationParams paginationParams; /// The builder used when the file list is empty. final WidgetBuilder? emptyBuilder; @@ -26,7 +26,7 @@ class PinnedMessagesScreen extends StatefulWidget { const PinnedMessagesScreen({ required this.messageTheme, this.sortOptions, - this.paginationParams, + this.paginationParams = const PaginationParams(limit: 20), this.emptyBuilder, this.onShowMessage, }); @@ -156,7 +156,7 @@ class _PinnedMessagesScreenState extends State { true, ), sort: widget.sortOptions, - pagination: widget.paginationParams!.copyWith( + pagination: widget.paginationParams.copyWith( offset: messageSearchBloc.messageResponses?.length ?? 0, ), ), diff --git a/stream_chat_v1/lib/user_mentions_page.dart b/stream_chat_v1/lib/user_mentions_page.dart index b10df76bf6..fa2d834201 100644 --- a/stream_chat_v1/lib/user_mentions_page.dart +++ b/stream_chat_v1/lib/user_mentions_page.dart @@ -23,7 +23,7 @@ class UserMentionsPage extends StatelessWidget { direction: SortOption.ASC, ), ], - paginationParams: PaginationParams(limit: 20), + limit: 20, showResultCount: false, emptyBuilder: (_) { return LayoutBuilder( diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index b236a85e80..21cb538dca 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -7,7 +7,7 @@ environment: sdk: '>=2.12.0 <3.0.0' dependencies: - flutter_app_badger: ^1.2.0 + flutter_app_badger: ^1.3.0 flutter: sdk: flutter stream_chat_flutter: @@ -25,17 +25,17 @@ dependencies: url: https://github.com/GetStream/stream-chat-flutter.git ref: develop path: packages/stream_chat_localizations - flutter_local_notifications: ^5.0.0+4 + flutter_local_notifications: ^8.2.0 flutter_svg: ^0.22.0 - flutter_secure_storage: ^4.2.0 + flutter_secure_storage: ^4.2.1 yaml: ^3.1.0 - uuid: ^3.0.4 + uuid: ^3.0.5 streaming_shared_preferences: ^2.0.0 - lottie: ^1.0.1 - collection: ^1.15.0-nullsafety.4 + lottie: ^1.2.1 + collection: ^1.15.0 dev_dependencies: - flutter_launcher_icons: ^0.9.0 + flutter_launcher_icons: ^0.9.2 test: any dependency_overrides: From 04c4df95555facd73431fd218f67a7b5c1b2b967 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Wed, 6 Oct 2021 10:59:03 +0200 Subject: [PATCH 084/172] bump version --- stream_chat_v1/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index 036abdea54..a42a7bcb71 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -1,7 +1,7 @@ name: example description: A new Flutter project. publish_to: 'none' -version: 1.7.0 +version: 1.7.1 environment: sdk: '>=2.12.0 <3.0.0' From d9e997ffb754c659befb971d6ef2b14fdd68e768 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Wed, 6 Oct 2021 11:50:21 +0200 Subject: [PATCH 085/172] update ios --- stream_chat_v1/ios/Flutter/AppFrameworkInfo.plist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stream_chat_v1/ios/Flutter/AppFrameworkInfo.plist b/stream_chat_v1/ios/Flutter/AppFrameworkInfo.plist index 6b4c0f78a7..f2872cf474 100644 --- a/stream_chat_v1/ios/Flutter/AppFrameworkInfo.plist +++ b/stream_chat_v1/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 8.0 + 9.0 From 3d3cc26616de3a433173176aa00fa3cbdbb01a17 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Wed, 6 Oct 2021 11:56:34 +0200 Subject: [PATCH 086/172] merge develop --- stream_chat_v1/ios/Flutter/AppFrameworkInfo.plist | 2 +- stream_chat_v1/ios/fastlane/Fastfile | 3 ++- .../ios/fastlane/testflight_gym_export_options.plist | 2 +- stream_chat_v1/lib/localizations.dart | 2 +- stream_chat_v1/pubspec.yaml | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/stream_chat_v1/ios/Flutter/AppFrameworkInfo.plist b/stream_chat_v1/ios/Flutter/AppFrameworkInfo.plist index 6b4c0f78a7..f2872cf474 100644 --- a/stream_chat_v1/ios/Flutter/AppFrameworkInfo.plist +++ b/stream_chat_v1/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 8.0 + 9.0 diff --git a/stream_chat_v1/ios/fastlane/Fastfile b/stream_chat_v1/ios/fastlane/Fastfile index 2d46198a85..c0df993e0f 100644 --- a/stream_chat_v1/ios/fastlane/Fastfile +++ b/stream_chat_v1/ios/fastlane/Fastfile @@ -62,7 +62,7 @@ platform :ios do settings_to_override = { :BUNDLE_IDENTIFIER => "io.getstream.flutter", - :PROVISIONING_PROFILE_SPECIFIER => "match AppStore io.getstream.flutter 1620032657" + :PROVISIONING_PROFILE_SPECIFIER => "match AppStore io.getstream.flutter 1630916072" } gym( @@ -83,6 +83,7 @@ platform :ios do groups: ['Public'], distribute_external: true, changelog: message, + username: 'salvatore@getstream.io', reject_build_waiting_for_review: true ) end diff --git a/stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist b/stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist index 2d09042589..1c4d3dca93 100644 --- a/stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist +++ b/stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist @@ -7,7 +7,7 @@ provisioningProfiles io.getstream.flutter - match AppStore io.getstream.flutter + match AppStore io.getstream.flutter 1630916072 \ No newline at end of file diff --git a/stream_chat_v1/lib/localizations.dart b/stream_chat_v1/lib/localizations.dart index c0a46c05e0..3af45038b3 100644 --- a/stream_chat_v1/lib/localizations.dart +++ b/stream_chat_v1/lib/localizations.dart @@ -170,7 +170,7 @@ class AppLocalizations { 'Sei sicuro di voler rimuovere questo membro?', 'search': 'Cerca', 'select_user_to_try_flutter_sdk': - 'Selezione un utente per provare l\'SDK Flutter', + 'Seleziona un utente per provare l\'SDK Flutter', 'shared_groups': 'Gruppi in comune', 'sign_out': 'Sign out', 'something_went_wrong_error_message': 'Qualcosa รฉ andato storto', diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index 21cb538dca..0c9254210b 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -1,7 +1,7 @@ name: example description: A new Flutter project. publish_to: 'none' -version: 1.7.0 +version: 1.7.1 environment: sdk: '>=2.12.0 <3.0.0' From 7519495b351b112857e1a7a0a19cf301be61dda1 Mon Sep 17 00:00:00 2001 From: Gordon Hayes Date: Wed, 6 Oct 2021 13:21:19 +0200 Subject: [PATCH 087/172] chore: update dependencies and fix lint warnings --- stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj | 2 -- stream_chat_v1/lib/advanced_options_page.dart | 1 - stream_chat_v1/lib/channel_file_display_screen.dart | 1 - stream_chat_v1/lib/channel_media_display_screen.dart | 1 - stream_chat_v1/lib/chat_info_screen.dart | 1 - stream_chat_v1/lib/group_chat_details_screen.dart | 1 - stream_chat_v1/lib/group_info_screen.dart | 1 - stream_chat_v1/lib/new_chat_screen.dart | 1 - stream_chat_v1/lib/notifications_service.dart | 3 ++- stream_chat_v1/lib/pinned_messages_screen.dart | 1 - stream_chat_v1/pubspec.yaml | 2 +- 11 files changed, 3 insertions(+), 12 deletions(-) diff --git a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj index 417fb0bdeb..052c2cef92 100644 --- a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj +++ b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj @@ -251,7 +251,6 @@ "${BUILT_PRODUCTS_DIR}/connectivity_plus/connectivity_plus.framework", "${BUILT_PRODUCTS_DIR}/file_picker/file_picker.framework", "${BUILT_PRODUCTS_DIR}/flutter_app_badger/flutter_app_badger.framework", - "${BUILT_PRODUCTS_DIR}/flutter_keyboard_visibility/flutter_keyboard_visibility.framework", "${BUILT_PRODUCTS_DIR}/flutter_local_notifications/flutter_local_notifications.framework", "${BUILT_PRODUCTS_DIR}/flutter_secure_storage/flutter_secure_storage.framework", "${BUILT_PRODUCTS_DIR}/image_gallery_saver/image_gallery_saver.framework", @@ -281,7 +280,6 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/connectivity_plus.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/file_picker.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_app_badger.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_keyboard_visibility.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_local_notifications.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_secure_storage.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/image_gallery_saver.framework", diff --git a/stream_chat_v1/lib/advanced_options_page.dart b/stream_chat_v1/lib/advanced_options_page.dart index f6f6f9faea..a42f2007f8 100644 --- a/stream_chat_v1/lib/advanced_options_page.dart +++ b/stream_chat_v1/lib/advanced_options_page.dart @@ -39,7 +39,6 @@ class _AdvancedOptionsPageState extends State { backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, elevation: 1, centerTitle: true, - brightness: Theme.of(context).brightness, title: Text( AppLocalizations.of(context).advancedOptions, style: StreamChatTheme.of(context).textTheme.headlineBold.copyWith( diff --git a/stream_chat_v1/lib/channel_file_display_screen.dart b/stream_chat_v1/lib/channel_file_display_screen.dart index c6bd84cbab..4f4a806ce8 100644 --- a/stream_chat_v1/lib/channel_file_display_screen.dart +++ b/stream_chat_v1/lib/channel_file_display_screen.dart @@ -53,7 +53,6 @@ class _ChannelFileDisplayScreenState extends State { return Scaffold( backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, appBar: AppBar( - brightness: Theme.of(context).brightness, elevation: 1, centerTitle: true, title: Text( diff --git a/stream_chat_v1/lib/channel_media_display_screen.dart b/stream_chat_v1/lib/channel_media_display_screen.dart index d7fc81b492..ee232935e2 100644 --- a/stream_chat_v1/lib/channel_media_display_screen.dart +++ b/stream_chat_v1/lib/channel_media_display_screen.dart @@ -62,7 +62,6 @@ class _ChannelMediaDisplayScreenState extends State { return Scaffold( backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, appBar: AppBar( - brightness: Theme.of(context).brightness, elevation: 1, centerTitle: true, title: Text( diff --git a/stream_chat_v1/lib/chat_info_screen.dart b/stream_chat_v1/lib/chat_info_screen.dart index 3ef0814a9a..2ba078912c 100644 --- a/stream_chat_v1/lib/chat_info_screen.dart +++ b/stream_chat_v1/lib/chat_info_screen.dart @@ -505,7 +505,6 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { return Scaffold( backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, appBar: AppBar( - brightness: Theme.of(context).brightness, elevation: 1, centerTitle: true, title: Text( diff --git a/stream_chat_v1/lib/group_chat_details_screen.dart b/stream_chat_v1/lib/group_chat_details_screen.dart index 6b899375a6..df40cc552f 100644 --- a/stream_chat_v1/lib/group_chat_details_screen.dart +++ b/stream_chat_v1/lib/group_chat_details_screen.dart @@ -62,7 +62,6 @@ class _GroupChatDetailsScreenState extends State { child: Scaffold( backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, appBar: AppBar( - brightness: Theme.of(context).brightness, elevation: 1, backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, leading: const StreamBackButton(), diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/group_info_screen.dart index eb28936c69..6a06e1e1da 100644 --- a/stream_chat_v1/lib/group_info_screen.dart +++ b/stream_chat_v1/lib/group_info_screen.dart @@ -93,7 +93,6 @@ class _GroupInfoScreenState extends State { return Scaffold( backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, appBar: AppBar( - brightness: Theme.of(context).brightness, elevation: 1.0, toolbarHeight: 56.0, backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, diff --git a/stream_chat_v1/lib/new_chat_screen.dart b/stream_chat_v1/lib/new_chat_screen.dart index 461aa7cf26..eb247c3ffe 100644 --- a/stream_chat_v1/lib/new_chat_screen.dart +++ b/stream_chat_v1/lib/new_chat_screen.dart @@ -120,7 +120,6 @@ class _NewChatScreenState extends State { return Scaffold( backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, appBar: AppBar( - brightness: Theme.of(context).brightness, elevation: 0, backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, leading: const StreamBackButton(), diff --git a/stream_chat_v1/lib/notifications_service.dart b/stream_chat_v1/lib/notifications_service.dart index 86d6268711..7e32197c0c 100644 --- a/stream_chat_v1/lib/notifications_service.dart +++ b/stream_chat_v1/lib/notifications_service.dart @@ -63,7 +63,8 @@ void showLocalNotification( android: AndroidNotificationDetails( 'message channel', AppLocalizations.of(context).messageChannelName, - AppLocalizations.of(context).messageChannelDescription, + channelDescription: + AppLocalizations.of(context).messageChannelDescription, priority: Priority.high, importance: Importance.high, ), diff --git a/stream_chat_v1/lib/pinned_messages_screen.dart b/stream_chat_v1/lib/pinned_messages_screen.dart index da335bab11..a3470bd31e 100644 --- a/stream_chat_v1/lib/pinned_messages_screen.dart +++ b/stream_chat_v1/lib/pinned_messages_screen.dart @@ -61,7 +61,6 @@ class _PinnedMessagesScreenState extends State { return Scaffold( backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, appBar: AppBar( - brightness: Theme.of(context).brightness, elevation: 1, centerTitle: true, title: Text( diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index 0c9254210b..b30685d57a 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -25,7 +25,7 @@ dependencies: url: https://github.com/GetStream/stream-chat-flutter.git ref: develop path: packages/stream_chat_localizations - flutter_local_notifications: ^8.2.0 + flutter_local_notifications: ^9.0.0 flutter_svg: ^0.22.0 flutter_secure_storage: ^4.2.1 yaml: ^3.1.0 From bda9fab2993ff5524c3caf9c208e391d3e47adb7 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 7 Oct 2021 11:57:46 +0200 Subject: [PATCH 088/172] fix ios build for ios 15 --- stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj index 417fb0bdeb..df8c694a06 100644 --- a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj +++ b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj @@ -443,7 +443,7 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", @@ -582,7 +582,7 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", @@ -616,7 +616,7 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", From 081680aa35860be0d8ec6511ba4600ae1e3725fb Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 7 Oct 2021 14:38:49 +0200 Subject: [PATCH 089/172] fix ios build for ios 15 --- stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj index df8c694a06..417fb0bdeb 100644 --- a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj +++ b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj @@ -443,7 +443,7 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", @@ -582,7 +582,7 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", @@ -616,7 +616,7 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", From b8cf5949aa8f1d1931482eccdf85659cd8cf9a82 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 7 Oct 2021 15:07:00 +0200 Subject: [PATCH 090/172] update profiles; --- stream_chat_v1/ios/fastlane/beta_gym_export_options.plist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stream_chat_v1/ios/fastlane/beta_gym_export_options.plist b/stream_chat_v1/ios/fastlane/beta_gym_export_options.plist index 372152802c..ab7643ae0f 100644 --- a/stream_chat_v1/ios/fastlane/beta_gym_export_options.plist +++ b/stream_chat_v1/ios/fastlane/beta_gym_export_options.plist @@ -7,7 +7,7 @@ provisioningProfiles io.getstream.flutter - match AdHoc io.getstream.flutter 1620032657 + match AdHoc io.getstream.flutter 1633610671 \ No newline at end of file From a9e27d3878171f733fa96f17d2f87ed9e25079dd Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 7 Oct 2021 15:44:33 +0200 Subject: [PATCH 091/172] update profiles --- stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj index 417fb0bdeb..cc4fc1c97e 100644 --- a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj +++ b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj @@ -451,7 +451,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter 1620032657"; + PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter 1633610671"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; @@ -590,7 +590,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter 1620032657"; + PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter 1633610671"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -624,7 +624,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter 1620032657"; + PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter 1633610671"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; From 95d8e2468e825ad1e695dd80835d1da6ab237d1e Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 8 Oct 2021 10:18:02 +0200 Subject: [PATCH 092/172] update fastfile --- stream_chat_v1/ios/fastlane/Fastfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stream_chat_v1/ios/fastlane/Fastfile b/stream_chat_v1/ios/fastlane/Fastfile index c0df993e0f..60680010c7 100644 --- a/stream_chat_v1/ios/fastlane/Fastfile +++ b/stream_chat_v1/ios/fastlane/Fastfile @@ -1,4 +1,4 @@ -fastlane_version "2.187.0" +fastlane_version "2.195.0" default_platform :ios before_all do From 3a9f8badfd009c360b29797ed5ec57c8ed1f6788 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 8 Oct 2021 10:46:24 +0200 Subject: [PATCH 093/172] update fastfile --- stream_chat_v1/ios/Gemfile.lock | 79 ++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 37 deletions(-) diff --git a/stream_chat_v1/ios/Gemfile.lock b/stream_chat_v1/ios/Gemfile.lock index 06d690f33b..85b5b38dd3 100644 --- a/stream_chat_v1/ios/Gemfile.lock +++ b/stream_chat_v1/ios/Gemfile.lock @@ -1,26 +1,27 @@ GEM remote: https://rubygems.org/ specs: - CFPropertyList (3.0.3) + CFPropertyList (3.0.4) + rexml addressable (2.8.0) public_suffix (>= 2.0.2, < 5.0) artifactory (3.0.15) atomos (0.1.3) - aws-eventstream (1.1.1) - aws-partitions (1.473.0) - aws-sdk-core (3.115.0) + aws-eventstream (1.2.0) + aws-partitions (1.512.0) + aws-sdk-core (3.121.1) aws-eventstream (~> 1, >= 1.0.2) aws-partitions (~> 1, >= 1.239.0) aws-sigv4 (~> 1.1) jmespath (~> 1.0) - aws-sdk-kms (1.44.0) - aws-sdk-core (~> 3, >= 3.112.0) + aws-sdk-kms (1.49.0) + aws-sdk-core (~> 3, >= 3.120.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.96.1) - aws-sdk-core (~> 3, >= 3.112.0) + aws-sdk-s3 (1.103.0) + aws-sdk-core (~> 3, >= 3.120.0) aws-sdk-kms (~> 1) - aws-sigv4 (~> 1.1) - aws-sigv4 (1.2.3) + aws-sigv4 (~> 1.4) + aws-sigv4 (1.4.0) aws-eventstream (~> 1, >= 1.0.2) babosa (1.0.4) claide (1.0.3) @@ -29,14 +30,14 @@ GEM commander (4.6.0) highline (~> 2.0.0) declarative (0.0.20) - digest-crc (0.6.3) + digest-crc (0.6.4) rake (>= 12.0.0, < 14.0.0) domain_name (0.5.20190701) unf (>= 0.0.5, < 1.0.0) dotenv (2.7.6) - emoji_regex (3.2.2) - excon (0.83.0) - faraday (1.5.0) + emoji_regex (3.2.3) + excon (0.86.0) + faraday (1.8.0) faraday-em_http (~> 1.0) faraday-em_synchrony (~> 1.0) faraday-excon (~> 1.1) @@ -44,6 +45,7 @@ GEM faraday-net_http (~> 1.0) faraday-net_http_persistent (~> 1.1) faraday-patron (~> 1.0) + faraday-rack (~> 1.0) multipart-post (>= 1.2, < 3) ruby2_keywords (>= 0.0.4) faraday-cookie_jar (0.0.7) @@ -54,14 +56,15 @@ GEM faraday-excon (1.1.0) faraday-httpclient (1.0.1) faraday-net_http (1.0.1) - faraday-net_http_persistent (1.1.0) + faraday-net_http_persistent (1.2.0) faraday-patron (1.0.0) - faraday_middleware (1.0.0) + faraday-rack (1.0.0) + faraday_middleware (1.1.0) faraday (~> 1.0) - fastimage (2.2.4) - fastlane (2.187.0) + fastimage (2.2.5) + fastlane (2.195.0) CFPropertyList (>= 2.3, < 4.0.0) - addressable (>= 2.3, < 3.0.0) + addressable (>= 2.8, < 3.0.0) artifactory (~> 3.0) aws-sdk-s3 (~> 1.0) babosa (>= 1.0.3, < 2.0.0) @@ -76,7 +79,7 @@ GEM faraday_middleware (~> 1.0) fastimage (>= 2.1.0, < 3.0.0) gh_inspector (>= 1.1.2, < 2.0.0) - google-apis-androidpublisher_v3 (~> 0.1) + google-apis-androidpublisher_v3 (~> 0.3) google-apis-playcustomapp_v1 (~> 0.1) google-cloud-storage (~> 1.31) highline (~> 2.0) @@ -85,6 +88,7 @@ GEM mini_magick (>= 4.9.4, < 5.0.0) multipart-post (~> 2.0.0) naturally (~> 2.2) + optparse (~> 0.1.1) plist (>= 3.1.0, < 4.0.0) rubyzip (>= 2.0.0, < 3.0.0) security (= 0.1.3) @@ -99,9 +103,9 @@ GEM xcpretty-travis-formatter (>= 0.0.3) fastlane-plugin-firebase_app_distribution (0.2.9) gh_inspector (1.1.3) - google-apis-androidpublisher_v3 (0.8.0) + google-apis-androidpublisher_v3 (0.11.0) google-apis-core (>= 0.4, < 2.a) - google-apis-core (0.4.0) + google-apis-core (0.4.1) addressable (~> 2.5, >= 2.5.1) googleauth (>= 0.16.2, < 2.a) httpclient (>= 2.8.1, < 3.a) @@ -110,19 +114,19 @@ GEM retriable (>= 2.0, < 4.a) rexml webrick - google-apis-iamcredentials_v1 (0.6.0) + google-apis-iamcredentials_v1 (0.7.0) google-apis-core (>= 0.4, < 2.a) google-apis-playcustomapp_v1 (0.5.0) google-apis-core (>= 0.4, < 2.a) - google-apis-storage_v1 (0.6.0) + google-apis-storage_v1 (0.8.0) google-apis-core (>= 0.4, < 2.a) google-cloud-core (1.6.0) google-cloud-env (~> 1.0) google-cloud-errors (~> 1.0) google-cloud-env (1.5.0) faraday (>= 0.17.3, < 2.0) - google-cloud-errors (1.1.0) - google-cloud-storage (1.34.0) + google-cloud-errors (1.2.0) + google-cloud-storage (1.34.1) addressable (~> 2.5) digest-crc (~> 0.4) google-apis-iamcredentials_v1 (~> 0.1) @@ -130,31 +134,32 @@ GEM google-cloud-core (~> 1.6) googleauth (>= 0.16.2, < 2.a) mini_mime (~> 1.0) - googleauth (0.16.2) + googleauth (1.0.0) faraday (>= 0.17.3, < 2.0) jwt (>= 1.4, < 3.0) memoist (~> 0.16) multi_json (~> 1.11) os (>= 0.9, < 2.0) - signet (~> 0.14) + signet (>= 0.16, < 2.a) highline (2.0.3) http-cookie (1.0.4) domain_name (~> 0.5) httpclient (2.8.3) jmespath (1.4.0) json (2.5.1) - jwt (2.2.3) + jwt (2.3.0) memoist (0.16.2) mini_magick (4.11.0) - mini_mime (1.1.0) + mini_mime (1.1.1) multi_json (1.15.0) multipart-post (2.0.0) nanaimo (0.3.0) naturally (2.2.1) + optparse (0.1.1) os (1.1.1) plist (3.6.0) public_suffix (4.0.6) - rake (13.0.4) + rake (13.0.6) representable (3.1.1) declarative (< 0.1.0) trailblazer-option (>= 0.1.1, < 0.2.0) @@ -162,11 +167,11 @@ GEM retriable (3.1.2) rexml (3.2.5) rouge (2.0.7) - ruby2_keywords (0.0.4) + ruby2_keywords (0.0.5) rubyzip (2.3.2) security (0.1.3) - signet (0.15.0) - addressable (~> 2.3) + signet (0.16.0) + addressable (~> 2.8) faraday (>= 0.17.3, < 2.0) jwt (>= 1.5, < 3.0) multi_json (~> 1.10) @@ -184,11 +189,11 @@ GEM uber (0.1.0) unf (0.1.4) unf_ext - unf_ext (0.0.7.7) - unicode-display_width (1.7.0) + unf_ext (0.0.8) + unicode-display_width (1.8.0) webrick (1.7.0) word_wrap (1.0.0) - xcodeproj (1.20.0) + xcodeproj (1.21.0) CFPropertyList (>= 2.3.3, < 4.0) atomos (~> 0.1.3) claide (>= 1.0.2, < 2.0) From 0df5bbfbba2424f91a91036179270310a1f20063 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 8 Oct 2021 11:15:16 +0200 Subject: [PATCH 094/172] update fastfile to work with xcode 13 --- stream_chat_v1/ios/fastlane/Fastfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/stream_chat_v1/ios/fastlane/Fastfile b/stream_chat_v1/ios/fastlane/Fastfile index 60680010c7..4caf06415d 100644 --- a/stream_chat_v1/ios/fastlane/Fastfile +++ b/stream_chat_v1/ios/fastlane/Fastfile @@ -34,7 +34,8 @@ platform :ios do desc "Deploy build to Firebase" lane :deploy_to_firebase do match_me - + xcversion(version: "~> 13.0.0") + gym( workspace: "./Runner.xcworkspace", scheme: "Runner", @@ -59,6 +60,7 @@ platform :ios do desc "Deploy build to TestFlight" lane :deploy_to_testflight do match_appstore + xcversion(version: "~> 13.0.0") settings_to_override = { :BUNDLE_IDENTIFIER => "io.getstream.flutter", From 858015318fb2bf7431747e5dc0ef77b65ed0b8f7 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 8 Oct 2021 11:33:56 +0200 Subject: [PATCH 095/172] update fastfile to work with xcode 13 --- stream_chat_v1/ios/Gemfile | 1 + stream_chat_v1/ios/fastlane/README.md | 2 +- stream_chat_v1/ios/fastlane/report.xml | 20 +++++--------------- 3 files changed, 7 insertions(+), 16 deletions(-) diff --git a/stream_chat_v1/ios/Gemfile b/stream_chat_v1/ios/Gemfile index cdd3a6b349..866ec9e672 100644 --- a/stream_chat_v1/ios/Gemfile +++ b/stream_chat_v1/ios/Gemfile @@ -1,6 +1,7 @@ source "https://rubygems.org" gem "fastlane" +gem "xcode-install" plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile') eval_gemfile(plugins_path) if File.exist?(plugins_path) diff --git a/stream_chat_v1/ios/fastlane/README.md b/stream_chat_v1/ios/fastlane/README.md index 7658d642c6..d6922829c2 100644 --- a/stream_chat_v1/ios/fastlane/README.md +++ b/stream_chat_v1/ios/fastlane/README.md @@ -42,6 +42,6 @@ Deploy build to TestFlight ---- -This README.md is auto-generated and will be re-generated every time [fastlane](https://fastlane.tools) is run. +This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run. More information about fastlane can be found on [fastlane.tools](https://fastlane.tools). The documentation of fastlane can be found on [docs.fastlane.tools](https://docs.fastlane.tools). diff --git a/stream_chat_v1/ios/fastlane/report.xml b/stream_chat_v1/ios/fastlane/report.xml index 55d4f11d97..c91f10a976 100644 --- a/stream_chat_v1/ios/fastlane/report.xml +++ b/stream_chat_v1/ios/fastlane/report.xml @@ -5,37 +5,27 @@ - + - + - + - + - - - - - - - - - - - + From fc69b62d738bc9786f0a2c727dad42eef521dd2c Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 8 Oct 2021 11:48:50 +0200 Subject: [PATCH 096/172] update fastfile to work with xcode 13 --- stream_chat_v1/ios/fastlane/Fastfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stream_chat_v1/ios/fastlane/Fastfile b/stream_chat_v1/ios/fastlane/Fastfile index 4caf06415d..68c3ea5e81 100644 --- a/stream_chat_v1/ios/fastlane/Fastfile +++ b/stream_chat_v1/ios/fastlane/Fastfile @@ -34,6 +34,7 @@ platform :ios do desc "Deploy build to Firebase" lane :deploy_to_firebase do match_me + xcode_install(version: "13.0") xcversion(version: "~> 13.0.0") gym( @@ -60,6 +61,7 @@ platform :ios do desc "Deploy build to TestFlight" lane :deploy_to_testflight do match_appstore + xcode_install(version: "13.0") xcversion(version: "~> 13.0.0") settings_to_override = { From 56dac48507ad1042c31f1a0f413ec7f2c8cfe712 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 8 Oct 2021 12:19:18 +0200 Subject: [PATCH 097/172] update mcaos image --- stream_chat_v1/ios/Gemfile | 1 - stream_chat_v1/ios/fastlane/Fastfile | 4 ---- 2 files changed, 5 deletions(-) diff --git a/stream_chat_v1/ios/Gemfile b/stream_chat_v1/ios/Gemfile index 866ec9e672..cdd3a6b349 100644 --- a/stream_chat_v1/ios/Gemfile +++ b/stream_chat_v1/ios/Gemfile @@ -1,7 +1,6 @@ source "https://rubygems.org" gem "fastlane" -gem "xcode-install" plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile') eval_gemfile(plugins_path) if File.exist?(plugins_path) diff --git a/stream_chat_v1/ios/fastlane/Fastfile b/stream_chat_v1/ios/fastlane/Fastfile index 68c3ea5e81..b1ac253a0e 100644 --- a/stream_chat_v1/ios/fastlane/Fastfile +++ b/stream_chat_v1/ios/fastlane/Fastfile @@ -34,8 +34,6 @@ platform :ios do desc "Deploy build to Firebase" lane :deploy_to_firebase do match_me - xcode_install(version: "13.0") - xcversion(version: "~> 13.0.0") gym( workspace: "./Runner.xcworkspace", @@ -61,8 +59,6 @@ platform :ios do desc "Deploy build to TestFlight" lane :deploy_to_testflight do match_appstore - xcode_install(version: "13.0") - xcversion(version: "~> 13.0.0") settings_to_override = { :BUNDLE_IDENTIFIER => "io.getstream.flutter", From 8746107c83ab287b91d1ec544088ad549a181917 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 18 Oct 2021 15:27:35 +0200 Subject: [PATCH 098/172] fix build --- stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj | 6 +++--- stream_chat_v1/ios/fastlane/beta_gym_export_options.plist | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj index 661acd0c3f..3b333d08d5 100644 --- a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj +++ b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj @@ -449,7 +449,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter 1633610671"; + PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter 1634304851"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; @@ -588,7 +588,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter 1633610671"; + PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter 1634304851"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -622,7 +622,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter 1633610671"; + PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter 1634304851"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; diff --git a/stream_chat_v1/ios/fastlane/beta_gym_export_options.plist b/stream_chat_v1/ios/fastlane/beta_gym_export_options.plist index ab7643ae0f..a7d01e55c9 100644 --- a/stream_chat_v1/ios/fastlane/beta_gym_export_options.plist +++ b/stream_chat_v1/ios/fastlane/beta_gym_export_options.plist @@ -7,7 +7,7 @@ provisioningProfiles io.getstream.flutter - match AdHoc io.getstream.flutter 1633610671 + match AdHoc io.getstream.flutter 1634304851 \ No newline at end of file From 4d1801f53f1b440097b0390256882f3b472bc202 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Wed, 20 Oct 2021 13:38:02 +0530 Subject: [PATCH 099/172] fix: add message search thread navigation support Signed-off-by: xsahil03x --- stream_chat_v1/lib/channel_page.dart | 4 +-- stream_chat_v1/lib/routes/app_routes.dart | 43 ++++++++++++++++------- stream_chat_v1/lib/thread_page.dart | 10 +++--- 3 files changed, 38 insertions(+), 19 deletions(-) diff --git a/stream_chat_v1/lib/channel_page.dart b/stream_chat_v1/lib/channel_page.dart index af21cb649d..6ed2398399 100644 --- a/stream_chat_v1/lib/channel_page.dart +++ b/stream_chat_v1/lib/channel_page.dart @@ -142,9 +142,7 @@ class _ChannelPageState extends State { ); }, threadBuilder: (_, parentMessage) { - return ThreadPage( - parent: parentMessage, - ); + return ThreadPage(parent: parentMessage!); }, pinPermissions: ['owner', 'admin', 'member'], ), diff --git a/stream_chat_v1/lib/routes/app_routes.dart b/stream_chat_v1/lib/routes/app_routes.dart index a9beedc02e..78593c4956 100644 --- a/stream_chat_v1/lib/routes/app_routes.dart +++ b/stream_chat_v1/lib/routes/app_routes.dart @@ -1,3 +1,4 @@ +import 'package:collection/src/iterable_extensions.dart'; import 'package:example/channel_list_page.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; @@ -12,6 +13,7 @@ import '../home_page.dart'; import '../main.dart'; import '../new_chat_screen.dart'; import '../new_group_chat_screen.dart'; +import '../thread_page.dart'; import 'routes.dart'; class AppRoutes { @@ -48,18 +50,35 @@ class AppRoutes { ); case Routes.CHANNEL_PAGE: return MaterialPageRoute( - settings: RouteSettings(arguments: args, name: Routes.CHANNEL_PAGE), - builder: (_) { - final channelPageArgs = args as ChannelPageArgs; - return StreamChannel( - channel: channelPageArgs.channel!, - initialMessageId: channelPageArgs.initialMessage?.id, - child: ChannelPage( - highlightInitialMessage: - channelPageArgs.initialMessage != null, - ), - ); - }); + settings: RouteSettings(arguments: args, name: Routes.CHANNEL_PAGE), + builder: (context) { + final channelPageArgs = args as ChannelPageArgs; + final initialMessage = channelPageArgs.initialMessage; + + return StreamChannel( + channel: channelPageArgs.channel!, + initialMessageId: initialMessage?.id, + child: Builder( + builder: (context) { + final parentId = initialMessage?.parentId; + Message? parentMessage; + if (parentId != null) { + final channel = StreamChannel.of(context).channel; + parentMessage = channel.state!.messages + .firstWhereOrNull((it) => it.id == parentId); + } + if (parentMessage != null) { + return ThreadPage(parent: parentMessage); + } + return ChannelPage( + highlightInitialMessage: + channelPageArgs.initialMessage != null, + ); + }, + ), + ); + }, + ); case Routes.NEW_CHAT: return MaterialPageRoute( settings: RouteSettings(arguments: args, name: Routes.NEW_CHAT), diff --git a/stream_chat_v1/lib/thread_page.dart b/stream_chat_v1/lib/thread_page.dart index 5e9d4fc54a..ca8d67cd95 100644 --- a/stream_chat_v1/lib/thread_page.dart +++ b/stream_chat_v1/lib/thread_page.dart @@ -2,13 +2,13 @@ import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; class ThreadPage extends StatefulWidget { - final Message? parent; + final Message parent; final int? initialScrollIndex; final double? initialAlignment; ThreadPage({ Key? key, - this.parent, + required this.parent, this.initialScrollIndex, this.initialAlignment, }) : super(key: key); @@ -39,7 +39,7 @@ class _ThreadPageState extends State { return Scaffold( backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, appBar: ThreadHeader( - parent: widget.parent!, + parent: widget.parent, ), body: Column( children: [ @@ -50,6 +50,8 @@ class _ThreadPageState extends State { initialAlignment: widget.initialAlignment, onMessageSwiped: _reply, messageFilter: defaultFilter, + showScrollToBottom: false, + highlightInitialMessage: true, messageBuilder: (context, details, messages, defaultMessage) { return defaultMessage.copyWith( onReplyTap: _reply, @@ -61,7 +63,7 @@ class _ThreadPageState extends State { pinPermissions: ['owner', 'admin', 'member'], ), ), - if (widget.parent!.type != 'deleted') + if (widget.parent.type != 'deleted') MessageInput( parentMessage: widget.parent, focusNode: _focusNode, From f07888556551dead5a7a43519681baad4e21bdc5 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 2 Nov 2021 12:45:57 +0100 Subject: [PATCH 100/172] update deps --- stream_chat_v1/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index b30685d57a..9043349871 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -26,7 +26,7 @@ dependencies: ref: develop path: packages/stream_chat_localizations flutter_local_notifications: ^9.0.0 - flutter_svg: ^0.22.0 + flutter_svg: ^0.23.0 flutter_secure_storage: ^4.2.1 yaml: ^3.1.0 uuid: ^3.0.5 From 7ba0b8fe22e7d9aa46f318425969d8597f06fa28 Mon Sep 17 00:00:00 2001 From: Gordon Hayes Date: Tue, 7 Dec 2021 16:17:36 +0100 Subject: [PATCH 101/172] fix: channel list performance --- stream_chat_v1/lib/channel_list.dart | 257 +++++++++++----------- stream_chat_v1/lib/channel_list_page.dart | 2 +- 2 files changed, 132 insertions(+), 127 deletions(-) diff --git a/stream_chat_v1/lib/channel_list.dart b/stream_chat_v1/lib/channel_list.dart index d675fba384..a1a6879b36 100644 --- a/stream_chat_v1/lib/channel_list.dart +++ b/stream_chat_v1/lib/channel_list.dart @@ -4,6 +4,7 @@ import 'package:example/localizations.dart'; import 'package:example/routes/routes.dart'; import 'package:example/search_text_field.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'channel_page.dart'; @@ -16,6 +17,8 @@ class ChannelList extends StatefulWidget { } class _ChannelList extends State { + ScrollController _scrollController = ScrollController(); + TextEditingController? _controller; String _channelQuery = ''; @@ -46,6 +49,7 @@ class _ChannelList extends State { void dispose() { _controller?.removeListener(_channelQueryListener); _controller?.dispose(); + _scrollController.dispose(); super.dispose(); } @@ -61,143 +65,144 @@ class _ChannelList extends State { } return true; }, - child: NestedScrollView( - floatHeaderSlivers: true, - headerSliverBuilder: (_, __) => [ - SliverToBoxAdapter( - child: SearchTextField( - controller: _controller, - showCloseButton: _isSearchActive, - hintText: AppLocalizations.of(context).search, + child: NotificationListener( + onNotification: (ScrollNotification scrollInfo) { + if (_scrollController.position.userScrollDirection == + ScrollDirection.reverse) { + FocusScope.of(context).unfocus(); + } + return true; + }, + child: NestedScrollView( + controller: _scrollController, + floatHeaderSlivers: false, + headerSliverBuilder: (_, __) => [ + SliverToBoxAdapter( + child: SearchTextField( + controller: _controller, + showCloseButton: _isSearchActive, + hintText: AppLocalizations.of(context).search, + ), ), - ), - ], - body: AnimatedSwitcher( - duration: const Duration(milliseconds: 350), - child: GestureDetector( - behavior: HitTestBehavior.opaque, - onPanDown: (_) => FocusScope.of(context).unfocus(), + ], + body: MessageSearchBloc( child: _isSearchActive - ? MessageSearchBloc( - child: MessageSearchListView( - showErrorTile: true, - messageQuery: _channelQuery, - filters: Filter.in_('members', [user!.id]), - sortOptions: [ - SortOption( - 'created_at', - direction: SortOption.ASC, - ), - ], - pullToRefresh: false, - limit: 20, - emptyBuilder: (_) { - return LayoutBuilder( - builder: (context, viewportConstraints) { - return SingleChildScrollView( - physics: AlwaysScrollableScrollPhysics(), - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: viewportConstraints.maxHeight, - ), - child: Center( - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(24), - child: StreamSvgIcon.search( - size: 96, - color: Colors.grey, - ), - ), - Text( - AppLocalizations.of(context).noResults, + ? MessageSearchListView( + showErrorTile: true, + messageQuery: _channelQuery, + filters: Filter.in_('members', [user!.id]), + sortOptions: [ + SortOption( + 'created_at', + direction: SortOption.ASC, + ), + ], + pullToRefresh: false, + limit: 30, + emptyBuilder: (_) { + return LayoutBuilder( + builder: (context, viewportConstraints) { + return SingleChildScrollView( + physics: AlwaysScrollableScrollPhysics(), + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: viewportConstraints.maxHeight, + ), + child: Center( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(24), + child: StreamSvgIcon.search( + size: 96, + color: Colors.grey, ), - ], - ), + ), + Text( + AppLocalizations.of(context).noResults, + ), + ], ), ), - ); - }, - ); - }, - onItemTap: (messageResponse) async { - FocusScope.of(context).requestFocus(FocusNode()); - final client = StreamChat.of(context).client; - final message = messageResponse.message; - final channel = client.channel( - messageResponse.channel!.type, - id: messageResponse.channel!.id, - ); - if (channel.state == null) { - await channel.watch(); - } - Navigator.pushNamed( - context, - Routes.CHANNEL_PAGE, - arguments: ChannelPageArgs( - channel: channel, - initialMessage: message, - ), - ); - }, - ), + ), + ); + }, + ); + }, + onItemTap: (messageResponse) async { + FocusScope.of(context).requestFocus(FocusNode()); + final client = StreamChat.of(context).client; + final message = messageResponse.message; + final channel = client.channel( + messageResponse.channel!.type, + id: messageResponse.channel!.id, + ); + if (channel.state == null) { + await channel.watch(); + } + Navigator.pushNamed( + context, + Routes.CHANNEL_PAGE, + arguments: ChannelPageArgs( + channel: channel, + initialMessage: message, + ), + ); + }, ) - : ChannelsBloc( - child: ChannelListView( - onChannelTap: (channel, _) { - Navigator.pushNamed( + : ChannelListView( + onChannelTap: (channel, _) { + Navigator.pushNamed( + context, + Routes.CHANNEL_PAGE, + arguments: ChannelPageArgs( + channel: channel, + ), + ); + }, + onStartChatPressed: () { + Navigator.pushNamed(context, Routes.NEW_CHAT); + }, + swipeToAction: true, + filter: Filter.in_('members', [user!.id]), + presence: true, + limit: 30, + onViewInfoTap: (channel) { + Navigator.pop(context); + if (channel.memberCount == 2 && channel.isDistinct) { + Navigator.push( context, - Routes.CHANNEL_PAGE, - arguments: ChannelPageArgs( - channel: channel, - ), - ); - }, - onStartChatPressed: () { - Navigator.pushNamed(context, Routes.NEW_CHAT); - }, - swipeToAction: true, - filter: Filter.in_('members', [user!.id]), - presence: true, - limit: 20, - onViewInfoTap: (channel) { - Navigator.pop(context); - if (channel.memberCount == 2 && channel.isDistinct) { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => StreamChannel( - channel: channel, - child: ChatInfoScreen( - messageTheme: StreamChatTheme.of(context) - .ownMessageTheme, - user: channel.state!.members - .where((m) => - m.userId != - channel.client.state.currentUser!.id) - .first - .user, - ), + MaterialPageRoute( + builder: (context) => StreamChannel( + channel: channel, + child: ChatInfoScreen( + messageTheme: + StreamChatTheme.of(context).ownMessageTheme, + user: channel.state!.members + .where((m) => + m.userId != + channel.client.state.currentUser!.id) + .first + .user, ), ), - ); - } else { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => StreamChannel( - channel: channel, - child: GroupInfoScreen( - messageTheme: StreamChatTheme.of(context) - .ownMessageTheme, - ), + ), + ); + } else { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => StreamChannel( + channel: channel, + child: GroupInfoScreen( + messageTheme: + StreamChatTheme.of(context).ownMessageTheme, ), ), - ); - } - }, - ), + ), + ); + } + }, ), ), ), diff --git a/stream_chat_v1/lib/channel_list_page.dart b/stream_chat_v1/lib/channel_list_page.dart index f29f96ac8e..928df1b2c5 100644 --- a/stream_chat_v1/lib/channel_list_page.dart +++ b/stream_chat_v1/lib/channel_list_page.dart @@ -100,7 +100,7 @@ class _ChannelListPageState extends State { body: IndexedStack( index: _currentIndex, children: [ - ChannelList(), + ChannelsBloc(child: ChannelList()), UserMentionsPage(), ], ), From 0ca9544461d03b2d6cca451e8e0fbae0de3b4c95 Mon Sep 17 00:00:00 2001 From: Gordon Hayes Date: Wed, 8 Dec 2021 15:14:23 +0100 Subject: [PATCH 102/172] chore: move message search bloc --- stream_chat_v1/lib/channel_list.dart | 220 +++++++++++----------- stream_chat_v1/lib/channel_list_page.dart | 6 +- 2 files changed, 114 insertions(+), 112 deletions(-) diff --git a/stream_chat_v1/lib/channel_list.dart b/stream_chat_v1/lib/channel_list.dart index a1a6879b36..d13e830fe8 100644 --- a/stream_chat_v1/lib/channel_list.dart +++ b/stream_chat_v1/lib/channel_list.dart @@ -85,126 +85,124 @@ class _ChannelList extends State { ), ), ], - body: MessageSearchBloc( - child: _isSearchActive - ? MessageSearchListView( - showErrorTile: true, - messageQuery: _channelQuery, - filters: Filter.in_('members', [user!.id]), - sortOptions: [ - SortOption( - 'created_at', - direction: SortOption.ASC, - ), - ], - pullToRefresh: false, - limit: 30, - emptyBuilder: (_) { - return LayoutBuilder( - builder: (context, viewportConstraints) { - return SingleChildScrollView( - physics: AlwaysScrollableScrollPhysics(), - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: viewportConstraints.maxHeight, - ), - child: Center( - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(24), - child: StreamSvgIcon.search( - size: 96, - color: Colors.grey, - ), - ), - Text( - AppLocalizations.of(context).noResults, + body: _isSearchActive + ? MessageSearchListView( + showErrorTile: true, + messageQuery: _channelQuery, + filters: Filter.in_('members', [user!.id]), + sortOptions: [ + SortOption( + 'created_at', + direction: SortOption.ASC, + ), + ], + pullToRefresh: false, + limit: 30, + emptyBuilder: (_) { + return LayoutBuilder( + builder: (context, viewportConstraints) { + return SingleChildScrollView( + physics: AlwaysScrollableScrollPhysics(), + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: viewportConstraints.maxHeight, + ), + child: Center( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(24), + child: StreamSvgIcon.search( + size: 96, + color: Colors.grey, ), - ], - ), + ), + Text( + AppLocalizations.of(context).noResults, + ), + ], ), ), - ); - }, - ); - }, - onItemTap: (messageResponse) async { - FocusScope.of(context).requestFocus(FocusNode()); - final client = StreamChat.of(context).client; - final message = messageResponse.message; - final channel = client.channel( - messageResponse.channel!.type, - id: messageResponse.channel!.id, - ); - if (channel.state == null) { - await channel.watch(); - } - Navigator.pushNamed( + ), + ); + }, + ); + }, + onItemTap: (messageResponse) async { + FocusScope.of(context).requestFocus(FocusNode()); + final client = StreamChat.of(context).client; + final message = messageResponse.message; + final channel = client.channel( + messageResponse.channel!.type, + id: messageResponse.channel!.id, + ); + if (channel.state == null) { + await channel.watch(); + } + Navigator.pushNamed( + context, + Routes.CHANNEL_PAGE, + arguments: ChannelPageArgs( + channel: channel, + initialMessage: message, + ), + ); + }, + ) + : ChannelListView( + onChannelTap: (channel, _) { + Navigator.pushNamed( + context, + Routes.CHANNEL_PAGE, + arguments: ChannelPageArgs( + channel: channel, + ), + ); + }, + onStartChatPressed: () { + Navigator.pushNamed(context, Routes.NEW_CHAT); + }, + swipeToAction: true, + filter: Filter.in_('members', [user!.id]), + presence: true, + limit: 30, + onViewInfoTap: (channel) { + Navigator.pop(context); + if (channel.memberCount == 2 && channel.isDistinct) { + Navigator.push( context, - Routes.CHANNEL_PAGE, - arguments: ChannelPageArgs( - channel: channel, - initialMessage: message, + MaterialPageRoute( + builder: (context) => StreamChannel( + channel: channel, + child: ChatInfoScreen( + messageTheme: + StreamChatTheme.of(context).ownMessageTheme, + user: channel.state!.members + .where((m) => + m.userId != + channel.client.state.currentUser!.id) + .first + .user, + ), + ), ), ); - }, - ) - : ChannelListView( - onChannelTap: (channel, _) { - Navigator.pushNamed( + } else { + Navigator.push( context, - Routes.CHANNEL_PAGE, - arguments: ChannelPageArgs( - channel: channel, - ), - ); - }, - onStartChatPressed: () { - Navigator.pushNamed(context, Routes.NEW_CHAT); - }, - swipeToAction: true, - filter: Filter.in_('members', [user!.id]), - presence: true, - limit: 30, - onViewInfoTap: (channel) { - Navigator.pop(context); - if (channel.memberCount == 2 && channel.isDistinct) { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => StreamChannel( - channel: channel, - child: ChatInfoScreen( - messageTheme: - StreamChatTheme.of(context).ownMessageTheme, - user: channel.state!.members - .where((m) => - m.userId != - channel.client.state.currentUser!.id) - .first - .user, - ), + MaterialPageRoute( + builder: (context) => StreamChannel( + channel: channel, + child: GroupInfoScreen( + messageTheme: + StreamChatTheme.of(context).ownMessageTheme, ), ), - ); - } else { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => StreamChannel( - channel: channel, - child: GroupInfoScreen( - messageTheme: - StreamChatTheme.of(context).ownMessageTheme, - ), - ), - ), - ); - } - }, - ), - ), + ), + ); + } + }, + ), ), ), ); diff --git a/stream_chat_v1/lib/channel_list_page.dart b/stream_chat_v1/lib/channel_list_page.dart index 928df1b2c5..be43bd65f6 100644 --- a/stream_chat_v1/lib/channel_list_page.dart +++ b/stream_chat_v1/lib/channel_list_page.dart @@ -100,7 +100,11 @@ class _ChannelListPageState extends State { body: IndexedStack( index: _currentIndex, children: [ - ChannelsBloc(child: ChannelList()), + ChannelsBloc( + child: MessageSearchBloc( + child: ChannelList(), + ), + ), UserMentionsPage(), ], ), From a9d5cb2caea37176fda0c4b1f08d4e89eb3c49b3 Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Thu, 6 Jan 2022 18:34:50 +0530 Subject: [PATCH 103/172] added mip changes, capabilities changes --- stream_chat_v1/lib/channel_page.dart | 11 +-- stream_chat_v1/lib/group_info_screen.dart | 90 +++++++++++++---------- stream_chat_v1/lib/thread_page.dart | 18 ++--- stream_chat_v1/pubspec.yaml | 8 +- 4 files changed, 66 insertions(+), 61 deletions(-) diff --git a/stream_chat_v1/lib/channel_page.dart b/stream_chat_v1/lib/channel_page.dart index 6ed2398399..19aa3a314c 100644 --- a/stream_chat_v1/lib/channel_page.dart +++ b/stream_chat_v1/lib/channel_page.dart @@ -34,8 +34,8 @@ class ChannelPage extends StatefulWidget { } class _ChannelPageState extends State { - Message? _quotedMessage; FocusNode? _focusNode; + MessageInputController _messageInputController = MessageInputController(); @override void initState() { @@ -50,7 +50,7 @@ class _ChannelPageState extends State { } void _reply(Message message) { - setState(() => _quotedMessage = message); + _messageInputController.quotedMessage = message; WidgetsBinding.instance!.addPostFrameCallback((timeStamp) { _focusNode!.requestFocus(); }); @@ -144,7 +144,6 @@ class _ChannelPageState extends State { threadBuilder: (_, parentMessage) { return ThreadPage(parent: parentMessage!); }, - pinPermissions: ['owner', 'admin', 'member'], ), Positioned( bottom: 0, @@ -177,11 +176,7 @@ class _ChannelPageState extends State { ), MessageInput( focusNode: _focusNode, - quotedMessage: _quotedMessage, - onQuotedMessageCleared: () { - setState(() => _quotedMessage = null); - _focusNode!.unfocus(); - }, + messageInputController: _messageInputController, ), ], ), diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/group_info_screen.dart index 6a06e1e1da..66c8306f2a 100644 --- a/stream_chat_v1/lib/group_info_screen.dart +++ b/stream_chat_v1/lib/group_info_screen.dart @@ -150,7 +150,10 @@ class _GroupInfoScreenState extends State { ), centerTitle: true, actions: [ - if (!channel.channel.isDistinct && isOwner) + if (!channel.channel.isDistinct && + isOwner && + channel.channel.ownCapabilities + .contains(PermissionType.updateChannelMembers)) StreamNeumorphicButton( child: InkWell( onTap: () { @@ -365,6 +368,8 @@ class _GroupInfoScreenState extends State { ), Expanded( child: TextField( + enabled: channel.ownCapabilities + .contains(PermissionType.updateChannel), focusNode: _focusNode, controller: _nameController, cursorColor: @@ -449,47 +454,50 @@ class _GroupInfoScreenState extends State { // ), // onTap: () {}, // ), - StreamBuilder( - stream: StreamChannel.of(context).channel.isMutedStream, - builder: (context, snapshot) { - mutedBool.value = snapshot.data; + if (channel.channel.ownCapabilities + .contains(PermissionType.muteChannel)) + StreamBuilder( + stream: StreamChannel.of(context).channel.isMutedStream, + builder: (context, snapshot) { + mutedBool.value = snapshot.data; - return OptionListTile( - tileColor: StreamChatTheme.of(context).colorTheme.appBg, - separatorColor: StreamChatTheme.of(context).colorTheme.disabled, - title: AppLocalizations.of(context).muteGroup, - titleTextStyle: StreamChatTheme.of(context).textTheme.body, - leading: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: StreamSvgIcon.mute( - size: 24.0, - color: StreamChatTheme.of(context) - .colorTheme - .textHighEmphasis - .withOpacity(0.5), + return OptionListTile( + tileColor: StreamChatTheme.of(context).colorTheme.appBg, + separatorColor: + StreamChatTheme.of(context).colorTheme.disabled, + title: AppLocalizations.of(context).muteGroup, + titleTextStyle: StreamChatTheme.of(context).textTheme.body, + leading: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: StreamSvgIcon.mute( + size: 24.0, + color: StreamChatTheme.of(context) + .colorTheme + .textHighEmphasis + .withOpacity(0.5), + ), ), - ), - trailing: snapshot.data == null - ? CircularProgressIndicator() - : ValueListenableBuilder( - valueListenable: mutedBool, - builder: (context, value, _) { - return CupertinoSwitch( - value: value!, - onChanged: (val) { - mutedBool.value = val; + trailing: snapshot.data == null + ? CircularProgressIndicator() + : ValueListenableBuilder( + valueListenable: mutedBool, + builder: (context, value, _) { + return CupertinoSwitch( + value: value!, + onChanged: (val) { + mutedBool.value = val; - if (snapshot.data!) { - channel.channel.unmute(); - } else { - channel.channel.mute(); - } - }, - ); - }), - onTap: () {}, - ); - }), + if (snapshot.data!) { + channel.channel.unmute(); + } else { + channel.channel.mute(); + } + }, + ); + }), + onTap: () {}, + ); + }), OptionListTile( title: AppLocalizations.of(context).pinnedMessages, tileColor: StreamChatTheme.of(context).colorTheme.appBg, @@ -654,7 +662,9 @@ class _GroupInfoScreenState extends State { ); }, ), - if (!channel.channel.isDistinct) + if (!channel.channel.isDistinct && + channel.channel.ownCapabilities + .contains(PermissionType.leaveChannel)) OptionListTile( tileColor: StreamChatTheme.of(context).colorTheme.appBg, separatorColor: StreamChatTheme.of(context).colorTheme.disabled, diff --git a/stream_chat_v1/lib/thread_page.dart b/stream_chat_v1/lib/thread_page.dart index ca8d67cd95..f61130c9a0 100644 --- a/stream_chat_v1/lib/thread_page.dart +++ b/stream_chat_v1/lib/thread_page.dart @@ -18,8 +18,14 @@ class ThreadPage extends StatefulWidget { } class _ThreadPageState extends State { - Message? _quotedMessage; FocusNode _focusNode = FocusNode(); + late MessageInputController _messageInputController; + + @override + void initState() { + super.initState(); + _messageInputController = MessageInputController(message: widget.parent); + } @override void dispose() { @@ -28,7 +34,7 @@ class _ThreadPageState extends State { } void _reply(Message message) { - setState(() => _quotedMessage = message); + _messageInputController.quotedMessage = message; WidgetsBinding.instance!.addPostFrameCallback((timeStamp) { _focusNode.requestFocus(); }); @@ -60,18 +66,12 @@ class _ThreadPageState extends State { }, ); }, - pinPermissions: ['owner', 'admin', 'member'], ), ), if (widget.parent.type != 'deleted') MessageInput( - parentMessage: widget.parent, focusNode: _focusNode, - quotedMessage: _quotedMessage, - onQuotedMessageCleared: () { - setState(() => _quotedMessage = null); - _focusNode.unfocus(); - }, + messageInputController: _messageInputController, ), ], ), diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index 9043349871..d2190d05a3 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -23,7 +23,7 @@ dependencies: stream_chat_localizations: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop + ref: feat/capabilities path: packages/stream_chat_localizations flutter_local_notifications: ^9.0.0 flutter_svg: ^0.23.0 @@ -42,17 +42,17 @@ dependency_overrides: stream_chat: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop + ref: feat/capabilities path: packages/stream_chat stream_chat_flutter_core: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop + ref: feat/capabilities path: packages/stream_chat_flutter_core stream_chat_flutter: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop + ref: feat/capabilities path: packages/stream_chat_flutter flutter: From d0076606ca7e8df37f34f28910b86f2daedeceef Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Wed, 19 Jan 2022 19:03:09 +0530 Subject: [PATCH 104/172] fix(sample): fix various bugs. Signed-off-by: xsahil03x --- stream_chat_v1/lib/channel_list_page.dart | 10 +++++++++- stream_chat_v1/lib/chat_info_screen.dart | 7 ++++--- stream_chat_v1/lib/group_chat_details_screen.dart | 2 +- stream_chat_v1/lib/group_info_screen.dart | 3 ++- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/stream_chat_v1/lib/channel_list_page.dart b/stream_chat_v1/lib/channel_list_page.dart index be43bd65f6..d484307456 100644 --- a/stream_chat_v1/lib/channel_list_page.dart +++ b/stream_chat_v1/lib/channel_list_page.dart @@ -40,7 +40,15 @@ class _ChannelListPageState extends State { Positioned( top: -3, right: -16, - child: UnreadIndicator(), + child: StreamBuilder( + stream: + StreamChat.of(context).client.state.unreadChannelsStream, + initialData: 0, + builder: + (BuildContext context, AsyncSnapshot snapshot) { + return Text(snapshot.data.toString()); + }, + ), ), ], ), diff --git a/stream_chat_v1/lib/chat_info_screen.dart b/stream_chat_v1/lib/chat_info_screen.dart index 2ba078912c..c6b6a8c1f0 100644 --- a/stream_chat_v1/lib/chat_info_screen.dart +++ b/stream_chat_v1/lib/chat_info_screen.dart @@ -245,12 +245,13 @@ class _ChatInfoScreenState extends State { if (channel.state == null) { await channel.watch(); } - Navigator.pushNamed( + Navigator.pushNamedAndRemoveUntil( context, Routes.CHANNEL_PAGE, + ModalRoute.withName(Routes.CHANNEL_LIST_PAGE), arguments: ChannelPageArgs( - channel: channel, - initialMessage: message, + channel: c, + initialMessage: m, ), ); }, diff --git a/stream_chat_v1/lib/group_chat_details_screen.dart b/stream_chat_v1/lib/group_chat_details_screen.dart index df40cc552f..7dec664420 100644 --- a/stream_chat_v1/lib/group_chat_details_screen.dart +++ b/stream_chat_v1/lib/group_chat_details_screen.dart @@ -144,7 +144,7 @@ class _GroupChatDetailsScreenState extends State { Navigator.pushNamedAndRemoveUntil( context, Routes.CHANNEL_PAGE, - ModalRoute.withName(Routes.HOME), + ModalRoute.withName(Routes.CHANNEL_LIST_PAGE), arguments: ChannelPageArgs(channel: channel), ); } catch (err) { diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/group_info_screen.dart index 6a06e1e1da..b51816352d 100644 --- a/stream_chat_v1/lib/group_info_screen.dart +++ b/stream_chat_v1/lib/group_info_screen.dart @@ -534,9 +534,10 @@ class _GroupInfoScreenState extends State { if (channel.state == null) { await channel.watch(); } - Navigator.pushNamed( + Navigator.pushNamedAndRemoveUntil( context, Routes.CHANNEL_PAGE, + ModalRoute.withName(Routes.CHANNEL_LIST_PAGE), arguments: ChannelPageArgs( channel: channel, initialMessage: message, From 5ad910318872cc63a801dcf771e567cd6728dd70 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 25 Jan 2022 15:29:22 +0100 Subject: [PATCH 105/172] remove role check --- .../ios/Runner.xcodeproj/project.pbxproj | 33 ++++++++++++------- .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- stream_chat_v1/lib/group_info_screen.dart | 15 +++------ 3 files changed, 27 insertions(+), 23 deletions(-) diff --git a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj index 3b333d08d5..fe295e0f84 100644 --- a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj +++ b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 50; objects = { /* Begin PBXBuildFile section */ @@ -177,7 +177,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 1140; - LastUpgradeCheck = 1020; + LastUpgradeCheck = 1300; ORGANIZATIONNAME = "The Chromium Authors"; TargetAttributes = { 97C146ED1CF9000F007C117D = { @@ -245,7 +245,7 @@ "${BUILT_PRODUCTS_DIR}/DKImagePickerController/DKImagePickerController.framework", "${BUILT_PRODUCTS_DIR}/DKPhotoGallery/DKPhotoGallery.framework", "${BUILT_PRODUCTS_DIR}/FMDB/FMDB.framework", - "${BUILT_PRODUCTS_DIR}/Reachability/Reachability.framework", + "${BUILT_PRODUCTS_DIR}/ReachabilitySwift/Reachability.framework", "${BUILT_PRODUCTS_DIR}/SDWebImage/SDWebImage.framework", "${BUILT_PRODUCTS_DIR}/SwiftyGif/SwiftyGif.framework", "${BUILT_PRODUCTS_DIR}/connectivity_plus/connectivity_plus.framework", @@ -256,14 +256,14 @@ "${BUILT_PRODUCTS_DIR}/image_gallery_saver/image_gallery_saver.framework", "${BUILT_PRODUCTS_DIR}/image_picker/image_picker.framework", "${BUILT_PRODUCTS_DIR}/libwebp/libwebp.framework", - "${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework", + "${BUILT_PRODUCTS_DIR}/path_provider_ios/path_provider_ios.framework", "${BUILT_PRODUCTS_DIR}/photo_manager/photo_manager.framework", "${BUILT_PRODUCTS_DIR}/share_plus/share_plus.framework", - "${BUILT_PRODUCTS_DIR}/shared_preferences/shared_preferences.framework", + "${BUILT_PRODUCTS_DIR}/shared_preferences_ios/shared_preferences_ios.framework", "${BUILT_PRODUCTS_DIR}/sqflite/sqflite.framework", "${BUILT_PRODUCTS_DIR}/sqlite3/sqlite3.framework", "${BUILT_PRODUCTS_DIR}/sqlite3_flutter_libs/sqlite3_flutter_libs.framework", - "${BUILT_PRODUCTS_DIR}/url_launcher/url_launcher.framework", + "${BUILT_PRODUCTS_DIR}/url_launcher_ios/url_launcher_ios.framework", "${BUILT_PRODUCTS_DIR}/video_compress/video_compress.framework", "${BUILT_PRODUCTS_DIR}/video_player/video_player.framework", "${BUILT_PRODUCTS_DIR}/video_thumbnail/video_thumbnail.framework", @@ -285,14 +285,14 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/image_gallery_saver.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/image_picker.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libwebp.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider_ios.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/photo_manager.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/share_plus.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences_ios.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqflite.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqlite3.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqlite3_flutter_libs.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher_ios.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_compress.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_player.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_thumbnail.framework", @@ -442,7 +442,10 @@ ); INFOPLIST_FILE = Runner/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 11.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", @@ -581,7 +584,10 @@ ); INFOPLIST_FILE = Runner/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 11.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", @@ -615,7 +621,10 @@ ); INFOPLIST_FILE = Runner/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 11.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", diff --git a/stream_chat_v1/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/stream_chat_v1/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index fb2dffc49b..c87d15a335 100644 --- a/stream_chat_v1/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/stream_chat_v1/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ { ); } - var userMember = snapshot.data!.firstWhereOrNull( - (e) => e.user!.id == StreamChat.of(context).currentUser!.id, - ); - var isOwner = userMember?.role == 'owner'; - return Scaffold( backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, appBar: AppBar( @@ -150,10 +145,8 @@ class _GroupInfoScreenState extends State { ), centerTitle: true, actions: [ - if (!channel.channel.isDistinct && - isOwner && - channel.channel.ownCapabilities - .contains(PermissionType.updateChannelMembers)) + if (channel.channel.ownCapabilities + .contains(PermissionType.updateChannelMembers)) StreamNeumorphicButton( child: InkWell( onTap: () { @@ -177,7 +170,9 @@ class _GroupInfoScreenState extends State { height: 8.0, color: StreamChatTheme.of(context).colorTheme.disabled, ), - if (isOwner) _buildNameTile(), + if (channel.channel.ownCapabilities + .contains(PermissionType.updateChannel)) + _buildNameTile(), _buildOptionListTiles(), ], ), From b021f747444646fcb39364eb55fac574f4f8a127 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 3 Feb 2022 17:19:48 +0100 Subject: [PATCH 106/172] update deps --- stream_chat_v1/lib/channel_list_page.dart | 10 +--------- stream_chat_v1/pubspec.yaml | 4 ++-- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/stream_chat_v1/lib/channel_list_page.dart b/stream_chat_v1/lib/channel_list_page.dart index d484307456..be43bd65f6 100644 --- a/stream_chat_v1/lib/channel_list_page.dart +++ b/stream_chat_v1/lib/channel_list_page.dart @@ -40,15 +40,7 @@ class _ChannelListPageState extends State { Positioned( top: -3, right: -16, - child: StreamBuilder( - stream: - StreamChat.of(context).client.state.unreadChannelsStream, - initialData: 0, - builder: - (BuildContext context, AsyncSnapshot snapshot) { - return Text(snapshot.data.toString()); - }, - ), + child: UnreadIndicator(), ), ], ), diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index 9043349871..67335498cc 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -26,8 +26,8 @@ dependencies: ref: develop path: packages/stream_chat_localizations flutter_local_notifications: ^9.0.0 - flutter_svg: ^0.23.0 - flutter_secure_storage: ^4.2.1 + flutter_svg: ^1.0.3 + flutter_secure_storage: ^5.0.2 yaml: ^3.1.0 uuid: ^3.0.5 streaming_shared_preferences: ^2.0.0 From 2660a09abf50a26197b90e795405d1f619a8d1b8 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 3 Feb 2022 17:47:57 +0100 Subject: [PATCH 107/172] update android compile sdk --- stream_chat_v1/android/app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stream_chat_v1/android/app/build.gradle b/stream_chat_v1/android/app/build.gradle index ce7eeeea5f..147d607fec 100644 --- a/stream_chat_v1/android/app/build.gradle +++ b/stream_chat_v1/android/app/build.gradle @@ -26,7 +26,7 @@ apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - compileSdkVersion 30 + compileSdkVersion 31 ndkVersion '21.4.7075529' sourceSets { From 82c738a49a27978d1c0d8f2777cb11b24df9136e Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Mon, 21 Mar 2022 16:12:28 +0530 Subject: [PATCH 108/172] feat(sample-app): Migrate sample app to v4 Signed-off-by: xsahil03x --- stream_chat_v1/android/app/build.gradle | 2 +- stream_chat_v1/lib/advanced_options_page.dart | 1 - .../lib/channel_file_display_screen.dart | 2 +- stream_chat_v1/lib/channel_list.dart | 193 +++++++++++++----- stream_chat_v1/lib/channel_list_page.dart | 12 +- .../lib/channel_media_display_screen.dart | 6 +- stream_chat_v1/lib/channel_page.dart | 11 +- stream_chat_v1/lib/chat_info_screen.dart | 30 +-- stream_chat_v1/lib/choose_user_page.dart | 2 +- .../lib/group_chat_details_screen.dart | 7 +- stream_chat_v1/lib/group_info_screen.dart | 19 +- stream_chat_v1/lib/home_page.dart | 1 - stream_chat_v1/lib/main.dart | 1 - stream_chat_v1/lib/new_chat_screen.dart | 12 +- stream_chat_v1/lib/new_group_chat_screen.dart | 8 +- .../lib/pinned_messages_screen.dart | 4 +- stream_chat_v1/lib/splash_screen.dart | 1 - stream_chat_v1/lib/thread_page.dart | 8 +- stream_chat_v1/lib/user_mentions_page.dart | 2 +- 19 files changed, 199 insertions(+), 123 deletions(-) diff --git a/stream_chat_v1/android/app/build.gradle b/stream_chat_v1/android/app/build.gradle index ce7eeeea5f..147d607fec 100644 --- a/stream_chat_v1/android/app/build.gradle +++ b/stream_chat_v1/android/app/build.gradle @@ -26,7 +26,7 @@ apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - compileSdkVersion 30 + compileSdkVersion 31 ndkVersion '21.4.7075529' sourceSets { diff --git a/stream_chat_v1/lib/advanced_options_page.dart b/stream_chat_v1/lib/advanced_options_page.dart index a42f2007f8..2645e19933 100644 --- a/stream_chat_v1/lib/advanced_options_page.dart +++ b/stream_chat_v1/lib/advanced_options_page.dart @@ -3,7 +3,6 @@ import 'package:example/localizations.dart'; import 'package:example/routes/routes.dart'; import 'package:example/stream_version.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; diff --git a/stream_chat_v1/lib/channel_file_display_screen.dart b/stream_chat_v1/lib/channel_file_display_screen.dart index 4f4a806ce8..743b3eb0ca 100644 --- a/stream_chat_v1/lib/channel_file_display_screen.dart +++ b/stream_chat_v1/lib/channel_file_display_screen.dart @@ -160,7 +160,7 @@ class _ChannelFileDisplayScreenState extends State { padding: const EdgeInsets.all(1.0), child: Padding( padding: const EdgeInsets.all(8.0), - child: FileAttachment( + child: StreamFileAttachment( message: media.values.toList()[position], attachment: media.keys.toList()[position], ), diff --git a/stream_chat_v1/lib/channel_list.dart b/stream_chat_v1/lib/channel_list.dart index d13e830fe8..25813f0682 100644 --- a/stream_chat_v1/lib/channel_list.dart +++ b/stream_chat_v1/lib/channel_list.dart @@ -6,6 +6,7 @@ import 'package:example/search_text_field.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; +import 'package:flutter_slidable/flutter_slidable.dart'; import 'channel_page.dart'; import 'chat_info_screen.dart'; @@ -39,6 +40,16 @@ class _ChannelList extends State { }); } + late final _channelListController = StreamChannelListController( + client: StreamChat.of(context).client, + filter: Filter.in_( + 'members', + [StreamChat.of(context).currentUser!.id], + ), + presence: true, + limit: 30, + ); + @override void initState() { super.initState(); @@ -86,7 +97,7 @@ class _ChannelList extends State { ), ], body: _isSearchActive - ? MessageSearchListView( + ? StreamMessageSearchListView( showErrorTile: true, messageQuery: _channelQuery, filters: Filter.in_('members', [user!.id]), @@ -149,59 +160,141 @@ class _ChannelList extends State { ); }, ) - : ChannelListView( - onChannelTap: (channel, _) { - Navigator.pushNamed( - context, - Routes.CHANNEL_PAGE, - arguments: ChannelPageArgs( - channel: channel, - ), - ); - }, - onStartChatPressed: () { - Navigator.pushNamed(context, Routes.NEW_CHAT); - }, - swipeToAction: true, - filter: Filter.in_('members', [user!.id]), - presence: true, - limit: 30, - onViewInfoTap: (channel) { - Navigator.pop(context); - if (channel.memberCount == 2 && channel.isDistinct) { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => StreamChannel( - channel: channel, - child: ChatInfoScreen( - messageTheme: - StreamChatTheme.of(context).ownMessageTheme, - user: channel.state!.members - .where((m) => - m.userId != - channel.client.state.currentUser!.id) - .first - .user, - ), + : SlidableAutoCloseBehavior( + closeWhenOpened: true, + child: RefreshIndicator( + onRefresh: _channelListController.refresh, + child: StreamChannelListView( + controller: _channelListController, + itemBuilder: (context, channel, tile) { + final chatTheme = StreamChatTheme.of(context); + final backgroundColor = chatTheme.colorTheme.inputBg; + final canDeleteChannel = channel.ownCapabilities + .contains(PermissionType.deleteChannel); + return Slidable( + groupTag: 'channels-actions', + endActionPane: ActionPane( + extentRatio: canDeleteChannel ? 0.40 : 0.20, + motion: const BehindMotion(), + children: [ + CustomSlidableAction( + child: Icon(Icons.more_horiz), + backgroundColor: backgroundColor, + onPressed: (_) { + showChannelInfoModalBottomSheet( + context: context, + channel: channel, + onViewInfoTap: () { + Navigator.pop(context); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) { + final isOneToOne = + channel.memberCount == 2 && + channel.isDistinct; + return StreamChannel( + channel: channel, + child: isOneToOne + ? ChatInfoScreen( + messageTheme: chatTheme + .ownMessageTheme, + user: channel + .state!.members + .where((m) => + m.userId != + channel + .client + .state + .currentUser! + .id) + .first + .user, + ) + : GroupInfoScreen( + messageTheme: chatTheme + .ownMessageTheme, + ), + ); + }, + ), + ); + }, + ); + }, + ), + if (canDeleteChannel) + CustomSlidableAction( + backgroundColor: backgroundColor, + child: StreamSvgIcon.delete( + color: chatTheme.colorTheme.accentError, + ), + onPressed: (_) async { + final res = await showConfirmationDialog( + context, + title: 'Delete Conversation', + question: + 'Are you sure you want to delete this conversation?', + okText: 'Delete', + cancelText: 'Cancel', + icon: StreamSvgIcon.delete( + color: chatTheme.colorTheme.accentError, + ), + ); + if (res == true) { + await _channelListController + .deleteChannel(channel); + } + }, + ), + ], ), - ), - ); - } else { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => StreamChannel( + child: tile, + ); + }, + onChannelTap: (channel) { + Navigator.pushNamed( + context, + Routes.CHANNEL_PAGE, + arguments: ChannelPageArgs( channel: channel, - child: GroupInfoScreen( - messageTheme: - StreamChatTheme.of(context).ownMessageTheme, + ), + ); + }, + emptyBuilder: (_) { + return Center( + child: Padding( + padding: EdgeInsets.all(8), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded(child: StreamChannelListEmptyWidget()), + TextButton( + onPressed: () { + Navigator.pushNamed( + context, + Routes.NEW_CHAT, + ); + }, + child: Text( + 'Start a chat', + style: StreamChatTheme.of(context) + .textTheme + .bodyBold + .copyWith( + color: StreamChatTheme.of(context) + .colorTheme + .accentPrimary, + ), + ), + ), + ], ), ), - ), - ); - } - }, + ); + }, + ), + ), ), ), ), diff --git a/stream_chat_v1/lib/channel_list_page.dart b/stream_chat_v1/lib/channel_list_page.dart index be43bd65f6..af45104f60 100644 --- a/stream_chat_v1/lib/channel_list_page.dart +++ b/stream_chat_v1/lib/channel_list_page.dart @@ -40,7 +40,7 @@ class _ChannelListPageState extends State { Positioned( top: -3, right: -16, - child: UnreadIndicator(), + child: StreamUnreadIndicator(), ), ], ), @@ -70,7 +70,7 @@ class _ChannelListPageState extends State { } return Scaffold( backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, - appBar: ChannelListHeader( + appBar: StreamChannelListHeader( onNewChatButtonTap: () { Navigator.pushNamed(context, Routes.NEW_CHAT); }, @@ -100,10 +100,8 @@ class _ChannelListPageState extends State { body: IndexedStack( index: _currentIndex, children: [ - ChannelsBloc( - child: MessageSearchBloc( - child: ChannelList(), - ), + MessageSearchBloc( + child: ChannelList(), ), UserMentionsPage(), ], @@ -165,7 +163,7 @@ class LeftDrawer extends StatelessWidget { ), child: Row( children: [ - UserAvatar( + StreamUserAvatar( user: user, showOnlineStatus: false, constraints: BoxConstraints.tight(Size.fromRadius(20)), diff --git a/stream_chat_v1/lib/channel_media_display_screen.dart b/stream_chat_v1/lib/channel_media_display_screen.dart index ee232935e2..5ccd92cdd2 100644 --- a/stream_chat_v1/lib/channel_media_display_screen.dart +++ b/stream_chat_v1/lib/channel_media_display_screen.dart @@ -21,7 +21,7 @@ class ChannelMediaDisplayScreen extends StatefulWidget { final ShowMessageCallback? onShowMessage; - final MessageThemeData messageTheme; + final StreamMessageThemeData messageTheme; const ChannelMediaDisplayScreen({ required this.messageTheme, @@ -180,7 +180,7 @@ class _ChannelMediaDisplayScreenState extends State { MaterialPageRoute( builder: (context) => StreamChannel( channel: channel, - child: FullScreenMedia( + child: StreamFullScreenMedia( mediaAttachments: media.map((e) => e.attachment).toList(), startIndex: position, @@ -194,7 +194,7 @@ class _ChannelMediaDisplayScreenState extends State { }, child: media[position].attachment.type == 'image' ? IgnorePointer( - child: ImageAttachment( + child: StreamImageAttachment( attachment: media[position].attachment, message: media[position].message, showTitle: false, diff --git a/stream_chat_v1/lib/channel_page.dart b/stream_chat_v1/lib/channel_page.dart index 19aa3a314c..6cf60e5a5d 100644 --- a/stream_chat_v1/lib/channel_page.dart +++ b/stream_chat_v1/lib/channel_page.dart @@ -60,7 +60,7 @@ class _ChannelPageState extends State { Widget build(BuildContext context) { return Scaffold( backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, - appBar: ChannelHeader( + appBar: StreamChannelHeader( showTypingIndicator: false, onImageTap: () async { var channel = StreamChannel.of(context).channel; @@ -108,7 +108,7 @@ class _ChannelPageState extends State { Expanded( child: Stack( children: [ - MessageListView( + StreamMessageListView( initialScrollIndex: widget.initialScrollIndex, initialAlignment: widget.initialAlignment, highlightInitialMessage: widget.highlightInitialMessage, @@ -137,7 +137,7 @@ class _ChannelPageState extends State { ); }, deletedBottomRowBuilder: (context, message) { - return const VisibleFootnote(); + return const StreamVisibleFootnote(); }, ); }, @@ -155,8 +155,7 @@ class _ChannelPageState extends State { .colorTheme .appBg .withOpacity(.9), - child: TypingIndicator( - alignment: Alignment.centerLeft, + child: StreamTypingIndicator( padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 4, @@ -174,7 +173,7 @@ class _ChannelPageState extends State { ], ), ), - MessageInput( + StreamMessageInput( focusNode: _focusNode, messageInputController: _messageInputController, ), diff --git a/stream_chat_v1/lib/chat_info_screen.dart b/stream_chat_v1/lib/chat_info_screen.dart index 2ba078912c..9556840c1c 100644 --- a/stream_chat_v1/lib/chat_info_screen.dart +++ b/stream_chat_v1/lib/chat_info_screen.dart @@ -1,8 +1,6 @@ -import 'package:collection/collection.dart' show IterableExtension; import 'package:example/localizations.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:jiffy/jiffy.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'channel_file_display_screen.dart'; @@ -16,7 +14,7 @@ class ChatInfoScreen extends StatefulWidget { /// User in consideration final User? user; - final MessageThemeData messageTheme; + final StreamMessageThemeData messageTheme; const ChatInfoScreen({ Key? key, @@ -54,13 +52,7 @@ class _ChatInfoScreenState extends State { height: 8.0, color: StreamChatTheme.of(context).colorTheme.disabled, ), - if ([ - 'admin', - 'owner', - ].contains(channel.state!.members - .firstWhereOrNull( - (m) => m.userId == channel.client.state.currentUser!.id) - ?.role)) + if (channel.ownCapabilities.contains(PermissionType.deleteChannel)) _buildDeleteListTile(), ], ), @@ -78,7 +70,7 @@ class _ChatInfoScreenState extends State { children: [ Padding( padding: const EdgeInsets.all(16.0), - child: UserAvatar( + child: StreamUserAvatar( user: widget.user!, constraints: BoxConstraints.tightFor( width: 72.0, @@ -95,7 +87,7 @@ class _ChatInfoScreenState extends State { SizedBox(height: 7.0), _buildConnectedTitleState(), SizedBox(height: 15.0), - OptionListTile( + StreamOptionListTile( title: '@${widget.user!.id}', tileColor: StreamChatTheme.of(context).colorTheme.appBg, trailing: Padding( @@ -148,7 +140,7 @@ class _ChatInfoScreenState extends State { builder: (context, snapshot) { mutedBool.value = snapshot.data; - return OptionListTile( + return StreamOptionListTile( tileColor: StreamChatTheme.of(context).colorTheme.appBg, title: AppLocalizations.of(context).muteUser, titleTextStyle: StreamChatTheme.of(context).textTheme.body, @@ -201,7 +193,7 @@ class _ChatInfoScreenState extends State { // ), // onTap: () {}, // ), - OptionListTile( + StreamOptionListTile( title: AppLocalizations.of(context).pinnedMessages, tileColor: StreamChatTheme.of(context).colorTheme.appBg, titleTextStyle: StreamChatTheme.of(context).textTheme.body, @@ -261,7 +253,7 @@ class _ChatInfoScreenState extends State { ); }, ), - OptionListTile( + StreamOptionListTile( title: AppLocalizations.of(context).photosAndVideos, tileColor: StreamChatTheme.of(context).colorTheme.appBg, titleTextStyle: StreamChatTheme.of(context).textTheme.body, @@ -321,7 +313,7 @@ class _ChatInfoScreenState extends State { ); }, ), - OptionListTile( + StreamOptionListTile( title: AppLocalizations.of(context).files, tileColor: StreamChatTheme.of(context).colorTheme.appBg, titleTextStyle: StreamChatTheme.of(context).textTheme.body, @@ -361,7 +353,7 @@ class _ChatInfoScreenState extends State { ); }, ), - OptionListTile( + StreamOptionListTile( title: AppLocalizations.of(context).sharedGroups, tileColor: StreamChatTheme.of(context).colorTheme.appBg, titleTextStyle: StreamChatTheme.of(context).textTheme.body, @@ -391,7 +383,7 @@ class _ChatInfoScreenState extends State { } Widget _buildDeleteListTile() { - return OptionListTile( + return StreamOptionListTile( title: 'Delete Conversation', tileColor: StreamChatTheme.of(context).colorTheme.appBg, titleTextStyle: StreamChatTheme.of(context).textTheme.body.copyWith( @@ -632,7 +624,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { children: [ Padding( padding: const EdgeInsets.all(8.0), - child: ChannelAvatar( + child: StreamChannelAvatar( channel: channel, constraints: BoxConstraints(maxWidth: 40.0, maxHeight: 40.0), diff --git a/stream_chat_v1/lib/choose_user_page.dart b/stream_chat_v1/lib/choose_user_page.dart index 7d3ce51667..611804c523 100644 --- a/stream_chat_v1/lib/choose_user_page.dart +++ b/stream_chat_v1/lib/choose_user_page.dart @@ -124,7 +124,7 @@ class ChooseUserPage extends StatelessWidget { arguments: HomePageArgs(client), ); }, - leading: UserAvatar( + leading: StreamUserAvatar( user: user, constraints: BoxConstraints.tight( Size.fromRadius(20), diff --git a/stream_chat_v1/lib/group_chat_details_screen.dart b/stream_chat_v1/lib/group_chat_details_screen.dart index df40cc552f..cd75681d71 100644 --- a/stream_chat_v1/lib/group_chat_details_screen.dart +++ b/stream_chat_v1/lib/group_chat_details_screen.dart @@ -1,7 +1,6 @@ import 'package:example/localizations.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -import 'package:uuid/uuid.dart'; import 'channel_page.dart'; import 'routes/routes.dart'; @@ -155,7 +154,7 @@ class _GroupChatDetailsScreenState extends State { ), ], ), - body: ConnectionStatusBuilder( + body: StreamConnectionStatusBuilder( statusBuilder: (context, status) { String statusString = ''; bool showStatus = true; @@ -172,7 +171,7 @@ class _GroupChatDetailsScreenState extends State { statusString = AppLocalizations.of(context).disconnected; break; } - return InfoTile( + return StreamInfoTile( showMessage: showStatus, tileAnchor: Alignment.topCenter, childAnchor: Alignment.topCenter, @@ -222,7 +221,7 @@ class _GroupChatDetailsScreenState extends State { final user = _selectedUsers[index]; return ListTile( key: ObjectKey(user), - leading: UserAvatar( + leading: StreamUserAvatar( user: user, constraints: BoxConstraints.tightFor( width: 40, diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/group_info_screen.dart index 9609249736..ba7091670b 100644 --- a/stream_chat_v1/lib/group_info_screen.dart +++ b/stream_chat_v1/lib/group_info_screen.dart @@ -4,7 +4,6 @@ import 'package:collection/collection.dart' show IterableExtension; import 'package:example/localizations.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:jiffy/jiffy.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'channel_file_display_screen.dart'; @@ -15,7 +14,7 @@ import 'pinned_messages_screen.dart'; import 'routes/routes.dart'; class GroupInfoScreen extends StatefulWidget { - final MessageThemeData messageTheme; + final StreamMessageThemeData messageTheme; const GroupInfoScreen({ Key? key, @@ -222,7 +221,7 @@ class _GroupInfoScreenState extends State { horizontal: 8.0, vertical: 12.0, ), - child: UserAvatar( + child: StreamUserAvatar( user: member.user!, constraints: BoxConstraints.tightFor( height: 40.0, @@ -456,7 +455,7 @@ class _GroupInfoScreenState extends State { builder: (context, snapshot) { mutedBool.value = snapshot.data; - return OptionListTile( + return StreamOptionListTile( tileColor: StreamChatTheme.of(context).colorTheme.appBg, separatorColor: StreamChatTheme.of(context).colorTheme.disabled, @@ -493,7 +492,7 @@ class _GroupInfoScreenState extends State { onTap: () {}, ); }), - OptionListTile( + StreamOptionListTile( title: AppLocalizations.of(context).pinnedMessages, tileColor: StreamChatTheme.of(context).colorTheme.appBg, titleTextStyle: StreamChatTheme.of(context).textTheme.body, @@ -553,7 +552,7 @@ class _GroupInfoScreenState extends State { ); }, ), - OptionListTile( + StreamOptionListTile( tileColor: StreamChatTheme.of(context).colorTheme.appBg, separatorColor: StreamChatTheme.of(context).colorTheme.disabled, title: AppLocalizations.of(context).photosAndVideos, @@ -615,7 +614,7 @@ class _GroupInfoScreenState extends State { ); }, ), - OptionListTile( + StreamOptionListTile( tileColor: StreamChatTheme.of(context).colorTheme.appBg, separatorColor: StreamChatTheme.of(context).colorTheme.disabled, title: AppLocalizations.of(context).files, @@ -660,7 +659,7 @@ class _GroupInfoScreenState extends State { if (!channel.channel.isDistinct && channel.channel.ownCapabilities .contains(PermissionType.leaveChannel)) - OptionListTile( + StreamOptionListTile( tileColor: StreamChatTheme.of(context).colorTheme.appBg, separatorColor: StreamChatTheme.of(context).colorTheme.disabled, title: AppLocalizations.of(context).leaveGroup, @@ -730,7 +729,7 @@ class _GroupInfoScreenState extends State { child: _buildTextInputSection(modalSetState), ), Expanded( - child: UserListView( + child: StreamUserListView( selectedUsers: {}, onUserTap: (user, _) async { _searchController!.clear(); @@ -900,7 +899,7 @@ class _GroupInfoScreenState extends State { Center( child: Padding( padding: const EdgeInsets.all(16.0), - child: UserAvatar( + child: StreamUserAvatar( user: user, constraints: BoxConstraints.tightFor( height: 64.0, diff --git a/stream_chat_v1/lib/home_page.dart b/stream_chat_v1/lib/home_page.dart index a53dd2c74c..e37b8622bc 100644 --- a/stream_chat_v1/lib/home_page.dart +++ b/stream_chat_v1/lib/home_page.dart @@ -4,7 +4,6 @@ import 'package:example/channel_page.dart'; import 'package:example/notifications_service.dart'; import 'package:example/routes/app_routes.dart'; import 'package:example/routes/routes.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; diff --git a/stream_chat_v1/lib/main.dart b/stream_chat_v1/lib/main.dart index fc4ed9b076..31717ca4f9 100644 --- a/stream_chat_v1/lib/main.dart +++ b/stream_chat_v1/lib/main.dart @@ -4,7 +4,6 @@ import 'package:example/choose_user_page.dart'; import 'package:example/home_page.dart'; import 'package:example/localizations.dart'; import 'package:example/splash_screen.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; diff --git a/stream_chat_v1/lib/new_chat_screen.dart b/stream_chat_v1/lib/new_chat_screen.dart index eb247c3ffe..ffd95541ba 100644 --- a/stream_chat_v1/lib/new_chat_screen.dart +++ b/stream_chat_v1/lib/new_chat_screen.dart @@ -130,7 +130,7 @@ class _NewChatScreenState extends State { ), centerTitle: true, ), - body: ConnectionStatusBuilder( + body: StreamConnectionStatusBuilder( statusBuilder: (context, status) { String statusString = ''; bool showStatus = true; @@ -147,7 +147,7 @@ class _NewChatScreenState extends State { statusString = AppLocalizations.of(context).disconnected; break; } - return InfoTile( + return StreamInfoTile( showMessage: showStatus, tileAnchor: Alignment.topCenter, childAnchor: Alignment.topCenter, @@ -200,7 +200,7 @@ class _NewChatScreenState extends State { .overlay, shape: BoxShape.circle, ), - child: UserAvatar( + child: StreamUserAvatar( showOnlineStatus: false, user: user, constraints: BoxConstraints.tightFor( @@ -288,7 +288,7 @@ class _NewChatScreenState extends State { behavior: HitTestBehavior.opaque, onPanDown: (_) => FocusScope.of(context).unfocus(), child: UsersBloc( - child: UserListView( + child: StreamUserListView( selectedUsers: _selectedUsers, groupAlphabetically: _isSearchActive ? false : true, @@ -366,7 +366,7 @@ class _NewChatScreenState extends State { future: channel!.initialized, builder: (context, snapshot) { if (snapshot.data == true) { - return MessageListView(); + return StreamMessageListView(); } return Center( @@ -384,7 +384,7 @@ class _NewChatScreenState extends State { }, ), ), - MessageInput( + StreamMessageInput( focusNode: _messageInputFocusNode, preMessageSending: (message) async { await channel!.watch(); diff --git a/stream_chat_v1/lib/new_group_chat_screen.dart b/stream_chat_v1/lib/new_group_chat_screen.dart index 2d0842ab24..a2a2ec5cae 100644 --- a/stream_chat_v1/lib/new_group_chat_screen.dart +++ b/stream_chat_v1/lib/new_group_chat_screen.dart @@ -88,7 +88,7 @@ class _NewGroupChatScreenState extends State { ) ], ), - body: ConnectionStatusBuilder( + body: StreamConnectionStatusBuilder( statusBuilder: (context, status) { String statusString = ''; bool showStatus = true; @@ -105,7 +105,7 @@ class _NewGroupChatScreenState extends State { statusString = AppLocalizations.of(context).disconnected; break; } - return InfoTile( + return StreamInfoTile( showMessage: showStatus, tileAnchor: Alignment.topCenter, childAnchor: Alignment.topCenter, @@ -136,7 +136,7 @@ class _NewGroupChatScreenState extends State { children: [ Stack( children: [ - UserAvatar( + StreamUserAvatar( onlineIndicatorAlignment: Alignment(0.9, 0.9), user: user, @@ -229,7 +229,7 @@ class _NewGroupChatScreenState extends State { behavior: HitTestBehavior.opaque, onPanDown: (_) => FocusScope.of(context).unfocus(), child: UsersBloc( - child: UserListView( + child: StreamUserListView( selectedUsers: _selectedUsers, pullToRefresh: false, groupAlphabetically: _isSearchActive ? false : true, diff --git a/stream_chat_v1/lib/pinned_messages_screen.dart b/stream_chat_v1/lib/pinned_messages_screen.dart index a3470bd31e..6c2eaec9a6 100644 --- a/stream_chat_v1/lib/pinned_messages_screen.dart +++ b/stream_chat_v1/lib/pinned_messages_screen.dart @@ -21,7 +21,7 @@ class PinnedMessagesScreen extends StatefulWidget { final ShowMessageCallback? onShowMessage; - final MessageThemeData messageTheme; + final StreamMessageThemeData messageTheme; const PinnedMessagesScreen({ required this.messageTheme, @@ -166,7 +166,7 @@ class _PinnedMessagesScreenState extends State { var text = data[position].message.text ?? ''; return ListTile( - leading: UserAvatar( + leading: StreamUserAvatar( user: user, constraints: BoxConstraints.tightFor( width: 40.0, diff --git a/stream_chat_v1/lib/splash_screen.dart b/stream_chat_v1/lib/splash_screen.dart index 2c8922898d..9e72572d76 100644 --- a/stream_chat_v1/lib/splash_screen.dart +++ b/stream_chat_v1/lib/splash_screen.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter/scheduler.dart'; import 'package:lottie/lottie.dart'; mixin SplashScreenStateMixin on State diff --git a/stream_chat_v1/lib/thread_page.dart b/stream_chat_v1/lib/thread_page.dart index f61130c9a0..6ffd5e3ac8 100644 --- a/stream_chat_v1/lib/thread_page.dart +++ b/stream_chat_v1/lib/thread_page.dart @@ -44,13 +44,13 @@ class _ThreadPageState extends State { Widget build(BuildContext context) { return Scaffold( backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, - appBar: ThreadHeader( + appBar: StreamThreadHeader( parent: widget.parent, ), body: Column( children: [ Expanded( - child: MessageListView( + child: StreamMessageListView( parentMessage: widget.parent, initialScrollIndex: widget.initialScrollIndex, initialAlignment: widget.initialAlignment, @@ -62,14 +62,14 @@ class _ThreadPageState extends State { return defaultMessage.copyWith( onReplyTap: _reply, deletedBottomRowBuilder: (context, message) { - return const VisibleFootnote(); + return const StreamVisibleFootnote(); }, ); }, ), ), if (widget.parent.type != 'deleted') - MessageInput( + StreamMessageInput( focusNode: _focusNode, messageInputController: _messageInputController, ), diff --git a/stream_chat_v1/lib/user_mentions_page.dart b/stream_chat_v1/lib/user_mentions_page.dart index fa2d834201..4d266a111c 100644 --- a/stream_chat_v1/lib/user_mentions_page.dart +++ b/stream_chat_v1/lib/user_mentions_page.dart @@ -10,7 +10,7 @@ class UserMentionsPage extends StatelessWidget { Widget build(BuildContext context) { final user = StreamChat.of(context).currentUser!; return MessageSearchBloc( - child: MessageSearchListView( + child: StreamMessageSearchListView( filters: Filter.in_('members', [user.id]), messageFilters: Filter.custom( operator: r'$contains', From 1ee7e0f95641069e29c56490e409a09cd6f9f0ce Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 22 Mar 2022 10:29:43 +0100 Subject: [PATCH 109/172] update deps --- .../ios/Runner.xcodeproj/project.pbxproj | 6 ++---- stream_chat_v1/pubspec.yaml | 14 +++++++------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj index fe295e0f84..925a6899d9 100644 --- a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj +++ b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj @@ -264,8 +264,7 @@ "${BUILT_PRODUCTS_DIR}/sqlite3/sqlite3.framework", "${BUILT_PRODUCTS_DIR}/sqlite3_flutter_libs/sqlite3_flutter_libs.framework", "${BUILT_PRODUCTS_DIR}/url_launcher_ios/url_launcher_ios.framework", - "${BUILT_PRODUCTS_DIR}/video_compress/video_compress.framework", - "${BUILT_PRODUCTS_DIR}/video_player/video_player.framework", + "${BUILT_PRODUCTS_DIR}/video_player_avfoundation/video_player_avfoundation.framework", "${BUILT_PRODUCTS_DIR}/video_thumbnail/video_thumbnail.framework", "${BUILT_PRODUCTS_DIR}/wakelock/wakelock.framework", ); @@ -293,8 +292,7 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqlite3.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqlite3_flutter_libs.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher_ios.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_compress.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_player.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_player_avfoundation.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_thumbnail.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/wakelock.framework", ); diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index d2190d05a3..ae257d6fc9 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -13,20 +13,20 @@ dependencies: stream_chat_flutter: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop + ref: v4 path: packages/stream_chat_flutter stream_chat_persistence: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop + ref: v4 path: packages/stream_chat_persistence stream_chat_localizations: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: feat/capabilities + ref: v4 path: packages/stream_chat_localizations flutter_local_notifications: ^9.0.0 - flutter_svg: ^0.23.0 + flutter_svg: ^1.0.1 flutter_secure_storage: ^4.2.1 yaml: ^3.1.0 uuid: ^3.0.5 @@ -42,17 +42,17 @@ dependency_overrides: stream_chat: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: feat/capabilities + ref: v4 path: packages/stream_chat stream_chat_flutter_core: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: feat/capabilities + ref: v4 path: packages/stream_chat_flutter_core stream_chat_flutter: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: feat/capabilities + ref: v4 path: packages/stream_chat_flutter flutter: From 7b457a28bd6bfd950bf7033917289d17be831535 Mon Sep 17 00:00:00 2001 From: Ayush Shekhar Date: Wed, 13 Apr 2022 18:46:39 +0530 Subject: [PATCH 110/172] Migrated most of the code from deprecated widgets to v4 widgets, and changed data being supplied for full screen implementation --- stream_chat_v1/android/app/build.gradle | 2 +- .../ios/Runner.xcodeproj/project.pbxproj | 6 ++---- stream_chat_v1/lib/advanced_options_page.dart | 1 - .../lib/channel_file_display_screen.dart | 2 +- stream_chat_v1/lib/channel_list.dart | 2 +- stream_chat_v1/lib/channel_list_page.dart | 6 +++--- .../lib/channel_media_display_screen.dart | 17 +++++++++------ stream_chat_v1/lib/channel_page.dart | 11 +++++----- stream_chat_v1/lib/chat_info_screen.dart | 21 +++++++++---------- stream_chat_v1/lib/choose_user_page.dart | 2 +- .../lib/group_chat_details_screen.dart | 7 +++---- stream_chat_v1/lib/group_info_screen.dart | 19 ++++++++--------- stream_chat_v1/lib/home_page.dart | 1 - stream_chat_v1/lib/main.dart | 1 - stream_chat_v1/lib/new_chat_screen.dart | 12 +++++------ stream_chat_v1/lib/new_group_chat_screen.dart | 8 +++---- .../lib/pinned_messages_screen.dart | 4 ++-- stream_chat_v1/lib/splash_screen.dart | 1 - stream_chat_v1/lib/thread_page.dart | 8 +++---- stream_chat_v1/lib/user_mentions_page.dart | 2 +- stream_chat_v1/pubspec.yaml | 8 +++---- 21 files changed, 68 insertions(+), 73 deletions(-) diff --git a/stream_chat_v1/android/app/build.gradle b/stream_chat_v1/android/app/build.gradle index ce7eeeea5f..147d607fec 100644 --- a/stream_chat_v1/android/app/build.gradle +++ b/stream_chat_v1/android/app/build.gradle @@ -26,7 +26,7 @@ apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - compileSdkVersion 30 + compileSdkVersion 31 ndkVersion '21.4.7075529' sourceSets { diff --git a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj index fe295e0f84..925a6899d9 100644 --- a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj +++ b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj @@ -264,8 +264,7 @@ "${BUILT_PRODUCTS_DIR}/sqlite3/sqlite3.framework", "${BUILT_PRODUCTS_DIR}/sqlite3_flutter_libs/sqlite3_flutter_libs.framework", "${BUILT_PRODUCTS_DIR}/url_launcher_ios/url_launcher_ios.framework", - "${BUILT_PRODUCTS_DIR}/video_compress/video_compress.framework", - "${BUILT_PRODUCTS_DIR}/video_player/video_player.framework", + "${BUILT_PRODUCTS_DIR}/video_player_avfoundation/video_player_avfoundation.framework", "${BUILT_PRODUCTS_DIR}/video_thumbnail/video_thumbnail.framework", "${BUILT_PRODUCTS_DIR}/wakelock/wakelock.framework", ); @@ -293,8 +292,7 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqlite3.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqlite3_flutter_libs.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher_ios.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_compress.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_player.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_player_avfoundation.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_thumbnail.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/wakelock.framework", ); diff --git a/stream_chat_v1/lib/advanced_options_page.dart b/stream_chat_v1/lib/advanced_options_page.dart index a42f2007f8..2645e19933 100644 --- a/stream_chat_v1/lib/advanced_options_page.dart +++ b/stream_chat_v1/lib/advanced_options_page.dart @@ -3,7 +3,6 @@ import 'package:example/localizations.dart'; import 'package:example/routes/routes.dart'; import 'package:example/stream_version.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; diff --git a/stream_chat_v1/lib/channel_file_display_screen.dart b/stream_chat_v1/lib/channel_file_display_screen.dart index 4f4a806ce8..743b3eb0ca 100644 --- a/stream_chat_v1/lib/channel_file_display_screen.dart +++ b/stream_chat_v1/lib/channel_file_display_screen.dart @@ -160,7 +160,7 @@ class _ChannelFileDisplayScreenState extends State { padding: const EdgeInsets.all(1.0), child: Padding( padding: const EdgeInsets.all(8.0), - child: FileAttachment( + child: StreamFileAttachment( message: media.values.toList()[position], attachment: media.keys.toList()[position], ), diff --git a/stream_chat_v1/lib/channel_list.dart b/stream_chat_v1/lib/channel_list.dart index d13e830fe8..3ebe2a5e6c 100644 --- a/stream_chat_v1/lib/channel_list.dart +++ b/stream_chat_v1/lib/channel_list.dart @@ -86,7 +86,7 @@ class _ChannelList extends State { ), ], body: _isSearchActive - ? MessageSearchListView( + ? StreamMessageSearchListView( showErrorTile: true, messageQuery: _channelQuery, filters: Filter.in_('members', [user!.id]), diff --git a/stream_chat_v1/lib/channel_list_page.dart b/stream_chat_v1/lib/channel_list_page.dart index be43bd65f6..f2f70eb2a9 100644 --- a/stream_chat_v1/lib/channel_list_page.dart +++ b/stream_chat_v1/lib/channel_list_page.dart @@ -40,7 +40,7 @@ class _ChannelListPageState extends State { Positioned( top: -3, right: -16, - child: UnreadIndicator(), + child: StreamUnreadIndicator(), ), ], ), @@ -70,7 +70,7 @@ class _ChannelListPageState extends State { } return Scaffold( backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, - appBar: ChannelListHeader( + appBar: StreamChannelListHeader( onNewChatButtonTap: () { Navigator.pushNamed(context, Routes.NEW_CHAT); }, @@ -165,7 +165,7 @@ class LeftDrawer extends StatelessWidget { ), child: Row( children: [ - UserAvatar( + StreamUserAvatar( user: user, showOnlineStatus: false, constraints: BoxConstraints.tight(Size.fromRadius(20)), diff --git a/stream_chat_v1/lib/channel_media_display_screen.dart b/stream_chat_v1/lib/channel_media_display_screen.dart index ee232935e2..0cfdde6bf3 100644 --- a/stream_chat_v1/lib/channel_media_display_screen.dart +++ b/stream_chat_v1/lib/channel_media_display_screen.dart @@ -21,7 +21,7 @@ class ChannelMediaDisplayScreen extends StatefulWidget { final ShowMessageCallback? onShowMessage; - final MessageThemeData messageTheme; + final StreamMessageThemeData messageTheme; const ChannelMediaDisplayScreen({ required this.messageTheme, @@ -180,11 +180,16 @@ class _ChannelMediaDisplayScreenState extends State { MaterialPageRoute( builder: (context) => StreamChannel( channel: channel, - child: FullScreenMedia( - mediaAttachments: - media.map((e) => e.attachment).toList(), + child: StreamFullScreenMedia( + mediaAttachmentPackages: media + .map( + (e) => StreamAttachmentPackage( + attachment: e.attachment, + message: e.message, + ), + ) + .toList(), startIndex: position, - message: media[position].message, userName: media[position].message.user!.name, onShowMessage: widget.onShowMessage, ), @@ -194,7 +199,7 @@ class _ChannelMediaDisplayScreenState extends State { }, child: media[position].attachment.type == 'image' ? IgnorePointer( - child: ImageAttachment( + child: StreamImageAttachment( attachment: media[position].attachment, message: media[position].message, showTitle: false, diff --git a/stream_chat_v1/lib/channel_page.dart b/stream_chat_v1/lib/channel_page.dart index 19aa3a314c..6cf60e5a5d 100644 --- a/stream_chat_v1/lib/channel_page.dart +++ b/stream_chat_v1/lib/channel_page.dart @@ -60,7 +60,7 @@ class _ChannelPageState extends State { Widget build(BuildContext context) { return Scaffold( backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, - appBar: ChannelHeader( + appBar: StreamChannelHeader( showTypingIndicator: false, onImageTap: () async { var channel = StreamChannel.of(context).channel; @@ -108,7 +108,7 @@ class _ChannelPageState extends State { Expanded( child: Stack( children: [ - MessageListView( + StreamMessageListView( initialScrollIndex: widget.initialScrollIndex, initialAlignment: widget.initialAlignment, highlightInitialMessage: widget.highlightInitialMessage, @@ -137,7 +137,7 @@ class _ChannelPageState extends State { ); }, deletedBottomRowBuilder: (context, message) { - return const VisibleFootnote(); + return const StreamVisibleFootnote(); }, ); }, @@ -155,8 +155,7 @@ class _ChannelPageState extends State { .colorTheme .appBg .withOpacity(.9), - child: TypingIndicator( - alignment: Alignment.centerLeft, + child: StreamTypingIndicator( padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 4, @@ -174,7 +173,7 @@ class _ChannelPageState extends State { ], ), ), - MessageInput( + StreamMessageInput( focusNode: _focusNode, messageInputController: _messageInputController, ), diff --git a/stream_chat_v1/lib/chat_info_screen.dart b/stream_chat_v1/lib/chat_info_screen.dart index 2ba078912c..297106e467 100644 --- a/stream_chat_v1/lib/chat_info_screen.dart +++ b/stream_chat_v1/lib/chat_info_screen.dart @@ -2,7 +2,6 @@ import 'package:collection/collection.dart' show IterableExtension; import 'package:example/localizations.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:jiffy/jiffy.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'channel_file_display_screen.dart'; @@ -16,7 +15,7 @@ class ChatInfoScreen extends StatefulWidget { /// User in consideration final User? user; - final MessageThemeData messageTheme; + final StreamMessageThemeData messageTheme; const ChatInfoScreen({ Key? key, @@ -78,7 +77,7 @@ class _ChatInfoScreenState extends State { children: [ Padding( padding: const EdgeInsets.all(16.0), - child: UserAvatar( + child: StreamUserAvatar( user: widget.user!, constraints: BoxConstraints.tightFor( width: 72.0, @@ -95,7 +94,7 @@ class _ChatInfoScreenState extends State { SizedBox(height: 7.0), _buildConnectedTitleState(), SizedBox(height: 15.0), - OptionListTile( + StreamOptionListTile( title: '@${widget.user!.id}', tileColor: StreamChatTheme.of(context).colorTheme.appBg, trailing: Padding( @@ -148,7 +147,7 @@ class _ChatInfoScreenState extends State { builder: (context, snapshot) { mutedBool.value = snapshot.data; - return OptionListTile( + return StreamOptionListTile( tileColor: StreamChatTheme.of(context).colorTheme.appBg, title: AppLocalizations.of(context).muteUser, titleTextStyle: StreamChatTheme.of(context).textTheme.body, @@ -201,7 +200,7 @@ class _ChatInfoScreenState extends State { // ), // onTap: () {}, // ), - OptionListTile( + StreamOptionListTile( title: AppLocalizations.of(context).pinnedMessages, tileColor: StreamChatTheme.of(context).colorTheme.appBg, titleTextStyle: StreamChatTheme.of(context).textTheme.body, @@ -261,7 +260,7 @@ class _ChatInfoScreenState extends State { ); }, ), - OptionListTile( + StreamOptionListTile( title: AppLocalizations.of(context).photosAndVideos, tileColor: StreamChatTheme.of(context).colorTheme.appBg, titleTextStyle: StreamChatTheme.of(context).textTheme.body, @@ -321,7 +320,7 @@ class _ChatInfoScreenState extends State { ); }, ), - OptionListTile( + StreamOptionListTile( title: AppLocalizations.of(context).files, tileColor: StreamChatTheme.of(context).colorTheme.appBg, titleTextStyle: StreamChatTheme.of(context).textTheme.body, @@ -361,7 +360,7 @@ class _ChatInfoScreenState extends State { ); }, ), - OptionListTile( + StreamOptionListTile( title: AppLocalizations.of(context).sharedGroups, tileColor: StreamChatTheme.of(context).colorTheme.appBg, titleTextStyle: StreamChatTheme.of(context).textTheme.body, @@ -391,7 +390,7 @@ class _ChatInfoScreenState extends State { } Widget _buildDeleteListTile() { - return OptionListTile( + return StreamOptionListTile( title: 'Delete Conversation', tileColor: StreamChatTheme.of(context).colorTheme.appBg, titleTextStyle: StreamChatTheme.of(context).textTheme.body.copyWith( @@ -632,7 +631,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { children: [ Padding( padding: const EdgeInsets.all(8.0), - child: ChannelAvatar( + child: StreamChannelAvatar( channel: channel, constraints: BoxConstraints(maxWidth: 40.0, maxHeight: 40.0), diff --git a/stream_chat_v1/lib/choose_user_page.dart b/stream_chat_v1/lib/choose_user_page.dart index 7d3ce51667..611804c523 100644 --- a/stream_chat_v1/lib/choose_user_page.dart +++ b/stream_chat_v1/lib/choose_user_page.dart @@ -124,7 +124,7 @@ class ChooseUserPage extends StatelessWidget { arguments: HomePageArgs(client), ); }, - leading: UserAvatar( + leading: StreamUserAvatar( user: user, constraints: BoxConstraints.tight( Size.fromRadius(20), diff --git a/stream_chat_v1/lib/group_chat_details_screen.dart b/stream_chat_v1/lib/group_chat_details_screen.dart index df40cc552f..cd75681d71 100644 --- a/stream_chat_v1/lib/group_chat_details_screen.dart +++ b/stream_chat_v1/lib/group_chat_details_screen.dart @@ -1,7 +1,6 @@ import 'package:example/localizations.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -import 'package:uuid/uuid.dart'; import 'channel_page.dart'; import 'routes/routes.dart'; @@ -155,7 +154,7 @@ class _GroupChatDetailsScreenState extends State { ), ], ), - body: ConnectionStatusBuilder( + body: StreamConnectionStatusBuilder( statusBuilder: (context, status) { String statusString = ''; bool showStatus = true; @@ -172,7 +171,7 @@ class _GroupChatDetailsScreenState extends State { statusString = AppLocalizations.of(context).disconnected; break; } - return InfoTile( + return StreamInfoTile( showMessage: showStatus, tileAnchor: Alignment.topCenter, childAnchor: Alignment.topCenter, @@ -222,7 +221,7 @@ class _GroupChatDetailsScreenState extends State { final user = _selectedUsers[index]; return ListTile( key: ObjectKey(user), - leading: UserAvatar( + leading: StreamUserAvatar( user: user, constraints: BoxConstraints.tightFor( width: 40, diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/group_info_screen.dart index 9609249736..ba7091670b 100644 --- a/stream_chat_v1/lib/group_info_screen.dart +++ b/stream_chat_v1/lib/group_info_screen.dart @@ -4,7 +4,6 @@ import 'package:collection/collection.dart' show IterableExtension; import 'package:example/localizations.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:jiffy/jiffy.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'channel_file_display_screen.dart'; @@ -15,7 +14,7 @@ import 'pinned_messages_screen.dart'; import 'routes/routes.dart'; class GroupInfoScreen extends StatefulWidget { - final MessageThemeData messageTheme; + final StreamMessageThemeData messageTheme; const GroupInfoScreen({ Key? key, @@ -222,7 +221,7 @@ class _GroupInfoScreenState extends State { horizontal: 8.0, vertical: 12.0, ), - child: UserAvatar( + child: StreamUserAvatar( user: member.user!, constraints: BoxConstraints.tightFor( height: 40.0, @@ -456,7 +455,7 @@ class _GroupInfoScreenState extends State { builder: (context, snapshot) { mutedBool.value = snapshot.data; - return OptionListTile( + return StreamOptionListTile( tileColor: StreamChatTheme.of(context).colorTheme.appBg, separatorColor: StreamChatTheme.of(context).colorTheme.disabled, @@ -493,7 +492,7 @@ class _GroupInfoScreenState extends State { onTap: () {}, ); }), - OptionListTile( + StreamOptionListTile( title: AppLocalizations.of(context).pinnedMessages, tileColor: StreamChatTheme.of(context).colorTheme.appBg, titleTextStyle: StreamChatTheme.of(context).textTheme.body, @@ -553,7 +552,7 @@ class _GroupInfoScreenState extends State { ); }, ), - OptionListTile( + StreamOptionListTile( tileColor: StreamChatTheme.of(context).colorTheme.appBg, separatorColor: StreamChatTheme.of(context).colorTheme.disabled, title: AppLocalizations.of(context).photosAndVideos, @@ -615,7 +614,7 @@ class _GroupInfoScreenState extends State { ); }, ), - OptionListTile( + StreamOptionListTile( tileColor: StreamChatTheme.of(context).colorTheme.appBg, separatorColor: StreamChatTheme.of(context).colorTheme.disabled, title: AppLocalizations.of(context).files, @@ -660,7 +659,7 @@ class _GroupInfoScreenState extends State { if (!channel.channel.isDistinct && channel.channel.ownCapabilities .contains(PermissionType.leaveChannel)) - OptionListTile( + StreamOptionListTile( tileColor: StreamChatTheme.of(context).colorTheme.appBg, separatorColor: StreamChatTheme.of(context).colorTheme.disabled, title: AppLocalizations.of(context).leaveGroup, @@ -730,7 +729,7 @@ class _GroupInfoScreenState extends State { child: _buildTextInputSection(modalSetState), ), Expanded( - child: UserListView( + child: StreamUserListView( selectedUsers: {}, onUserTap: (user, _) async { _searchController!.clear(); @@ -900,7 +899,7 @@ class _GroupInfoScreenState extends State { Center( child: Padding( padding: const EdgeInsets.all(16.0), - child: UserAvatar( + child: StreamUserAvatar( user: user, constraints: BoxConstraints.tightFor( height: 64.0, diff --git a/stream_chat_v1/lib/home_page.dart b/stream_chat_v1/lib/home_page.dart index a53dd2c74c..e37b8622bc 100644 --- a/stream_chat_v1/lib/home_page.dart +++ b/stream_chat_v1/lib/home_page.dart @@ -4,7 +4,6 @@ import 'package:example/channel_page.dart'; import 'package:example/notifications_service.dart'; import 'package:example/routes/app_routes.dart'; import 'package:example/routes/routes.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; diff --git a/stream_chat_v1/lib/main.dart b/stream_chat_v1/lib/main.dart index fc4ed9b076..31717ca4f9 100644 --- a/stream_chat_v1/lib/main.dart +++ b/stream_chat_v1/lib/main.dart @@ -4,7 +4,6 @@ import 'package:example/choose_user_page.dart'; import 'package:example/home_page.dart'; import 'package:example/localizations.dart'; import 'package:example/splash_screen.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; diff --git a/stream_chat_v1/lib/new_chat_screen.dart b/stream_chat_v1/lib/new_chat_screen.dart index eb247c3ffe..ffd95541ba 100644 --- a/stream_chat_v1/lib/new_chat_screen.dart +++ b/stream_chat_v1/lib/new_chat_screen.dart @@ -130,7 +130,7 @@ class _NewChatScreenState extends State { ), centerTitle: true, ), - body: ConnectionStatusBuilder( + body: StreamConnectionStatusBuilder( statusBuilder: (context, status) { String statusString = ''; bool showStatus = true; @@ -147,7 +147,7 @@ class _NewChatScreenState extends State { statusString = AppLocalizations.of(context).disconnected; break; } - return InfoTile( + return StreamInfoTile( showMessage: showStatus, tileAnchor: Alignment.topCenter, childAnchor: Alignment.topCenter, @@ -200,7 +200,7 @@ class _NewChatScreenState extends State { .overlay, shape: BoxShape.circle, ), - child: UserAvatar( + child: StreamUserAvatar( showOnlineStatus: false, user: user, constraints: BoxConstraints.tightFor( @@ -288,7 +288,7 @@ class _NewChatScreenState extends State { behavior: HitTestBehavior.opaque, onPanDown: (_) => FocusScope.of(context).unfocus(), child: UsersBloc( - child: UserListView( + child: StreamUserListView( selectedUsers: _selectedUsers, groupAlphabetically: _isSearchActive ? false : true, @@ -366,7 +366,7 @@ class _NewChatScreenState extends State { future: channel!.initialized, builder: (context, snapshot) { if (snapshot.data == true) { - return MessageListView(); + return StreamMessageListView(); } return Center( @@ -384,7 +384,7 @@ class _NewChatScreenState extends State { }, ), ), - MessageInput( + StreamMessageInput( focusNode: _messageInputFocusNode, preMessageSending: (message) async { await channel!.watch(); diff --git a/stream_chat_v1/lib/new_group_chat_screen.dart b/stream_chat_v1/lib/new_group_chat_screen.dart index 2d0842ab24..a2a2ec5cae 100644 --- a/stream_chat_v1/lib/new_group_chat_screen.dart +++ b/stream_chat_v1/lib/new_group_chat_screen.dart @@ -88,7 +88,7 @@ class _NewGroupChatScreenState extends State { ) ], ), - body: ConnectionStatusBuilder( + body: StreamConnectionStatusBuilder( statusBuilder: (context, status) { String statusString = ''; bool showStatus = true; @@ -105,7 +105,7 @@ class _NewGroupChatScreenState extends State { statusString = AppLocalizations.of(context).disconnected; break; } - return InfoTile( + return StreamInfoTile( showMessage: showStatus, tileAnchor: Alignment.topCenter, childAnchor: Alignment.topCenter, @@ -136,7 +136,7 @@ class _NewGroupChatScreenState extends State { children: [ Stack( children: [ - UserAvatar( + StreamUserAvatar( onlineIndicatorAlignment: Alignment(0.9, 0.9), user: user, @@ -229,7 +229,7 @@ class _NewGroupChatScreenState extends State { behavior: HitTestBehavior.opaque, onPanDown: (_) => FocusScope.of(context).unfocus(), child: UsersBloc( - child: UserListView( + child: StreamUserListView( selectedUsers: _selectedUsers, pullToRefresh: false, groupAlphabetically: _isSearchActive ? false : true, diff --git a/stream_chat_v1/lib/pinned_messages_screen.dart b/stream_chat_v1/lib/pinned_messages_screen.dart index a3470bd31e..6c2eaec9a6 100644 --- a/stream_chat_v1/lib/pinned_messages_screen.dart +++ b/stream_chat_v1/lib/pinned_messages_screen.dart @@ -21,7 +21,7 @@ class PinnedMessagesScreen extends StatefulWidget { final ShowMessageCallback? onShowMessage; - final MessageThemeData messageTheme; + final StreamMessageThemeData messageTheme; const PinnedMessagesScreen({ required this.messageTheme, @@ -166,7 +166,7 @@ class _PinnedMessagesScreenState extends State { var text = data[position].message.text ?? ''; return ListTile( - leading: UserAvatar( + leading: StreamUserAvatar( user: user, constraints: BoxConstraints.tightFor( width: 40.0, diff --git a/stream_chat_v1/lib/splash_screen.dart b/stream_chat_v1/lib/splash_screen.dart index 2c8922898d..9e72572d76 100644 --- a/stream_chat_v1/lib/splash_screen.dart +++ b/stream_chat_v1/lib/splash_screen.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter/scheduler.dart'; import 'package:lottie/lottie.dart'; mixin SplashScreenStateMixin on State diff --git a/stream_chat_v1/lib/thread_page.dart b/stream_chat_v1/lib/thread_page.dart index f61130c9a0..6ffd5e3ac8 100644 --- a/stream_chat_v1/lib/thread_page.dart +++ b/stream_chat_v1/lib/thread_page.dart @@ -44,13 +44,13 @@ class _ThreadPageState extends State { Widget build(BuildContext context) { return Scaffold( backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, - appBar: ThreadHeader( + appBar: StreamThreadHeader( parent: widget.parent, ), body: Column( children: [ Expanded( - child: MessageListView( + child: StreamMessageListView( parentMessage: widget.parent, initialScrollIndex: widget.initialScrollIndex, initialAlignment: widget.initialAlignment, @@ -62,14 +62,14 @@ class _ThreadPageState extends State { return defaultMessage.copyWith( onReplyTap: _reply, deletedBottomRowBuilder: (context, message) { - return const VisibleFootnote(); + return const StreamVisibleFootnote(); }, ); }, ), ), if (widget.parent.type != 'deleted') - MessageInput( + StreamMessageInput( focusNode: _focusNode, messageInputController: _messageInputController, ), diff --git a/stream_chat_v1/lib/user_mentions_page.dart b/stream_chat_v1/lib/user_mentions_page.dart index fa2d834201..4d266a111c 100644 --- a/stream_chat_v1/lib/user_mentions_page.dart +++ b/stream_chat_v1/lib/user_mentions_page.dart @@ -10,7 +10,7 @@ class UserMentionsPage extends StatelessWidget { Widget build(BuildContext context) { final user = StreamChat.of(context).currentUser!; return MessageSearchBloc( - child: MessageSearchListView( + child: StreamMessageSearchListView( filters: Filter.in_('members', [user.id]), messageFilters: Filter.custom( operator: r'$contains', diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index d2190d05a3..d730fa3997 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -26,7 +26,7 @@ dependencies: ref: feat/capabilities path: packages/stream_chat_localizations flutter_local_notifications: ^9.0.0 - flutter_svg: ^0.23.0 + flutter_svg: flutter_secure_storage: ^4.2.1 yaml: ^3.1.0 uuid: ^3.0.5 @@ -42,17 +42,17 @@ dependency_overrides: stream_chat: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: feat/capabilities + ref: 5587622587e1fb31e1935d4209189db0434ef09b path: packages/stream_chat stream_chat_flutter_core: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: feat/capabilities + ref: 5587622587e1fb31e1935d4209189db0434ef09b path: packages/stream_chat_flutter_core stream_chat_flutter: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: feat/capabilities + ref: 5587622587e1fb31e1935d4209189db0434ef09b path: packages/stream_chat_flutter flutter: From d0b1154fcf12e256981056f64fd2cacf17636f16 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Wed, 20 Apr 2022 11:08:27 +0200 Subject: [PATCH 111/172] bump version --- stream_chat_v1/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index 67335498cc..1585c6b34e 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -1,7 +1,7 @@ name: example description: A new Flutter project. publish_to: 'none' -version: 1.7.1 +version: 1.8.1 environment: sdk: '>=2.12.0 <3.0.0' From 885205c0ded233848f3654dfcad2c1d4b9654a64 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Fri, 22 Apr 2022 16:21:33 +0530 Subject: [PATCH 112/172] feat(sample-app): add sentry Signed-off-by: xsahil03x --- stream_chat_v1/android/app/build.gradle | 2 +- stream_chat_v1/lib/advanced_options_page.dart | 5 +- stream_chat_v1/lib/main.dart | 67 +++++++++++++++++-- stream_chat_v1/pubspec.yaml | 6 +- 4 files changed, 64 insertions(+), 16 deletions(-) diff --git a/stream_chat_v1/android/app/build.gradle b/stream_chat_v1/android/app/build.gradle index 147d607fec..189df9753a 100644 --- a/stream_chat_v1/android/app/build.gradle +++ b/stream_chat_v1/android/app/build.gradle @@ -40,7 +40,7 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.example.example" - minSdkVersion 21 + minSdkVersion 22 targetSdkVersion 30 versionCode flutterVersionCode.toInteger() versionName flutterVersionName diff --git a/stream_chat_v1/lib/advanced_options_page.dart b/stream_chat_v1/lib/advanced_options_page.dart index a42f2007f8..facb9a04fb 100644 --- a/stream_chat_v1/lib/advanced_options_page.dart +++ b/stream_chat_v1/lib/advanced_options_page.dart @@ -294,10 +294,7 @@ class _AdvancedOptionsPageState extends State { ), ); - final client = StreamChatClient( - apiKey, - logLevel: Level.INFO, - )..chatPersistenceClient = chatPersistentClient; + final client = buildStreamChatClient(apiKey); try { await client.connectUser( diff --git a/stream_chat_v1/lib/main.dart b/stream_chat_v1/lib/main.dart index fc4ed9b076..3acb1a99a0 100644 --- a/stream_chat_v1/lib/main.dart +++ b/stream_chat_v1/lib/main.dart @@ -4,17 +4,16 @@ import 'package:example/choose_user_page.dart'; import 'package:example/home_page.dart'; import 'package:example/localizations.dart'; import 'package:example/splash_screen.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:stream_chat_localizations/stream_chat_localizations.dart'; import 'package:stream_chat_persistence/stream_chat_persistence.dart'; import 'package:streaming_shared_preferences/streaming_shared_preferences.dart'; -import 'app_config.dart'; import 'routes/app_routes.dart'; import 'routes/routes.dart'; @@ -23,8 +22,65 @@ final chatPersistentClient = StreamChatPersistenceClient( connectionMode: ConnectionMode.regular, ); +void sampleAppLogHandler(LogRecord record) async { + if (kDebugMode) StreamChatClient.defaultLogHandler(record); + + // report errors to sentry + if (record.error != null || record.stackTrace != null) { + await Sentry.captureException( + record.error, + stackTrace: record.stackTrace, + ); + } +} + +StreamChatClient buildStreamChatClient( + String apiKey, { + Level logLevel = Level.SEVERE, +}) { + return StreamChatClient( + apiKey, + logLevel: logLevel, + logHandlerFunction: sampleAppLogHandler, + )..chatPersistenceClient = chatPersistentClient; +} + void main() async { - runApp(MyApp()); + const sentryDsn = + 'https://6381ef88de4140db8f5e25ab37e0f08c@o1213503.ingest.sentry.io/6352870'; + + /// Captures errors reported by the Flutter framework. + FlutterError.onError = (FlutterErrorDetails details) { + if (kDebugMode) { + // In development mode, simply print to console. + FlutterError.dumpErrorToConsole(details); + } else { + // In production mode, report to the application zone to report to sentry. + Zone.current.handleUncaughtError(details.exception, details.stack!); + } + }; + + Future _reportError(dynamic error, StackTrace stackTrace) async { + // Print the exception to the console. + if (kDebugMode) { + // Print the full stacktrace in debug mode. + print(stackTrace); + return; + } else { + // Send the Exception and Stacktrace to sentry in Production mode. + await Sentry.captureException(error, stackTrace: stackTrace); + } + } + + runZonedGuarded( + () async { + await SentryFlutter.init( + (options) => options.dsn = sentryDsn, + ); + runApp(MyApp()); + }, + _reportError, + ); } class MyApp extends StatefulWidget { @@ -46,10 +102,7 @@ class _MyAppState extends State token = await secureStorage.read(key: kStreamToken); } - final client = StreamChatClient( - apiKey ?? kDefaultStreamApiKey, - logLevel: Level.SEVERE, - )..chatPersistenceClient = chatPersistentClient; + final client = buildStreamChatClient(apiKey ?? kStreamApiKey); if (userId != null && token != null) { await client.connectUser( diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index 1585c6b34e..6f9ccbc59f 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -33,6 +33,7 @@ dependencies: streaming_shared_preferences: ^2.0.0 lottie: ^1.2.1 collection: ^1.15.0 + sentry_flutter: ^6.5.0 dev_dependencies: flutter_launcher_icons: ^0.9.2 @@ -40,10 +41,7 @@ dev_dependencies: dependency_overrides: stream_chat: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop - path: packages/stream_chat + path: ../../../stream-chat-flutter/packages/stream_chat stream_chat_flutter_core: git: url: https://github.com/GetStream/stream-chat-flutter.git From 87722daaf8371747f2270f9d6774b82f9b38ee56 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Fri, 22 Apr 2022 17:23:11 +0530 Subject: [PATCH 113/172] chore(sample-app): revert stream-chat dependency to git Signed-off-by: xsahil03x --- stream_chat_v1/pubspec.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index 6f9ccbc59f..96af0ca7f6 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -41,7 +41,10 @@ dev_dependencies: dependency_overrides: stream_chat: - path: ../../../stream-chat-flutter/packages/stream_chat + git: + url: https://github.com/GetStream/stream-chat-flutter.git + ref: develop + path: packages/stream_chat stream_chat_flutter_core: git: url: https://github.com/GetStream/stream-chat-flutter.git From 0a430101f3334700d22b1f78c14d838417a93b3c Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 28 Apr 2022 14:53:00 +0200 Subject: [PATCH 114/172] update lists --- .../ios/Runner.xcodeproj/project.pbxproj | 2 + stream_chat_v1/lib/channel_list.dart | 86 ++++++---- stream_chat_v1/lib/group_info_screen.dart | 136 +++++++-------- stream_chat_v1/lib/new_chat_screen.dart | 53 ++++-- stream_chat_v1/lib/new_group_chat_screen.dart | 146 ++++++++-------- stream_chat_v1/lib/user_mentions_page.dart | 157 +++++++++--------- 6 files changed, 317 insertions(+), 263 deletions(-) diff --git a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj index 925a6899d9..5b28f5387d 100644 --- a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj +++ b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj @@ -264,6 +264,7 @@ "${BUILT_PRODUCTS_DIR}/sqlite3/sqlite3.framework", "${BUILT_PRODUCTS_DIR}/sqlite3_flutter_libs/sqlite3_flutter_libs.framework", "${BUILT_PRODUCTS_DIR}/url_launcher_ios/url_launcher_ios.framework", + "${BUILT_PRODUCTS_DIR}/video_compress/video_compress.framework", "${BUILT_PRODUCTS_DIR}/video_player_avfoundation/video_player_avfoundation.framework", "${BUILT_PRODUCTS_DIR}/video_thumbnail/video_thumbnail.framework", "${BUILT_PRODUCTS_DIR}/wakelock/wakelock.framework", @@ -292,6 +293,7 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqlite3.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqlite3_flutter_libs.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher_ios.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_compress.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_player_avfoundation.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_thumbnail.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/wakelock.framework", diff --git a/stream_chat_v1/lib/channel_list.dart b/stream_chat_v1/lib/channel_list.dart index 25813f0682..5c8164e354 100644 --- a/stream_chat_v1/lib/channel_list.dart +++ b/stream_chat_v1/lib/channel_list.dart @@ -20,9 +20,21 @@ class ChannelList extends StatefulWidget { class _ChannelList extends State { ScrollController _scrollController = ScrollController(); - TextEditingController? _controller; + late StreamMessageSearchListController _messageSearchListController = + StreamMessageSearchListController( + client: StreamChat.of(context).client, + filter: Filter.in_('members', [StreamChat.of(context).currentUser!.id]), + limit: 5, + searchQuery: '', + sort: [ + SortOption( + 'created_at', + direction: SortOption.ASC, + ), + ], + ); - String _channelQuery = ''; + TextEditingController? _controller; bool _isSearchActive = false; @@ -32,10 +44,11 @@ class _ChannelList extends State { if (_debounce?.isActive ?? false) _debounce!.cancel(); _debounce = Timer(const Duration(milliseconds: 350), () { if (mounted) { + _messageSearchListController.searchQuery = _controller!.text; setState(() { - _channelQuery = _controller!.text; - _isSearchActive = _channelQuery.isNotEmpty; + _isSearchActive = _controller!.text.isNotEmpty; }); + if (_isSearchActive) _messageSearchListController.doInitialLoad(); } }); } @@ -61,12 +74,12 @@ class _ChannelList extends State { _controller?.removeListener(_channelQueryListener); _controller?.dispose(); _scrollController.dispose(); + _channelListController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { - final user = StreamChat.of(context).currentUser; return WillPopScope( onWillPop: () async { if (_isSearchActive) { @@ -98,17 +111,7 @@ class _ChannelList extends State { ], body: _isSearchActive ? StreamMessageSearchListView( - showErrorTile: true, - messageQuery: _channelQuery, - filters: Filter.in_('members', [user!.id]), - sortOptions: [ - SortOption( - 'created_at', - direction: SortOption.ASC, - ), - ], - pullToRefresh: false, - limit: 30, + controller: _messageSearchListController, emptyBuilder: (_) { return LayoutBuilder( builder: (context, viewportConstraints) { @@ -139,24 +142,34 @@ class _ChannelList extends State { }, ); }, - onItemTap: (messageResponse) async { - FocusScope.of(context).requestFocus(FocusNode()); - final client = StreamChat.of(context).client; - final message = messageResponse.message; - final channel = client.channel( - messageResponse.channel!.type, - id: messageResponse.channel!.id, - ); - if (channel.state == null) { - await channel.watch(); - } - Navigator.pushNamed( - context, - Routes.CHANNEL_PAGE, - arguments: ChannelPageArgs( - channel: channel, - initialMessage: message, - ), + itemBuilder: ( + context, + messageResponses, + index, + defaultWidget, + ) { + return defaultWidget.copyWith( + onTap: () async { + final messageResponse = messageResponses[index]; + FocusScope.of(context).requestFocus(FocusNode()); + final client = StreamChat.of(context).client; + final message = messageResponse.message; + final channel = client.channel( + messageResponse.channel!.type, + id: messageResponse.channel!.id, + ); + if (channel.state == null) { + await channel.watch(); + } + Navigator.pushNamed( + context, + Routes.CHANNEL_PAGE, + arguments: ChannelPageArgs( + channel: channel, + initialMessage: message, + ), + ); + }, ); }, ) @@ -166,9 +179,10 @@ class _ChannelList extends State { onRefresh: _channelListController.refresh, child: StreamChannelListView( controller: _channelListController, - itemBuilder: (context, channel, tile) { + itemBuilder: (context, channels, index, defaultWidget) { final chatTheme = StreamChatTheme.of(context); final backgroundColor = chatTheme.colorTheme.inputBg; + final channel = channels[index]; final canDeleteChannel = channel.ownCapabilities .contains(PermissionType.deleteChannel); return Slidable( @@ -249,7 +263,7 @@ class _ChannelList extends State { ), ], ), - child: tile, + child: defaultWidget, ); }, onChannelTap: (channel) { diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/group_info_screen.dart index ba7091670b..e650b07ac4 100644 --- a/stream_chat_v1/lib/group_info_screen.dart +++ b/stream_chat_v1/lib/group_info_screen.dart @@ -704,6 +704,28 @@ class _GroupInfoScreenState extends State { void _buildAddUserModal(context) { var channel = StreamChannel.of(context).channel; + final userListController = StreamUserListController( + client: channel.client, + limit: 25, + filter: Filter.and( + [ + if (_searchController!.text.isNotEmpty) + Filter.autoComplete('name', _userNameQuery), + Filter.notIn('id', [ + StreamChat.of(context).currentUser!.id, + ...channel.state!.members + .map(((e) => e.userId)) + .whereType(), + ]), + ], + ), + sort: [ + SortOption( + 'name', + direction: 1, + ), + ], + ); showDialog( useRootNavigator: false, @@ -721,85 +743,63 @@ class _GroupInfoScreenState extends State { ), clipBehavior: Clip.antiAlias, child: Scaffold( - body: UsersBloc( - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(16), - child: _buildTextInputSection(modalSetState), - ), - Expanded( - child: StreamUserListView( - selectedUsers: {}, - onUserTap: (user, _) async { - _searchController!.clear(); + body: Column( + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: _buildTextInputSection(modalSetState), + ), + Expanded( + child: StreamUserListView( + controller: userListController, + onUserTap: (user) async { + _searchController!.clear(); - await channel.addMembers([user.id]); - Navigator.pop(context); - setState(() {}); - }, - crossAxisCount: 4, - limit: 25, - filter: Filter.and( - [ - if (_searchController!.text.isNotEmpty) - Filter.autoComplete('name', _userNameQuery), - Filter.notIn('id', [ - StreamChat.of(context).currentUser!.id, - ...channel.state!.members - .map(((e) => e.userId)) - .whereType(), - ]), - ], - ), - sort: [ - SortOption( - 'name', - direction: 1, - ), - ], - emptyBuilder: (_) { - return LayoutBuilder( - builder: (context, viewportConstraints) { - return SingleChildScrollView( - physics: AlwaysScrollableScrollPhysics(), - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: viewportConstraints.maxHeight, - ), - child: Center( - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(24), - child: StreamSvgIcon.search( - size: 96, - color: StreamChatTheme.of(context) - .colorTheme - .textLowEmphasis, - ), + await channel.addMembers([user.id]); + Navigator.pop(context); + setState(() {}); + }, + emptyBuilder: (_) { + return LayoutBuilder( + builder: (context, viewportConstraints) { + return SingleChildScrollView( + physics: AlwaysScrollableScrollPhysics(), + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: viewportConstraints.maxHeight, + ), + child: Center( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(24), + child: StreamSvgIcon.search( + size: 96, + color: StreamChatTheme.of(context) + .colorTheme + .textLowEmphasis, ), - Text(AppLocalizations.of(context) - .noUserMatchesTheseKeywords), - ], - ), + ), + Text(AppLocalizations.of(context) + .noUserMatchesTheseKeywords), + ], ), ), - ); - }, - ); - }, - ), + ), + ); + }, + ); + }, ), - ], - ), + ), + ], ), ), ), ); }); }, - ); + ).then((_) => userListController.dispose()); } Widget _buildTextInputSection(modalSetState) { diff --git a/stream_chat_v1/lib/new_chat_screen.dart b/stream_chat_v1/lib/new_chat_screen.dart index ffd95541ba..1d57d29a52 100644 --- a/stream_chat_v1/lib/new_chat_screen.dart +++ b/stream_chat_v1/lib/new_chat_screen.dart @@ -19,6 +19,20 @@ class _NewChatScreenState extends State { late TextEditingController _controller; + late final userListController = StreamUserListController( + client: StreamChat.of(context).client, + limit: 25, + filter: Filter.and([ + Filter.notEqual('id', StreamChat.of(context).currentUser!.id), + ]), + sort: [ + SortOption( + 'name', + direction: 1, + ), + ], + ); + ChipInputTextFieldState? get _chipInputTextFieldState => _chipInputTextFieldStateKey.currentState; @@ -45,6 +59,12 @@ class _NewChatScreenState extends State { _userNameQuery = _controller.text; _isSearchActive = _userNameQuery.isNotEmpty; }); + userListController.filter = Filter.and([ + if (_userNameQuery.isNotEmpty) + Filter.autoComplete('name', _userNameQuery), + Filter.notEqual('id', StreamChat.of(context).currentUser!.id), + ]); + userListController.doInitialLoad(); }); } @@ -112,6 +132,7 @@ class _NewChatScreenState extends State { _controller.clear(); _controller.removeListener(_userNameListener); _controller.dispose(); + userListController.dispose(); super.dispose(); } @@ -289,10 +310,10 @@ class _NewChatScreenState extends State { onPanDown: (_) => FocusScope.of(context).unfocus(), child: UsersBloc( child: StreamUserListView( - selectedUsers: _selectedUsers, - groupAlphabetically: - _isSearchActive ? false : true, - onUserTap: (user, _) { + controller: userListController, + // groupAlphabetically: + // _isSearchActive ? false : true, + onUserTap: (user) { _controller.clear(); if (!_selectedUsers.contains(user)) { _chipInputTextFieldState @@ -302,19 +323,17 @@ class _NewChatScreenState extends State { _chipInputTextFieldState!.removeItem(user); } }, - limit: 25, - filter: Filter.and([ - if (_userNameQuery.isNotEmpty) - Filter.autoComplete('name', _userNameQuery), - Filter.notEqual('id', - StreamChat.of(context).currentUser!.id), - ]), - sort: [ - SortOption( - 'name', - direction: 1, - ), - ], + itemBuilder: ( + context, + users, + index, + defaultWidget, + ) { + return defaultWidget.copyWith( + selected: + _selectedUsers.contains(users[index]), + ); + }, emptyBuilder: (_) { return LayoutBuilder( builder: (context, viewportConstraints) { diff --git a/stream_chat_v1/lib/new_group_chat_screen.dart b/stream_chat_v1/lib/new_group_chat_screen.dart index a2a2ec5cae..ff0c175782 100644 --- a/stream_chat_v1/lib/new_group_chat_screen.dart +++ b/stream_chat_v1/lib/new_group_chat_screen.dart @@ -23,6 +23,20 @@ class _NewGroupChatScreenState extends State { Timer? _debounce; + late final userListController = StreamUserListController( + client: StreamChat.of(context).client, + sort: [ + SortOption( + 'name', + direction: 1, + ), + ], + limit: 25, + filter: Filter.and([ + Filter.notEqual('id', StreamChat.of(context).currentUser!.id), + ]), + ); + void _userNameListener() { if (_debounce?.isActive ?? false) _debounce!.cancel(); _debounce = Timer(const Duration(milliseconds: 350), () { @@ -31,6 +45,12 @@ class _NewGroupChatScreenState extends State { _userNameQuery = _controller!.text; _isSearchActive = _userNameQuery.isNotEmpty; }); + userListController.filter = Filter.and([ + if (_userNameQuery.isNotEmpty) + Filter.autoComplete('name', _userNameQuery), + Filter.notEqual('id', StreamChat.of(context).currentUser!.id), + ]); + userListController.doInitialLoad(); } }); } @@ -46,6 +66,7 @@ class _NewGroupChatScreenState extends State { _controller?.clear(); _controller?.removeListener(_userNameListener); _controller?.dispose(); + userListController.dispose(); super.dispose(); } @@ -228,77 +249,66 @@ class _NewGroupChatScreenState extends State { body: GestureDetector( behavior: HitTestBehavior.opaque, onPanDown: (_) => FocusScope.of(context).unfocus(), - child: UsersBloc( - child: StreamUserListView( - selectedUsers: _selectedUsers, - pullToRefresh: false, - groupAlphabetically: _isSearchActive ? false : true, - onUserTap: (user, _) { - if (!_selectedUsers.contains(user)) { - setState(() { - _selectedUsers.add(user); - }); - } else { - setState(() { - _selectedUsers.remove(user); - }); - } - }, - limit: 25, - filter: Filter.and([ - if (_userNameQuery.isNotEmpty) - Filter.autoComplete('name', _userNameQuery), - Filter.notEqual( - 'id', StreamChat.of(context).currentUser!.id), - ]), - sort: [ - SortOption( - 'name', - direction: 1, - ), - ], - emptyBuilder: (_) { - return LayoutBuilder( - builder: (context, viewportConstraints) { - return SingleChildScrollView( - physics: AlwaysScrollableScrollPhysics(), - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: viewportConstraints.maxHeight, - ), - child: Center( - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(24), - child: StreamSvgIcon.search( - size: 96, - color: StreamChatTheme.of(context) - .colorTheme - .textLowEmphasis, - ), - ), - Text( - AppLocalizations.of(context) - .noUserMatchesTheseKeywords, - style: StreamChatTheme.of(context) - .textTheme - .footnote - .copyWith( - color: StreamChatTheme.of(context) - .colorTheme - .textLowEmphasis, - ), + child: StreamUserListView( + controller: userListController, + // groupAlphabetically: _isSearchActive ? false : true, + itemBuilder: (context, items, index, defaultWidget) { + return defaultWidget.copyWith( + selected: _selectedUsers.contains(items[index]), + ); + }, + onUserTap: (user) { + if (!_selectedUsers.contains(user)) { + setState(() { + _selectedUsers.add(user); + }); + } else { + setState(() { + _selectedUsers.remove(user); + }); + } + }, + emptyBuilder: (_) { + return LayoutBuilder( + builder: (context, viewportConstraints) { + return SingleChildScrollView( + physics: AlwaysScrollableScrollPhysics(), + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: viewportConstraints.maxHeight, + ), + child: Center( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(24), + child: StreamSvgIcon.search( + size: 96, + color: StreamChatTheme.of(context) + .colorTheme + .textLowEmphasis, ), - ], - ), + ), + Text( + AppLocalizations.of(context) + .noUserMatchesTheseKeywords, + style: StreamChatTheme.of(context) + .textTheme + .footnote + .copyWith( + color: StreamChatTheme.of(context) + .colorTheme + .textLowEmphasis, + ), + ), + ], ), ), - ); - }, - ); - }, - ), + ), + ); + }, + ); + }, ), ), ), diff --git a/stream_chat_v1/lib/user_mentions_page.dart b/stream_chat_v1/lib/user_mentions_page.dart index 4d266a111c..3dcbab6498 100644 --- a/stream_chat_v1/lib/user_mentions_page.dart +++ b/stream_chat_v1/lib/user_mentions_page.dart @@ -5,85 +5,94 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'channel_page.dart'; -class UserMentionsPage extends StatelessWidget { +class UserMentionsPage extends StatefulWidget { + @override + State createState() => _UserMentionsPageState(); +} + +class _UserMentionsPageState extends State { + late final controller = StreamMessageSearchListController( + client: StreamChat.of(context).client, + filter: Filter.in_('members', [StreamChat.of(context).currentUser!.id]), + messageFilter: Filter.custom( + operator: r'$contains', + key: 'mentioned_users.id', + value: StreamChat.of(context).currentUser!.id, + ), + sort: [ + SortOption( + 'created_at', + direction: SortOption.ASC, + ), + ], + limit: 20, + ); @override Widget build(BuildContext context) { - final user = StreamChat.of(context).currentUser!; - return MessageSearchBloc( - child: StreamMessageSearchListView( - filters: Filter.in_('members', [user.id]), - messageFilters: Filter.custom( - operator: r'$contains', - key: 'mentioned_users.id', - value: user.id, - ), - sortOptions: [ - SortOption( - 'created_at', - direction: SortOption.ASC, - ), - ], - limit: 20, - showResultCount: false, - emptyBuilder: (_) { - return LayoutBuilder( - builder: (context, viewportConstraints) { - return SingleChildScrollView( - physics: AlwaysScrollableScrollPhysics(), - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: viewportConstraints.maxHeight, - ), - child: Center( - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(24), - child: StreamSvgIcon.mentions( - size: 96, - color: - StreamChatTheme.of(context).colorTheme.disabled, - ), - ), - Text( - AppLocalizations.of(context).noMentionsExistYet, - style: StreamChatTheme.of(context) - .textTheme - .body - .copyWith( - color: StreamChatTheme.of(context) - .colorTheme - .textLowEmphasis, - ), + return StreamMessageSearchListView( + controller: controller, + emptyBuilder: (_) { + return LayoutBuilder( + builder: (context, viewportConstraints) { + return SingleChildScrollView( + physics: AlwaysScrollableScrollPhysics(), + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: viewportConstraints.maxHeight, + ), + child: Center( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(24), + child: StreamSvgIcon.mentions( + size: 96, + color: + StreamChatTheme.of(context).colorTheme.disabled, ), - ], - ), + ), + Text( + AppLocalizations.of(context).noMentionsExistYet, + style: + StreamChatTheme.of(context).textTheme.body.copyWith( + color: StreamChatTheme.of(context) + .colorTheme + .textLowEmphasis, + ), + ), + ], ), ), - ); - }, - ); - }, - onItemTap: (messageResponse) async { - final client = StreamChat.of(context).client; - final message = messageResponse.message; - final channel = client.channel( - messageResponse.channel!.type, - id: messageResponse.channel!.id, - ); - if (channel.state == null) { - await channel.watch(); - } - Navigator.pushNamed( - context, - Routes.CHANNEL_PAGE, - arguments: ChannelPageArgs( - channel: channel, - initialMessage: message, - ), - ); - }, - ), + ), + ); + }, + ); + }, + onMessageTap: (messageResponse) async { + final client = StreamChat.of(context).client; + final message = messageResponse.message; + final channel = client.channel( + messageResponse.channel!.type, + id: messageResponse.channel!.id, + ); + if (channel.state == null) { + await channel.watch(); + } + Navigator.pushNamed( + context, + Routes.CHANNEL_PAGE, + arguments: ChannelPageArgs( + channel: channel, + initialMessage: message, + ), + ); + }, ); } + + @override + void dispose() { + controller.dispose(); + super.dispose(); + } } From 02fe35c20ffdba1c4f5316adb376ded94b7e441c Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 28 Apr 2022 14:53:29 +0200 Subject: [PATCH 115/172] update lists --- stream_chat_v1/lib/new_chat_screen.dart | 133 ++++++++++++------------ 1 file changed, 65 insertions(+), 68 deletions(-) diff --git a/stream_chat_v1/lib/new_chat_screen.dart b/stream_chat_v1/lib/new_chat_screen.dart index 1d57d29a52..f0ce09815e 100644 --- a/stream_chat_v1/lib/new_chat_screen.dart +++ b/stream_chat_v1/lib/new_chat_screen.dart @@ -308,77 +308,74 @@ class _NewChatScreenState extends State { ? GestureDetector( behavior: HitTestBehavior.opaque, onPanDown: (_) => FocusScope.of(context).unfocus(), - child: UsersBloc( - child: StreamUserListView( - controller: userListController, - // groupAlphabetically: - // _isSearchActive ? false : true, - onUserTap: (user) { - _controller.clear(); - if (!_selectedUsers.contains(user)) { - _chipInputTextFieldState - ?..addItem(user) - ..pauseItemAddition(); - } else { - _chipInputTextFieldState!.removeItem(user); - } - }, - itemBuilder: ( - context, - users, - index, - defaultWidget, - ) { - return defaultWidget.copyWith( - selected: - _selectedUsers.contains(users[index]), - ); - }, - emptyBuilder: (_) { - return LayoutBuilder( - builder: (context, viewportConstraints) { - return SingleChildScrollView( - physics: - AlwaysScrollableScrollPhysics(), - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: - viewportConstraints.maxHeight, - ), - child: Center( - child: Column( - children: [ - Padding( - padding: - const EdgeInsets.all(24), - child: StreamSvgIcon.search( - size: 96, - color: Colors.grey, - ), - ), - Text( - AppLocalizations.of(context) - .noUserMatchesTheseKeywords, - style: StreamChatTheme.of( - context) - .textTheme - .footnote - .copyWith( - color: StreamChatTheme - .of(context) - .colorTheme - .textHighEmphasis - .withOpacity(.5)), + child: StreamUserListView( + controller: userListController, + // groupAlphabetically: + // _isSearchActive ? false : true, + onUserTap: (user) { + _controller.clear(); + if (!_selectedUsers.contains(user)) { + _chipInputTextFieldState + ?..addItem(user) + ..pauseItemAddition(); + } else { + _chipInputTextFieldState!.removeItem(user); + } + }, + itemBuilder: ( + context, + users, + index, + defaultWidget, + ) { + return defaultWidget.copyWith( + selected: + _selectedUsers.contains(users[index]), + ); + }, + emptyBuilder: (_) { + return LayoutBuilder( + builder: (context, viewportConstraints) { + return SingleChildScrollView( + physics: AlwaysScrollableScrollPhysics(), + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: + viewportConstraints.maxHeight, + ), + child: Center( + child: Column( + children: [ + Padding( + padding: + const EdgeInsets.all(24), + child: StreamSvgIcon.search( + size: 96, + color: Colors.grey, ), - ], - ), + ), + Text( + AppLocalizations.of(context) + .noUserMatchesTheseKeywords, + style: StreamChatTheme.of( + context) + .textTheme + .footnote + .copyWith( + color: StreamChatTheme + .of(context) + .colorTheme + .textHighEmphasis + .withOpacity(.5)), + ), + ], ), ), - ); - }, - ); - }, - ), + ), + ); + }, + ); + }, ), ) : FutureBuilder( From 2f95ff4f46f0eb969208c5ec4e09afdef278c5a3 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 29 Apr 2022 15:24:35 +0200 Subject: [PATCH 116/172] align with v4 --- .../lib/channel_file_display_screen.dart | 260 ++++++------- stream_chat_v1/lib/channel_list.dart | 50 +-- stream_chat_v1/lib/channel_list_page.dart | 4 +- .../lib/channel_media_display_screen.dart | 351 +++++++++--------- stream_chat_v1/lib/channel_page.dart | 2 +- stream_chat_v1/lib/chat_info_screen.dart | 73 +--- stream_chat_v1/lib/group_info_screen.dart | 309 +++++++-------- .../lib/pinned_messages_screen.dart | 173 +++------ stream_chat_v1/lib/thread_page.dart | 5 +- 9 files changed, 500 insertions(+), 727 deletions(-) diff --git a/stream_chat_v1/lib/channel_file_display_screen.dart b/stream_chat_v1/lib/channel_file_display_screen.dart index 743b3eb0ca..8806f97fd2 100644 --- a/stream_chat_v1/lib/channel_file_display_screen.dart +++ b/stream_chat_v1/lib/channel_file_display_screen.dart @@ -1,52 +1,45 @@ import 'package:example/localizations.dart'; +import 'package:example/routes/routes.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; +import 'package:video_player/video_player.dart'; -class ChannelFileDisplayScreen extends StatefulWidget { - /// The sorting used for the channels matching the filters. - /// Sorting is based on field and direction, multiple sorting options can be provided. - /// You can sort based on last_updated, last_message_at, updated_at, created_at or member_count. - /// Direction can be ascending or descending. - final List? sortOptions; - - /// Pagination parameters - /// limit: the number of users to return (max is 30) - /// offset: the offset (max is 1000) - /// message_limit: how many messages should be included to each channel - final PaginationParams paginationParams; +import 'channel_page.dart'; - /// The builder used when the file list is empty. - final WidgetBuilder? emptyBuilder; +class ChannelFileDisplayScreen extends StatefulWidget { + final StreamMessageThemeData messageTheme; const ChannelFileDisplayScreen({ - this.sortOptions, - this.paginationParams = const PaginationParams(limit: 20), - this.emptyBuilder, - }); + Key? key, + required this.messageTheme, + }) : super(key: key); @override - _ChannelFileDisplayScreenState createState() => + State createState() => _ChannelFileDisplayScreenState(); } class _ChannelFileDisplayScreenState extends State { - @override - void initState() { - super.initState(); - final messageSearchBloc = MessageSearchBloc.of(context); - messageSearchBloc.search( - filter: Filter.in_( - 'cid', - [StreamChannel.of(context).channel.cid!], - ), - messageFilter: Filter.in_( - 'attachments.type', - ['file'], + final Map controllerCache = {}; + + late final controller = StreamMessageSearchListController( + client: StreamChat.of(context).client, + filter: Filter.in_( + 'cid', + [StreamChannel.of(context).channel.cid!], + ), + messageFilter: Filter.in_( + 'attachments.type', + ['file'], + ), + sort: [ + SortOption( + 'created_at', + direction: SortOption.ASC, ), - sort: widget.sortOptions, - pagination: widget.paginationParams, - ); - } + ], + limit: 20, + ); @override Widget build(BuildContext context) { @@ -58,120 +51,109 @@ class _ChannelFileDisplayScreenState extends State { title: Text( AppLocalizations.of(context).files, style: TextStyle( - color: StreamChatTheme.of(context).colorTheme.textHighEmphasis, - fontSize: 16.0), - ), - leading: Center( - child: InkWell( - onTap: () { - Navigator.of(context).pop(); - }, - child: Container( - width: 24.0, - height: 24.0, - child: StreamSvgIcon.left( - color: StreamChatTheme.of(context).colorTheme.textHighEmphasis, - size: 24.0, - ), - ), + color: StreamChatTheme.of(context).colorTheme.textHighEmphasis, + fontSize: 16.0, ), ), + leading: StreamBackButton(), backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, ), - body: _buildMediaGrid(), - ); - } - - Widget _buildMediaGrid() { - final messageSearchBloc = MessageSearchBloc.of(context); - - return StreamBuilder>( - builder: (context, snapshot) { - if (snapshot.data == null) { - return Center( - child: const CircularProgressIndicator(), - ); - } - - if (snapshot.data!.isEmpty) { - if (widget.emptyBuilder != null) { - return widget.emptyBuilder!(context); - } - return Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - StreamSvgIcon.files( - size: 136.0, - color: StreamChatTheme.of(context).colorTheme.disabled, - ), - SizedBox(height: 16.0), - Text( - AppLocalizations.of(context).noFiles, - style: TextStyle( - fontSize: 14.0, - color: - StreamChatTheme.of(context).colorTheme.textHighEmphasis, - ), - ), - SizedBox(height: 8.0), - Text( - AppLocalizations.of(context).filesAppearHere, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 14.0, - color: StreamChatTheme.of(context) - .colorTheme - .textHighEmphasis - .withOpacity(0.5), + body: ValueListenableBuilder( + valueListenable: controller, + builder: ( + BuildContext context, + PagedValue value, + Widget? child, + ) { + return value.when( + (items, nextPageKey, error) { + if (items.isEmpty) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + StreamSvgIcon.files( + size: 136.0, + color: StreamChatTheme.of(context).colorTheme.disabled, + ), + SizedBox(height: 16.0), + Text( + AppLocalizations.of(context).noFiles, + style: TextStyle( + fontSize: 14.0, + color: StreamChatTheme.of(context) + .colorTheme + .textHighEmphasis, + ), + ), + SizedBox(height: 8.0), + Text( + AppLocalizations.of(context).filesAppearHere, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 14.0, + color: StreamChatTheme.of(context) + .colorTheme + .textHighEmphasis + .withOpacity(0.5), + ), + ), + ], ), - ), - ], - ), - ); - } + ); + } + final media = {}; - final media = {}; + for (var item in items) { + item.message.attachments + .where((e) => e.type == 'file') + .forEach((e) { + media[e] = item.message; + }); + } - for (var item in snapshot.data!) { - item.message.attachments.where((e) => e.type == 'file').forEach((e) { - media[e] = item.message; - }); - } - - return LazyLoadScrollView( - onEndOfPage: () => messageSearchBloc.search( - filter: Filter.in_( - 'cid', - [StreamChannel.of(context).channel.cid!], - ), - messageFilter: Filter.in_( - 'attachments.type', - ['file'], - ), - sort: widget.sortOptions, - pagination: widget.paginationParams.copyWith( - offset: messageSearchBloc.messageResponses?.length ?? 0, - ), - ), - child: ListView.builder( - itemBuilder: (context, position) { - return Padding( - padding: const EdgeInsets.all(1.0), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: StreamFileAttachment( - message: media.values.toList()[position], - attachment: media.keys.toList()[position], - ), + return LazyLoadScrollView( + onEndOfPage: () async { + if (nextPageKey != null) { + controller.loadMore(nextPageKey); + } + }, + child: ListView.builder( + itemBuilder: (context, position) { + return Padding( + padding: const EdgeInsets.all(1.0), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: StreamFileAttachment( + message: media.values.toList()[position], + attachment: media.keys.toList()[position], + ), + ), + ); + }, + itemCount: media.length, ), ); }, - itemCount: media.length, - ), - ); - }, - stream: messageSearchBloc.messagesStream, + loading: () => Center( + child: const CircularProgressIndicator(), + ), + error: (_) => Offstage(), + ); + }, + ), ); } + + @override + void dispose() { + controller.dispose(); + super.dispose(); + } + + @override + void initState() { + controller.doInitialLoad(); + super.initState(); + } } diff --git a/stream_chat_v1/lib/channel_list.dart b/stream_chat_v1/lib/channel_list.dart index 5c8164e354..dcc1e913d2 100644 --- a/stream_chat_v1/lib/channel_list.dart +++ b/stream_chat_v1/lib/channel_list.dart @@ -278,31 +278,33 @@ class _ChannelList extends State { emptyBuilder: (_) { return Center( child: Padding( - padding: EdgeInsets.all(8), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded(child: StreamChannelListEmptyWidget()), - TextButton( - onPressed: () { - Navigator.pushNamed( - context, - Routes.NEW_CHAT, - ); - }, - child: Text( - 'Start a chat', - style: StreamChatTheme.of(context) - .textTheme - .bodyBold - .copyWith( - color: StreamChatTheme.of(context) - .colorTheme - .accentPrimary, - ), - ), + padding: const EdgeInsets.all(8), + child: StreamScrollViewEmptyWidget( + emptyIcon: StreamSvgIcon.message( + size: 148, + color: StreamChatTheme.of(context) + .colorTheme + .disabled, + ), + emptyTitle: TextButton( + onPressed: () { + Navigator.pushNamed( + context, + Routes.NEW_CHAT, + ); + }, + child: Text( + 'Start a chat', + style: StreamChatTheme.of(context) + .textTheme + .bodyBold + .copyWith( + color: StreamChatTheme.of(context) + .colorTheme + .accentPrimary, + ), ), - ], + ), ), ), ); diff --git a/stream_chat_v1/lib/channel_list_page.dart b/stream_chat_v1/lib/channel_list_page.dart index af45104f60..6a9438f409 100644 --- a/stream_chat_v1/lib/channel_list_page.dart +++ b/stream_chat_v1/lib/channel_list_page.dart @@ -100,9 +100,7 @@ class _ChannelListPageState extends State { body: IndexedStack( index: _currentIndex, children: [ - MessageSearchBloc( - child: ChannelList(), - ), + ChannelList(), UserMentionsPage(), ], ), diff --git a/stream_chat_v1/lib/channel_media_display_screen.dart b/stream_chat_v1/lib/channel_media_display_screen.dart index 0cfdde6bf3..65c9a5d39d 100644 --- a/stream_chat_v1/lib/channel_media_display_screen.dart +++ b/stream_chat_v1/lib/channel_media_display_screen.dart @@ -1,61 +1,45 @@ import 'package:example/localizations.dart'; +import 'package:example/routes/routes.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:video_player/video_player.dart'; -class ChannelMediaDisplayScreen extends StatefulWidget { - /// The sorting used for the channels matching the filters. - /// Sorting is based on field and direction, multiple sorting options can be provided. - /// You can sort based on last_updated, last_message_at, updated_at, created_at or member_count. - /// Direction can be ascending or descending. - final List? sortOptions; - - /// Pagination parameters - /// limit: the number of users to return (max is 30) - /// offset: the offset (max is 1000) - /// message_limit: how many messages should be included to each channel - final PaginationParams paginationParams; - - /// The builder used when the file list is empty. - final WidgetBuilder? emptyBuilder; - - final ShowMessageCallback? onShowMessage; +import 'channel_page.dart'; +class ChannelMediaDisplayScreen extends StatefulWidget { final StreamMessageThemeData messageTheme; const ChannelMediaDisplayScreen({ + Key? key, required this.messageTheme, - this.sortOptions, - this.paginationParams = const PaginationParams(limit: 20), - this.emptyBuilder, - this.onShowMessage, - }); + }) : super(key: key); @override - _ChannelMediaDisplayScreenState createState() => + State createState() => _ChannelMediaDisplayScreenState(); } class _ChannelMediaDisplayScreenState extends State { - Map controllerCache = {}; - - @override - void initState() { - super.initState(); - final messageSearchBloc = MessageSearchBloc.of(context); - messageSearchBloc.search( - filter: Filter.in_( - 'cid', - [StreamChannel.of(context).channel.cid!], - ), - messageFilter: Filter.in_( - 'attachments.type', - ['image', 'video'], + final Map controllerCache = {}; + + late final controller = StreamMessageSearchListController( + client: StreamChat.of(context).client, + filter: Filter.in_( + 'cid', + [StreamChannel.of(context).channel.cid!], + ), + messageFilter: Filter.in_( + 'attachments.type', + ['image', 'video'], + ), + sort: [ + SortOption( + 'created_at', + direction: SortOption.ASC, ), - sort: widget.sortOptions, - pagination: widget.paginationParams, - ); - } + ], + limit: 20, + ); @override Widget build(BuildContext context) { @@ -74,160 +58,169 @@ class _ChannelMediaDisplayScreenState extends State { leading: StreamBackButton(), backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, ), - body: _buildMediaGrid(), - ); - } - - Widget _buildMediaGrid() { - final messageSearchBloc = MessageSearchBloc.of(context); - - return StreamBuilder>( - builder: (context, snapshot) { - if (snapshot.data == null) { - return Center( - child: const CircularProgressIndicator(), - ); - } - - if (snapshot.data!.isEmpty) { - if (widget.emptyBuilder != null) { - return widget.emptyBuilder!(context); - } - return Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - StreamSvgIcon.pictures( - size: 136.0, - color: StreamChatTheme.of(context).colorTheme.disabled, - ), - SizedBox(height: 16.0), - Text( - AppLocalizations.of(context).noMedia, - style: TextStyle( - fontSize: 14.0, - color: - StreamChatTheme.of(context).colorTheme.textHighEmphasis, - ), - ), - SizedBox(height: 8.0), - Text( - AppLocalizations.of(context).photosOrVideosWillAppearHere, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 14.0, - color: StreamChatTheme.of(context) - .colorTheme - .textHighEmphasis - .withOpacity(0.5), + body: ValueListenableBuilder( + valueListenable: controller, + builder: (BuildContext context, + PagedValue value, Widget? child) { + return value.when( + (items, nextPageKey, error) { + if (items.isEmpty) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + StreamSvgIcon.pictures( + size: 136.0, + color: StreamChatTheme.of(context).colorTheme.disabled, + ), + SizedBox(height: 16.0), + Text( + AppLocalizations.of(context).noMedia, + style: TextStyle( + fontSize: 14.0, + color: StreamChatTheme.of(context) + .colorTheme + .textHighEmphasis, + ), + ), + SizedBox(height: 8.0), + Text( + AppLocalizations.of(context) + .photosOrVideosWillAppearHere, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 14.0, + color: StreamChatTheme.of(context) + .colorTheme + .textHighEmphasis + .withOpacity(0.5), + ), + ), + ], ), - ), - ], - ), - ); - } - - final media = <_AssetPackage>[]; - - for (var item in snapshot.data!) { - item.message.attachments - .where((e) => - (e.type == 'image' || e.type == 'video') && - e.ogScrapeUrl == null) - .forEach((e) { - VideoPlayerController? controller; - if (e.type == 'video') { - var cachedController = controllerCache[e.assetUrl]; - - if (cachedController == null) { - controller = VideoPlayerController.network(e.assetUrl!); - controller.initialize(); - controllerCache[e.assetUrl] = controller; - } else { - controller = cachedController; + ); + } + final media = <_AssetPackage>[]; + + for (var item in value.asSuccess.items) { + item.message.attachments + .where((e) => + (e.type == 'image' || e.type == 'video') && + e.ogScrapeUrl == null) + .forEach((e) { + VideoPlayerController? controller; + if (e.type == 'video') { + var cachedController = controllerCache[e.assetUrl]; + + if (cachedController == null) { + controller = VideoPlayerController.network(e.assetUrl!); + controller.initialize(); + controllerCache[e.assetUrl] = controller; + } else { + controller = cachedController; + } + } + media.add(_AssetPackage(e, item.message, controller)); + }); } - } - media.add(_AssetPackage(e, item.message, controller)); - }); - } - return LazyLoadScrollView( - onEndOfPage: () => messageSearchBloc.search( - filter: Filter.in_( - 'cid', - [StreamChannel.of(context).channel.cid!], - ), - messageFilter: Filter.in_( - 'attachments.type', - ['image', 'video'], - ), - sort: widget.sortOptions, - pagination: widget.paginationParams.copyWith( - offset: messageSearchBloc.messageResponses?.length ?? 0, - ), - ), - child: GridView.builder( - gridDelegate: - SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3), - itemBuilder: (context, position) { - var channel = StreamChannel.of(context).channel; - return Padding( - padding: const EdgeInsets.all(1.0), - child: InkWell( - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => StreamChannel( - channel: channel, - child: StreamFullScreenMedia( - mediaAttachmentPackages: media - .map( - (e) => StreamAttachmentPackage( - attachment: e.attachment, - message: e.message, + return LazyLoadScrollView( + onEndOfPage: () async { + if (nextPageKey != null) { + controller.loadMore(nextPageKey); + } + }, + child: GridView.builder( + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 3), + itemBuilder: (context, position) { + var channel = StreamChannel.of(context).channel; + return Padding( + padding: const EdgeInsets.all(1.0), + child: InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => StreamChannel( + channel: channel, + child: StreamFullScreenMedia( + mediaAttachmentPackages: media + .map( + (e) => StreamAttachmentPackage( + attachment: e.attachment, + message: e.message, + ), + ) + .toList(), + startIndex: position, + userName: media[position].message.user!.name, + onShowMessage: (m, c) async { + final client = + StreamChat.of(context).client; + final message = m; + final channel = client.channel( + c.type, + id: c.id, + ); + if (channel.state == null) { + await channel.watch(); + } + Navigator.pushNamed( + context, + Routes.CHANNEL_PAGE, + arguments: ChannelPageArgs( + channel: channel, + initialMessage: message, + ), + ); + }, + ), + ), + ), + ); + }, + child: media[position].attachment.type == 'image' + ? IgnorePointer( + child: StreamImageAttachment( + attachment: media[position].attachment, + message: media[position].message, + showTitle: false, + size: Size( + MediaQuery.of(context).size.width * 0.8, + MediaQuery.of(context).size.height * 0.3, ), - ) - .toList(), - startIndex: position, - userName: media[position].message.user!.name, - onShowMessage: widget.onShowMessage, - ), - ), + messageTheme: widget.messageTheme, + ), + ) + : VideoPlayer(media[position].videoPlayer!), ), ); }, - child: media[position].attachment.type == 'image' - ? IgnorePointer( - child: StreamImageAttachment( - attachment: media[position].attachment, - message: media[position].message, - showTitle: false, - size: Size( - MediaQuery.of(context).size.width * 0.8, - MediaQuery.of(context).size.height * 0.3, - ), - messageTheme: widget.messageTheme, - ), - ) - : VideoPlayer(media[position].videoPlayer!), + itemCount: media.length, ), ); }, - itemCount: media.length, - ), - ); - }, - stream: messageSearchBloc.messagesStream, + loading: () => Center( + child: const CircularProgressIndicator(), + ), + error: (_) => Offstage(), + ); + }, + ), ); } @override void dispose() { + controller.dispose(); super.dispose(); - for (var c in controllerCache.values) { - c!.dispose(); - } + } + + @override + void initState() { + controller.doInitialLoad(); + super.initState(); } } diff --git a/stream_chat_v1/lib/channel_page.dart b/stream_chat_v1/lib/channel_page.dart index 6cf60e5a5d..e2b2d42cc1 100644 --- a/stream_chat_v1/lib/channel_page.dart +++ b/stream_chat_v1/lib/channel_page.dart @@ -35,7 +35,7 @@ class ChannelPage extends StatefulWidget { class _ChannelPageState extends State { FocusNode? _focusNode; - MessageInputController _messageInputController = MessageInputController(); + StreamMessageInputController _messageInputController = StreamMessageInputController(); @override void initState() { diff --git a/stream_chat_v1/lib/chat_info_screen.dart b/stream_chat_v1/lib/chat_info_screen.dart index 9556840c1c..38602295b0 100644 --- a/stream_chat_v1/lib/chat_info_screen.dart +++ b/stream_chat_v1/lib/chat_info_screen.dart @@ -218,36 +218,7 @@ class _ChatInfoScreenState extends State { MaterialPageRoute( builder: (context) => StreamChannel( channel: channel, - child: MessageSearchBloc( - child: PinnedMessagesScreen( - messageTheme: widget.messageTheme, - sortOptions: [ - SortOption( - 'created_at', - direction: SortOption.ASC, - ), - ], - onShowMessage: (m, c) async { - final client = StreamChat.of(context).client; - final message = m; - final channel = client.channel( - c.type, - id: c.id, - ); - if (channel.state == null) { - await channel.watch(); - } - Navigator.pushNamed( - context, - Routes.CHANNEL_PAGE, - arguments: ChannelPageArgs( - channel: channel, - initialMessage: message, - ), - ); - }, - ), - ), + child: PinnedMessagesScreen(), ), ), ); @@ -278,35 +249,8 @@ class _ChatInfoScreenState extends State { MaterialPageRoute( builder: (context) => StreamChannel( channel: channel, - child: MessageSearchBloc( - child: ChannelMediaDisplayScreen( - messageTheme: widget.messageTheme, - sortOptions: [ - SortOption( - 'created_at', - direction: SortOption.ASC, - ), - ], - onShowMessage: (m, c) async { - final client = StreamChat.of(context).client; - final message = m; - final channel = client.channel( - c.type, - id: c.id, - ); - if (channel.state == null) { - await channel.watch(); - } - Navigator.pushNamed( - context, - Routes.CHANNEL_PAGE, - arguments: ChannelPageArgs( - channel: channel, - initialMessage: message, - ), - ); - }, - ), + child: ChannelMediaDisplayScreen( + messageTheme: widget.messageTheme, ), ), ), @@ -338,15 +282,8 @@ class _ChatInfoScreenState extends State { MaterialPageRoute( builder: (context) => StreamChannel( channel: channel, - child: MessageSearchBloc( - child: ChannelFileDisplayScreen( - sortOptions: [ - SortOption( - 'created_at', - direction: SortOption.ASC, - ), - ], - ), + child: ChannelFileDisplayScreen( + messageTheme: widget.messageTheme, ), ), ), diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/group_info_screen.dart index e650b07ac4..bf5fec2f28 100644 --- a/stream_chat_v1/lib/group_info_screen.dart +++ b/stream_chat_v1/lib/group_info_screen.dart @@ -40,16 +40,52 @@ class _GroupInfoScreenState extends State { ValueNotifier mutedBool = ValueNotifier(false); + late final channel = StreamChannel.of(context).channel; + + late final userListController = StreamUserListController( + client: StreamChat.of(context).client, + limit: 25, + filter: Filter.and( + [ + if (_searchController!.text.isNotEmpty) + Filter.autoComplete('name', _userNameQuery), + Filter.notIn('id', [ + StreamChat.of(context).currentUser!.id, + ...channel.state!.members + .map(((e) => e.userId)) + .whereType(), + ]), + ], + ), + sort: [ + SortOption( + 'name', + direction: 1, + ), + ], + ); + void _userNameListener() { if (_searchController!.text == _userNameQuery) { return; } if (_debounce?.isActive ?? false) _debounce!.cancel(); _debounce = Timer(const Duration(milliseconds: 350), () { - if (mounted && modalSetStateCallback != null) { - modalSetStateCallback!(() { - _userNameQuery = _searchController!.text; - }); + if (mounted) { + _userNameQuery = _searchController!.text; + userListController.filter = Filter.and( + [ + if (_searchController!.text.isNotEmpty) + Filter.autoComplete('name', _userNameQuery), + Filter.notIn('id', [ + StreamChat.of(context).currentUser!.id, + ...channel.state!.members + .map(((e) => e.userId)) + .whereType(), + ]), + ], + ); + userListController.doInitialLoad(); } }); } @@ -57,25 +93,28 @@ class _GroupInfoScreenState extends State { @override void initState() { super.initState(); - var channel = StreamChannel.of(context); + _nameController = TextEditingController.fromValue( - TextEditingValue( - text: (channel.channel.extraData['name'] as String?) ?? ''), + TextEditingValue(text: (channel.extraData['name'] as String?) ?? ''), ); _searchController = TextEditingController()..addListener(_userNameListener); _nameController!.addListener(() { setState(() {}); }); - mutedBool = ValueNotifier(StreamChannel.of(context).channel.isMuted); + mutedBool = ValueNotifier(channel.isMuted); } @override - Widget build(BuildContext context) { - var channel = StreamChannel.of(context); + void dispose() { + userListController.dispose(); + super.dispose(); + } + @override + Widget build(BuildContext context) { return StreamBuilder>( - stream: channel.channel.state!.membersStream, + stream: channel.state!.membersStream, builder: (context, snapshot) { if (!snapshot.hasData) { return Container( @@ -94,7 +133,7 @@ class _GroupInfoScreenState extends State { title: Column( children: [ StreamBuilder( - stream: channel.channelStateStream, + stream: channel.state?.channelStateStream, builder: (context, state) { if (!state.hasData) { return Text( @@ -131,7 +170,7 @@ class _GroupInfoScreenState extends State { height: 3.0, ), Text( - '${channel.channel.memberCount} ${AppLocalizations.of(context).members}, ${snapshot.data?.where((e) => e.user!.online).length ?? 0} ${AppLocalizations.of(context).online}', + '${channel.memberCount} ${AppLocalizations.of(context).members}, ${snapshot.data?.where((e) => e.user!.online).length ?? 0} ${AppLocalizations.of(context).online}', style: TextStyle( color: StreamChatTheme.of(context) .colorTheme @@ -144,7 +183,7 @@ class _GroupInfoScreenState extends State { ), centerTitle: true, actions: [ - if (channel.channel.ownCapabilities + if (channel.ownCapabilities .contains(PermissionType.updateChannelMembers)) StreamNeumorphicButton( child: InkWell( @@ -169,7 +208,7 @@ class _GroupInfoScreenState extends State { height: 8.0, color: StreamChatTheme.of(context).colorTheme.disabled, ), - if (channel.channel.ownCapabilities + if (channel.ownCapabilities .contains(PermissionType.updateChannel)) _buildNameTile(), _buildOptionListTiles(), @@ -336,7 +375,6 @@ class _GroupInfoScreenState extends State { } Widget _buildNameTile() { - var channel = StreamChannel.of(context).channel; var channelName = (channel.extraData['name'] as String?) ?? ''; return Material( @@ -412,7 +450,7 @@ class _GroupInfoScreenState extends State { size: 24.0, ), onTap: () { - StreamChannel.of(context).channel.update({ + channel.update({ 'name': _nameController!.text.trim(), }).catchError((err) { setState(() { @@ -432,8 +470,6 @@ class _GroupInfoScreenState extends State { } Widget _buildOptionListTiles() { - var channel = StreamChannel.of(context); - return Column( children: [ // OptionListTile( @@ -448,10 +484,9 @@ class _GroupInfoScreenState extends State { // ), // onTap: () {}, // ), - if (channel.channel.ownCapabilities - .contains(PermissionType.muteChannel)) + if (channel.ownCapabilities.contains(PermissionType.muteChannel)) StreamBuilder( - stream: StreamChannel.of(context).channel.isMutedStream, + stream: channel.isMutedStream, builder: (context, snapshot) { mutedBool.value = snapshot.data; @@ -482,9 +517,9 @@ class _GroupInfoScreenState extends State { mutedBool.value = val; if (snapshot.data!) { - channel.channel.unmute(); + channel.unmute(); } else { - channel.channel.mute(); + channel.mute(); } }, ); @@ -517,36 +552,7 @@ class _GroupInfoScreenState extends State { MaterialPageRoute( builder: (context) => StreamChannel( channel: channel, - child: MessageSearchBloc( - child: PinnedMessagesScreen( - messageTheme: widget.messageTheme, - sortOptions: [ - SortOption( - 'created_at', - direction: SortOption.ASC, - ), - ], - onShowMessage: (m, c) async { - final client = StreamChat.of(context).client; - final message = m; - final channel = client.channel( - c.type, - id: c.id, - ); - if (channel.state == null) { - await channel.watch(); - } - Navigator.pushNamed( - context, - Routes.CHANNEL_PAGE, - arguments: ChannelPageArgs( - channel: channel, - initialMessage: message, - ), - ); - }, - ), - ), + child: PinnedMessagesScreen(), ), ), ); @@ -578,36 +584,8 @@ class _GroupInfoScreenState extends State { MaterialPageRoute( builder: (context) => StreamChannel( channel: channel, - child: MessageSearchBloc( - child: ChannelMediaDisplayScreen( - messageTheme: widget.messageTheme, - sortOptions: [ - SortOption( - 'created_at', - direction: SortOption.ASC, - ), - ], - paginationParams: PaginationParams(limit: 20), - onShowMessage: (m, c) async { - final client = StreamChat.of(context).client; - final message = m; - final channel = client.channel( - c.type, - id: c.id, - ); - if (channel.state == null) { - await channel.watch(); - } - await Navigator.pushNamed( - context, - Routes.CHANNEL_PAGE, - arguments: ChannelPageArgs( - channel: channel, - initialMessage: message, - ), - ); - }, - ), + child: ChannelMediaDisplayScreen( + messageTheme: widget.messageTheme, ), ), ), @@ -640,25 +618,16 @@ class _GroupInfoScreenState extends State { MaterialPageRoute( builder: (context) => StreamChannel( channel: channel, - child: MessageSearchBloc( - child: ChannelFileDisplayScreen( - sortOptions: [ - SortOption( - 'created_at', - direction: SortOption.ASC, - ), - ], - paginationParams: PaginationParams(limit: 20), - ), + child: ChannelFileDisplayScreen( + messageTheme: widget.messageTheme, ), ), ), ); }, ), - if (!channel.channel.isDistinct && - channel.channel.ownCapabilities - .contains(PermissionType.leaveChannel)) + if (!channel.isDistinct && + channel.ownCapabilities.contains(PermissionType.leaveChannel)) StreamOptionListTile( tileColor: StreamChatTheme.of(context).colorTheme.appBg, separatorColor: StreamChatTheme.of(context).colorTheme.disabled, @@ -703,106 +672,81 @@ class _GroupInfoScreenState extends State { } void _buildAddUserModal(context) { - var channel = StreamChannel.of(context).channel; - final userListController = StreamUserListController( - client: channel.client, - limit: 25, - filter: Filter.and( - [ - if (_searchController!.text.isNotEmpty) - Filter.autoComplete('name', _userNameQuery), - Filter.notIn('id', [ - StreamChat.of(context).currentUser!.id, - ...channel.state!.members - .map(((e) => e.userId)) - .whereType(), - ]), - ], - ), - sort: [ - SortOption( - 'name', - direction: 1, - ), - ], - ); - showDialog( useRootNavigator: false, context: context, barrierColor: StreamChatTheme.of(context).colorTheme.overlay, builder: (context) { - return StatefulBuilder(builder: (context, modalSetState) { - modalSetStateCallback = modalSetState; - return Padding( - padding: EdgeInsets.only(top: 16.0, left: 8.0, right: 8.0), - child: Material( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(16.0), - topRight: Radius.circular(16.0), - ), - clipBehavior: Clip.antiAlias, - child: Scaffold( - body: Column( - children: [ - Padding( - padding: const EdgeInsets.all(16), - child: _buildTextInputSection(modalSetState), - ), - Expanded( - child: StreamUserListView( - controller: userListController, - onUserTap: (user) async { - _searchController!.clear(); + return Padding( + padding: EdgeInsets.only(top: 16.0, left: 8.0, right: 8.0), + child: Material( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(16.0), + topRight: Radius.circular(16.0), + ), + clipBehavior: Clip.antiAlias, + child: Scaffold( + body: Column( + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: _buildTextInputSection(), + ), + Expanded( + child: StreamUserGridView( + controller: userListController, + onUserTap: (user) async { + _searchController!.clear(); - await channel.addMembers([user.id]); - Navigator.pop(context); - setState(() {}); - }, - emptyBuilder: (_) { - return LayoutBuilder( - builder: (context, viewportConstraints) { - return SingleChildScrollView( - physics: AlwaysScrollableScrollPhysics(), - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: viewportConstraints.maxHeight, - ), - child: Center( - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(24), - child: StreamSvgIcon.search( - size: 96, - color: StreamChatTheme.of(context) - .colorTheme - .textLowEmphasis, - ), + await channel.addMembers([user.id]); + Navigator.pop(context); + setState(() {}); + }, + emptyBuilder: (_) { + return LayoutBuilder( + builder: (context, viewportConstraints) { + return SingleChildScrollView( + physics: AlwaysScrollableScrollPhysics(), + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: viewportConstraints.maxHeight, + ), + child: Center( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(24), + child: StreamSvgIcon.search( + size: 96, + color: StreamChatTheme.of(context) + .colorTheme + .textLowEmphasis, ), - Text(AppLocalizations.of(context) - .noUserMatchesTheseKeywords), - ], - ), + ), + Text(AppLocalizations.of(context) + .noUserMatchesTheseKeywords), + ], ), ), - ); - }, - ); - }, - ), + ), + ); + }, + ); + }, ), - ], - ), + ), + ], ), ), - ); - }); + ), + ); }, - ).then((_) => userListController.dispose()); + ).whenComplete(() { + _searchController?.clear(); + }); } - Widget _buildTextInputSection(modalSetState) { + Widget _buildTextInputSection() { final theme = StreamChatTheme.of(context); return Column( children: [ @@ -862,7 +806,6 @@ class _GroupInfoScreenState extends State { } void _showUserInfoModal(User? user, bool isUserAdmin) { - var channel = StreamChannel.of(context).channel; final color = StreamChatTheme.of(context).colorTheme.barsBg; showModalBottomSheet( diff --git a/stream_chat_v1/lib/pinned_messages_screen.dart b/stream_chat_v1/lib/pinned_messages_screen.dart index 6c2eaec9a6..7ab6d98c60 100644 --- a/stream_chat_v1/lib/pinned_messages_screen.dart +++ b/stream_chat_v1/lib/pinned_messages_screen.dart @@ -1,60 +1,34 @@ import 'package:example/localizations.dart'; +import 'package:example/routes/routes.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -import 'package:video_player/video_player.dart'; -class PinnedMessagesScreen extends StatefulWidget { - /// The sorting used for the channels matching the filters. - /// Sorting is based on field and direction, multiple sorting options can be provided. - /// You can sort based on last_updated, last_message_at, updated_at, created_at or member_count. - /// Direction can be ascending or descending. - final List? sortOptions; - - /// Pagination parameters - /// limit: the number of users to return (max is 30) - /// offset: the offset (max is 1000) - /// message_limit: how many messages should be included to each channel - final PaginationParams paginationParams; - - /// The builder used when the file list is empty. - final WidgetBuilder? emptyBuilder; - - final ShowMessageCallback? onShowMessage; - - final StreamMessageThemeData messageTheme; - - const PinnedMessagesScreen({ - required this.messageTheme, - this.sortOptions, - this.paginationParams = const PaginationParams(limit: 20), - this.emptyBuilder, - this.onShowMessage, - }); +import 'channel_page.dart'; +class PinnedMessagesScreen extends StatefulWidget { @override - _PinnedMessagesScreenState createState() => _PinnedMessagesScreenState(); + State createState() => _PinnedMessagesScreenState(); } class _PinnedMessagesScreenState extends State { - Map controllerCache = {}; - - @override - void initState() { - super.initState(); - final messageSearchBloc = MessageSearchBloc.of(context); - messageSearchBloc.search( - filter: Filter.in_( - 'cid', - [StreamChannel.of(context).channel.cid!], + late final controller = StreamMessageSearchListController( + client: StreamChat.of(context).client, + filter: Filter.in_( + 'cid', + [StreamChannel.of(context).channel.cid!], + ), + messageFilter: Filter.equal( + 'pinned', + true, + ), + sort: [ + SortOption( + 'created_at', + direction: SortOption.ASC, ), - messageFilter: Filter.equal( - 'pinned', - true, - ), - sort: widget.sortOptions, - pagination: widget.paginationParams, - ); - } + ], + limit: 20, + ); @override Widget build(BuildContext context) { @@ -73,25 +47,9 @@ class _PinnedMessagesScreenState extends State { leading: StreamBackButton(), backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, ), - body: _buildMediaGrid(), - ); - } - - Widget _buildMediaGrid() { - final messageSearchBloc = MessageSearchBloc.of(context); - - return StreamBuilder>( - builder: (context, snapshot) { - if (snapshot.data == null) { - return Center( - child: const CircularProgressIndicator(), - ); - } - - if (snapshot.data!.isEmpty) { - if (widget.emptyBuilder != null) { - return widget.emptyBuilder!(context); - } + body: StreamMessageSearchListView( + controller: controller, + emptyBuilder: (_) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -140,74 +98,33 @@ class _PinnedMessagesScreenState extends State { ], ), ); - } - - var data = snapshot.data ?? []; - - return LazyLoadScrollView( - onEndOfPage: () => messageSearchBloc.search( - filter: Filter.in_( - 'cid', - [StreamChannel.of(context).channel.cid!], - ), - messageFilter: Filter.equal( - 'pinned', - true, - ), - sort: widget.sortOptions, - pagination: widget.paginationParams.copyWith( - offset: messageSearchBloc.messageResponses?.length ?? 0, + }, + onMessageTap: (messageResponse) async { + final client = StreamChat.of(context).client; + final message = messageResponse.message; + final channel = client.channel( + messageResponse.channel!.type, + id: messageResponse.channel!.id, + ); + if (channel.state == null) { + await channel.watch(); + } + Navigator.pushNamed( + context, + Routes.CHANNEL_PAGE, + arguments: ChannelPageArgs( + channel: channel, + initialMessage: message, ), - ), - child: ListView.builder( - itemBuilder: (context, position) { - var user = data[position].message.user!; - var attachments = data[position].message.attachments; - var text = data[position].message.text ?? ''; - - return ListTile( - leading: StreamUserAvatar( - user: user, - constraints: BoxConstraints.tightFor( - width: 40.0, - height: 40.0, - ), - borderRadius: BorderRadius.circular(28), - ), - title: Text( - user.name, - style: TextStyle( - color: StreamChatTheme.of(context) - .colorTheme - .textHighEmphasis, - fontWeight: FontWeight.bold), - ), - subtitle: Text( - text != '' - ? text - : (attachments.isNotEmpty - ? '${attachments.length} ${attachments.length > 1 ? AppLocalizations.of(context).attachments : AppLocalizations.of(context).attachment}' - : ''), - ), - onTap: () { - widget.onShowMessage?.call(data[position].message, - StreamChannel.of(context).channel); - }, - ); - }, - itemCount: snapshot.data!.length, - ), - ); - }, - stream: messageSearchBloc.messagesStream, + ); + }, + ), ); } @override void dispose() { + controller.dispose(); super.dispose(); - for (var c in controllerCache.values) { - c!.dispose(); - } } } diff --git a/stream_chat_v1/lib/thread_page.dart b/stream_chat_v1/lib/thread_page.dart index 6ffd5e3ac8..3983cb765f 100644 --- a/stream_chat_v1/lib/thread_page.dart +++ b/stream_chat_v1/lib/thread_page.dart @@ -19,12 +19,13 @@ class ThreadPage extends StatefulWidget { class _ThreadPageState extends State { FocusNode _focusNode = FocusNode(); - late MessageInputController _messageInputController; + late StreamMessageInputController _messageInputController; @override void initState() { super.initState(); - _messageInputController = MessageInputController(message: widget.parent); + _messageInputController = + StreamMessageInputController(message: widget.parent); } @override From 7780d3bcf8db0ae88ce18adfb90f35c3ee98f45e Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 29 Apr 2022 15:27:02 +0200 Subject: [PATCH 117/172] fix analysis --- stream_chat_v1/lib/channel_file_display_screen.dart | 3 --- stream_chat_v1/lib/chat_info_screen.dart | 2 -- stream_chat_v1/lib/group_info_screen.dart | 1 - stream_chat_v1/lib/routes/app_routes.dart | 2 +- 4 files changed, 1 insertion(+), 7 deletions(-) diff --git a/stream_chat_v1/lib/channel_file_display_screen.dart b/stream_chat_v1/lib/channel_file_display_screen.dart index 8806f97fd2..e7be692146 100644 --- a/stream_chat_v1/lib/channel_file_display_screen.dart +++ b/stream_chat_v1/lib/channel_file_display_screen.dart @@ -1,11 +1,8 @@ import 'package:example/localizations.dart'; -import 'package:example/routes/routes.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:video_player/video_player.dart'; -import 'channel_page.dart'; - class ChannelFileDisplayScreen extends StatefulWidget { final StreamMessageThemeData messageTheme; diff --git a/stream_chat_v1/lib/chat_info_screen.dart b/stream_chat_v1/lib/chat_info_screen.dart index 38602295b0..731050deb7 100644 --- a/stream_chat_v1/lib/chat_info_screen.dart +++ b/stream_chat_v1/lib/chat_info_screen.dart @@ -5,9 +5,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'channel_file_display_screen.dart'; import 'channel_media_display_screen.dart'; -import 'channel_page.dart'; import 'pinned_messages_screen.dart'; -import 'routes/routes.dart'; /// Detail screen for a 1:1 chat correspondence class ChatInfoScreen extends StatefulWidget { diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/group_info_screen.dart index bf5fec2f28..529c0a40a9 100644 --- a/stream_chat_v1/lib/group_info_screen.dart +++ b/stream_chat_v1/lib/group_info_screen.dart @@ -11,7 +11,6 @@ import 'channel_media_display_screen.dart'; import 'channel_page.dart'; import 'chat_info_screen.dart'; import 'pinned_messages_screen.dart'; -import 'routes/routes.dart'; class GroupInfoScreen extends StatefulWidget { final StreamMessageThemeData messageTheme; diff --git a/stream_chat_v1/lib/routes/app_routes.dart b/stream_chat_v1/lib/routes/app_routes.dart index 78593c4956..4f913b48db 100644 --- a/stream_chat_v1/lib/routes/app_routes.dart +++ b/stream_chat_v1/lib/routes/app_routes.dart @@ -1,4 +1,4 @@ -import 'package:collection/src/iterable_extensions.dart'; +import 'package:collection/collection.dart'; import 'package:example/channel_list_page.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; From e5acb6d0cf3ab4e9b1a08bec1ad624cba4106aa7 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 3 May 2022 09:22:05 +0200 Subject: [PATCH 118/172] bump version --- stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj | 12 ++++++++---- stream_chat_v1/pubspec.yaml | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj index 5b28f5387d..2a8979a4dd 100644 --- a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj +++ b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj @@ -247,6 +247,7 @@ "${BUILT_PRODUCTS_DIR}/FMDB/FMDB.framework", "${BUILT_PRODUCTS_DIR}/ReachabilitySwift/Reachability.framework", "${BUILT_PRODUCTS_DIR}/SDWebImage/SDWebImage.framework", + "${BUILT_PRODUCTS_DIR}/Sentry/Sentry.framework", "${BUILT_PRODUCTS_DIR}/SwiftyGif/SwiftyGif.framework", "${BUILT_PRODUCTS_DIR}/connectivity_plus/connectivity_plus.framework", "${BUILT_PRODUCTS_DIR}/file_picker/file_picker.framework", @@ -254,17 +255,18 @@ "${BUILT_PRODUCTS_DIR}/flutter_local_notifications/flutter_local_notifications.framework", "${BUILT_PRODUCTS_DIR}/flutter_secure_storage/flutter_secure_storage.framework", "${BUILT_PRODUCTS_DIR}/image_gallery_saver/image_gallery_saver.framework", - "${BUILT_PRODUCTS_DIR}/image_picker/image_picker.framework", + "${BUILT_PRODUCTS_DIR}/image_picker_ios/image_picker_ios.framework", "${BUILT_PRODUCTS_DIR}/libwebp/libwebp.framework", + "${BUILT_PRODUCTS_DIR}/package_info_plus/package_info_plus.framework", "${BUILT_PRODUCTS_DIR}/path_provider_ios/path_provider_ios.framework", "${BUILT_PRODUCTS_DIR}/photo_manager/photo_manager.framework", + "${BUILT_PRODUCTS_DIR}/sentry_flutter/sentry_flutter.framework", "${BUILT_PRODUCTS_DIR}/share_plus/share_plus.framework", "${BUILT_PRODUCTS_DIR}/shared_preferences_ios/shared_preferences_ios.framework", "${BUILT_PRODUCTS_DIR}/sqflite/sqflite.framework", "${BUILT_PRODUCTS_DIR}/sqlite3/sqlite3.framework", "${BUILT_PRODUCTS_DIR}/sqlite3_flutter_libs/sqlite3_flutter_libs.framework", "${BUILT_PRODUCTS_DIR}/url_launcher_ios/url_launcher_ios.framework", - "${BUILT_PRODUCTS_DIR}/video_compress/video_compress.framework", "${BUILT_PRODUCTS_DIR}/video_player_avfoundation/video_player_avfoundation.framework", "${BUILT_PRODUCTS_DIR}/video_thumbnail/video_thumbnail.framework", "${BUILT_PRODUCTS_DIR}/wakelock/wakelock.framework", @@ -276,6 +278,7 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FMDB.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Reachability.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImage.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Sentry.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftyGif.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/connectivity_plus.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/file_picker.framework", @@ -283,17 +286,18 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_local_notifications.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_secure_storage.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/image_gallery_saver.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/image_picker.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/image_picker_ios.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libwebp.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/package_info_plus.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider_ios.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/photo_manager.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sentry_flutter.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/share_plus.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences_ios.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqflite.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqlite3.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqlite3_flutter_libs.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher_ios.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_compress.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_player_avfoundation.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_thumbnail.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/wakelock.framework", diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index 023a74feae..a4cb9ea246 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -1,7 +1,7 @@ name: example description: A new Flutter project. publish_to: 'none' -version: 1.8.1 +version: 2.0.0 environment: sdk: '>=2.12.0 <3.0.0' From 2fd8ffa953037373a41472f40ef503c76b2a647b Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 3 May 2022 09:53:25 +0200 Subject: [PATCH 119/172] profile --- stream_chat_v1/ios/fastlane/beta_gym_export_options.plist | 2 +- stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/stream_chat_v1/ios/fastlane/beta_gym_export_options.plist b/stream_chat_v1/ios/fastlane/beta_gym_export_options.plist index a7d01e55c9..e88559ac2a 100644 --- a/stream_chat_v1/ios/fastlane/beta_gym_export_options.plist +++ b/stream_chat_v1/ios/fastlane/beta_gym_export_options.plist @@ -7,7 +7,7 @@ provisioningProfiles io.getstream.flutter - match AdHoc io.getstream.flutter 1634304851 + match AdHoc io.getstream.flutter \ No newline at end of file diff --git a/stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist b/stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist index 1c4d3dca93..2d09042589 100644 --- a/stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist +++ b/stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist @@ -7,7 +7,7 @@ provisioningProfiles io.getstream.flutter - match AppStore io.getstream.flutter 1630916072 + match AppStore io.getstream.flutter \ No newline at end of file From 4614c083b4e20b8b919e12b1484882b915c2a8cb Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 3 May 2022 10:43:19 +0200 Subject: [PATCH 120/172] profile --- stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist b/stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist index 2d09042589..1c4d3dca93 100644 --- a/stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist +++ b/stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist @@ -7,7 +7,7 @@ provisioningProfiles io.getstream.flutter - match AppStore io.getstream.flutter + match AppStore io.getstream.flutter 1630916072 \ No newline at end of file From f579ff9d9d23895cdccda06150dc79662d0739d1 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 3 May 2022 10:44:57 +0200 Subject: [PATCH 121/172] profile --- stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj index 2a8979a4dd..daeb9c3b00 100644 --- a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj +++ b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj @@ -456,7 +456,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter 1634304851"; + PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; @@ -598,7 +598,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter 1634304851"; + PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -635,7 +635,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter 1634304851"; + PROVISIONING_PROFILE_SPECIFIER = "match AdHoc io.getstream.flutter"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; From 17504dfa4cd66477f77932fccffa62aa9835af68 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 3 May 2022 11:23:46 +0200 Subject: [PATCH 122/172] profiles --- stream_chat_v1/ios/fastlane/Fastfile | 2 +- stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/stream_chat_v1/ios/fastlane/Fastfile b/stream_chat_v1/ios/fastlane/Fastfile index b1ac253a0e..c072b9f034 100644 --- a/stream_chat_v1/ios/fastlane/Fastfile +++ b/stream_chat_v1/ios/fastlane/Fastfile @@ -62,7 +62,7 @@ platform :ios do settings_to_override = { :BUNDLE_IDENTIFIER => "io.getstream.flutter", - :PROVISIONING_PROFILE_SPECIFIER => "match AppStore io.getstream.flutter 1630916072" + :PROVISIONING_PROFILE_SPECIFIER => "match AppStore io.getstream.flutter 1651569762" } gym( diff --git a/stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist b/stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist index 1c4d3dca93..16bb6afee5 100644 --- a/stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist +++ b/stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist @@ -7,7 +7,7 @@ provisioningProfiles io.getstream.flutter - match AppStore io.getstream.flutter 1630916072 + match AppStore io.getstream.flutter 1651569762 \ No newline at end of file From 11e623016a5894ba090add0053fb68494fc02622 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 3 May 2022 11:31:20 +0200 Subject: [PATCH 123/172] fix deps --- stream_chat_v1/pubspec.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index a4cb9ea246..5b86045719 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -13,17 +13,17 @@ dependencies: stream_chat_flutter: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: v4 + ref: develop path: packages/stream_chat_flutter stream_chat_persistence: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: v4 + ref: develop path: packages/stream_chat_persistence stream_chat_localizations: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: v4 + ref: develop path: packages/stream_chat_localizations flutter_local_notifications: ^9.0.0 flutter_svg: ^1.0.3 @@ -43,17 +43,17 @@ dependency_overrides: stream_chat: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: v4 + ref: develop path: packages/stream_chat stream_chat_flutter_core: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: v4 + ref: develop path: packages/stream_chat_flutter_core stream_chat_flutter: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: v4 + ref: develop path: packages/stream_chat_flutter flutter: From 45b27c4fe53b116787b045dd148b15b7494887e3 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 17 May 2022 11:03:18 +0200 Subject: [PATCH 124/172] fix android with flutter 3.0 --- .../src/main/kotlin/com/example/example/Application.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stream_chat_v1/android/app/src/main/kotlin/com/example/example/Application.kt b/stream_chat_v1/android/app/src/main/kotlin/com/example/example/Application.kt index d32cec4de0..938a498352 100644 --- a/stream_chat_v1/android/app/src/main/kotlin/com/example/example/Application.kt +++ b/stream_chat_v1/android/app/src/main/kotlin/com/example/example/Application.kt @@ -12,12 +12,12 @@ class Application : FlutterApplication(), PluginRegistrantCallback { super.onCreate() } - override fun registerWith(registry: PluginRegistry?) { - PathProviderPlugin.registerWith(registry?.registrarFor( + override fun registerWith(registry: PluginRegistry) { + PathProviderPlugin.registerWith(registry.registrarFor( "io.flutter.plugins.pathprovider.PathProviderPlugin")) - SharedPreferencesPlugin.registerWith(registry?.registrarFor( + SharedPreferencesPlugin.registerWith(registry.registrarFor( "io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin")) - FlutterLocalNotificationsPlugin.registerWith(registry?.registrarFor( + FlutterLocalNotificationsPlugin.registerWith(registry.registrarFor( "com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin")) } } \ No newline at end of file From 54424a270bc03a06859f87539eeee3de247c6168 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Wed, 18 May 2022 11:56:52 +0200 Subject: [PATCH 125/172] update to flutter 3.0 --- stream_chat_v1/.metadata | 39 ++++++++++++- stream_chat_v1/lib/channel_page.dart | 5 +- stream_chat_v1/lib/group_info_screen.dart | 69 +++++++++++------------ stream_chat_v1/lib/main.dart | 4 +- stream_chat_v1/lib/thread_page.dart | 8 ++- 5 files changed, 79 insertions(+), 46 deletions(-) diff --git a/stream_chat_v1/.metadata b/stream_chat_v1/.metadata index 783bcdc2a3..ce13b42014 100644 --- a/stream_chat_v1/.metadata +++ b/stream_chat_v1/.metadata @@ -1,10 +1,45 @@ # This file tracks properties of this Flutter project. # Used by Flutter tool to assess capabilities and perform upgrades etc. # -# This file should be version controlled and should not be manually edited. +# This file should be version controlled. version: - revision: 8962f6dc68ec8e2206ac2fa874da4a453856c7d3 + revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851 channel: stable project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851 + base_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851 + - platform: android + create_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851 + base_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851 + - platform: ios + create_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851 + base_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851 + - platform: linux + create_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851 + base_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851 + - platform: macos + create_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851 + base_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851 + - platform: web + create_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851 + base_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851 + - platform: windows + create_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851 + base_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/stream_chat_v1/lib/channel_page.dart b/stream_chat_v1/lib/channel_page.dart index e2b2d42cc1..9a4b0571e2 100644 --- a/stream_chat_v1/lib/channel_page.dart +++ b/stream_chat_v1/lib/channel_page.dart @@ -35,7 +35,8 @@ class ChannelPage extends StatefulWidget { class _ChannelPageState extends State { FocusNode? _focusNode; - StreamMessageInputController _messageInputController = StreamMessageInputController(); + StreamMessageInputController _messageInputController = + StreamMessageInputController(); @override void initState() { @@ -51,7 +52,7 @@ class _ChannelPageState extends State { void _reply(Message message) { _messageInputController.quotedMessage = message; - WidgetsBinding.instance!.addPostFrameCallback((timeStamp) { + WidgetsBinding.instance.addPostFrameCallback((timeStamp) { _focusNode!.requestFocus(); }); } diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/group_info_screen.dart index 529c0a40a9..a03bacef60 100644 --- a/stream_chat_v1/lib/group_info_screen.dart +++ b/stream_chat_v1/lib/group_info_screen.dart @@ -41,28 +41,7 @@ class _GroupInfoScreenState extends State { late final channel = StreamChannel.of(context).channel; - late final userListController = StreamUserListController( - client: StreamChat.of(context).client, - limit: 25, - filter: Filter.and( - [ - if (_searchController!.text.isNotEmpty) - Filter.autoComplete('name', _userNameQuery), - Filter.notIn('id', [ - StreamChat.of(context).currentUser!.id, - ...channel.state!.members - .map(((e) => e.userId)) - .whereType(), - ]), - ], - ), - sort: [ - SortOption( - 'name', - direction: 1, - ), - ], - ); + late StreamUserListController userListController; void _userNameListener() { if (_searchController!.text == _userNameQuery) { @@ -104,6 +83,33 @@ class _GroupInfoScreenState extends State { mutedBool = ValueNotifier(channel.isMuted); } + @override + void didChangeDependencies() { + userListController = StreamUserListController( + client: StreamChat.of(context).client, + limit: 25, + filter: Filter.and( + [ + if (_searchController!.text.isNotEmpty) + Filter.autoComplete('name', _userNameQuery), + Filter.notIn('id', [ + StreamChat.of(context).currentUser!.id, + ...channel.state!.members + .map(((e) => e.userId)) + .whereType(), + ]), + ], + ), + sort: [ + SortOption( + 'name', + direction: 1, + ), + ], + ); + super.didChangeDependencies(); + } + @override void dispose() { userListController.dispose(); @@ -220,7 +226,7 @@ class _GroupInfoScreenState extends State { Widget _buildMembers(List members) { final groupMembers = members ..sort((prev, curr) { - if (curr.role == 'owner') return 1; + if (curr.userId == channel.createdBy?.id) return 1; return 0; }); @@ -246,7 +252,8 @@ class _GroupInfoScreenState extends State { final userMember = groupMembers.firstWhereOrNull( (e) => e.user!.id == StreamChat.of(context).currentUser!.id, ); - _showUserInfoModal(member.user, userMember?.role == 'owner'); + _showUserInfoModal( + member.user, userMember?.userId == channel.createdBy?.id); }, child: Container( height: 65.0, @@ -293,7 +300,7 @@ class _GroupInfoScreenState extends State { Padding( padding: const EdgeInsets.all(8.0), child: Text( - member.role == 'owner' + member.userId == channel.createdBy?.id ? AppLocalizations.of(context).owner : '', style: TextStyle( @@ -920,18 +927,6 @@ class _GroupInfoScreenState extends State { ); }, ), - // if (!channel.isDistinct && - // StreamChat.of(context).user!.id != user.id && - // isUserAdmin) - // _buildModalListTile( - // context, - // StreamSvgIcon.iconUserSettings( - // color: StreamChatTheme.of(context).colorTheme.textLowEmphasis, - // size: 24.0, - // ), - // 'Make Owner', () { - // // TODO: Add make owner implementation (Remaining from backend) - // }), if (!channel.isDistinct && StreamChat.of(context).currentUser!.id != user.id && isUserAdmin) diff --git a/stream_chat_v1/lib/main.dart b/stream_chat_v1/lib/main.dart index 3acb1a99a0..91690705a5 100644 --- a/stream_chat_v1/lib/main.dart +++ b/stream_chat_v1/lib/main.dart @@ -36,7 +36,7 @@ void sampleAppLogHandler(LogRecord record) async { StreamChatClient buildStreamChatClient( String apiKey, { - Level logLevel = Level.SEVERE, + Level logLevel = Level.INFO, }) { return StreamChatClient( apiKey, @@ -129,7 +129,7 @@ class _MyAppState extends State final now = DateTime.now().millisecondsSinceEpoch; if (now - timeOfStartMs > 1500) { - SchedulerBinding.instance!.addPostFrameCallback((timeStamp) { + SchedulerBinding.instance.addPostFrameCallback((timeStamp) { forwardAnimations(); }); } else { diff --git a/stream_chat_v1/lib/thread_page.dart b/stream_chat_v1/lib/thread_page.dart index 3983cb765f..d5f9c77678 100644 --- a/stream_chat_v1/lib/thread_page.dart +++ b/stream_chat_v1/lib/thread_page.dart @@ -24,8 +24,10 @@ class _ThreadPageState extends State { @override void initState() { super.initState(); - _messageInputController = - StreamMessageInputController(message: widget.parent); + _messageInputController = StreamMessageInputController( + message: Message( + parentId: widget.parent.id, + )); } @override @@ -36,7 +38,7 @@ class _ThreadPageState extends State { void _reply(Message message) { _messageInputController.quotedMessage = message; - WidgetsBinding.instance!.addPostFrameCallback((timeStamp) { + WidgetsBinding.instance.addPostFrameCallback((timeStamp) { _focusNode.requestFocus(); }); } From 7721cc3d5bec1014be8af3edac48aec2e6bb7c35 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Wed, 18 May 2022 11:57:52 +0200 Subject: [PATCH 126/172] bump version --- stream_chat_v1/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index 5b86045719..10f739b489 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -1,7 +1,7 @@ name: example description: A new Flutter project. publish_to: 'none' -version: 2.0.0 +version: 2.1.0 environment: sdk: '>=2.12.0 <3.0.0' From 163f5f2f3da51f366032e78351bbf728cb665672 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 20 May 2022 13:25:10 +0200 Subject: [PATCH 127/172] bump version --- stream_chat_v1/pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index 10f739b489..dae63d7920 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -1,10 +1,10 @@ name: example description: A new Flutter project. publish_to: 'none' -version: 2.1.0 +version: 2.1.1 environment: - sdk: '>=2.12.0 <3.0.0' + sdk: '>=2.17.0 <3.0.0' dependencies: flutter_app_badger: ^1.3.0 From 126d76e87d63121db428cd6b2d88960e45b10d41 Mon Sep 17 00:00:00 2001 From: Gordon Hayes Date: Thu, 22 Sep 2022 16:04:58 +0200 Subject: [PATCH 128/172] feat: update to v5 --- .../ios/Flutter/AppFrameworkInfo.plist | 2 +- stream_chat_v1/ios/Runner/Info.plist | 6 +- stream_chat_v1/lib/channel_list.dart | 3 +- .../lib/channel_media_display_screen.dart | 4 -- stream_chat_v1/lib/chat_info_screen.dart | 2 +- stream_chat_v1/lib/group_info_screen.dart | 4 +- stream_chat_v1/lib/main.dart | 11 ++-- .../macos/Runner.xcodeproj/project.pbxproj | 62 ++++++++++++++++++- .../contents.xcworkspacedata | 3 + .../macos/Runner/DebugProfile.entitlements | 4 ++ .../macos/Runner/Release.entitlements | 4 ++ stream_chat_v1/pubspec.yaml | 13 ++-- 12 files changed, 96 insertions(+), 22 deletions(-) diff --git a/stream_chat_v1/ios/Flutter/AppFrameworkInfo.plist b/stream_chat_v1/ios/Flutter/AppFrameworkInfo.plist index f2872cf474..4f8d4d2456 100644 --- a/stream_chat_v1/ios/Flutter/AppFrameworkInfo.plist +++ b/stream_chat_v1/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 9.0 + 11.0 diff --git a/stream_chat_v1/ios/Runner/Info.plist b/stream_chat_v1/ios/Runner/Info.plist index a1b83010c3..31b04f72c8 100644 --- a/stream_chat_v1/ios/Runner/Info.plist +++ b/stream_chat_v1/ios/Runner/Info.plist @@ -67,5 +67,7 @@ en it - - \ No newline at end of file + CADisableMinimumFrameDurationOnPhone + + + diff --git a/stream_chat_v1/lib/channel_list.dart b/stream_chat_v1/lib/channel_list.dart index dcc1e913d2..39a6c0a0ce 100644 --- a/stream_chat_v1/lib/channel_list.dart +++ b/stream_chat_v1/lib/channel_list.dart @@ -244,7 +244,8 @@ class _ChannelList extends State { color: chatTheme.colorTheme.accentError, ), onPressed: (_) async { - final res = await showConfirmationDialog( + final res = + await showConfirmationBottomSheet( context, title: 'Delete Conversation', question: diff --git a/stream_chat_v1/lib/channel_media_display_screen.dart b/stream_chat_v1/lib/channel_media_display_screen.dart index 65c9a5d39d..d3789edc9c 100644 --- a/stream_chat_v1/lib/channel_media_display_screen.dart +++ b/stream_chat_v1/lib/channel_media_display_screen.dart @@ -186,10 +186,6 @@ class _ChannelMediaDisplayScreenState extends State { attachment: media[position].attachment, message: media[position].message, showTitle: false, - size: Size( - MediaQuery.of(context).size.width * 0.8, - MediaQuery.of(context).size.height * 0.3, - ), messageTheme: widget.messageTheme, ), ) diff --git a/stream_chat_v1/lib/chat_info_screen.dart b/stream_chat_v1/lib/chat_info_screen.dart index 731050deb7..90c2f07cf0 100644 --- a/stream_chat_v1/lib/chat_info_screen.dart +++ b/stream_chat_v1/lib/chat_info_screen.dart @@ -339,7 +339,7 @@ class _ChatInfoScreenState extends State { } void _showDeleteDialog() async { - final res = await showConfirmationDialog( + final res = await showConfirmationBottomSheet( context, title: AppLocalizations.of(context).deleteConversationTitle, okText: AppLocalizations.of(context).delete.toUpperCase(), diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/group_info_screen.dart index a03bacef60..d28356992a 100644 --- a/stream_chat_v1/lib/group_info_screen.dart +++ b/stream_chat_v1/lib/group_info_screen.dart @@ -654,7 +654,7 @@ class _GroupInfoScreenState extends State { width: 24.0, ), onTap: () async { - final res = await showConfirmationDialog( + final res = await showConfirmationBottomSheet( context, title: AppLocalizations.of(context).leaveConversation, okText: AppLocalizations.of(context).leave.toUpperCase(), @@ -939,7 +939,7 @@ class _GroupInfoScreenState extends State { size: 24.0, ), AppLocalizations.of(context).removeFromGroup, () async { - final res = await showConfirmationDialog( + final res = await showConfirmationBottomSheet( context, title: AppLocalizations.of(context).removeMember, okText: diff --git a/stream_chat_v1/lib/main.dart b/stream_chat_v1/lib/main.dart index 91690705a5..a2f5b4c84b 100644 --- a/stream_chat_v1/lib/main.dart +++ b/stream_chat_v1/lib/main.dart @@ -172,11 +172,14 @@ class _MyAppState extends State GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, ], - builder: (context, child) => StreamChatTheme( - data: StreamChatThemeData( - brightness: Theme.of(context).brightness, + builder: (context, child) => StreamChatConfiguration( + data: StreamChatConfigurationData(), + child: StreamChatTheme( + data: StreamChatThemeData( + brightness: Theme.of(context).brightness, + ), + child: child!, ), - child: child!, ), onGenerateRoute: AppRoutes.generateRoute, onGenerateInitialRoutes: (initialRouteName) { diff --git a/stream_chat_v1/macos/Runner.xcodeproj/project.pbxproj b/stream_chat_v1/macos/Runner.xcodeproj/project.pbxproj index ce10a1fcd4..c973575621 100644 --- a/stream_chat_v1/macos/Runner.xcodeproj/project.pbxproj +++ b/stream_chat_v1/macos/Runner.xcodeproj/project.pbxproj @@ -21,6 +21,7 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ + 1E52A3376056853520695B44 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 782D013032AAC6BDCC56A273 /* Pods_Runner.framework */; }; 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; @@ -52,9 +53,10 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 1CCCE971B34B1EF0E9C23CAC /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; - 33CC10ED2044A3C60003C045 /* stream_chat_v1.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "stream_chat_v1.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10ED2044A3C60003C045 /* stream_chat_v1.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = stream_chat_v1.app; sourceTree = BUILT_PRODUCTS_DIR; }; 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; @@ -66,8 +68,11 @@ 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 782D013032AAC6BDCC56A273 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 929AC42CE2CDA27FE9235234 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + D4F4A1B883B395E86A7B745A /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -75,6 +80,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 1E52A3376056853520695B44 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -99,6 +105,7 @@ 33CEB47122A05771004F2AC0 /* Flutter */, 33CC10EE2044A3C60003C045 /* Products */, D73912EC22F37F3D000D13A0 /* Frameworks */, + 3A21EEB06B73EAB5B839B688 /* Pods */, ); sourceTree = ""; }; @@ -145,9 +152,21 @@ path = Runner; sourceTree = ""; }; + 3A21EEB06B73EAB5B839B688 /* Pods */ = { + isa = PBXGroup; + children = ( + 1CCCE971B34B1EF0E9C23CAC /* Pods-Runner.debug.xcconfig */, + 929AC42CE2CDA27FE9235234 /* Pods-Runner.release.xcconfig */, + D4F4A1B883B395E86A7B745A /* Pods-Runner.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; D73912EC22F37F3D000D13A0 /* Frameworks */ = { isa = PBXGroup; children = ( + 782D013032AAC6BDCC56A273 /* Pods_Runner.framework */, ); name = Frameworks; sourceTree = ""; @@ -159,11 +178,13 @@ isa = PBXNativeTarget; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + 1A517F7352EDBCB64556EE14 /* [CP] Check Pods Manifest.lock */, 33CC10E92044A3C60003C045 /* Sources */, 33CC10EA2044A3C60003C045 /* Frameworks */, 33CC10EB2044A3C60003C045 /* Resources */, 33CC110E2044A8840003C045 /* Bundle Framework */, 3399D490228B24CF009A79C7 /* ShellScript */, + 5EA8C195DB09CB61CDB56B17 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -233,6 +254,28 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 1A517F7352EDBCB64556EE14 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; 3399D490228B24CF009A79C7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -270,6 +313,23 @@ shellPath = /bin/sh; shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; }; + 5EA8C195DB09CB61CDB56B17 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ diff --git a/stream_chat_v1/macos/Runner.xcworkspace/contents.xcworkspacedata b/stream_chat_v1/macos/Runner.xcworkspace/contents.xcworkspacedata index 1d526a16ed..21a3cc14c7 100644 --- a/stream_chat_v1/macos/Runner.xcworkspace/contents.xcworkspacedata +++ b/stream_chat_v1/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + diff --git a/stream_chat_v1/macos/Runner/DebugProfile.entitlements b/stream_chat_v1/macos/Runner/DebugProfile.entitlements index dddb8a30c8..681e73fe27 100644 --- a/stream_chat_v1/macos/Runner/DebugProfile.entitlements +++ b/stream_chat_v1/macos/Runner/DebugProfile.entitlements @@ -8,5 +8,9 @@ com.apple.security.network.server + com.apple.security.network.client + + com.apple.security.files.user-selected.read-write + diff --git a/stream_chat_v1/macos/Runner/Release.entitlements b/stream_chat_v1/macos/Runner/Release.entitlements index 852fa1a472..43a8b8c70d 100644 --- a/stream_chat_v1/macos/Runner/Release.entitlements +++ b/stream_chat_v1/macos/Runner/Release.entitlements @@ -4,5 +4,9 @@ com.apple.security.app-sandbox + com.apple.security.network.client + + com.apple.security.files.user-selected.read-write + diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index dae63d7920..ec7999ddb0 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -13,17 +13,17 @@ dependencies: stream_chat_flutter: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop + ref: v5 path: packages/stream_chat_flutter stream_chat_persistence: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop + ref: v5 path: packages/stream_chat_persistence stream_chat_localizations: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop + ref: v5 path: packages/stream_chat_localizations flutter_local_notifications: ^9.0.0 flutter_svg: ^1.0.3 @@ -34,6 +34,7 @@ dependencies: lottie: ^1.2.1 collection: ^1.15.0 sentry_flutter: ^6.5.0 + flutter_slidable: ^2.0.0 dev_dependencies: flutter_launcher_icons: ^0.9.2 @@ -43,17 +44,17 @@ dependency_overrides: stream_chat: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop + ref: v5 path: packages/stream_chat stream_chat_flutter_core: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop + ref: v5 path: packages/stream_chat_flutter_core stream_chat_flutter: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop + ref: v5 path: packages/stream_chat_flutter flutter: From 3b667840c928c15852c8c790022f3c252061b244 Mon Sep 17 00:00:00 2001 From: Gordon Hayes Date: Wed, 5 Oct 2022 16:34:11 +0200 Subject: [PATCH 129/172] chore: update branch --- stream_chat_v1/pubspec.yaml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index ec7999ddb0..894d1aa32a 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -1,10 +1,10 @@ name: example description: A new Flutter project. -publish_to: 'none' +publish_to: "none" version: 2.1.1 environment: - sdk: '>=2.17.0 <3.0.0' + sdk: ">=2.17.0 <3.0.0" dependencies: flutter_app_badger: ^1.3.0 @@ -13,17 +13,17 @@ dependencies: stream_chat_flutter: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: v5 + ref: develop path: packages/stream_chat_flutter stream_chat_persistence: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: v5 + ref: develop path: packages/stream_chat_persistence stream_chat_localizations: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: v5 + ref: develop path: packages/stream_chat_localizations flutter_local_notifications: ^9.0.0 flutter_svg: ^1.0.3 @@ -44,17 +44,17 @@ dependency_overrides: stream_chat: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: v5 + ref: develop path: packages/stream_chat stream_chat_flutter_core: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: v5 + ref: develop path: packages/stream_chat_flutter_core stream_chat_flutter: git: url: https://github.com/GetStream/stream-chat-flutter.git - ref: v5 + ref: develop path: packages/stream_chat_flutter flutter: From c5fbeef1bb474c6a328d63045de3c4b85b705834 Mon Sep 17 00:00:00 2001 From: Gordon Hayes Date: Thu, 6 Oct 2022 12:42:57 +0200 Subject: [PATCH 130/172] style: provide folder structure --- stream_chat_v1/lib/app.dart | 182 ++++++++++++++++++ stream_chat_v1/lib/main.dart | 181 +---------------- .../{ => pages}/advanced_options_page.dart | 8 +- .../channel_file_display_screen.dart | 2 +- .../lib/{ => pages}/channel_list_page.dart | 6 +- .../channel_media_display_screen.dart | 2 +- .../lib/{ => pages}/channel_page.dart | 2 +- .../lib/{ => pages}/chat_info_screen.dart | 9 +- .../lib/{ => pages}/choose_user_page.dart | 12 +- .../group_chat_details_screen.dart | 4 +- .../lib/{ => pages}/group_info_screen.dart | 4 +- stream_chat_v1/lib/{ => pages}/home_page.dart | 4 +- .../lib/{ => pages}/new_chat_screen.dart | 6 +- .../{ => pages}/new_group_chat_screen.dart | 7 +- .../{ => pages}/pinned_messages_screen.dart | 2 +- .../lib/{ => pages}/splash_screen.dart | 0 .../lib/{ => pages}/thread_page.dart | 0 .../lib/{ => pages}/user_mentions_page.dart | 2 +- stream_chat_v1/lib/routes/app_routes.dart | 24 +-- stream_chat_v1/lib/routes/routes.dart | 4 +- .../lib/{ => utils}/app_config.dart | 3 + .../lib/{ => utils}/localizations.dart | 0 .../{ => utils}/notifications_service.dart | 4 +- .../lib/{ => widgets}/channel_list.dart | 10 +- .../{ => widgets}/chips_input_text_field.dart | 2 +- .../lib/{ => widgets}/search_text_field.dart | 0 .../lib/{ => widgets}/stream_version.dart | 2 +- 27 files changed, 244 insertions(+), 238 deletions(-) create mode 100644 stream_chat_v1/lib/app.dart rename stream_chat_v1/lib/{ => pages}/advanced_options_page.dart (98%) rename stream_chat_v1/lib/{ => pages}/channel_file_display_screen.dart (98%) rename stream_chat_v1/lib/{ => pages}/channel_list_page.dart (98%) rename stream_chat_v1/lib/{ => pages}/channel_media_display_screen.dart (99%) rename stream_chat_v1/lib/{ => pages}/channel_page.dart (99%) rename stream_chat_v1/lib/{ => pages}/chat_info_screen.dart (98%) rename stream_chat_v1/lib/{ => pages}/choose_user_page.dart (96%) rename stream_chat_v1/lib/{ => pages}/group_chat_details_screen.dart (99%) rename stream_chat_v1/lib/{ => pages}/group_info_screen.dart (99%) rename stream_chat_v1/lib/{ => pages}/home_page.dart (96%) rename stream_chat_v1/lib/{ => pages}/new_chat_screen.dart (99%) rename stream_chat_v1/lib/{ => pages}/new_group_chat_screen.dart (98%) rename stream_chat_v1/lib/{ => pages}/pinned_messages_screen.dart (98%) rename stream_chat_v1/lib/{ => pages}/splash_screen.dart (100%) rename stream_chat_v1/lib/{ => pages}/thread_page.dart (100%) rename stream_chat_v1/lib/{ => pages}/user_mentions_page.dart (98%) rename stream_chat_v1/lib/{ => utils}/app_config.dart (96%) rename stream_chat_v1/lib/{ => utils}/localizations.dart (100%) rename stream_chat_v1/lib/{ => utils}/notifications_service.dart (95%) rename stream_chat_v1/lib/{ => widgets}/channel_list.dart (98%) rename stream_chat_v1/lib/{ => widgets}/chips_input_text_field.dart (99%) rename stream_chat_v1/lib/{ => widgets}/search_text_field.dart (100%) rename stream_chat_v1/lib/{ => widgets}/stream_version.dart (95%) diff --git a/stream_chat_v1/lib/app.dart b/stream_chat_v1/lib/app.dart new file mode 100644 index 0000000000..c1a6f40bc4 --- /dev/null +++ b/stream_chat_v1/lib/app.dart @@ -0,0 +1,182 @@ +import 'dart:async'; + +import 'package:example/pages/choose_user_page.dart'; +import 'package:example/pages/home_page.dart'; +import 'package:example/utils/localizations.dart'; +import 'package:example/pages/splash_screen.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; +import 'package:stream_chat_localizations/stream_chat_localizations.dart'; +import 'package:stream_chat_persistence/stream_chat_persistence.dart'; +import 'package:streaming_shared_preferences/streaming_shared_preferences.dart'; + +import 'routes/app_routes.dart'; +import 'routes/routes.dart'; + +final chatPersistentClient = StreamChatPersistenceClient( + logLevel: Level.SEVERE, + connectionMode: ConnectionMode.regular, +); + +void sampleAppLogHandler(LogRecord record) async { + if (kDebugMode) StreamChatClient.defaultLogHandler(record); + + // report errors to setnry.io + if (record.error != null || record.stackTrace != null) { + await Sentry.captureException( + record.error, + stackTrace: record.stackTrace, + ); + } +} + +StreamChatClient buildStreamChatClient( + String apiKey, { + Level logLevel = Level.INFO, +}) { + return StreamChatClient( + apiKey, + logLevel: logLevel, + logHandlerFunction: sampleAppLogHandler, + )..chatPersistenceClient = chatPersistentClient; +} + +class MyApp extends StatefulWidget { + @override + _MyAppState createState() => _MyAppState(); +} + +class _MyAppState extends State + with SplashScreenStateMixin, TickerProviderStateMixin { + InitData? _initData; + + Future _initConnection() async { + String? apiKey, userId, token; + + if (!kIsWeb) { + final secureStorage = FlutterSecureStorage(); + apiKey = await secureStorage.read(key: kStreamApiKey); + userId = await secureStorage.read(key: kStreamUserId); + token = await secureStorage.read(key: kStreamToken); + } + + final client = buildStreamChatClient(apiKey ?? kStreamApiKey); + + if (userId != null && token != null) { + await client.connectUser( + User(id: userId), + token, + ); + } + + final prefs = await StreamingSharedPreferences.instance; + + return InitData(client, prefs); + } + + @override + void initState() { + final timeOfStartMs = DateTime.now().millisecondsSinceEpoch; + + _initConnection().then( + (initData) { + setState(() { + _initData = initData; + }); + + final now = DateTime.now().millisecondsSinceEpoch; + + if (now - timeOfStartMs > 1500) { + SchedulerBinding.instance.addPostFrameCallback((timeStamp) { + forwardAnimations(); + }); + } else { + Future.delayed(Duration(milliseconds: 1500)).then((value) { + forwardAnimations(); + }); + } + }, + ); + + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Stack( + alignment: Alignment.center, + children: [ + if (_initData != null) + PreferenceBuilder( + preference: _initData!.preferences.getInt( + 'theme', + defaultValue: 0, + ), + builder: (context, snapshot) => MaterialApp( + theme: ThemeData.light(), + darkTheme: ThemeData.dark(), + themeMode: { + -1: ThemeMode.dark, + 0: ThemeMode.system, + 1: ThemeMode.light, + }[snapshot], + supportedLocales: const [ + Locale('en'), + Locale('it'), + ], + localizationsDelegates: const [ + AppLocalizationsDelegate(), + GlobalStreamChatLocalizations.delegate, + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + ], + builder: (context, child) => StreamChatConfiguration( + data: StreamChatConfigurationData(), + child: StreamChatTheme( + data: StreamChatThemeData( + brightness: Theme.of(context).brightness, + ), + child: child!, + ), + ), + onGenerateRoute: AppRoutes.generateRoute, + onGenerateInitialRoutes: (initialRouteName) { + if (initialRouteName == Routes.HOME) { + return [ + AppRoutes.generateRoute( + RouteSettings( + name: Routes.HOME, + arguments: HomePageArgs(_initData!.client), + ), + )! + ]; + } + return [ + AppRoutes.generateRoute( + RouteSettings( + name: Routes.CHOOSE_USER, + ), + )! + ]; + }, + initialRoute: _initData!.client.state.currentUser == null + ? Routes.CHOOSE_USER + : Routes.HOME, + ), + ), + if (!animationCompleted) buildAnimation(), + ], + ); + } +} + +class InitData { + final StreamChatClient client; + final StreamingSharedPreferences preferences; + + InitData(this.client, this.preferences); +} diff --git a/stream_chat_v1/lib/main.dart b/stream_chat_v1/lib/main.dart index a2f5b4c84b..d60b848587 100644 --- a/stream_chat_v1/lib/main.dart +++ b/stream_chat_v1/lib/main.dart @@ -1,54 +1,13 @@ import 'dart:async'; -import 'package:example/choose_user_page.dart'; -import 'package:example/home_page.dart'; -import 'package:example/localizations.dart'; -import 'package:example/splash_screen.dart'; +import 'package:example/utils/app_config.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/scheduler.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; -import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -import 'package:stream_chat_localizations/stream_chat_localizations.dart'; -import 'package:stream_chat_persistence/stream_chat_persistence.dart'; -import 'package:streaming_shared_preferences/streaming_shared_preferences.dart'; -import 'routes/app_routes.dart'; -import 'routes/routes.dart'; - -final chatPersistentClient = StreamChatPersistenceClient( - logLevel: Level.SEVERE, - connectionMode: ConnectionMode.regular, -); - -void sampleAppLogHandler(LogRecord record) async { - if (kDebugMode) StreamChatClient.defaultLogHandler(record); - - // report errors to sentry - if (record.error != null || record.stackTrace != null) { - await Sentry.captureException( - record.error, - stackTrace: record.stackTrace, - ); - } -} - -StreamChatClient buildStreamChatClient( - String apiKey, { - Level logLevel = Level.INFO, -}) { - return StreamChatClient( - apiKey, - logLevel: logLevel, - logHandlerFunction: sampleAppLogHandler, - )..chatPersistenceClient = chatPersistentClient; -} +import 'package:example/app.dart'; void main() async { - const sentryDsn = - 'https://6381ef88de4140db8f5e25ab37e0f08c@o1213503.ingest.sentry.io/6352870'; - /// Captures errors reported by the Flutter framework. FlutterError.onError = (FlutterErrorDetails details) { if (kDebugMode) { @@ -82,139 +41,3 @@ void main() async { _reportError, ); } - -class MyApp extends StatefulWidget { - @override - _MyAppState createState() => _MyAppState(); -} - -class _MyAppState extends State - with SplashScreenStateMixin, TickerProviderStateMixin { - InitData? _initData; - - Future _initConnection() async { - String? apiKey, userId, token; - - if (!kIsWeb) { - final secureStorage = FlutterSecureStorage(); - apiKey = await secureStorage.read(key: kStreamApiKey); - userId = await secureStorage.read(key: kStreamUserId); - token = await secureStorage.read(key: kStreamToken); - } - - final client = buildStreamChatClient(apiKey ?? kStreamApiKey); - - if (userId != null && token != null) { - await client.connectUser( - User(id: userId), - token, - ); - } - - final prefs = await StreamingSharedPreferences.instance; - - return InitData(client, prefs); - } - - @override - void initState() { - final timeOfStartMs = DateTime.now().millisecondsSinceEpoch; - - _initConnection().then( - (initData) { - setState(() { - _initData = initData; - }); - - final now = DateTime.now().millisecondsSinceEpoch; - - if (now - timeOfStartMs > 1500) { - SchedulerBinding.instance.addPostFrameCallback((timeStamp) { - forwardAnimations(); - }); - } else { - Future.delayed(Duration(milliseconds: 1500)).then((value) { - forwardAnimations(); - }); - } - }, - ); - - super.initState(); - } - - @override - Widget build(BuildContext context) { - return Stack( - alignment: Alignment.center, - children: [ - if (_initData != null) - PreferenceBuilder( - preference: _initData!.preferences.getInt( - 'theme', - defaultValue: 0, - ), - builder: (context, snapshot) => MaterialApp( - theme: ThemeData.light(), - darkTheme: ThemeData.dark(), - themeMode: { - -1: ThemeMode.dark, - 0: ThemeMode.system, - 1: ThemeMode.light, - }[snapshot], - supportedLocales: const [ - Locale('en'), - Locale('it'), - ], - localizationsDelegates: const [ - AppLocalizationsDelegate(), - GlobalStreamChatLocalizations.delegate, - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - ], - builder: (context, child) => StreamChatConfiguration( - data: StreamChatConfigurationData(), - child: StreamChatTheme( - data: StreamChatThemeData( - brightness: Theme.of(context).brightness, - ), - child: child!, - ), - ), - onGenerateRoute: AppRoutes.generateRoute, - onGenerateInitialRoutes: (initialRouteName) { - if (initialRouteName == Routes.HOME) { - return [ - AppRoutes.generateRoute( - RouteSettings( - name: Routes.HOME, - arguments: HomePageArgs(_initData!.client), - ), - )! - ]; - } - return [ - AppRoutes.generateRoute( - RouteSettings( - name: Routes.CHOOSE_USER, - ), - )! - ]; - }, - initialRoute: _initData!.client.state.currentUser == null - ? Routes.CHOOSE_USER - : Routes.HOME, - ), - ), - if (!animationCompleted) buildAnimation(), - ], - ); - } -} - -class InitData { - final StreamChatClient client; - final StreamingSharedPreferences preferences; - - InitData(this.client, this.preferences); -} diff --git a/stream_chat_v1/lib/advanced_options_page.dart b/stream_chat_v1/lib/pages/advanced_options_page.dart similarity index 98% rename from stream_chat_v1/lib/advanced_options_page.dart rename to stream_chat_v1/lib/pages/advanced_options_page.dart index f442453f91..566e54a992 100644 --- a/stream_chat_v1/lib/advanced_options_page.dart +++ b/stream_chat_v1/lib/pages/advanced_options_page.dart @@ -1,13 +1,13 @@ -import 'package:example/home_page.dart'; -import 'package:example/localizations.dart'; +import 'package:example/app.dart'; +import 'package:example/pages/home_page.dart'; +import 'package:example/utils/localizations.dart'; import 'package:example/routes/routes.dart'; -import 'package:example/stream_version.dart'; +import 'package:example/widgets/stream_version.dart'; import 'package:flutter/material.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'choose_user_page.dart'; -import 'main.dart'; class AdvancedOptionsPage extends StatefulWidget { @override diff --git a/stream_chat_v1/lib/channel_file_display_screen.dart b/stream_chat_v1/lib/pages/channel_file_display_screen.dart similarity index 98% rename from stream_chat_v1/lib/channel_file_display_screen.dart rename to stream_chat_v1/lib/pages/channel_file_display_screen.dart index e7be692146..e08d6361fd 100644 --- a/stream_chat_v1/lib/channel_file_display_screen.dart +++ b/stream_chat_v1/lib/pages/channel_file_display_screen.dart @@ -1,4 +1,4 @@ -import 'package:example/localizations.dart'; +import 'package:example/utils/localizations.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:video_player/video_player.dart'; diff --git a/stream_chat_v1/lib/channel_list_page.dart b/stream_chat_v1/lib/pages/channel_list_page.dart similarity index 98% rename from stream_chat_v1/lib/channel_list_page.dart rename to stream_chat_v1/lib/pages/channel_list_page.dart index 6a9438f409..128f2c748b 100644 --- a/stream_chat_v1/lib/channel_list_page.dart +++ b/stream_chat_v1/lib/pages/channel_list_page.dart @@ -1,8 +1,8 @@ import 'dart:async'; -import 'package:example/localizations.dart'; +import 'package:example/utils/localizations.dart'; import 'package:example/routes/routes.dart'; -import 'package:example/user_mentions_page.dart'; +import 'package:example/pages/user_mentions_page.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_app_badger/flutter_app_badger.dart'; @@ -10,7 +10,7 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:streaming_shared_preferences/streaming_shared_preferences.dart'; -import 'channel_list.dart'; +import 'package:example/widgets/channel_list.dart'; class ChannelListPage extends StatefulWidget { const ChannelListPage({ diff --git a/stream_chat_v1/lib/channel_media_display_screen.dart b/stream_chat_v1/lib/pages/channel_media_display_screen.dart similarity index 99% rename from stream_chat_v1/lib/channel_media_display_screen.dart rename to stream_chat_v1/lib/pages/channel_media_display_screen.dart index d3789edc9c..efc6423601 100644 --- a/stream_chat_v1/lib/channel_media_display_screen.dart +++ b/stream_chat_v1/lib/pages/channel_media_display_screen.dart @@ -1,4 +1,4 @@ -import 'package:example/localizations.dart'; +import 'package:example/utils/localizations.dart'; import 'package:example/routes/routes.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; diff --git a/stream_chat_v1/lib/channel_page.dart b/stream_chat_v1/lib/pages/channel_page.dart similarity index 99% rename from stream_chat_v1/lib/channel_page.dart rename to stream_chat_v1/lib/pages/channel_page.dart index 9a4b0571e2..f6e7af54c6 100644 --- a/stream_chat_v1/lib/channel_page.dart +++ b/stream_chat_v1/lib/pages/channel_page.dart @@ -1,6 +1,6 @@ import 'package:collection/collection.dart'; import 'package:example/routes/routes.dart'; -import 'package:example/thread_page.dart'; +import 'package:example/pages/thread_page.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; diff --git a/stream_chat_v1/lib/chat_info_screen.dart b/stream_chat_v1/lib/pages/chat_info_screen.dart similarity index 98% rename from stream_chat_v1/lib/chat_info_screen.dart rename to stream_chat_v1/lib/pages/chat_info_screen.dart index 90c2f07cf0..f484e9e42c 100644 --- a/stream_chat_v1/lib/chat_info_screen.dart +++ b/stream_chat_v1/lib/pages/chat_info_screen.dart @@ -1,11 +1,10 @@ -import 'package:example/localizations.dart'; +import 'package:example/pages/channel_file_display_screen.dart'; +import 'package:example/utils/localizations.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; - -import 'channel_file_display_screen.dart'; -import 'channel_media_display_screen.dart'; -import 'pinned_messages_screen.dart'; +import 'package:example/pages/channel_media_display_screen.dart'; +import 'package:example/pages/pinned_messages_screen.dart'; /// Detail screen for a 1:1 chat correspondence class ChatInfoScreen extends StatefulWidget { diff --git a/stream_chat_v1/lib/choose_user_page.dart b/stream_chat_v1/lib/pages/choose_user_page.dart similarity index 96% rename from stream_chat_v1/lib/choose_user_page.dart rename to stream_chat_v1/lib/pages/choose_user_page.dart index 611804c523..8aabf80441 100644 --- a/stream_chat_v1/lib/choose_user_page.dart +++ b/stream_chat_v1/lib/pages/choose_user_page.dart @@ -1,15 +1,15 @@ -import 'package:example/app_config.dart'; -import 'package:example/home_page.dart'; -import 'package:example/localizations.dart'; -import 'package:example/stream_version.dart'; +import 'package:example/app.dart'; +import 'package:example/utils/app_config.dart'; +import 'package:example/pages/home_page.dart'; +import 'package:example/utils/localizations.dart'; +import 'package:example/widgets/stream_version.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -import 'main.dart'; -import 'routes/routes.dart'; +import '../routes/routes.dart'; const kStreamApiKey = 'STREAM_API_KEY'; const kStreamUserId = 'STREAM_USER_ID'; diff --git a/stream_chat_v1/lib/group_chat_details_screen.dart b/stream_chat_v1/lib/pages/group_chat_details_screen.dart similarity index 99% rename from stream_chat_v1/lib/group_chat_details_screen.dart rename to stream_chat_v1/lib/pages/group_chat_details_screen.dart index 6859f2b67d..5215f3d97c 100644 --- a/stream_chat_v1/lib/group_chat_details_screen.dart +++ b/stream_chat_v1/lib/pages/group_chat_details_screen.dart @@ -1,9 +1,9 @@ -import 'package:example/localizations.dart'; +import 'package:example/utils/localizations.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'channel_page.dart'; -import 'routes/routes.dart'; +import '../routes/routes.dart'; class GroupChatDetailsScreen extends StatefulWidget { final List? selectedUsers; diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/pages/group_info_screen.dart similarity index 99% rename from stream_chat_v1/lib/group_info_screen.dart rename to stream_chat_v1/lib/pages/group_info_screen.dart index d28356992a..dba8963244 100644 --- a/stream_chat_v1/lib/group_info_screen.dart +++ b/stream_chat_v1/lib/pages/group_info_screen.dart @@ -1,12 +1,12 @@ import 'dart:async'; import 'package:collection/collection.dart' show IterableExtension; -import 'package:example/localizations.dart'; +import 'package:example/pages/channel_file_display_screen.dart'; +import 'package:example/utils/localizations.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -import 'channel_file_display_screen.dart'; import 'channel_media_display_screen.dart'; import 'channel_page.dart'; import 'chat_info_screen.dart'; diff --git a/stream_chat_v1/lib/home_page.dart b/stream_chat_v1/lib/pages/home_page.dart similarity index 96% rename from stream_chat_v1/lib/home_page.dart rename to stream_chat_v1/lib/pages/home_page.dart index e37b8622bc..48eae88319 100644 --- a/stream_chat_v1/lib/home_page.dart +++ b/stream_chat_v1/lib/pages/home_page.dart @@ -1,7 +1,7 @@ import 'dart:async'; -import 'package:example/channel_page.dart'; -import 'package:example/notifications_service.dart'; +import 'package:example/pages/channel_page.dart'; +import 'package:example/utils/notifications_service.dart'; import 'package:example/routes/app_routes.dart'; import 'package:example/routes/routes.dart'; import 'package:flutter/material.dart'; diff --git a/stream_chat_v1/lib/new_chat_screen.dart b/stream_chat_v1/lib/pages/new_chat_screen.dart similarity index 99% rename from stream_chat_v1/lib/new_chat_screen.dart rename to stream_chat_v1/lib/pages/new_chat_screen.dart index f0ce09815e..57ebd02f6c 100644 --- a/stream_chat_v1/lib/new_chat_screen.dart +++ b/stream_chat_v1/lib/pages/new_chat_screen.dart @@ -1,12 +1,12 @@ import 'dart:async'; -import 'package:example/localizations.dart'; +import 'package:example/utils/localizations.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'channel_page.dart'; -import 'chips_input_text_field.dart'; -import 'routes/routes.dart'; +import '../widgets/chips_input_text_field.dart'; +import '../routes/routes.dart'; class NewChatScreen extends StatefulWidget { @override diff --git a/stream_chat_v1/lib/new_group_chat_screen.dart b/stream_chat_v1/lib/pages/new_group_chat_screen.dart similarity index 98% rename from stream_chat_v1/lib/new_group_chat_screen.dart rename to stream_chat_v1/lib/pages/new_group_chat_screen.dart index ff0c175782..9948448a1f 100644 --- a/stream_chat_v1/lib/new_group_chat_screen.dart +++ b/stream_chat_v1/lib/pages/new_group_chat_screen.dart @@ -1,11 +1,11 @@ import 'dart:async'; -import 'package:example/localizations.dart'; +import 'package:example/utils/localizations.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -import 'routes/routes.dart'; -import 'search_text_field.dart'; +import '../routes/routes.dart'; +import '../widgets/search_text_field.dart'; class NewGroupChatScreen extends StatefulWidget { @override @@ -251,7 +251,6 @@ class _NewGroupChatScreenState extends State { onPanDown: (_) => FocusScope.of(context).unfocus(), child: StreamUserListView( controller: userListController, - // groupAlphabetically: _isSearchActive ? false : true, itemBuilder: (context, items, index, defaultWidget) { return defaultWidget.copyWith( selected: _selectedUsers.contains(items[index]), diff --git a/stream_chat_v1/lib/pinned_messages_screen.dart b/stream_chat_v1/lib/pages/pinned_messages_screen.dart similarity index 98% rename from stream_chat_v1/lib/pinned_messages_screen.dart rename to stream_chat_v1/lib/pages/pinned_messages_screen.dart index 7ab6d98c60..bdf359a252 100644 --- a/stream_chat_v1/lib/pinned_messages_screen.dart +++ b/stream_chat_v1/lib/pages/pinned_messages_screen.dart @@ -1,4 +1,4 @@ -import 'package:example/localizations.dart'; +import 'package:example/utils/localizations.dart'; import 'package:example/routes/routes.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; diff --git a/stream_chat_v1/lib/splash_screen.dart b/stream_chat_v1/lib/pages/splash_screen.dart similarity index 100% rename from stream_chat_v1/lib/splash_screen.dart rename to stream_chat_v1/lib/pages/splash_screen.dart diff --git a/stream_chat_v1/lib/thread_page.dart b/stream_chat_v1/lib/pages/thread_page.dart similarity index 100% rename from stream_chat_v1/lib/thread_page.dart rename to stream_chat_v1/lib/pages/thread_page.dart diff --git a/stream_chat_v1/lib/user_mentions_page.dart b/stream_chat_v1/lib/pages/user_mentions_page.dart similarity index 98% rename from stream_chat_v1/lib/user_mentions_page.dart rename to stream_chat_v1/lib/pages/user_mentions_page.dart index 3dcbab6498..8b8bfa442d 100644 --- a/stream_chat_v1/lib/user_mentions_page.dart +++ b/stream_chat_v1/lib/pages/user_mentions_page.dart @@ -1,4 +1,4 @@ -import 'package:example/localizations.dart'; +import 'package:example/utils/localizations.dart'; import 'package:example/routes/routes.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; diff --git a/stream_chat_v1/lib/routes/app_routes.dart b/stream_chat_v1/lib/routes/app_routes.dart index 4f913b48db..cea1ebe04f 100644 --- a/stream_chat_v1/lib/routes/app_routes.dart +++ b/stream_chat_v1/lib/routes/app_routes.dart @@ -1,19 +1,19 @@ import 'package:collection/collection.dart'; -import 'package:example/channel_list_page.dart'; +import 'package:example/pages/channel_list_page.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -import '../advanced_options_page.dart'; -import '../channel_page.dart'; -import '../chat_info_screen.dart'; -import '../choose_user_page.dart'; -import '../group_chat_details_screen.dart'; -import '../group_info_screen.dart'; -import '../home_page.dart'; -import '../main.dart'; -import '../new_chat_screen.dart'; -import '../new_group_chat_screen.dart'; -import '../thread_page.dart'; +import '../app.dart'; +import '../pages/advanced_options_page.dart'; +import '../pages/channel_page.dart'; +import '../pages/chat_info_screen.dart'; +import '../pages/choose_user_page.dart'; +import '../pages/group_chat_details_screen.dart'; +import '../pages/group_info_screen.dart'; +import '../pages/home_page.dart'; +import '../pages/new_chat_screen.dart'; +import '../pages/new_group_chat_screen.dart'; +import '../pages/thread_page.dart'; import 'routes.dart'; class AppRoutes { diff --git a/stream_chat_v1/lib/routes/routes.dart b/stream_chat_v1/lib/routes/routes.dart index 239bd282b0..8ba28933e2 100644 --- a/stream_chat_v1/lib/routes/routes.dart +++ b/stream_chat_v1/lib/routes/routes.dart @@ -1,5 +1,5 @@ -/// Define all the route names here -class Routes { +/// Application routes +abstract class Routes { static const String APP = '/app'; static const String HOME = '/home'; static const String CHOOSE_USER = '/choose_user'; diff --git a/stream_chat_v1/lib/app_config.dart b/stream_chat_v1/lib/utils/app_config.dart similarity index 96% rename from stream_chat_v1/lib/app_config.dart rename to stream_chat_v1/lib/utils/app_config.dart index c5fbe67171..c9771343db 100644 --- a/stream_chat_v1/lib/app_config.dart +++ b/stream_chat_v1/lib/utils/app_config.dart @@ -1,5 +1,8 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; +const sentryDsn = + 'https://6381ef88de4140db8f5e25ab37e0f08c@o1213503.ingest.sentry.io/6352870'; + const kDefaultStreamApiKey = 'kv7mcsxr24p8'; final defaultUsers = { diff --git a/stream_chat_v1/lib/localizations.dart b/stream_chat_v1/lib/utils/localizations.dart similarity index 100% rename from stream_chat_v1/lib/localizations.dart rename to stream_chat_v1/lib/utils/localizations.dart diff --git a/stream_chat_v1/lib/notifications_service.dart b/stream_chat_v1/lib/utils/notifications_service.dart similarity index 95% rename from stream_chat_v1/lib/notifications_service.dart rename to stream_chat_v1/lib/utils/notifications_service.dart index 7e32197c0c..b6cafb16c8 100644 --- a/stream_chat_v1/lib/notifications_service.dart +++ b/stream_chat_v1/lib/utils/notifications_service.dart @@ -1,5 +1,5 @@ -import 'package:example/channel_page.dart'; -import 'package:example/localizations.dart'; +import 'package:example/pages/channel_page.dart'; +import 'package:example/utils/localizations.dart'; import 'package:example/routes/routes.dart'; import 'package:flutter/material.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart' diff --git a/stream_chat_v1/lib/channel_list.dart b/stream_chat_v1/lib/widgets/channel_list.dart similarity index 98% rename from stream_chat_v1/lib/channel_list.dart rename to stream_chat_v1/lib/widgets/channel_list.dart index 39a6c0a0ce..f72ca393dc 100644 --- a/stream_chat_v1/lib/channel_list.dart +++ b/stream_chat_v1/lib/widgets/channel_list.dart @@ -1,16 +1,16 @@ import 'dart:async'; -import 'package:example/localizations.dart'; +import 'package:example/utils/localizations.dart'; import 'package:example/routes/routes.dart'; -import 'package:example/search_text_field.dart'; +import 'package:example/widgets/search_text_field.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:flutter_slidable/flutter_slidable.dart'; -import 'channel_page.dart'; -import 'chat_info_screen.dart'; -import 'group_info_screen.dart'; +import '../pages/channel_page.dart'; +import '../pages/chat_info_screen.dart'; +import '../pages/group_info_screen.dart'; class ChannelList extends StatefulWidget { @override diff --git a/stream_chat_v1/lib/chips_input_text_field.dart b/stream_chat_v1/lib/widgets/chips_input_text_field.dart similarity index 99% rename from stream_chat_v1/lib/chips_input_text_field.dart rename to stream_chat_v1/lib/widgets/chips_input_text_field.dart index 73149c4e2e..ed1f78c107 100644 --- a/stream_chat_v1/lib/chips_input_text_field.dart +++ b/stream_chat_v1/lib/widgets/chips_input_text_field.dart @@ -1,4 +1,4 @@ -import 'package:example/localizations.dart'; +import 'package:example/utils/localizations.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; diff --git a/stream_chat_v1/lib/search_text_field.dart b/stream_chat_v1/lib/widgets/search_text_field.dart similarity index 100% rename from stream_chat_v1/lib/search_text_field.dart rename to stream_chat_v1/lib/widgets/search_text_field.dart diff --git a/stream_chat_v1/lib/stream_version.dart b/stream_chat_v1/lib/widgets/stream_version.dart similarity index 95% rename from stream_chat_v1/lib/stream_version.dart rename to stream_chat_v1/lib/widgets/stream_version.dart index 47d4651fc1..2151470a9c 100644 --- a/stream_chat_v1/lib/stream_version.dart +++ b/stream_chat_v1/lib/widgets/stream_version.dart @@ -1,4 +1,4 @@ -import 'package:example/localizations.dart'; +import 'package:example/utils/localizations.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:yaml/yaml.dart'; From 898153c867b609641782ab2371fcecd8a70f4ba8 Mon Sep 17 00:00:00 2001 From: Gordon Hayes Date: Thu, 6 Oct 2022 14:31:51 +0200 Subject: [PATCH 131/172] chore: update package lints and apply fixes --- stream_chat_v1/analysis_options.yaml | 29 +++ stream_chat_v1/lib/app.dart | 14 +- stream_chat_v1/lib/main.dart | 6 +- .../lib/pages/advanced_options_page.dart | 28 +-- .../pages/channel_file_display_screen.dart | 16 +- .../lib/pages/channel_list_page.dart | 35 ++- .../pages/channel_media_display_screen.dart | 22 +- stream_chat_v1/lib/pages/channel_page.dart | 21 +- .../lib/pages/chat_info_screen.dart | 206 ++++++++---------- .../lib/pages/choose_user_page.dart | 19 +- .../lib/pages/group_chat_details_screen.dart | 27 +-- .../lib/pages/group_info_screen.dart | 114 +++++----- stream_chat_v1/lib/pages/home_page.dart | 4 +- stream_chat_v1/lib/pages/new_chat_screen.dart | 78 +++---- .../lib/pages/new_group_chat_screen.dart | 26 ++- .../lib/pages/pinned_messages_screen.dart | 14 +- stream_chat_v1/lib/pages/splash_screen.dart | 14 +- stream_chat_v1/lib/pages/thread_page.dart | 10 +- .../lib/pages/user_mentions_page.dart | 10 +- stream_chat_v1/lib/routes/app_routes.dart | 12 +- stream_chat_v1/lib/routes/routes.dart | 2 + stream_chat_v1/lib/utils/app_config.dart | 18 +- .../lib/utils/notifications_service.dart | 21 +- stream_chat_v1/lib/widgets/channel_list.dart | 18 +- .../lib/widgets/chips_input_text_field.dart | 170 +++++++-------- .../lib/widgets/search_text_field.dart | 2 +- .../lib/widgets/stream_version.dart | 2 +- stream_chat_v1/pubspec.yaml | 1 + 28 files changed, 480 insertions(+), 459 deletions(-) create mode 100644 stream_chat_v1/analysis_options.yaml diff --git a/stream_chat_v1/analysis_options.yaml b/stream_chat_v1/analysis_options.yaml new file mode 100644 index 0000000000..61b6c4de17 --- /dev/null +++ b/stream_chat_v1/analysis_options.yaml @@ -0,0 +1,29 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at + # https://dart-lang.github.io/linter/lints/index.html. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/stream_chat_v1/lib/app.dart b/stream_chat_v1/lib/app.dart index c1a6f40bc4..f5f64e3999 100644 --- a/stream_chat_v1/lib/app.dart +++ b/stream_chat_v1/lib/app.dart @@ -45,12 +45,14 @@ StreamChatClient buildStreamChatClient( )..chatPersistenceClient = chatPersistentClient; } -class MyApp extends StatefulWidget { +class StreamChatSampleApp extends StatefulWidget { + const StreamChatSampleApp({super.key}); + @override - _MyAppState createState() => _MyAppState(); + State createState() => _StreamChatSampleAppState(); } -class _MyAppState extends State +class _StreamChatSampleAppState extends State with SplashScreenStateMixin, TickerProviderStateMixin { InitData? _initData; @@ -58,7 +60,7 @@ class _MyAppState extends State String? apiKey, userId, token; if (!kIsWeb) { - final secureStorage = FlutterSecureStorage(); + const secureStorage = FlutterSecureStorage(); apiKey = await secureStorage.read(key: kStreamApiKey); userId = await secureStorage.read(key: kStreamUserId); token = await secureStorage.read(key: kStreamToken); @@ -95,7 +97,7 @@ class _MyAppState extends State forwardAnimations(); }); } else { - Future.delayed(Duration(milliseconds: 1500)).then((value) { + Future.delayed(const Duration(milliseconds: 1500)).then((value) { forwardAnimations(); }); } @@ -157,7 +159,7 @@ class _MyAppState extends State } return [ AppRoutes.generateRoute( - RouteSettings( + const RouteSettings( name: Routes.CHOOSE_USER, ), )! diff --git a/stream_chat_v1/lib/main.dart b/stream_chat_v1/lib/main.dart index d60b848587..87aeed700f 100644 --- a/stream_chat_v1/lib/main.dart +++ b/stream_chat_v1/lib/main.dart @@ -19,7 +19,7 @@ void main() async { } }; - Future _reportError(dynamic error, StackTrace stackTrace) async { + Future reportError(dynamic error, StackTrace stackTrace) async { // Print the exception to the console. if (kDebugMode) { // Print the full stacktrace in debug mode. @@ -36,8 +36,8 @@ void main() async { await SentryFlutter.init( (options) => options.dsn = sentryDsn, ); - runApp(MyApp()); + runApp(const StreamChatSampleApp()); }, - _reportError, + reportError, ); } diff --git a/stream_chat_v1/lib/pages/advanced_options_page.dart b/stream_chat_v1/lib/pages/advanced_options_page.dart index 566e54a992..1b03bf60fc 100644 --- a/stream_chat_v1/lib/pages/advanced_options_page.dart +++ b/stream_chat_v1/lib/pages/advanced_options_page.dart @@ -10,8 +10,10 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'choose_user_page.dart'; class AdvancedOptionsPage extends StatefulWidget { + const AdvancedOptionsPage({super.key}); + @override - _AdvancedOptionsPageState createState() => _AdvancedOptionsPageState(); + State createState() => _AdvancedOptionsPageState(); } class _AdvancedOptionsPageState extends State { @@ -88,7 +90,7 @@ class _AdvancedOptionsPageState extends State { .textHighEmphasis, ), decoration: InputDecoration( - errorStyle: TextStyle(height: 0, fontSize: 0), + errorStyle: const TextStyle(height: 0, fontSize: 0), labelStyle: TextStyle( fontSize: 14, fontWeight: FontWeight.bold, @@ -110,7 +112,7 @@ class _AdvancedOptionsPageState extends State { ), textInputAction: TextInputAction.next, ), - SizedBox(height: 8), + const SizedBox(height: 8), TextFormField( controller: _userIdController, onChanged: (_) { @@ -139,7 +141,7 @@ class _AdvancedOptionsPageState extends State { ), textInputAction: TextInputAction.next, decoration: InputDecoration( - errorStyle: TextStyle(height: 0, fontSize: 0), + errorStyle: const TextStyle(height: 0, fontSize: 0), labelStyle: TextStyle( fontWeight: FontWeight.bold, fontSize: 14, @@ -160,7 +162,7 @@ class _AdvancedOptionsPageState extends State { : AppLocalizations.of(context).userId, ), ), - SizedBox(height: 8), + const SizedBox(height: 8), TextFormField( onChanged: (_) { if (_userTokenError != null) { @@ -189,7 +191,7 @@ class _AdvancedOptionsPageState extends State { ), textInputAction: TextInputAction.next, decoration: InputDecoration( - errorStyle: TextStyle(height: 0, fontSize: 0), + errorStyle: const TextStyle(height: 0, fontSize: 0), labelStyle: TextStyle( fontWeight: FontWeight.bold, fontSize: 14, @@ -210,7 +212,7 @@ class _AdvancedOptionsPageState extends State { : AppLocalizations.of(context).userToken, ), ), - SizedBox(height: 8), + const SizedBox(height: 8), TextFormField( controller: _usernameController, textInputAction: TextInputAction.done, @@ -231,7 +233,7 @@ class _AdvancedOptionsPageState extends State { labelText: AppLocalizations.of(context).usernameOptional, ), ), - Spacer(), + const Spacer(), ElevatedButton( style: ButtonStyle( backgroundColor: MaterialStateProperty.all( @@ -286,7 +288,7 @@ class _AdvancedOptionsPageState extends State { ), height: 100, width: 100, - child: Center( + child: const Center( child: CircularProgressIndicator(), ), ), @@ -294,6 +296,7 @@ class _AdvancedOptionsPageState extends State { ); final client = buildStreamChatClient(apiKey); + final navigator = Navigator.of(context); try { await client.connectUser( @@ -303,7 +306,7 @@ class _AdvancedOptionsPageState extends State { userToken, ); - final secureStorage = FlutterSecureStorage(); + const secureStorage = FlutterSecureStorage(); secureStorage.write( key: kStreamApiKey, value: apiKey, @@ -330,8 +333,7 @@ class _AdvancedOptionsPageState extends State { return; } loading = false; - await Navigator.pushNamedAndRemoveUntil( - context, + await navigator.pushNamedAndRemoveUntil( Routes.HOME, ModalRoute.withName(Routes.HOME), arguments: HomePageArgs(client), @@ -339,7 +341,7 @@ class _AdvancedOptionsPageState extends State { } }, ), - StreamVersion(), + const StreamVersion(), ], ), ), diff --git a/stream_chat_v1/lib/pages/channel_file_display_screen.dart b/stream_chat_v1/lib/pages/channel_file_display_screen.dart index e08d6361fd..782c54199c 100644 --- a/stream_chat_v1/lib/pages/channel_file_display_screen.dart +++ b/stream_chat_v1/lib/pages/channel_file_display_screen.dart @@ -27,10 +27,10 @@ class _ChannelFileDisplayScreenState extends State { ), messageFilter: Filter.in_( 'attachments.type', - ['file'], + const ['file'], ), sort: [ - SortOption( + const SortOption( 'created_at', direction: SortOption.ASC, ), @@ -52,7 +52,7 @@ class _ChannelFileDisplayScreenState extends State { fontSize: 16.0, ), ), - leading: StreamBackButton(), + leading: const StreamBackButton(), backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, ), body: ValueListenableBuilder( @@ -73,7 +73,7 @@ class _ChannelFileDisplayScreenState extends State { size: 136.0, color: StreamChatTheme.of(context).colorTheme.disabled, ), - SizedBox(height: 16.0), + const SizedBox(height: 16.0), Text( AppLocalizations.of(context).noFiles, style: TextStyle( @@ -83,7 +83,7 @@ class _ChannelFileDisplayScreenState extends State { .textHighEmphasis, ), ), - SizedBox(height: 8.0), + const SizedBox(height: 8.0), Text( AppLocalizations.of(context).filesAppearHere, textAlign: TextAlign.center, @@ -132,10 +132,10 @@ class _ChannelFileDisplayScreenState extends State { ), ); }, - loading: () => Center( - child: const CircularProgressIndicator(), + loading: () => const Center( + child: CircularProgressIndicator(), ), - error: (_) => Offstage(), + error: (_) => const Offstage(), ); }, ), diff --git a/stream_chat_v1/lib/pages/channel_list_page.dart b/stream_chat_v1/lib/pages/channel_list_page.dart index 128f2c748b..7812d7b88c 100644 --- a/stream_chat_v1/lib/pages/channel_list_page.dart +++ b/stream_chat_v1/lib/pages/channel_list_page.dart @@ -18,7 +18,7 @@ class ChannelListPage extends StatefulWidget { }) : super(key: key); @override - _ChannelListPageState createState() => _ChannelListPageState(); + State createState() => _ChannelListPageState(); } class _ChannelListPageState extends State { @@ -37,7 +37,7 @@ class _ChannelListPageState extends State { ? StreamChatTheme.of(context).colorTheme.textHighEmphasis : Colors.grey, ), - Positioned( + const Positioned( top: -3, right: -16, child: StreamUnreadIndicator(), @@ -66,7 +66,7 @@ class _ChannelListPageState extends State { Widget build(BuildContext context) { final user = StreamChat.of(context).currentUser; if (user == null) { - return Offstage(); + return const Offstage(); } return Scaffold( backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, @@ -99,7 +99,7 @@ class _ChannelListPageState extends State { ), body: IndexedStack( index: _currentIndex, - children: [ + children: const [ ChannelList(), UserMentionsPage(), ], @@ -164,13 +164,14 @@ class LeftDrawer extends StatelessWidget { StreamUserAvatar( user: user, showOnlineStatus: false, - constraints: BoxConstraints.tight(Size.fromRadius(20)), + constraints: + BoxConstraints.tight(const Size.fromRadius(20)), ), Padding( padding: const EdgeInsets.only(left: 16.0), child: Text( user.name, - style: TextStyle( + style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, ), @@ -194,7 +195,7 @@ class LeftDrawer extends StatelessWidget { }, title: Text( AppLocalizations.of(context).newDirectMessage, - style: TextStyle( + style: const TextStyle( fontSize: 14.5, ), ), @@ -214,7 +215,7 @@ class LeftDrawer extends StatelessWidget { }, title: Text( AppLocalizations.of(context).newGroup, - style: TextStyle( + style: const TextStyle( fontSize: 14.5, ), ), @@ -224,21 +225,20 @@ class LeftDrawer extends StatelessWidget { alignment: Alignment.bottomCenter, child: ListTile( onTap: () async { + final client = StreamChat.of(context).client; + final navigator = + Navigator.of(context, rootNavigator: true); Navigator.pop(context); if (!kIsWeb) { - final secureStorage = FlutterSecureStorage(); + const secureStorage = FlutterSecureStorage(); await secureStorage.deleteAll(); } - final client = StreamChat.of(context).client; client.disconnectUser(); await client.dispose(); - await Navigator.of( - context, - rootNavigator: true, - ).pushNamedAndRemoveUntil( + await navigator.pushNamedAndRemoveUntil( Routes.CHOOSE_USER, ModalRoute.withName(Routes.CHOOSE_USER), ); @@ -251,7 +251,7 @@ class LeftDrawer extends StatelessWidget { ), title: Text( AppLocalizations.of(context).signOut, - style: TextStyle( + style: const TextStyle( fontSize: 14.5, ), ), @@ -263,12 +263,11 @@ class LeftDrawer extends StatelessWidget { .colorTheme .textLowEmphasis, onPressed: () async { + final theme = Theme.of(context); final sp = await StreamingSharedPreferences.instance; sp.setInt( 'theme', - Theme.of(context).brightness == Brightness.dark - ? 1 - : -1, + theme.brightness == Brightness.dark ? 1 : -1, ); }, ), diff --git a/stream_chat_v1/lib/pages/channel_media_display_screen.dart b/stream_chat_v1/lib/pages/channel_media_display_screen.dart index efc6423601..9017538efd 100644 --- a/stream_chat_v1/lib/pages/channel_media_display_screen.dart +++ b/stream_chat_v1/lib/pages/channel_media_display_screen.dart @@ -30,10 +30,10 @@ class _ChannelMediaDisplayScreenState extends State { ), messageFilter: Filter.in_( 'attachments.type', - ['image', 'video'], + const ['image', 'video'], ), sort: [ - SortOption( + const SortOption( 'created_at', direction: SortOption.ASC, ), @@ -55,7 +55,7 @@ class _ChannelMediaDisplayScreenState extends State { fontSize: 16.0, ), ), - leading: StreamBackButton(), + leading: const StreamBackButton(), backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, ), body: ValueListenableBuilder( @@ -73,7 +73,7 @@ class _ChannelMediaDisplayScreenState extends State { size: 136.0, color: StreamChatTheme.of(context).colorTheme.disabled, ), - SizedBox(height: 16.0), + const SizedBox(height: 16.0), Text( AppLocalizations.of(context).noMedia, style: TextStyle( @@ -83,7 +83,7 @@ class _ChannelMediaDisplayScreenState extends State { .textHighEmphasis, ), ), - SizedBox(height: 8.0), + const SizedBox(height: 8.0), Text( AppLocalizations.of(context) .photosOrVideosWillAppearHere, @@ -131,7 +131,7 @@ class _ChannelMediaDisplayScreenState extends State { } }, child: GridView.builder( - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3), itemBuilder: (context, position) { var channel = StreamChannel.of(context).channel; @@ -158,6 +158,7 @@ class _ChannelMediaDisplayScreenState extends State { onShowMessage: (m, c) async { final client = StreamChat.of(context).client; + final navigator = Navigator.of(context); final message = m; final channel = client.channel( c.type, @@ -166,8 +167,7 @@ class _ChannelMediaDisplayScreenState extends State { if (channel.state == null) { await channel.watch(); } - Navigator.pushNamed( - context, + navigator.pushNamed( Routes.CHANNEL_PAGE, arguments: ChannelPageArgs( channel: channel, @@ -197,10 +197,10 @@ class _ChannelMediaDisplayScreenState extends State { ), ); }, - loading: () => Center( - child: const CircularProgressIndicator(), + loading: () => const Center( + child: CircularProgressIndicator(), ), - error: (_) => Offstage(), + error: (_) => const Offstage(), ); }, ), diff --git a/stream_chat_v1/lib/pages/channel_page.dart b/stream_chat_v1/lib/pages/channel_page.dart index f6e7af54c6..23e57d7a6b 100644 --- a/stream_chat_v1/lib/pages/channel_page.dart +++ b/stream_chat_v1/lib/pages/channel_page.dart @@ -30,12 +30,12 @@ class ChannelPage extends StatefulWidget { }) : super(key: key); @override - _ChannelPageState createState() => _ChannelPageState(); + State createState() => _ChannelPageState(); } class _ChannelPageState extends State { FocusNode? _focusNode; - StreamMessageInputController _messageInputController = + final StreamMessageInputController _messageInputController = StreamMessageInputController(); @override @@ -64,7 +64,8 @@ class _ChannelPageState extends State { appBar: StreamChannelHeader( showTypingIndicator: false, onImageTap: () async { - var channel = StreamChannel.of(context).channel; + final channel = StreamChannel.of(context).channel; + final navigator = Navigator.of(context); if (channel.memberCount == 2 && channel.isDistinct) { final currentUser = StreamChat.of(context).currentUser; @@ -76,17 +77,17 @@ class _ChannelPageState extends State { context, MaterialPageRoute( builder: (context) => StreamChannel( + channel: channel, child: ChatInfoScreen( messageTheme: StreamChatTheme.of(context).ownMessageTheme, user: otherUser.user, ), - channel: channel, ), ), ); if (pop == true) { - Navigator.pop(context); + navigator.pop(); } } } else { @@ -94,10 +95,10 @@ class _ChannelPageState extends State { context, MaterialPageRoute( builder: (context) => StreamChannel( + channel: channel, child: GroupInfoScreen( messageTheme: StreamChatTheme.of(context).ownMessageTheme, ), - channel: channel, ), ), ); @@ -116,6 +117,7 @@ class _ChannelPageState extends State { onMessageSwiped: _reply, messageFilter: defaultFilter, messageBuilder: (context, details, messages, defaultMessage) { + final navigator = Navigator.of(context); return defaultMessage.copyWith( onReplyTap: _reply, onShowMessage: (m, c) async { @@ -128,8 +130,7 @@ class _ChannelPageState extends State { if (channel.state == null) { await channel.watch(); } - Navigator.pushReplacementNamed( - context, + navigator.pushReplacementNamed( Routes.CHANNEL_PAGE, arguments: ChannelPageArgs( channel: channel, @@ -184,8 +185,8 @@ class _ChannelPageState extends State { } bool defaultFilter(Message m) { - var _currentUser = StreamChat.of(context).currentUser; - final isMyMessage = m.user?.id == _currentUser?.id; + final currentUser = StreamChat.of(context).currentUser; + final isMyMessage = m.user?.id == currentUser?.id; final isDeletedOrShadowed = m.isDeleted == true || m.shadowed == true; if (isDeletedOrShadowed && !isMyMessage) return false; return true; diff --git a/stream_chat_v1/lib/pages/chat_info_screen.dart b/stream_chat_v1/lib/pages/chat_info_screen.dart index f484e9e42c..dc4e6c3313 100644 --- a/stream_chat_v1/lib/pages/chat_info_screen.dart +++ b/stream_chat_v1/lib/pages/chat_info_screen.dart @@ -20,7 +20,7 @@ class ChatInfoScreen extends StatefulWidget { }) : super(key: key); @override - _ChatInfoScreenState createState() => _ChatInfoScreenState(); + State createState() => _ChatInfoScreenState(); } class _ChatInfoScreenState extends State { @@ -69,7 +69,7 @@ class _ChatInfoScreenState extends State { padding: const EdgeInsets.all(16.0), child: StreamUserAvatar( user: widget.user!, - constraints: BoxConstraints.tightFor( + constraints: const BoxConstraints.tightFor( width: 72.0, height: 72.0, ), @@ -79,11 +79,12 @@ class _ChatInfoScreenState extends State { ), Text( widget.user!.name, - style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold), + style: const TextStyle( + fontSize: 16.0, fontWeight: FontWeight.bold), ), - SizedBox(height: 7.0), + const SizedBox(height: 7.0), _buildConnectedTitleState(), - SizedBox(height: 15.0), + const SizedBox(height: 15.0), StreamOptionListTile( title: '@${widget.user!.id}', tileColor: StreamChatTheme.of(context).colorTheme.appBg, @@ -103,7 +104,7 @@ class _ChatInfoScreenState extends State { ), ], ), - Positioned( + const Positioned( top: 0, left: 0, width: 58, @@ -120,18 +121,6 @@ class _ChatInfoScreenState extends State { return Column( children: [ - // _OptionListTile( - // title: 'Notifications', - // leading: StreamSvgIcon.Icon_notification( - // size: 24.0, - // color: StreamChatTheme.of(context).colorTheme.textHighEmphasis.withOpacity(0.5), - // ), - // trailing: CupertinoSwitch( - // value: true, - // onChanged: (val) {}, - // ), - // onTap: () {}, - // ), StreamBuilder( stream: StreamChannel.of(context).channel.isMutedStream, builder: (context, snapshot) { @@ -152,7 +141,7 @@ class _ChatInfoScreenState extends State { ), ), trailing: snapshot.data == null - ? CircularProgressIndicator() + ? const CircularProgressIndicator() : ValueListenableBuilder( valueListenable: mutedBool, builder: (context, value, _) { @@ -172,24 +161,6 @@ class _ChatInfoScreenState extends State { onTap: () {}, ); }), - // _OptionListTile( - // title: 'Block User', - // leading: StreamSvgIcon.Icon_user_delete( - // size: 24.0, - // color: StreamChatTheme.of(context).colorTheme.textHighEmphasis.withOpacity(0.5), - // ), - // trailing: CupertinoSwitch( - // value: widget.user.banned, - // onChanged: (val) { - // if (widget.user.banned) { - // channel.channel.shadowBan(widget.user.id, {}); - // } else { - // channel.channel.unbanUser(widget.user.id); - // } - // }, - // ), - // onTap: () {}, - // ), StreamOptionListTile( title: AppLocalizations.of(context).pinnedMessages, tileColor: StreamChatTheme.of(context).colorTheme.appBg, @@ -215,7 +186,7 @@ class _ChatInfoScreenState extends State { MaterialPageRoute( builder: (context) => StreamChannel( channel: channel, - child: PinnedMessagesScreen(), + child: const PinnedMessagesScreen(), ), ), ); @@ -338,6 +309,7 @@ class _ChatInfoScreenState extends State { } void _showDeleteDialog() async { + final streamChannel = StreamChannel.of(context); final res = await showConfirmationBottomSheet( context, title: AppLocalizations.of(context).deleteConversationTitle, @@ -348,7 +320,7 @@ class _ChatInfoScreenState extends State { color: StreamChatTheme.of(context).colorTheme.accentError, ), ); - var channel = StreamChannel.of(context).channel; + final channel = streamChannel.channel; if (res == true) { await channel.delete().then((value) { Navigator.pop(context); @@ -358,7 +330,7 @@ class _ChatInfoScreenState extends State { } Widget _buildConnectedTitleState() { - var alternativeWidget; + late Text alternativeWidget; final otherMember = widget.user; @@ -390,22 +362,22 @@ class _ChatInfoScreenState extends State { if (widget.user!.online) Material( type: MaterialType.circle, + color: StreamChatTheme.of(context).colorTheme.barsBg, child: Container( padding: const EdgeInsets.symmetric(horizontal: 8.0), - constraints: BoxConstraints.tightFor( + constraints: const BoxConstraints.tightFor( width: 24, height: 12, ), child: Material( - shape: CircleBorder(), + shape: const CircleBorder(), color: StreamChatTheme.of(context).colorTheme.accentInfo, ), ), - color: StreamChatTheme.of(context).colorTheme.barsBg, ), alternativeWidget, if (widget.user!.online) - SizedBox( + const SizedBox( width: 24.0, ), ], @@ -417,7 +389,7 @@ class _SharedGroupsScreen extends StatefulWidget { final User? mainUser; final User? otherUser; - _SharedGroupsScreen(this.mainUser, this.otherUser); + const _SharedGroupsScreen(this.mainUser, this.otherUser); @override __SharedGroupsScreenState createState() => __SharedGroupsScreenState(); @@ -439,7 +411,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { color: StreamChatTheme.of(context).colorTheme.textHighEmphasis, fontSize: 16.0), ), - leading: StreamBackButton(), + leading: const StreamBackButton(), backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, ), body: StreamBuilder>( @@ -451,7 +423,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { ), builder: (context, snapshot) { if (!snapshot.hasData) { - return Center( + return const Center( child: CircularProgressIndicator(), ); } @@ -465,7 +437,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { size: 136.0, color: StreamChatTheme.of(context).colorTheme.disabled, ), - SizedBox(height: 16.0), + const SizedBox(height: 16.0), Text( AppLocalizations.of(context).noSharedGroups, style: TextStyle( @@ -475,7 +447,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { .textHighEmphasis, ), ), - SizedBox(height: 8.0), + const SizedBox(height: 8.0), Text( AppLocalizations.of(context).groupSharedWithUserAppearHere, textAlign: TextAlign.center, @@ -515,84 +487,86 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { } Widget _buildListTile(Channel channel) { - var extraData = channel.extraData; - var members = channel.state!.members; + final extraData = channel.extraData; + final members = channel.state!.members; - var textStyle = TextStyle(fontSize: 14.0, fontWeight: FontWeight.bold); + const textStyle = TextStyle(fontSize: 14.0, fontWeight: FontWeight.bold); - return Container( + return SizedBox( height: 64.0, - child: LayoutBuilder(builder: (context, constraints) { - String? title; - if (extraData['name'] == null) { - final otherMembers = members.where((member) => - member.userId != StreamChat.of(context).currentUser!.id); - if (otherMembers.isNotEmpty) { - final maxWidth = constraints.maxWidth; - final maxChars = maxWidth / textStyle.fontSize!; - var currentChars = 0; - final currentMembers = []; - otherMembers.forEach((element) { - final newLength = currentChars + element.user!.name.length; - if (newLength < maxChars) { - currentChars = newLength; - currentMembers.add(element); + child: LayoutBuilder( + builder: (context, constraints) { + String? title; + if (extraData['name'] == null) { + final otherMembers = members.where((member) => + member.userId != StreamChat.of(context).currentUser!.id); + if (otherMembers.isNotEmpty) { + final maxWidth = constraints.maxWidth; + final maxChars = maxWidth / textStyle.fontSize!; + var currentChars = 0; + final currentMembers = []; + for (var element in otherMembers) { + final newLength = currentChars + element.user!.name.length; + if (newLength < maxChars) { + currentChars = newLength; + currentMembers.add(element); + } } - }); - final exceedingMembers = - otherMembers.length - currentMembers.length; - title = - '${currentMembers.map((e) => e.user!.name).join(', ')} ${exceedingMembers > 0 ? '+ $exceedingMembers' : ''}'; + final exceedingMembers = + otherMembers.length - currentMembers.length; + title = + '${currentMembers.map((e) => e.user!.name).join(', ')} ${exceedingMembers > 0 ? '+ $exceedingMembers' : ''}'; + } else { + title = 'No title'; + } } else { - title = 'No title'; + title = extraData['name'] as String; } - } else { - title = extraData['name'] as String; - } - return Column( - children: [ - Expanded( - child: Row( - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: StreamChannelAvatar( - channel: channel, - constraints: - BoxConstraints(maxWidth: 40.0, maxHeight: 40.0), + return Column( + children: [ + Expanded( + child: Row( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: StreamChannelAvatar( + channel: channel, + constraints: const BoxConstraints( + maxWidth: 40.0, maxHeight: 40.0), + ), ), - ), - Expanded( + Expanded( + child: Text( + title, + style: textStyle, + )), + Padding( + padding: const EdgeInsets.all(8.0), child: Text( - title, - style: textStyle, - )), - Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - '${channel.memberCount} ${AppLocalizations.of(context).members.toLowerCase()}', - style: TextStyle( - color: StreamChatTheme.of(context) - .colorTheme - .textHighEmphasis - .withOpacity(0.5)), - ), - ) - ], + '${channel.memberCount} ${AppLocalizations.of(context).members.toLowerCase()}', + style: TextStyle( + color: StreamChatTheme.of(context) + .colorTheme + .textHighEmphasis + .withOpacity(0.5)), + ), + ) + ], + ), ), - ), - Container( - height: 1.0, - color: StreamChatTheme.of(context) - .colorTheme - .textHighEmphasis - .withOpacity(.08), - ), - ], - ); - }), + Container( + height: 1.0, + color: StreamChatTheme.of(context) + .colorTheme + .textHighEmphasis + .withOpacity(.08), + ), + ], + ); + }, + ), ); } } diff --git a/stream_chat_v1/lib/pages/choose_user_page.dart b/stream_chat_v1/lib/pages/choose_user_page.dart index 8aabf80441..37969c6138 100644 --- a/stream_chat_v1/lib/pages/choose_user_page.dart +++ b/stream_chat_v1/lib/pages/choose_user_page.dart @@ -16,6 +16,8 @@ const kStreamUserId = 'STREAM_USER_ID'; const kStreamToken = 'STREAM_TOKEN'; class ChooseUserPage extends StatelessWidget { + const ChooseUserPage({super.key}); + @override Widget build(BuildContext context) { final users = defaultUsers; @@ -85,7 +87,7 @@ class ChooseUserPage extends StatelessWidget { ), height: 100, width: 100, - child: Center( + child: const Center( child: CircularProgressIndicator(), ), ), @@ -97,13 +99,15 @@ class ChooseUserPage extends StatelessWidget { logLevel: Level.INFO, )..chatPersistenceClient = chatPersistentClient; + final navigator = Navigator.of(context); + await client.connectUser( user, token, ); if (!kIsWeb) { - final secureStorage = FlutterSecureStorage(); + const secureStorage = FlutterSecureStorage(); secureStorage.write( key: kStreamApiKey, value: kDefaultStreamApiKey, @@ -117,8 +121,7 @@ class ChooseUserPage extends StatelessWidget { value: token, ); } - Navigator.pushNamedAndRemoveUntil( - context, + navigator.pushNamedAndRemoveUntil( Routes.HOME, ModalRoute.withName(Routes.HOME), arguments: HomePageArgs(client), @@ -127,7 +130,7 @@ class ChooseUserPage extends StatelessWidget { leading: StreamUserAvatar( user: user, constraints: BoxConstraints.tight( - Size.fromRadius(20), + const Size.fromRadius(20), ), ), title: Text( @@ -158,13 +161,13 @@ class ChooseUserPage extends StatelessWidget { Navigator.pushNamed(context, Routes.ADVANCED_OPTIONS); }, leading: CircleAvatar( + backgroundColor: + StreamChatTheme.of(context).colorTheme.borders, child: StreamSvgIcon.settings( color: StreamChatTheme.of(context) .colorTheme .textHighEmphasis, ), - backgroundColor: - StreamChatTheme.of(context).colorTheme.borders, ), title: Text( AppLocalizations.of(context).advancedOptions, @@ -193,7 +196,7 @@ class ChooseUserPage extends StatelessWidget { ), ), ), - StreamVersion(), + const StreamVersion(), ], ), ), diff --git a/stream_chat_v1/lib/pages/group_chat_details_screen.dart b/stream_chat_v1/lib/pages/group_chat_details_screen.dart index 5215f3d97c..9ae78eba5c 100644 --- a/stream_chat_v1/lib/pages/group_chat_details_screen.dart +++ b/stream_chat_v1/lib/pages/group_chat_details_screen.dart @@ -14,7 +14,7 @@ class GroupChatDetailsScreen extends StatefulWidget { }) : super(key: key); @override - _GroupChatDetailsScreenState createState() => _GroupChatDetailsScreenState(); + State createState() => _GroupChatDetailsScreenState(); } class _GroupChatDetailsScreenState extends State { @@ -73,7 +73,7 @@ class _GroupChatDetailsScreenState extends State { ), centerTitle: true, bottom: PreferredSize( - preferredSize: Size.fromHeight(kToolbarHeight), + preferredSize: const Size.fromHeight(kToolbarHeight), child: Padding( padding: const EdgeInsets.symmetric(vertical: 18, horizontal: 16), child: Row( @@ -87,7 +87,7 @@ class _GroupChatDetailsScreenState extends State { .textLowEmphasis, ), ), - SizedBox(width: 16), + const SizedBox(width: 16), Expanded( child: TextField( controller: _groupNameController, @@ -130,8 +130,9 @@ class _GroupChatDetailsScreenState extends State { try { final groupName = _groupNameController!.text; final client = StreamChat.of(context).client; + final navigator = Navigator.of(context); final channel = client.channel('messaging', - id: Uuid().v4(), + id: const Uuid().v4(), extraData: { 'members': [ client.state.currentUser!.id, @@ -140,8 +141,7 @@ class _GroupChatDetailsScreenState extends State { 'name': groupName, }); await channel.watch(); - Navigator.pushNamedAndRemoveUntil( - context, + navigator.pushNamedAndRemoveUntil( Routes.CHANNEL_PAGE, ModalRoute.withName(Routes.CHANNEL_LIST_PAGE), arguments: ChannelPageArgs(channel: channel), @@ -223,14 +223,15 @@ class _GroupChatDetailsScreenState extends State { key: ObjectKey(user), leading: StreamUserAvatar( user: user, - constraints: BoxConstraints.tightFor( + constraints: const BoxConstraints.tightFor( width: 40, height: 40, ), ), title: Text( user.name, - style: TextStyle(fontWeight: FontWeight.bold), + style: + const TextStyle(fontWeight: FontWeight.bold), ), contentPadding: const EdgeInsets.symmetric( horizontal: 12, @@ -273,7 +274,7 @@ class _GroupChatDetailsScreenState extends State { useRootNavigator: false, backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, context: context, - shape: RoundedRectangleBorder( + shape: const RoundedRectangleBorder( borderRadius: BorderRadius.only( topLeft: Radius.circular(16.0), topRight: Radius.circular(16.0), @@ -282,25 +283,25 @@ class _GroupChatDetailsScreenState extends State { return Column( mainAxisSize: MainAxisSize.min, children: [ - SizedBox( + const SizedBox( height: 26.0, ), StreamSvgIcon.error( color: StreamChatTheme.of(context).colorTheme.accentError, size: 24.0, ), - SizedBox( + const SizedBox( height: 26.0, ), Text( AppLocalizations.of(context).somethingWentWrongErrorMessage, style: StreamChatTheme.of(context).textTheme.headlineBold, ), - SizedBox( + const SizedBox( height: 7.0, ), Text(AppLocalizations.of(context).operationCouldNotBeCompleted), - SizedBox( + const SizedBox( height: 36.0, ), Container( diff --git a/stream_chat_v1/lib/pages/group_info_screen.dart b/stream_chat_v1/lib/pages/group_info_screen.dart index dba8963244..ccddb8a973 100644 --- a/stream_chat_v1/lib/pages/group_info_screen.dart +++ b/stream_chat_v1/lib/pages/group_info_screen.dart @@ -21,7 +21,7 @@ class GroupInfoScreen extends StatefulWidget { }) : super(key: key); @override - _GroupInfoScreenState createState() => _GroupInfoScreenState(); + State createState() => _GroupInfoScreenState(); } class _GroupInfoScreenState extends State { @@ -101,7 +101,7 @@ class _GroupInfoScreenState extends State { ], ), sort: [ - SortOption( + const SortOption( 'name', direction: 1, ), @@ -124,7 +124,7 @@ class _GroupInfoScreenState extends State { if (!snapshot.hasData) { return Container( color: StreamChatTheme.of(context).colorTheme.disabled, - child: Center(child: CircularProgressIndicator()), + child: const Center(child: CircularProgressIndicator()), ); } @@ -134,7 +134,7 @@ class _GroupInfoScreenState extends State { elevation: 1.0, toolbarHeight: 56.0, backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, - leading: StreamBackButton(), + leading: const StreamBackButton(), title: Column( children: [ StreamBuilder( @@ -171,7 +171,7 @@ class _GroupInfoScreenState extends State { overflow: TextOverflow.ellipsis, ); }), - SizedBox( + const SizedBox( height: 3.0, ), Text( @@ -242,11 +242,12 @@ class _GroupInfoScreenState extends State { children: [ ListView.builder( shrinkWrap: true, - physics: NeverScrollableScrollPhysics(), + physics: const NeverScrollableScrollPhysics(), itemCount: groupMembersLength, itemBuilder: (context, index) { final member = groupMembers[index]; return Material( + color: StreamChatTheme.of(context).colorTheme.appBg, child: InkWell( onTap: () { final userMember = groupMembers.firstWhereOrNull( @@ -255,7 +256,7 @@ class _GroupInfoScreenState extends State { _showUserInfoModal( member.user, userMember?.userId == channel.createdBy?.id); }, - child: Container( + child: SizedBox( height: 65.0, child: Column( children: [ @@ -268,7 +269,7 @@ class _GroupInfoScreenState extends State { ), child: StreamUserAvatar( user: member.user!, - constraints: BoxConstraints.tightFor( + constraints: const BoxConstraints.tightFor( height: 40.0, width: 40.0, ), @@ -281,9 +282,10 @@ class _GroupInfoScreenState extends State { children: [ Text( member.user!.name, - style: TextStyle(fontWeight: FontWeight.bold), + style: const TextStyle( + fontWeight: FontWeight.bold), ), - SizedBox( + const SizedBox( height: 1.0, ), Text( @@ -320,7 +322,6 @@ class _GroupInfoScreenState extends State { ), ), ), - color: StreamChatTheme.of(context).colorTheme.appBg, ); }, ), @@ -333,7 +334,7 @@ class _GroupInfoScreenState extends State { }, child: Material( color: StreamChatTheme.of(context).colorTheme.appBg, - child: Container( + child: SizedBox( height: 65.0, child: Column( children: [ @@ -401,7 +402,7 @@ class _GroupInfoScreenState extends State { .withOpacity(0.5)), ), ), - SizedBox( + const SizedBox( width: 7.0, ), Expanded( @@ -422,7 +423,7 @@ class _GroupInfoScreenState extends State { .colorTheme .textHighEmphasis .withOpacity(0.5))), - style: TextStyle( + style: const TextStyle( fontWeight: FontWeight.bold, height: 0.82, ), @@ -478,18 +479,6 @@ class _GroupInfoScreenState extends State { Widget _buildOptionListTiles() { return Column( children: [ - // OptionListTile( - // title: 'Notifications', - // leading: StreamSvgIcon.Icon_notification( - // size: 24.0, - // color: StreamChatTheme.of(context).colorTheme.textHighEmphasis.withOpacity(0.5), - // ), - // trailing: CupertinoSwitch( - // value: true, - // onChanged: (val) {}, - // ), - // onTap: () {}, - // ), if (channel.ownCapabilities.contains(PermissionType.muteChannel)) StreamBuilder( stream: channel.isMutedStream, @@ -513,7 +502,7 @@ class _GroupInfoScreenState extends State { ), ), trailing: snapshot.data == null - ? CircularProgressIndicator() + ? const CircularProgressIndicator() : ValueListenableBuilder( valueListenable: mutedBool, builder: (context, value, _) { @@ -558,7 +547,7 @@ class _GroupInfoScreenState extends State { MaterialPageRoute( builder: (context) => StreamChannel( channel: channel, - child: PinnedMessagesScreen(), + child: const PinnedMessagesScreen(), ), ), ); @@ -649,11 +638,14 @@ class _GroupInfoScreenState extends State { .withOpacity(0.5), ), ), - trailing: Container( + trailing: const SizedBox( height: 24.0, width: 24.0, ), onTap: () async { + final streamChannel = StreamChannel.of(context); + final streamChat = StreamChat.of(context); + final navigator = Navigator.of(context); final res = await showConfirmationBottomSheet( context, title: AppLocalizations.of(context).leaveConversation, @@ -666,10 +658,9 @@ class _GroupInfoScreenState extends State { ), ); if (res == true) { - final channel = StreamChannel.of(context).channel; - await channel - .removeMembers([StreamChat.of(context).currentUser!.id]); - Navigator.pop(context); + final channel = streamChannel.channel; + await channel.removeMembers([streamChat.currentUser!.id]); + navigator.pop(); } }, ), @@ -684,9 +675,9 @@ class _GroupInfoScreenState extends State { barrierColor: StreamChatTheme.of(context).colorTheme.overlay, builder: (context) { return Padding( - padding: EdgeInsets.only(top: 16.0, left: 8.0, right: 8.0), + padding: const EdgeInsets.only(top: 16.0, left: 8.0, right: 8.0), child: Material( - borderRadius: BorderRadius.only( + borderRadius: const BorderRadius.only( topLeft: Radius.circular(16.0), topRight: Radius.circular(16.0), ), @@ -703,16 +694,17 @@ class _GroupInfoScreenState extends State { controller: userListController, onUserTap: (user) async { _searchController!.clear(); + final navigator = Navigator.of(context); await channel.addMembers([user.id]); - Navigator.pop(context); + navigator.pop(); setState(() {}); }, emptyBuilder: (_) { return LayoutBuilder( builder: (context, viewportConstraints) { return SingleChildScrollView( - physics: AlwaysScrollableScrollPhysics(), + physics: const AlwaysScrollableScrollPhysics(), child: ConstrainedBox( constraints: BoxConstraints( minHeight: viewportConstraints.maxHeight, @@ -760,7 +752,7 @@ class _GroupInfoScreenState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( - child: Container( + child: SizedBox( height: 36, child: TextField( controller: _searchController, @@ -771,7 +763,8 @@ class _GroupInfoScreenState extends State { hintStyle: theme.textTheme.body.copyWith( color: theme.colorTheme.textLowEmphasis, ), - prefixIconConstraints: BoxConstraints.tight(Size(40, 24)), + prefixIconConstraints: + BoxConstraints.tight(const Size(40, 24)), prefixIcon: StreamSvgIcon.search( color: theme.colorTheme.textHighEmphasis, size: 24, @@ -792,12 +785,12 @@ class _GroupInfoScreenState extends State { ), ), ), - SizedBox(width: 16.0), + const SizedBox(width: 16.0), IconButton( icon: StreamSvgIcon.closeSmall( color: theme.colorTheme.textLowEmphasis, ), - constraints: BoxConstraints.tightFor( + constraints: const BoxConstraints.tightFor( height: 24, width: 24, ), @@ -829,19 +822,19 @@ class _GroupInfoScreenState extends State { child: Column( mainAxisSize: MainAxisSize.min, children: [ - SizedBox( + const SizedBox( height: 24.0, ), Center( child: Text( user!.name, - style: TextStyle( + style: const TextStyle( fontSize: 16.0, fontWeight: FontWeight.bold, ), ), ), - SizedBox( + const SizedBox( height: 5.0, ), _buildConnectedTitleState(user)!, @@ -850,7 +843,7 @@ class _GroupInfoScreenState extends State { padding: const EdgeInsets.all(16.0), child: StreamUserAvatar( user: user, - constraints: BoxConstraints.tightFor( + constraints: const BoxConstraints.tightFor( height: 64.0, width: 64.0, ), @@ -869,9 +862,10 @@ class _GroupInfoScreenState extends State { ), AppLocalizations.of(context).viewInfo, () async { - var client = StreamChat.of(context).client; + final client = StreamChat.of(context).client; + final navigator = Navigator.of(context); - var c = client.channel('messaging', extraData: { + final c = client.channel('messaging', extraData: { 'members': [ user.id, StreamChat.of(context).currentUser!.id, @@ -880,8 +874,7 @@ class _GroupInfoScreenState extends State { await c.watch(); - await Navigator.push( - context, + await navigator.push( MaterialPageRoute( builder: (context) => StreamChannel( channel: c, @@ -905,9 +898,10 @@ class _GroupInfoScreenState extends State { ), AppLocalizations.of(context).message, () async { - var client = StreamChat.of(context).client; + final client = StreamChat.of(context).client; + final navigator = Navigator.of(context); - var c = client.channel('messaging', extraData: { + final c = client.channel('messaging', extraData: { 'members': [ user.id, StreamChat.of(context).currentUser!.id, @@ -916,12 +910,11 @@ class _GroupInfoScreenState extends State { await c.watch(); - await Navigator.push( - context, + await navigator.push( MaterialPageRoute( builder: (context) => StreamChannel( channel: c, - child: ChannelPage(), + child: const ChannelPage(), ), ), ); @@ -939,6 +932,7 @@ class _GroupInfoScreenState extends State { size: 24.0, ), AppLocalizations.of(context).removeFromGroup, () async { + final navigator = Navigator.of(context); final res = await showConfirmationBottomSheet( context, title: AppLocalizations.of(context).removeMember, @@ -953,7 +947,7 @@ class _GroupInfoScreenState extends State { if (res == true) { await channel.removeMembers([user.id]); } - Navigator.pop(context); + navigator.pop(); }, color: StreamChatTheme.of(context).colorTheme.accentError), @@ -974,7 +968,7 @@ class _GroupInfoScreenState extends State { ), ); }, - shape: RoundedRectangleBorder( + shape: const RoundedRectangleBorder( borderRadius: BorderRadius.only( topLeft: Radius.circular(16.0), topRight: Radius.circular(16.0), @@ -984,7 +978,7 @@ class _GroupInfoScreenState extends State { } Widget? _buildConnectedTitleState(User? user) { - var alternativeWidget; + late Text alternativeWidget; final otherMember = user; @@ -1028,7 +1022,7 @@ class _GroupInfoScreenState extends State { height: 1.0, color: StreamChatTheme.of(context).colorTheme.disabled, ), - Container( + SizedBox( height: 64.0, child: Row( children: [ @@ -1068,13 +1062,13 @@ class _GroupInfoScreenState extends State { final maxChars = maxWidth / maxFontSize!; var currentChars = 0; final currentMembers = []; - otherMembers.forEach((element) { + for (var element in otherMembers) { final newLength = currentChars + element.user!.name.length; if (newLength < maxChars) { currentChars = newLength; currentMembers.add(element); } - }); + } final exceedingMembers = otherMembers.length - currentMembers.length; title = diff --git a/stream_chat_v1/lib/pages/home_page.dart b/stream_chat_v1/lib/pages/home_page.dart index 48eae88319..623844af36 100644 --- a/stream_chat_v1/lib/pages/home_page.dart +++ b/stream_chat_v1/lib/pages/home_page.dart @@ -72,7 +72,7 @@ class HomePageArgs { } class HomePage extends StatefulWidget { - HomePage({ + const HomePage({ Key? key, required this.chatClient, }) : super(key: key); @@ -80,7 +80,7 @@ class HomePage extends StatefulWidget { final StreamChatClient chatClient; @override - _HomePageState createState() => _HomePageState(); + State createState() => _HomePageState(); } class _HomePageState extends State { diff --git a/stream_chat_v1/lib/pages/new_chat_screen.dart b/stream_chat_v1/lib/pages/new_chat_screen.dart index 57ebd02f6c..5b06df552b 100644 --- a/stream_chat_v1/lib/pages/new_chat_screen.dart +++ b/stream_chat_v1/lib/pages/new_chat_screen.dart @@ -9,8 +9,10 @@ import '../widgets/chips_input_text_field.dart'; import '../routes/routes.dart'; class NewChatScreen extends StatefulWidget { + const NewChatScreen({super.key}); + @override - _NewChatScreenState createState() => _NewChatScreenState(); + State createState() => _NewChatScreenState(); } class _NewChatScreenState extends State { @@ -26,7 +28,7 @@ class _NewChatScreenState extends State { Filter.notEqual('id', StreamChat.of(context).currentUser!.id), ]), sort: [ - SortOption( + const SortOption( 'name', direction: 1, ), @@ -54,11 +56,12 @@ class _NewChatScreenState extends State { void _userNameListener() { if (_debounce?.isActive ?? false) _debounce!.cancel(); _debounce = Timer(const Duration(milliseconds: 350), () { - if (mounted) + if (mounted) { setState(() { _userNameQuery = _controller.text; _isSearchActive = _userNameQuery.isNotEmpty; }); + } userListController.filter = Filter.and([ if (_userNameQuery.isNotEmpty) Filter.autoComplete('name', _userNameQuery), @@ -97,13 +100,13 @@ class _NewChatScreenState extends State { 'distinct': true, }), messageLimit: 0, - paginationParams: PaginationParams( + paginationParams: const PaginationParams( limit: 1, ), ); - final _channelExisted = res.length == 1; - if (_channelExisted) { + final channelExisted = res.length == 1; + if (channelExisted) { channel = res.first; await channel!.watch(); } else { @@ -224,7 +227,7 @@ class _NewChatScreenState extends State { child: StreamUserAvatar( showOnlineStatus: false, user: user, - constraints: BoxConstraints.tightFor( + constraints: const BoxConstraints.tightFor( height: 24, width: 24, ), @@ -243,37 +246,35 @@ class _NewChatScreenState extends State { }, ), if (!_isSearchActive && !_selectedUsers.isNotEmpty) - Container( - child: InkWell( - onTap: () { - Navigator.pushNamed( - context, - Routes.NEW_GROUP_CHAT, - ); - }, - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Row( - children: [ - StreamNeumorphicButton( - child: Center( - child: StreamSvgIcon.contacts( - color: StreamChatTheme.of(context) - .colorTheme - .accentPrimary, - size: 24, - ), + InkWell( + onTap: () { + Navigator.pushNamed( + context, + Routes.NEW_GROUP_CHAT, + ); + }, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Row( + children: [ + StreamNeumorphicButton( + child: Center( + child: StreamSvgIcon.contacts( + color: StreamChatTheme.of(context) + .colorTheme + .accentPrimary, + size: 24, ), ), - SizedBox(width: 8), - Text( - AppLocalizations.of(context).createAGroup, - style: StreamChatTheme.of(context) - .textTheme - .bodyBold, - ), - ], - ), + ), + const SizedBox(width: 8), + Text( + AppLocalizations.of(context).createAGroup, + style: StreamChatTheme.of(context) + .textTheme + .bodyBold, + ), + ], ), ), ), @@ -337,7 +338,8 @@ class _NewChatScreenState extends State { return LayoutBuilder( builder: (context, viewportConstraints) { return SingleChildScrollView( - physics: AlwaysScrollableScrollPhysics(), + physics: + const AlwaysScrollableScrollPhysics(), child: ConstrainedBox( constraints: BoxConstraints( minHeight: @@ -382,7 +384,7 @@ class _NewChatScreenState extends State { future: channel!.initialized, builder: (context, snapshot) { if (snapshot.data == true) { - return StreamMessageListView(); + return const StreamMessageListView(); } return Center( diff --git a/stream_chat_v1/lib/pages/new_group_chat_screen.dart b/stream_chat_v1/lib/pages/new_group_chat_screen.dart index 9948448a1f..69cd06174c 100644 --- a/stream_chat_v1/lib/pages/new_group_chat_screen.dart +++ b/stream_chat_v1/lib/pages/new_group_chat_screen.dart @@ -8,8 +8,10 @@ import '../routes/routes.dart'; import '../widgets/search_text_field.dart'; class NewGroupChatScreen extends StatefulWidget { + const NewGroupChatScreen({super.key}); + @override - _NewGroupChatScreenState createState() => _NewGroupChatScreenState(); + State createState() => _NewGroupChatScreenState(); } class _NewGroupChatScreenState extends State { @@ -26,7 +28,7 @@ class _NewGroupChatScreenState extends State { late final userListController = StreamUserListController( client: StreamChat.of(context).client, sort: [ - SortOption( + const SortOption( 'name', direction: 1, ), @@ -144,13 +146,14 @@ class _NewGroupChatScreenState extends State { ), if (_selectedUsers.isNotEmpty) SliverToBoxAdapter( - child: Container( + child: SizedBox( height: 104, child: ListView.separated( scrollDirection: Axis.horizontal, itemCount: _selectedUsers.length, padding: const EdgeInsets.all(8), - separatorBuilder: (_, __) => SizedBox(width: 16), + separatorBuilder: (_, __) => + const SizedBox(width: 16), itemBuilder: (_, index) { final user = _selectedUsers.elementAt(index); return Column( @@ -159,11 +162,12 @@ class _NewGroupChatScreenState extends State { children: [ StreamUserAvatar( onlineIndicatorAlignment: - Alignment(0.9, 0.9), + const Alignment(0.9, 0.9), user: user, showOnlineStatus: true, borderRadius: BorderRadius.circular(32), - constraints: BoxConstraints.tightFor( + constraints: + const BoxConstraints.tightFor( height: 64, width: 64, ), @@ -201,10 +205,10 @@ class _NewGroupChatScreenState extends State { ) ], ), - SizedBox(height: 4), + const SizedBox(height: 4), Text( user.name.split(' ')[0], - style: TextStyle( + style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 12, ), @@ -218,7 +222,7 @@ class _NewGroupChatScreenState extends State { SliverPersistentHeader( pinned: true, delegate: _HeaderDelegate( - height: 30, + height: 32, child: Container( width: double.maxFinite, decoration: BoxDecoration( @@ -232,7 +236,7 @@ class _NewGroupChatScreenState extends State { ), child: Text( _isSearchActive - ? '${AppLocalizations.of(context).matchesFor} \"$_userNameQuery\"' + ? '${AppLocalizations.of(context).matchesFor} "$_userNameQuery"' : AppLocalizations.of(context).onThePlatorm, style: TextStyle( color: StreamChatTheme.of(context) @@ -271,7 +275,7 @@ class _NewGroupChatScreenState extends State { return LayoutBuilder( builder: (context, viewportConstraints) { return SingleChildScrollView( - physics: AlwaysScrollableScrollPhysics(), + physics: const AlwaysScrollableScrollPhysics(), child: ConstrainedBox( constraints: BoxConstraints( minHeight: viewportConstraints.maxHeight, diff --git a/stream_chat_v1/lib/pages/pinned_messages_screen.dart b/stream_chat_v1/lib/pages/pinned_messages_screen.dart index bdf359a252..407eb63b4c 100644 --- a/stream_chat_v1/lib/pages/pinned_messages_screen.dart +++ b/stream_chat_v1/lib/pages/pinned_messages_screen.dart @@ -6,6 +6,8 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'channel_page.dart'; class PinnedMessagesScreen extends StatefulWidget { + const PinnedMessagesScreen({super.key}); + @override State createState() => _PinnedMessagesScreenState(); } @@ -22,7 +24,7 @@ class _PinnedMessagesScreenState extends State { true, ), sort: [ - SortOption( + const SortOption( 'created_at', direction: SortOption.ASC, ), @@ -44,7 +46,7 @@ class _PinnedMessagesScreenState extends State { fontSize: 16.0, ), ), - leading: StreamBackButton(), + leading: const StreamBackButton(), backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, ), body: StreamMessageSearchListView( @@ -58,7 +60,7 @@ class _PinnedMessagesScreenState extends State { size: 136.0, color: StreamChatTheme.of(context).colorTheme.disabled, ), - SizedBox(height: 16.0), + const SizedBox(height: 16.0), Text( AppLocalizations.of(context).noPinnedItems, style: TextStyle( @@ -68,7 +70,7 @@ class _PinnedMessagesScreenState extends State { fontWeight: FontWeight.bold, ), ), - SizedBox(height: 8.0), + const SizedBox(height: 8.0), RichText( textAlign: TextAlign.center, text: TextSpan(children: [ @@ -101,6 +103,7 @@ class _PinnedMessagesScreenState extends State { }, onMessageTap: (messageResponse) async { final client = StreamChat.of(context).client; + final navigator = Navigator.of(context); final message = messageResponse.message; final channel = client.channel( messageResponse.channel!.type, @@ -109,8 +112,7 @@ class _PinnedMessagesScreenState extends State { if (channel.state == null) { await channel.watch(); } - Navigator.pushNamed( - context, + navigator.pushNamed( Routes.CHANNEL_PAGE, arguments: ChannelPageArgs( channel: channel, diff --git a/stream_chat_v1/lib/pages/splash_screen.dart b/stream_chat_v1/lib/pages/splash_screen.dart index 9e72572d76..ce3760c4c7 100644 --- a/stream_chat_v1/lib/pages/splash_screen.dart +++ b/stream_chat_v1/lib/pages/splash_screen.dart @@ -12,7 +12,7 @@ mixin SplashScreenStateMixin on State _scaleAnimationController = AnimationController( vsync: this, value: 0, - duration: Duration( + duration: const Duration( milliseconds: 500, ), ); @@ -26,7 +26,7 @@ mixin SplashScreenStateMixin on State _animationController = AnimationController( vsync: this, - duration: Duration( + duration: const Duration( milliseconds: 1000, ), ); @@ -38,14 +38,14 @@ mixin SplashScreenStateMixin on State curve: Curves.easeInOut, )); colorAnimation = ColorTween( - begin: Color(0xff005FFF), - end: Color(0xff005FFF), + begin: const Color(0xff005FFF), + end: const Color(0xff005FFF), ).animate(CurvedAnimation( parent: _animationController, curve: Curves.easeInOut, )); colorAnimation = ColorTween( - begin: Color(0xff005FFF), + begin: const Color(0xff005FFF), end: Colors.transparent, ).animate(CurvedAnimation( parent: _animationController, @@ -73,14 +73,14 @@ mixin SplashScreenStateMixin on State builder: (context, snapshot) { return Container( alignment: Alignment.center, - constraints: BoxConstraints.expand(), + constraints: const BoxConstraints.expand(), color: colorAnimation.value, child: !_animationController.isAnimating ? Lottie.asset( 'assets/floating_boat.json', alignment: Alignment.center, ) - : SizedBox(), + : const SizedBox(), ); }), ); diff --git a/stream_chat_v1/lib/pages/thread_page.dart b/stream_chat_v1/lib/pages/thread_page.dart index d5f9c77678..4e57c35632 100644 --- a/stream_chat_v1/lib/pages/thread_page.dart +++ b/stream_chat_v1/lib/pages/thread_page.dart @@ -6,7 +6,7 @@ class ThreadPage extends StatefulWidget { final int? initialScrollIndex; final double? initialAlignment; - ThreadPage({ + const ThreadPage({ Key? key, required this.parent, this.initialScrollIndex, @@ -14,11 +14,11 @@ class ThreadPage extends StatefulWidget { }) : super(key: key); @override - _ThreadPageState createState() => _ThreadPageState(); + State createState() => _ThreadPageState(); } class _ThreadPageState extends State { - FocusNode _focusNode = FocusNode(); + final FocusNode _focusNode = FocusNode(); late StreamMessageInputController _messageInputController; @override @@ -82,8 +82,8 @@ class _ThreadPageState extends State { } bool defaultFilter(Message m) { - var _currentUser = StreamChat.of(context).currentUser; - final isMyMessage = m.user?.id == _currentUser?.id; + final currentUser = StreamChat.of(context).currentUser; + final isMyMessage = m.user?.id == currentUser?.id; final isDeletedOrShadowed = m.isDeleted == true || m.shadowed == true; if (isDeletedOrShadowed && !isMyMessage) return false; return true; diff --git a/stream_chat_v1/lib/pages/user_mentions_page.dart b/stream_chat_v1/lib/pages/user_mentions_page.dart index 8b8bfa442d..52543786e1 100644 --- a/stream_chat_v1/lib/pages/user_mentions_page.dart +++ b/stream_chat_v1/lib/pages/user_mentions_page.dart @@ -6,6 +6,8 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'channel_page.dart'; class UserMentionsPage extends StatefulWidget { + const UserMentionsPage({super.key}); + @override State createState() => _UserMentionsPageState(); } @@ -20,7 +22,7 @@ class _UserMentionsPageState extends State { value: StreamChat.of(context).currentUser!.id, ), sort: [ - SortOption( + const SortOption( 'created_at', direction: SortOption.ASC, ), @@ -35,7 +37,7 @@ class _UserMentionsPageState extends State { return LayoutBuilder( builder: (context, viewportConstraints) { return SingleChildScrollView( - physics: AlwaysScrollableScrollPhysics(), + physics: const AlwaysScrollableScrollPhysics(), child: ConstrainedBox( constraints: BoxConstraints( minHeight: viewportConstraints.maxHeight, @@ -70,6 +72,7 @@ class _UserMentionsPageState extends State { }, onMessageTap: (messageResponse) async { final client = StreamChat.of(context).client; + final navigator = Navigator.of(context); final message = messageResponse.message; final channel = client.channel( messageResponse.channel!.type, @@ -78,8 +81,7 @@ class _UserMentionsPageState extends State { if (channel.state == null) { await channel.watch(); } - Navigator.pushNamed( - context, + navigator.pushNamed( Routes.CHANNEL_PAGE, arguments: ChannelPageArgs( channel: channel, diff --git a/stream_chat_v1/lib/routes/app_routes.dart b/stream_chat_v1/lib/routes/app_routes.dart index cea1ebe04f..cee0a57488 100644 --- a/stream_chat_v1/lib/routes/app_routes.dart +++ b/stream_chat_v1/lib/routes/app_routes.dart @@ -25,7 +25,7 @@ class AppRoutes { return MaterialPageRoute( settings: RouteSettings(arguments: args, name: Routes.APP), builder: (_) { - return MyApp(); + return const StreamChatSampleApp(); }); case Routes.HOME: return MaterialPageRoute( @@ -40,13 +40,13 @@ class AppRoutes { return MaterialPageRoute( settings: RouteSettings(arguments: args, name: Routes.CHOOSE_USER), builder: (_) { - return ChooseUserPage(); + return const ChooseUserPage(); }); case Routes.ADVANCED_OPTIONS: return MaterialPageRoute( settings: RouteSettings(arguments: args, name: Routes.ADVANCED_OPTIONS), - builder: (_) => AdvancedOptionsPage(), + builder: (_) => const AdvancedOptionsPage(), ); case Routes.CHANNEL_PAGE: return MaterialPageRoute( @@ -83,14 +83,14 @@ class AppRoutes { return MaterialPageRoute( settings: RouteSettings(arguments: args, name: Routes.NEW_CHAT), builder: (_) { - return NewChatScreen(); + return const NewChatScreen(); }); case Routes.NEW_GROUP_CHAT: return MaterialPageRoute( settings: RouteSettings(arguments: args, name: Routes.NEW_GROUP_CHAT), builder: (_) { - return NewGroupChatScreen(); + return const NewGroupChatScreen(); }); case Routes.NEW_GROUP_CHAT_DETAILS: return MaterialPageRoute( @@ -125,7 +125,7 @@ class AppRoutes { settings: RouteSettings(arguments: args, name: Routes.CHANNEL_LIST_PAGE), builder: (context) { - return ChannelListPage(); + return const ChannelListPage(); }); // Default case, should not reach here. default: diff --git a/stream_chat_v1/lib/routes/routes.dart b/stream_chat_v1/lib/routes/routes.dart index 8ba28933e2..844d7b9bba 100644 --- a/stream_chat_v1/lib/routes/routes.dart +++ b/stream_chat_v1/lib/routes/routes.dart @@ -1,3 +1,5 @@ +// ignore_for_file: constant_identifier_names + /// Application routes abstract class Routes { static const String APP = '/app'; diff --git a/stream_chat_v1/lib/utils/app_config.dart b/stream_chat_v1/lib/utils/app_config.dart index c9771343db..e006cddfee 100644 --- a/stream_chat_v1/lib/utils/app_config.dart +++ b/stream_chat_v1/lib/utils/app_config.dart @@ -9,7 +9,7 @@ final defaultUsers = { 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoic2FsdmF0b3JlIn0.pgiJz7sIc7iP29BHKFwe3nLm5-OaR_1l2P-SlgiC9a8': User( id: 'salvatore', - extraData: { + extraData: const { 'name': 'Salvatore Giordano', 'image': 'https://avatars.githubusercontent.com/u/20601437?s=460&u=3f66c22a7483980624804054ae7f357cf102c784&v=4', @@ -18,7 +18,7 @@ final defaultUsers = { 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoic2FoaWwifQ.WnIUoB5gR2kcAsFhiDvkiD6zdHXZ-VSU2aQWWkhsvfo': User( id: 'sahil', - extraData: { + extraData: const { 'name': 'Sahil Kumar', 'image': 'https://avatars.githubusercontent.com/u/25670178?s=400&u=30ded3784d8d2310c5748f263fd5e6433c119aa1&v=4', @@ -27,7 +27,7 @@ final defaultUsers = { 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiYmVuIn0.nAz2sNFGQwY7rl2Og2z3TGHUsdpnN53tOsUglJFvLmg': User( id: 'ben', - extraData: { + extraData: const { 'name': 'Ben Golden', 'image': 'https://avatars.githubusercontent.com/u/1581974?s=400&v=4', }, @@ -35,7 +35,7 @@ final defaultUsers = { 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoidGhpZXJyeSJ9.lEq6TrZtHzjoNtf7HHRufUPyGo_pa8vg4_XhEBp4ckY': User( id: 'thierry', - extraData: { + extraData: const { 'name': 'Thierry Schellenbach', 'image': 'https://avatars.githubusercontent.com/u/265409?s=400&u=2d0e3bb1820db992066196bff7b004f0eee8e28d&v=4', @@ -44,7 +44,7 @@ final defaultUsers = { 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoidG9tbWFzbyJ9.GLSI0ESshERMo2WjUpysD709NEtn1zmGimUN2an7g9o': User( id: 'tommaso', - extraData: { + extraData: const { 'name': 'Tommaso Barbugli', 'image': 'https://avatars.githubusercontent.com/u/88735?s=400&v=4', }, @@ -52,7 +52,7 @@ final defaultUsers = { 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiZGV2ZW4ifQ.z3zI4PqJnNhc-1o-VKcmb6BnnQ0oxFNCRHwEulHqcWc': User( id: 'deven', - extraData: { + extraData: const { 'name': 'Deven Joshi', 'image': 'https://avatars.githubusercontent.com/u/26357843?s=400&u=0c61d890866e67bf69f58878be58915e9bfd39ee&v=4', @@ -61,7 +61,7 @@ final defaultUsers = { 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoibmVldmFzaCJ9.3EdHegTxibrz3A9cTiKmpEyawwcCVB8FXnoFzr4eKvw': User( id: 'neevash', - extraData: { + extraData: const { 'name': 'Neevash Ramdial', 'image': 'https://avatars.githubusercontent.com/u/25674767?s=400&u=1d7333baf7dd9d143db8bfcdb31a838b89cfff9c&v=4', @@ -70,14 +70,14 @@ final defaultUsers = { 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoicWF0ZXN0MSJ9.fnelU7HcP7QoEEsCGteNlF1fppofzNlrnpDQuIgeKCU': User( id: 'qatest1', - extraData: { + extraData: const { 'name': 'QA test 1', }, ), 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoicWF0ZXN0MiJ9.vSCqAEbs2WVmMWsOsa7065Fsjq-rsTih6qsHPynl7XM': User( id: 'qatest2', - extraData: { + extraData: const { 'name': 'QA test 2', }, ), diff --git a/stream_chat_v1/lib/utils/notifications_service.dart b/stream_chat_v1/lib/utils/notifications_service.dart index b6cafb16c8..b56fc9985a 100644 --- a/stream_chat_v1/lib/utils/notifications_service.dart +++ b/stream_chat_v1/lib/utils/notifications_service.dart @@ -20,18 +20,23 @@ void showLocalNotification( } if (event.message == null) return; final flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); - final initializationSettingsAndroid = + const initializationSettingsAndroid = AndroidInitializationSettings('launch_background'); - final initializationSettingsIOS = IOSInitializationSettings(); - final initializationSettings = InitializationSettings( + const initializationSettingsIOS = IOSInitializationSettings(); + const initializationSettings = InitializationSettings( android: initializationSettingsAndroid, iOS: initializationSettingsIOS, ); + + final appLocalizations = AppLocalizations.of(context); + await flutterLocalNotificationsPlugin.initialize( initializationSettings, onSelectNotification: (channelCid) async { if (channelCid != null) { final client = StreamChat.of(context).client; + final navigator = Navigator.of(context); + var channel = client.state.channels[channelCid]; if (channel == null) { @@ -45,8 +50,7 @@ void showLocalNotification( await channel.watch(); } - Navigator.pushNamed( - context, + navigator.pushNamed( Routes.CHANNEL_PAGE, arguments: ChannelPageArgs( channel: channel, @@ -62,13 +66,12 @@ void showLocalNotification( NotificationDetails( android: AndroidNotificationDetails( 'message channel', - AppLocalizations.of(context).messageChannelName, - channelDescription: - AppLocalizations.of(context).messageChannelDescription, + appLocalizations.messageChannelName, + channelDescription: appLocalizations.messageChannelDescription, priority: Priority.high, importance: Importance.high, ), - iOS: IOSNotificationDetails(), + iOS: const IOSNotificationDetails(), ), payload: '${event.channelType}:${event.channelId}', ); diff --git a/stream_chat_v1/lib/widgets/channel_list.dart b/stream_chat_v1/lib/widgets/channel_list.dart index f72ca393dc..5337feb1c5 100644 --- a/stream_chat_v1/lib/widgets/channel_list.dart +++ b/stream_chat_v1/lib/widgets/channel_list.dart @@ -13,21 +13,23 @@ import '../pages/chat_info_screen.dart'; import '../pages/group_info_screen.dart'; class ChannelList extends StatefulWidget { + const ChannelList({super.key}); + @override - _ChannelList createState() => _ChannelList(); + State createState() => _ChannelList(); } class _ChannelList extends State { - ScrollController _scrollController = ScrollController(); + final ScrollController _scrollController = ScrollController(); - late StreamMessageSearchListController _messageSearchListController = + late final StreamMessageSearchListController _messageSearchListController = StreamMessageSearchListController( client: StreamChat.of(context).client, filter: Filter.in_('members', [StreamChat.of(context).currentUser!.id]), limit: 5, searchQuery: '', sort: [ - SortOption( + const SortOption( 'created_at', direction: SortOption.ASC, ), @@ -116,7 +118,7 @@ class _ChannelList extends State { return LayoutBuilder( builder: (context, viewportConstraints) { return SingleChildScrollView( - physics: AlwaysScrollableScrollPhysics(), + physics: const AlwaysScrollableScrollPhysics(), child: ConstrainedBox( constraints: BoxConstraints( minHeight: viewportConstraints.maxHeight, @@ -153,6 +155,7 @@ class _ChannelList extends State { final messageResponse = messageResponses[index]; FocusScope.of(context).requestFocus(FocusNode()); final client = StreamChat.of(context).client; + final navigator = Navigator.of(context); final message = messageResponse.message; final channel = client.channel( messageResponse.channel!.type, @@ -161,8 +164,7 @@ class _ChannelList extends State { if (channel.state == null) { await channel.watch(); } - Navigator.pushNamed( - context, + navigator.pushNamed( Routes.CHANNEL_PAGE, arguments: ChannelPageArgs( channel: channel, @@ -192,7 +194,6 @@ class _ChannelList extends State { motion: const BehindMotion(), children: [ CustomSlidableAction( - child: Icon(Icons.more_horiz), backgroundColor: backgroundColor, onPressed: (_) { showChannelInfoModalBottomSheet( @@ -236,6 +237,7 @@ class _ChannelList extends State { }, ); }, + child: const Icon(Icons.more_horiz), ), if (canDeleteChannel) CustomSlidableAction( diff --git a/stream_chat_v1/lib/widgets/chips_input_text_field.dart b/stream_chat_v1/lib/widgets/chips_input_text_field.dart index ed1f78c107..1e9755886e 100644 --- a/stream_chat_v1/lib/widgets/chips_input_text_field.dart +++ b/stream_chat_v1/lib/widgets/chips_input_text_field.dart @@ -68,97 +68,95 @@ class ChipInputTextFieldState extends State> { child: Material( elevation: 1, color: StreamChatTheme.of(context).colorTheme.barsBg, - child: Container( - child: Padding( - padding: const EdgeInsets.fromLTRB(16, 16, 16, 16), - child: Row( - children: [ - Padding( - padding: const EdgeInsets.symmetric(vertical: 4.0), - child: Text( - '${AppLocalizations.of(context).to.toUpperCase()}:', - style: StreamChatTheme.of(context) - .textTheme - .footnote - .copyWith( - color: StreamChatTheme.of(context) - .colorTheme - .textHighEmphasis - .withOpacity(.5)), - ), + child: Padding( + padding: const EdgeInsets.fromLTRB(16, 16, 16, 16), + child: Row( + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 4.0), + child: Text( + '${AppLocalizations.of(context).to.toUpperCase()}:', + style: StreamChatTheme.of(context) + .textTheme + .footnote + .copyWith( + color: StreamChatTheme.of(context) + .colorTheme + .textHighEmphasis + .withOpacity(.5)), ), - SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Wrap( - spacing: 8.0, - runSpacing: 4.0, - children: _chips.map((item) { - return widget.chipBuilder(context, item); - }).toList(), - ), - if (!_pauseItemAddition) - TextField( - controller: widget.controller, - onChanged: widget.onInputChanged, - focusNode: widget.focusNode, - decoration: InputDecoration( - isDense: true, - border: InputBorder.none, - focusedBorder: InputBorder.none, - enabledBorder: InputBorder.none, - errorBorder: InputBorder.none, - disabledBorder: InputBorder.none, - contentPadding: const EdgeInsets.only(top: 4.0), - hintText: widget.hint, - hintStyle: StreamChatTheme.of(context) - .textTheme - .body - .copyWith( - color: StreamChatTheme.of(context) - .colorTheme - .textHighEmphasis - .withOpacity(.5)), - ), + ), + const SizedBox(width: 12), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Wrap( + spacing: 8.0, + runSpacing: 4.0, + children: _chips.map((item) { + return widget.chipBuilder(context, item); + }).toList(), + ), + if (!_pauseItemAddition) + TextField( + controller: widget.controller, + onChanged: widget.onInputChanged, + focusNode: widget.focusNode, + decoration: InputDecoration( + isDense: true, + border: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + errorBorder: InputBorder.none, + disabledBorder: InputBorder.none, + contentPadding: const EdgeInsets.only(top: 4.0), + hintText: widget.hint, + hintStyle: StreamChatTheme.of(context) + .textTheme + .body + .copyWith( + color: StreamChatTheme.of(context) + .colorTheme + .textHighEmphasis + .withOpacity(.5)), ), - ], - ), + ), + ], ), - SizedBox(width: 12), - Align( - alignment: Alignment.bottomCenter, - child: IconButton( - icon: _chips.isEmpty - ? StreamSvgIcon.user( - color: StreamChatTheme.of(context) - .colorTheme - .textHighEmphasis - .withOpacity(0.5), - size: 24, - ) - : StreamSvgIcon.userAdd( - color: StreamChatTheme.of(context) - .colorTheme - .textHighEmphasis - .withOpacity(0.5), - size: 24, - ), - onPressed: resumeItemAddition, - alignment: Alignment.topRight, - visualDensity: VisualDensity.compact, - padding: const EdgeInsets.all(0), - splashRadius: 24, - constraints: BoxConstraints.tightFor( - height: 24, - width: 24, - ), + ), + const SizedBox(width: 12), + Align( + alignment: Alignment.bottomCenter, + child: IconButton( + icon: _chips.isEmpty + ? StreamSvgIcon.user( + color: StreamChatTheme.of(context) + .colorTheme + .textHighEmphasis + .withOpacity(0.5), + size: 24, + ) + : StreamSvgIcon.userAdd( + color: StreamChatTheme.of(context) + .colorTheme + .textHighEmphasis + .withOpacity(0.5), + size: 24, + ), + onPressed: resumeItemAddition, + alignment: Alignment.topRight, + visualDensity: VisualDensity.compact, + padding: const EdgeInsets.all(0), + splashRadius: 24, + constraints: const BoxConstraints.tightFor( + height: 24, + width: 24, ), ), - ], - ), + ), + ], ), ), ), diff --git a/stream_chat_v1/lib/widgets/search_text_field.dart b/stream_chat_v1/lib/widgets/search_text_field.dart index 7641a7b3f4..1d80ab7a8b 100644 --- a/stream_chat_v1/lib/widgets/search_text_field.dart +++ b/stream_chat_v1/lib/widgets/search_text_field.dart @@ -41,7 +41,7 @@ class SearchTextField extends StatelessWidget { onChanged: onChanged, decoration: InputDecoration( prefixText: ' ', - prefixIconConstraints: BoxConstraints.tight(Size(40, 24)), + prefixIconConstraints: BoxConstraints.tight(const Size(40, 24)), prefixIcon: Padding( padding: const EdgeInsets.only( left: 8, diff --git a/stream_chat_v1/lib/widgets/stream_version.dart b/stream_chat_v1/lib/widgets/stream_version.dart index 2151470a9c..572cb3d1ba 100644 --- a/stream_chat_v1/lib/widgets/stream_version.dart +++ b/stream_chat_v1/lib/widgets/stream_version.dart @@ -18,7 +18,7 @@ class StreamVersion extends StatelessWidget { future: rootBundle.loadString('pubspec.lock'), builder: (context, snapshot) { if (!snapshot.hasData) { - return SizedBox(); + return const SizedBox(); } final pubspec = snapshot.data!; diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index 894d1aa32a..1c7a956b16 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -39,6 +39,7 @@ dependencies: dev_dependencies: flutter_launcher_icons: ^0.9.2 test: any + flutter_lints: ^2.0.0 dependency_overrides: stream_chat: From bd405e71c9cae597cecdd97243cfb79144eddf7e Mon Sep 17 00:00:00 2001 From: Gordon Hayes Date: Fri, 7 Oct 2022 11:25:49 +0200 Subject: [PATCH 132/172] chore: prefer final and lazy init --- .../lib/pages/advanced_options_page.dart | 9 +++ .../pages/channel_media_display_screen.dart | 4 +- .../lib/pages/chat_info_screen.dart | 6 +- .../lib/pages/group_chat_details_screen.dart | 23 +++---- .../lib/pages/group_info_screen.dart | 62 ++++++++++--------- .../lib/pages/new_group_chat_screen.dart | 17 ++--- stream_chat_v1/lib/widgets/channel_list.dart | 19 +++--- 7 files changed, 67 insertions(+), 73 deletions(-) diff --git a/stream_chat_v1/lib/pages/advanced_options_page.dart b/stream_chat_v1/lib/pages/advanced_options_page.dart index 1b03bf60fc..4cd5e099fc 100644 --- a/stream_chat_v1/lib/pages/advanced_options_page.dart +++ b/stream_chat_v1/lib/pages/advanced_options_page.dart @@ -32,6 +32,15 @@ class _AdvancedOptionsPageState extends State { bool loading = false; + @override + void dispose() { + _apiKeyController.dispose(); + _userIdController.dispose(); + _userTokenController.dispose(); + _usernameController.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { return Scaffold( diff --git a/stream_chat_v1/lib/pages/channel_media_display_screen.dart b/stream_chat_v1/lib/pages/channel_media_display_screen.dart index 9017538efd..e16cb933e7 100644 --- a/stream_chat_v1/lib/pages/channel_media_display_screen.dart +++ b/stream_chat_v1/lib/pages/channel_media_display_screen.dart @@ -102,7 +102,7 @@ class _ChannelMediaDisplayScreenState extends State { } final media = <_AssetPackage>[]; - for (var item in value.asSuccess.items) { + for (final item in value.asSuccess.items) { item.message.attachments .where((e) => (e.type == 'image' || e.type == 'video') && @@ -110,7 +110,7 @@ class _ChannelMediaDisplayScreenState extends State { .forEach((e) { VideoPlayerController? controller; if (e.type == 'video') { - var cachedController = controllerCache[e.assetUrl]; + final cachedController = controllerCache[e.assetUrl]; if (cachedController == null) { controller = VideoPlayerController.network(e.assetUrl!); diff --git a/stream_chat_v1/lib/pages/chat_info_screen.dart b/stream_chat_v1/lib/pages/chat_info_screen.dart index dc4e6c3313..ff9761d3f7 100644 --- a/stream_chat_v1/lib/pages/chat_info_screen.dart +++ b/stream_chat_v1/lib/pages/chat_info_screen.dart @@ -117,7 +117,7 @@ class _ChatInfoScreenState extends State { } Widget _buildOptionListTiles() { - var channel = StreamChannel.of(context); + final channel = StreamChannel.of(context); return Column( children: [ @@ -398,7 +398,7 @@ class _SharedGroupsScreen extends StatefulWidget { class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { @override Widget build(BuildContext context) { - var chat = StreamChat.of(context); + final chat = StreamChat.of(context); return Scaffold( backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, @@ -505,7 +505,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { final maxChars = maxWidth / textStyle.fontSize!; var currentChars = 0; final currentMembers = []; - for (var element in otherMembers) { + for (final element in otherMembers) { final newLength = currentChars + element.user!.name.length; if (newLength < maxChars) { currentChars = newLength; diff --git a/stream_chat_v1/lib/pages/group_chat_details_screen.dart b/stream_chat_v1/lib/pages/group_chat_details_screen.dart index 9ae78eba5c..8b813ec3ed 100644 --- a/stream_chat_v1/lib/pages/group_chat_details_screen.dart +++ b/stream_chat_v1/lib/pages/group_chat_details_screen.dart @@ -18,16 +18,17 @@ class GroupChatDetailsScreen extends StatefulWidget { } class _GroupChatDetailsScreenState extends State { - final _selectedUsers = []; + late final _selectedUsers = [...?widget.selectedUsers]; - TextEditingController? _groupNameController; + late final TextEditingController _groupNameController = + TextEditingController()..addListener(_groupNameListener); bool _isGroupNameEmpty = true; int get _totalUsers => _selectedUsers.length; void _groupNameListener() { - final name = _groupNameController!.text; + final name = _groupNameController.text; if (mounted) { setState(() { _isGroupNameEmpty = name.isEmpty; @@ -35,19 +36,11 @@ class _GroupChatDetailsScreenState extends State { } } - @override - void initState() { - super.initState(); - _selectedUsers.addAll(widget.selectedUsers!); - _groupNameController = TextEditingController() - ..addListener(_groupNameListener); - } - @override void dispose() { - _groupNameController?.removeListener(_groupNameListener); - _groupNameController?.clear(); - _groupNameController?.dispose(); + _groupNameController.removeListener(_groupNameListener); + _groupNameController.clear(); + _groupNameController.dispose(); super.dispose(); } @@ -128,7 +121,7 @@ class _GroupChatDetailsScreenState extends State { ? null : () async { try { - final groupName = _groupNameController!.text; + final groupName = _groupNameController.text; final client = StreamChat.of(context).client; final navigator = Navigator.of(context); final channel = client.channel('messaging', diff --git a/stream_chat_v1/lib/pages/group_info_screen.dart b/stream_chat_v1/lib/pages/group_info_screen.dart index ccddb8a973..95c0680595 100644 --- a/stream_chat_v1/lib/pages/group_info_screen.dart +++ b/stream_chat_v1/lib/pages/group_info_screen.dart @@ -25,9 +25,14 @@ class GroupInfoScreen extends StatefulWidget { } class _GroupInfoScreenState extends State { - TextEditingController? _nameController; + late final TextEditingController _nameController = + TextEditingController.fromValue( + TextEditingValue(text: (channel.extraData['name'] as String?) ?? ''), + ); + + late final TextEditingController _searchController = TextEditingController() + ..addListener(_userNameListener); - TextEditingController? _searchController; String _userNameQuery = ''; Timer? _debounce; @@ -37,23 +42,23 @@ class _GroupInfoScreenState extends State { bool listExpanded = false; - ValueNotifier mutedBool = ValueNotifier(false); + late ValueNotifier mutedBool = ValueNotifier(channel.isMuted); late final channel = StreamChannel.of(context).channel; - late StreamUserListController userListController; + late StreamUserListController _userListController; void _userNameListener() { - if (_searchController!.text == _userNameQuery) { + if (_searchController.text == _userNameQuery) { return; } if (_debounce?.isActive ?? false) _debounce!.cancel(); _debounce = Timer(const Duration(milliseconds: 350), () { if (mounted) { - _userNameQuery = _searchController!.text; - userListController.filter = Filter.and( + _userNameQuery = _searchController.text; + _userListController.filter = Filter.and( [ - if (_searchController!.text.isNotEmpty) + if (_searchController.text.isNotEmpty) Filter.autoComplete('name', _userNameQuery), Filter.notIn('id', [ StreamChat.of(context).currentUser!.id, @@ -63,7 +68,7 @@ class _GroupInfoScreenState extends State { ]), ], ); - userListController.doInitialLoad(); + _userListController.doInitialLoad(); } }); } @@ -72,12 +77,7 @@ class _GroupInfoScreenState extends State { void initState() { super.initState(); - _nameController = TextEditingController.fromValue( - TextEditingValue(text: (channel.extraData['name'] as String?) ?? ''), - ); - _searchController = TextEditingController()..addListener(_userNameListener); - - _nameController!.addListener(() { + _nameController.addListener(() { setState(() {}); }); mutedBool = ValueNotifier(channel.isMuted); @@ -85,12 +85,12 @@ class _GroupInfoScreenState extends State { @override void didChangeDependencies() { - userListController = StreamUserListController( + _userListController = StreamUserListController( client: StreamChat.of(context).client, limit: 25, filter: Filter.and( [ - if (_searchController!.text.isNotEmpty) + if (_searchController.text.isNotEmpty) Filter.autoComplete('name', _userNameQuery), Filter.notIn('id', [ StreamChat.of(context).currentUser!.id, @@ -112,7 +112,9 @@ class _GroupInfoScreenState extends State { @override void dispose() { - userListController.dispose(); + _nameController.dispose(); + _searchController.dispose(); + _userListController.dispose(); super.dispose(); } @@ -382,7 +384,7 @@ class _GroupInfoScreenState extends State { } Widget _buildNameTile() { - var channelName = (channel.extraData['name'] as String?) ?? ''; + final channelName = (channel.extraData['name'] as String?) ?? ''; return Material( color: StreamChatTheme.of(context).colorTheme.appBg, @@ -429,7 +431,7 @@ class _GroupInfoScreenState extends State { ), ), ), - if (channelName != _nameController!.text.trim()) + if (channelName != _nameController.text.trim()) Row( mainAxisSize: MainAxisSize.min, children: [ @@ -437,7 +439,7 @@ class _GroupInfoScreenState extends State { child: StreamSvgIcon.closeSmall(), onTap: () { setState(() { - _nameController!.text = _getChannelName( + _nameController.text = _getChannelName( 2 * MediaQuery.of(context).size.width / 3, members: channel.state!.members, extraData: channel.extraData, @@ -458,10 +460,10 @@ class _GroupInfoScreenState extends State { ), onTap: () { channel.update({ - 'name': _nameController!.text.trim(), + 'name': _nameController.text.trim(), }).catchError((err) { setState(() { - _nameController!.text = channelName; + _nameController.text = channelName; _focusNode.unfocus(); }); }); @@ -572,7 +574,7 @@ class _GroupInfoScreenState extends State { color: StreamChatTheme.of(context).colorTheme.textLowEmphasis, ), onTap: () { - var channel = StreamChannel.of(context).channel; + final channel = StreamChannel.of(context).channel; Navigator.push( context, @@ -606,7 +608,7 @@ class _GroupInfoScreenState extends State { color: StreamChatTheme.of(context).colorTheme.textLowEmphasis, ), onTap: () { - var channel = StreamChannel.of(context).channel; + final channel = StreamChannel.of(context).channel; Navigator.push( context, @@ -691,9 +693,9 @@ class _GroupInfoScreenState extends State { ), Expanded( child: StreamUserGridView( - controller: userListController, + controller: _userListController, onUserTap: (user) async { - _searchController!.clear(); + _searchController.clear(); final navigator = Navigator.of(context); await channel.addMembers([user.id]); @@ -740,7 +742,7 @@ class _GroupInfoScreenState extends State { ); }, ).whenComplete(() { - _searchController?.clear(); + _searchController.clear(); }); } @@ -1053,7 +1055,7 @@ class _GroupInfoScreenState extends State { double? maxFontSize, }) { String? title; - var client = StreamChat.of(context); + final client = StreamChat.of(context); if (extraData['name'] == null) { final otherMembers = members!.where((member) => member.user!.id != client.currentUser!.id); @@ -1062,7 +1064,7 @@ class _GroupInfoScreenState extends State { final maxChars = maxWidth / maxFontSize!; var currentChars = 0; final currentMembers = []; - for (var element in otherMembers) { + for (final element in otherMembers) { final newLength = currentChars + element.user!.name.length; if (newLength < maxChars) { currentChars = newLength; diff --git a/stream_chat_v1/lib/pages/new_group_chat_screen.dart b/stream_chat_v1/lib/pages/new_group_chat_screen.dart index 69cd06174c..8446e6a286 100644 --- a/stream_chat_v1/lib/pages/new_group_chat_screen.dart +++ b/stream_chat_v1/lib/pages/new_group_chat_screen.dart @@ -15,7 +15,8 @@ class NewGroupChatScreen extends StatefulWidget { } class _NewGroupChatScreenState extends State { - TextEditingController? _controller; + late final TextEditingController _controller = TextEditingController() + ..addListener(_userNameListener); String _userNameQuery = ''; @@ -44,7 +45,7 @@ class _NewGroupChatScreenState extends State { _debounce = Timer(const Duration(milliseconds: 350), () { if (mounted) { setState(() { - _userNameQuery = _controller!.text; + _userNameQuery = _controller.text; _isSearchActive = _userNameQuery.isNotEmpty; }); userListController.filter = Filter.and([ @@ -57,17 +58,11 @@ class _NewGroupChatScreenState extends State { }); } - @override - void initState() { - super.initState(); - _controller = TextEditingController()..addListener(_userNameListener); - } - @override void dispose() { - _controller?.clear(); - _controller?.removeListener(_userNameListener); - _controller?.dispose(); + _controller.clear(); + _controller.removeListener(_userNameListener); + _controller.dispose(); userListController.dispose(); super.dispose(); } diff --git a/stream_chat_v1/lib/widgets/channel_list.dart b/stream_chat_v1/lib/widgets/channel_list.dart index 5337feb1c5..44cb7ba476 100644 --- a/stream_chat_v1/lib/widgets/channel_list.dart +++ b/stream_chat_v1/lib/widgets/channel_list.dart @@ -36,7 +36,8 @@ class _ChannelList extends State { ], ); - TextEditingController? _controller; + late final TextEditingController _controller = TextEditingController() + ..addListener(_channelQueryListener); bool _isSearchActive = false; @@ -46,9 +47,9 @@ class _ChannelList extends State { if (_debounce?.isActive ?? false) _debounce!.cancel(); _debounce = Timer(const Duration(milliseconds: 350), () { if (mounted) { - _messageSearchListController.searchQuery = _controller!.text; + _messageSearchListController.searchQuery = _controller.text; setState(() { - _isSearchActive = _controller!.text.isNotEmpty; + _isSearchActive = _controller.text.isNotEmpty; }); if (_isSearchActive) _messageSearchListController.doInitialLoad(); } @@ -65,16 +66,10 @@ class _ChannelList extends State { limit: 30, ); - @override - void initState() { - super.initState(); - _controller = TextEditingController()..addListener(_channelQueryListener); - } - @override void dispose() { - _controller?.removeListener(_channelQueryListener); - _controller?.dispose(); + _controller.removeListener(_channelQueryListener); + _controller.dispose(); _scrollController.dispose(); _channelListController.dispose(); super.dispose(); @@ -85,7 +80,7 @@ class _ChannelList extends State { return WillPopScope( onWillPop: () async { if (_isSearchActive) { - _controller!.clear(); + _controller.clear(); setState(() => _isSearchActive = false); return false; } From 158719c7160567a752ce70b38f6ba38df796b3f8 Mon Sep 17 00:00:00 2001 From: Gordon Hayes Date: Mon, 10 Oct 2022 14:43:43 +0200 Subject: [PATCH 133/172] perf: improve splash animation --- stream_chat_v1/lib/pages/splash_screen.dart | 167 ++++++++++---------- 1 file changed, 84 insertions(+), 83 deletions(-) diff --git a/stream_chat_v1/lib/pages/splash_screen.dart b/stream_chat_v1/lib/pages/splash_screen.dart index ce3760c4c7..e198b7c103 100644 --- a/stream_chat_v1/lib/pages/splash_screen.dart +++ b/stream_chat_v1/lib/pages/splash_screen.dart @@ -3,55 +3,46 @@ import 'package:lottie/lottie.dart'; mixin SplashScreenStateMixin on State implements TickerProvider { - late Animation animation, scaleAnimation; - late AnimationController _animationController, _scaleAnimationController; - late Animation colorAnimation; - bool animationCompleted = false; + late final _animationController = AnimationController( + vsync: this, + duration: const Duration( + milliseconds: 1000, + ), + ); - void _createAnimations() { - _scaleAnimationController = AnimationController( - vsync: this, - value: 0, - duration: const Duration( - milliseconds: 500, - ), - ); - scaleAnimation = Tween( - begin: 1.0, - end: 1.5, - ).animate(CurvedAnimation( - parent: _scaleAnimationController, - curve: Curves.easeInOutBack, - )); + late final _scaleAnimationController = AnimationController( + vsync: this, + value: 0, + duration: const Duration( + milliseconds: 500, + ), + ); - _animationController = AnimationController( - vsync: this, - duration: const Duration( - milliseconds: 1000, - ), - ); - animation = Tween( - begin: 0.0, - end: 1000.0, - ).animate(CurvedAnimation( - parent: _animationController, - curve: Curves.easeInOut, - )); - colorAnimation = ColorTween( - begin: const Color(0xff005FFF), - end: const Color(0xff005FFF), - ).animate(CurvedAnimation( - parent: _animationController, - curve: Curves.easeInOut, - )); - colorAnimation = ColorTween( - begin: const Color(0xff005FFF), - end: Colors.transparent, - ).animate(CurvedAnimation( - parent: _animationController, - curve: Curves.easeInOut, - )); - } + late final _circleAnimation = Tween( + begin: 0.0, + end: 1000.0, + ).animate(CurvedAnimation( + parent: _animationController, + curve: Curves.easeInOut, + )); + + late final _colorAnimation = ColorTween( + begin: const Color(0xff005FFF), + end: Colors.transparent, + ).animate(CurvedAnimation( + parent: _animationController, + curve: Curves.easeInOut, + )); + + late final _scaleAnimation = Tween( + begin: 1.0, + end: 1.5, + ).animate(CurvedAnimation( + parent: _scaleAnimationController, + curve: Curves.easeInOutCubic, + )); + + bool animationCompleted = false; void forwardAnimations() { _scaleAnimationController.forward().whenComplete(() { @@ -59,38 +50,61 @@ mixin SplashScreenStateMixin on State }); } + void _onAnimationComplete(AnimationStatus status) { + if (status == AnimationStatus.completed) { + setState(() { + animationCompleted = true; + }); + } + } + + @override + void initState() { + _animationController.addStatusListener(_onAnimationComplete); + super.initState(); + } + + @override + void dispose() { + _animationController.removeStatusListener(_onAnimationComplete); + _animationController.dispose(); + _scaleAnimationController.dispose(); + super.dispose(); + } + Widget buildAnimation() => Stack( clipBehavior: Clip.none, alignment: Alignment.center, children: [ AnimatedBuilder( - animation: scaleAnimation, - builder: (context, _) { - return Transform.scale( - scale: scaleAnimation.value, - child: AnimatedBuilder( - animation: colorAnimation, - builder: (context, snapshot) { - return Container( - alignment: Alignment.center, - constraints: const BoxConstraints.expand(), - color: colorAnimation.value, - child: !_animationController.isAnimating - ? Lottie.asset( - 'assets/floating_boat.json', - alignment: Alignment.center, - ) - : const SizedBox(), - ); - }), - ); - }, + animation: _scaleAnimation, + builder: (context, child) => + Transform.scale(scale: _scaleAnimation.value, child: child), + child: AnimatedBuilder( + animation: _colorAnimation, + builder: (context, child) { + return DecoratedBox( + decoration: BoxDecoration(color: _colorAnimation.value), + child: Center( + child: !_animationController.isAnimating + ? child + : const SizedBox(), + ), + ); + }, + child: RepaintBoundary( + child: Lottie.asset( + 'assets/floating_boat.json', + alignment: Alignment.center, + ), + ), + ), ), AnimatedBuilder( - animation: animation, + animation: _circleAnimation, builder: (context, snapshot) { return Transform.scale( - scale: animation.value, + scale: _circleAnimation.value, child: Container( width: 1.0, height: 1.0, @@ -105,17 +119,4 @@ mixin SplashScreenStateMixin on State ), ], ); - - @override - void initState() { - _createAnimations(); - _animationController.addStatusListener((status) { - if (status == AnimationStatus.completed) { - setState(() { - animationCompleted = true; - }); - } - }); - super.initState(); - } } From cee5874b863cf24150420875e977179a2825d5c0 Mon Sep 17 00:00:00 2001 From: Gordon Hayes Date: Mon, 10 Oct 2022 14:49:09 +0200 Subject: [PATCH 134/172] chore: start method with call to initState super --- stream_chat_v1/lib/pages/splash_screen.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stream_chat_v1/lib/pages/splash_screen.dart b/stream_chat_v1/lib/pages/splash_screen.dart index e198b7c103..da075acb49 100644 --- a/stream_chat_v1/lib/pages/splash_screen.dart +++ b/stream_chat_v1/lib/pages/splash_screen.dart @@ -60,8 +60,8 @@ mixin SplashScreenStateMixin on State @override void initState() { - _animationController.addStatusListener(_onAnimationComplete); super.initState(); + _animationController.addStatusListener(_onAnimationComplete); } @override From 201470fc1c267dd17a97d23895abe2f23f275a3f Mon Sep 17 00:00:00 2001 From: Gordon Hayes Date: Mon, 17 Oct 2022 15:01:03 +0200 Subject: [PATCH 135/172] refactor: use gorouter for navigation --- stream_chat_v1/.gitignore | 1 - .../ios/Runner.xcodeproj/project.pbxproj | 2 + stream_chat_v1/lib/app.dart | 167 ++++--- .../lib/pages/advanced_options_page.dart | 165 +++---- .../lib/pages/channel_list_page.dart | 49 +- .../pages/channel_media_display_screen.dart | 25 +- stream_chat_v1/lib/pages/channel_page.dart | 61 +-- .../lib/pages/choose_user_page.dart | 24 +- .../lib/pages/group_chat_details_screen.dart | 145 +++--- .../lib/pages/group_info_screen.dart | 62 ++- stream_chat_v1/lib/pages/home_page.dart | 115 ----- stream_chat_v1/lib/pages/new_chat_screen.dart | 30 +- .../lib/pages/new_group_chat_screen.dart | 436 +++++++++--------- .../lib/pages/pinned_messages_screen.dart | 15 +- .../lib/pages/user_mentions_page.dart | 15 +- stream_chat_v1/lib/routes/app_routes.dart | 242 +++++----- stream_chat_v1/lib/routes/routes.dart | 49 +- stream_chat_v1/lib/state/init_data.dart | 36 ++ .../lib/state/new_group_chat_state.dart | 29 ++ .../utils/local_notification_observer.dart | 69 +++ .../lib/utils/notifications_service.dart | 12 +- stream_chat_v1/lib/widgets/channel_list.dart | 29 +- .../macos/Runner.xcodeproj/project.pbxproj | 11 +- .../macos/Runner/DebugProfile.entitlements | 6 +- .../macos/Runner/Release.entitlements | 4 +- .../macos/Runner/RunnerDebug.entitlements | 16 + stream_chat_v1/pubspec.yaml | 4 +- 27 files changed, 913 insertions(+), 906 deletions(-) delete mode 100644 stream_chat_v1/lib/pages/home_page.dart create mode 100644 stream_chat_v1/lib/state/init_data.dart create mode 100644 stream_chat_v1/lib/state/new_group_chat_state.dart create mode 100644 stream_chat_v1/lib/utils/local_notification_observer.dart create mode 100644 stream_chat_v1/macos/Runner/RunnerDebug.entitlements diff --git a/stream_chat_v1/.gitignore b/stream_chat_v1/.gitignore index 114843e11f..564aecd415 100644 --- a/stream_chat_v1/.gitignore +++ b/stream_chat_v1/.gitignore @@ -32,7 +32,6 @@ /build/ # Web related -lib/generated_plugin_registrant.dart # Symbolication related app.*.symbols diff --git a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj index daeb9c3b00..b6f9d7cf63 100644 --- a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj +++ b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj @@ -251,6 +251,7 @@ "${BUILT_PRODUCTS_DIR}/SwiftyGif/SwiftyGif.framework", "${BUILT_PRODUCTS_DIR}/connectivity_plus/connectivity_plus.framework", "${BUILT_PRODUCTS_DIR}/file_picker/file_picker.framework", + "${BUILT_PRODUCTS_DIR}/file_selector_ios/file_selector_ios.framework", "${BUILT_PRODUCTS_DIR}/flutter_app_badger/flutter_app_badger.framework", "${BUILT_PRODUCTS_DIR}/flutter_local_notifications/flutter_local_notifications.framework", "${BUILT_PRODUCTS_DIR}/flutter_secure_storage/flutter_secure_storage.framework", @@ -282,6 +283,7 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftyGif.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/connectivity_plus.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/file_picker.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/file_selector_ios.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_app_badger.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_local_notifications.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_secure_storage.framework", diff --git a/stream_chat_v1/lib/app.dart b/stream_chat_v1/lib/app.dart index f5f64e3999..f58f7a2606 100644 --- a/stream_chat_v1/lib/app.dart +++ b/stream_chat_v1/lib/app.dart @@ -1,28 +1,31 @@ import 'dart:async'; +import 'package:example/state/init_data.dart'; import 'package:example/pages/choose_user_page.dart'; -import 'package:example/pages/home_page.dart'; -import 'package:example/utils/localizations.dart'; import 'package:example/pages/splash_screen.dart'; +import 'package:example/routes/app_routes.dart'; +import 'package:example/routes/routes.dart'; +import 'package:example/utils/app_config.dart'; +import 'package:example/utils/local_notification_observer.dart'; +import 'package:example/utils/localizations.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:go_router/go_router.dart'; +import 'package:provider/provider.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:stream_chat_localizations/stream_chat_localizations.dart'; import 'package:stream_chat_persistence/stream_chat_persistence.dart'; import 'package:streaming_shared_preferences/streaming_shared_preferences.dart'; -import 'routes/app_routes.dart'; -import 'routes/routes.dart'; - final chatPersistentClient = StreamChatPersistenceClient( logLevel: Level.SEVERE, connectionMode: ConnectionMode.regular, ); -void sampleAppLogHandler(LogRecord record) async { +void _sampleAppLogHandler(LogRecord record) async { if (kDebugMode) StreamChatClient.defaultLogHandler(record); // report errors to setnry.io @@ -34,14 +37,17 @@ void sampleAppLogHandler(LogRecord record) async { } } -StreamChatClient buildStreamChatClient( - String apiKey, { - Level logLevel = Level.INFO, -}) { +StreamChatClient buildStreamChatClient(String apiKey) { + late Level logLevel; + if (kDebugMode) { + logLevel = Level.INFO; + } else { + logLevel = Level.SEVERE; + } return StreamChatClient( apiKey, logLevel: logLevel, - logHandlerFunction: sampleAppLogHandler, + logHandlerFunction: _sampleAppLogHandler, )..chatPersistenceClient = chatPersistentClient; } @@ -54,7 +60,7 @@ class StreamChatSampleApp extends StatefulWidget { class _StreamChatSampleAppState extends State with SplashScreenStateMixin, TickerProviderStateMixin { - InitData? _initData; + final InitNotifier _initNotifier = InitNotifier(); Future _initConnection() async { String? apiKey, userId, token; @@ -66,7 +72,7 @@ class _StreamChatSampleAppState extends State token = await secureStorage.read(key: kStreamToken); } - final client = buildStreamChatClient(apiKey ?? kStreamApiKey); + final client = buildStreamChatClient(apiKey ?? kDefaultStreamApiKey); if (userId != null && token != null) { await client.connectUser( @@ -87,7 +93,7 @@ class _StreamChatSampleAppState extends State _initConnection().then( (initData) { setState(() { - _initData = initData; + _initNotifier.initData = initData; }); final now = DateTime.now().millisecondsSinceEpoch; @@ -107,67 +113,87 @@ class _StreamChatSampleAppState extends State super.initState(); } + final GlobalKey _navigatorKey = GlobalKey(); + LocalNotificationObserver? localNotificationObserver; + + /// Conditionally sets up the router and adding an observer for the + /// current chat client. + GoRouter _setupRouter() { + if (localNotificationObserver != null) { + localNotificationObserver!.dispose(); + } + localNotificationObserver = LocalNotificationObserver( + _initNotifier.initData!.client, _navigatorKey); + + return GoRouter( + refreshListenable: _initNotifier, + initialLocation: Routes.CHANNEL_LIST_PAGE.path, + navigatorKey: _navigatorKey, + observers: [localNotificationObserver!], + redirect: (context, state) { + final loggedIn = + _initNotifier.initData?.client.state.currentUser != null; + final loggingIn = state.subloc == Routes.CHOOSE_USER.path || + state.subloc == Routes.ADVANCED_OPTIONS.path; + + if (!loggedIn) { + return loggingIn ? null : Routes.CHOOSE_USER.path; + } + + // if the user is logged in but still on the login page, send them to + // the home page + if (loggedIn && state.subloc == Routes.CHOOSE_USER.path) { + return Routes.CHANNEL_LIST_PAGE.path; + } + + return null; + }, + routes: appRoutes, + ); + } + @override Widget build(BuildContext context) { return Stack( alignment: Alignment.center, children: [ - if (_initData != null) - PreferenceBuilder( - preference: _initData!.preferences.getInt( - 'theme', - defaultValue: 0, - ), - builder: (context, snapshot) => MaterialApp( - theme: ThemeData.light(), - darkTheme: ThemeData.dark(), - themeMode: { - -1: ThemeMode.dark, - 0: ThemeMode.system, - 1: ThemeMode.light, - }[snapshot], - supportedLocales: const [ - Locale('en'), - Locale('it'), - ], - localizationsDelegates: const [ - AppLocalizationsDelegate(), - GlobalStreamChatLocalizations.delegate, - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - ], - builder: (context, child) => StreamChatConfiguration( - data: StreamChatConfigurationData(), - child: StreamChatTheme( - data: StreamChatThemeData( - brightness: Theme.of(context).brightness, + if (_initNotifier.initData != null) + ChangeNotifierProvider.value( + value: _initNotifier, + builder: (context, child) => Builder( + builder: (context) { + context.watch(); // rebuild on change + return PreferenceBuilder( + preference: _initNotifier.initData!.preferences.getInt( + 'theme', + defaultValue: 0, ), - child: child!, - ), - ), - onGenerateRoute: AppRoutes.generateRoute, - onGenerateInitialRoutes: (initialRouteName) { - if (initialRouteName == Routes.HOME) { - return [ - AppRoutes.generateRoute( - RouteSettings( - name: Routes.HOME, - arguments: HomePageArgs(_initData!.client), - ), - )! - ]; - } - return [ - AppRoutes.generateRoute( - const RouteSettings( - name: Routes.CHOOSE_USER, + builder: (context, snapshot) => MaterialApp.router( + theme: ThemeData.light(), + darkTheme: ThemeData.dark(), + themeMode: const { + -1: ThemeMode.dark, + 0: ThemeMode.system, + 1: ThemeMode.light, + }[snapshot], + supportedLocales: const [ + Locale('en'), + Locale('it'), + ], + localizationsDelegates: const [ + AppLocalizationsDelegate(), + GlobalStreamChatLocalizations.delegate, + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + ], + builder: (context, child) => StreamChat( + client: _initNotifier.initData!.client, + child: child, ), - )! - ]; + routerConfig: _setupRouter(), + ), + ); }, - initialRoute: _initData!.client.state.currentUser == null - ? Routes.CHOOSE_USER - : Routes.HOME, ), ), if (!animationCompleted) buildAnimation(), @@ -175,10 +201,3 @@ class _StreamChatSampleAppState extends State ); } } - -class InitData { - final StreamChatClient client; - final StreamingSharedPreferences preferences; - - InitData(this.client, this.preferences); -} diff --git a/stream_chat_v1/lib/pages/advanced_options_page.dart b/stream_chat_v1/lib/pages/advanced_options_page.dart index 4cd5e099fc..ab50871f71 100644 --- a/stream_chat_v1/lib/pages/advanced_options_page.dart +++ b/stream_chat_v1/lib/pages/advanced_options_page.dart @@ -1,13 +1,15 @@ import 'package:example/app.dart'; -import 'package:example/pages/home_page.dart'; +import 'package:example/state/init_data.dart'; import 'package:example/utils/localizations.dart'; import 'package:example/routes/routes.dart'; import 'package:example/widgets/stream_version.dart'; import 'package:flutter/material.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:go_router/go_router.dart'; +import 'package:provider/provider.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -import 'choose_user_page.dart'; +import 'package:example/pages/choose_user_page.dart'; class AdvancedOptionsPage extends StatefulWidget { const AdvancedOptionsPage({super.key}); @@ -41,6 +43,86 @@ class _AdvancedOptionsPageState extends State { super.dispose(); } + Future _login() async { + if (loading) { + return; + } + if (_formKey.currentState!.validate()) { + final apiKey = _apiKeyController.text; + final userId = _userIdController.text; + final userToken = _userTokenController.text; + final username = _usernameController.text; + + loading = true; + showDialog( + barrierDismissible: false, + context: context, + barrierColor: StreamChatTheme.of(context).colorTheme.overlay, + builder: (context) => Center( + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16), + color: StreamChatTheme.of(context).colorTheme.barsBg, + ), + height: 100, + width: 100, + child: const Center( + child: CircularProgressIndicator(), + ), + ), + ), + ); + + final client = buildStreamChatClient(apiKey); + final router = GoRouter.of(context); + final initNotifier = context.read(); + + try { + await client.connectUser( + User( + id: userId, + extraData: { + 'name': username, + }, + ), + userToken, + ); + + const secureStorage = FlutterSecureStorage(); + await Future.wait([ + secureStorage.write( + key: kStreamApiKey, + value: apiKey, + ), + secureStorage.write( + key: kStreamUserId, + value: userId, + ), + secureStorage.write( + key: kStreamToken, + value: userToken, + ), + ]); + } catch (e) { + debugPrint(e.toString()); + var errorText = AppLocalizations.of(context).errorConnecting; + if (e is Map) { + errorText = e['message'] ?? errorText; + } + Navigator.of(context).pop(); + setState(() { + _apiKeyError = errorText.toUpperCase(); + }); + loading = false; + return; + } + loading = false; + initNotifier.initData = initNotifier.initData!.copyWith(client: client); + + router.goNamed(Routes.CHOOSE_USER.name); + } + } + @override Widget build(BuildContext context) { return Scaffold( @@ -260,6 +342,7 @@ class _AdvancedOptionsPageState extends State { ), ), ), + onPressed: _login, child: Text( AppLocalizations.of(context).login, style: TextStyle( @@ -271,84 +354,6 @@ class _AdvancedOptionsPageState extends State { : Colors.white, ), ), - onPressed: () async { - if (loading) { - return; - } - if (_formKey.currentState!.validate()) { - final apiKey = _apiKeyController.text; - final userId = _userIdController.text; - final userToken = _userTokenController.text; - final username = _usernameController.text; - - loading = true; - showDialog( - barrierDismissible: false, - context: context, - barrierColor: - StreamChatTheme.of(context).colorTheme.overlay, - builder: (context) => Center( - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(16), - color: StreamChatTheme.of(context) - .colorTheme - .barsBg, - ), - height: 100, - width: 100, - child: const Center( - child: CircularProgressIndicator(), - ), - ), - ), - ); - - final client = buildStreamChatClient(apiKey); - final navigator = Navigator.of(context); - - try { - await client.connectUser( - User(id: userId, extraData: { - 'name': username, - }), - userToken, - ); - - const secureStorage = FlutterSecureStorage(); - secureStorage.write( - key: kStreamApiKey, - value: apiKey, - ); - secureStorage.write( - key: kStreamUserId, - value: userId, - ); - secureStorage.write( - key: kStreamToken, - value: userToken, - ); - } catch (e) { - var errorText = - AppLocalizations.of(context).errorConnecting; - if (e is Map) { - errorText = e['message'] ?? errorText; - } - Navigator.pop(context); - setState(() { - _apiKeyError = errorText.toUpperCase(); - }); - loading = false; - return; - } - loading = false; - await navigator.pushNamedAndRemoveUntil( - Routes.HOME, - ModalRoute.withName(Routes.HOME), - arguments: HomePageArgs(client), - ); - } - }, ), const StreamVersion(), ], diff --git a/stream_chat_v1/lib/pages/channel_list_page.dart b/stream_chat_v1/lib/pages/channel_list_page.dart index 7812d7b88c..7ee34bd876 100644 --- a/stream_chat_v1/lib/pages/channel_list_page.dart +++ b/stream_chat_v1/lib/pages/channel_list_page.dart @@ -1,17 +1,21 @@ import 'dart:async'; -import 'package:example/utils/localizations.dart'; -import 'package:example/routes/routes.dart'; +import 'package:example/app.dart'; +import 'package:example/state/init_data.dart'; import 'package:example/pages/user_mentions_page.dart'; +import 'package:example/routes/routes.dart'; +import 'package:example/utils/app_config.dart'; +import 'package:example/utils/localizations.dart'; +import 'package:example/widgets/channel_list.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_app_badger/flutter_app_badger.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:go_router/go_router.dart'; +import 'package:provider/provider.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:streaming_shared_preferences/streaming_shared_preferences.dart'; -import 'package:example/widgets/channel_list.dart'; - class ChannelListPage extends StatefulWidget { const ChannelListPage({ Key? key, @@ -71,12 +75,10 @@ class _ChannelListPageState extends State { return Scaffold( backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, appBar: StreamChannelListHeader( - onNewChatButtonTap: () { - Navigator.pushNamed(context, Routes.NEW_CHAT); - }, - preNavigationCallback: () { - FocusScope.of(context).requestFocus(FocusNode()); - }, + onNewChatButtonTap: () => + GoRouter.of(context).pushNamed(Routes.NEW_CHAT.name), + preNavigationCallback: () => + FocusScope.of(context).requestFocus(FocusNode()), ), drawer: LeftDrawer( user: user, @@ -188,10 +190,8 @@ class LeftDrawer extends StatelessWidget { .withOpacity(.5), ), onTap: () { - Navigator.popAndPushNamed( - context, - Routes.NEW_CHAT, - ); + Navigator.of(context).pop(); + GoRouter.of(context).pushNamed(Routes.NEW_CHAT.name); }, title: Text( AppLocalizations.of(context).newDirectMessage, @@ -208,10 +208,8 @@ class LeftDrawer extends StatelessWidget { .withOpacity(.5), ), onTap: () { - Navigator.popAndPushNamed( - context, - Routes.NEW_GROUP_CHAT, - ); + Navigator.of(context).pop(); + GoRouter.of(context).pushNamed(Routes.NEW_GROUP_CHAT.name); }, title: Text( AppLocalizations.of(context).newGroup, @@ -226,22 +224,21 @@ class LeftDrawer extends StatelessWidget { child: ListTile( onTap: () async { final client = StreamChat.of(context).client; - final navigator = - Navigator.of(context, rootNavigator: true); - Navigator.pop(context); + final router = GoRouter.of(context); + final initNotifier = context.read(); if (!kIsWeb) { const secureStorage = FlutterSecureStorage(); await secureStorage.deleteAll(); } - client.disconnectUser(); + await client.disconnectUser(flushChatPersistence: true); await client.dispose(); + initNotifier.initData = initNotifier.initData!.copyWith( + client: + buildStreamChatClient(kDefaultStreamApiKey)); - await navigator.pushNamedAndRemoveUntil( - Routes.CHOOSE_USER, - ModalRoute.withName(Routes.CHOOSE_USER), - ); + router.goNamed(Routes.CHOOSE_USER.name); }, leading: StreamSvgIcon.user( color: StreamChatTheme.of(context) diff --git a/stream_chat_v1/lib/pages/channel_media_display_screen.dart b/stream_chat_v1/lib/pages/channel_media_display_screen.dart index e16cb933e7..18bd7a5cc0 100644 --- a/stream_chat_v1/lib/pages/channel_media_display_screen.dart +++ b/stream_chat_v1/lib/pages/channel_media_display_screen.dart @@ -1,10 +1,10 @@ import 'package:example/utils/localizations.dart'; -import 'package:example/routes/routes.dart'; import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:video_player/video_player.dart'; -import 'channel_page.dart'; +import '../routes/routes.dart'; class ChannelMediaDisplayScreen extends StatefulWidget { final StreamMessageThemeData messageTheme; @@ -156,23 +156,16 @@ class _ChannelMediaDisplayScreenState extends State { startIndex: position, userName: media[position].message.user!.name, onShowMessage: (m, c) async { - final client = - StreamChat.of(context).client; - final navigator = Navigator.of(context); - final message = m; - final channel = client.channel( - c.type, - id: c.id, - ); + final router = GoRouter.of(context); if (channel.state == null) { await channel.watch(); } - navigator.pushNamed( - Routes.CHANNEL_PAGE, - arguments: ChannelPageArgs( - channel: channel, - initialMessage: message, - ), + router.pushNamed( + Routes.CHANNEL_PAGE.name, + params: + Routes.CHANNEL_PAGE.params(channel), + queryParams: + Routes.CHANNEL_PAGE.queryParams(m), ); }, ), diff --git a/stream_chat_v1/lib/pages/channel_page.dart b/stream_chat_v1/lib/pages/channel_page.dart index 23e57d7a6b..e2714ee651 100644 --- a/stream_chat_v1/lib/pages/channel_page.dart +++ b/stream_chat_v1/lib/pages/channel_page.dart @@ -2,21 +2,9 @@ import 'package:collection/collection.dart'; import 'package:example/routes/routes.dart'; import 'package:example/pages/thread_page.dart'; import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -import 'chat_info_screen.dart'; -import 'group_info_screen.dart'; - -class ChannelPageArgs { - final Channel? channel; - final Message? initialMessage; - - const ChannelPageArgs({ - this.channel, - this.initialMessage, - }); -} - class ChannelPage extends StatefulWidget { final int? initialScrollIndex; final double? initialAlignment; @@ -63,9 +51,10 @@ class _ChannelPageState extends State { backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, appBar: StreamChannelHeader( showTypingIndicator: false, + onBackPressed: () => GoRouter.of(context).pop(), onImageTap: () async { final channel = StreamChannel.of(context).channel; - final navigator = Navigator.of(context); + final router = GoRouter.of(context); if (channel.memberCount == 2 && channel.isDistinct) { final currentUser = StreamChat.of(context).currentUser; @@ -73,34 +62,16 @@ class _ChannelPageState extends State { (element) => element.user!.id != currentUser!.id, ); if (otherUser != null) { - final pop = await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => StreamChannel( - channel: channel, - child: ChatInfoScreen( - messageTheme: StreamChatTheme.of(context).ownMessageTheme, - user: otherUser.user, - ), - ), - ), + router.pushNamed( + Routes.CHAT_INFO_SCREEN.name, + params: Routes.CHAT_INFO_SCREEN.params(channel), + extra: otherUser.user, ); - - if (pop == true) { - navigator.pop(); - } } } else { - await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => StreamChannel( - channel: channel, - child: GroupInfoScreen( - messageTheme: StreamChatTheme.of(context).ownMessageTheme, - ), - ), - ), + GoRouter.of(context).pushNamed( + Routes.GROUP_INFO_SCREEN.name, + params: Routes.GROUP_INFO_SCREEN.params(channel), ); } }, @@ -117,7 +88,7 @@ class _ChannelPageState extends State { onMessageSwiped: _reply, messageFilter: defaultFilter, messageBuilder: (context, details, messages, defaultMessage) { - final navigator = Navigator.of(context); + final router = GoRouter.of(context); return defaultMessage.copyWith( onReplyTap: _reply, onShowMessage: (m, c) async { @@ -130,12 +101,10 @@ class _ChannelPageState extends State { if (channel.state == null) { await channel.watch(); } - navigator.pushReplacementNamed( - Routes.CHANNEL_PAGE, - arguments: ChannelPageArgs( - channel: channel, - initialMessage: message, - ), + router.goNamed( + Routes.CHANNEL_PAGE.name, + params: Routes.CHANNEL_PAGE.params(channel), + queryParams: Routes.CHANNEL_PAGE.queryParams(message), ); }, deletedBottomRowBuilder: (context, message) { diff --git a/stream_chat_v1/lib/pages/choose_user_page.dart b/stream_chat_v1/lib/pages/choose_user_page.dart index 37969c6138..d5be33ad8d 100644 --- a/stream_chat_v1/lib/pages/choose_user_page.dart +++ b/stream_chat_v1/lib/pages/choose_user_page.dart @@ -1,12 +1,13 @@ -import 'package:example/app.dart'; +import 'package:example/state/init_data.dart'; import 'package:example/utils/app_config.dart'; -import 'package:example/pages/home_page.dart'; import 'package:example/utils/localizations.dart'; import 'package:example/widgets/stream_version.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:go_router/go_router.dart'; +import 'package:provider/provider.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import '../routes/routes.dart'; @@ -94,12 +95,10 @@ class ChooseUserPage extends StatelessWidget { ), ); - final client = StreamChatClient( - kDefaultStreamApiKey, - logLevel: Level.INFO, - )..chatPersistenceClient = chatPersistentClient; + final client = + context.read().initData!.client; - final navigator = Navigator.of(context); + final router = GoRouter.of(context); await client.connectUser( user, @@ -121,11 +120,7 @@ class ChooseUserPage extends StatelessWidget { value: token, ); } - navigator.pushNamedAndRemoveUntil( - Routes.HOME, - ModalRoute.withName(Routes.HOME), - arguments: HomePageArgs(client), - ); + router.replaceNamed(Routes.CHANNEL_LIST_PAGE.name); }, leading: StreamUserAvatar( user: user, @@ -157,9 +152,8 @@ class ChooseUserPage extends StatelessWidget { ); }), ListTile( - onTap: () { - Navigator.pushNamed(context, Routes.ADVANCED_OPTIONS); - }, + onTap: () => GoRouter.of(context) + .pushNamed(Routes.ADVANCED_OPTIONS.name), leading: CircleAvatar( backgroundColor: StreamChatTheme.of(context).colorTheme.borders, diff --git a/stream_chat_v1/lib/pages/group_chat_details_screen.dart b/stream_chat_v1/lib/pages/group_chat_details_screen.dart index 8b813ec3ed..488b3d55ca 100644 --- a/stream_chat_v1/lib/pages/group_chat_details_screen.dart +++ b/stream_chat_v1/lib/pages/group_chat_details_screen.dart @@ -1,16 +1,17 @@ +import 'package:example/state/new_group_chat_state.dart'; import 'package:example/utils/localizations.dart'; import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -import 'channel_page.dart'; import '../routes/routes.dart'; class GroupChatDetailsScreen extends StatefulWidget { - final List? selectedUsers; + final NewGroupChatState groupChatState; const GroupChatDetailsScreen({ Key? key, - required this.selectedUsers, + required this.groupChatState, }) : super(key: key); @override @@ -18,14 +19,12 @@ class GroupChatDetailsScreen extends StatefulWidget { } class _GroupChatDetailsScreenState extends State { - late final _selectedUsers = [...?widget.selectedUsers]; - late final TextEditingController _groupNameController = TextEditingController()..addListener(_groupNameListener); bool _isGroupNameEmpty = true; - int get _totalUsers => _selectedUsers.length; + int get _totalUsers => widget.groupChatState.users.length; void _groupNameListener() { final name = _groupNameController.text; @@ -48,7 +47,7 @@ class _GroupChatDetailsScreenState extends State { Widget build(BuildContext context) { return WillPopScope( onWillPop: () async { - Navigator.pop(context, _selectedUsers); + GoRouter.of(context).pop(); return false; }, child: Scaffold( @@ -123,21 +122,21 @@ class _GroupChatDetailsScreenState extends State { try { final groupName = _groupNameController.text; final client = StreamChat.of(context).client; - final navigator = Navigator.of(context); + final router = GoRouter.of(context); final channel = client.channel('messaging', id: const Uuid().v4(), extraData: { 'members': [ client.state.currentUser!.id, - ..._selectedUsers.map((e) => e.id), + ...widget.groupChatState.users + .map((e) => e.id), ], 'name': groupName, }); await channel.watch(); - navigator.pushNamedAndRemoveUntil( - Routes.CHANNEL_PAGE, - ModalRoute.withName(Routes.CHANNEL_LIST_PAGE), - arguments: ChannelPageArgs(channel: channel), + router.goNamed( + Routes.CHANNEL_PAGE.name, + params: Routes.CHANNEL_PAGE.params(channel), ); } catch (err) { _showErrorAlert(); @@ -192,67 +191,73 @@ class _GroupChatDetailsScreenState extends State { ), ), ), - Expanded( - child: GestureDetector( - behavior: HitTestBehavior.opaque, - onPanDown: (_) => FocusScope.of(context).unfocus(), - child: ListView.separated( - itemCount: _selectedUsers.length + 1, - separatorBuilder: (_, __) => Container( - height: 1, - color: StreamChatTheme.of(context).colorTheme.borders, - ), - itemBuilder: (_, index) { - if (index == _selectedUsers.length) { - return Container( - height: 1, - color: StreamChatTheme.of(context) - .colorTheme - .borders, - ); - } - final user = _selectedUsers[index]; - return ListTile( - key: ObjectKey(user), - leading: StreamUserAvatar( - user: user, - constraints: const BoxConstraints.tightFor( - width: 40, - height: 40, - ), - ), - title: Text( - user.name, - style: - const TextStyle(fontWeight: FontWeight.bold), - ), - contentPadding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 8, - ), - trailing: IconButton( - icon: Icon( - Icons.clear_rounded, + AnimatedBuilder( + animation: widget.groupChatState, + builder: (context, child) { + return Expanded( + child: GestureDetector( + behavior: HitTestBehavior.opaque, + onPanDown: (_) => FocusScope.of(context).unfocus(), + child: ListView.separated( + itemCount: widget.groupChatState.users.length + 1, + separatorBuilder: (_, __) => Container( + height: 1, color: StreamChatTheme.of(context) .colorTheme - .textHighEmphasis, + .borders, ), - padding: const EdgeInsets.all(0), - splashRadius: 24, - onPressed: () { - setState(() { - _selectedUsers.remove(user); - }); - if (_selectedUsers.isEmpty) { - Navigator.pop(context, _selectedUsers); + itemBuilder: (_, index) { + if (index == + widget.groupChatState.users.length) { + return Container( + height: 1, + color: StreamChatTheme.of(context) + .colorTheme + .borders, + ); } + final user = widget.groupChatState.users + .elementAt(index); + return ListTile( + key: ObjectKey(user), + leading: StreamUserAvatar( + user: user, + constraints: const BoxConstraints.tightFor( + width: 40, + height: 40, + ), + ), + title: Text( + user.name, + style: const TextStyle( + fontWeight: FontWeight.bold), + ), + contentPadding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 8, + ), + trailing: IconButton( + icon: Icon( + Icons.clear_rounded, + color: StreamChatTheme.of(context) + .colorTheme + .textHighEmphasis, + ), + padding: const EdgeInsets.all(0), + splashRadius: 24, + onPressed: () { + widget.groupChatState.removeUser(user); + if (widget.groupChatState.users.isEmpty) { + GoRouter.of(context).pop(); + } + }, + ), + ); }, ), - ); - }, - ), - ), - ), + ), + ); + }), ], ), ); @@ -308,6 +313,7 @@ class _GroupChatDetailsScreenState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ TextButton( + onPressed: GoRouter.of(context).pop, child: Text( AppLocalizations.of(context).ok, style: StreamChatTheme.of(context) @@ -318,9 +324,6 @@ class _GroupChatDetailsScreenState extends State { .colorTheme .accentPrimary), ), - onPressed: () { - Navigator.of(context).pop(); - }, ), ], ), diff --git a/stream_chat_v1/lib/pages/group_info_screen.dart b/stream_chat_v1/lib/pages/group_info_screen.dart index 95c0680595..303858e891 100644 --- a/stream_chat_v1/lib/pages/group_info_screen.dart +++ b/stream_chat_v1/lib/pages/group_info_screen.dart @@ -2,14 +2,14 @@ import 'dart:async'; import 'package:collection/collection.dart' show IterableExtension; import 'package:example/pages/channel_file_display_screen.dart'; +import 'package:example/routes/routes.dart'; import 'package:example/utils/localizations.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'channel_media_display_screen.dart'; -import 'channel_page.dart'; -import 'chat_info_screen.dart'; import 'pinned_messages_screen.dart'; class GroupInfoScreen extends StatefulWidget { @@ -647,7 +647,7 @@ class _GroupInfoScreenState extends State { onTap: () async { final streamChannel = StreamChannel.of(context); final streamChat = StreamChat.of(context); - final navigator = Navigator.of(context); + final router = GoRouter.of(context); final res = await showConfirmationBottomSheet( context, title: AppLocalizations.of(context).leaveConversation, @@ -662,7 +662,7 @@ class _GroupInfoScreenState extends State { if (res == true) { final channel = streamChannel.channel; await channel.removeMembers([streamChat.currentUser!.id]); - navigator.pop(); + router.pop(); } }, ), @@ -865,7 +865,7 @@ class _GroupInfoScreenState extends State { AppLocalizations.of(context).viewInfo, () async { final client = StreamChat.of(context).client; - final navigator = Navigator.of(context); + final router = GoRouter.of(context); final c = client.channel('messaging', extraData: { 'members': [ @@ -876,16 +876,10 @@ class _GroupInfoScreenState extends State { await c.watch(); - await navigator.push( - MaterialPageRoute( - builder: (context) => StreamChannel( - channel: c, - child: ChatInfoScreen( - messageTheme: widget.messageTheme, - user: user, - ), - ), - ), + router.pushNamed( + Routes.CHAT_INFO_SCREEN.name, + params: Routes.CHAT_INFO_SCREEN.params(c), + extra: user, ); }, ), @@ -901,7 +895,7 @@ class _GroupInfoScreenState extends State { AppLocalizations.of(context).message, () async { final client = StreamChat.of(context).client; - final navigator = Navigator.of(context); + final router = GoRouter.of(context); final c = client.channel('messaging', extraData: { 'members': [ @@ -912,13 +906,9 @@ class _GroupInfoScreenState extends State { await c.watch(); - await navigator.push( - MaterialPageRoute( - builder: (context) => StreamChannel( - channel: c, - child: const ChannelPage(), - ), - ), + router.pushNamed( + Routes.CHANNEL_PAGE.name, + params: Routes.CHANNEL_PAGE.params(c), ); }, ), @@ -934,7 +924,7 @@ class _GroupInfoScreenState extends State { size: 24.0, ), AppLocalizations.of(context).removeFromGroup, () async { - final navigator = Navigator.of(context); + final router = GoRouter.of(context); final res = await showConfirmationBottomSheet( context, title: AppLocalizations.of(context).removeMember, @@ -949,21 +939,23 @@ class _GroupInfoScreenState extends State { if (res == true) { await channel.removeMembers([user.id]); } - navigator.pop(); + router.pop(); }, color: StreamChatTheme.of(context).colorTheme.accentError), _buildModalListTile( - context, - StreamSvgIcon.closeSmall( - color: StreamChatTheme.of(context) - .colorTheme - .textLowEmphasis, - size: 24.0, - ), - AppLocalizations.of(context).cancel, () { - Navigator.pop(context); - }), + context, + StreamSvgIcon.closeSmall( + color: StreamChatTheme.of(context) + .colorTheme + .textLowEmphasis, + size: 24.0, + ), + AppLocalizations.of(context).cancel, + () { + Navigator.pop(context); + }, + ), ], ), ), diff --git a/stream_chat_v1/lib/pages/home_page.dart b/stream_chat_v1/lib/pages/home_page.dart deleted file mode 100644 index 623844af36..0000000000 --- a/stream_chat_v1/lib/pages/home_page.dart +++ /dev/null @@ -1,115 +0,0 @@ -import 'dart:async'; - -import 'package:example/pages/channel_page.dart'; -import 'package:example/utils/notifications_service.dart'; -import 'package:example/routes/app_routes.dart'; -import 'package:example/routes/routes.dart'; -import 'package:flutter/material.dart'; -import 'package:stream_chat_flutter/stream_chat_flutter.dart'; - -class MyObserver extends NavigatorObserver { - Route? currentRoute; - late final StreamSubscription _subscription; - - MyObserver( - StreamChatClient client, - GlobalKey navigatorKey, - ) { - _subscription = client - .on( - EventType.messageNew, - EventType.notificationMessageNew, - ) - .listen((event) { - if (event.message?.user?.id == client.state.currentUser?.id) { - return; - } - final channelId = event.channelId; - if (currentRoute?.settings.name == Routes.CHANNEL_PAGE) { - final args = currentRoute?.settings.arguments as ChannelPageArgs; - if (args.channel?.id == channelId) { - return; - } - } - - showLocalNotification( - event, - client.state.currentUser!.id, - navigatorKey.currentState!.context, - ); - }); - } - - @override - void didPop(Route route, Route? previousRoute) { - currentRoute = route; - } - - @override - void didPush(Route route, Route? previousRoute) { - currentRoute = route; - } - - @override - void didRemove(Route route, Route? previousRoute) { - currentRoute = route; - } - - @override - void didReplace({Route? newRoute, Route? oldRoute}) { - currentRoute = newRoute; - } - - void dispose() { - _subscription.cancel(); - } -} - -class HomePageArgs { - final StreamChatClient chatClient; - - HomePageArgs(this.chatClient); -} - -class HomePage extends StatefulWidget { - const HomePage({ - Key? key, - required this.chatClient, - }) : super(key: key); - - final StreamChatClient chatClient; - - @override - State createState() => _HomePageState(); -} - -class _HomePageState extends State { - final GlobalKey _navigatorKey = GlobalKey(); - MyObserver? _observer; - - @override - Widget build(BuildContext context) { - return StreamChat( - client: widget.chatClient, - child: WillPopScope( - onWillPop: () async { - final canPop = await _navigatorKey.currentState?.maybePop() ?? false; - return !canPop; - }, - child: Navigator( - key: _navigatorKey, - onGenerateRoute: AppRoutes.generateRoute, - initialRoute: Routes.CHANNEL_LIST_PAGE, - observers: [_observer!], - ), - ), - ); - } - - @override - void didChangeDependencies() { - _observer?.dispose(); - _observer = MyObserver(widget.chatClient, _navigatorKey); - super.didChangeDependencies(); - } -} diff --git a/stream_chat_v1/lib/pages/new_chat_screen.dart b/stream_chat_v1/lib/pages/new_chat_screen.dart index 5b06df552b..45c3528091 100644 --- a/stream_chat_v1/lib/pages/new_chat_screen.dart +++ b/stream_chat_v1/lib/pages/new_chat_screen.dart @@ -2,9 +2,9 @@ import 'dart:async'; import 'package:example/utils/localizations.dart'; import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -import 'channel_page.dart'; import '../widgets/chips_input_text_field.dart'; import '../routes/routes.dart'; @@ -61,13 +61,14 @@ class _NewChatScreenState extends State { _userNameQuery = _controller.text; _isSearchActive = _userNameQuery.isNotEmpty; }); + + userListController.filter = Filter.and([ + if (_userNameQuery.isNotEmpty) + Filter.autoComplete('name', _userNameQuery), + Filter.notEqual('id', StreamChat.of(context).currentUser!.id), + ]); + userListController.doInitialLoad(); } - userListController.filter = Filter.and([ - if (_userNameQuery.isNotEmpty) - Filter.autoComplete('name', _userNameQuery), - Filter.notEqual('id', StreamChat.of(context).currentUser!.id), - ]); - userListController.doInitialLoad(); }); } @@ -248,9 +249,8 @@ class _NewChatScreenState extends State { if (!_isSearchActive && !_selectedUsers.isNotEmpty) InkWell( onTap: () { - Navigator.pushNamed( - context, - Routes.NEW_GROUP_CHAT, + GoRouter.of(context).pushNamed( + Routes.NEW_GROUP_CHAT.name, ); }, child: Padding( @@ -311,8 +311,6 @@ class _NewChatScreenState extends State { onPanDown: (_) => FocusScope.of(context).unfocus(), child: StreamUserListView( controller: userListController, - // groupAlphabetically: - // _isSearchActive ? false : true, onUserTap: (user) { _controller.clear(); if (!_selectedUsers.contains(user)) { @@ -409,11 +407,9 @@ class _NewChatScreenState extends State { return message; }, onMessageSent: (m) { - Navigator.pushNamedAndRemoveUntil( - context, - Routes.CHANNEL_PAGE, - ModalRoute.withName(Routes.CHANNEL_LIST_PAGE), - arguments: ChannelPageArgs(channel: channel), + GoRouter.of(context).goNamed( + Routes.CHANNEL_PAGE.name, + params: Routes.CHANNEL_PAGE.params(channel!), ); }, ), diff --git a/stream_chat_v1/lib/pages/new_group_chat_screen.dart b/stream_chat_v1/lib/pages/new_group_chat_screen.dart index 8446e6a286..fbe2a71f63 100644 --- a/stream_chat_v1/lib/pages/new_group_chat_screen.dart +++ b/stream_chat_v1/lib/pages/new_group_chat_screen.dart @@ -1,7 +1,9 @@ import 'dart:async'; +import 'package:example/state/new_group_chat_state.dart'; import 'package:example/utils/localizations.dart'; import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import '../routes/routes.dart'; @@ -20,7 +22,7 @@ class _NewGroupChatScreenState extends State { String _userNameQuery = ''; - final _selectedUsers = {}; + final groupChatState = NewGroupChatState(); bool _isSearchActive = false; @@ -69,250 +71,240 @@ class _NewGroupChatScreenState extends State { @override Widget build(BuildContext context) { - return Scaffold( - backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, - appBar: AppBar( - elevation: 1, - backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, - leading: const StreamBackButton(), - title: Text( - AppLocalizations.of(context).addGroupMembers, - style: TextStyle( - color: StreamChatTheme.of(context).colorTheme.textHighEmphasis, - fontSize: 16, - ), - ), - centerTitle: true, - actions: [ - if (_selectedUsers.isNotEmpty) - IconButton( - icon: StreamSvgIcon.arrowRight( - color: StreamChatTheme.of(context).colorTheme.accentPrimary, + return AnimatedBuilder( + animation: groupChatState, + builder: (context, child) { + final state = groupChatState; + return Scaffold( + backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, + appBar: AppBar( + elevation: 1, + backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, + leading: const StreamBackButton(), + title: Text( + AppLocalizations.of(context).addGroupMembers, + style: TextStyle( + color: StreamChatTheme.of(context).colorTheme.textHighEmphasis, + fontSize: 16, ), - onPressed: () async { - final updatedList = await Navigator.pushNamed( - context, - Routes.NEW_GROUP_CHAT_DETAILS, - arguments: _selectedUsers.toList(growable: false), - ); - if (updatedList != null) { - setState(() { - _selectedUsers - ..clear() - ..addAll(updatedList as Iterable); - }); - } - }, - ) - ], - ), - body: StreamConnectionStatusBuilder( - statusBuilder: (context, status) { - String statusString = ''; - bool showStatus = true; - - switch (status) { - case ConnectionStatus.connected: - statusString = AppLocalizations.of(context).connected; - showStatus = false; - break; - case ConnectionStatus.connecting: - statusString = AppLocalizations.of(context).reconnecting; - break; - case ConnectionStatus.disconnected: - statusString = AppLocalizations.of(context).disconnected; - break; - } - return StreamInfoTile( - showMessage: showStatus, - tileAnchor: Alignment.topCenter, - childAnchor: Alignment.topCenter, - message: statusString, - child: NestedScrollView( - floatHeaderSlivers: true, - headerSliverBuilder: - (BuildContext context, bool innerBoxIsScrolled) { - return [ - SliverToBoxAdapter( - child: SearchTextField( - controller: _controller, - hintText: AppLocalizations.of(context).search, - ), + ), + centerTitle: true, + actions: [ + if (state.users.isNotEmpty) + IconButton( + icon: StreamSvgIcon.arrowRight( + color: StreamChatTheme.of(context).colorTheme.accentPrimary, ), - if (_selectedUsers.isNotEmpty) - SliverToBoxAdapter( - child: SizedBox( - height: 104, - child: ListView.separated( - scrollDirection: Axis.horizontal, - itemCount: _selectedUsers.length, - padding: const EdgeInsets.all(8), - separatorBuilder: (_, __) => - const SizedBox(width: 16), - itemBuilder: (_, index) { - final user = _selectedUsers.elementAt(index); - return Column( - children: [ - Stack( + onPressed: () async { + GoRouter.of(context).pushNamed( + Routes.NEW_GROUP_CHAT_DETAILS.name, + extra: state, + ); + }, + ) + ], + ), + body: StreamConnectionStatusBuilder( + statusBuilder: (context, status) { + String statusString = ''; + bool showStatus = true; + + switch (status) { + case ConnectionStatus.connected: + statusString = AppLocalizations.of(context).connected; + showStatus = false; + break; + case ConnectionStatus.connecting: + statusString = AppLocalizations.of(context).reconnecting; + break; + case ConnectionStatus.disconnected: + statusString = AppLocalizations.of(context).disconnected; + break; + } + return StreamInfoTile( + showMessage: showStatus, + tileAnchor: Alignment.topCenter, + childAnchor: Alignment.topCenter, + message: statusString, + child: NestedScrollView( + floatHeaderSlivers: true, + headerSliverBuilder: + (BuildContext context, bool innerBoxIsScrolled) { + return [ + SliverToBoxAdapter( + child: SearchTextField( + controller: _controller, + hintText: AppLocalizations.of(context).search, + ), + ), + if (state.users.isNotEmpty) + SliverToBoxAdapter( + child: SizedBox( + height: 104, + child: ListView.separated( + scrollDirection: Axis.horizontal, + itemCount: state.users.length, + padding: const EdgeInsets.all(8), + separatorBuilder: (_, __) => + const SizedBox(width: 16), + itemBuilder: (_, index) { + final user = state.users.elementAt(index); + return Column( children: [ - StreamUserAvatar( - onlineIndicatorAlignment: - const Alignment(0.9, 0.9), - user: user, - showOnlineStatus: true, - borderRadius: BorderRadius.circular(32), - constraints: - const BoxConstraints.tightFor( - height: 64, - width: 64, - ), - ), - Positioned( - top: -4, - right: -4, - child: GestureDetector( - onTap: () { - if (_selectedUsers.contains(user)) { - setState(() => - _selectedUsers.remove(user)); - } - }, - child: Container( - decoration: BoxDecoration( - color: StreamChatTheme.of(context) - .colorTheme - .appBg, - shape: BoxShape.circle, - border: Border.all( - color: StreamChatTheme.of(context) - .colorTheme - .appBg, - ), - ), - child: StreamSvgIcon.close( - color: StreamChatTheme.of(context) - .colorTheme - .textHighEmphasis, - size: 24, + Stack( + children: [ + StreamUserAvatar( + onlineIndicatorAlignment: + const Alignment(0.9, 0.9), + user: user, + showOnlineStatus: true, + borderRadius: + BorderRadius.circular(32), + constraints: + const BoxConstraints.tightFor( + height: 64, + width: 64, ), ), + Positioned( + top: -4, + right: -4, + child: GestureDetector( + onTap: () { + groupChatState.removeUser(user); + }, + child: Container( + decoration: BoxDecoration( + color: + StreamChatTheme.of(context) + .colorTheme + .appBg, + shape: BoxShape.circle, + border: Border.all( + color: StreamChatTheme.of( + context) + .colorTheme + .appBg, + ), + ), + child: StreamSvgIcon.close( + color: + StreamChatTheme.of(context) + .colorTheme + .textHighEmphasis, + size: 24, + ), + ), + ), + ) + ], + ), + const SizedBox(height: 4), + Text( + user.name.split(' ')[0], + style: const TextStyle( + fontWeight: FontWeight.bold, + fontSize: 12, ), - ) + ), ], - ), - const SizedBox(height: 4), - Text( - user.name.split(' ')[0], - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 12, - ), - ), - ], - ); - }, - ), - ), - ), - SliverPersistentHeader( - pinned: true, - delegate: _HeaderDelegate( - height: 32, - child: Container( - width: double.maxFinite, - decoration: BoxDecoration( - gradient: - StreamChatTheme.of(context).colorTheme.bgGradient, - ), - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 8, - horizontal: 8, + ); + }, + ), ), - child: Text( - _isSearchActive - ? '${AppLocalizations.of(context).matchesFor} "$_userNameQuery"' - : AppLocalizations.of(context).onThePlatorm, - style: TextStyle( - color: StreamChatTheme.of(context) + ), + SliverPersistentHeader( + pinned: true, + delegate: _HeaderDelegate( + height: 32, + child: Container( + width: double.maxFinite, + decoration: BoxDecoration( + gradient: StreamChatTheme.of(context) .colorTheme - .textLowEmphasis, + .bgGradient, + ), + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 8, + horizontal: 8, + ), + child: Text( + _isSearchActive + ? '${AppLocalizations.of(context).matchesFor} "$_userNameQuery"' + : AppLocalizations.of(context).onThePlatorm, + style: TextStyle( + color: StreamChatTheme.of(context) + .colorTheme + .textLowEmphasis, + ), + ), ), ), ), ), - ), - ), - ]; - }, - body: GestureDetector( - behavior: HitTestBehavior.opaque, - onPanDown: (_) => FocusScope.of(context).unfocus(), - child: StreamUserListView( - controller: userListController, - itemBuilder: (context, items, index, defaultWidget) { - return defaultWidget.copyWith( - selected: _selectedUsers.contains(items[index]), - ); - }, - onUserTap: (user) { - if (!_selectedUsers.contains(user)) { - setState(() { - _selectedUsers.add(user); - }); - } else { - setState(() { - _selectedUsers.remove(user); - }); - } + ]; }, - emptyBuilder: (_) { - return LayoutBuilder( - builder: (context, viewportConstraints) { - return SingleChildScrollView( - physics: const AlwaysScrollableScrollPhysics(), - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: viewportConstraints.maxHeight, - ), - child: Center( - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(24), - child: StreamSvgIcon.search( - size: 96, - color: StreamChatTheme.of(context) - .colorTheme - .textLowEmphasis, - ), - ), - Text( - AppLocalizations.of(context) - .noUserMatchesTheseKeywords, - style: StreamChatTheme.of(context) - .textTheme - .footnote - .copyWith( + body: GestureDetector( + behavior: HitTestBehavior.opaque, + onPanDown: (_) => FocusScope.of(context).unfocus(), + child: StreamUserListView( + controller: userListController, + itemBuilder: (context, items, index, defaultWidget) { + return defaultWidget.copyWith( + selected: state.users.contains(items[index]), + ); + }, + onUserTap: groupChatState.addOrRemoveUser, + emptyBuilder: (_) { + return LayoutBuilder( + builder: (context, viewportConstraints) { + return SingleChildScrollView( + physics: const AlwaysScrollableScrollPhysics(), + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: viewportConstraints.maxHeight, + ), + child: Center( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(24), + child: StreamSvgIcon.search( + size: 96, color: StreamChatTheme.of(context) .colorTheme .textLowEmphasis, ), + ), + Text( + AppLocalizations.of(context) + .noUserMatchesTheseKeywords, + style: StreamChatTheme.of(context) + .textTheme + .footnote + .copyWith( + color: StreamChatTheme.of(context) + .colorTheme + .textLowEmphasis, + ), + ), + ], ), - ], + ), ), - ), - ), + ); + }, ); }, - ); - }, + ), + ), ), - ), - ), - ); - }, - ), + ); + }, + ), + ); + }, ); } } diff --git a/stream_chat_v1/lib/pages/pinned_messages_screen.dart b/stream_chat_v1/lib/pages/pinned_messages_screen.dart index 407eb63b4c..a38aa551b1 100644 --- a/stream_chat_v1/lib/pages/pinned_messages_screen.dart +++ b/stream_chat_v1/lib/pages/pinned_messages_screen.dart @@ -1,10 +1,9 @@ import 'package:example/utils/localizations.dart'; import 'package:example/routes/routes.dart'; import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -import 'channel_page.dart'; - class PinnedMessagesScreen extends StatefulWidget { const PinnedMessagesScreen({super.key}); @@ -103,7 +102,7 @@ class _PinnedMessagesScreenState extends State { }, onMessageTap: (messageResponse) async { final client = StreamChat.of(context).client; - final navigator = Navigator.of(context); + final router = GoRouter.of(context); final message = messageResponse.message; final channel = client.channel( messageResponse.channel!.type, @@ -112,12 +111,10 @@ class _PinnedMessagesScreenState extends State { if (channel.state == null) { await channel.watch(); } - navigator.pushNamed( - Routes.CHANNEL_PAGE, - arguments: ChannelPageArgs( - channel: channel, - initialMessage: message, - ), + router.pushNamed( + Routes.CHANNEL_PAGE.name, + params: Routes.CHANNEL_PAGE.params(channel), + queryParams: Routes.CHANNEL_PAGE.queryParams(message), ); }, ), diff --git a/stream_chat_v1/lib/pages/user_mentions_page.dart b/stream_chat_v1/lib/pages/user_mentions_page.dart index 52543786e1..c95329c271 100644 --- a/stream_chat_v1/lib/pages/user_mentions_page.dart +++ b/stream_chat_v1/lib/pages/user_mentions_page.dart @@ -1,10 +1,9 @@ import 'package:example/utils/localizations.dart'; import 'package:example/routes/routes.dart'; import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -import 'channel_page.dart'; - class UserMentionsPage extends StatefulWidget { const UserMentionsPage({super.key}); @@ -72,7 +71,7 @@ class _UserMentionsPageState extends State { }, onMessageTap: (messageResponse) async { final client = StreamChat.of(context).client; - final navigator = Navigator.of(context); + final router = GoRouter.of(context); final message = messageResponse.message; final channel = client.channel( messageResponse.channel!.type, @@ -81,12 +80,10 @@ class _UserMentionsPageState extends State { if (channel.state == null) { await channel.watch(); } - navigator.pushNamed( - Routes.CHANNEL_PAGE, - arguments: ChannelPageArgs( - channel: channel, - initialMessage: message, - ), + router.pushNamed( + Routes.CHANNEL_PAGE.name, + params: Routes.CHANNEL_PAGE.params(channel), + queryParams: Routes.CHANNEL_PAGE.queryParams(message), ); }, ); diff --git a/stream_chat_v1/lib/routes/app_routes.dart b/stream_chat_v1/lib/routes/app_routes.dart index cee0a57488..9842d0cc7a 100644 --- a/stream_chat_v1/lib/routes/app_routes.dart +++ b/stream_chat_v1/lib/routes/app_routes.dart @@ -1,135 +1,127 @@ import 'package:collection/collection.dart'; +import 'package:example/pages/advanced_options_page.dart'; import 'package:example/pages/channel_list_page.dart'; +import 'package:example/pages/channel_page.dart'; +import 'package:example/pages/chat_info_screen.dart'; +import 'package:example/pages/group_chat_details_screen.dart'; +import 'package:example/pages/group_info_screen.dart'; +import 'package:example/pages/new_chat_screen.dart'; +import 'package:example/pages/new_group_chat_screen.dart'; +import 'package:example/pages/thread_page.dart'; +import 'package:example/routes/routes.dart'; +import 'package:example/state/new_group_chat_state.dart'; import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -import '../app.dart'; -import '../pages/advanced_options_page.dart'; -import '../pages/channel_page.dart'; -import '../pages/chat_info_screen.dart'; import '../pages/choose_user_page.dart'; -import '../pages/group_chat_details_screen.dart'; -import '../pages/group_info_screen.dart'; -import '../pages/home_page.dart'; -import '../pages/new_chat_screen.dart'; -import '../pages/new_group_chat_screen.dart'; -import '../pages/thread_page.dart'; -import 'routes.dart'; -class AppRoutes { - /// Add entry for new route here - static Route? generateRoute(RouteSettings settings) { - final args = settings.arguments; - switch (settings.name) { - case Routes.APP: - return MaterialPageRoute( - settings: RouteSettings(arguments: args, name: Routes.APP), - builder: (_) { - return const StreamChatSampleApp(); - }); - case Routes.HOME: - return MaterialPageRoute( - settings: RouteSettings(arguments: args, name: Routes.HOME), - builder: (_) { - final homePageArgs = args as HomePageArgs; - return HomePage( - chatClient: homePageArgs.chatClient, - ); - }); - case Routes.CHOOSE_USER: - return MaterialPageRoute( - settings: RouteSettings(arguments: args, name: Routes.CHOOSE_USER), - builder: (_) { - return const ChooseUserPage(); - }); - case Routes.ADVANCED_OPTIONS: - return MaterialPageRoute( - settings: - RouteSettings(arguments: args, name: Routes.ADVANCED_OPTIONS), - builder: (_) => const AdvancedOptionsPage(), - ); - case Routes.CHANNEL_PAGE: - return MaterialPageRoute( - settings: RouteSettings(arguments: args, name: Routes.CHANNEL_PAGE), - builder: (context) { - final channelPageArgs = args as ChannelPageArgs; - final initialMessage = channelPageArgs.initialMessage; +final appRoutes = [ + GoRoute( + name: Routes.CHANNEL_LIST_PAGE.name, + path: Routes.CHANNEL_LIST_PAGE.path, + builder: (BuildContext context, GoRouterState state) => + const ChannelListPage(), + routes: [ + GoRoute( + name: Routes.CHANNEL_PAGE.name, + path: Routes.CHANNEL_PAGE.path, + builder: (context, state) { + final channel = + StreamChat.of(context).client.state.channels[state.params['cid']]; + final messageId = state.queryParams['mid']; + final parentId = state.queryParams['pid']; - return StreamChannel( - channel: channelPageArgs.channel!, - initialMessageId: initialMessage?.id, - child: Builder( - builder: (context) { - final parentId = initialMessage?.parentId; - Message? parentMessage; - if (parentId != null) { - final channel = StreamChannel.of(context).channel; - parentMessage = channel.state!.messages - .firstWhereOrNull((it) => it.id == parentId); - } - if (parentMessage != null) { - return ThreadPage(parent: parentMessage); - } - return ChannelPage( - highlightInitialMessage: - channelPageArgs.initialMessage != null, - ); - }, - ), - ); - }, - ); - case Routes.NEW_CHAT: - return MaterialPageRoute( - settings: RouteSettings(arguments: args, name: Routes.NEW_CHAT), - builder: (_) { - return const NewChatScreen(); - }); - case Routes.NEW_GROUP_CHAT: - return MaterialPageRoute( - settings: - RouteSettings(arguments: args, name: Routes.NEW_GROUP_CHAT), - builder: (_) { - return const NewGroupChatScreen(); - }); - case Routes.NEW_GROUP_CHAT_DETAILS: - return MaterialPageRoute( - settings: RouteSettings( - arguments: args, name: Routes.NEW_GROUP_CHAT_DETAILS), - builder: (_) { - return GroupChatDetailsScreen( - selectedUsers: args as List?, - ); - }); - case Routes.CHAT_INFO_SCREEN: - return MaterialPageRoute( - settings: - RouteSettings(arguments: args, name: Routes.CHAT_INFO_SCREEN), - builder: (context) { - return ChatInfoScreen( - user: args as User?, - messageTheme: StreamChatTheme.of(context).ownMessageTheme, + Message? parentMessage; + if (parentId != null) { + parentMessage = channel?.state!.messages + .firstWhereOrNull((it) => it.id == parentId); + } + + return StreamChannel( + channel: channel!, + initialMessageId: messageId, + child: Builder( + builder: (context) { + return (parentMessage != null) + ? ThreadPage(parent: parentMessage) + : ChannelPage( + highlightInitialMessage: messageId != null, + ); + }, + ), + ); + }, + routes: [ + GoRoute( + name: Routes.CHAT_INFO_SCREEN.name, + path: Routes.CHAT_INFO_SCREEN.path, + builder: (BuildContext context, GoRouterState state) { + final channel = StreamChat.of(context) + .client + .state + .channels[state.params['cid']]; + return StreamChannel( + channel: channel!, + child: ChatInfoScreen( + user: state.extra as User?, + messageTheme: StreamChatTheme.of(context).ownMessageTheme, + ), ); - }); - case Routes.GROUP_INFO_SCREEN: - return MaterialPageRoute( - settings: - RouteSettings(arguments: args, name: Routes.GROUP_INFO_SCREEN), - builder: (context) { - return GroupInfoScreen( - messageTheme: StreamChatTheme.of(context).ownMessageTheme, + }, + ), + GoRoute( + name: Routes.GROUP_INFO_SCREEN.name, + path: Routes.GROUP_INFO_SCREEN.path, + builder: (BuildContext context, GoRouterState state) { + final channel = StreamChat.of(context) + .client + .state + .channels[state.params['cid']]; + return StreamChannel( + channel: channel!, + child: GroupInfoScreen( + messageTheme: StreamChatTheme.of(context).ownMessageTheme, + ), ); - }); - case Routes.CHANNEL_LIST_PAGE: - return MaterialPageRoute( - settings: - RouteSettings(arguments: args, name: Routes.CHANNEL_LIST_PAGE), - builder: (context) { - return const ChannelListPage(); - }); - // Default case, should not reach here. - default: - return null; - } - } -} + }, + ), + ], + ), + ], + ), + GoRoute( + name: Routes.NEW_CHAT.name, + path: Routes.NEW_CHAT.path, + builder: (BuildContext context, GoRouterState state) { + return const NewChatScreen(); + }, + ), + GoRoute( + name: Routes.NEW_GROUP_CHAT.name, + path: Routes.NEW_GROUP_CHAT.path, + builder: (BuildContext context, GoRouterState state) { + return const NewGroupChatScreen(); + }, + ), + GoRoute( + name: Routes.NEW_GROUP_CHAT_DETAILS.name, + path: Routes.NEW_GROUP_CHAT_DETAILS.path, + builder: (BuildContext context, GoRouterState state) { + final groupChatState = state.extra as NewGroupChatState; + return GroupChatDetailsScreen(groupChatState: groupChatState); + }, + ), + GoRoute( + name: Routes.CHOOSE_USER.name, + path: Routes.CHOOSE_USER.path, + builder: (BuildContext context, GoRouterState state) => + const ChooseUserPage(), + ), + GoRoute( + name: Routes.ADVANCED_OPTIONS.name, + path: Routes.ADVANCED_OPTIONS.path, + builder: (BuildContext context, GoRouterState state) => + const AdvancedOptionsPage(), + ), +]; diff --git a/stream_chat_v1/lib/routes/routes.dart b/stream_chat_v1/lib/routes/routes.dart index 844d7b9bba..5c9749a2b1 100644 --- a/stream_chat_v1/lib/routes/routes.dart +++ b/stream_chat_v1/lib/routes/routes.dart @@ -1,16 +1,43 @@ // ignore_for_file: constant_identifier_names +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; + /// Application routes abstract class Routes { - static const String APP = '/app'; - static const String HOME = '/home'; - static const String CHOOSE_USER = '/choose_user'; - static const String ADVANCED_OPTIONS = '/advance_options'; - static const String CHANNEL_PAGE = '/channel_page'; - static const String NEW_CHAT = '/new_chat'; - static const String NEW_GROUP_CHAT = '/new_group_chat'; - static const String NEW_GROUP_CHAT_DETAILS = '/new_group_chat_details'; - static const String CHAT_INFO_SCREEN = '/chat_info_screen'; - static const String GROUP_INFO_SCREEN = '/group_info_screen'; - static const String CHANNEL_LIST_PAGE = '/channel_list_page'; + static const RouteConfig CHOOSE_USER = + RouteConfig(name: 'choose_user', path: '/users'); + static const RouteConfig ADVANCED_OPTIONS = + RouteConfig(name: 'advanced_options', path: '/options'); + static const ChannelRouteConfig CHANNEL_PAGE = + ChannelRouteConfig(name: 'channel_page', path: 'channel/:cid'); + static const RouteConfig NEW_CHAT = + RouteConfig(name: 'new_chat', path: '/new_chat'); + static const RouteConfig NEW_GROUP_CHAT = + RouteConfig(name: 'new_group_chat', path: '/new_group_chat'); + static const RouteConfig NEW_GROUP_CHAT_DETAILS = RouteConfig( + name: 'new_group_chat_details', path: '/new_group_chat_details'); + static const ChannelRouteConfig CHAT_INFO_SCREEN = + ChannelRouteConfig(name: 'chat_info_screen', path: 'chat_info_screen'); + static const ChannelRouteConfig GROUP_INFO_SCREEN = + ChannelRouteConfig(name: 'group_info_screen', path: 'group_info_screen'); + static const RouteConfig CHANNEL_LIST_PAGE = + RouteConfig(name: 'channel_list_page', path: '/channels'); +} + +class RouteConfig { + final String name; + final String path; + + const RouteConfig({required this.name, required this.path}); +} + +class ChannelRouteConfig extends RouteConfig { + const ChannelRouteConfig({required super.name, required super.path}); + + Map params(Channel channel) => {'cid': channel.cid!}; + + Map queryParams(Message message) => { + 'mid': message.id, + if (message.parentId != null) 'pid': message.parentId! + }; } diff --git a/stream_chat_v1/lib/state/init_data.dart b/stream_chat_v1/lib/state/init_data.dart new file mode 100644 index 0000000000..7f23896afd --- /dev/null +++ b/stream_chat_v1/lib/state/init_data.dart @@ -0,0 +1,36 @@ +import 'package:flutter/widgets.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; +import 'package:streaming_shared_preferences/streaming_shared_preferences.dart'; + +/// {@template init_notifier} +/// [ChangeNotifier] to store [InitData] and notify listeners on change. +/// {@endtemplate} +class InitNotifier extends ChangeNotifier { + /// {@macro init_notifier} + InitNotifier(); + + InitData? _initData; + + set initData(InitData? data) { + _initData = data; + notifyListeners(); + } + + InitData? get initData => _initData; +} + +/// {@template init_data} +/// Manages the initialization data for the sample application. +/// +/// Stores a reference to the current [StreamChatClient]. +/// {@endtemplate} +class InitData { + /// {@macro init_data} + InitData(this.client, this.preferences); + + final StreamChatClient client; + final StreamingSharedPreferences preferences; + + InitData copyWith({required StreamChatClient client}) => + InitData(client, preferences); +} diff --git a/stream_chat_v1/lib/state/new_group_chat_state.dart b/stream_chat_v1/lib/state/new_group_chat_state.dart new file mode 100644 index 0000000000..2b6f6460e1 --- /dev/null +++ b/stream_chat_v1/lib/state/new_group_chat_state.dart @@ -0,0 +1,29 @@ +import 'package:flutter/widgets.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; + +class NewGroupChatState extends ChangeNotifier { + final users = {}; + + void addUser(User user) { + if (!users.contains(user)) { + users.add(user); + notifyListeners(); + } + } + + void removeUser(User user) { + if (users.contains(user)) { + users.remove(user); + notifyListeners(); + } + } + + void addOrRemoveUser(User user) { + if (users.contains(user)) { + users.remove(user); + } else { + users.add(user); + } + notifyListeners(); + } +} diff --git a/stream_chat_v1/lib/utils/local_notification_observer.dart b/stream_chat_v1/lib/utils/local_notification_observer.dart new file mode 100644 index 0000000000..8befd49421 --- /dev/null +++ b/stream_chat_v1/lib/utils/local_notification_observer.dart @@ -0,0 +1,69 @@ +import 'dart:async'; + +import 'package:example/routes/routes.dart'; +import 'package:example/utils/notifications_service.dart'; +import 'package:flutter/material.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; + +class LocalNotificationObserver extends NavigatorObserver { + Route? currentRoute; + late final StreamSubscription _subscription; + + LocalNotificationObserver( + StreamChatClient client, + GlobalKey navigatorKey, + ) { + _subscription = client + .on( + EventType.messageNew, + EventType.notificationMessageNew, + ) + .listen((event) { + _handleEvent(event, client, navigatorKey); + }); + } + + void _handleEvent(Event event, StreamChatClient client, + GlobalKey navigatorKey) { + if (event.message?.user?.id == client.state.currentUser?.id) { + return; + } + final channelId = event.cid; + if (currentRoute?.settings.name == Routes.CHANNEL_PAGE.name) { + final args = currentRoute?.settings.arguments as Map; + if (args['cid'] == channelId) { + return; + } + } + + showLocalNotification( + event, + client.state.currentUser!.id, + navigatorKey.currentState!.context, + ); + } + + @override + void didPop(Route route, Route? previousRoute) { + currentRoute = route; + } + + @override + void didPush(Route route, Route? previousRoute) { + currentRoute = route; + } + + @override + void didRemove(Route route, Route? previousRoute) { + currentRoute = route; + } + + @override + void didReplace({Route? newRoute, Route? oldRoute}) { + currentRoute = newRoute; + } + + void dispose() { + _subscription.cancel(); + } +} diff --git a/stream_chat_v1/lib/utils/notifications_service.dart b/stream_chat_v1/lib/utils/notifications_service.dart index b56fc9985a..a02d2eed53 100644 --- a/stream_chat_v1/lib/utils/notifications_service.dart +++ b/stream_chat_v1/lib/utils/notifications_service.dart @@ -1,9 +1,9 @@ -import 'package:example/pages/channel_page.dart'; import 'package:example/utils/localizations.dart'; import 'package:example/routes/routes.dart'; import 'package:flutter/material.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart' hide Message; +import 'package:go_router/go_router.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; void showLocalNotification( @@ -35,7 +35,7 @@ void showLocalNotification( onSelectNotification: (channelCid) async { if (channelCid != null) { final client = StreamChat.of(context).client; - final navigator = Navigator.of(context); + final router = GoRouter.of(context); var channel = client.state.channels[channelCid]; @@ -50,11 +50,9 @@ void showLocalNotification( await channel.watch(); } - navigator.pushNamed( - Routes.CHANNEL_PAGE, - arguments: ChannelPageArgs( - channel: channel, - ), + router.pushNamed( + Routes.CHANNEL_PAGE.name, + params: Routes.CHANNEL_PAGE.params(channel), ); } }, diff --git a/stream_chat_v1/lib/widgets/channel_list.dart b/stream_chat_v1/lib/widgets/channel_list.dart index 44cb7ba476..f63edbec42 100644 --- a/stream_chat_v1/lib/widgets/channel_list.dart +++ b/stream_chat_v1/lib/widgets/channel_list.dart @@ -5,10 +5,10 @@ import 'package:example/routes/routes.dart'; import 'package:example/widgets/search_text_field.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; +import 'package:go_router/go_router.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:flutter_slidable/flutter_slidable.dart'; -import '../pages/channel_page.dart'; import '../pages/chat_info_screen.dart'; import '../pages/group_info_screen.dart'; @@ -150,7 +150,7 @@ class _ChannelList extends State { final messageResponse = messageResponses[index]; FocusScope.of(context).requestFocus(FocusNode()); final client = StreamChat.of(context).client; - final navigator = Navigator.of(context); + final router = GoRouter.of(context); final message = messageResponse.message; final channel = client.channel( messageResponse.channel!.type, @@ -159,12 +159,10 @@ class _ChannelList extends State { if (channel.state == null) { await channel.watch(); } - navigator.pushNamed( - Routes.CHANNEL_PAGE, - arguments: ChannelPageArgs( - channel: channel, - initialMessage: message, - ), + router.pushNamed( + Routes.CHANNEL_PAGE.name, + params: Routes.CHANNEL_PAGE.params(channel), + queryParams: Routes.CHANNEL_PAGE.queryParams(message), ); }, ); @@ -265,12 +263,9 @@ class _ChannelList extends State { ); }, onChannelTap: (channel) { - Navigator.pushNamed( - context, - Routes.CHANNEL_PAGE, - arguments: ChannelPageArgs( - channel: channel, - ), + GoRouter.of(context).pushNamed( + Routes.CHANNEL_PAGE.name, + params: Routes.CHANNEL_PAGE.params(channel), ); }, emptyBuilder: (_) { @@ -286,10 +281,8 @@ class _ChannelList extends State { ), emptyTitle: TextButton( onPressed: () { - Navigator.pushNamed( - context, - Routes.NEW_CHAT, - ); + GoRouter.of(context) + .pushNamed(Routes.NEW_CHAT.name); }, child: Text( 'Start a chat', diff --git a/stream_chat_v1/macos/Runner.xcodeproj/project.pbxproj b/stream_chat_v1/macos/Runner.xcodeproj/project.pbxproj index c973575621..8972854e80 100644 --- a/stream_chat_v1/macos/Runner.xcodeproj/project.pbxproj +++ b/stream_chat_v1/macos/Runner.xcodeproj/project.pbxproj @@ -72,6 +72,7 @@ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; 929AC42CE2CDA27FE9235234 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + CDF4BDDD28F9A6920059DB87 /* RunnerDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerDebug.entitlements; sourceTree = ""; }; D4F4A1B883B395E86A7B745A /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -142,6 +143,7 @@ 33FAB671232836740065AC1E /* Runner */ = { isa = PBXGroup; children = ( + CDF4BDDD28F9A6920059DB87 /* RunnerDebug.entitlements */, 33CC10F02044A3C60003C045 /* AppDelegate.swift */, 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, 33E51913231747F40026EE4D /* DebugProfile.entitlements */, @@ -159,7 +161,6 @@ 929AC42CE2CDA27FE9235234 /* Pods-Runner.release.xcconfig */, D4F4A1B883B395E86A7B745A /* Pods-Runner.profile.xcconfig */, ); - name = Pods; path = Pods; sourceTree = ""; }; @@ -209,7 +210,6 @@ 33CC10EC2044A3C60003C045 = { CreatedOnToolsVersion = 9.2; LastSwiftMigration = 1100; - ProvisioningStyle = Automatic; SystemCapabilities = { com.apple.Sandbox = { enabled = 1; @@ -419,6 +419,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Runner/Info.plist; @@ -544,9 +545,11 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_ENTITLEMENTS = Runner/RunnerDebug.entitlements; + CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -565,8 +568,10 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", diff --git a/stream_chat_v1/macos/Runner/DebugProfile.entitlements b/stream_chat_v1/macos/Runner/DebugProfile.entitlements index 681e73fe27..0eaccf1418 100644 --- a/stream_chat_v1/macos/Runner/DebugProfile.entitlements +++ b/stream_chat_v1/macos/Runner/DebugProfile.entitlements @@ -6,11 +6,11 @@ com.apple.security.cs.allow-jit - com.apple.security.network.server + com.apple.security.files.user-selected.read-write com.apple.security.network.client - com.apple.security.files.user-selected.read-write - + com.apple.security.network.server + diff --git a/stream_chat_v1/macos/Runner/Release.entitlements b/stream_chat_v1/macos/Runner/Release.entitlements index 43a8b8c70d..a0463869a9 100644 --- a/stream_chat_v1/macos/Runner/Release.entitlements +++ b/stream_chat_v1/macos/Runner/Release.entitlements @@ -4,9 +4,9 @@ com.apple.security.app-sandbox + com.apple.security.files.user-selected.read-write + com.apple.security.network.client - com.apple.security.files.user-selected.read-write - diff --git a/stream_chat_v1/macos/Runner/RunnerDebug.entitlements b/stream_chat_v1/macos/Runner/RunnerDebug.entitlements new file mode 100644 index 0000000000..0eaccf1418 --- /dev/null +++ b/stream_chat_v1/macos/Runner/RunnerDebug.entitlements @@ -0,0 +1,16 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.files.user-selected.read-write + + com.apple.security.network.client + + com.apple.security.network.server + + + diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index 1c7a956b16..8b6e901e13 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -27,7 +27,7 @@ dependencies: path: packages/stream_chat_localizations flutter_local_notifications: ^9.0.0 flutter_svg: ^1.0.3 - flutter_secure_storage: ^5.0.2 + flutter_secure_storage: ^6.0.0 yaml: ^3.1.0 uuid: ^3.0.5 streaming_shared_preferences: ^2.0.0 @@ -35,6 +35,8 @@ dependencies: collection: ^1.15.0 sentry_flutter: ^6.5.0 flutter_slidable: ^2.0.0 + go_router: ^5.0.5 + provider: ^6.0.3 dev_dependencies: flutter_launcher_icons: ^0.9.2 From 31e387403887b185fe61db16270b97789f303802 Mon Sep 17 00:00:00 2001 From: Leandro Borges Ferreira Date: Fri, 27 Jan 2023 12:26:24 +0100 Subject: [PATCH 136/172] Updating dependencies --- stream_chat_v1/android/app/build.gradle | 4 ++-- stream_chat_v1/android/app/src/main/AndroidManifest.xml | 3 ++- stream_chat_v1/android/build.gradle | 4 ++-- .../android/gradle/wrapper/gradle-wrapper.properties | 2 +- stream_chat_v1/pubspec.yaml | 2 +- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/stream_chat_v1/android/app/build.gradle b/stream_chat_v1/android/app/build.gradle index 189df9753a..7a92816525 100644 --- a/stream_chat_v1/android/app/build.gradle +++ b/stream_chat_v1/android/app/build.gradle @@ -26,7 +26,7 @@ apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - compileSdkVersion 31 + compileSdkVersion 33 ndkVersion '21.4.7075529' sourceSets { @@ -41,7 +41,7 @@ android { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.example.example" minSdkVersion 22 - targetSdkVersion 30 + targetSdkVersion 33 versionCode flutterVersionCode.toInteger() versionName flutterVersionName testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/stream_chat_v1/android/app/src/main/AndroidManifest.xml b/stream_chat_v1/android/app/src/main/AndroidManifest.xml index fb4ab7f7c1..3ea0f99076 100644 --- a/stream_chat_v1/android/app/src/main/AndroidManifest.xml +++ b/stream_chat_v1/android/app/src/main/AndroidManifest.xml @@ -21,7 +21,8 @@ android:theme="@style/LaunchTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" - android:windowSoftInputMode="adjustResize"> + android:windowSoftInputMode="adjustResize" + android:exported="true"> diff --git a/stream_chat_v1/android/build.gradle b/stream_chat_v1/android/build.gradle index aeb95a68c9..b8901a857b 100644 --- a/stream_chat_v1/android/build.gradle +++ b/stream_chat_v1/android/build.gradle @@ -1,12 +1,12 @@ buildscript { - ext.kotlin_version = '1.5.20' + ext.kotlin_version = '1.7.10' repositories { google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:4.2.2' + classpath 'com.android.tools.build:gradle:7.2.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'com.google.gms:google-services:4.3.2' } diff --git a/stream_chat_v1/android/gradle/wrapper/gradle-wrapper.properties b/stream_chat_v1/android/gradle/wrapper/gradle-wrapper.properties index bdbde4da10..75b9065830 100644 --- a/stream_chat_v1/android/gradle/wrapper/gradle-wrapper.properties +++ b/stream_chat_v1/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.9-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index 8b6e901e13..93ade174f5 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -31,7 +31,7 @@ dependencies: yaml: ^3.1.0 uuid: ^3.0.5 streaming_shared_preferences: ^2.0.0 - lottie: ^1.2.1 + lottie: ^2.2.0 collection: ^1.15.0 sentry_flutter: ^6.5.0 flutter_slidable: ^2.0.0 From badfbbca2f18896efde7fcfb900c5128e7e6e162 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Fri, 7 Apr 2023 05:05:15 +0530 Subject: [PATCH 137/172] chore(sample-app): update to latest develop branch. Signed-off-by: xsahil03x --- stream_chat_v1/pubspec.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index 93ade174f5..51f8228fe2 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -5,6 +5,7 @@ version: 2.1.1 environment: sdk: ">=2.17.0 <3.0.0" + flutter: ">=1.17.0" dependencies: flutter_app_badger: ^1.3.0 @@ -26,12 +27,12 @@ dependencies: ref: develop path: packages/stream_chat_localizations flutter_local_notifications: ^9.0.0 - flutter_svg: ^1.0.3 + flutter_svg: ^2.0.4 flutter_secure_storage: ^6.0.0 yaml: ^3.1.0 uuid: ^3.0.5 streaming_shared_preferences: ^2.0.0 - lottie: ^2.2.0 + lottie: ^2.0.0 collection: ^1.15.0 sentry_flutter: ^6.5.0 flutter_slidable: ^2.0.0 From b542be600b4caa6bc74fa744e473b9490ea53db4 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Fri, 7 Apr 2023 05:17:12 +0530 Subject: [PATCH 138/172] chore(sample-app): update version Signed-off-by: xsahil03x --- stream_chat_v1/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index 51f8228fe2..cfc14b8d6f 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -1,7 +1,7 @@ name: example description: A new Flutter project. publish_to: "none" -version: 2.1.1 +version: 2.2.0 environment: sdk: ">=2.17.0 <3.0.0" From 682898991430995456a13a66c4983c3aeef2172c Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Fri, 7 Apr 2023 18:31:15 +0530 Subject: [PATCH 139/172] chore(sample-app): update app icons, lottie and android project. Signed-off-by: xsahil03x --- stream_chat_v1/.metadata | 25 +--- .../android/app/src/main/AndroidManifest.xml | 13 +- .../kotlin/com/example/example/Application.kt | 23 --- .../com/example/example/MainActivity.kt | 6 - .../getstream/stream_chat_v1/MainActivity.kt | 6 - .../drawable-hdpi/ic_launcher_background.png | Bin 0 -> 514 bytes .../drawable-hdpi/ic_launcher_foreground.png | Bin 0 -> 4342 bytes .../drawable-mdpi/ic_launcher_background.png | Bin 0 -> 333 bytes .../drawable-mdpi/ic_launcher_foreground.png | Bin 0 -> 2623 bytes .../drawable-xhdpi/ic_launcher_background.png | Bin 0 -> 684 bytes .../drawable-xhdpi/ic_launcher_foreground.png | Bin 0 -> 5106 bytes .../ic_launcher_background.png | Bin 0 -> 1021 bytes .../ic_launcher_foreground.png | Bin 0 -> 8365 bytes .../ic_launcher_background.png | Bin 0 -> 1710 bytes .../ic_launcher_foreground.png | Bin 0 -> 11099 bytes .../res/drawable/ic_launcher_foreground.xml | 18 --- .../main/res/drawable/launch_background.xml | 9 +- .../res/mipmap-anydpi-v26/ic_launcher.xml | 6 +- .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 - .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 4323 -> 2988 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 4323 -> 0 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 2628 -> 1840 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 2628 -> 0 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 6191 -> 4096 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 6191 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 9719 -> 6422 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 9719 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 14197 -> 8762 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 14197 -> 0 bytes .../app/src/main/res/values-night/styles.xml | 4 +- .../app/src/main/res/values/colors.xml | 4 - .../res/values/ic_launcher_background.xml | 4 - .../app/src/main/res/values/styles.xml | 14 +- stream_chat_v1/assets/android_icon.png | Bin 15354 -> 0 bytes .../assets/{ios_icon.png => ic_launcher.png} | Bin .../assets/ic_launcher_background.png | Bin 0 -> 4234 bytes .../assets/ic_launcher_foreground.png | Bin 0 -> 13908 bytes .../AppIcon.appiconset/Icon-App-50x50@1x.png | Bin 0 -> 1910 bytes .../AppIcon.appiconset/Icon-App-50x50@2x.png | Bin 0 -> 4296 bytes .../AppIcon.appiconset/Icon-App-57x57@1x.png | Bin 0 -> 2158 bytes .../AppIcon.appiconset/Icon-App-57x57@2x.png | Bin 0 -> 4779 bytes .../AppIcon.appiconset/Icon-App-72x72@1x.png | Bin 0 -> 2988 bytes .../AppIcon.appiconset/Icon-App-72x72@2x.png | Bin 0 -> 6422 bytes .../AppIcon.appiconset/Contents.json | 132 +++++++++--------- .../AppIcon.appiconset/app_icon_1024.png | Bin 46993 -> 52126 bytes .../AppIcon.appiconset/app_icon_128.png | Bin 3276 -> 5468 bytes .../AppIcon.appiconset/app_icon_16.png | Bin 1429 -> 476 bytes .../AppIcon.appiconset/app_icon_256.png | Bin 5933 -> 11508 bytes .../AppIcon.appiconset/app_icon_32.png | Bin 1243 -> 1094 bytes .../AppIcon.appiconset/app_icon_512.png | Bin 14800 -> 24550 bytes .../AppIcon.appiconset/app_icon_64.png | Bin 1874 -> 2513 bytes stream_chat_v1/pubspec.yaml | 20 ++- stream_chat_v1/web/favicon.png | Bin 917 -> 476 bytes stream_chat_v1/web/icons/Icon-192.png | Bin 5292 -> 8762 bytes stream_chat_v1/web/icons/Icon-512.png | Bin 8252 -> 24550 bytes .../web/icons/Icon-maskable-192.png | Bin 0 -> 8762 bytes .../web/icons/Icon-maskable-512.png | Bin 0 -> 24550 bytes stream_chat_v1/web/manifest.json | 14 +- 58 files changed, 132 insertions(+), 171 deletions(-) delete mode 100644 stream_chat_v1/android/app/src/main/kotlin/com/example/example/Application.kt delete mode 100644 stream_chat_v1/android/app/src/main/kotlin/io/getstream/stream_chat_v1/MainActivity.kt create mode 100644 stream_chat_v1/android/app/src/main/res/drawable-hdpi/ic_launcher_background.png create mode 100644 stream_chat_v1/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png create mode 100644 stream_chat_v1/android/app/src/main/res/drawable-mdpi/ic_launcher_background.png create mode 100644 stream_chat_v1/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png create mode 100644 stream_chat_v1/android/app/src/main/res/drawable-xhdpi/ic_launcher_background.png create mode 100644 stream_chat_v1/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png create mode 100644 stream_chat_v1/android/app/src/main/res/drawable-xxhdpi/ic_launcher_background.png create mode 100644 stream_chat_v1/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png create mode 100644 stream_chat_v1/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_background.png create mode 100644 stream_chat_v1/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png delete mode 100644 stream_chat_v1/android/app/src/main/res/drawable/ic_launcher_foreground.xml delete mode 100644 stream_chat_v1/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml delete mode 100644 stream_chat_v1/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png delete mode 100644 stream_chat_v1/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png delete mode 100644 stream_chat_v1/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png delete mode 100644 stream_chat_v1/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png delete mode 100644 stream_chat_v1/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png delete mode 100644 stream_chat_v1/android/app/src/main/res/values/colors.xml delete mode 100644 stream_chat_v1/android/app/src/main/res/values/ic_launcher_background.xml delete mode 100644 stream_chat_v1/assets/android_icon.png rename stream_chat_v1/assets/{ios_icon.png => ic_launcher.png} (100%) create mode 100644 stream_chat_v1/assets/ic_launcher_background.png create mode 100644 stream_chat_v1/assets/ic_launcher_foreground.png create mode 100644 stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png create mode 100644 stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png create mode 100644 stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png create mode 100644 stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png create mode 100644 stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png create mode 100644 stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png create mode 100644 stream_chat_v1/web/icons/Icon-maskable-192.png create mode 100644 stream_chat_v1/web/icons/Icon-maskable-512.png diff --git a/stream_chat_v1/.metadata b/stream_chat_v1/.metadata index ce13b42014..c3217d62b0 100644 --- a/stream_chat_v1/.metadata +++ b/stream_chat_v1/.metadata @@ -4,7 +4,7 @@ # This file should be version controlled. version: - revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851 + revision: b06b8b2710955028a6b562f5aa6fe62941d6febf channel: stable project_type: app @@ -13,26 +13,11 @@ project_type: app migration: platforms: - platform: root - create_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851 - base_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851 + create_revision: b06b8b2710955028a6b562f5aa6fe62941d6febf + base_revision: b06b8b2710955028a6b562f5aa6fe62941d6febf - platform: android - create_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851 - base_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851 - - platform: ios - create_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851 - base_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851 - - platform: linux - create_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851 - base_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851 - - platform: macos - create_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851 - base_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851 - - platform: web - create_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851 - base_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851 - - platform: windows - create_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851 - base_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851 + create_revision: b06b8b2710955028a6b562f5aa6fe62941d6febf + base_revision: b06b8b2710955028a6b562f5aa6fe62941d6febf # User provided section diff --git a/stream_chat_v1/android/app/src/main/AndroidManifest.xml b/stream_chat_v1/android/app/src/main/AndroidManifest.xml index 3ea0f99076..fa7cbe449e 100644 --- a/stream_chat_v1/android/app/src/main/AndroidManifest.xml +++ b/stream_chat_v1/android/app/src/main/AndroidManifest.xml @@ -9,10 +9,9 @@ + + @@ -38,4 +45,4 @@ android:name="flutterEmbedding" android:value="2" /> - + \ No newline at end of file diff --git a/stream_chat_v1/android/app/src/main/kotlin/com/example/example/Application.kt b/stream_chat_v1/android/app/src/main/kotlin/com/example/example/Application.kt deleted file mode 100644 index 938a498352..0000000000 --- a/stream_chat_v1/android/app/src/main/kotlin/com/example/example/Application.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.example.example - -import com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin -import io.flutter.app.FlutterApplication -import io.flutter.plugin.common.PluginRegistry -import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback -import io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin -import io.flutter.plugins.pathprovider.PathProviderPlugin - -class Application : FlutterApplication(), PluginRegistrantCallback { - override fun onCreate() { - super.onCreate() - } - - override fun registerWith(registry: PluginRegistry) { - PathProviderPlugin.registerWith(registry.registrarFor( - "io.flutter.plugins.pathprovider.PathProviderPlugin")) - SharedPreferencesPlugin.registerWith(registry.registrarFor( - "io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin")) - FlutterLocalNotificationsPlugin.registerWith(registry.registrarFor( - "com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin")) - } -} \ No newline at end of file diff --git a/stream_chat_v1/android/app/src/main/kotlin/com/example/example/MainActivity.kt b/stream_chat_v1/android/app/src/main/kotlin/com/example/example/MainActivity.kt index 1656503f3f..e793a000d6 100644 --- a/stream_chat_v1/android/app/src/main/kotlin/com/example/example/MainActivity.kt +++ b/stream_chat_v1/android/app/src/main/kotlin/com/example/example/MainActivity.kt @@ -1,12 +1,6 @@ package com.example.example -import androidx.annotation.NonNull; import io.flutter.embedding.android.FlutterActivity -import io.flutter.embedding.engine.FlutterEngine -import io.flutter.plugins.GeneratedPluginRegistrant class MainActivity: FlutterActivity() { - override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { - GeneratedPluginRegistrant.registerWith(flutterEngine); - } } diff --git a/stream_chat_v1/android/app/src/main/kotlin/io/getstream/stream_chat_v1/MainActivity.kt b/stream_chat_v1/android/app/src/main/kotlin/io/getstream/stream_chat_v1/MainActivity.kt deleted file mode 100644 index 3b9195b570..0000000000 --- a/stream_chat_v1/android/app/src/main/kotlin/io/getstream/stream_chat_v1/MainActivity.kt +++ /dev/null @@ -1,6 +0,0 @@ -package io.getstream.stream_chat_v1 - -import io.flutter.embedding.android.FlutterActivity - -class MainActivity: FlutterActivity() { -} diff --git a/stream_chat_v1/android/app/src/main/res/drawable-hdpi/ic_launcher_background.png b/stream_chat_v1/android/app/src/main/res/drawable-hdpi/ic_launcher_background.png new file mode 100644 index 0000000000000000000000000000000000000000..83e8029b3ab4dbc174aadc08964bde13587ae97e GIT binary patch literal 514 zcmeAS@N?(olHy`uVBq!ia0vp^i$Iuz4M-mPBqq(kzX4a4-ePj`~+D V&$I-NCAly?9C literal 0 HcmV?d00001 diff --git a/stream_chat_v1/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png b/stream_chat_v1/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..8c255db3ac83b748acb2bc135d4f6cc73fcc26bf GIT binary patch literal 4342 zcmd^D`8yQQ*B6Dcj-|1VS;!vQx0s9>#+H4nkR?lq$(Ef=3}elfA{vD3YqDk+B1?8< zA8RsXN%(rd&-+ij&-=sY+#l}qIiGXSbDneWJu!xNwHWER=_n{D7_~7djv+4+RCVMH{7V`s~V1Ho(X9J6G@S)$tE_BBP3EzdGXxuaUTB!c{9)!zA>(a3y=p z3(7~@Nk}njLqBA#Xp!7oR)KBycI4C`r9O`8Pwkz+(s6hUE0O|DEP!uZAoeu{YYe1i zK1rU0lICP&JX=zZf__^6Xi4eO0m|lLt)1@x@pxgEi2paRq<$Q@(ak&|eo8(gsJkV&4 z_q7bR*3s$jzj?pj=gaUg!o(s#=8_&>>oGg=G9_g{{e#52?8AV7fKS3ih?bEx>#yca zE*7afhP-W~<EPZGc!3R$u@6GA3!l>alzhS zZwXwH6dH}@0udhh9DBRoMWGNP;^Mp!84BPG^?EC2#J}Gu&t_TCdnj2;o8Hs=ao@Fp zN4glLlG@sXrw#jV@|T1=*er_0AD2#9;?qpWuVuWWeUGPugO(rBI?g?xeBa|I1M{kx znwpA9suG<$k!OPwnV))l@8SuBfsR?X?E&cG%k}kjh3t}p;lg5tFErDt2NHU5_EPpH~ZdPV-zqkr_vLF$M*N`MPEc#UytBO8iJWYjkCoh zB-T#HFt+^J3dT1iMz1{(INZ%%Jp>-Bc#=Nv%`Vx_m*0MwJ_|enq z0bSN}FeE~h$(gJIqILl zRGZTndRpT?d}j3|ePc0+#S^++95`?si+-&es^!kDi%xL#hyDSF>wZX(eQAVPNwr`BbCeDzvDa` z7*5j{>liBh7t_u%LsWU4#mIj%Ua!?jNEP56H%1G#n*4TNnt|?z@{a7#A9ap|-tIFdX~J^1cK1I=Pl1 zKI2nA$k&?NpigBh7(BAX7t2$TQ;jy$JoQZGhFOy;1C%y%CCB9}d|$Yt^GzG@+CX7u z$gV7?rYWD|Wh)2*xnP&Dxh>(yJ*sON%D|z*#`2V>OVJ&{lztZOz|b|D5r0;etC$^4 ze|oo)Oz`GYFA0Dqe4>GPqN*1Jx#_VDSmh#J!97o5L_Z<3ag z@m^jZ$-8fNCLL|fDHrs}(UF(lJhU_36)lid#EvH2s&zVATCVF^Y9|fn*z$qFsv@GI zqLeRhAp5i}LlNa$l!6axDYsR?BjvPk6j$OJoR_HuCNJ;zegNPGc#@?76uw3pkOj#h zf7o=yds7B{8T|S+gyQET>2zib`IA2F{8h^f5IMLp=;&8+--TW8zooU;yU)BcSxg9+ zz=L&cQDvo<1o3T4%Jg&kKiu4Oi3=SeR4|K&({!lJ=*q9O`LN?TMrn3)GqW@O>A< zANb*$?&>&ht`Gm<@NE7s^f$!*BPw zhZtRVjpa!MZ{Or)3b>`DbW&!xs_@{I4eGf|6_BGYqxw6ew$OvA?4*RV(CsNFS$l^? zimQ6)`K?wFllO6&KK3moEuHULBWdZORX^utBRZ}C83}$UuLA#IKdW zfb_8k@7O%zd1Q^RW$vEe0tTy|QfVYR`!fpJE;!8)#=#0!2AIrv^zdR3do(o2uFwXL zvDE75=DJpFc~KoI*_;#C_mPfczySh9oyovg%*V$Xm(udwHSMqp+p~<)t@v6hMw~D3 z*ib*pyJ~en=w|y>g+4yic+>VstD2!FN+3yet1E^LY`8MR!#$}{dE~!6H3ClFd0u$N zX@td2tG6bi1!?Muca<0_w&gQp9rEEJjc=DPbam=Aw&9*n)z8g=uT200g6u~^u(`iWT!KdZ(KiWv+3Y5ThhQ^2-o#!kUL7D$U zi$j&A=5Y-|;x{vf2D`{iG};T=K4k}aJ09}m8`y&dn;w31dFJr%cn_ldi?FX2?$NNr zRwUR3(}DP_sZD6vt0a&^&8L+oRY$JO9?Bjr4#@L*Qzo21!dj!Ji~QlpTms&P4K|?Z zTR?D7yf>j#RaIpb!Apn-(PqUj`N|RJ^6>X~|HyEb@DT`vEr9m4(N{Hfoj%d_GfbM| z1(4RHOga3lyj`jXYHZvAk`UV0N8pbEqmP3>qVfHIbov5?;OeGxybuTi)V(>|@6voH zTmgz?kyvn!;7iOa!43vDf7OywrXt37?14(ez#A)9@*RMy0L*dm^11NZDU#2xYTPfE zx&T7hM^IIT#q(^P-QzRh*(|_c{nL%Otp6$(9w+g}D;!=@C|=7khxY{qs(lkmKdN)2 zIs#OQdwR}*Dgy;f-^jFulBX^G>jh2Am|cGrczv&WqZ9E*Ean?U=Fo{?zpz?+_+{Pc zX=5;bzYA{=;7XJn&0zQju$k=I8`&eu)G?nx45EjRF$Di&0ImR=cP zZpUvI_hiaAkM9p7D&#$8R{YLZzNDC)9`0DD@5iu`O^38_=UG}7n{}7jDXL2CtccU6y?exxNzWYkK4O1BJh)eP^Wqm?g4kMcmZA`N!Qj&G%6W}BmAtO`6L9G7R z{8%><$N~>Zq)o%q2V$nF*}Ptp*ikzDlSb23$OZI-B-DtuR3G}vK;dwPP&WLv{iiZM=4cKMN;R6e#*zuFL%co_ais^8# zhIS-Nve##E3DEtKp|+K7*so<>JRH710)^C4CUTGR z!9#xqnY6eV!pW1L6d&{aL91CL6z}Xo?IM;BjA^?XppwB|@~PN9bgjIhkeBi~?+@ZB7rxs2{t(ax34 z=hPx_^}X)%_SlDfW1Rh~9iO~OrO7~&PZQ+Eg9b0VTLJ<`?TVNN*GhO4ZHD&l;nGwJ zZd=F^t2c$`l66U%X$xx`@Qde`Gk&AsX>Q%<15jjkx`Senkf4Hziis(K+jn}#-s_vt zgTyOaB_$;-_%-7UgATW`sxBy8oyjaSV1BKg0grF*UiEi=E$d43+x<}%#mMviaA)>t z?5U1o*muWw4y#4J8sUSZ?^s}?-5HOlp)(bw&Kp>T7$ zrchK^xKd5ZP9PsAo)FCp`DKpO>?kcQy(3UdYWKn8)p6c>+nuM`u5%4l_iCKt?=|_A zU5dXn>!_}lcEjpvXTQUhs!$8Vq*g0bFN0eR|Cm;GudZ7DE^RMwwW3Snu5@u8=kD^{afe1Yx7YWDR`ZYE${E2Ee;oyxR{6tHgv{;4%G$i6v@f*C@j}A z@X{Sfzgbr1DsM_AlRuP|6crg#Q8O6suYIklFF#9T=_Z$)|EsM|xIA0benNbJs6&W{ zF4wf@REdRT1~vWtF&U@91w^jt+3C>{Y223o z^N0N8Vm)Kym;Hl-wf*Ziq-~HaIqtXXWiNkGv>j24VG{Bg7Xob#58lN>B3# zQm%u>sA!l>y-7o6V}%C(V*HygWb*Rz=9xF70C0Q!B@HEez7@|9R$myW;{VGuCMMqX%?k-!$4o8sc`v3-iVCwpxsmUO_-F*crge z2cMRf>`l%;ifEy_fK*0nxvj@H3WG&w5&Hn@3`<^q)~B&;tUnfinY*_wFV)m57P{TvFPxbj~=c=yn{A|6UOG56a4 cC0x)9mfioR>04fQInSWbM&Cu1BOgBh4-0e(Z~y=R literal 0 HcmV?d00001 diff --git a/stream_chat_v1/android/app/src/main/res/drawable-mdpi/ic_launcher_background.png b/stream_chat_v1/android/app/src/main/res/drawable-mdpi/ic_launcher_background.png new file mode 100644 index 0000000000000000000000000000000000000000..6a78a3117d84ed2135bedd5b4bd5835708adfa21 GIT binary patch literal 333 zcmeAS@N?(olHy`uVBq!ia0vp^IUvlz1|<8_!p|}=Fp7A(IEGX(zP)&mlR-h?fPwtG zm;Zw282^~$WaPN8dhSfuWB+6iNFPq(={D3kwn1VvhcmEHaQ3kCI(MeKbLh* G2~7b0Sbi1& literal 0 HcmV?d00001 diff --git a/stream_chat_v1/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png b/stream_chat_v1/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..0145cae348b6ccb43cebd5facdc41c23b18f6f11 GIT binary patch literal 2623 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 literal 0 HcmV?d00001 diff --git a/stream_chat_v1/android/app/src/main/res/drawable-xxhdpi/ic_launcher_background.png b/stream_chat_v1/android/app/src/main/res/drawable-xxhdpi/ic_launcher_background.png new file mode 100644 index 0000000000000000000000000000000000000000..b1b4cace8f9bf8bf3f35bf9a82967b2de4404f04 GIT binary patch literal 1021 zcmeAS@N?(olHy`uVBq!ia0y~yU~~at4mO}j{44ik3=GUiJY5_^Dj45hQDkIL5IAr^ z{L7MhE`!$$kMs^+x%Q@*ts!zfGeccs2ZNzYgM^X;kDx*uhk!Fnha%Gv0mh_J;n6S| eO%MZ}8)E7ovFDvHn$!!-)(oDmelF{r5}E*YM&_3Q literal 0 HcmV?d00001 diff --git a/stream_chat_v1/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png b/stream_chat_v1/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..837416c02b7c1ecce8d812553ec71fc4088ea1d4 GIT binary patch literal 8365 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 MGc&BX`}Fny0OsCD)c^nh literal 0 HcmV?d00001 diff --git a/stream_chat_v1/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_background.png b/stream_chat_v1/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_background.png new file mode 100644 index 0000000000000000000000000000000000000000..8b20fd605819b8070931f6ea8a5bde9be0981215 GIT binary patch literal 1710 zcmeAS@N?(olHy`uVBq!ia0y~yVB7%09Be?56MhC-3=C|go-U3d6^w7M8uBtI2pn)= zt9cZE^l@XW$SjXNi7MNa5vX-%6%|nr~=kQ44$rjF6*2Ung9*er4;}G literal 0 HcmV?d00001 diff --git a/stream_chat_v1/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png b/stream_chat_v1/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..5f89936bd38c201ff431bada8435cc1f041aa4a9 GIT binary patch literal 11099 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 Bo - - - - - diff --git a/stream_chat_v1/android/app/src/main/res/drawable/launch_background.xml b/stream_chat_v1/android/app/src/main/res/drawable/launch_background.xml index 3618fa7ad7..304732f884 100644 --- a/stream_chat_v1/android/app/src/main/res/drawable/launch_background.xml +++ b/stream_chat_v1/android/app/src/main/res/drawable/launch_background.xml @@ -1,5 +1,12 @@ - + + + + diff --git a/stream_chat_v1/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/stream_chat_v1/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml index 7353dbd1fd..7e91a578c4 100644 --- a/stream_chat_v1/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ b/stream_chat_v1/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -1,5 +1,5 @@ - - - \ No newline at end of file + + + diff --git a/stream_chat_v1/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/stream_chat_v1/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 7353dbd1fd..0000000000 --- a/stream_chat_v1/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/stream_chat_v1/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/stream_chat_v1/android/app/src/main/res/mipmap-hdpi/ic_launcher.png index 818a3c804bc92eee150317fdcfb8e378947fd732..8ec56ee792d137eb68a716c4a44e2e1ef96be32c 100644 GIT binary patch literal 2988 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 MrZy&3M(*+d0pjzbVgLXD literal 4323 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 R7z6+S002ovPDHLkV1jwwX;1(F diff --git a/stream_chat_v1/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/stream_chat_v1/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 818a3c804bc92eee150317fdcfb8e378947fd732..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4323 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 R7z6+S002ovPDHLkV1jwwX;1(F diff --git a/stream_chat_v1/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/stream_chat_v1/android/app/src/main/res/mipmap-mdpi/ic_launcher.png index 38bf9b8031b3507b789b9b8670e8c5b4f3cc5f14..2f7fdaa7e0c24641edac586d68e910dd7b916345 100644 GIT binary patch delta 1826 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

mD4Zu(e0Mh*}>&rSpSgS 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 literal 6191 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 literal 9719 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 FV1hlikk|kK diff --git a/stream_chat_v1/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/stream_chat_v1/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index bd5086fc46fed00127c20cd98d76372f6bc5981f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9719 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 FV1hlikk|kK diff --git a/stream_chat_v1/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/stream_chat_v1/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index 6a602c324673cce1bfcc909227ee84295c5eb2ec..dd30e06e2861798f277a9e4e444417f0f444e3f4 100644 GIT binary patch literal 8762 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

<>5{8FHRmJLp8Fp#2t+eq`i$^Rvu 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 diff --git a/stream_chat_v1/web/icons/Icon-512.png b/stream_chat_v1/web/icons/Icon-512.png index 88cfd48dff1169879ba46840804b412fe02fefd6..e362036687d23f272cbfbff2065cf530d514c76a 100644 GIT binary patch literal 24550 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 literal 8252 zcmd5=2T+s!lYZ%-(h(2@5fr2dC?F^$C=i-}R6$UX8af(!je;W5yC_|HmujSgN*6?W z3knF*TL1$|?oD*=zPbBVex*RUIKsL<(&Rj9%^UD2IK3W?2j>D?eWQgvS-HLymHo9%~|N2Q{~j za?*X-{b9JRowv_*Mh|;*-kPFn>PI;r<#kFaxFqbn?aq|PduQg=2Q;~Qc}#z)_T%x9 zE|0!a70`58wjREmAH38H1)#gof)U3g9FZ^ zF7&-0^Hy{4XHWLoC*hOG(dg~2g6&?-wqcpf{ z&3=o8vw7lMi22jCG9RQbv8H}`+}9^zSk`nlR8?Z&G2dlDy$4#+WOlg;VHqzuE=fM@ z?OI6HEJH4&tA?FVG}9>jAnq_^tlw8NbjNhfqk2rQr?h(F&WiKy03Sn=-;ZJRh~JrD zbt)zLbnabttEZ>zUiu`N*u4sfQaLE8-WDn@tHp50uD(^r-}UsUUu)`!Rl1PozAc!a z?uj|2QDQ%oV-jxUJmJycySBINSKdX{kDYRS=+`HgR2GO19fg&lZKyBFbbXhQV~v~L za^U944F1_GtuFXtvDdDNDvp<`fqy);>Vw=ncy!NB85Tw{&sT5&Ox%-p%8fTS;OzlRBwErvO+ROe?{%q-Zge=%Up|D4L#>4K@Ke=x%?*^_^P*KD zgXueMiS63!sEw@fNLB-i^F|@Oib+S4bcy{eu&e}Xvb^(mA!=U=Xr3||IpV~3K zQWzEsUeX_qBe6fky#M zzOJm5b+l;~>=sdp%i}}0h zO?B?i*W;Ndn02Y0GUUPxERG`3Bjtj!NroLoYtyVdLtl?SE*CYpf4|_${ku2s`*_)k zN=a}V8_2R5QANlxsq!1BkT6$4>9=-Ix4As@FSS;1q^#TXPrBsw>hJ}$jZ{kUHoP+H zvoYiR39gX}2OHIBYCa~6ERRPJ#V}RIIZakUmuIoLF*{sO8rAUEB9|+A#C|@kw5>u0 zBd=F!4I)Be8ycH*)X1-VPiZ+Ts8_GB;YW&ZFFUo|Sw|x~ZajLsp+_3gv((Q#N>?Jz zFBf`~p_#^${zhPIIJY~yo!7$-xi2LK%3&RkFg}Ax)3+dFCjGgKv^1;lUzQlPo^E{K zmCnrwJ)NuSaJEmueEPO@(_6h3f5mFffhkU9r8A8(JC5eOkux{gPmx_$Uv&|hyj)gN zd>JP8l2U&81@1Hc>#*su2xd{)T`Yw< zN$dSLUN}dfx)Fu`NcY}TuZ)SdviT{JHaiYgP4~@`x{&h*Hd>c3K_To9BnQi@;tuoL z%PYQo&{|IsM)_>BrF1oB~+`2_uZQ48z9!)mtUR zdfKE+b*w8cPu;F6RYJiYyV;PRBbThqHBEu_(U{(gGtjM}Zi$pL8Whx}<JwE3RM0F8x7%!!s)UJVq|TVd#hf1zVLya$;mYp(^oZQ2>=ZXU1c$}f zm|7kfk>=4KoQoQ!2&SOW5|JP1)%#55C$M(u4%SP~tHa&M+=;YsW=v(Old9L3(j)`u z2?#fK&1vtS?G6aOt@E`gZ9*qCmyvc>Ma@Q8^I4y~f3gs7*d=ATlP>1S zyF=k&6p2;7dn^8?+!wZO5r~B+;@KXFEn^&C=6ma1J7Au6y29iMIxd7#iW%=iUzq&C=$aPLa^Q zncia$@TIy6UT@69=nbty5epP>*fVW@5qbUcb2~Gg75dNd{COFLdiz3}kODn^U*=@E z0*$7u7Rl2u)=%fk4m8EK1ctR!6%Ve`e!O20L$0LkM#f+)n9h^dn{n`T*^~d+l*Qlx z$;JC0P9+en2Wlxjwq#z^a6pdnD6fJM!GV7_%8%c)kc5LZs_G^qvw)&J#6WSp< zmsd~1-(GrgjC56Pdf6#!dt^y8Rg}!#UXf)W%~PeU+kU`FeSZHk)%sFv++#Dujk-~m zFHvVJC}UBn2jN& zs!@nZ?e(iyZPNo`p1i#~wsv9l@#Z|ag3JR>0#u1iW9M1RK1iF6-RbJ4KYg?B`dET9 zyR~DjZ>%_vWYm*Z9_+^~hJ_|SNTzBKx=U0l9 z9x(J96b{`R)UVQ$I`wTJ@$_}`)_DyUNOso6=WOmQKI1e`oyYy1C&%AQU<0-`(ow)1 zT}gYdwWdm4wW6|K)LcfMe&psE0XGhMy&xS`@vLi|1#Za{D6l@#D!?nW87wcscUZgELT{Cz**^;Zb~7 z(~WFRO`~!WvyZAW-8v!6n&j*PLm9NlN}BuUN}@E^TX*4Or#dMMF?V9KBeLSiLO4?B zcE3WNIa-H{ThrlCoN=XjOGk1dT=xwwrmt<1a)mrRzg{35`@C!T?&_;Q4Ce=5=>z^*zE_c(0*vWo2_#TD<2)pLXV$FlwP}Ik74IdDQU@yhkCr5h zn5aa>B7PWy5NQ!vf7@p_qtC*{dZ8zLS;JetPkHi>IvPjtJ#ThGQD|Lq#@vE2xdl%`x4A8xOln}BiQ92Po zW;0%A?I5CQ_O`@Ad=`2BLPPbBuPUp@Hb%a_OOI}y{Rwa<#h z5^6M}s7VzE)2&I*33pA>e71d78QpF>sNK;?lj^Kl#wU7G++`N_oL4QPd-iPqBhhs| z(uVM}$ItF-onXuuXO}o$t)emBO3Hjfyil@*+GF;9j?`&67GBM;TGkLHi>@)rkS4Nj zAEk;u)`jc4C$qN6WV2dVd#q}2X6nKt&X*}I@jP%Srs%%DS92lpDY^K*Sx4`l;aql$ zt*-V{U&$DM>pdO?%jt$t=vg5|p+Rw?SPaLW zB6nvZ69$ne4Z(s$3=Rf&RX8L9PWMV*S0@R zuIk&ba#s6sxVZ51^4Kon46X^9`?DC9mEhWB3f+o4#2EXFqy0(UTc>GU| zGCJmI|Dn-dX#7|_6(fT)>&YQ0H&&JX3cTvAq(a@ydM4>5Njnuere{J8p;3?1az60* z$1E7Yyxt^ytULeokgDnRVKQw9vzHg1>X@@jM$n$HBlveIrKP5-GJq%iWH#odVwV6cF^kKX(@#%%uQVb>#T6L^mC@)%SMd4DF? zVky!~ge27>cpUP1Vi}Z32lbLV+CQy+T5Wdmva6Fg^lKb!zrg|HPU=5Qu}k;4GVH+x z%;&pN1LOce0w@9i1Mo-Y|7|z}fbch@BPp2{&R-5{GLoeu8@limQmFF zaJRR|^;kW_nw~0V^ zfTnR!Ni*;-%oSHG1yItARs~uxra|O?YJxBzLjpeE-=~TO3Dn`JL5Gz;F~O1u3|FE- zvK2Vve`ylc`a}G`gpHg58Cqc9fMoy1L}7x7T>%~b&irrNMo?np3`q;d3d;zTK>nrK zOjPS{@&74-fA7j)8uT9~*g23uGnxwIVj9HorzUX#s0pcp2?GH6i}~+kv9fWChtPa_ z@T3m+$0pbjdQw7jcnHn;Pi85hk_u2-1^}c)LNvjdam8K-XJ+KgKQ%!?2n_!#{$H|| zLO=%;hRo6EDmnOBKCL9Cg~ETU##@u^W_5joZ%Et%X_n##%JDOcsO=0VL|Lkk!VdRJ z^|~2pB@PUspT?NOeO?=0Vb+fAGc!j%Ufn-cB`s2A~W{Zj{`wqWq_-w0wr@6VrM zbzni@8c>WS!7c&|ZR$cQ;`niRw{4kG#e z70e!uX8VmP23SuJ*)#(&R=;SxGAvq|&>geL&!5Z7@0Z(No*W561n#u$Uc`f9pD70# z=sKOSK|bF~#khTTn)B28h^a1{;>EaRnHj~>i=Fnr3+Fa4 z`^+O5_itS#7kPd20rq66_wH`%?HNzWk@XFK0n;Z@Cx{kx==2L22zWH$Yg?7 zvDj|u{{+NR3JvUH({;b*$b(U5U z7(lF!1bz2%06+|-v(D?2KgwNw7( zJB#Tz+ZRi&U$i?f34m7>uTzO#+E5cbaiQ&L}UxyOQq~afbNB4EI{E04ZWg53w0A{O%qo=lF8d zf~ktGvIgf-a~zQoWf>loF7pOodrd0a2|BzwwPDV}ShauTK8*fmF6NRbO>Iw9zZU}u zw8Ya}?seBnEGQDmH#XpUUkj}N49tP<2jYwTFp!P+&Fd(%Z#yo80|5@zN(D{_pNow*&4%ql zW~&yp@scb-+Qj-EmErY+Tu=dUmf@*BoXY2&oKT8U?8?s1d}4a`Aq>7SV800m$FE~? zjmz(LY+Xx9sDX$;vU`xgw*jLw7dWOnWWCO8o|;}f>cu0Q&`0I{YudMn;P;L3R-uz# zfns_mZED_IakFBPP2r_S8XM$X)@O-xVKi4`7373Jkd5{2$M#%cRhWer3M(vr{S6>h zj{givZJ3(`yFL@``(afn&~iNx@B1|-qfYiZu?-_&Z8+R~v`d6R-}EX9IVXWO-!hL5 z*k6T#^2zAXdardU3Ao~I)4DGdAv2bx{4nOK`20rJo>rmk3S2ZDu}))8Z1m}CKigf0 z3L`3Y`{huj`xj9@`$xTZzZc3je?n^yG<8sw$`Y%}9mUsjUR%T!?k^(q)6FH6Af^b6 zlPg~IEwg0y;`t9y;#D+uz!oE4VP&Je!<#q*F?m5L5?J3i@!0J6q#eu z!RRU`-)HeqGi_UJZ(n~|PSNsv+Wgl{P-TvaUQ9j?ZCtvb^37U$sFpBrkT{7Jpd?HpIvj2!}RIq zH{9~+gErN2+}J`>Jvng2hwM`=PLNkc7pkjblKW|+Fk9rc)G1R>Ww>RC=r-|!m-u7( zc(a$9NG}w#PjWNMS~)o=i~WA&4L(YIW25@AL9+H9!?3Y}sv#MOdY{bb9j>p`{?O(P zIvb`n?_(gP2w3P#&91JX*md+bBEr%xUHMVqfB;(f?OPtMnAZ#rm5q5mh;a2f_si2_ z3oXWB?{NF(JtkAn6F(O{z@b76OIqMC$&oJ_&S|YbFJ*)3qVX_uNf5b8(!vGX19hsG z(OP>RmZp29KH9Ge2kKjKigUmOe^K_!UXP`von)PR8Qz$%=EmOB9xS(ZxE_tnyzo}7 z=6~$~9k0M~v}`w={AeqF?_)9q{m8K#6M{a&(;u;O41j)I$^T?lx5(zlebpY@NT&#N zR+1bB)-1-xj}R8uwqwf=iP1GbxBjneCC%UrSdSxK1vM^i9;bUkS#iRZw2H>rS<2<$ zNT3|sDH>{tXb=zq7XZi*K?#Zsa1h1{h5!Tq_YbKFm_*=A5-<~j63he;4`77!|LBlo zR^~tR3yxcU=gDFbshyF6>o0bdp$qmHS7D}m3;^QZq9kBBU|9$N-~oU?G5;jyFR7>z hN`IR97YZXIo@y!QgFWddJ3|0`sjFx!m))><{BI=FK%f8s diff --git a/stream_chat_v1/web/icons/Icon-maskable-192.png b/stream_chat_v1/web/icons/Icon-maskable-192.png new file mode 100644 index 0000000000000000000000000000000000000000..dd30e06e2861798f277a9e4e444417f0f444e3f4 GIT binary patch literal 8762 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

<>5{8FHRmJLp8Fp#2t+eq`i$^Rvu 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 literal 0 HcmV?d00001 diff --git a/stream_chat_v1/web/manifest.json b/stream_chat_v1/web/manifest.json index 97eb9afb4a..0657cf7bb7 100644 --- a/stream_chat_v1/web/manifest.json +++ b/stream_chat_v1/web/manifest.json @@ -18,6 +18,18 @@ "src": "icons/Icon-512.png", "sizes": "512x512", "type": "image/png" + }, + { + "src": "icons/Icon-maskable-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "icons/Icon-maskable-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" } ] -} +} \ No newline at end of file From 477a1f2bc9e0c6f9172d7ec72f2f73188d6ab57c Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Sat, 8 Apr 2023 02:18:15 +0530 Subject: [PATCH 140/172] chore(sample-app): update deploymeny target on macos Signed-off-by: xsahil03x --- stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj | 12 +++++++----- stream_chat_v1/ios/Runner/Info.plist | 2 ++ .../macos/Runner.xcodeproj/project.pbxproj | 11 ++++++----- .../xcshareddata/xcschemes/Runner.xcscheme | 8 +++----- 4 files changed, 18 insertions(+), 15 deletions(-) diff --git a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj index b6f9d7cf63..8a0506c849 100644 --- a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj +++ b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -223,6 +223,7 @@ /* Begin PBXShellScriptBuildPhase section */ 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -259,11 +260,11 @@ "${BUILT_PRODUCTS_DIR}/image_picker_ios/image_picker_ios.framework", "${BUILT_PRODUCTS_DIR}/libwebp/libwebp.framework", "${BUILT_PRODUCTS_DIR}/package_info_plus/package_info_plus.framework", - "${BUILT_PRODUCTS_DIR}/path_provider_ios/path_provider_ios.framework", + "${BUILT_PRODUCTS_DIR}/path_provider_foundation/path_provider_foundation.framework", "${BUILT_PRODUCTS_DIR}/photo_manager/photo_manager.framework", "${BUILT_PRODUCTS_DIR}/sentry_flutter/sentry_flutter.framework", "${BUILT_PRODUCTS_DIR}/share_plus/share_plus.framework", - "${BUILT_PRODUCTS_DIR}/shared_preferences_ios/shared_preferences_ios.framework", + "${BUILT_PRODUCTS_DIR}/shared_preferences_foundation/shared_preferences_foundation.framework", "${BUILT_PRODUCTS_DIR}/sqflite/sqflite.framework", "${BUILT_PRODUCTS_DIR}/sqlite3/sqlite3.framework", "${BUILT_PRODUCTS_DIR}/sqlite3_flutter_libs/sqlite3_flutter_libs.framework", @@ -291,11 +292,11 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/image_picker_ios.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libwebp.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/package_info_plus.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider_ios.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider_foundation.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/photo_manager.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sentry_flutter.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/share_plus.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences_ios.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences_foundation.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqflite.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqlite3.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqlite3_flutter_libs.framework", @@ -311,6 +312,7 @@ }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); diff --git a/stream_chat_v1/ios/Runner/Info.plist b/stream_chat_v1/ios/Runner/Info.plist index 31b04f72c8..17d3006974 100644 --- a/stream_chat_v1/ios/Runner/Info.plist +++ b/stream_chat_v1/ios/Runner/Info.plist @@ -69,5 +69,7 @@ CADisableMinimumFrameDurationOnPhone + UIApplicationSupportsIndirectInputEvents + diff --git a/stream_chat_v1/macos/Runner.xcodeproj/project.pbxproj b/stream_chat_v1/macos/Runner.xcodeproj/project.pbxproj index 8972854e80..237a137008 100644 --- a/stream_chat_v1/macos/Runner.xcodeproj/project.pbxproj +++ b/stream_chat_v1/macos/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 51; + objectVersion = 54; objects = { /* Begin PBXAggregateTarget section */ @@ -204,7 +204,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 0930; + LastUpgradeCheck = 1300; ORGANIZATIONNAME = ""; TargetAttributes = { 33CC10EC2044A3C60003C045 = { @@ -278,6 +278,7 @@ }; 3399D490228B24CF009A79C7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -404,7 +405,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; @@ -484,7 +485,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; @@ -531,7 +532,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; diff --git a/stream_chat_v1/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/stream_chat_v1/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 1961c76671..55dda25a80 100644 --- a/stream_chat_v1/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/stream_chat_v1/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ - - + + - - Date: Sat, 8 Apr 2023 02:48:30 +0530 Subject: [PATCH 141/172] chore(sample-app): update workflow and fix flutter web for deployment Signed-off-by: xsahil03x --- stream_chat_v1/web/index.html | 52 ++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/stream_chat_v1/web/index.html b/stream_chat_v1/web/index.html index c9fb727522..9697ba7542 100644 --- a/stream_chat_v1/web/index.html +++ b/stream_chat_v1/web/index.html @@ -1,34 +1,60 @@ + + + - + - + - example + Stream Chat V1 + + + + + - - - - + From 5bae6284e42d42553dc892496e58f4beaff48ea3 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Sat, 8 Apr 2023 03:05:43 +0530 Subject: [PATCH 142/172] chore(sample-app): add ruby version Signed-off-by: xsahil03x --- stream_chat_v1/ios/.ruby-version | 1 + stream_chat_v1/web/index.html | 1 + 2 files changed, 2 insertions(+) create mode 100644 stream_chat_v1/ios/.ruby-version diff --git a/stream_chat_v1/ios/.ruby-version b/stream_chat_v1/ios/.ruby-version new file mode 100644 index 0000000000..a0cd9f0ccb --- /dev/null +++ b/stream_chat_v1/ios/.ruby-version @@ -0,0 +1 @@ +3.1.0 \ No newline at end of file diff --git a/stream_chat_v1/web/index.html b/stream_chat_v1/web/index.html index 9697ba7542..9c82347ef2 100644 --- a/stream_chat_v1/web/index.html +++ b/stream_chat_v1/web/index.html @@ -39,6 +39,7 @@ + - - + From d183efc63e92d9d2a51782354b4530ddd93f9485 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Mon, 13 Jan 2025 23:13:55 +0100 Subject: [PATCH 164/172] fix: pin chewie to 1.8.5 --- stream_chat_v1/pubspec_overrides.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/stream_chat_v1/pubspec_overrides.yaml b/stream_chat_v1/pubspec_overrides.yaml index 3ae03d0f4b..24248ecf3a 100644 --- a/stream_chat_v1/pubspec_overrides.yaml +++ b/stream_chat_v1/pubspec_overrides.yaml @@ -23,4 +23,8 @@ dependency_overrides: git: url: https://github.com/GetStream/stream-chat-flutter.git ref: master - path: packages/stream_chat_localizations \ No newline at end of file + path: packages/stream_chat_localizations + + # The last chewie version that supports flutter 3.24.5 + # Issue: https://github.com/fluttercommunity/chewie/issues/888 + chewie: 1.8.5 \ No newline at end of file From 688bf48d83f3ddf2e43ffe1d979123a89f9e78ff Mon Sep 17 00:00:00 2001 From: kanat Date: Fri, 24 Jan 2025 18:33:42 -0500 Subject: [PATCH 165/172] [CHA-546] set up ios with local environment --- stream_chat_v1/ios/Flutter/Debug.xcconfig | 1 - stream_chat_v1/ios/Flutter/Release.xcconfig | 1 - stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj | 12 ++++++------ stream_chat_v1/ios/Runner/Info.plist | 5 +++++ stream_chat_v1/lib/app.dart | 9 ++++++++- 5 files changed, 19 insertions(+), 9 deletions(-) diff --git a/stream_chat_v1/ios/Flutter/Debug.xcconfig b/stream_chat_v1/ios/Flutter/Debug.xcconfig index b2f5fae9c2..ec97fc6f30 100644 --- a/stream_chat_v1/ios/Flutter/Debug.xcconfig +++ b/stream_chat_v1/ios/Flutter/Debug.xcconfig @@ -1,3 +1,2 @@ #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" -#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" diff --git a/stream_chat_v1/ios/Flutter/Release.xcconfig b/stream_chat_v1/ios/Flutter/Release.xcconfig index 88c29144c8..c4855bfe20 100644 --- a/stream_chat_v1/ios/Flutter/Release.xcconfig +++ b/stream_chat_v1/ios/Flutter/Release.xcconfig @@ -1,3 +1,2 @@ #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" -#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" diff --git a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj index 2ec0f4e864..1dff587d86 100644 --- a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj +++ b/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj @@ -466,7 +466,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -493,7 +493,7 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -558,7 +558,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -607,7 +607,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -635,7 +635,7 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -672,7 +672,7 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", diff --git a/stream_chat_v1/ios/Runner/Info.plist b/stream_chat_v1/ios/Runner/Info.plist index 5167f27f5e..27d9c14b17 100644 --- a/stream_chat_v1/ios/Runner/Info.plist +++ b/stream_chat_v1/ios/Runner/Info.plist @@ -65,5 +65,10 @@ UIViewControllerBasedStatusBarAppearance + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + diff --git a/stream_chat_v1/lib/app.dart b/stream_chat_v1/lib/app.dart index a986c89118..b151468bd0 100644 --- a/stream_chat_v1/lib/app.dart +++ b/stream_chat_v1/lib/app.dart @@ -110,6 +110,8 @@ StreamChatClient buildStreamChatClient(String apiKey) { apiKey, logLevel: logLevel, logHandlerFunction: _sampleAppLogHandler, + //baseURL: 'http://:3030', + //baseWsUrl: 'ws://:8800', )..chatPersistenceClient = chatPersistentClient; } @@ -173,9 +175,14 @@ class _StreamChatSampleAppState extends State .listen(_onFirebaseTokenRefresh(client))); final token = await FirebaseMessaging.instance.getToken(); + debugPrint('[onTokenInit] #firebase; token: $token'); if (token != null) { + // replace with your push provider name, e.g., 'chat-flutter-firebase' + const pushProviderName = null; + // add Token to Stream - await client.addDevice(token, PushProvider.firebase); + await client.addDevice(token, PushProvider.firebase, + pushProviderName: pushProviderName); } } // User logged out From 11a4f84bff34a85990f3a7806f2f133a69550f09 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Wed, 12 Feb 2025 13:57:28 +0530 Subject: [PATCH 166/172] refactor: rename `stream_chat_v1` -> `sample_app` --- .gitignore | 5 +- melos.yaml | 12 +- {stream_chat_v1 => sample_app}/.gitignore | 0 {stream_chat_v1 => sample_app}/.metadata | 0 {stream_chat_v1 => sample_app}/README.md | 0 .../analysis_options.yaml | 0 .../android/.gitignore | 0 .../android/app/build.gradle | 0 .../android/app/debug.keystore | Bin .../android/app/src/debug/AndroidManifest.xml | 0 .../android/app/src/main/AndroidManifest.xml | 0 .../com/example/example/MainActivity.kt | 0 .../drawable-anydpi-v24/ic_notification.xml | 0 .../ic_notification_in_app.xml | 0 .../drawable-hdpi/ic_launcher_background.png | Bin .../drawable-hdpi/ic_launcher_foreground.png | Bin .../res/drawable-hdpi/ic_notification.png | Bin .../drawable-hdpi/ic_notification_in_app.png | Bin .../drawable-mdpi/ic_launcher_background.png | Bin .../drawable-mdpi/ic_launcher_foreground.png | Bin .../res/drawable-mdpi/ic_notification.png | Bin .../drawable-mdpi/ic_notification_in_app.png | Bin .../res/drawable-v21/launch_background.xml | 0 .../drawable-xhdpi/ic_launcher_background.png | Bin .../drawable-xhdpi/ic_launcher_foreground.png | Bin .../res/drawable-xhdpi/ic_notification.png | Bin .../drawable-xhdpi/ic_notification_in_app.png | Bin .../ic_launcher_background.png | Bin .../ic_launcher_foreground.png | Bin .../res/drawable-xxhdpi/ic_notification.png | Bin .../ic_notification_in_app.png | Bin .../ic_launcher_background.png | Bin .../ic_launcher_foreground.png | Bin .../main/res/drawable/launch_background.xml | 0 .../res/mipmap-anydpi-v26/ic_launcher.xml | 0 .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin .../app/src/main/res/values-night/styles.xml | 0 .../app/src/main/res/values/styles.xml | 0 .../app/src/profile/AndroidManifest.xml | 0 .../android/build.gradle | 0 .../android/gradle.properties | 0 .../gradle/wrapper/gradle-wrapper.properties | 0 .../android/settings.gradle | 0 .../android/settings_aar.gradle | 0 .../assets/floating_boat.json | 0 .../assets/ic_launcher.png | Bin .../assets/ic_launcher_background.png | Bin .../assets/ic_launcher_foreground.png | Bin .../assets/icon_arrow_right.svg | 0 .../assets/logo.svg | 0 {stream_chat_v1 => sample_app}/ios/.gitignore | 0 .../ios/.ruby-version | 0 .../ios/Flutter/AppFrameworkInfo.plist | 0 .../ios/Flutter/Debug.xcconfig | 0 .../ios/Flutter/Release.xcconfig | 0 {stream_chat_v1 => sample_app}/ios/Gemfile | 0 .../ios/Gemfile.lock | 0 sample_app/ios/Podfile | 44 ++ .../ios/Runner.xcodeproj/project.pbxproj | 0 .../contents.xcworkspacedata | 0 .../xcshareddata/IDEWorkspaceChecks.plist | 0 .../xcshareddata/WorkspaceSettings.xcsettings | 0 .../xcschemes/Notifications.xcscheme | 0 .../xcshareddata/xcschemes/Runner.xcscheme | 0 .../contents.xcworkspacedata | 0 .../xcshareddata/IDEWorkspaceChecks.plist | 0 .../xcshareddata/WorkspaceSettings.xcsettings | 0 .../ios/Runner/AppDelegate.swift | 0 .../AppIcon.appiconset/Contents.json | 0 .../Icon-App-1024x1024@1x.png | Bin .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin .../AppIcon.appiconset/Icon-App-50x50@1x.png | Bin .../AppIcon.appiconset/Icon-App-50x50@2x.png | Bin .../AppIcon.appiconset/Icon-App-57x57@1x.png | Bin .../AppIcon.appiconset/Icon-App-57x57@2x.png | Bin .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin .../AppIcon.appiconset/Icon-App-72x72@1x.png | Bin .../AppIcon.appiconset/Icon-App-72x72@2x.png | Bin .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin .../Icon-App-83.5x83.5@2x.png | Bin .../LaunchBackground.imageset/Contents.json | 0 .../LaunchBackground.imageset/background.png | Bin .../LaunchImage.imageset/Contents.json | 0 .../LaunchImage.imageset/LaunchImage.png | Bin .../LaunchImage.imageset/LaunchImage@2x.png | Bin .../LaunchImage.imageset/LaunchImage@3x.png | Bin .../LaunchImage.imageset/README.md | 0 .../Runner/Base.lproj/LaunchScreen.storyboard | 0 .../ios/Runner/Base.lproj/Main.storyboard | 0 .../ios/Runner/GoogleService-Info.plist | 0 .../ios/Runner/Info.plist | 0 .../ios/Runner/Runner-Bridging-Header.h | 0 .../ios/Runner/Runner.entitlements | 0 .../ios/fastlane/Appfile | 0 .../ios/fastlane/Fastfile | 0 .../ios/fastlane/Matchfile | 0 .../ios/fastlane/Pluginfile | 0 .../ios/fastlane/README.md | 0 .../fastlane/beta_gym_export_options.plist | 0 .../ios/fastlane/report.xml | 0 .../testflight_gym_export_options.plist | 0 .../ios/firebase_app_id_file.json | 0 {stream_chat_v1 => sample_app}/lib/app.dart | 16 +- .../lib/firebase_options.dart | 0 {stream_chat_v1 => sample_app}/lib/main.dart | 4 +- .../lib/pages/advanced_options_page.dart | 12 +- .../pages/channel_file_display_screen.dart | 2 +- .../lib/pages/channel_list_page.dart | 16 +- .../pages/channel_media_display_screen.dart | 2 +- .../lib/pages/channel_page.dart | 4 +- .../lib/pages/chat_info_screen.dart | 8 +- .../lib/pages/choose_user_page.dart | 8 +- .../lib/pages/group_chat_details_screen.dart | 4 +- .../lib/pages/group_info_screen.dart | 6 +- .../lib/pages/new_chat_screen.dart | 2 +- .../lib/pages/new_group_chat_screen.dart | 4 +- .../lib/pages/pinned_messages_screen.dart | 4 +- .../lib/pages/splash_screen.dart | 0 .../lib/pages/thread_list_page.dart | 2 +- .../lib/pages/thread_page.dart | 0 .../lib/pages/user_mentions_page.dart | 4 +- .../lib/routes/app_routes.dart | 22 +- .../lib/routes/routes.dart | 0 .../lib/state/init_data.dart | 0 .../lib/state/new_group_chat_state.dart | 0 .../lib/utils/app_config.dart | 0 .../utils/local_notification_observer.dart | 4 +- .../lib/utils/localizations.dart | 0 .../lib/utils/notifications_service.dart | 4 +- .../lib/widgets/channel_list.dart | 6 +- .../lib/widgets/chips_input_text_field.dart | 2 +- .../lib/widgets/search_text_field.dart | 0 .../lib/widgets/stream_version.dart | 2 +- .../macos/.gitignore | 0 .../macos/Flutter/Flutter-Debug.xcconfig | 0 .../macos/Flutter/Flutter-Release.xcconfig | 0 sample_app/macos/Podfile | 43 ++ .../macos/Runner.xcodeproj/project.pbxproj | 0 .../xcshareddata/IDEWorkspaceChecks.plist | 0 .../xcshareddata/xcschemes/Runner.xcscheme | 0 .../contents.xcworkspacedata | 0 .../xcshareddata/IDEWorkspaceChecks.plist | 0 .../macos/Runner/AppDelegate.swift | 0 .../AppIcon.appiconset/Contents.json | 0 .../AppIcon.appiconset/app_icon_1024.png | Bin .../AppIcon.appiconset/app_icon_128.png | Bin .../AppIcon.appiconset/app_icon_16.png | Bin .../AppIcon.appiconset/app_icon_256.png | Bin .../AppIcon.appiconset/app_icon_32.png | Bin .../AppIcon.appiconset/app_icon_512.png | Bin .../AppIcon.appiconset/app_icon_64.png | Bin .../macos/Runner/Base.lproj/MainMenu.xib | 0 .../macos/Runner/Configs/AppInfo.xcconfig | 0 .../macos/Runner/Configs/Debug.xcconfig | 0 .../macos/Runner/Configs/Release.xcconfig | 0 .../macos/Runner/Configs/Warnings.xcconfig | 0 .../macos/Runner/DebugProfile.entitlements | 0 .../macos/Runner/GoogleService-Info.plist | 0 .../macos/Runner/Info.plist | 0 .../macos/Runner/MainFlutterWindow.swift | 0 .../macos/Runner/Release.entitlements | 0 .../macos/Runner/RunnerDebug.entitlements | 0 .../macos/firebase_app_id_file.json | 0 {stream_chat_v1 => sample_app}/pubspec.yaml | 20 +- .../web/favicon.png | Bin .../web/icons/Icon-192.png | Bin .../web/icons/Icon-512.png | Bin .../web/icons/Icon-maskable-192.png | Bin .../web/icons/Icon-maskable-512.png | Bin {stream_chat_v1 => sample_app}/web/index.html | 0 .../web/manifest.json | 0 .../web/sql-wasm.js | 0 .../web/sql-wasm.wasm | Bin .../android/app/google-services.json | 559 ------------------ stream_chat_v1/ios/Flutter/.last_build_id | 1 - stream_chat_v1/pubspec_overrides.yaml | 30 - 190 files changed, 181 insertions(+), 671 deletions(-) rename {stream_chat_v1 => sample_app}/.gitignore (100%) rename {stream_chat_v1 => sample_app}/.metadata (100%) rename {stream_chat_v1 => sample_app}/README.md (100%) rename {stream_chat_v1 => sample_app}/analysis_options.yaml (100%) rename {stream_chat_v1 => sample_app}/android/.gitignore (100%) rename {stream_chat_v1 => sample_app}/android/app/build.gradle (100%) rename {stream_chat_v1 => sample_app}/android/app/debug.keystore (100%) rename {stream_chat_v1 => sample_app}/android/app/src/debug/AndroidManifest.xml (100%) rename {stream_chat_v1 => sample_app}/android/app/src/main/AndroidManifest.xml (100%) rename {stream_chat_v1 => sample_app}/android/app/src/main/kotlin/com/example/example/MainActivity.kt (100%) rename {stream_chat_v1 => sample_app}/android/app/src/main/res/drawable-anydpi-v24/ic_notification.xml (100%) rename {stream_chat_v1 => sample_app}/android/app/src/main/res/drawable-anydpi-v24/ic_notification_in_app.xml (100%) rename {stream_chat_v1 => sample_app}/android/app/src/main/res/drawable-hdpi/ic_launcher_background.png (100%) rename {stream_chat_v1 => sample_app}/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png (100%) rename {stream_chat_v1 => sample_app}/android/app/src/main/res/drawable-hdpi/ic_notification.png (100%) rename {stream_chat_v1 => sample_app}/android/app/src/main/res/drawable-hdpi/ic_notification_in_app.png (100%) rename {stream_chat_v1 => sample_app}/android/app/src/main/res/drawable-mdpi/ic_launcher_background.png (100%) rename {stream_chat_v1 => sample_app}/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png (100%) rename {stream_chat_v1 => sample_app}/android/app/src/main/res/drawable-mdpi/ic_notification.png (100%) rename {stream_chat_v1 => sample_app}/android/app/src/main/res/drawable-mdpi/ic_notification_in_app.png (100%) rename {stream_chat_v1 => sample_app}/android/app/src/main/res/drawable-v21/launch_background.xml (100%) rename {stream_chat_v1 => sample_app}/android/app/src/main/res/drawable-xhdpi/ic_launcher_background.png (100%) rename {stream_chat_v1 => sample_app}/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png (100%) rename {stream_chat_v1 => sample_app}/android/app/src/main/res/drawable-xhdpi/ic_notification.png (100%) rename {stream_chat_v1 => sample_app}/android/app/src/main/res/drawable-xhdpi/ic_notification_in_app.png (100%) rename {stream_chat_v1 => sample_app}/android/app/src/main/res/drawable-xxhdpi/ic_launcher_background.png (100%) rename {stream_chat_v1 => sample_app}/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png (100%) rename {stream_chat_v1 => sample_app}/android/app/src/main/res/drawable-xxhdpi/ic_notification.png (100%) rename {stream_chat_v1 => sample_app}/android/app/src/main/res/drawable-xxhdpi/ic_notification_in_app.png (100%) rename {stream_chat_v1 => sample_app}/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_background.png (100%) rename {stream_chat_v1 => sample_app}/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png (100%) rename {stream_chat_v1 => sample_app}/android/app/src/main/res/drawable/launch_background.xml (100%) rename {stream_chat_v1 => sample_app}/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml (100%) rename {stream_chat_v1 => sample_app}/android/app/src/main/res/mipmap-hdpi/ic_launcher.png (100%) rename {stream_chat_v1 => sample_app}/android/app/src/main/res/mipmap-mdpi/ic_launcher.png (100%) rename {stream_chat_v1 => sample_app}/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png (100%) rename {stream_chat_v1 => sample_app}/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png (100%) rename {stream_chat_v1 => sample_app}/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png (100%) rename {stream_chat_v1 => sample_app}/android/app/src/main/res/values-night/styles.xml (100%) rename {stream_chat_v1 => sample_app}/android/app/src/main/res/values/styles.xml (100%) rename {stream_chat_v1 => sample_app}/android/app/src/profile/AndroidManifest.xml (100%) rename {stream_chat_v1 => sample_app}/android/build.gradle (100%) rename {stream_chat_v1 => sample_app}/android/gradle.properties (100%) rename {stream_chat_v1 => sample_app}/android/gradle/wrapper/gradle-wrapper.properties (100%) rename {stream_chat_v1 => sample_app}/android/settings.gradle (100%) rename {stream_chat_v1 => sample_app}/android/settings_aar.gradle (100%) rename {stream_chat_v1 => sample_app}/assets/floating_boat.json (100%) rename {stream_chat_v1 => sample_app}/assets/ic_launcher.png (100%) rename {stream_chat_v1 => sample_app}/assets/ic_launcher_background.png (100%) rename {stream_chat_v1 => sample_app}/assets/ic_launcher_foreground.png (100%) rename {stream_chat_v1 => sample_app}/assets/icon_arrow_right.svg (100%) rename {stream_chat_v1 => sample_app}/assets/logo.svg (100%) rename {stream_chat_v1 => sample_app}/ios/.gitignore (100%) rename {stream_chat_v1 => sample_app}/ios/.ruby-version (100%) rename {stream_chat_v1 => sample_app}/ios/Flutter/AppFrameworkInfo.plist (100%) rename {stream_chat_v1 => sample_app}/ios/Flutter/Debug.xcconfig (100%) rename {stream_chat_v1 => sample_app}/ios/Flutter/Release.xcconfig (100%) rename {stream_chat_v1 => sample_app}/ios/Gemfile (100%) rename {stream_chat_v1 => sample_app}/ios/Gemfile.lock (100%) create mode 100644 sample_app/ios/Podfile rename {stream_chat_v1 => sample_app}/ios/Runner.xcodeproj/project.pbxproj (100%) rename {stream_chat_v1 => sample_app}/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata (100%) rename {stream_chat_v1 => sample_app}/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist (100%) rename {stream_chat_v1 => sample_app}/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings (100%) rename {stream_chat_v1 => sample_app}/ios/Runner.xcodeproj/xcshareddata/xcschemes/Notifications.xcscheme (100%) rename {stream_chat_v1 => sample_app}/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme (100%) rename {stream_chat_v1 => sample_app}/ios/Runner.xcworkspace/contents.xcworkspacedata (100%) rename {stream_chat_v1 => sample_app}/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist (100%) rename {stream_chat_v1 => sample_app}/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/AppDelegate.swift (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Base.lproj/LaunchScreen.storyboard (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Base.lproj/Main.storyboard (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/GoogleService-Info.plist (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Info.plist (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Runner-Bridging-Header.h (100%) rename {stream_chat_v1 => sample_app}/ios/Runner/Runner.entitlements (100%) rename {stream_chat_v1 => sample_app}/ios/fastlane/Appfile (100%) rename {stream_chat_v1 => sample_app}/ios/fastlane/Fastfile (100%) rename {stream_chat_v1 => sample_app}/ios/fastlane/Matchfile (100%) rename {stream_chat_v1 => sample_app}/ios/fastlane/Pluginfile (100%) rename {stream_chat_v1 => sample_app}/ios/fastlane/README.md (100%) rename {stream_chat_v1 => sample_app}/ios/fastlane/beta_gym_export_options.plist (100%) rename {stream_chat_v1 => sample_app}/ios/fastlane/report.xml (100%) rename {stream_chat_v1 => sample_app}/ios/fastlane/testflight_gym_export_options.plist (100%) rename {stream_chat_v1 => sample_app}/ios/firebase_app_id_file.json (100%) rename {stream_chat_v1 => sample_app}/lib/app.dart (96%) rename {stream_chat_v1 => sample_app}/lib/firebase_options.dart (100%) rename {stream_chat_v1 => sample_app}/lib/main.dart (95%) rename {stream_chat_v1 => sample_app}/lib/pages/advanced_options_page.dart (97%) rename {stream_chat_v1 => sample_app}/lib/pages/channel_file_display_screen.dart (98%) rename {stream_chat_v1 => sample_app}/lib/pages/channel_list_page.dart (95%) rename {stream_chat_v1 => sample_app}/lib/pages/channel_media_display_screen.dart (99%) rename {stream_chat_v1 => sample_app}/lib/pages/channel_page.dart (98%) rename {stream_chat_v1 => sample_app}/lib/pages/chat_info_screen.dart (98%) rename {stream_chat_v1 => sample_app}/lib/pages/choose_user_page.dart (97%) rename {stream_chat_v1 => sample_app}/lib/pages/group_chat_details_screen.dart (99%) rename {stream_chat_v1 => sample_app}/lib/pages/group_info_screen.dart (99%) rename {stream_chat_v1 => sample_app}/lib/pages/new_chat_screen.dart (99%) rename {stream_chat_v1 => sample_app}/lib/pages/new_group_chat_screen.dart (99%) rename {stream_chat_v1 => sample_app}/lib/pages/pinned_messages_screen.dart (97%) rename {stream_chat_v1 => sample_app}/lib/pages/splash_screen.dart (100%) rename {stream_chat_v1 => sample_app}/lib/pages/thread_list_page.dart (97%) rename {stream_chat_v1 => sample_app}/lib/pages/thread_page.dart (100%) rename {stream_chat_v1 => sample_app}/lib/pages/user_mentions_page.dart (96%) rename {stream_chat_v1 => sample_app}/lib/routes/app_routes.dart (85%) rename {stream_chat_v1 => sample_app}/lib/routes/routes.dart (100%) rename {stream_chat_v1 => sample_app}/lib/state/init_data.dart (100%) rename {stream_chat_v1 => sample_app}/lib/state/new_group_chat_state.dart (100%) rename {stream_chat_v1 => sample_app}/lib/utils/app_config.dart (100%) rename {stream_chat_v1 => sample_app}/lib/utils/local_notification_observer.dart (93%) rename {stream_chat_v1 => sample_app}/lib/utils/localizations.dart (100%) rename {stream_chat_v1 => sample_app}/lib/utils/notifications_service.dart (95%) rename {stream_chat_v1 => sample_app}/lib/widgets/channel_list.dart (98%) rename {stream_chat_v1 => sample_app}/lib/widgets/chips_input_text_field.dart (99%) rename {stream_chat_v1 => sample_app}/lib/widgets/search_text_field.dart (100%) rename {stream_chat_v1 => sample_app}/lib/widgets/stream_version.dart (95%) rename {stream_chat_v1 => sample_app}/macos/.gitignore (100%) rename {stream_chat_v1 => sample_app}/macos/Flutter/Flutter-Debug.xcconfig (100%) rename {stream_chat_v1 => sample_app}/macos/Flutter/Flutter-Release.xcconfig (100%) create mode 100644 sample_app/macos/Podfile rename {stream_chat_v1 => sample_app}/macos/Runner.xcodeproj/project.pbxproj (100%) rename {stream_chat_v1 => sample_app}/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist (100%) rename {stream_chat_v1 => sample_app}/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme (100%) rename {stream_chat_v1 => sample_app}/macos/Runner.xcworkspace/contents.xcworkspacedata (100%) rename {stream_chat_v1 => sample_app}/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist (100%) rename {stream_chat_v1 => sample_app}/macos/Runner/AppDelegate.swift (100%) rename {stream_chat_v1 => sample_app}/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json (100%) rename {stream_chat_v1 => sample_app}/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png (100%) rename {stream_chat_v1 => sample_app}/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png (100%) rename {stream_chat_v1 => sample_app}/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png (100%) rename {stream_chat_v1 => sample_app}/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png (100%) rename {stream_chat_v1 => sample_app}/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png (100%) rename {stream_chat_v1 => sample_app}/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png (100%) rename {stream_chat_v1 => sample_app}/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png (100%) rename {stream_chat_v1 => sample_app}/macos/Runner/Base.lproj/MainMenu.xib (100%) rename {stream_chat_v1 => sample_app}/macos/Runner/Configs/AppInfo.xcconfig (100%) rename {stream_chat_v1 => sample_app}/macos/Runner/Configs/Debug.xcconfig (100%) rename {stream_chat_v1 => sample_app}/macos/Runner/Configs/Release.xcconfig (100%) rename {stream_chat_v1 => sample_app}/macos/Runner/Configs/Warnings.xcconfig (100%) rename {stream_chat_v1 => sample_app}/macos/Runner/DebugProfile.entitlements (100%) rename {stream_chat_v1 => sample_app}/macos/Runner/GoogleService-Info.plist (100%) rename {stream_chat_v1 => sample_app}/macos/Runner/Info.plist (100%) rename {stream_chat_v1 => sample_app}/macos/Runner/MainFlutterWindow.swift (100%) rename {stream_chat_v1 => sample_app}/macos/Runner/Release.entitlements (100%) rename {stream_chat_v1 => sample_app}/macos/Runner/RunnerDebug.entitlements (100%) rename {stream_chat_v1 => sample_app}/macos/firebase_app_id_file.json (100%) rename {stream_chat_v1 => sample_app}/pubspec.yaml (78%) rename {stream_chat_v1 => sample_app}/web/favicon.png (100%) rename {stream_chat_v1 => sample_app}/web/icons/Icon-192.png (100%) rename {stream_chat_v1 => sample_app}/web/icons/Icon-512.png (100%) rename {stream_chat_v1 => sample_app}/web/icons/Icon-maskable-192.png (100%) rename {stream_chat_v1 => sample_app}/web/icons/Icon-maskable-512.png (100%) rename {stream_chat_v1 => sample_app}/web/index.html (100%) rename {stream_chat_v1 => sample_app}/web/manifest.json (100%) rename {stream_chat_v1 => sample_app}/web/sql-wasm.js (100%) rename {stream_chat_v1 => sample_app}/web/sql-wasm.wasm (100%) delete mode 100644 stream_chat_v1/android/app/google-services.json delete mode 100644 stream_chat_v1/ios/Flutter/.last_build_id delete mode 100644 stream_chat_v1/pubspec_overrides.yaml diff --git a/.gitignore b/.gitignore index 5054df6c2b..8b623cd5cf 100644 --- a/.gitignore +++ b/.gitignore @@ -89,6 +89,7 @@ Podfile.lock *.js_ *.js.deps *.js.map +*.wasm **/lcov.info # Other ignored files @@ -115,4 +116,6 @@ gradle-wrapper.jar # Exceptions to the above rules !/pubspec.lock !**/example/web/sql-wasm.js -!**/example/web/sql-wasm.wasm \ No newline at end of file +!**/example/web/sql-wasm.wasm +!/sample_app/web/sql-wasm.js +!/sample_app/web/sql-wasm.wasm \ No newline at end of file diff --git a/melos.yaml b/melos.yaml index 9c2570cec2..61be314ba6 100644 --- a/melos.yaml +++ b/melos.yaml @@ -2,7 +2,17 @@ name: stream_chat_flutter repository: https://github.com/GetStream/stream-chat-flutter packages: - - packages/** + - sample_app + - packages/* + - packages/*/example + +categories: + sample_app: + - sample_app + packages: + - packages/* + examples: + - packages/*/example command: bootstrap: diff --git a/stream_chat_v1/.gitignore b/sample_app/.gitignore similarity index 100% rename from stream_chat_v1/.gitignore rename to sample_app/.gitignore diff --git a/stream_chat_v1/.metadata b/sample_app/.metadata similarity index 100% rename from stream_chat_v1/.metadata rename to sample_app/.metadata diff --git a/stream_chat_v1/README.md b/sample_app/README.md similarity index 100% rename from stream_chat_v1/README.md rename to sample_app/README.md diff --git a/stream_chat_v1/analysis_options.yaml b/sample_app/analysis_options.yaml similarity index 100% rename from stream_chat_v1/analysis_options.yaml rename to sample_app/analysis_options.yaml diff --git a/stream_chat_v1/android/.gitignore b/sample_app/android/.gitignore similarity index 100% rename from stream_chat_v1/android/.gitignore rename to sample_app/android/.gitignore diff --git a/stream_chat_v1/android/app/build.gradle b/sample_app/android/app/build.gradle similarity index 100% rename from stream_chat_v1/android/app/build.gradle rename to sample_app/android/app/build.gradle diff --git a/stream_chat_v1/android/app/debug.keystore b/sample_app/android/app/debug.keystore similarity index 100% rename from stream_chat_v1/android/app/debug.keystore rename to sample_app/android/app/debug.keystore diff --git a/stream_chat_v1/android/app/src/debug/AndroidManifest.xml b/sample_app/android/app/src/debug/AndroidManifest.xml similarity index 100% rename from stream_chat_v1/android/app/src/debug/AndroidManifest.xml rename to sample_app/android/app/src/debug/AndroidManifest.xml diff --git a/stream_chat_v1/android/app/src/main/AndroidManifest.xml b/sample_app/android/app/src/main/AndroidManifest.xml similarity index 100% rename from stream_chat_v1/android/app/src/main/AndroidManifest.xml rename to sample_app/android/app/src/main/AndroidManifest.xml diff --git a/stream_chat_v1/android/app/src/main/kotlin/com/example/example/MainActivity.kt b/sample_app/android/app/src/main/kotlin/com/example/example/MainActivity.kt similarity index 100% rename from stream_chat_v1/android/app/src/main/kotlin/com/example/example/MainActivity.kt rename to sample_app/android/app/src/main/kotlin/com/example/example/MainActivity.kt diff --git a/stream_chat_v1/android/app/src/main/res/drawable-anydpi-v24/ic_notification.xml b/sample_app/android/app/src/main/res/drawable-anydpi-v24/ic_notification.xml similarity index 100% rename from stream_chat_v1/android/app/src/main/res/drawable-anydpi-v24/ic_notification.xml rename to sample_app/android/app/src/main/res/drawable-anydpi-v24/ic_notification.xml diff --git a/stream_chat_v1/android/app/src/main/res/drawable-anydpi-v24/ic_notification_in_app.xml b/sample_app/android/app/src/main/res/drawable-anydpi-v24/ic_notification_in_app.xml similarity index 100% rename from stream_chat_v1/android/app/src/main/res/drawable-anydpi-v24/ic_notification_in_app.xml rename to sample_app/android/app/src/main/res/drawable-anydpi-v24/ic_notification_in_app.xml diff --git a/stream_chat_v1/android/app/src/main/res/drawable-hdpi/ic_launcher_background.png b/sample_app/android/app/src/main/res/drawable-hdpi/ic_launcher_background.png similarity index 100% rename from stream_chat_v1/android/app/src/main/res/drawable-hdpi/ic_launcher_background.png rename to sample_app/android/app/src/main/res/drawable-hdpi/ic_launcher_background.png diff --git a/stream_chat_v1/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png b/sample_app/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png similarity index 100% rename from stream_chat_v1/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png rename to sample_app/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png diff --git a/stream_chat_v1/android/app/src/main/res/drawable-hdpi/ic_notification.png b/sample_app/android/app/src/main/res/drawable-hdpi/ic_notification.png similarity index 100% rename from stream_chat_v1/android/app/src/main/res/drawable-hdpi/ic_notification.png rename to sample_app/android/app/src/main/res/drawable-hdpi/ic_notification.png diff --git a/stream_chat_v1/android/app/src/main/res/drawable-hdpi/ic_notification_in_app.png b/sample_app/android/app/src/main/res/drawable-hdpi/ic_notification_in_app.png similarity index 100% rename from stream_chat_v1/android/app/src/main/res/drawable-hdpi/ic_notification_in_app.png rename to sample_app/android/app/src/main/res/drawable-hdpi/ic_notification_in_app.png diff --git a/stream_chat_v1/android/app/src/main/res/drawable-mdpi/ic_launcher_background.png b/sample_app/android/app/src/main/res/drawable-mdpi/ic_launcher_background.png similarity index 100% rename from stream_chat_v1/android/app/src/main/res/drawable-mdpi/ic_launcher_background.png rename to sample_app/android/app/src/main/res/drawable-mdpi/ic_launcher_background.png diff --git a/stream_chat_v1/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png b/sample_app/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png similarity index 100% rename from stream_chat_v1/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png rename to sample_app/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png diff --git a/stream_chat_v1/android/app/src/main/res/drawable-mdpi/ic_notification.png b/sample_app/android/app/src/main/res/drawable-mdpi/ic_notification.png similarity index 100% rename from stream_chat_v1/android/app/src/main/res/drawable-mdpi/ic_notification.png rename to sample_app/android/app/src/main/res/drawable-mdpi/ic_notification.png diff --git a/stream_chat_v1/android/app/src/main/res/drawable-mdpi/ic_notification_in_app.png b/sample_app/android/app/src/main/res/drawable-mdpi/ic_notification_in_app.png similarity index 100% rename from stream_chat_v1/android/app/src/main/res/drawable-mdpi/ic_notification_in_app.png rename to sample_app/android/app/src/main/res/drawable-mdpi/ic_notification_in_app.png diff --git a/stream_chat_v1/android/app/src/main/res/drawable-v21/launch_background.xml b/sample_app/android/app/src/main/res/drawable-v21/launch_background.xml similarity index 100% rename from stream_chat_v1/android/app/src/main/res/drawable-v21/launch_background.xml rename to sample_app/android/app/src/main/res/drawable-v21/launch_background.xml diff --git a/stream_chat_v1/android/app/src/main/res/drawable-xhdpi/ic_launcher_background.png b/sample_app/android/app/src/main/res/drawable-xhdpi/ic_launcher_background.png similarity index 100% rename from stream_chat_v1/android/app/src/main/res/drawable-xhdpi/ic_launcher_background.png rename to sample_app/android/app/src/main/res/drawable-xhdpi/ic_launcher_background.png diff --git a/stream_chat_v1/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png b/sample_app/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png similarity index 100% rename from stream_chat_v1/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png rename to sample_app/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png diff --git a/stream_chat_v1/android/app/src/main/res/drawable-xhdpi/ic_notification.png b/sample_app/android/app/src/main/res/drawable-xhdpi/ic_notification.png similarity index 100% rename from stream_chat_v1/android/app/src/main/res/drawable-xhdpi/ic_notification.png rename to sample_app/android/app/src/main/res/drawable-xhdpi/ic_notification.png diff --git a/stream_chat_v1/android/app/src/main/res/drawable-xhdpi/ic_notification_in_app.png b/sample_app/android/app/src/main/res/drawable-xhdpi/ic_notification_in_app.png similarity index 100% rename from stream_chat_v1/android/app/src/main/res/drawable-xhdpi/ic_notification_in_app.png rename to sample_app/android/app/src/main/res/drawable-xhdpi/ic_notification_in_app.png diff --git a/stream_chat_v1/android/app/src/main/res/drawable-xxhdpi/ic_launcher_background.png b/sample_app/android/app/src/main/res/drawable-xxhdpi/ic_launcher_background.png similarity index 100% rename from stream_chat_v1/android/app/src/main/res/drawable-xxhdpi/ic_launcher_background.png rename to sample_app/android/app/src/main/res/drawable-xxhdpi/ic_launcher_background.png diff --git a/stream_chat_v1/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png b/sample_app/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png similarity index 100% rename from stream_chat_v1/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png rename to sample_app/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png diff --git a/stream_chat_v1/android/app/src/main/res/drawable-xxhdpi/ic_notification.png b/sample_app/android/app/src/main/res/drawable-xxhdpi/ic_notification.png similarity index 100% rename from stream_chat_v1/android/app/src/main/res/drawable-xxhdpi/ic_notification.png rename to sample_app/android/app/src/main/res/drawable-xxhdpi/ic_notification.png diff --git a/stream_chat_v1/android/app/src/main/res/drawable-xxhdpi/ic_notification_in_app.png b/sample_app/android/app/src/main/res/drawable-xxhdpi/ic_notification_in_app.png similarity index 100% rename from stream_chat_v1/android/app/src/main/res/drawable-xxhdpi/ic_notification_in_app.png rename to sample_app/android/app/src/main/res/drawable-xxhdpi/ic_notification_in_app.png diff --git a/stream_chat_v1/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_background.png b/sample_app/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_background.png similarity index 100% rename from stream_chat_v1/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_background.png rename to sample_app/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_background.png diff --git a/stream_chat_v1/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png b/sample_app/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png similarity index 100% rename from stream_chat_v1/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png rename to sample_app/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png diff --git a/stream_chat_v1/android/app/src/main/res/drawable/launch_background.xml b/sample_app/android/app/src/main/res/drawable/launch_background.xml similarity index 100% rename from stream_chat_v1/android/app/src/main/res/drawable/launch_background.xml rename to sample_app/android/app/src/main/res/drawable/launch_background.xml diff --git a/stream_chat_v1/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/sample_app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml similarity index 100% rename from stream_chat_v1/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml rename to sample_app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml diff --git a/stream_chat_v1/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/sample_app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png similarity index 100% rename from stream_chat_v1/android/app/src/main/res/mipmap-hdpi/ic_launcher.png rename to sample_app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png diff --git a/stream_chat_v1/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/sample_app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png similarity index 100% rename from stream_chat_v1/android/app/src/main/res/mipmap-mdpi/ic_launcher.png rename to sample_app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png diff --git a/stream_chat_v1/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/sample_app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png similarity index 100% rename from stream_chat_v1/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png rename to sample_app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png diff --git a/stream_chat_v1/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/sample_app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png similarity index 100% rename from stream_chat_v1/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png rename to sample_app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png diff --git a/stream_chat_v1/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/sample_app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png similarity index 100% rename from stream_chat_v1/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png rename to sample_app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png diff --git a/stream_chat_v1/android/app/src/main/res/values-night/styles.xml b/sample_app/android/app/src/main/res/values-night/styles.xml similarity index 100% rename from stream_chat_v1/android/app/src/main/res/values-night/styles.xml rename to sample_app/android/app/src/main/res/values-night/styles.xml diff --git a/stream_chat_v1/android/app/src/main/res/values/styles.xml b/sample_app/android/app/src/main/res/values/styles.xml similarity index 100% rename from stream_chat_v1/android/app/src/main/res/values/styles.xml rename to sample_app/android/app/src/main/res/values/styles.xml diff --git a/stream_chat_v1/android/app/src/profile/AndroidManifest.xml b/sample_app/android/app/src/profile/AndroidManifest.xml similarity index 100% rename from stream_chat_v1/android/app/src/profile/AndroidManifest.xml rename to sample_app/android/app/src/profile/AndroidManifest.xml diff --git a/stream_chat_v1/android/build.gradle b/sample_app/android/build.gradle similarity index 100% rename from stream_chat_v1/android/build.gradle rename to sample_app/android/build.gradle diff --git a/stream_chat_v1/android/gradle.properties b/sample_app/android/gradle.properties similarity index 100% rename from stream_chat_v1/android/gradle.properties rename to sample_app/android/gradle.properties diff --git a/stream_chat_v1/android/gradle/wrapper/gradle-wrapper.properties b/sample_app/android/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from stream_chat_v1/android/gradle/wrapper/gradle-wrapper.properties rename to sample_app/android/gradle/wrapper/gradle-wrapper.properties diff --git a/stream_chat_v1/android/settings.gradle b/sample_app/android/settings.gradle similarity index 100% rename from stream_chat_v1/android/settings.gradle rename to sample_app/android/settings.gradle diff --git a/stream_chat_v1/android/settings_aar.gradle b/sample_app/android/settings_aar.gradle similarity index 100% rename from stream_chat_v1/android/settings_aar.gradle rename to sample_app/android/settings_aar.gradle diff --git a/stream_chat_v1/assets/floating_boat.json b/sample_app/assets/floating_boat.json similarity index 100% rename from stream_chat_v1/assets/floating_boat.json rename to sample_app/assets/floating_boat.json diff --git a/stream_chat_v1/assets/ic_launcher.png b/sample_app/assets/ic_launcher.png similarity index 100% rename from stream_chat_v1/assets/ic_launcher.png rename to sample_app/assets/ic_launcher.png diff --git a/stream_chat_v1/assets/ic_launcher_background.png b/sample_app/assets/ic_launcher_background.png similarity index 100% rename from stream_chat_v1/assets/ic_launcher_background.png rename to sample_app/assets/ic_launcher_background.png diff --git a/stream_chat_v1/assets/ic_launcher_foreground.png b/sample_app/assets/ic_launcher_foreground.png similarity index 100% rename from stream_chat_v1/assets/ic_launcher_foreground.png rename to sample_app/assets/ic_launcher_foreground.png diff --git a/stream_chat_v1/assets/icon_arrow_right.svg b/sample_app/assets/icon_arrow_right.svg similarity index 100% rename from stream_chat_v1/assets/icon_arrow_right.svg rename to sample_app/assets/icon_arrow_right.svg diff --git a/stream_chat_v1/assets/logo.svg b/sample_app/assets/logo.svg similarity index 100% rename from stream_chat_v1/assets/logo.svg rename to sample_app/assets/logo.svg diff --git a/stream_chat_v1/ios/.gitignore b/sample_app/ios/.gitignore similarity index 100% rename from stream_chat_v1/ios/.gitignore rename to sample_app/ios/.gitignore diff --git a/stream_chat_v1/ios/.ruby-version b/sample_app/ios/.ruby-version similarity index 100% rename from stream_chat_v1/ios/.ruby-version rename to sample_app/ios/.ruby-version diff --git a/stream_chat_v1/ios/Flutter/AppFrameworkInfo.plist b/sample_app/ios/Flutter/AppFrameworkInfo.plist similarity index 100% rename from stream_chat_v1/ios/Flutter/AppFrameworkInfo.plist rename to sample_app/ios/Flutter/AppFrameworkInfo.plist diff --git a/stream_chat_v1/ios/Flutter/Debug.xcconfig b/sample_app/ios/Flutter/Debug.xcconfig similarity index 100% rename from stream_chat_v1/ios/Flutter/Debug.xcconfig rename to sample_app/ios/Flutter/Debug.xcconfig diff --git a/stream_chat_v1/ios/Flutter/Release.xcconfig b/sample_app/ios/Flutter/Release.xcconfig similarity index 100% rename from stream_chat_v1/ios/Flutter/Release.xcconfig rename to sample_app/ios/Flutter/Release.xcconfig diff --git a/stream_chat_v1/ios/Gemfile b/sample_app/ios/Gemfile similarity index 100% rename from stream_chat_v1/ios/Gemfile rename to sample_app/ios/Gemfile diff --git a/stream_chat_v1/ios/Gemfile.lock b/sample_app/ios/Gemfile.lock similarity index 100% rename from stream_chat_v1/ios/Gemfile.lock rename to sample_app/ios/Gemfile.lock diff --git a/sample_app/ios/Podfile b/sample_app/ios/Podfile new file mode 100644 index 0000000000..d97f17e223 --- /dev/null +++ b/sample_app/ios/Podfile @@ -0,0 +1,44 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '12.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj b/sample_app/ios/Runner.xcodeproj/project.pbxproj similarity index 100% rename from stream_chat_v1/ios/Runner.xcodeproj/project.pbxproj rename to sample_app/ios/Runner.xcodeproj/project.pbxproj diff --git a/stream_chat_v1/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/sample_app/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from stream_chat_v1/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to sample_app/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/stream_chat_v1/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/sample_app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 100% rename from stream_chat_v1/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to sample_app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/stream_chat_v1/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/sample_app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings similarity index 100% rename from stream_chat_v1/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings rename to sample_app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings diff --git a/stream_chat_v1/ios/Runner.xcodeproj/xcshareddata/xcschemes/Notifications.xcscheme b/sample_app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Notifications.xcscheme similarity index 100% rename from stream_chat_v1/ios/Runner.xcodeproj/xcshareddata/xcschemes/Notifications.xcscheme rename to sample_app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Notifications.xcscheme diff --git a/stream_chat_v1/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/sample_app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme similarity index 100% rename from stream_chat_v1/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme rename to sample_app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme diff --git a/stream_chat_v1/ios/Runner.xcworkspace/contents.xcworkspacedata b/sample_app/ios/Runner.xcworkspace/contents.xcworkspacedata similarity index 100% rename from stream_chat_v1/ios/Runner.xcworkspace/contents.xcworkspacedata rename to sample_app/ios/Runner.xcworkspace/contents.xcworkspacedata diff --git a/stream_chat_v1/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/sample_app/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 100% rename from stream_chat_v1/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to sample_app/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/stream_chat_v1/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/sample_app/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings similarity index 100% rename from stream_chat_v1/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings rename to sample_app/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings diff --git a/stream_chat_v1/ios/Runner/AppDelegate.swift b/sample_app/ios/Runner/AppDelegate.swift similarity index 100% rename from stream_chat_v1/ios/Runner/AppDelegate.swift rename to sample_app/ios/Runner/AppDelegate.swift diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json rename to sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png similarity index 100% rename from stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png rename to sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png similarity index 100% rename from stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png rename to sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png similarity index 100% rename from stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png rename to sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png similarity index 100% rename from stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png rename to sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png similarity index 100% rename from stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png rename to sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png similarity index 100% rename from stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png rename to sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png similarity index 100% rename from stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png rename to sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png similarity index 100% rename from stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png rename to sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png similarity index 100% rename from stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png rename to sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png similarity index 100% rename from stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png rename to sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png b/sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png similarity index 100% rename from stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png rename to sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png b/sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png similarity index 100% rename from stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png rename to sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png b/sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png similarity index 100% rename from stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png rename to sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png b/sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png similarity index 100% rename from stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png rename to sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png similarity index 100% rename from stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png rename to sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png similarity index 100% rename from stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png rename to sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png b/sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png similarity index 100% rename from stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png rename to sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png b/sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png similarity index 100% rename from stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png rename to sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png similarity index 100% rename from stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png rename to sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png similarity index 100% rename from stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png rename to sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png similarity index 100% rename from stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png rename to sample_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json b/sample_app/ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json similarity index 100% rename from stream_chat_v1/ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json rename to sample_app/ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png b/sample_app/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png similarity index 100% rename from stream_chat_v1/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png rename to sample_app/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/sample_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json similarity index 100% rename from stream_chat_v1/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json rename to sample_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/sample_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png similarity index 100% rename from stream_chat_v1/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png rename to sample_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/sample_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png similarity index 100% rename from stream_chat_v1/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png rename to sample_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/sample_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png similarity index 100% rename from stream_chat_v1/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png rename to sample_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/sample_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md similarity index 100% rename from stream_chat_v1/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md rename to sample_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md diff --git a/stream_chat_v1/ios/Runner/Base.lproj/LaunchScreen.storyboard b/sample_app/ios/Runner/Base.lproj/LaunchScreen.storyboard similarity index 100% rename from stream_chat_v1/ios/Runner/Base.lproj/LaunchScreen.storyboard rename to sample_app/ios/Runner/Base.lproj/LaunchScreen.storyboard diff --git a/stream_chat_v1/ios/Runner/Base.lproj/Main.storyboard b/sample_app/ios/Runner/Base.lproj/Main.storyboard similarity index 100% rename from stream_chat_v1/ios/Runner/Base.lproj/Main.storyboard rename to sample_app/ios/Runner/Base.lproj/Main.storyboard diff --git a/stream_chat_v1/ios/Runner/GoogleService-Info.plist b/sample_app/ios/Runner/GoogleService-Info.plist similarity index 100% rename from stream_chat_v1/ios/Runner/GoogleService-Info.plist rename to sample_app/ios/Runner/GoogleService-Info.plist diff --git a/stream_chat_v1/ios/Runner/Info.plist b/sample_app/ios/Runner/Info.plist similarity index 100% rename from stream_chat_v1/ios/Runner/Info.plist rename to sample_app/ios/Runner/Info.plist diff --git a/stream_chat_v1/ios/Runner/Runner-Bridging-Header.h b/sample_app/ios/Runner/Runner-Bridging-Header.h similarity index 100% rename from stream_chat_v1/ios/Runner/Runner-Bridging-Header.h rename to sample_app/ios/Runner/Runner-Bridging-Header.h diff --git a/stream_chat_v1/ios/Runner/Runner.entitlements b/sample_app/ios/Runner/Runner.entitlements similarity index 100% rename from stream_chat_v1/ios/Runner/Runner.entitlements rename to sample_app/ios/Runner/Runner.entitlements diff --git a/stream_chat_v1/ios/fastlane/Appfile b/sample_app/ios/fastlane/Appfile similarity index 100% rename from stream_chat_v1/ios/fastlane/Appfile rename to sample_app/ios/fastlane/Appfile diff --git a/stream_chat_v1/ios/fastlane/Fastfile b/sample_app/ios/fastlane/Fastfile similarity index 100% rename from stream_chat_v1/ios/fastlane/Fastfile rename to sample_app/ios/fastlane/Fastfile diff --git a/stream_chat_v1/ios/fastlane/Matchfile b/sample_app/ios/fastlane/Matchfile similarity index 100% rename from stream_chat_v1/ios/fastlane/Matchfile rename to sample_app/ios/fastlane/Matchfile diff --git a/stream_chat_v1/ios/fastlane/Pluginfile b/sample_app/ios/fastlane/Pluginfile similarity index 100% rename from stream_chat_v1/ios/fastlane/Pluginfile rename to sample_app/ios/fastlane/Pluginfile diff --git a/stream_chat_v1/ios/fastlane/README.md b/sample_app/ios/fastlane/README.md similarity index 100% rename from stream_chat_v1/ios/fastlane/README.md rename to sample_app/ios/fastlane/README.md diff --git a/stream_chat_v1/ios/fastlane/beta_gym_export_options.plist b/sample_app/ios/fastlane/beta_gym_export_options.plist similarity index 100% rename from stream_chat_v1/ios/fastlane/beta_gym_export_options.plist rename to sample_app/ios/fastlane/beta_gym_export_options.plist diff --git a/stream_chat_v1/ios/fastlane/report.xml b/sample_app/ios/fastlane/report.xml similarity index 100% rename from stream_chat_v1/ios/fastlane/report.xml rename to sample_app/ios/fastlane/report.xml diff --git a/stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist b/sample_app/ios/fastlane/testflight_gym_export_options.plist similarity index 100% rename from stream_chat_v1/ios/fastlane/testflight_gym_export_options.plist rename to sample_app/ios/fastlane/testflight_gym_export_options.plist diff --git a/stream_chat_v1/ios/firebase_app_id_file.json b/sample_app/ios/firebase_app_id_file.json similarity index 100% rename from stream_chat_v1/ios/firebase_app_id_file.json rename to sample_app/ios/firebase_app_id_file.json diff --git a/stream_chat_v1/lib/app.dart b/sample_app/lib/app.dart similarity index 96% rename from stream_chat_v1/lib/app.dart rename to sample_app/lib/app.dart index b151468bd0..b1df2e2a57 100644 --- a/stream_chat_v1/lib/app.dart +++ b/sample_app/lib/app.dart @@ -1,13 +1,13 @@ import 'dart:async'; -import 'package:example/pages/choose_user_page.dart'; -import 'package:example/pages/splash_screen.dart'; -import 'package:example/routes/app_routes.dart'; -import 'package:example/routes/routes.dart'; -import 'package:example/state/init_data.dart'; -import 'package:example/utils/app_config.dart'; -import 'package:example/utils/local_notification_observer.dart'; -import 'package:example/utils/localizations.dart'; +import 'package:sample_app/pages/choose_user_page.dart'; +import 'package:sample_app/pages/splash_screen.dart'; +import 'package:sample_app/routes/app_routes.dart'; +import 'package:sample_app/routes/routes.dart'; +import 'package:sample_app/state/init_data.dart'; +import 'package:sample_app/utils/app_config.dart'; +import 'package:sample_app/utils/local_notification_observer.dart'; +import 'package:sample_app/utils/localizations.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/foundation.dart'; diff --git a/stream_chat_v1/lib/firebase_options.dart b/sample_app/lib/firebase_options.dart similarity index 100% rename from stream_chat_v1/lib/firebase_options.dart rename to sample_app/lib/firebase_options.dart diff --git a/stream_chat_v1/lib/main.dart b/sample_app/lib/main.dart similarity index 95% rename from stream_chat_v1/lib/main.dart rename to sample_app/lib/main.dart index b50982a9e9..90f51b144f 100644 --- a/stream_chat_v1/lib/main.dart +++ b/sample_app/lib/main.dart @@ -1,7 +1,7 @@ import 'dart:async'; -import 'package:example/app.dart'; -import 'package:example/utils/app_config.dart'; +import 'package:sample_app/app.dart'; +import 'package:sample_app/utils/app_config.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; diff --git a/stream_chat_v1/lib/pages/advanced_options_page.dart b/sample_app/lib/pages/advanced_options_page.dart similarity index 97% rename from stream_chat_v1/lib/pages/advanced_options_page.dart rename to sample_app/lib/pages/advanced_options_page.dart index ab50871f71..6512a8acac 100644 --- a/stream_chat_v1/lib/pages/advanced_options_page.dart +++ b/sample_app/lib/pages/advanced_options_page.dart @@ -1,15 +1,15 @@ -import 'package:example/app.dart'; -import 'package:example/state/init_data.dart'; -import 'package:example/utils/localizations.dart'; -import 'package:example/routes/routes.dart'; -import 'package:example/widgets/stream_version.dart'; +import 'package:sample_app/app.dart'; +import 'package:sample_app/state/init_data.dart'; +import 'package:sample_app/utils/localizations.dart'; +import 'package:sample_app/routes/routes.dart'; +import 'package:sample_app/widgets/stream_version.dart'; import 'package:flutter/material.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:go_router/go_router.dart'; import 'package:provider/provider.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -import 'package:example/pages/choose_user_page.dart'; +import 'package:sample_app/pages/choose_user_page.dart'; class AdvancedOptionsPage extends StatefulWidget { const AdvancedOptionsPage({super.key}); diff --git a/stream_chat_v1/lib/pages/channel_file_display_screen.dart b/sample_app/lib/pages/channel_file_display_screen.dart similarity index 98% rename from stream_chat_v1/lib/pages/channel_file_display_screen.dart rename to sample_app/lib/pages/channel_file_display_screen.dart index 03adab2ff7..24463427f2 100644 --- a/stream_chat_v1/lib/pages/channel_file_display_screen.dart +++ b/sample_app/lib/pages/channel_file_display_screen.dart @@ -1,4 +1,4 @@ -import 'package:example/utils/localizations.dart'; +import 'package:sample_app/utils/localizations.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:video_player/video_player.dart'; diff --git a/stream_chat_v1/lib/pages/channel_list_page.dart b/sample_app/lib/pages/channel_list_page.dart similarity index 95% rename from stream_chat_v1/lib/pages/channel_list_page.dart rename to sample_app/lib/pages/channel_list_page.dart index c4384eca15..570c9dd3df 100644 --- a/stream_chat_v1/lib/pages/channel_list_page.dart +++ b/sample_app/lib/pages/channel_list_page.dart @@ -1,13 +1,13 @@ import 'dart:async'; -import 'package:example/app.dart'; -import 'package:example/pages/thread_list_page.dart'; -import 'package:example/pages/user_mentions_page.dart'; -import 'package:example/routes/routes.dart'; -import 'package:example/state/init_data.dart'; -import 'package:example/utils/app_config.dart'; -import 'package:example/utils/localizations.dart'; -import 'package:example/widgets/channel_list.dart'; +import 'package:sample_app/app.dart'; +import 'package:sample_app/pages/thread_list_page.dart'; +import 'package:sample_app/pages/user_mentions_page.dart'; +import 'package:sample_app/routes/routes.dart'; +import 'package:sample_app/state/init_data.dart'; +import 'package:sample_app/utils/app_config.dart'; +import 'package:sample_app/utils/localizations.dart'; +import 'package:sample_app/widgets/channel_list.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_app_badger/flutter_app_badger.dart'; diff --git a/stream_chat_v1/lib/pages/channel_media_display_screen.dart b/sample_app/lib/pages/channel_media_display_screen.dart similarity index 99% rename from stream_chat_v1/lib/pages/channel_media_display_screen.dart rename to sample_app/lib/pages/channel_media_display_screen.dart index ccb64a63d3..243a37b2a9 100644 --- a/stream_chat_v1/lib/pages/channel_media_display_screen.dart +++ b/sample_app/lib/pages/channel_media_display_screen.dart @@ -1,4 +1,4 @@ -import 'package:example/utils/localizations.dart'; +import 'package:sample_app/utils/localizations.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; diff --git a/stream_chat_v1/lib/pages/channel_page.dart b/sample_app/lib/pages/channel_page.dart similarity index 98% rename from stream_chat_v1/lib/pages/channel_page.dart rename to sample_app/lib/pages/channel_page.dart index 88bbcc8f12..d46466f840 100644 --- a/stream_chat_v1/lib/pages/channel_page.dart +++ b/sample_app/lib/pages/channel_page.dart @@ -1,6 +1,6 @@ import 'package:collection/collection.dart'; -import 'package:example/pages/thread_page.dart'; -import 'package:example/routes/routes.dart'; +import 'package:sample_app/pages/thread_page.dart'; +import 'package:sample_app/routes/routes.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; diff --git a/stream_chat_v1/lib/pages/chat_info_screen.dart b/sample_app/lib/pages/chat_info_screen.dart similarity index 98% rename from stream_chat_v1/lib/pages/chat_info_screen.dart rename to sample_app/lib/pages/chat_info_screen.dart index f63f158d90..326b115072 100644 --- a/stream_chat_v1/lib/pages/chat_info_screen.dart +++ b/sample_app/lib/pages/chat_info_screen.dart @@ -1,10 +1,10 @@ -import 'package:example/pages/channel_file_display_screen.dart'; -import 'package:example/utils/localizations.dart'; +import 'package:sample_app/pages/channel_file_display_screen.dart'; +import 'package:sample_app/utils/localizations.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -import 'package:example/pages/channel_media_display_screen.dart'; -import 'package:example/pages/pinned_messages_screen.dart'; +import 'package:sample_app/pages/channel_media_display_screen.dart'; +import 'package:sample_app/pages/pinned_messages_screen.dart'; /// Detail screen for a 1:1 chat correspondence class ChatInfoScreen extends StatefulWidget { diff --git a/stream_chat_v1/lib/pages/choose_user_page.dart b/sample_app/lib/pages/choose_user_page.dart similarity index 97% rename from stream_chat_v1/lib/pages/choose_user_page.dart rename to sample_app/lib/pages/choose_user_page.dart index 79b0cb7442..52a61ed483 100644 --- a/stream_chat_v1/lib/pages/choose_user_page.dart +++ b/sample_app/lib/pages/choose_user_page.dart @@ -1,7 +1,7 @@ -import 'package:example/state/init_data.dart'; -import 'package:example/utils/app_config.dart'; -import 'package:example/utils/localizations.dart'; -import 'package:example/widgets/stream_version.dart'; +import 'package:sample_app/state/init_data.dart'; +import 'package:sample_app/utils/app_config.dart'; +import 'package:sample_app/utils/localizations.dart'; +import 'package:sample_app/widgets/stream_version.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; diff --git a/stream_chat_v1/lib/pages/group_chat_details_screen.dart b/sample_app/lib/pages/group_chat_details_screen.dart similarity index 99% rename from stream_chat_v1/lib/pages/group_chat_details_screen.dart rename to sample_app/lib/pages/group_chat_details_screen.dart index 1c27665d34..849c7c5ad3 100644 --- a/stream_chat_v1/lib/pages/group_chat_details_screen.dart +++ b/sample_app/lib/pages/group_chat_details_screen.dart @@ -1,5 +1,5 @@ -import 'package:example/state/new_group_chat_state.dart'; -import 'package:example/utils/localizations.dart'; +import 'package:sample_app/state/new_group_chat_state.dart'; +import 'package:sample_app/utils/localizations.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; diff --git a/stream_chat_v1/lib/pages/group_info_screen.dart b/sample_app/lib/pages/group_info_screen.dart similarity index 99% rename from stream_chat_v1/lib/pages/group_info_screen.dart rename to sample_app/lib/pages/group_info_screen.dart index 7b48d51392..47d91ae804 100644 --- a/stream_chat_v1/lib/pages/group_info_screen.dart +++ b/sample_app/lib/pages/group_info_screen.dart @@ -1,9 +1,9 @@ import 'dart:async'; import 'package:collection/collection.dart' show IterableExtension; -import 'package:example/pages/channel_file_display_screen.dart'; -import 'package:example/routes/routes.dart'; -import 'package:example/utils/localizations.dart'; +import 'package:sample_app/pages/channel_file_display_screen.dart'; +import 'package:sample_app/routes/routes.dart'; +import 'package:sample_app/utils/localizations.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; diff --git a/stream_chat_v1/lib/pages/new_chat_screen.dart b/sample_app/lib/pages/new_chat_screen.dart similarity index 99% rename from stream_chat_v1/lib/pages/new_chat_screen.dart rename to sample_app/lib/pages/new_chat_screen.dart index 9611aa9f40..622eca3702 100644 --- a/stream_chat_v1/lib/pages/new_chat_screen.dart +++ b/sample_app/lib/pages/new_chat_screen.dart @@ -1,6 +1,6 @@ import 'dart:async'; -import 'package:example/utils/localizations.dart'; +import 'package:sample_app/utils/localizations.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; diff --git a/stream_chat_v1/lib/pages/new_group_chat_screen.dart b/sample_app/lib/pages/new_group_chat_screen.dart similarity index 99% rename from stream_chat_v1/lib/pages/new_group_chat_screen.dart rename to sample_app/lib/pages/new_group_chat_screen.dart index fbe2a71f63..1a63fdd625 100644 --- a/stream_chat_v1/lib/pages/new_group_chat_screen.dart +++ b/sample_app/lib/pages/new_group_chat_screen.dart @@ -1,7 +1,7 @@ import 'dart:async'; -import 'package:example/state/new_group_chat_state.dart'; -import 'package:example/utils/localizations.dart'; +import 'package:sample_app/state/new_group_chat_state.dart'; +import 'package:sample_app/utils/localizations.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; diff --git a/stream_chat_v1/lib/pages/pinned_messages_screen.dart b/sample_app/lib/pages/pinned_messages_screen.dart similarity index 97% rename from stream_chat_v1/lib/pages/pinned_messages_screen.dart rename to sample_app/lib/pages/pinned_messages_screen.dart index 11a5705c86..8cffa8957f 100644 --- a/stream_chat_v1/lib/pages/pinned_messages_screen.dart +++ b/sample_app/lib/pages/pinned_messages_screen.dart @@ -1,5 +1,5 @@ -import 'package:example/utils/localizations.dart'; -import 'package:example/routes/routes.dart'; +import 'package:sample_app/utils/localizations.dart'; +import 'package:sample_app/routes/routes.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; diff --git a/stream_chat_v1/lib/pages/splash_screen.dart b/sample_app/lib/pages/splash_screen.dart similarity index 100% rename from stream_chat_v1/lib/pages/splash_screen.dart rename to sample_app/lib/pages/splash_screen.dart diff --git a/stream_chat_v1/lib/pages/thread_list_page.dart b/sample_app/lib/pages/thread_list_page.dart similarity index 97% rename from stream_chat_v1/lib/pages/thread_list_page.dart rename to sample_app/lib/pages/thread_list_page.dart index 7c88f950cb..391e800195 100644 --- a/stream_chat_v1/lib/pages/thread_list_page.dart +++ b/sample_app/lib/pages/thread_list_page.dart @@ -1,4 +1,4 @@ -import 'package:example/pages/thread_page.dart'; +import 'package:sample_app/pages/thread_page.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; diff --git a/stream_chat_v1/lib/pages/thread_page.dart b/sample_app/lib/pages/thread_page.dart similarity index 100% rename from stream_chat_v1/lib/pages/thread_page.dart rename to sample_app/lib/pages/thread_page.dart diff --git a/stream_chat_v1/lib/pages/user_mentions_page.dart b/sample_app/lib/pages/user_mentions_page.dart similarity index 96% rename from stream_chat_v1/lib/pages/user_mentions_page.dart rename to sample_app/lib/pages/user_mentions_page.dart index 4ec3b6de73..6d199086df 100644 --- a/stream_chat_v1/lib/pages/user_mentions_page.dart +++ b/sample_app/lib/pages/user_mentions_page.dart @@ -1,5 +1,5 @@ -import 'package:example/utils/localizations.dart'; -import 'package:example/routes/routes.dart'; +import 'package:sample_app/utils/localizations.dart'; +import 'package:sample_app/routes/routes.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; diff --git a/stream_chat_v1/lib/routes/app_routes.dart b/sample_app/lib/routes/app_routes.dart similarity index 85% rename from stream_chat_v1/lib/routes/app_routes.dart rename to sample_app/lib/routes/app_routes.dart index ebcbf429b9..694c7fd608 100644 --- a/stream_chat_v1/lib/routes/app_routes.dart +++ b/sample_app/lib/routes/app_routes.dart @@ -1,15 +1,15 @@ import 'package:collection/collection.dart'; -import 'package:example/pages/advanced_options_page.dart'; -import 'package:example/pages/channel_list_page.dart'; -import 'package:example/pages/channel_page.dart'; -import 'package:example/pages/chat_info_screen.dart'; -import 'package:example/pages/group_chat_details_screen.dart'; -import 'package:example/pages/group_info_screen.dart'; -import 'package:example/pages/new_chat_screen.dart'; -import 'package:example/pages/new_group_chat_screen.dart'; -import 'package:example/pages/thread_page.dart'; -import 'package:example/routes/routes.dart'; -import 'package:example/state/new_group_chat_state.dart'; +import 'package:sample_app/pages/advanced_options_page.dart'; +import 'package:sample_app/pages/channel_list_page.dart'; +import 'package:sample_app/pages/channel_page.dart'; +import 'package:sample_app/pages/chat_info_screen.dart'; +import 'package:sample_app/pages/group_chat_details_screen.dart'; +import 'package:sample_app/pages/group_info_screen.dart'; +import 'package:sample_app/pages/new_chat_screen.dart'; +import 'package:sample_app/pages/new_group_chat_screen.dart'; +import 'package:sample_app/pages/thread_page.dart'; +import 'package:sample_app/routes/routes.dart'; +import 'package:sample_app/state/new_group_chat_state.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; diff --git a/stream_chat_v1/lib/routes/routes.dart b/sample_app/lib/routes/routes.dart similarity index 100% rename from stream_chat_v1/lib/routes/routes.dart rename to sample_app/lib/routes/routes.dart diff --git a/stream_chat_v1/lib/state/init_data.dart b/sample_app/lib/state/init_data.dart similarity index 100% rename from stream_chat_v1/lib/state/init_data.dart rename to sample_app/lib/state/init_data.dart diff --git a/stream_chat_v1/lib/state/new_group_chat_state.dart b/sample_app/lib/state/new_group_chat_state.dart similarity index 100% rename from stream_chat_v1/lib/state/new_group_chat_state.dart rename to sample_app/lib/state/new_group_chat_state.dart diff --git a/stream_chat_v1/lib/utils/app_config.dart b/sample_app/lib/utils/app_config.dart similarity index 100% rename from stream_chat_v1/lib/utils/app_config.dart rename to sample_app/lib/utils/app_config.dart diff --git a/stream_chat_v1/lib/utils/local_notification_observer.dart b/sample_app/lib/utils/local_notification_observer.dart similarity index 93% rename from stream_chat_v1/lib/utils/local_notification_observer.dart rename to sample_app/lib/utils/local_notification_observer.dart index 591a151f99..d6496ee39e 100644 --- a/stream_chat_v1/lib/utils/local_notification_observer.dart +++ b/sample_app/lib/utils/local_notification_observer.dart @@ -1,7 +1,7 @@ import 'dart:async'; -import 'package:example/routes/routes.dart'; -import 'package:example/utils/notifications_service.dart' as pn; +import 'package:sample_app/routes/routes.dart'; +import 'package:sample_app/utils/notifications_service.dart' as pn; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; diff --git a/stream_chat_v1/lib/utils/localizations.dart b/sample_app/lib/utils/localizations.dart similarity index 100% rename from stream_chat_v1/lib/utils/localizations.dart rename to sample_app/lib/utils/localizations.dart diff --git a/stream_chat_v1/lib/utils/notifications_service.dart b/sample_app/lib/utils/notifications_service.dart similarity index 95% rename from stream_chat_v1/lib/utils/notifications_service.dart rename to sample_app/lib/utils/notifications_service.dart index 0e858cc7f4..d472ac7dba 100644 --- a/stream_chat_v1/lib/utils/notifications_service.dart +++ b/sample_app/lib/utils/notifications_service.dart @@ -1,5 +1,5 @@ -import 'package:example/routes/routes.dart'; -import 'package:example/utils/localizations.dart'; +import 'package:sample_app/routes/routes.dart'; +import 'package:sample_app/utils/localizations.dart'; import 'package:flutter/material.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart' hide Message; diff --git a/stream_chat_v1/lib/widgets/channel_list.dart b/sample_app/lib/widgets/channel_list.dart similarity index 98% rename from stream_chat_v1/lib/widgets/channel_list.dart rename to sample_app/lib/widgets/channel_list.dart index e283d2a6e5..62c3a002b1 100644 --- a/stream_chat_v1/lib/widgets/channel_list.dart +++ b/sample_app/lib/widgets/channel_list.dart @@ -1,8 +1,8 @@ import 'dart:async'; -import 'package:example/utils/localizations.dart'; -import 'package:example/routes/routes.dart'; -import 'package:example/widgets/search_text_field.dart'; +import 'package:sample_app/utils/localizations.dart'; +import 'package:sample_app/routes/routes.dart'; +import 'package:sample_app/widgets/search_text_field.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:go_router/go_router.dart'; diff --git a/stream_chat_v1/lib/widgets/chips_input_text_field.dart b/sample_app/lib/widgets/chips_input_text_field.dart similarity index 99% rename from stream_chat_v1/lib/widgets/chips_input_text_field.dart rename to sample_app/lib/widgets/chips_input_text_field.dart index 1e9755886e..2aadea07eb 100644 --- a/stream_chat_v1/lib/widgets/chips_input_text_field.dart +++ b/sample_app/lib/widgets/chips_input_text_field.dart @@ -1,4 +1,4 @@ -import 'package:example/utils/localizations.dart'; +import 'package:sample_app/utils/localizations.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; diff --git a/stream_chat_v1/lib/widgets/search_text_field.dart b/sample_app/lib/widgets/search_text_field.dart similarity index 100% rename from stream_chat_v1/lib/widgets/search_text_field.dart rename to sample_app/lib/widgets/search_text_field.dart diff --git a/stream_chat_v1/lib/widgets/stream_version.dart b/sample_app/lib/widgets/stream_version.dart similarity index 95% rename from stream_chat_v1/lib/widgets/stream_version.dart rename to sample_app/lib/widgets/stream_version.dart index 572cb3d1ba..ae736bb619 100644 --- a/stream_chat_v1/lib/widgets/stream_version.dart +++ b/sample_app/lib/widgets/stream_version.dart @@ -1,4 +1,4 @@ -import 'package:example/utils/localizations.dart'; +import 'package:sample_app/utils/localizations.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:yaml/yaml.dart'; diff --git a/stream_chat_v1/macos/.gitignore b/sample_app/macos/.gitignore similarity index 100% rename from stream_chat_v1/macos/.gitignore rename to sample_app/macos/.gitignore diff --git a/stream_chat_v1/macos/Flutter/Flutter-Debug.xcconfig b/sample_app/macos/Flutter/Flutter-Debug.xcconfig similarity index 100% rename from stream_chat_v1/macos/Flutter/Flutter-Debug.xcconfig rename to sample_app/macos/Flutter/Flutter-Debug.xcconfig diff --git a/stream_chat_v1/macos/Flutter/Flutter-Release.xcconfig b/sample_app/macos/Flutter/Flutter-Release.xcconfig similarity index 100% rename from stream_chat_v1/macos/Flutter/Flutter-Release.xcconfig rename to sample_app/macos/Flutter/Flutter-Release.xcconfig diff --git a/sample_app/macos/Podfile b/sample_app/macos/Podfile new file mode 100644 index 0000000000..c795730db8 --- /dev/null +++ b/sample_app/macos/Podfile @@ -0,0 +1,43 @@ +platform :osx, '10.14' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_macos_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_macos_build_settings(target) + end +end diff --git a/stream_chat_v1/macos/Runner.xcodeproj/project.pbxproj b/sample_app/macos/Runner.xcodeproj/project.pbxproj similarity index 100% rename from stream_chat_v1/macos/Runner.xcodeproj/project.pbxproj rename to sample_app/macos/Runner.xcodeproj/project.pbxproj diff --git a/stream_chat_v1/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/sample_app/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 100% rename from stream_chat_v1/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to sample_app/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/stream_chat_v1/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/sample_app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme similarity index 100% rename from stream_chat_v1/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme rename to sample_app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme diff --git a/stream_chat_v1/macos/Runner.xcworkspace/contents.xcworkspacedata b/sample_app/macos/Runner.xcworkspace/contents.xcworkspacedata similarity index 100% rename from stream_chat_v1/macos/Runner.xcworkspace/contents.xcworkspacedata rename to sample_app/macos/Runner.xcworkspace/contents.xcworkspacedata diff --git a/stream_chat_v1/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/sample_app/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 100% rename from stream_chat_v1/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to sample_app/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/stream_chat_v1/macos/Runner/AppDelegate.swift b/sample_app/macos/Runner/AppDelegate.swift similarity index 100% rename from stream_chat_v1/macos/Runner/AppDelegate.swift rename to sample_app/macos/Runner/AppDelegate.swift diff --git a/stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/sample_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json rename to sample_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/sample_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png similarity index 100% rename from stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png rename to sample_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png diff --git a/stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/sample_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png similarity index 100% rename from stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png rename to sample_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png diff --git a/stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/sample_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png similarity index 100% rename from stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png rename to sample_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png diff --git a/stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/sample_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png similarity index 100% rename from stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png rename to sample_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png diff --git a/stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/sample_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png similarity index 100% rename from stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png rename to sample_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png diff --git a/stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/sample_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png similarity index 100% rename from stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png rename to sample_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png diff --git a/stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/sample_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png similarity index 100% rename from stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png rename to sample_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png diff --git a/stream_chat_v1/macos/Runner/Base.lproj/MainMenu.xib b/sample_app/macos/Runner/Base.lproj/MainMenu.xib similarity index 100% rename from stream_chat_v1/macos/Runner/Base.lproj/MainMenu.xib rename to sample_app/macos/Runner/Base.lproj/MainMenu.xib diff --git a/stream_chat_v1/macos/Runner/Configs/AppInfo.xcconfig b/sample_app/macos/Runner/Configs/AppInfo.xcconfig similarity index 100% rename from stream_chat_v1/macos/Runner/Configs/AppInfo.xcconfig rename to sample_app/macos/Runner/Configs/AppInfo.xcconfig diff --git a/stream_chat_v1/macos/Runner/Configs/Debug.xcconfig b/sample_app/macos/Runner/Configs/Debug.xcconfig similarity index 100% rename from stream_chat_v1/macos/Runner/Configs/Debug.xcconfig rename to sample_app/macos/Runner/Configs/Debug.xcconfig diff --git a/stream_chat_v1/macos/Runner/Configs/Release.xcconfig b/sample_app/macos/Runner/Configs/Release.xcconfig similarity index 100% rename from stream_chat_v1/macos/Runner/Configs/Release.xcconfig rename to sample_app/macos/Runner/Configs/Release.xcconfig diff --git a/stream_chat_v1/macos/Runner/Configs/Warnings.xcconfig b/sample_app/macos/Runner/Configs/Warnings.xcconfig similarity index 100% rename from stream_chat_v1/macos/Runner/Configs/Warnings.xcconfig rename to sample_app/macos/Runner/Configs/Warnings.xcconfig diff --git a/stream_chat_v1/macos/Runner/DebugProfile.entitlements b/sample_app/macos/Runner/DebugProfile.entitlements similarity index 100% rename from stream_chat_v1/macos/Runner/DebugProfile.entitlements rename to sample_app/macos/Runner/DebugProfile.entitlements diff --git a/stream_chat_v1/macos/Runner/GoogleService-Info.plist b/sample_app/macos/Runner/GoogleService-Info.plist similarity index 100% rename from stream_chat_v1/macos/Runner/GoogleService-Info.plist rename to sample_app/macos/Runner/GoogleService-Info.plist diff --git a/stream_chat_v1/macos/Runner/Info.plist b/sample_app/macos/Runner/Info.plist similarity index 100% rename from stream_chat_v1/macos/Runner/Info.plist rename to sample_app/macos/Runner/Info.plist diff --git a/stream_chat_v1/macos/Runner/MainFlutterWindow.swift b/sample_app/macos/Runner/MainFlutterWindow.swift similarity index 100% rename from stream_chat_v1/macos/Runner/MainFlutterWindow.swift rename to sample_app/macos/Runner/MainFlutterWindow.swift diff --git a/stream_chat_v1/macos/Runner/Release.entitlements b/sample_app/macos/Runner/Release.entitlements similarity index 100% rename from stream_chat_v1/macos/Runner/Release.entitlements rename to sample_app/macos/Runner/Release.entitlements diff --git a/stream_chat_v1/macos/Runner/RunnerDebug.entitlements b/sample_app/macos/Runner/RunnerDebug.entitlements similarity index 100% rename from stream_chat_v1/macos/Runner/RunnerDebug.entitlements rename to sample_app/macos/Runner/RunnerDebug.entitlements diff --git a/stream_chat_v1/macos/firebase_app_id_file.json b/sample_app/macos/firebase_app_id_file.json similarity index 100% rename from stream_chat_v1/macos/firebase_app_id_file.json rename to sample_app/macos/firebase_app_id_file.json diff --git a/stream_chat_v1/pubspec.yaml b/sample_app/pubspec.yaml similarity index 78% rename from stream_chat_v1/pubspec.yaml rename to sample_app/pubspec.yaml index cf3d450f55..65c437a6b5 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/sample_app/pubspec.yaml @@ -1,32 +1,32 @@ -name: example +name: sample_app description: A new Flutter project. publish_to: "none" version: 2.2.0 environment: - sdk: '>=3.0.0 <4.0.0' - flutter: ">=3.7.0" + sdk: ^3.5.4 + flutter: ">=3.24.5" dependencies: flutter_app_badger: ^1.5.0 flutter: sdk: flutter - stream_chat_flutter: ^9.1.0 - stream_chat_persistence: ^9.1.0 - stream_chat_localizations: ^9.1.0 + stream_chat_flutter: ^9.3.0 + stream_chat_persistence: ^9.3.0 + stream_chat_localizations: ^9.3.0 flutter_local_notifications: ^18.0.1 - flutter_svg: ^2.0.7 + flutter_svg: ^2.0.10+1 flutter_secure_storage: ^9.2.2 yaml: ^3.1.2 - uuid: ^4.4.2 + uuid: ^4.4.0 streaming_shared_preferences: ^2.0.0 lottie: ^3.1.2 - collection: ^1.17.1 + collection: ^1.17.2 sentry_flutter: ^8.3.0 flutter_slidable: ^3.1.1 go_router: ^14.6.2 provider: ^6.0.5 - video_player: ^2.7.0 + video_player: ^2.8.7 firebase_core: ^3.0.0 firebase_messaging: ^15.0.0 diff --git a/stream_chat_v1/web/favicon.png b/sample_app/web/favicon.png similarity index 100% rename from stream_chat_v1/web/favicon.png rename to sample_app/web/favicon.png diff --git a/stream_chat_v1/web/icons/Icon-192.png b/sample_app/web/icons/Icon-192.png similarity index 100% rename from stream_chat_v1/web/icons/Icon-192.png rename to sample_app/web/icons/Icon-192.png diff --git a/stream_chat_v1/web/icons/Icon-512.png b/sample_app/web/icons/Icon-512.png similarity index 100% rename from stream_chat_v1/web/icons/Icon-512.png rename to sample_app/web/icons/Icon-512.png diff --git a/stream_chat_v1/web/icons/Icon-maskable-192.png b/sample_app/web/icons/Icon-maskable-192.png similarity index 100% rename from stream_chat_v1/web/icons/Icon-maskable-192.png rename to sample_app/web/icons/Icon-maskable-192.png diff --git a/stream_chat_v1/web/icons/Icon-maskable-512.png b/sample_app/web/icons/Icon-maskable-512.png similarity index 100% rename from stream_chat_v1/web/icons/Icon-maskable-512.png rename to sample_app/web/icons/Icon-maskable-512.png diff --git a/stream_chat_v1/web/index.html b/sample_app/web/index.html similarity index 100% rename from stream_chat_v1/web/index.html rename to sample_app/web/index.html diff --git a/stream_chat_v1/web/manifest.json b/sample_app/web/manifest.json similarity index 100% rename from stream_chat_v1/web/manifest.json rename to sample_app/web/manifest.json diff --git a/stream_chat_v1/web/sql-wasm.js b/sample_app/web/sql-wasm.js similarity index 100% rename from stream_chat_v1/web/sql-wasm.js rename to sample_app/web/sql-wasm.js diff --git a/stream_chat_v1/web/sql-wasm.wasm b/sample_app/web/sql-wasm.wasm similarity index 100% rename from stream_chat_v1/web/sql-wasm.wasm rename to sample_app/web/sql-wasm.wasm diff --git a/stream_chat_v1/android/app/google-services.json b/stream_chat_v1/android/app/google-services.json deleted file mode 100644 index 5f06d00047..0000000000 --- a/stream_chat_v1/android/app/google-services.json +++ /dev/null @@ -1,559 +0,0 @@ -{ - "project_info": { - "project_number": "674907137625", - "firebase_url": "https://stream-chat-internal.firebaseio.com", - "project_id": "stream-chat-internal", - "storage_bucket": "stream-chat-internal.appspot.com" - }, - "client": [ - { - "client_info": { - "mobilesdk_app_id": "1:674907137625:android:e55b74fd5747e39ad7f348", - "android_client_info": { - "package_name": "com.example.example" - } - }, - "oauth_client": [ - { - "client_id": "674907137625-2scfo9a5cs074dced5vhm712ej6hhtpm.apps.googleusercontent.com", - "client_type": 1, - "android_info": { - "package_name": "com.example.example", - "certificate_hash": "84e6cb4b0fd5e03f18cc895f25771449543e5b0b" - } - }, - { - "client_id": "674907137625-c4p9d8pffjokeurnhlkkg0n7hlqhohrp.apps.googleusercontent.com", - "client_type": 1, - "android_info": { - "package_name": "com.example.example", - "certificate_hash": "df0590804ff40703acf8b82d07ed2f8a21cd4cc8" - } - }, - { - "client_id": "674907137625-o5iqvv6dtmljtn069b5djv19ad9a7js0.apps.googleusercontent.com", - "client_type": 3 - } - ], - "api_key": [ - { - "current_key": "AIzaSyBArS4RH7lUn3xbD-jhzWl5hVWZhliRgY0" - } - ], - "services": { - "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "674907137625-o5iqvv6dtmljtn069b5djv19ad9a7js0.apps.googleusercontent.com", - "client_type": 3 - }, - { - "client_id": "674907137625-5frv6vlii750pp5250ub20e3te88rhj8.apps.googleusercontent.com", - "client_type": 2, - "ios_info": { - "bundle_id": "io.stream.ionic-angular-starter" - } - } - ] - } - } - }, - { - "client_info": { - "mobilesdk_app_id": "1:674907137625:android:5effa1cd0fef9003d7f348", - "android_client_info": { - "package_name": "com.sampleapp" - } - }, - "oauth_client": [ - { - "client_id": "674907137625-o5iqvv6dtmljtn069b5djv19ad9a7js0.apps.googleusercontent.com", - "client_type": 3 - } - ], - "api_key": [ - { - "current_key": "AIzaSyBArS4RH7lUn3xbD-jhzWl5hVWZhliRgY0" - } - ], - "services": { - "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "674907137625-o5iqvv6dtmljtn069b5djv19ad9a7js0.apps.googleusercontent.com", - "client_type": 3 - }, - { - "client_id": "674907137625-5frv6vlii750pp5250ub20e3te88rhj8.apps.googleusercontent.com", - "client_type": 2, - "ios_info": { - "bundle_id": "io.stream.ionic-angular-starter" - } - } - ] - } - } - }, - { - "client_info": { - "mobilesdk_app_id": "1:674907137625:android:07c76802bbfd5654d7f348", - "android_client_info": { - "package_name": "com.sampleapp.rnpushtest" - } - }, - "oauth_client": [ - { - "client_id": "674907137625-bl2uf0ct9k22u5g5scak89ou9q5631vd.apps.googleusercontent.com", - "client_type": 1, - "android_info": { - "package_name": "com.sampleapp.rnpushtest", - "certificate_hash": "5e8f16062ea3cd2c4a0d547876baa6f38cabf625" - } - }, - { - "client_id": "674907137625-o5iqvv6dtmljtn069b5djv19ad9a7js0.apps.googleusercontent.com", - "client_type": 3 - } - ], - "api_key": [ - { - "current_key": "AIzaSyBArS4RH7lUn3xbD-jhzWl5hVWZhliRgY0" - } - ], - "services": { - "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "674907137625-o5iqvv6dtmljtn069b5djv19ad9a7js0.apps.googleusercontent.com", - "client_type": 3 - }, - { - "client_id": "674907137625-5frv6vlii750pp5250ub20e3te88rhj8.apps.googleusercontent.com", - "client_type": 2, - "ios_info": { - "bundle_id": "io.stream.ionic-angular-starter" - } - } - ] - } - } - }, - { - "client_info": { - "mobilesdk_app_id": "1:674907137625:android:c02fbdcc683148e1d7f348", - "android_client_info": { - "package_name": "io.getstream.chat.android.compose.sample" - } - }, - "oauth_client": [ - { - "client_id": "674907137625-70lqivg5sj9plf8cadf3mb9d4kqpjgg7.apps.googleusercontent.com", - "client_type": 1, - "android_info": { - "package_name": "io.getstream.chat.android.compose.sample", - "certificate_hash": "0df0d0349c0eb717eea90c0b41fc00ab1ab04e16" - } - }, - { - "client_id": "674907137625-plbo43m7pjorusbm76qstde280asrf71.apps.googleusercontent.com", - "client_type": 1, - "android_info": { - "package_name": "io.getstream.chat.android.compose.sample", - "certificate_hash": "c3188b0a93adae431af73d407565f38f284cbb4e" - } - }, - { - "client_id": "674907137625-o5iqvv6dtmljtn069b5djv19ad9a7js0.apps.googleusercontent.com", - "client_type": 3 - } - ], - "api_key": [ - { - "current_key": "AIzaSyBArS4RH7lUn3xbD-jhzWl5hVWZhliRgY0" - } - ], - "services": { - "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "674907137625-o5iqvv6dtmljtn069b5djv19ad9a7js0.apps.googleusercontent.com", - "client_type": 3 - }, - { - "client_id": "674907137625-5frv6vlii750pp5250ub20e3te88rhj8.apps.googleusercontent.com", - "client_type": 2, - "ios_info": { - "bundle_id": "io.stream.ionic-angular-starter" - } - } - ] - } - } - }, - { - "client_info": { - "mobilesdk_app_id": "1:674907137625:android:e96a572655e6c0e8d7f348", - "android_client_info": { - "package_name": "io.getstream.chat.android.compose.sample.debug" - } - }, - "oauth_client": [ - { - "client_id": "674907137625-ioqo27dsi1u5mg7uc9ubgpe0olma47hg.apps.googleusercontent.com", - "client_type": 1, - "android_info": { - "package_name": "io.getstream.chat.android.compose.sample.debug", - "certificate_hash": "c3188b0a93adae431af73d407565f38f284cbb4e" - } - }, - { - "client_id": "674907137625-o5iqvv6dtmljtn069b5djv19ad9a7js0.apps.googleusercontent.com", - "client_type": 3 - } - ], - "api_key": [ - { - "current_key": "AIzaSyBArS4RH7lUn3xbD-jhzWl5hVWZhliRgY0" - } - ], - "services": { - "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "674907137625-o5iqvv6dtmljtn069b5djv19ad9a7js0.apps.googleusercontent.com", - "client_type": 3 - }, - { - "client_id": "674907137625-5frv6vlii750pp5250ub20e3te88rhj8.apps.googleusercontent.com", - "client_type": 2, - "ios_info": { - "bundle_id": "io.stream.ionic-angular-starter" - } - } - ] - } - } - }, - { - "client_info": { - "mobilesdk_app_id": "1:674907137625:android:c41e48c4c799aee8d7f348", - "android_client_info": { - "package_name": "io.getstream.chat.example" - } - }, - "oauth_client": [ - { - "client_id": "674907137625-o5iqvv6dtmljtn069b5djv19ad9a7js0.apps.googleusercontent.com", - "client_type": 3 - } - ], - "api_key": [ - { - "current_key": "AIzaSyBArS4RH7lUn3xbD-jhzWl5hVWZhliRgY0" - } - ], - "services": { - "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "674907137625-o5iqvv6dtmljtn069b5djv19ad9a7js0.apps.googleusercontent.com", - "client_type": 3 - }, - { - "client_id": "674907137625-5frv6vlii750pp5250ub20e3te88rhj8.apps.googleusercontent.com", - "client_type": 2, - "ios_info": { - "bundle_id": "io.stream.ionic-angular-starter" - } - } - ] - } - } - }, - { - "client_info": { - "mobilesdk_app_id": "1:674907137625:android:c36d6f4ab7491192d7f348", - "android_client_info": { - "package_name": "io.getstream.chat.sample" - } - }, - "oauth_client": [ - { - "client_id": "674907137625-o5iqvv6dtmljtn069b5djv19ad9a7js0.apps.googleusercontent.com", - "client_type": 3 - } - ], - "api_key": [ - { - "current_key": "AIzaSyBArS4RH7lUn3xbD-jhzWl5hVWZhliRgY0" - } - ], - "services": { - "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "674907137625-o5iqvv6dtmljtn069b5djv19ad9a7js0.apps.googleusercontent.com", - "client_type": 3 - }, - { - "client_id": "674907137625-5frv6vlii750pp5250ub20e3te88rhj8.apps.googleusercontent.com", - "client_type": 2, - "ios_info": { - "bundle_id": "io.stream.ionic-angular-starter" - } - } - ] - } - } - }, - { - "client_info": { - "mobilesdk_app_id": "1:674907137625:android:d91b4d966e372431d7f348", - "android_client_info": { - "package_name": "io.getstream.chat.sample.debug" - } - }, - "oauth_client": [ - { - "client_id": "674907137625-o5iqvv6dtmljtn069b5djv19ad9a7js0.apps.googleusercontent.com", - "client_type": 3 - } - ], - "api_key": [ - { - "current_key": "AIzaSyBArS4RH7lUn3xbD-jhzWl5hVWZhliRgY0" - } - ], - "services": { - "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "674907137625-o5iqvv6dtmljtn069b5djv19ad9a7js0.apps.googleusercontent.com", - "client_type": 3 - }, - { - "client_id": "674907137625-5frv6vlii750pp5250ub20e3te88rhj8.apps.googleusercontent.com", - "client_type": 2, - "ios_info": { - "bundle_id": "io.stream.ionic-angular-starter" - } - } - ] - } - } - }, - { - "client_info": { - "mobilesdk_app_id": "1:674907137625:android:ff6593c705df1c43d7f348", - "android_client_info": { - "package_name": "io.getstream.chat.sdk" - } - }, - "oauth_client": [ - { - "client_id": "674907137625-khntpmmm3s1756v4jugnhcifgjlqrmd0.apps.googleusercontent.com", - "client_type": 1, - "android_info": { - "package_name": "io.getstream.chat.sdk", - "certificate_hash": "38f7d663a2ed58ae8990d365c41bd82df62185dc" - } - }, - { - "client_id": "674907137625-o5iqvv6dtmljtn069b5djv19ad9a7js0.apps.googleusercontent.com", - "client_type": 3 - } - ], - "api_key": [ - { - "current_key": "AIzaSyBArS4RH7lUn3xbD-jhzWl5hVWZhliRgY0" - } - ], - "services": { - "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "674907137625-o5iqvv6dtmljtn069b5djv19ad9a7js0.apps.googleusercontent.com", - "client_type": 3 - }, - { - "client_id": "674907137625-5frv6vlii750pp5250ub20e3te88rhj8.apps.googleusercontent.com", - "client_type": 2, - "ios_info": { - "bundle_id": "io.stream.ionic-angular-starter" - } - } - ] - } - } - }, - { - "client_info": { - "mobilesdk_app_id": "1:674907137625:android:630333f72f5080b2d7f348", - "android_client_info": { - "package_name": "io.getstream.chat.ui.sample" - } - }, - "oauth_client": [ - { - "client_id": "674907137625-8s27vqo4puao5d025nlsakt78j1pnb45.apps.googleusercontent.com", - "client_type": 1, - "android_info": { - "package_name": "io.getstream.chat.ui.sample", - "certificate_hash": "0df0d0349c0eb717eea90c0b41fc00ab1ab04e16" - } - }, - { - "client_id": "674907137625-j82a5eaohtarvub3agqtossi90fpefhg.apps.googleusercontent.com", - "client_type": 1, - "android_info": { - "package_name": "io.getstream.chat.ui.sample", - "certificate_hash": "c3188b0a93adae431af73d407565f38f284cbb4e" - } - }, - { - "client_id": "674907137625-o5iqvv6dtmljtn069b5djv19ad9a7js0.apps.googleusercontent.com", - "client_type": 3 - } - ], - "api_key": [ - { - "current_key": "AIzaSyBArS4RH7lUn3xbD-jhzWl5hVWZhliRgY0" - } - ], - "services": { - "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "674907137625-o5iqvv6dtmljtn069b5djv19ad9a7js0.apps.googleusercontent.com", - "client_type": 3 - }, - { - "client_id": "674907137625-5frv6vlii750pp5250ub20e3te88rhj8.apps.googleusercontent.com", - "client_type": 2, - "ios_info": { - "bundle_id": "io.stream.ionic-angular-starter" - } - } - ] - } - } - }, - { - "client_info": { - "mobilesdk_app_id": "1:674907137625:android:479d5763241739ded7f348", - "android_client_info": { - "package_name": "io.getstream.chat.ui.sample.debug" - } - }, - "oauth_client": [ - { - "client_id": "674907137625-miq20f82jaeioq126h3sn3sagm5fdbo5.apps.googleusercontent.com", - "client_type": 1, - "android_info": { - "package_name": "io.getstream.chat.ui.sample.debug", - "certificate_hash": "c3188b0a93adae431af73d407565f38f284cbb4e" - } - }, - { - "client_id": "674907137625-o5iqvv6dtmljtn069b5djv19ad9a7js0.apps.googleusercontent.com", - "client_type": 3 - } - ], - "api_key": [ - { - "current_key": "AIzaSyBArS4RH7lUn3xbD-jhzWl5hVWZhliRgY0" - } - ], - "services": { - "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "674907137625-o5iqvv6dtmljtn069b5djv19ad9a7js0.apps.googleusercontent.com", - "client_type": 3 - }, - { - "client_id": "674907137625-5frv6vlii750pp5250ub20e3te88rhj8.apps.googleusercontent.com", - "client_type": 2, - "ios_info": { - "bundle_id": "io.stream.ionic-angular-starter" - } - } - ] - } - } - }, - { - "client_info": { - "mobilesdk_app_id": "1:674907137625:android:47af6d69a27eac48d7f348", - "android_client_info": { - "package_name": "io.getstream.chat.virtualevent" - } - }, - "oauth_client": [ - { - "client_id": "674907137625-o5iqvv6dtmljtn069b5djv19ad9a7js0.apps.googleusercontent.com", - "client_type": 3 - } - ], - "api_key": [ - { - "current_key": "AIzaSyBArS4RH7lUn3xbD-jhzWl5hVWZhliRgY0" - } - ], - "services": { - "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "674907137625-o5iqvv6dtmljtn069b5djv19ad9a7js0.apps.googleusercontent.com", - "client_type": 3 - }, - { - "client_id": "674907137625-5frv6vlii750pp5250ub20e3te88rhj8.apps.googleusercontent.com", - "client_type": 2, - "ios_info": { - "bundle_id": "io.stream.ionic-angular-starter" - } - } - ] - } - } - }, - { - "client_info": { - "mobilesdk_app_id": "1:674907137625:android:e20ff8f1ccbf76e4d7f348", - "android_client_info": { - "package_name": "io.ionic.starter" - } - }, - "oauth_client": [ - { - "client_id": "674907137625-o5iqvv6dtmljtn069b5djv19ad9a7js0.apps.googleusercontent.com", - "client_type": 3 - } - ], - "api_key": [ - { - "current_key": "AIzaSyBArS4RH7lUn3xbD-jhzWl5hVWZhliRgY0" - } - ], - "services": { - "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "674907137625-o5iqvv6dtmljtn069b5djv19ad9a7js0.apps.googleusercontent.com", - "client_type": 3 - }, - { - "client_id": "674907137625-5frv6vlii750pp5250ub20e3te88rhj8.apps.googleusercontent.com", - "client_type": 2, - "ios_info": { - "bundle_id": "io.stream.ionic-angular-starter" - } - } - ] - } - } - } - ], - "configuration_version": "1" -} \ No newline at end of file diff --git a/stream_chat_v1/ios/Flutter/.last_build_id b/stream_chat_v1/ios/Flutter/.last_build_id deleted file mode 100644 index 7f117abae3..0000000000 --- a/stream_chat_v1/ios/Flutter/.last_build_id +++ /dev/null @@ -1 +0,0 @@ -c3757524e06ced55f3d1b83411b9e99c \ No newline at end of file diff --git a/stream_chat_v1/pubspec_overrides.yaml b/stream_chat_v1/pubspec_overrides.yaml deleted file mode 100644 index 24248ecf3a..0000000000 --- a/stream_chat_v1/pubspec_overrides.yaml +++ /dev/null @@ -1,30 +0,0 @@ -dependency_overrides: - stream_chat: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: master - path: packages/stream_chat - stream_chat_flutter_core: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: master - path: packages/stream_chat_flutter_core - stream_chat_flutter: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: master - path: packages/stream_chat_flutter - stream_chat_persistence: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: master - path: packages/stream_chat_persistence - stream_chat_localizations: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: master - path: packages/stream_chat_localizations - - # The last chewie version that supports flutter 3.24.5 - # Issue: https://github.com/fluttercommunity/chewie/issues/888 - chewie: 1.8.5 \ No newline at end of file From 83d8fbf662c6ca6e8e08af00de17cfeec010a8f7 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Wed, 12 Feb 2025 18:45:20 +0530 Subject: [PATCH 167/172] chore: fix lints and update project --- .gitignore | 11 + sample_app/.gitignore | 46 --- sample_app/analysis_options.yaml | 30 +- sample_app/android/.gitignore | 7 - sample_app/android/app/build.gradle | 4 +- sample_app/ios/.gitignore | 32 -- sample_app/ios/Podfile | 3 - .../ios/Runner.xcodeproj/project.pbxproj | 2 + sample_app/lib/app.dart | 27 +- sample_app/lib/main.dart | 7 +- .../lib/pages/advanced_options_page.dart | 26 +- .../pages/channel_file_display_screen.dart | 32 +- sample_app/lib/pages/channel_list_page.dart | 51 +-- .../pages/channel_media_display_screen.dart | 39 +-- sample_app/lib/pages/channel_page.dart | 20 +- sample_app/lib/pages/chat_info_screen.dart | 142 ++++---- sample_app/lib/pages/choose_user_page.dart | 20 +- .../lib/pages/group_chat_details_screen.dart | 57 ++-- sample_app/lib/pages/group_info_screen.dart | 312 +++++++++--------- sample_app/lib/pages/new_chat_screen.dart | 26 +- .../lib/pages/new_group_chat_screen.dart | 34 +- .../lib/pages/pinned_messages_screen.dart | 23 +- sample_app/lib/pages/splash_screen.dart | 16 +- sample_app/lib/pages/thread_list_page.dart | 2 +- sample_app/lib/pages/thread_page.dart | 10 +- sample_app/lib/pages/user_mentions_page.dart | 7 +- sample_app/lib/routes/app_routes.dart | 9 +- sample_app/lib/routes/routes.dart | 4 +- .../utils/local_notification_observer.dart | 8 +- sample_app/lib/utils/localizations.dart | 16 +- .../lib/utils/notifications_service.dart | 8 +- sample_app/lib/widgets/channel_list.dart | 46 ++- .../lib/widgets/chips_input_text_field.dart | 43 +-- sample_app/lib/widgets/search_text_field.dart | 29 +- sample_app/lib/widgets/stream_version.dart | 8 +- sample_app/macos/.gitignore | 6 - sample_app/macos/Podfile | 5 +- .../macos/Runner.xcodeproj/project.pbxproj | 20 +- .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- sample_app/macos/Runner/AppDelegate.swift | 6 +- sample_app/pubspec.yaml | 27 +- 41 files changed, 578 insertions(+), 645 deletions(-) delete mode 100644 sample_app/.gitignore delete mode 100644 sample_app/android/.gitignore delete mode 100644 sample_app/ios/.gitignore delete mode 100644 sample_app/macos/.gitignore diff --git a/.gitignore b/.gitignore index 8b623cd5cf..c24b8110b1 100644 --- a/.gitignore +++ b/.gitignore @@ -82,6 +82,17 @@ Podfile.lock !**/ios/**/default.pbxuser !**/ios/**/default.perspectivev3 +# macOS-related +**/macos/**/Pods/ +**/macos/**/xcuserdata +**/macos/**/Flutter/ephemeral + +# Windows-related +**/windows/flutter/ephemeral/ + +# Linux-related +**/linux/flutter/ephemeral/ + # Generated files *.dart.js *.info.json diff --git a/sample_app/.gitignore b/sample_app/.gitignore deleted file mode 100644 index 564aecd415..0000000000 --- a/sample_app/.gitignore +++ /dev/null @@ -1,46 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.buildlog/ -.history -.svn/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -**/doc/api/ -**/ios/Flutter/.last_build_id -.dart_tool/ -.flutter-plugins -.flutter-plugins-dependencies -.packages -.pub-cache/ -.pub/ -/build/ - -# Web related - -# Symbolication related -app.*.symbols - -# Obfuscation related -app.*.map.json - -# Android Studio will place build artifacts here -/android/app/debug -/android/app/profile -/android/app/release -lib/production_app_config.dart diff --git a/sample_app/analysis_options.yaml b/sample_app/analysis_options.yaml index 61b6c4de17..84b4cef988 100644 --- a/sample_app/analysis_options.yaml +++ b/sample_app/analysis_options.yaml @@ -1,29 +1,7 @@ -# This file configures the analyzer, which statically analyzes Dart code to -# check for errors, warnings, and lints. -# -# The issues identified by the analyzer are surfaced in the UI of Dart-enabled -# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be -# invoked from the command line by running `flutter analyze`. - -# The following line activates a set of recommended lints for Flutter apps, -# packages, and plugins designed to encourage good coding practices. -include: package:flutter_lints/flutter.yaml +include: ../analysis_options.yaml linter: - # The lint rules applied to this project can be customized in the - # section below to disable rules from the `package:flutter_lints/flutter.yaml` - # included above or to enable additional rules. A list of all available lints - # and their documentation is published at - # https://dart-lang.github.io/linter/lints/index.html. - # - # Instead of disabling a lint rule for the entire project in the - # section below, it can also be suppressed for a single line of code - # or a specific dart file by using the `// ignore: name_of_lint` and - # `// ignore_for_file: name_of_lint` syntax on the line or in the file - # producing the lint. rules: - # avoid_print: false # Uncomment to disable the `avoid_print` rule - # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule - -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options + cascade_invocations: false + public_member_api_docs: false + lines_longer_than_80_chars: false \ No newline at end of file diff --git a/sample_app/android/.gitignore b/sample_app/android/.gitignore deleted file mode 100644 index bc2100d8f7..0000000000 --- a/sample_app/android/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -gradle-wrapper.jar -/.gradle -/captures/ -/gradlew -/gradlew.bat -/local.properties -GeneratedPluginRegistrant.java diff --git a/sample_app/android/app/build.gradle b/sample_app/android/app/build.gradle index f82941f8d8..9eedd97ab9 100644 --- a/sample_app/android/app/build.gradle +++ b/sample_app/android/app/build.gradle @@ -26,7 +26,7 @@ if (flutterVersionName == null) { android { namespace "com.example.example" - compileSdkVersion 34 + compileSdkVersion 35 sourceSets { main.java.srcDirs += 'src/main/kotlin' @@ -40,7 +40,7 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.example.example" - minSdkVersion 22 + minSdkVersion 23 targetSdkVersion 34 versionCode flutterVersionCode.toInteger() versionName flutterVersionName diff --git a/sample_app/ios/.gitignore b/sample_app/ios/.gitignore deleted file mode 100644 index e96ef602b8..0000000000 --- a/sample_app/ios/.gitignore +++ /dev/null @@ -1,32 +0,0 @@ -*.mode1v3 -*.mode2v3 -*.moved-aside -*.pbxuser -*.perspectivev3 -**/*sync/ -.sconsign.dblite -.tags* -**/.vagrant/ -**/DerivedData/ -Icon? -**/Pods/ -**/.symlinks/ -profile -xcuserdata -**/.generated/ -Flutter/App.framework -Flutter/Flutter.framework -Flutter/Flutter.podspec -Flutter/Generated.xcconfig -Flutter/app.flx -Flutter/app.zip -Flutter/flutter_assets/ -Flutter/flutter_export_environment.sh -ServiceDefinitions.json -Runner/GeneratedPluginRegistrant.* - -# Exceptions to above rules. -!default.mode1v3 -!default.mode2v3 -!default.pbxuser -!default.perspectivev3 diff --git a/sample_app/ios/Podfile b/sample_app/ios/Podfile index d97f17e223..279576f388 100644 --- a/sample_app/ios/Podfile +++ b/sample_app/ios/Podfile @@ -32,9 +32,6 @@ target 'Runner' do use_modular_headers! flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) - target 'RunnerTests' do - inherit! :search_paths - end end post_install do |installer| diff --git a/sample_app/ios/Runner.xcodeproj/project.pbxproj b/sample_app/ios/Runner.xcodeproj/project.pbxproj index 1dff587d86..be3adbb991 100644 --- a/sample_app/ios/Runner.xcodeproj/project.pbxproj +++ b/sample_app/ios/Runner.xcodeproj/project.pbxproj @@ -276,6 +276,7 @@ "${BUILT_PRODUCTS_DIR}/package_info_plus/package_info_plus.framework", "${BUILT_PRODUCTS_DIR}/path_provider_foundation/path_provider_foundation.framework", "${BUILT_PRODUCTS_DIR}/photo_manager/photo_manager.framework", + "${BUILT_PRODUCTS_DIR}/record_darwin/record_darwin.framework", "${BUILT_PRODUCTS_DIR}/screen_brightness_ios/screen_brightness_ios.framework", "${BUILT_PRODUCTS_DIR}/sentry_flutter/sentry_flutter.framework", "${BUILT_PRODUCTS_DIR}/share_plus/share_plus.framework", @@ -319,6 +320,7 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/package_info_plus.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider_foundation.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/photo_manager.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/record_darwin.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/screen_brightness_ios.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sentry_flutter.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/share_plus.framework", diff --git a/sample_app/lib/app.dart b/sample_app/lib/app.dart index b1df2e2a57..a1c98ad593 100644 --- a/sample_app/lib/app.dart +++ b/sample_app/lib/app.dart @@ -1,13 +1,5 @@ import 'dart:async'; -import 'package:sample_app/pages/choose_user_page.dart'; -import 'package:sample_app/pages/splash_screen.dart'; -import 'package:sample_app/routes/app_routes.dart'; -import 'package:sample_app/routes/routes.dart'; -import 'package:sample_app/state/init_data.dart'; -import 'package:sample_app/utils/app_config.dart'; -import 'package:sample_app/utils/local_notification_observer.dart'; -import 'package:sample_app/utils/localizations.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/foundation.dart'; @@ -16,14 +8,21 @@ import 'package:flutter/scheduler.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:go_router/go_router.dart'; import 'package:provider/provider.dart'; +import 'package:sample_app/firebase_options.dart'; +import 'package:sample_app/pages/choose_user_page.dart'; +import 'package:sample_app/pages/splash_screen.dart'; +import 'package:sample_app/routes/app_routes.dart'; +import 'package:sample_app/routes/routes.dart'; +import 'package:sample_app/state/init_data.dart'; +import 'package:sample_app/utils/app_config.dart'; +import 'package:sample_app/utils/local_notification_observer.dart'; +import 'package:sample_app/utils/localizations.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:stream_chat_localizations/stream_chat_localizations.dart'; import 'package:stream_chat_persistence/stream_chat_persistence.dart'; import 'package:streaming_shared_preferences/streaming_shared_preferences.dart'; -import 'firebase_options.dart'; - /// Constructs callback for background notification handling. /// /// Will be invoked from another Isolate, that's why it's required to @@ -84,7 +83,6 @@ Future _onFirebaseBackgroundMessage(RemoteMessage message) async { final chatPersistentClient = StreamChatPersistenceClient( logLevel: Level.SEVERE, - connectionMode: ConnectionMode.regular, ); void _sampleAppLogHandler(LogRecord record) async { @@ -177,12 +175,11 @@ class _StreamChatSampleAppState extends State final token = await FirebaseMessaging.instance.getToken(); debugPrint('[onTokenInit] #firebase; token: $token'); if (token != null) { - // replace with your push provider name, e.g., 'chat-flutter-firebase' - const pushProviderName = null; + // replace with your push provider, e.g., 'PushProvider.xiaomi' + const pushProvider = PushProvider.firebase; // add Token to Stream - await client.addDevice(token, PushProvider.firebase, - pushProviderName: pushProviderName); + await client.addDevice(token, pushProvider); } } // User logged out diff --git a/sample_app/lib/main.dart b/sample_app/lib/main.dart index 90f51b144f..e1b3079049 100644 --- a/sample_app/lib/main.dart +++ b/sample_app/lib/main.dart @@ -1,14 +1,13 @@ import 'dart:async'; -import 'package:sample_app/app.dart'; -import 'package:sample_app/utils/app_config.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:sample_app/app.dart'; +import 'package:sample_app/firebase_options.dart'; +import 'package:sample_app/utils/app_config.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; -import 'firebase_options.dart'; - Future main() async { /// Captures errors reported by the Flutter framework. FlutterError.onError = (FlutterErrorDetails details) { diff --git a/sample_app/lib/pages/advanced_options_page.dart b/sample_app/lib/pages/advanced_options_page.dart index 6512a8acac..81ab732c02 100644 --- a/sample_app/lib/pages/advanced_options_page.dart +++ b/sample_app/lib/pages/advanced_options_page.dart @@ -1,15 +1,14 @@ -import 'package:sample_app/app.dart'; -import 'package:sample_app/state/init_data.dart'; -import 'package:sample_app/utils/localizations.dart'; -import 'package:sample_app/routes/routes.dart'; -import 'package:sample_app/widgets/stream_version.dart'; import 'package:flutter/material.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:go_router/go_router.dart'; import 'package:provider/provider.dart'; -import 'package:stream_chat_flutter/stream_chat_flutter.dart'; - +import 'package:sample_app/app.dart'; import 'package:sample_app/pages/choose_user_page.dart'; +import 'package:sample_app/routes/routes.dart'; +import 'package:sample_app/state/init_data.dart'; +import 'package:sample_app/utils/localizations.dart'; +import 'package:sample_app/widgets/stream_version.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; class AdvancedOptionsPage extends StatefulWidget { const AdvancedOptionsPage({super.key}); @@ -137,9 +136,8 @@ class _AdvancedOptionsPageState extends State { color: StreamChatTheme.of(context).colorTheme.textHighEmphasis), ), leading: IconButton( - icon: StreamSvgIcon.left( - color: StreamChatTheme.of(context).colorTheme.textHighEmphasis, - ), + icon: const StreamSvgIcon(icon: StreamSvgIcons.left), + color: StreamChatTheme.of(context).colorTheme.textHighEmphasis, onPressed: () { Navigator.pop(context); }, @@ -327,16 +325,16 @@ class _AdvancedOptionsPageState extends State { const Spacer(), ElevatedButton( style: ButtonStyle( - backgroundColor: MaterialStateProperty.all( + backgroundColor: WidgetStateProperty.all( Theme.of(context).brightness == Brightness.light ? StreamChatTheme.of(context) .colorTheme .accentPrimary : Colors.white), - elevation: MaterialStateProperty.all(0), - padding: MaterialStateProperty.all( + elevation: WidgetStateProperty.all(0), + padding: WidgetStateProperty.all( const EdgeInsets.symmetric(vertical: 16)), - shape: MaterialStateProperty.all( + shape: WidgetStateProperty.all( RoundedRectangleBorder( borderRadius: BorderRadius.circular(26), ), diff --git a/sample_app/lib/pages/channel_file_display_screen.dart b/sample_app/lib/pages/channel_file_display_screen.dart index 24463427f2..727dd6bb87 100644 --- a/sample_app/lib/pages/channel_file_display_screen.dart +++ b/sample_app/lib/pages/channel_file_display_screen.dart @@ -1,15 +1,16 @@ -import 'package:sample_app/utils/localizations.dart'; +// ignore_for_file: deprecated_member_use + import 'package:flutter/material.dart'; +import 'package:sample_app/utils/localizations.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:video_player/video_player.dart'; class ChannelFileDisplayScreen extends StatefulWidget { - final StreamMessageThemeData messageTheme; - const ChannelFileDisplayScreen({ - Key? key, + super.key, required this.messageTheme, - }) : super(key: key); + }); + final StreamMessageThemeData messageTheme; @override State createState() => @@ -49,7 +50,7 @@ class _ChannelFileDisplayScreenState extends State { AppLocalizations.of(context).files, style: TextStyle( color: StreamChatTheme.of(context).colorTheme.textHighEmphasis, - fontSize: 16.0, + fontSize: 16, ), ), leading: const StreamBackButton(), @@ -69,26 +70,27 @@ class _ChannelFileDisplayScreenState extends State { child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - StreamSvgIcon.files( - size: 136.0, + StreamSvgIcon( + icon: StreamSvgIcons.files, + size: 136, color: StreamChatTheme.of(context).colorTheme.disabled, ), - const SizedBox(height: 16.0), + const SizedBox(height: 16), Text( AppLocalizations.of(context).noFiles, style: TextStyle( - fontSize: 14.0, + fontSize: 14, color: StreamChatTheme.of(context) .colorTheme .textHighEmphasis, ), ), - const SizedBox(height: 8.0), + const SizedBox(height: 8), Text( AppLocalizations.of(context).filesAppearHere, textAlign: TextAlign.center, style: TextStyle( - fontSize: 14.0, + fontSize: 14, color: StreamChatTheme.of(context) .colorTheme .textHighEmphasis @@ -101,7 +103,7 @@ class _ChannelFileDisplayScreenState extends State { } final media = {}; - for (var item in items) { + for (final item in items) { item.message.attachments .where((e) => e.type == 'file') .forEach((e) { @@ -118,9 +120,9 @@ class _ChannelFileDisplayScreenState extends State { child: ListView.builder( itemBuilder: (context, position) { return Padding( - padding: const EdgeInsets.all(1.0), + padding: const EdgeInsets.all(1), child: Padding( - padding: const EdgeInsets.all(8.0), + padding: const EdgeInsets.all(8), child: StreamFileAttachment( message: media.values.toList()[position], file: media.keys.toList()[position], diff --git a/sample_app/lib/pages/channel_list_page.dart b/sample_app/lib/pages/channel_list_page.dart index 570c9dd3df..358e204bdb 100644 --- a/sample_app/lib/pages/channel_list_page.dart +++ b/sample_app/lib/pages/channel_list_page.dart @@ -1,5 +1,13 @@ +// ignore_for_file: deprecated_member_use + import 'dart:async'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_app_badger/flutter_app_badger.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:go_router/go_router.dart'; +import 'package:provider/provider.dart'; import 'package:sample_app/app.dart'; import 'package:sample_app/pages/thread_list_page.dart'; import 'package:sample_app/pages/user_mentions_page.dart'; @@ -8,19 +16,13 @@ import 'package:sample_app/state/init_data.dart'; import 'package:sample_app/utils/app_config.dart'; import 'package:sample_app/utils/localizations.dart'; import 'package:sample_app/widgets/channel_list.dart'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_app_badger/flutter_app_badger.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; -import 'package:go_router/go_router.dart'; -import 'package:provider/provider.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:streaming_shared_preferences/streaming_shared_preferences.dart'; class ChannelListPage extends StatefulWidget { const ChannelListPage({ - Key? key, - }) : super(key: key); + super.key, + }); @override State createState() => _ChannelListPageState(); @@ -37,7 +39,8 @@ class _ChannelListPageState extends State { icon: Stack( clipBehavior: Clip.none, children: [ - StreamSvgIcon.message( + StreamSvgIcon( + icon: StreamSvgIcons.message, color: _isSelected(0) ? StreamChatTheme.of(context).colorTheme.textHighEmphasis : Colors.grey, @@ -52,7 +55,8 @@ class _ChannelListPageState extends State { label: AppLocalizations.of(context).chats, ), BottomNavigationBarItem( - icon: StreamSvgIcon.mentions( + icon: StreamSvgIcon( + icon: StreamSvgIcons.mentions, color: _isSelected(1) ? StreamChatTheme.of(context).colorTheme.textHighEmphasis : Colors.grey, @@ -63,7 +67,8 @@ class _ChannelListPageState extends State { icon: Stack( clipBehavior: Clip.none, children: [ - Icon(Icons.message_outlined, + Icon( + Icons.message_outlined, color: _isSelected(2) ? StreamChatTheme.of(context).colorTheme.textHighEmphasis : Colors.grey, @@ -154,16 +159,16 @@ class _ChannelListPageState extends State { class LeftDrawer extends StatelessWidget { const LeftDrawer({ - Key? key, + super.key, required this.user, - }) : super(key: key); + }); final User user; @override Widget build(BuildContext context) { return Drawer( - child: Container( + child: ColoredBox( color: StreamChatTheme.of(context).colorTheme.barsBg, child: SafeArea( child: Padding( @@ -174,7 +179,7 @@ class LeftDrawer extends StatelessWidget { children: [ Padding( padding: const EdgeInsets.only( - bottom: 20.0, + bottom: 20, left: 8, ), child: Row( @@ -186,7 +191,7 @@ class LeftDrawer extends StatelessWidget { BoxConstraints.tight(const Size.fromRadius(20)), ), Padding( - padding: const EdgeInsets.only(left: 16.0), + padding: const EdgeInsets.only(left: 16), child: Text( user.name, style: const TextStyle( @@ -199,7 +204,8 @@ class LeftDrawer extends StatelessWidget { ), ), ListTile( - leading: StreamSvgIcon.penWrite( + leading: StreamSvgIcon( + icon: StreamSvgIcons.penWrite, color: StreamChatTheme.of(context) .colorTheme .textHighEmphasis @@ -217,11 +223,12 @@ class LeftDrawer extends StatelessWidget { ), ), ListTile( - leading: StreamSvgIcon.contacts( + leading: StreamSvgIcon( color: StreamChatTheme.of(context) .colorTheme .textHighEmphasis .withOpacity(.5), + icon: StreamSvgIcons.contacts, ), onTap: () { Navigator.of(context).pop(); @@ -256,7 +263,8 @@ class LeftDrawer extends StatelessWidget { router.goNamed(Routes.CHOOSE_USER.name); }, - leading: StreamSvgIcon.user( + leading: StreamSvgIcon( + icon: StreamSvgIcons.user, color: StreamChatTheme.of(context) .colorTheme .textHighEmphasis @@ -269,9 +277,8 @@ class LeftDrawer extends StatelessWidget { ), ), trailing: IconButton( - icon: StreamSvgIcon.iconMoon( - size: 24, - ), + iconSize: 24, + icon: const StreamSvgIcon(icon: StreamSvgIcons.moon), color: StreamChatTheme.of(context) .colorTheme .textLowEmphasis, diff --git a/sample_app/lib/pages/channel_media_display_screen.dart b/sample_app/lib/pages/channel_media_display_screen.dart index 243a37b2a9..d7b7a472d1 100644 --- a/sample_app/lib/pages/channel_media_display_screen.dart +++ b/sample_app/lib/pages/channel_media_display_screen.dart @@ -1,18 +1,18 @@ -import 'package:sample_app/utils/localizations.dart'; +// ignore_for_file: deprecated_member_use + import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; +import 'package:sample_app/routes/routes.dart'; +import 'package:sample_app/utils/localizations.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:video_player/video_player.dart'; -import '../routes/routes.dart'; - class ChannelMediaDisplayScreen extends StatefulWidget { - final StreamMessageThemeData messageTheme; - const ChannelMediaDisplayScreen({ - Key? key, + super.key, required this.messageTheme, - }) : super(key: key); + }); + final StreamMessageThemeData messageTheme; @override State createState() => @@ -52,7 +52,7 @@ class _ChannelMediaDisplayScreenState extends State { AppLocalizations.of(context).photosAndVideos, style: TextStyle( color: StreamChatTheme.of(context).colorTheme.textHighEmphasis, - fontSize: 16.0, + fontSize: 16, ), ), leading: const StreamBackButton(), @@ -69,27 +69,28 @@ class _ChannelMediaDisplayScreenState extends State { child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - StreamSvgIcon.pictures( - size: 136.0, + StreamSvgIcon( + icon: StreamSvgIcons.pictures, + size: 136, color: StreamChatTheme.of(context).colorTheme.disabled, ), - const SizedBox(height: 16.0), + const SizedBox(height: 16), Text( AppLocalizations.of(context).noMedia, style: TextStyle( - fontSize: 14.0, + fontSize: 14, color: StreamChatTheme.of(context) .colorTheme .textHighEmphasis, ), ), - const SizedBox(height: 8.0), + const SizedBox(height: 8), Text( AppLocalizations.of(context) .photosOrVideosWillAppearHere, textAlign: TextAlign.center, style: TextStyle( - fontSize: 14.0, + fontSize: 14, color: StreamChatTheme.of(context) .colorTheme .textHighEmphasis @@ -113,7 +114,8 @@ class _ChannelMediaDisplayScreenState extends State { final cachedController = controllerCache[e.assetUrl]; if (cachedController == null) { - controller = VideoPlayerController.network(e.assetUrl!); + final url = Uri.parse(e.assetUrl!); + controller = VideoPlayerController.networkUrl(url); controller.initialize(); controllerCache[e.assetUrl] = controller; } else { @@ -134,9 +136,9 @@ class _ChannelMediaDisplayScreenState extends State { gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3), itemBuilder: (context, position) { - var channel = StreamChannel.of(context).channel; + final channel = StreamChannel.of(context).channel; return Padding( - padding: const EdgeInsets.all(1.0), + padding: const EdgeInsets.all(1), child: InkWell( onTap: () { Navigator.push( @@ -214,9 +216,8 @@ class _ChannelMediaDisplayScreenState extends State { } class _AssetPackage { + _AssetPackage(this.attachment, this.message, this.videoPlayer); Attachment attachment; Message message; VideoPlayerController? videoPlayer; - - _AssetPackage(this.attachment, this.message, this.videoPlayer); } diff --git a/sample_app/lib/pages/channel_page.dart b/sample_app/lib/pages/channel_page.dart index d46466f840..dc1184f8ea 100644 --- a/sample_app/lib/pages/channel_page.dart +++ b/sample_app/lib/pages/channel_page.dart @@ -1,21 +1,23 @@ +// ignore_for_file: deprecated_member_use + import 'package:collection/collection.dart'; -import 'package:sample_app/pages/thread_page.dart'; -import 'package:sample_app/routes/routes.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; +import 'package:sample_app/pages/thread_page.dart'; +import 'package:sample_app/routes/routes.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; class ChannelPage extends StatefulWidget { - final int? initialScrollIndex; - final double? initialAlignment; - final bool highlightInitialMessage; const ChannelPage({ - Key? key, + super.key, this.initialScrollIndex, this.initialAlignment, this.highlightInitialMessage = false, - }) : super(key: key); + }); + final int? initialScrollIndex; + final double? initialAlignment; + final bool highlightInitialMessage; @override State createState() => _ChannelPageState(); @@ -156,9 +158,7 @@ class _ChannelPageState extends State { StreamMessageInput( focusNode: _focusNode, messageInputController: _messageInputController, - onQuotedMessageCleared: () { - _messageInputController.clearQuotedMessage(); - }, + onQuotedMessageCleared: _messageInputController.clearQuotedMessage, ), ], ), diff --git a/sample_app/lib/pages/chat_info_screen.dart b/sample_app/lib/pages/chat_info_screen.dart index 326b115072..6caacbdfc4 100644 --- a/sample_app/lib/pages/chat_info_screen.dart +++ b/sample_app/lib/pages/chat_info_screen.dart @@ -1,24 +1,26 @@ -import 'package:sample_app/pages/channel_file_display_screen.dart'; -import 'package:sample_app/utils/localizations.dart'; +// ignore_for_file: deprecated_member_use + import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:stream_chat_flutter/stream_chat_flutter.dart'; +import 'package:sample_app/pages/channel_file_display_screen.dart'; import 'package:sample_app/pages/channel_media_display_screen.dart'; import 'package:sample_app/pages/pinned_messages_screen.dart'; +import 'package:sample_app/utils/localizations.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; /// Detail screen for a 1:1 chat correspondence class ChatInfoScreen extends StatefulWidget { + const ChatInfoScreen({ + super.key, + required this.messageTheme, + this.user, + }); + /// User in consideration final User? user; final StreamMessageThemeData messageTheme; - const ChatInfoScreen({ - Key? key, - required this.messageTheme, - this.user, - }) : super(key: key); - @override State createState() => _ChatInfoScreenState(); } @@ -41,12 +43,12 @@ class _ChatInfoScreenState extends State { children: [ _buildUserHeader(), Container( - height: 8.0, + height: 8, color: StreamChatTheme.of(context).colorTheme.disabled, ), _buildOptionListTiles(), Container( - height: 8.0, + height: 8, color: StreamChatTheme.of(context).colorTheme.disabled, ), if (channel.ownCapabilities.contains(PermissionType.deleteChannel)) @@ -63,33 +65,32 @@ class _ChatInfoScreenState extends State { child: Stack( children: [ Column( - crossAxisAlignment: CrossAxisAlignment.center, children: [ Padding( - padding: const EdgeInsets.all(16.0), + padding: const EdgeInsets.all(16), child: StreamUserAvatar( user: widget.user!, constraints: const BoxConstraints.tightFor( - width: 72.0, - height: 72.0, + width: 72, + height: 72, ), - borderRadius: BorderRadius.circular(36.0), + borderRadius: BorderRadius.circular(36), showOnlineStatus: false, ), ), Text( widget.user!.name, style: const TextStyle( - fontSize: 16.0, fontWeight: FontWeight.bold), + fontSize: 16, fontWeight: FontWeight.bold), ), - const SizedBox(height: 7.0), + const SizedBox(height: 7), _buildConnectedTitleState(), - const SizedBox(height: 15.0), + const SizedBox(height: 15), StreamOptionListTile( title: '@${widget.user!.id}', tileColor: StreamChatTheme.of(context).colorTheme.appBg, trailing: Padding( - padding: const EdgeInsets.symmetric(horizontal: 8.0), + padding: const EdgeInsets.symmetric(horizontal: 8), child: Text( widget.user!.name, style: TextStyle( @@ -97,7 +98,7 @@ class _ChatInfoScreenState extends State { .colorTheme .textHighEmphasis .withOpacity(0.5), - fontSize: 16.0), + fontSize: 16), ), ), onTap: () {}, @@ -131,9 +132,10 @@ class _ChatInfoScreenState extends State { title: AppLocalizations.of(context).muteUser, titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( - padding: const EdgeInsets.symmetric(horizontal: 22.0), - child: StreamSvgIcon.mute( - size: 24.0, + padding: const EdgeInsets.symmetric(horizontal: 22), + child: StreamSvgIcon( + icon: StreamSvgIcons.mute, + size: 24, color: StreamChatTheme.of(context) .colorTheme .textHighEmphasis @@ -166,16 +168,18 @@ class _ChatInfoScreenState extends State { tileColor: StreamChatTheme.of(context).colorTheme.appBg, titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( - padding: const EdgeInsets.symmetric(horizontal: 22.0), - child: StreamSvgIcon.pin( - size: 24.0, + padding: const EdgeInsets.symmetric(horizontal: 22), + child: StreamSvgIcon( + icon: StreamSvgIcons.pin, + size: 24, color: StreamChatTheme.of(context) .colorTheme .textHighEmphasis .withOpacity(0.5), ), ), - trailing: StreamSvgIcon.right( + trailing: StreamSvgIcon( + icon: StreamSvgIcons.right, color: StreamChatTheme.of(context).colorTheme.textLowEmphasis, ), onTap: () { @@ -197,16 +201,18 @@ class _ChatInfoScreenState extends State { tileColor: StreamChatTheme.of(context).colorTheme.appBg, titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: StreamSvgIcon.pictures( - size: 36.0, + padding: const EdgeInsets.symmetric(horizontal: 16), + child: StreamSvgIcon( + icon: StreamSvgIcons.pictures, + size: 36, color: StreamChatTheme.of(context) .colorTheme .textHighEmphasis .withOpacity(0.5), ), ), - trailing: StreamSvgIcon.right( + trailing: StreamSvgIcon( + icon: StreamSvgIcons.right, color: StreamChatTheme.of(context).colorTheme.textLowEmphasis, ), onTap: () { @@ -230,16 +236,18 @@ class _ChatInfoScreenState extends State { tileColor: StreamChatTheme.of(context).colorTheme.appBg, titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( - padding: const EdgeInsets.symmetric(horizontal: 18.0), - child: StreamSvgIcon.files( - size: 32.0, + padding: const EdgeInsets.symmetric(horizontal: 18), + child: StreamSvgIcon( + icon: StreamSvgIcons.files, + size: 32, color: StreamChatTheme.of(context) .colorTheme .textHighEmphasis .withOpacity(0.5), ), ), - trailing: StreamSvgIcon.right( + trailing: StreamSvgIcon( + icon: StreamSvgIcons.right, color: StreamChatTheme.of(context).colorTheme.textLowEmphasis, ), onTap: () { @@ -263,16 +271,18 @@ class _ChatInfoScreenState extends State { tileColor: StreamChatTheme.of(context).colorTheme.appBg, titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( - padding: const EdgeInsets.symmetric(horizontal: 22.0), - child: StreamSvgIcon.iconGroup( - size: 24.0, + padding: const EdgeInsets.symmetric(horizontal: 22), + child: StreamSvgIcon( + icon: StreamSvgIcons.group, + size: 24, color: StreamChatTheme.of(context) .colorTheme .textHighEmphasis .withOpacity(0.5), ), ), - trailing: StreamSvgIcon.right( + trailing: StreamSvgIcon( + icon: StreamSvgIcons.right, color: StreamChatTheme.of(context).colorTheme.textLowEmphasis, ), onTap: () { @@ -295,15 +305,14 @@ class _ChatInfoScreenState extends State { color: StreamChatTheme.of(context).colorTheme.accentError, ), leading: Padding( - padding: const EdgeInsets.symmetric(horizontal: 22.0), - child: StreamSvgIcon.delete( + padding: const EdgeInsets.symmetric(horizontal: 22), + child: StreamSvgIcon( + icon: StreamSvgIcons.delete, + size: 24, color: StreamChatTheme.of(context).colorTheme.accentError, - size: 24.0, ), ), - onTap: () { - _showDeleteDialog(); - }, + onTap: _showDeleteDialog, titleColor: StreamChatTheme.of(context).colorTheme.accentError, ); } @@ -316,7 +325,8 @@ class _ChatInfoScreenState extends State { okText: AppLocalizations.of(context).delete.toUpperCase(), question: AppLocalizations.of(context).deleteConversationAreYouSure, cancelText: AppLocalizations.of(context).cancel.toUpperCase(), - icon: StreamSvgIcon.delete( + icon: StreamSvgIcon( + icon: StreamSvgIcons.delete, color: StreamChatTheme.of(context).colorTheme.accentError, ), ); @@ -364,7 +374,7 @@ class _ChatInfoScreenState extends State { type: MaterialType.circle, color: StreamChatTheme.of(context).colorTheme.barsBg, child: Container( - padding: const EdgeInsets.symmetric(horizontal: 8.0), + padding: const EdgeInsets.symmetric(horizontal: 8), constraints: const BoxConstraints.tightFor( width: 24, height: 12, @@ -378,7 +388,7 @@ class _ChatInfoScreenState extends State { alternativeWidget, if (widget.user!.online) const SizedBox( - width: 24.0, + width: 24, ), ], ); @@ -386,11 +396,10 @@ class _ChatInfoScreenState extends State { } class _SharedGroupsScreen extends StatefulWidget { + const _SharedGroupsScreen(this.mainUser, this.otherUser); final User? mainUser; final User? otherUser; - const _SharedGroupsScreen(this.mainUser, this.otherUser); - @override __SharedGroupsScreenState createState() => __SharedGroupsScreenState(); } @@ -409,7 +418,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { AppLocalizations.of(context).sharedGroups, style: TextStyle( color: StreamChatTheme.of(context).colorTheme.textHighEmphasis, - fontSize: 16.0), + fontSize: 16), ), leading: const StreamBackButton(), backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, @@ -433,26 +442,27 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - StreamSvgIcon.message( - size: 136.0, + StreamSvgIcon( + icon: StreamSvgIcons.message, + size: 136, color: StreamChatTheme.of(context).colorTheme.disabled, ), - const SizedBox(height: 16.0), + const SizedBox(height: 16), Text( AppLocalizations.of(context).noSharedGroups, style: TextStyle( - fontSize: 14.0, + fontSize: 14, color: StreamChatTheme.of(context) .colorTheme .textHighEmphasis, ), ), - const SizedBox(height: 8.0), + const SizedBox(height: 8), Text( AppLocalizations.of(context).groupSharedWithUserAppearHere, textAlign: TextAlign.center, style: TextStyle( - fontSize: 14.0, + fontSize: 14, color: StreamChatTheme.of(context) .colorTheme .textHighEmphasis @@ -490,10 +500,10 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { final extraData = channel.extraData; final members = channel.state!.members; - const textStyle = TextStyle(fontSize: 14.0, fontWeight: FontWeight.bold); + const textStyle = TextStyle(fontSize: 14, fontWeight: FontWeight.bold); return SizedBox( - height: 64.0, + height: 64, child: LayoutBuilder( builder: (context, constraints) { String? title; @@ -521,7 +531,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { title = 'No title'; } } else { - title = extraData['name'] as String; + title = extraData['name']! as String; } return Column( @@ -530,11 +540,11 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { child: Row( children: [ Padding( - padding: const EdgeInsets.all(8.0), + padding: const EdgeInsets.all(8), child: StreamChannelAvatar( channel: channel, - constraints: const BoxConstraints( - maxWidth: 40.0, maxHeight: 40.0), + constraints: + const BoxConstraints(maxWidth: 40, maxHeight: 40), ), ), Expanded( @@ -543,7 +553,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { style: textStyle, )), Padding( - padding: const EdgeInsets.all(8.0), + padding: const EdgeInsets.all(8), child: Text( '${channel.memberCount} ${AppLocalizations.of(context).members.toLowerCase()}', style: TextStyle( @@ -557,7 +567,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { ), ), Container( - height: 1.0, + height: 1, color: StreamChatTheme.of(context) .colorTheme .textHighEmphasis diff --git a/sample_app/lib/pages/choose_user_page.dart b/sample_app/lib/pages/choose_user_page.dart index 52a61ed483..b2aa66391a 100644 --- a/sample_app/lib/pages/choose_user_page.dart +++ b/sample_app/lib/pages/choose_user_page.dart @@ -1,17 +1,16 @@ -import 'package:sample_app/state/init_data.dart'; -import 'package:sample_app/utils/app_config.dart'; -import 'package:sample_app/utils/localizations.dart'; -import 'package:sample_app/widgets/stream_version.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:go_router/go_router.dart'; import 'package:provider/provider.dart'; +import 'package:sample_app/routes/routes.dart'; +import 'package:sample_app/state/init_data.dart'; +import 'package:sample_app/utils/app_config.dart'; +import 'package:sample_app/utils/localizations.dart'; +import 'package:sample_app/widgets/stream_version.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -import '../routes/routes.dart'; - const kStreamApiKey = 'STREAM_API_KEY'; const kStreamUserId = 'STREAM_USER_ID'; const kStreamToken = 'STREAM_TOKEN'; @@ -27,7 +26,6 @@ class ChooseUserPage extends StatelessWidget { backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, body: SafeArea( child: Column( - crossAxisAlignment: CrossAxisAlignment.center, children: [ Padding( padding: const EdgeInsets.only( @@ -46,7 +44,7 @@ class ChooseUserPage extends StatelessWidget { ), ), Padding( - padding: const EdgeInsets.only(bottom: 13.0), + padding: const EdgeInsets.only(bottom: 13), child: Text( AppLocalizations.of(context).welcomeToStreamChat, style: StreamChatTheme.of(context).textTheme.title, @@ -150,7 +148,8 @@ class ChooseUserPage extends StatelessWidget { .textLowEmphasis, ), ), - trailing: StreamSvgIcon.arrowRight( + trailing: StreamSvgIcon( + icon: StreamSvgIcons.arrowRight, color: StreamChatTheme.of(context) .colorTheme .accentPrimary, @@ -163,7 +162,8 @@ class ChooseUserPage extends StatelessWidget { leading: CircleAvatar( backgroundColor: StreamChatTheme.of(context).colorTheme.borders, - child: StreamSvgIcon.settings( + child: StreamSvgIcon( + icon: StreamSvgIcons.settings, color: StreamChatTheme.of(context) .colorTheme .textHighEmphasis, diff --git a/sample_app/lib/pages/group_chat_details_screen.dart b/sample_app/lib/pages/group_chat_details_screen.dart index 849c7c5ad3..5df7ae5075 100644 --- a/sample_app/lib/pages/group_chat_details_screen.dart +++ b/sample_app/lib/pages/group_chat_details_screen.dart @@ -1,18 +1,18 @@ -import 'package:sample_app/state/new_group_chat_state.dart'; -import 'package:sample_app/utils/localizations.dart'; +// ignore_for_file: deprecated_member_use + import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; +import 'package:sample_app/routes/routes.dart'; +import 'package:sample_app/state/new_group_chat_state.dart'; +import 'package:sample_app/utils/localizations.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -import '../routes/routes.dart'; - class GroupChatDetailsScreen extends StatefulWidget { - final NewGroupChatState groupChatState; - const GroupChatDetailsScreen({ - Key? key, + super.key, required this.groupChatState, - }) : super(key: key); + }); + final NewGroupChatState groupChatState; @override State createState() => _GroupChatDetailsScreenState(); @@ -90,7 +90,7 @@ class _GroupChatDetailsScreenState extends State { enabledBorder: InputBorder.none, errorBorder: InputBorder.none, disabledBorder: InputBorder.none, - contentPadding: const EdgeInsets.all(0), + contentPadding: EdgeInsets.zero, hintText: AppLocalizations.of(context).chooseAGroupChatName, hintStyle: TextStyle( @@ -109,13 +109,12 @@ class _GroupChatDetailsScreenState extends State { actions: [ StreamNeumorphicButton( child: IconButton( - padding: const EdgeInsets.all(0), - icon: StreamSvgIcon.check( - size: 24, - color: _isGroupNameEmpty - ? StreamChatTheme.of(context).colorTheme.textLowEmphasis - : StreamChatTheme.of(context).colorTheme.accentPrimary, - ), + iconSize: 24, + padding: EdgeInsets.zero, + color: _isGroupNameEmpty + ? StreamChatTheme.of(context).colorTheme.textLowEmphasis + : StreamChatTheme.of(context).colorTheme.accentPrimary, + icon: const StreamSvgIcon(icon: StreamSvgIcons.check), onPressed: _isGroupNameEmpty ? null : () async { @@ -148,8 +147,8 @@ class _GroupChatDetailsScreenState extends State { ), body: StreamConnectionStatusBuilder( statusBuilder: (context, status) { - String statusString = ''; - bool showStatus = true; + var statusString = ''; + var showStatus = true; switch (status) { case ConnectionStatus.connected: @@ -243,7 +242,7 @@ class _GroupChatDetailsScreenState extends State { .colorTheme .textHighEmphasis, ), - padding: const EdgeInsets.all(0), + padding: EdgeInsets.zero, splashRadius: 24, onPressed: () { widget.groupChatState.removeUser(user); @@ -269,45 +268,45 @@ class _GroupChatDetailsScreenState extends State { void _showErrorAlert() { showModalBottomSheet( - useRootNavigator: false, backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, context: context, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.only( - topLeft: Radius.circular(16.0), - topRight: Radius.circular(16.0), + topLeft: Radius.circular(16), + topRight: Radius.circular(16), )), builder: (context) { return Column( mainAxisSize: MainAxisSize.min, children: [ const SizedBox( - height: 26.0, + height: 26, ), - StreamSvgIcon.error( + StreamSvgIcon( + icon: StreamSvgIcons.error, color: StreamChatTheme.of(context).colorTheme.accentError, - size: 24.0, + size: 24, ), const SizedBox( - height: 26.0, + height: 26, ), Text( AppLocalizations.of(context).somethingWentWrongErrorMessage, style: StreamChatTheme.of(context).textTheme.headlineBold, ), const SizedBox( - height: 7.0, + height: 7, ), Text(AppLocalizations.of(context).operationCouldNotBeCompleted), const SizedBox( - height: 36.0, + height: 36, ), Container( color: StreamChatTheme.of(context) .colorTheme .textHighEmphasis .withOpacity(.08), - height: 1.0, + height: 1, ), Row( mainAxisAlignment: MainAxisAlignment.center, diff --git a/sample_app/lib/pages/group_info_screen.dart b/sample_app/lib/pages/group_info_screen.dart index 47d91ae804..664e1fb667 100644 --- a/sample_app/lib/pages/group_info_screen.dart +++ b/sample_app/lib/pages/group_info_screen.dart @@ -1,24 +1,24 @@ +// ignore_for_file: deprecated_member_use + import 'dart:async'; import 'package:collection/collection.dart' show IterableExtension; -import 'package:sample_app/pages/channel_file_display_screen.dart'; -import 'package:sample_app/routes/routes.dart'; -import 'package:sample_app/utils/localizations.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; +import 'package:sample_app/pages/channel_file_display_screen.dart'; +import 'package:sample_app/pages/channel_media_display_screen.dart'; +import 'package:sample_app/pages/pinned_messages_screen.dart'; +import 'package:sample_app/routes/routes.dart'; +import 'package:sample_app/utils/localizations.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -import 'channel_media_display_screen.dart'; -import 'pinned_messages_screen.dart'; - class GroupInfoScreen extends StatefulWidget { - final StreamMessageThemeData messageTheme; - const GroupInfoScreen({ - Key? key, + super.key, required this.messageTheme, - }) : super(key: key); + }); + final StreamMessageThemeData messageTheme; @override State createState() => _GroupInfoScreenState(); @@ -63,7 +63,7 @@ class _GroupInfoScreenState extends State { Filter.notIn('id', [ StreamChat.of(context).currentUser!.id, ...channel.state!.members - .map(((e) => e.userId)) + .map((e) => e.userId) .whereType(), ]), ], @@ -95,7 +95,7 @@ class _GroupInfoScreenState extends State { Filter.notIn('id', [ StreamChat.of(context).currentUser!.id, ...channel.state!.members - .map(((e) => e.userId)) + .map((e) => e.userId) .whereType(), ]), ], @@ -124,7 +124,7 @@ class _GroupInfoScreenState extends State { stream: channel.state!.membersStream, builder: (context, snapshot) { if (!snapshot.hasData) { - return Container( + return ColoredBox( color: StreamChatTheme.of(context).colorTheme.disabled, child: const Center(child: CircularProgressIndicator()), ); @@ -133,8 +133,8 @@ class _GroupInfoScreenState extends State { return Scaffold( backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, appBar: AppBar( - elevation: 1.0, - toolbarHeight: 56.0, + elevation: 1, + toolbarHeight: 56, backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, leading: const StreamBackButton(), title: Column( @@ -161,7 +161,7 @@ class _GroupInfoScreenState extends State { 2 * MediaQuery.of(context).size.width / 3, members: snapshot.data, extraData: state.data!.channel!.extraData, - maxFontSize: 16.0, + maxFontSize: 16, )!, style: TextStyle( color: StreamChatTheme.of(context) @@ -174,7 +174,7 @@ class _GroupInfoScreenState extends State { ); }), const SizedBox( - height: 3.0, + height: 3, ), Text( '${channel.memberCount} ${AppLocalizations.of(context).members}, ${snapshot.data?.where((e) => e.user!.online).length ?? 0} ${AppLocalizations.of(context).online}', @@ -183,7 +183,7 @@ class _GroupInfoScreenState extends State { .colorTheme .textHighEmphasis .withOpacity(0.5), - fontSize: 12.0, + fontSize: 12, ), ), ], @@ -198,8 +198,9 @@ class _GroupInfoScreenState extends State { _buildAddUserModal(context); }, child: Padding( - padding: const EdgeInsets.all(8.0), - child: StreamSvgIcon.userAdd( + padding: const EdgeInsets.all(8), + child: StreamSvgIcon( + icon: StreamSvgIcons.userAdd, color: StreamChatTheme.of(context) .colorTheme .accentPrimary), @@ -212,7 +213,7 @@ class _GroupInfoScreenState extends State { children: [ _buildMembers(snapshot.data!), Container( - height: 8.0, + height: 8, color: StreamChatTheme.of(context).colorTheme.disabled, ), if (channel.ownCapabilities @@ -259,21 +260,21 @@ class _GroupInfoScreenState extends State { member.user, userMember?.userId == channel.createdBy?.id); }, child: SizedBox( - height: 65.0, + height: 65, child: Column( children: [ Row( children: [ Padding( padding: const EdgeInsets.symmetric( - horizontal: 8.0, - vertical: 12.0, + horizontal: 8, + vertical: 12, ), child: StreamUserAvatar( user: member.user!, constraints: const BoxConstraints.tightFor( - height: 40.0, - width: 40.0, + height: 40, + width: 40, ), ), ), @@ -288,7 +289,7 @@ class _GroupInfoScreenState extends State { fontWeight: FontWeight.bold), ), const SizedBox( - height: 1.0, + height: 1, ), Text( _getLastSeen(member.user!), @@ -302,7 +303,7 @@ class _GroupInfoScreenState extends State { ), ), Padding( - padding: const EdgeInsets.all(8.0), + padding: const EdgeInsets.all(8), child: Text( member.userId == channel.createdBy?.id ? AppLocalizations.of(context).owner @@ -317,7 +318,7 @@ class _GroupInfoScreenState extends State { ], ), Container( - height: 1.0, + height: 1, color: StreamChatTheme.of(context).colorTheme.disabled, ), ], @@ -337,7 +338,7 @@ class _GroupInfoScreenState extends State { child: Material( color: StreamChatTheme.of(context).colorTheme.appBg, child: SizedBox( - height: 65.0, + height: 65, child: Column( children: [ Expanded( @@ -345,8 +346,9 @@ class _GroupInfoScreenState extends State { children: [ Padding( padding: const EdgeInsets.symmetric( - horizontal: 21.0, vertical: 12.0), - child: StreamSvgIcon.down( + horizontal: 21, vertical: 12), + child: StreamSvgIcon( + icon: StreamSvgIcons.down, color: StreamChatTheme.of(context) .colorTheme .textLowEmphasis, @@ -371,7 +373,7 @@ class _GroupInfoScreenState extends State { ), ), Container( - height: 1.0, + height: 1, color: StreamChatTheme.of(context).colorTheme.disabled, ), ], @@ -389,12 +391,12 @@ class _GroupInfoScreenState extends State { return Material( color: StreamChatTheme.of(context).colorTheme.appBg, child: Container( - height: 56.0, + height: 56, alignment: Alignment.center, child: Row( children: [ Padding( - padding: const EdgeInsets.all(7.0), + padding: const EdgeInsets.all(7), child: Text( AppLocalizations.of(context).name.toUpperCase(), style: StreamChatTheme.of(context).textTheme.footnote.copyWith( @@ -405,7 +407,7 @@ class _GroupInfoScreenState extends State { ), ), const SizedBox( - width: 7.0, + width: 7, ), Expanded( child: TextField( @@ -435,42 +437,35 @@ class _GroupInfoScreenState extends State { Row( mainAxisSize: MainAxisSize.min, children: [ - InkWell( - child: StreamSvgIcon.closeSmall(), - onTap: () { + IconButton( + icon: const StreamSvgIcon(icon: StreamSvgIcons.closeSmall), + onPressed: () { setState(() { _nameController.text = _getChannelName( 2 * MediaQuery.of(context).size.width / 3, members: channel.state!.members, extraData: channel.extraData, - maxFontSize: 16.0, + maxFontSize: 16, )!; _focusNode.unfocus(); }); }, ), - Padding( - padding: const EdgeInsets.only(right: 16.0, left: 8.0), - child: InkWell( - child: StreamSvgIcon.check( - color: StreamChatTheme.of(context) - .colorTheme - .accentPrimary, - size: 24.0, - ), - onTap: () { - try { - channel.update({ - 'name': _nameController.text.trim(), - }); - } catch (_) { - setState(() { - _nameController.text = channelName; - _focusNode.unfocus(); - }); - } - }, - ), + IconButton( + color: StreamChatTheme.of(context).colorTheme.accentPrimary, + icon: const StreamSvgIcon(icon: StreamSvgIcons.check), + onPressed: () { + try { + channel.update({ + 'name': _nameController.text.trim(), + }); + } catch (_) { + setState(() { + _nameController.text = channelName; + _focusNode.unfocus(); + }); + } + }, ), ], ), @@ -496,9 +491,10 @@ class _GroupInfoScreenState extends State { title: AppLocalizations.of(context).muteGroup, titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: StreamSvgIcon.mute( - size: 24.0, + padding: const EdgeInsets.symmetric(horizontal: 16), + child: StreamSvgIcon( + icon: StreamSvgIcons.mute, + size: 24, color: StreamChatTheme.of(context) .colorTheme .textHighEmphasis @@ -531,16 +527,18 @@ class _GroupInfoScreenState extends State { tileColor: StreamChatTheme.of(context).colorTheme.appBg, titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: StreamSvgIcon.pin( - size: 24.0, + padding: const EdgeInsets.symmetric(horizontal: 16), + child: StreamSvgIcon( + icon: StreamSvgIcons.pin, + size: 24, color: StreamChatTheme.of(context) .colorTheme .textHighEmphasis .withOpacity(0.5), ), ), - trailing: StreamSvgIcon.right( + trailing: StreamSvgIcon( + icon: StreamSvgIcons.right, color: StreamChatTheme.of(context).colorTheme.textLowEmphasis, ), onTap: () { @@ -563,16 +561,18 @@ class _GroupInfoScreenState extends State { title: AppLocalizations.of(context).photosAndVideos, titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( - padding: const EdgeInsets.symmetric(horizontal: 12.0), - child: StreamSvgIcon.pictures( - size: 32.0, + padding: const EdgeInsets.symmetric(horizontal: 12), + child: StreamSvgIcon( + icon: StreamSvgIcons.pictures, + size: 32, color: StreamChatTheme.of(context) .colorTheme .textHighEmphasis .withOpacity(0.5), ), ), - trailing: StreamSvgIcon.right( + trailing: StreamSvgIcon( + icon: StreamSvgIcons.right, color: StreamChatTheme.of(context).colorTheme.textLowEmphasis, ), onTap: () { @@ -597,16 +597,18 @@ class _GroupInfoScreenState extends State { title: AppLocalizations.of(context).files, titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( - padding: const EdgeInsets.symmetric(horizontal: 12.0), - child: StreamSvgIcon.files( - size: 32.0, + padding: const EdgeInsets.symmetric(horizontal: 12), + child: StreamSvgIcon( + icon: StreamSvgIcons.files, + size: 32, color: StreamChatTheme.of(context) .colorTheme .textHighEmphasis .withOpacity(0.5), ), ), - trailing: StreamSvgIcon.right( + trailing: StreamSvgIcon( + icon: StreamSvgIcons.right, color: StreamChatTheme.of(context).colorTheme.textLowEmphasis, ), onTap: () { @@ -633,9 +635,10 @@ class _GroupInfoScreenState extends State { title: AppLocalizations.of(context).leaveGroup, titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: StreamSvgIcon.userRemove( - size: 24.0, + padding: const EdgeInsets.symmetric(horizontal: 16), + child: StreamSvgIcon( + icon: StreamSvgIcons.userRemove, + size: 24, color: StreamChatTheme.of(context) .colorTheme .textHighEmphasis @@ -643,8 +646,8 @@ class _GroupInfoScreenState extends State { ), ), trailing: const SizedBox( - height: 24.0, - width: 24.0, + height: 24, + width: 24, ), onTap: () async { final streamChannel = StreamChannel.of(context); @@ -657,7 +660,8 @@ class _GroupInfoScreenState extends State { question: AppLocalizations.of(context).leaveConversationAreYouSure, cancelText: AppLocalizations.of(context).cancel.toUpperCase(), - icon: StreamSvgIcon.userRemove( + icon: StreamSvgIcon( + icon: StreamSvgIcons.userRemove, color: StreamChatTheme.of(context).colorTheme.accentError, ), ); @@ -679,11 +683,11 @@ class _GroupInfoScreenState extends State { barrierColor: StreamChatTheme.of(context).colorTheme.overlay, builder: (context) { return Padding( - padding: const EdgeInsets.only(top: 16.0, left: 8.0, right: 8.0), + padding: const EdgeInsets.only(top: 16, left: 8, right: 8), child: Material( borderRadius: const BorderRadius.only( - topLeft: Radius.circular(16.0), - topRight: Radius.circular(16.0), + topLeft: Radius.circular(16), + topRight: Radius.circular(16), ), clipBehavior: Clip.antiAlias, child: Scaffold( @@ -718,7 +722,8 @@ class _GroupInfoScreenState extends State { children: [ Padding( padding: const EdgeInsets.all(24), - child: StreamSvgIcon.search( + child: StreamSvgIcon( + icon: StreamSvgIcons.search, size: 96, color: StreamChatTheme.of(context) .colorTheme @@ -750,60 +755,48 @@ class _GroupInfoScreenState extends State { Widget _buildTextInputSection() { final theme = StreamChatTheme.of(context); - return Column( + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: SizedBox( - height: 36, - child: TextField( - controller: _searchController, - cursorColor: theme.colorTheme.textHighEmphasis, - autofocus: true, - decoration: InputDecoration( - hintText: AppLocalizations.of(context).search, - hintStyle: theme.textTheme.body.copyWith( - color: theme.colorTheme.textLowEmphasis, - ), - prefixIconConstraints: - BoxConstraints.tight(const Size(40, 24)), - prefixIcon: StreamSvgIcon.search( - color: theme.colorTheme.textHighEmphasis, - size: 24, - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(24.0), - borderSide: BorderSide( - color: theme.colorTheme.borders, - ), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(24.0), - borderSide: BorderSide( - color: theme.colorTheme.borders, - )), - contentPadding: const EdgeInsets.all(0), + Expanded( + child: SizedBox( + height: 36, + child: TextField( + controller: _searchController, + cursorColor: theme.colorTheme.textHighEmphasis, + autofocus: true, + decoration: InputDecoration( + hintText: AppLocalizations.of(context).search, + hintStyle: theme.textTheme.body.copyWith( + color: theme.colorTheme.textLowEmphasis, + ), + prefixIconConstraints: BoxConstraints.tight(const Size(40, 24)), + prefixIcon: StreamSvgIcon( + icon: StreamSvgIcons.search, + color: theme.colorTheme.textHighEmphasis, + size: 24, + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(24), + borderSide: BorderSide( + color: theme.colorTheme.borders, ), ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(24), + borderSide: BorderSide( + color: theme.colorTheme.borders, + )), + contentPadding: EdgeInsets.zero, ), ), - const SizedBox(width: 16.0), - IconButton( - icon: StreamSvgIcon.closeSmall( - color: theme.colorTheme.textLowEmphasis, - ), - constraints: const BoxConstraints.tightFor( - height: 24, - width: 24, - ), - padding: EdgeInsets.zero, - splashRadius: 24, - onPressed: () => Navigator.pop(context), - ) - ], + ), ), + IconButton( + icon: const StreamSvgIcon(icon: StreamSvgIcons.closeSmall), + color: theme.colorTheme.textHighEmphasis, + onPressed: () => Navigator.pop(context), + ) ], ); } @@ -812,7 +805,6 @@ class _GroupInfoScreenState extends State { final color = StreamChatTheme.of(context).colorTheme.barsBg; showModalBottomSheet( - useRootNavigator: false, context: context, clipBehavior: Clip.antiAlias, isScrollControlled: true, @@ -827,42 +819,43 @@ class _GroupInfoScreenState extends State { mainAxisSize: MainAxisSize.min, children: [ const SizedBox( - height: 24.0, + height: 24, ), Center( child: Text( user!.name, style: const TextStyle( - fontSize: 16.0, + fontSize: 16, fontWeight: FontWeight.bold, ), ), ), const SizedBox( - height: 5.0, + height: 5, ), _buildConnectedTitleState(user)!, Center( child: Padding( - padding: const EdgeInsets.all(16.0), + padding: const EdgeInsets.all(16), child: StreamUserAvatar( user: user, constraints: const BoxConstraints.tightFor( - height: 64.0, - width: 64.0, + height: 64, + width: 64, ), - borderRadius: BorderRadius.circular(32.0), + borderRadius: BorderRadius.circular(32), ), ), ), if (StreamChat.of(context).currentUser!.id != user.id) _buildModalListTile( context, - StreamSvgIcon.user( + StreamSvgIcon( color: StreamChatTheme.of(context) .colorTheme .textLowEmphasis, - size: 24.0, + size: 24, + icon: StreamSvgIcons.user, ), AppLocalizations.of(context).viewInfo, () async { @@ -888,11 +881,12 @@ class _GroupInfoScreenState extends State { if (StreamChat.of(context).currentUser!.id != user.id) _buildModalListTile( context, - StreamSvgIcon.message( + StreamSvgIcon( color: StreamChatTheme.of(context) .colorTheme .textLowEmphasis, - size: 24.0, + size: 24, + icon: StreamSvgIcons.message, ), AppLocalizations.of(context).message, () async { @@ -919,11 +913,12 @@ class _GroupInfoScreenState extends State { isUserAdmin) _buildModalListTile( context, - StreamSvgIcon.userRemove( + StreamSvgIcon( color: StreamChatTheme.of(context) .colorTheme .accentError, - size: 24.0, + size: 24, + icon: StreamSvgIcons.userRemove, ), AppLocalizations.of(context).removeFromGroup, () async { final router = GoRouter.of(context); @@ -947,11 +942,12 @@ class _GroupInfoScreenState extends State { StreamChatTheme.of(context).colorTheme.accentError), _buildModalListTile( context, - StreamSvgIcon.closeSmall( + StreamSvgIcon( color: StreamChatTheme.of(context) .colorTheme .textLowEmphasis, - size: 24.0, + size: 24, + icon: StreamSvgIcons.closeSmall, ), AppLocalizations.of(context).cancel, () { @@ -966,8 +962,8 @@ class _GroupInfoScreenState extends State { }, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.only( - topLeft: Radius.circular(16.0), - topRight: Radius.circular(16.0), + topLeft: Radius.circular(16), + topRight: Radius.circular(16), ), ), ); @@ -1015,15 +1011,15 @@ class _GroupInfoScreenState extends State { child: Column( children: [ Container( - height: 1.0, + height: 1, color: StreamChatTheme.of(context).colorTheme.disabled, ), SizedBox( - height: 64.0, + height: 64, child: Row( children: [ Padding( - padding: const EdgeInsets.all(16.0), + padding: const EdgeInsets.all(16), child: leading, ), Expanded( @@ -1082,8 +1078,8 @@ class _GroupInfoScreenState extends State { if (user.online) { return AppLocalizations.of(context).online; } else { - if(user.lastActive == null) { - return ""; + if (user.lastActive == null) { + return ''; } return '${AppLocalizations.of(context).lastSeen} ${Jiffy.parseFromDateTime(user.lastActive!).fromNow()}'; diff --git a/sample_app/lib/pages/new_chat_screen.dart b/sample_app/lib/pages/new_chat_screen.dart index 622eca3702..dfa5daaaf0 100644 --- a/sample_app/lib/pages/new_chat_screen.dart +++ b/sample_app/lib/pages/new_chat_screen.dart @@ -1,13 +1,14 @@ +// ignore_for_file: deprecated_member_use + import 'dart:async'; -import 'package:sample_app/utils/localizations.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; +import 'package:sample_app/routes/routes.dart'; +import 'package:sample_app/utils/localizations.dart'; +import 'package:sample_app/widgets/chips_input_text_field.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -import '../widgets/chips_input_text_field.dart'; -import '../routes/routes.dart'; - class NewChatScreen extends StatefulWidget { const NewChatScreen({super.key}); @@ -157,8 +158,8 @@ class _NewChatScreenState extends State { ), body: StreamConnectionStatusBuilder( statusBuilder: (context, status) { - String statusString = ''; - bool showStatus = true; + var statusString = ''; + var showStatus = true; switch (status) { case ConnectionStatus.connected: @@ -234,7 +235,7 @@ class _NewChatScreenState extends State { ), ), ), - StreamSvgIcon.close(), + const StreamSvgIcon(icon: StreamSvgIcons.close), ], ), ); @@ -259,11 +260,12 @@ class _NewChatScreenState extends State { children: [ StreamNeumorphicButton( child: Center( - child: StreamSvgIcon.contacts( + child: StreamSvgIcon( color: StreamChatTheme.of(context) .colorTheme .accentPrimary, size: 24, + icon: StreamSvgIcons.contacts, ), ), ), @@ -346,10 +348,10 @@ class _NewChatScreenState extends State { child: Center( child: Column( children: [ - Padding( - padding: - const EdgeInsets.all(24), - child: StreamSvgIcon.search( + const Padding( + padding: EdgeInsets.all(24), + child: StreamSvgIcon( + icon: StreamSvgIcons.search, size: 96, color: Colors.grey, ), diff --git a/sample_app/lib/pages/new_group_chat_screen.dart b/sample_app/lib/pages/new_group_chat_screen.dart index 1a63fdd625..c30f9c0bd8 100644 --- a/sample_app/lib/pages/new_group_chat_screen.dart +++ b/sample_app/lib/pages/new_group_chat_screen.dart @@ -1,14 +1,13 @@ import 'dart:async'; -import 'package:sample_app/state/new_group_chat_state.dart'; -import 'package:sample_app/utils/localizations.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; +import 'package:sample_app/routes/routes.dart'; +import 'package:sample_app/state/new_group_chat_state.dart'; +import 'package:sample_app/utils/localizations.dart'; +import 'package:sample_app/widgets/search_text_field.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -import '../routes/routes.dart'; -import '../widgets/search_text_field.dart'; - class NewGroupChatScreen extends StatefulWidget { const NewGroupChatScreen({super.key}); @@ -92,9 +91,8 @@ class _NewGroupChatScreenState extends State { actions: [ if (state.users.isNotEmpty) IconButton( - icon: StreamSvgIcon.arrowRight( - color: StreamChatTheme.of(context).colorTheme.accentPrimary, - ), + color: StreamChatTheme.of(context).colorTheme.accentPrimary, + icon: const StreamSvgIcon(icon: StreamSvgIcons.arrowRight), onPressed: () async { GoRouter.of(context).pushNamed( Routes.NEW_GROUP_CHAT_DETAILS.name, @@ -106,8 +104,8 @@ class _NewGroupChatScreenState extends State { ), body: StreamConnectionStatusBuilder( statusBuilder: (context, status) { - String statusString = ''; - bool showStatus = true; + var statusString = ''; + var showStatus = true; switch (status) { case ConnectionStatus.connected: @@ -157,7 +155,6 @@ class _NewGroupChatScreenState extends State { onlineIndicatorAlignment: const Alignment(0.9, 0.9), user: user, - showOnlineStatus: true, borderRadius: BorderRadius.circular(32), constraints: @@ -173,7 +170,7 @@ class _NewGroupChatScreenState extends State { onTap: () { groupChatState.removeUser(user); }, - child: Container( + child: DecoratedBox( decoration: BoxDecoration( color: StreamChatTheme.of(context) @@ -187,12 +184,13 @@ class _NewGroupChatScreenState extends State { .appBg, ), ), - child: StreamSvgIcon.close( + child: StreamSvgIcon( color: StreamChatTheme.of(context) .colorTheme .textHighEmphasis, size: 24, + icon: StreamSvgIcons.close, ), ), ), @@ -270,7 +268,8 @@ class _NewGroupChatScreenState extends State { children: [ Padding( padding: const EdgeInsets.all(24), - child: StreamSvgIcon.search( + child: StreamSvgIcon( + icon: StreamSvgIcons.search, size: 96, color: StreamChatTheme.of(context) .colorTheme @@ -310,18 +309,17 @@ class _NewGroupChatScreenState extends State { } class _HeaderDelegate extends SliverPersistentHeaderDelegate { - final Widget child; - final double height; - const _HeaderDelegate({ required this.child, required this.height, }); + final Widget child; + final double height; @override Widget build( BuildContext context, double shrinkOffset, bool overlapsContent) { - return Container( + return ColoredBox( color: StreamChatTheme.of(context).colorTheme.barsBg, child: child, ); diff --git a/sample_app/lib/pages/pinned_messages_screen.dart b/sample_app/lib/pages/pinned_messages_screen.dart index 8cffa8957f..2bcc792fc6 100644 --- a/sample_app/lib/pages/pinned_messages_screen.dart +++ b/sample_app/lib/pages/pinned_messages_screen.dart @@ -1,7 +1,9 @@ -import 'package:sample_app/utils/localizations.dart'; -import 'package:sample_app/routes/routes.dart'; +// ignore_for_file: deprecated_member_use + import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; +import 'package:sample_app/routes/routes.dart'; +import 'package:sample_app/utils/localizations.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; class PinnedMessagesScreen extends StatefulWidget { @@ -42,7 +44,7 @@ class _PinnedMessagesScreenState extends State { AppLocalizations.of(context).pinnedMessages, style: TextStyle( color: StreamChatTheme.of(context).colorTheme.textHighEmphasis, - fontSize: 16.0, + fontSize: 16, ), ), leading: const StreamBackButton(), @@ -55,28 +57,29 @@ class _PinnedMessagesScreenState extends State { child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - StreamSvgIcon.pin( - size: 136.0, + StreamSvgIcon( + icon: StreamSvgIcons.pin, + size: 136, color: StreamChatTheme.of(context).colorTheme.disabled, ), - const SizedBox(height: 16.0), + const SizedBox(height: 16), Text( AppLocalizations.of(context).noPinnedItems, style: TextStyle( - fontSize: 17.0, + fontSize: 17, color: StreamChatTheme.of(context).colorTheme.textHighEmphasis, fontWeight: FontWeight.bold, ), ), - const SizedBox(height: 8.0), + const SizedBox(height: 8), RichText( textAlign: TextAlign.center, text: TextSpan(children: [ TextSpan( text: '${AppLocalizations.of(context).longPressMessage} ', style: TextStyle( - fontSize: 14.0, + fontSize: 14, color: StreamChatTheme.of(context) .colorTheme .textHighEmphasis @@ -86,7 +89,7 @@ class _PinnedMessagesScreenState extends State { TextSpan( text: AppLocalizations.of(context).pinToConversation, style: TextStyle( - fontSize: 14.0, + fontSize: 14, fontWeight: FontWeight.bold, color: StreamChatTheme.of(context) .colorTheme diff --git a/sample_app/lib/pages/splash_screen.dart b/sample_app/lib/pages/splash_screen.dart index da075acb49..0bbdcd9ebe 100644 --- a/sample_app/lib/pages/splash_screen.dart +++ b/sample_app/lib/pages/splash_screen.dart @@ -1,3 +1,5 @@ +// ignore_for_file: deprecated_member_use + import 'package:flutter/material.dart'; import 'package:lottie/lottie.dart'; @@ -18,9 +20,9 @@ mixin SplashScreenStateMixin on State ), ); - late final _circleAnimation = Tween( - begin: 0.0, - end: 1000.0, + late final _circleAnimation = Tween( + begin: 0, + end: 1000, ).animate(CurvedAnimation( parent: _animationController, curve: Curves.easeInOut, @@ -34,8 +36,8 @@ mixin SplashScreenStateMixin on State curve: Curves.easeInOut, )); - late final _scaleAnimation = Tween( - begin: 1.0, + late final _scaleAnimation = Tween( + begin: 1, end: 1.5, ).animate(CurvedAnimation( parent: _scaleAnimationController, @@ -106,8 +108,8 @@ mixin SplashScreenStateMixin on State return Transform.scale( scale: _circleAnimation.value, child: Container( - width: 1.0, - height: 1.0, + width: 1, + height: 1, decoration: BoxDecoration( color: Colors.white .withOpacity(1 - _animationController.value), diff --git a/sample_app/lib/pages/thread_list_page.dart b/sample_app/lib/pages/thread_list_page.dart index 391e800195..a2e10ce1b9 100644 --- a/sample_app/lib/pages/thread_list_page.dart +++ b/sample_app/lib/pages/thread_list_page.dart @@ -1,5 +1,5 @@ -import 'package:sample_app/pages/thread_page.dart'; import 'package:flutter/material.dart'; +import 'package:sample_app/pages/thread_page.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; class ThreadListPage extends StatefulWidget { diff --git a/sample_app/lib/pages/thread_page.dart b/sample_app/lib/pages/thread_page.dart index da536bb3aa..248675eeef 100644 --- a/sample_app/lib/pages/thread_page.dart +++ b/sample_app/lib/pages/thread_page.dart @@ -2,16 +2,16 @@ import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; class ThreadPage extends StatefulWidget { - final Message parent; - final int? initialScrollIndex; - final double? initialAlignment; const ThreadPage({ - Key? key, + super.key, required this.parent, this.initialScrollIndex, this.initialAlignment, - }) : super(key: key); + }); + final Message parent; + final int? initialScrollIndex; + final double? initialAlignment; @override State createState() => _ThreadPageState(); diff --git a/sample_app/lib/pages/user_mentions_page.dart b/sample_app/lib/pages/user_mentions_page.dart index 6d199086df..820a38f78b 100644 --- a/sample_app/lib/pages/user_mentions_page.dart +++ b/sample_app/lib/pages/user_mentions_page.dart @@ -1,7 +1,7 @@ -import 'package:sample_app/utils/localizations.dart'; -import 'package:sample_app/routes/routes.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; +import 'package:sample_app/routes/routes.dart'; +import 'package:sample_app/utils/localizations.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; class UserMentionsPage extends StatefulWidget { @@ -46,7 +46,8 @@ class _UserMentionsPageState extends State { children: [ Padding( padding: const EdgeInsets.all(24), - child: StreamSvgIcon.mentions( + child: StreamSvgIcon( + icon: StreamSvgIcons.mentions, size: 96, color: StreamChatTheme.of(context).colorTheme.disabled, diff --git a/sample_app/lib/routes/app_routes.dart b/sample_app/lib/routes/app_routes.dart index 694c7fd608..094060eb44 100644 --- a/sample_app/lib/routes/app_routes.dart +++ b/sample_app/lib/routes/app_routes.dart @@ -1,8 +1,11 @@ import 'package:collection/collection.dart'; +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; import 'package:sample_app/pages/advanced_options_page.dart'; import 'package:sample_app/pages/channel_list_page.dart'; import 'package:sample_app/pages/channel_page.dart'; import 'package:sample_app/pages/chat_info_screen.dart'; +import 'package:sample_app/pages/choose_user_page.dart'; import 'package:sample_app/pages/group_chat_details_screen.dart'; import 'package:sample_app/pages/group_info_screen.dart'; import 'package:sample_app/pages/new_chat_screen.dart'; @@ -10,12 +13,8 @@ import 'package:sample_app/pages/new_group_chat_screen.dart'; import 'package:sample_app/pages/thread_page.dart'; import 'package:sample_app/routes/routes.dart'; import 'package:sample_app/state/new_group_chat_state.dart'; -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -import '../pages/choose_user_page.dart'; - final appRoutes = [ GoRoute( name: Routes.CHANNEL_LIST_PAGE.name, @@ -110,7 +109,7 @@ final appRoutes = [ name: Routes.NEW_GROUP_CHAT_DETAILS.name, path: Routes.NEW_GROUP_CHAT_DETAILS.path, builder: (BuildContext context, GoRouterState state) { - final groupChatState = state.extra as NewGroupChatState; + final groupChatState = state.extra! as NewGroupChatState; return GroupChatDetailsScreen(groupChatState: groupChatState); }, ), diff --git a/sample_app/lib/routes/routes.dart b/sample_app/lib/routes/routes.dart index 5c9749a2b1..1aede41c44 100644 --- a/sample_app/lib/routes/routes.dart +++ b/sample_app/lib/routes/routes.dart @@ -25,10 +25,10 @@ abstract class Routes { } class RouteConfig { - final String name; - final String path; const RouteConfig({required this.name, required this.path}); + final String name; + final String path; } class ChannelRouteConfig extends RouteConfig { diff --git a/sample_app/lib/utils/local_notification_observer.dart b/sample_app/lib/utils/local_notification_observer.dart index d6496ee39e..d9e8b0b8ba 100644 --- a/sample_app/lib/utils/local_notification_observer.dart +++ b/sample_app/lib/utils/local_notification_observer.dart @@ -1,13 +1,11 @@ import 'dart:async'; +import 'package:flutter/material.dart'; import 'package:sample_app/routes/routes.dart'; import 'package:sample_app/utils/notifications_service.dart' as pn; -import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; class LocalNotificationObserver extends NavigatorObserver { - Route? currentRoute; - late final StreamSubscription _subscription; LocalNotificationObserver( StreamChatClient client, @@ -22,6 +20,8 @@ class LocalNotificationObserver extends NavigatorObserver { _handleEvent(event, client, navigatorKey); }); } + Route? currentRoute; + late final StreamSubscription _subscription; void _handleEvent(Event event, StreamChatClient client, GlobalKey navigatorKey) { @@ -30,7 +30,7 @@ class LocalNotificationObserver extends NavigatorObserver { } final channelId = event.cid; if (currentRoute?.settings.name == Routes.CHANNEL_PAGE.name) { - final args = currentRoute?.settings.arguments as Map; + final args = currentRoute!.settings.arguments! as Map; if (args['cid'] == channelId) { return; } diff --git a/sample_app/lib/utils/localizations.dart b/sample_app/lib/utils/localizations.dart index 3af45038b3..598aa48282 100644 --- a/sample_app/lib/utils/localizations.dart +++ b/sample_app/lib/utils/localizations.dart @@ -2,6 +2,8 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; class AppLocalizations { + + AppLocalizations(this.locale); static const _localizedValues = >{ 'en': { 'add_a_group_name': 'Add a group name', @@ -64,7 +66,7 @@ class AppLocalizations { 'online': 'Online', 'on_the_platform': 'On the platform', 'operation_could_not_be_completed': - 'The operation couldn\'t be completed.', + "The operation couldn't be completed.", 'owner': 'Owner', 'photos_and_videos': 'Photos & Videos', 'photos_or_videos_will_appear_here': @@ -98,7 +100,7 @@ class AppLocalizations { 'add_a_group_name': 'Aggiungi un nome al gruppo', 'add_group_members': 'Aggiungi un membro', 'advanced_options': 'Opzioni Avanzate', - 'api_key_error': 'Per favore inserisci l\'API Key', + 'api_key_error': "Per favore inserisci l'API Key", 'attachment': 'allegato', 'attachments': 'allegati', 'cancel': 'Annulla', @@ -117,7 +119,7 @@ class AppLocalizations { 'files': 'File', 'files_appear_here': 'I file inviati in questa chat compariranno qui', 'group_shared_with_user_appear_here': - 'I gruppi in comune con quest\'utente compariranno qui', + "I gruppi in comune con quest'utente compariranno qui", 'last_seen': 'Ultimo accesso', 'leave': 'Lascia', 'leave_conversation': 'Lascia conversazione', @@ -155,7 +157,7 @@ class AppLocalizations { 'online': 'Online', 'on_the_platform': 'Sulla piattaforma', 'operation_could_not_be_completed': - 'Non รฉ stato possibile completare l\'operazione.', + "Non รฉ stato possibile completare l'operazione.", 'owner': 'Proprietario', 'photos_and_videos': 'Foto & Video', 'photos_or_videos_will_appear_here': @@ -170,7 +172,7 @@ class AppLocalizations { 'Sei sicuro di voler rimuovere questo membro?', 'search': 'Cerca', 'select_user_to_try_flutter_sdk': - 'Seleziona un utente per provare l\'SDK Flutter', + "Seleziona un utente per provare l'SDK Flutter", 'shared_groups': 'Gruppi in comune', 'sign_out': 'Sign out', 'something_went_wrong_error_message': 'Qualcosa รฉ andato storto', @@ -179,7 +181,7 @@ class AppLocalizations { 'to': 'A', 'type_a_name_hint': 'Scrivi un nome', 'user_id': 'User ID', - 'user_id_error': 'Per favore inserisci l\'ID dell\'utente', + 'user_id_error': "Per favore inserisci l'ID dell'utente", 'username_optional': 'Username (opzionale)', 'user_token': 'Token Utente', 'user_token_error': 'Per favore inserisci il token', @@ -190,8 +192,6 @@ class AppLocalizations { final Locale locale; - AppLocalizations(this.locale); - String get addAGroupName { return _localizedValues[locale.languageCode]!['add_a_group_name']!; } diff --git a/sample_app/lib/utils/notifications_service.dart b/sample_app/lib/utils/notifications_service.dart index d472ac7dba..9c34099c4f 100644 --- a/sample_app/lib/utils/notifications_service.dart +++ b/sample_app/lib/utils/notifications_service.dart @@ -1,9 +1,9 @@ -import 'package:sample_app/routes/routes.dart'; -import 'package:sample_app/utils/localizations.dart'; import 'package:flutter/material.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart' hide Message; import 'package:go_router/go_router.dart'; +import 'package:sample_app/routes/routes.dart'; +import 'package:sample_app/utils/localizations.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; void showLocalNotification( @@ -18,7 +18,9 @@ void showLocalNotification( if (![ EventType.messageNew, EventType.notificationMessageNew, - ].contains(event.type)) return; + ].contains(event.type)) { + return; + } // Return if the message is null. if (event.message == null) return; diff --git a/sample_app/lib/widgets/channel_list.dart b/sample_app/lib/widgets/channel_list.dart index 62c3a002b1..d17678c305 100644 --- a/sample_app/lib/widgets/channel_list.dart +++ b/sample_app/lib/widgets/channel_list.dart @@ -1,16 +1,15 @@ import 'dart:async'; -import 'package:sample_app/utils/localizations.dart'; -import 'package:sample_app/routes/routes.dart'; -import 'package:sample_app/widgets/search_text_field.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; +import 'package:flutter_slidable/flutter_slidable.dart'; import 'package:go_router/go_router.dart'; +import 'package:sample_app/pages/chat_info_screen.dart'; +import 'package:sample_app/pages/group_info_screen.dart'; +import 'package:sample_app/routes/routes.dart'; +import 'package:sample_app/utils/localizations.dart'; +import 'package:sample_app/widgets/search_text_field.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -import 'package:flutter_slidable/flutter_slidable.dart'; - -import '../pages/chat_info_screen.dart'; -import '../pages/group_info_screen.dart'; class ChannelList extends StatefulWidget { const ChannelList({super.key}); @@ -62,7 +61,6 @@ class _ChannelList extends State { 'members', [StreamChat.of(context).currentUser!.id], ), - presence: true, limit: 30, ); @@ -77,14 +75,12 @@ class _ChannelList extends State { @override Widget build(BuildContext context) { - return WillPopScope( - onWillPop: () async { - if (_isSearchActive) { - _controller.clear(); - setState(() => _isSearchActive = false); - return false; - } - return true; + return PopScope( + canPop: _isSearchActive == false, + onPopInvokedWithResult: (didPop, _) { + if (didPop) return; + _controller.clear(); + setState(() => _isSearchActive = false); }, child: NotificationListener( onNotification: (ScrollNotification scrollInfo) { @@ -96,7 +92,6 @@ class _ChannelList extends State { }, child: NestedScrollView( controller: _scrollController, - floatHeaderSlivers: false, headerSliverBuilder: (_, __) => [ SliverToBoxAdapter( child: SearchTextField( @@ -121,9 +116,10 @@ class _ChannelList extends State { child: Center( child: Column( children: [ - Padding( - padding: const EdgeInsets.all(24), - child: StreamSvgIcon.search( + const Padding( + padding: EdgeInsets.all(24), + child: StreamSvgIcon( + icon: StreamSvgIcons.search, size: 96, color: Colors.grey, ), @@ -170,7 +166,6 @@ class _ChannelList extends State { }, ) : SlidableAutoCloseBehavior( - closeWhenOpened: true, child: RefreshIndicator( onRefresh: _channelListController.refresh, child: StreamChannelListView( @@ -236,7 +231,8 @@ class _ChannelList extends State { if (canDeleteChannel) CustomSlidableAction( backgroundColor: backgroundColor, - child: StreamSvgIcon.delete( + child: StreamSvgIcon( + icon: StreamSvgIcons.delete, color: chatTheme.colorTheme.accentError, ), onPressed: (_) async { @@ -248,7 +244,8 @@ class _ChannelList extends State { 'Are you sure you want to delete this conversation?', okText: 'Delete', cancelText: 'Cancel', - icon: StreamSvgIcon.delete( + icon: StreamSvgIcon( + icon: StreamSvgIcons.delete, color: chatTheme.colorTheme.accentError, ), ); @@ -274,7 +271,8 @@ class _ChannelList extends State { child: Padding( padding: const EdgeInsets.all(8), child: StreamScrollViewEmptyWidget( - emptyIcon: StreamSvgIcon.message( + emptyIcon: StreamSvgIcon( + icon: StreamSvgIcons.message, size: 148, color: StreamChatTheme.of(context) .colorTheme diff --git a/sample_app/lib/widgets/chips_input_text_field.dart b/sample_app/lib/widgets/chips_input_text_field.dart index 2aadea07eb..45368e0939 100644 --- a/sample_app/lib/widgets/chips_input_text_field.dart +++ b/sample_app/lib/widgets/chips_input_text_field.dart @@ -1,5 +1,7 @@ -import 'package:sample_app/utils/localizations.dart'; +// ignore_for_file: deprecated_member_use + import 'package:flutter/material.dart'; +import 'package:sample_app/utils/localizations.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; typedef ChipBuilder = Widget Function(BuildContext context, T chip); @@ -7,16 +9,8 @@ typedef OnChipAdded = void Function(T chip); typedef OnChipRemoved = void Function(T chip); class ChipsInputTextField extends StatefulWidget { - final TextEditingController? controller; - final FocusNode? focusNode; - final ValueChanged? onInputChanged; - final ChipBuilder chipBuilder; - final OnChipAdded? onChipAdded; - final OnChipRemoved? onChipRemoved; - final String hint; - const ChipsInputTextField({ - Key? key, + super.key, required this.chipBuilder, required this.controller, this.onInputChanged, @@ -24,7 +18,14 @@ class ChipsInputTextField extends StatefulWidget { this.onChipAdded, this.onChipRemoved, this.hint = 'Type a name', - }) : super(key: key); + }); + final TextEditingController? controller; + final FocusNode? focusNode; + final ValueChanged? onInputChanged; + final ChipBuilder chipBuilder; + final OnChipAdded? onChipAdded; + final OnChipRemoved? onChipRemoved; + final String hint; @override ChipInputTextFieldState createState() => ChipInputTextFieldState(); @@ -36,7 +37,7 @@ class ChipInputTextFieldState extends State> { void addItem(T item) { setState(() => _chips.add(item)); - if (widget.onChipAdded != null) widget.onChipAdded!(item); + widget.onChipAdded?.call(item); } void removeItem(T item) { @@ -44,7 +45,7 @@ class ChipInputTextFieldState extends State> { _chips.remove(item); if (_chips.isEmpty) resumeItemAddition(); }); - if (widget.onChipRemoved != null) widget.onChipRemoved!(item); + widget.onChipRemoved?.call(item); } void pauseItemAddition() { @@ -73,7 +74,7 @@ class ChipInputTextFieldState extends State> { child: Row( children: [ Padding( - padding: const EdgeInsets.symmetric(vertical: 4.0), + padding: const EdgeInsets.symmetric(vertical: 4), child: Text( '${AppLocalizations.of(context).to.toUpperCase()}:', style: StreamChatTheme.of(context) @@ -93,8 +94,8 @@ class ChipInputTextFieldState extends State> { mainAxisSize: MainAxisSize.min, children: [ Wrap( - spacing: 8.0, - runSpacing: 4.0, + spacing: 8, + runSpacing: 4, children: _chips.map((item) { return widget.chipBuilder(context, item); }).toList(), @@ -111,7 +112,7 @@ class ChipInputTextFieldState extends State> { enabledBorder: InputBorder.none, errorBorder: InputBorder.none, disabledBorder: InputBorder.none, - contentPadding: const EdgeInsets.only(top: 4.0), + contentPadding: const EdgeInsets.only(top: 4), hintText: widget.hint, hintStyle: StreamChatTheme.of(context) .textTheme @@ -131,14 +132,16 @@ class ChipInputTextFieldState extends State> { alignment: Alignment.bottomCenter, child: IconButton( icon: _chips.isEmpty - ? StreamSvgIcon.user( + ? StreamSvgIcon( + icon: StreamSvgIcons.user, color: StreamChatTheme.of(context) .colorTheme .textHighEmphasis .withOpacity(0.5), size: 24, ) - : StreamSvgIcon.userAdd( + : StreamSvgIcon( + icon: StreamSvgIcons.userAdd, color: StreamChatTheme.of(context) .colorTheme .textHighEmphasis @@ -148,7 +151,7 @@ class ChipInputTextFieldState extends State> { onPressed: resumeItemAddition, alignment: Alignment.topRight, visualDensity: VisualDensity.compact, - padding: const EdgeInsets.all(0), + padding: EdgeInsets.zero, splashRadius: 24, constraints: const BoxConstraints.tightFor( height: 24, diff --git a/sample_app/lib/widgets/search_text_field.dart b/sample_app/lib/widgets/search_text_field.dart index 1d80ab7a8b..ec3084e47e 100644 --- a/sample_app/lib/widgets/search_text_field.dart +++ b/sample_app/lib/widgets/search_text_field.dart @@ -1,21 +1,22 @@ +// ignore_for_file: deprecated_member_use + import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; class SearchTextField extends StatelessWidget { - final TextEditingController? controller; - final ValueChanged? onChanged; - final String hintText; - final VoidCallback? onTap; - final bool showCloseButton; - const SearchTextField({ - Key? key, + super.key, required this.controller, this.onChanged, this.onTap, this.hintText = 'Search', this.showCloseButton = true, - }) : super(key: key); + }); + final TextEditingController? controller; + final ValueChanged? onChanged; + final String hintText; + final VoidCallback? onTap; + final bool showCloseButton; @override Widget build(BuildContext context) { @@ -47,7 +48,8 @@ class SearchTextField extends StatelessWidget { left: 8, right: 8, ), - child: StreamSvgIcon.search( + child: StreamSvgIcon( + icon: StreamSvgIcons.search, color: StreamChatTheme.of(context).colorTheme.textHighEmphasis, size: 24, @@ -59,7 +61,7 @@ class SearchTextField extends StatelessWidget { .colorTheme .textHighEmphasis .withOpacity(.5)), - contentPadding: const EdgeInsets.all(0), + contentPadding: EdgeInsets.zero, border: OutlineInputBorder( borderSide: BorderSide.none, borderRadius: BorderRadius.circular(24), @@ -71,10 +73,9 @@ class SearchTextField extends StatelessWidget { Material( color: Colors.transparent, child: IconButton( - padding: const EdgeInsets.all(0), - icon: StreamSvgIcon.closeSmall( - color: Colors.grey, - ), + color: Colors.grey, + padding: EdgeInsets.zero, + icon: const StreamSvgIcon(icon: StreamSvgIcons.closeSmall), splashRadius: 24, onPressed: () { if (controller!.text.isNotEmpty) { diff --git a/sample_app/lib/widgets/stream_version.dart b/sample_app/lib/widgets/stream_version.dart index ae736bb619..dfafee4cd3 100644 --- a/sample_app/lib/widgets/stream_version.dart +++ b/sample_app/lib/widgets/stream_version.dart @@ -1,13 +1,13 @@ -import 'package:sample_app/utils/localizations.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:yaml/yaml.dart'; +import 'package:sample_app/utils/localizations.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; +import 'package:yaml/yaml.dart'; class StreamVersion extends StatelessWidget { const StreamVersion({ - Key? key, - }) : super(key: key); + super.key, + }); @override Widget build(BuildContext context) { diff --git a/sample_app/macos/.gitignore b/sample_app/macos/.gitignore deleted file mode 100644 index d2fd377230..0000000000 --- a/sample_app/macos/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -# Flutter-related -**/Flutter/ephemeral/ -**/Pods/ - -# Xcode-related -**/xcuserdata/ diff --git a/sample_app/macos/Podfile b/sample_app/macos/Podfile index c795730db8..9ec46f8cd5 100644 --- a/sample_app/macos/Podfile +++ b/sample_app/macos/Podfile @@ -1,4 +1,4 @@ -platform :osx, '10.14' +platform :osx, '10.15' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' @@ -31,9 +31,6 @@ target 'Runner' do use_modular_headers! flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) - target 'RunnerTests' do - inherit! :search_paths - end end post_install do |installer| diff --git a/sample_app/macos/Runner.xcodeproj/project.pbxproj b/sample_app/macos/Runner.xcodeproj/project.pbxproj index f0c9f2c1c2..562444e84a 100644 --- a/sample_app/macos/Runner.xcodeproj/project.pbxproj +++ b/sample_app/macos/Runner.xcodeproj/project.pbxproj @@ -189,6 +189,7 @@ 33CC110E2044A8840003C045 /* Bundle Framework */, 3399D490228B24CF009A79C7 /* ShellScript */, 5EA8C195DB09CB61CDB56B17 /* [CP] Embed Pods Frameworks */, + 61600C7AED8D72CB17EDB92D /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -207,7 +208,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { 33CC10EC2044A3C60003C045 = { @@ -335,6 +336,23 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; + 61600C7AED8D72CB17EDB92D /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ diff --git a/sample_app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/sample_app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 55dda25a80..6b8484ee89 100644 --- a/sample_app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/sample_app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ Bool { return true } + + override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { + return true + } } diff --git a/sample_app/pubspec.yaml b/sample_app/pubspec.yaml index 65c437a6b5..0ee87cc940 100644 --- a/sample_app/pubspec.yaml +++ b/sample_app/pubspec.yaml @@ -8,31 +8,30 @@ environment: flutter: ">=3.24.5" dependencies: - flutter_app_badger: ^1.5.0 + collection: ^1.17.2 + firebase_core: ^3.0.0 + firebase_messaging: ^15.0.0 flutter: sdk: flutter - stream_chat_flutter: ^9.3.0 - stream_chat_persistence: ^9.3.0 - stream_chat_localizations: ^9.3.0 + flutter_app_badger: ^1.5.0 flutter_local_notifications: ^18.0.1 - flutter_svg: ^2.0.10+1 flutter_secure_storage: ^9.2.2 - yaml: ^3.1.2 - uuid: ^4.4.0 - streaming_shared_preferences: ^2.0.0 - lottie: ^3.1.2 - collection: ^1.17.2 - sentry_flutter: ^8.3.0 flutter_slidable: ^3.1.1 + flutter_svg: ^2.0.10+1 go_router: ^14.6.2 + lottie: ^3.1.2 provider: ^6.0.5 + sentry_flutter: ^8.3.0 + stream_chat_flutter: ^9.3.0 + stream_chat_localizations: ^9.3.0 + stream_chat_persistence: ^9.3.0 + streaming_shared_preferences: ^2.0.0 + uuid: ^4.4.0 video_player: ^2.8.7 - firebase_core: ^3.0.0 - firebase_messaging: ^15.0.0 + yaml: ^3.1.2 dev_dependencies: flutter_launcher_icons: ^0.14.2 - flutter_lints: ^5.0.0 flutter: uses-material-design: true From a27a4927dd3f5abb3a3351d256db7c1cf4f8b9d0 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Wed, 12 Feb 2025 19:01:10 +0530 Subject: [PATCH 168/172] chore: move deps to shared dependencies --- melos.yaml | 11 +++++++++++ sample_app/pubspec.yaml | 12 ++++++++++++ 2 files changed, 23 insertions(+) diff --git a/melos.yaml b/melos.yaml index 61be314ba6..366b0d4ca9 100644 --- a/melos.yaml +++ b/melos.yaml @@ -37,13 +37,20 @@ command: drift: ^2.22.1 equatable: ^2.0.5 ezanimation: ^0.6.0 + firebase_core: ^3.0.0 + firebase_messaging: ^15.0.0 file_picker: ^8.0.5 file_selector: ^1.0.3 + flutter_app_badger: ^1.5.0 + flutter_local_notifications: ^18.0.1 flutter_markdown: ^0.7.2+1 flutter_portal: ^1.1.4 + flutter_secure_storage: ^9.2.2 + flutter_slidable: ^3.1.1 flutter_svg: ^2.0.10+1 freezed_annotation: ^2.4.1 get_thumbnail_video: ^0.7.3 + go_router: ^14.6.2 http_parser: ^4.0.2 image_gallery_saver_plus: ^3.0.5 image_picker: ^1.1.2 @@ -62,10 +69,12 @@ command: path_provider: ^2.1.3 photo_manager: ^3.2.0 photo_view: ^0.15.0 + provider: ^6.0.5 rate_limiter: ^1.0.0 record: ^5.2.0 responsive_builder: ^0.7.0 rxdart: ^0.28.0 + sentry_flutter: ^8.3.0 share_plus: ^10.0.2 shimmer: ^3.0.0 sqlite3_flutter_libs: ^0.5.26 @@ -74,6 +83,7 @@ command: stream_chat_flutter_core: ^9.3.0 stream_chat_localizations: ^9.3.0 stream_chat_persistence: ^9.3.0 + streaming_shared_preferences: ^2.0.0 svg_icon_widget: ^0.0.1 synchronized: ^3.1.0+1 thumblr: ^0.0.4 @@ -89,6 +99,7 @@ command: drift_dev: ^2.22.1 fake_async: ^1.3.1 faker_dart: ^0.2.1 + flutter_launcher_icons: ^0.14.2 freezed: ^2.4.2 json_serializable: ^6.7.1 mocktail: ^1.0.0 diff --git a/sample_app/pubspec.yaml b/sample_app/pubspec.yaml index 0ee87cc940..df1f92ef49 100644 --- a/sample_app/pubspec.yaml +++ b/sample_app/pubspec.yaml @@ -3,6 +3,18 @@ description: A new Flutter project. publish_to: "none" version: 2.2.0 +# Note: The environment configuration and dependency versions are managed by Melos. +# +# Do not edit them manually. +# +# Steps to update dependencies: +# 1. Modify the version in the melos.yaml file. +# 2. Run `melos bootstrap` to apply changes. +# +# Steps to add a new dependency: +# 1. Add the dependency to this list. +# 2. Add it to the melos.yaml file for future updates. + environment: sdk: ^3.5.4 flutter: ">=3.24.5" From 088b2de2625fcd4d36d3ee48f7425835d5861fc3 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Wed, 12 Feb 2025 23:02:43 +0530 Subject: [PATCH 169/172] chore: update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1ed64d7b54..81e4966f94 100644 --- a/README.md +++ b/README.md @@ -20,8 +20,8 @@ Stream allows developers to rapidly deploy scalable feeds and chat messaging wit For upgrading from V7 to V8, please refer to the [V8 Migration Guide](https://getstream.io/chat/docs/sdk/flutter/guides/migration_guide_8_0/) -## Sample apps and demos -Our team maintains a dedicated repository for full fledged sample applications and demos. Consider checking out [GetStream/flutter-samples](https://github.com/GetStream/flutter-samples) to learn more or get started by looking at our latest [Stream Chat demo](https://github.com/GetStream/flutter-samples/tree/main/packages/stream_chat_v1). +## Sample apps and demos +Check out our [sample_app](sample_app) to see Stream Chat's core features in action. For more sample apps and demos, visit [GetStream/flutter-samples](https://github.com/GetStream/flutter-samples). ## Free for Makers From 2f02e9a18767059ac7d615080bb72d1e21eca0ca Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Thu, 13 Feb 2025 01:35:04 +0530 Subject: [PATCH 170/172] chore: format sample app --- sample_app/lib/firebase_options.dart | 12 ++++++++---- sample_app/lib/pages/channel_page.dart | 1 - sample_app/lib/pages/thread_page.dart | 1 - sample_app/lib/routes/routes.dart | 1 - .../lib/utils/local_notification_observer.dart | 1 - sample_app/lib/utils/localizations.dart | 1 - 6 files changed, 8 insertions(+), 9 deletions(-) diff --git a/sample_app/lib/firebase_options.dart b/sample_app/lib/firebase_options.dart index 52072061f7..46d9b06bab 100644 --- a/sample_app/lib/firebase_options.dart +++ b/sample_app/lib/firebase_options.dart @@ -70,8 +70,10 @@ class DefaultFirebaseOptions { projectId: 'stream-chat-internal', databaseURL: 'https://stream-chat-internal.firebaseio.com', storageBucket: 'stream-chat-internal.appspot.com', - androidClientId: '674907137625-2scfo9a5cs074dced5vhm712ej6hhtpm.apps.googleusercontent.com', - iosClientId: '674907137625-flarfn9cefu4lermgpbc4b8rm8l15ian.apps.googleusercontent.com', + androidClientId: + '674907137625-2scfo9a5cs074dced5vhm712ej6hhtpm.apps.googleusercontent.com', + iosClientId: + '674907137625-flarfn9cefu4lermgpbc4b8rm8l15ian.apps.googleusercontent.com', iosBundleId: 'io.getstream.flutter', ); @@ -82,8 +84,10 @@ class DefaultFirebaseOptions { projectId: 'stream-chat-internal', databaseURL: 'https://stream-chat-internal.firebaseio.com', storageBucket: 'stream-chat-internal.appspot.com', - androidClientId: '674907137625-2scfo9a5cs074dced5vhm712ej6hhtpm.apps.googleusercontent.com', - iosClientId: '674907137625-p3msks3snq0h22l7ekpqcf0frr0vt8mg.apps.googleusercontent.com', + androidClientId: + '674907137625-2scfo9a5cs074dced5vhm712ej6hhtpm.apps.googleusercontent.com', + iosClientId: + '674907137625-p3msks3snq0h22l7ekpqcf0frr0vt8mg.apps.googleusercontent.com', iosBundleId: 'io.getstream.streamChatV1', ); } diff --git a/sample_app/lib/pages/channel_page.dart b/sample_app/lib/pages/channel_page.dart index dc1184f8ea..d922372b89 100644 --- a/sample_app/lib/pages/channel_page.dart +++ b/sample_app/lib/pages/channel_page.dart @@ -8,7 +8,6 @@ import 'package:sample_app/routes/routes.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; class ChannelPage extends StatefulWidget { - const ChannelPage({ super.key, this.initialScrollIndex, diff --git a/sample_app/lib/pages/thread_page.dart b/sample_app/lib/pages/thread_page.dart index 248675eeef..cdd3e85390 100644 --- a/sample_app/lib/pages/thread_page.dart +++ b/sample_app/lib/pages/thread_page.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; class ThreadPage extends StatefulWidget { - const ThreadPage({ super.key, required this.parent, diff --git a/sample_app/lib/routes/routes.dart b/sample_app/lib/routes/routes.dart index 1aede41c44..d60383edd2 100644 --- a/sample_app/lib/routes/routes.dart +++ b/sample_app/lib/routes/routes.dart @@ -25,7 +25,6 @@ abstract class Routes { } class RouteConfig { - const RouteConfig({required this.name, required this.path}); final String name; final String path; diff --git a/sample_app/lib/utils/local_notification_observer.dart b/sample_app/lib/utils/local_notification_observer.dart index d9e8b0b8ba..4b2fc12a69 100644 --- a/sample_app/lib/utils/local_notification_observer.dart +++ b/sample_app/lib/utils/local_notification_observer.dart @@ -6,7 +6,6 @@ import 'package:sample_app/utils/notifications_service.dart' as pn; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; class LocalNotificationObserver extends NavigatorObserver { - LocalNotificationObserver( StreamChatClient client, GlobalKey navigatorKey, diff --git a/sample_app/lib/utils/localizations.dart b/sample_app/lib/utils/localizations.dart index 598aa48282..8a6bee4ed5 100644 --- a/sample_app/lib/utils/localizations.dart +++ b/sample_app/lib/utils/localizations.dart @@ -2,7 +2,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; class AppLocalizations { - AppLocalizations(this.locale); static const _localizedValues = >{ 'en': { From 56e442eb5c8218ad649dd0a94470e98b2cab9edc Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Thu, 13 Feb 2025 01:30:06 +0530 Subject: [PATCH 171/172] refactor: use diff to only run commands for changes --- .github/workflows/legacy_version_analyze.yml | 40 ++---- .github/workflows/pr_title.yml | 1 + .github/workflows/stream_flutter_workflow.yml | 131 +++++++----------- melos.yaml | 50 +++---- packages/stream_chat/example/pubspec.yaml | 2 +- .../stream_chat_flutter/example/pubspec.yaml | 2 +- .../example/pubspec.yaml | 2 +- .../example/pubspec.yaml | 2 +- .../example/pubspec.yaml | 2 +- sample_app/pubspec.yaml | 2 +- 10 files changed, 93 insertions(+), 141 deletions(-) diff --git a/.github/workflows/legacy_version_analyze.yml b/.github/workflows/legacy_version_analyze.yml index 940a522180..9647126bb1 100644 --- a/.github/workflows/legacy_version_analyze.yml +++ b/.github/workflows/legacy_version_analyze.yml @@ -9,15 +9,9 @@ on: push: branches: - master - paths: - - 'packages/**' - - '.github/workflows/legacy_version_analyze.yml' pull_request: branches: - master - paths: - - 'packages/**' - - '.github/workflows/legacy_version_analyze.yml' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -34,38 +28,26 @@ jobs: if: github.event.pull_request.draft == false runs-on: ubuntu-latest steps: - - name: "Git Checkout" + - name: ๐Ÿ“š Git Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - - name: "Install Flutter" + - name: ๐ŸŽฏ Setup Flutter uses: subosito/flutter-action@v2 with: - flutter-version: ${{ env.flutter_version }} - channel: stable cache: true + channel: stable + flutter-version: ${{ env.flutter_version }} cache-key: flutter-:os:-:channel:-:version:-:arch:-:hash:-${{ hashFiles('**/pubspec.lock') }} - - name: "Install Tools" + - name: ๐Ÿ“ฆ Install Tools run: flutter pub global activate melos - - name: "Bootstrap Workspace" - run: melos bootstrap --verbose - - # Only analyze lib/; non-client code doesn't need to work on - # all supported legacy version. - - name: "Stream Chat Analyze" - run: cd packages/stream_chat/lib && dart analyze --fatal-infos . - - - name: "Stream Chat Flutter Core Analyze" - run: cd packages/stream_chat_flutter_core/lib && dart analyze --fatal-infos . - - - name: "Stream Chat Flutter Analyze" - run: cd packages/stream_chat_flutter/lib && dart analyze --fatal-infos . - - - name: "Stream Chat Persistence Analyze" - run: cd packages/stream_chat_persistence/lib && dart analyze --fatal-infos . + - name: โš™๏ธ Bootstrap Workspace + run: melos bootstrap - - name: "Stream Chat Localizations Analyze" - run: cd packages/stream_chat_localizations/lib && dart analyze --fatal-infos . \ No newline at end of file + - name: ๐Ÿ•ต๏ธ Analyze + # Only analyze lib/; non-client code doesn't need to work on + # all supported legacy version. + run: melos exec -c 1 --diff=origin/master...HEAD --include-dependents -- "dart analyze lib --fatal-infos" \ No newline at end of file diff --git a/.github/workflows/pr_title.yml b/.github/workflows/pr_title.yml index 8b200d5d8c..72455d7ed2 100644 --- a/.github/workflows/pr_title.yml +++ b/.github/workflows/pr_title.yml @@ -26,6 +26,7 @@ jobs: doc repo localization + sample_app requireScope: true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/stream_flutter_workflow.yml b/.github/workflows/stream_flutter_workflow.yml index 5c97dcbe3a..566a5ec17b 100644 --- a/.github/workflows/stream_flutter_workflow.yml +++ b/.github/workflows/stream_flutter_workflow.yml @@ -1,14 +1,12 @@ name: stream_flutter_workflow env: - ACTIONS_ALLOW_UNSECURE_COMMANDS: 'true' + # Note: The versions below should be manually updated after a new major + # version comes out. flutter_version: "3.x" on: pull_request: - paths: - - 'packages/**' - - '.github/workflows/stream_flutter_workflow.yml' types: - opened - reopened @@ -23,127 +21,102 @@ concurrency: cancel-in-progress: true jobs: - analyze: - timeout-minutes: 15 - if: github.event.pull_request.draft == false - runs-on: ubuntu-latest - steps: - - name: "Git Checkout" - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: "Install Flutter" - uses: subosito/flutter-action@v2 - with: - flutter-version: ${{ env.flutter_version }} - channel: stable - cache: true - cache-key: flutter-:os:-:channel:-:version:-:arch:-:hash:-${{ hashFiles('**/pubspec.lock') }} - - name: "Install Tools" - run: | - flutter pub global activate melos - - name: "Bootstrap Workspace" - run: melos bootstrap --verbose - - name: "Dart Analyze" - run: | - melos run analyze - - name: "Pub Check" - if: github.base_ref == 'master' - run: | - melos run lint:pub - - format: + lint: runs-on: ubuntu-latest - if: github.event.pull_request.draft == false timeout-minutes: 15 steps: - - name: "Git Checkout" + - name: ๐Ÿ“š Git Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - - name: "Install Flutter" + + - name: ๐ŸŽฏ Setup Flutter uses: subosito/flutter-action@v2 with: - flutter-version: ${{ env.flutter_version }} - channel: stable cache: true + channel: stable + flutter-version: ${{ env.flutter_version }} cache-key: flutter-:os:-:channel:-:version:-:arch:-:hash:-${{ hashFiles('**/pubspec.lock') }} - - name: "Install Tools" - run: | - flutter pub global activate melos - - name: "Bootstrap Workspace" + + - name: ๐Ÿ“ฆ Install Tools + run: flutter pub global activate melos + + - name: โš™๏ธ Bootstrap Workspace run: melos bootstrap - - name: "Melos Format" - run: melos run format - - name: "Validate Formatting" - run: | - ./.github/workflows/scripts/validate-formatting.sh + + - name: โœจ Check Formatting + run: melos run format:changes + + - name: ๐Ÿ•ต๏ธ Analyze + run: melos run analyze:changes + + - if: github.base_ref == 'master' + name: ๐Ÿš€ Pub Check + run: melos run publish:dry-run:changes test: runs-on: ubuntu-latest - if: github.event.pull_request.draft == false timeout-minutes: 30 steps: - - name: "Git Checkout" + - name: ๐Ÿ“š Git Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - - name: "Install Flutter" + + - name: ๐ŸŽฏ Setup Flutter uses: subosito/flutter-action@v2 with: - flutter-version: ${{ env.flutter_version }} - channel: stable cache: true + channel: stable + flutter-version: ${{ env.flutter_version }} cache-key: flutter-:os:-:channel:-:version:-:arch:-:hash:-${{ hashFiles('**/pubspec.lock') }} - # This step is needed due to https://github.com/actions/runner-images/issues/11279 - - name: Install SQLite3 - run: sudo apt-get update && sudo apt-get install -y sqlite3 libsqlite3-dev - - name: "Install Tools" + + - name: ๐Ÿ“ฆ Install Tools run: | flutter pub global activate melos flutter pub global activate remove_from_coverage - - name: "Bootstrap Workspace" + + - name: โš™๏ธ Bootstrap Workspace run: melos bootstrap - - name: "Flutter Test" - run: melos run test:all - - name: "Collect Coverage" + + - name: ๐Ÿงช Run Tests + run: melos run test:packages:changed + + - name: ๐Ÿ“Š Collect Coverage run: melos run coverage:ignore-file --no-select - - name: "Upload Coverage" - uses: codecov/codecov-action@v5 - with: - token: ${{secrets.CODECOV_TOKEN}} - files: packages/*/coverage/lcov.info - - name: "Stream Chat Coverage Check" + + - name: โœ… Stream Chat Coverage Check uses: VeryGoodOpenSource/very_good_coverage@v3.0.0 with: path: packages/stream_chat/coverage/lcov.info min_coverage: 70 - - name: "Stream Chat Localizations Coverage Check" + + - name: โœ… Stream Chat Localizations Coverage Check uses: VeryGoodOpenSource/very_good_coverage@v3.0.0 with: path: packages/stream_chat_localizations/coverage/lcov.info min_coverage: 100 - - name: "Stream Chat Persistence Coverage Check" + + - name: โœ… Stream Chat Persistence Coverage Check uses: VeryGoodOpenSource/very_good_coverage@v3.0.0 with: path: packages/stream_chat_persistence/coverage/lcov.info min_coverage: 95 - - name: "Stream Chat Flutter Core Coverage Check" + + - name: โœ… Stream Chat Flutter Core Coverage Check uses: VeryGoodOpenSource/very_good_coverage@v3.0.0 with: path: packages/stream_chat_flutter_core/coverage/lcov.info min_coverage: 30 - - name: "Stream Chat Flutter Coverage Check" + + - name: โœ… Stream Chat Flutter Coverage Check uses: VeryGoodOpenSource/very_good_coverage@v3.0.0 with: path: packages/stream_chat_flutter/coverage/lcov.info min_coverage: 44 - draft-build: - runs-on: ubuntu-latest - if: github.event.pull_request.draft == true - timeout-minutes: 1 - - steps: - - name: Run a one-line script - run: echo Draft PR, you are good. + - name: ๐Ÿ“ Upload coverage to Codecov + uses: codecov/codecov-action@v5 + with: + token: ${{secrets.CODECOV_TOKEN}} + files: packages/*/coverage/lcov.info diff --git a/melos.yaml b/melos.yaml index 366b0d4ca9..ac2a6158a4 100644 --- a/melos.yaml +++ b/melos.yaml @@ -117,38 +117,31 @@ scripts: run: melos run analyze && melos run format description: Run all static analysis checks - analyze:all: - run: melos run analyze && melos run metrics - description: Run all - analyze: - run: | - melos exec -c 5 --ignore="*example*" -- \ - dart analyze --fatal-infos . - description: | - Run `dart analyze` in all packages. - - Note: you can also rely on your IDEs Dart Analysis / Issues window. + run: melos exec -c 5 --ignore="*example*" -- "dart analyze --fatal-infos ." + description: Run `dart analyze` in all packages. + + analyze:changes: + run: melos exec -c 1 --diff=origin/master...HEAD --include-dependents -- "dart analyze --fatal-infos ." + description: Run `dart analyze` in all changed packages. format: run: dart format --set-exit-if-changed . - description: | - Run `dart format --set-exit-if-changed .` in all packages. + description: Run `dart format --set-exit-if-changed .` in all packages. - metrics: - run: | - melos exec -c 1 --ignore="*example*" -- \ - flutter pub run dart_code_metrics:metrics analyze lib - description: | - Run `dart_code_metrics` in all packages. - - Note: you can also rely on your IDEs Dart Analysis / Issues window. + format:changes: + run: melos exec -c 1 --diff=origin/master...HEAD --include-dependents -- "dart format --set-exit-if-changed ." + description: Run `dart format` in all changed packages. lint:pub: - run: | - melos exec -c 5 --no-private --ignore="*example*" -- \ - flutter pub publish --dry-run - description: | - Run `pub publish --dry-run` in all packages. - - Note: you can also rely on your IDEs Dart Analysis / Issues window. + run: melos exec -c 5 --no-private --ignore="*example*" -- "flutter pub publish --dry-run" + description: Run `pub publish --dry-run` in all packages. + + publish:dry-run:changes: + run: >- + melos exec -c 1 --diff=origin/master...HEAD --no-private --include-dependents -- + "[ -f pubspec.yaml ] && ! grep -q 'publish_to: none' pubspec.yaml && flutter pub publish --dry-run || echo 'Package not publishable, skipping'" + description: Run `flutter pub publish --dry-run` in all changed packages. generate:all: run: melos run generate:dart && melos run generate:flutter @@ -180,6 +173,10 @@ scripts: flutter: true dirExists: test + test:changes: + run: melos exec -c 1 --diff=origin/master...HEAD --include-dependents -- "[ -d test ] && flutter test --no-pub --coverage || echo 'No tests found, skipping'" + description: Run `flutter test` in all changed packages. + update:goldens: run: melos exec -c 1 --depends-on="alchemist" -- "flutter test --tags golden --update-goldens" description: Update golden files for all packages in this project. @@ -191,8 +188,7 @@ scripts: flutter: true coverage:ignore-file: - run: | - melos exec -c 5 --fail-fast -- "\$MELOS_ROOT_PATH/.github/workflows/scripts/remove-from-coverage.sh" + run: melos exec -c 1 --fail-fast -- "\$MELOS_ROOT_PATH/.github/workflows/scripts/remove-from-coverage.sh" description: Removes all the ignored files from the coverage report. packageFilters: dirExists: coverage diff --git a/packages/stream_chat/example/pubspec.yaml b/packages/stream_chat/example/pubspec.yaml index 42033280d2..6802ea488a 100644 --- a/packages/stream_chat/example/pubspec.yaml +++ b/packages/stream_chat/example/pubspec.yaml @@ -1,7 +1,7 @@ name: stream_chat_example description: A new Flutter project. -publish_to: "none" +publish_to: none version: 1.0.0+1 # Note: The environment configuration and dependency versions are managed by Melos. diff --git a/packages/stream_chat_flutter/example/pubspec.yaml b/packages/stream_chat_flutter/example/pubspec.yaml index 1d988e5074..d69c37e345 100644 --- a/packages/stream_chat_flutter/example/pubspec.yaml +++ b/packages/stream_chat_flutter/example/pubspec.yaml @@ -1,6 +1,6 @@ name: stream_chat_flutter_example description: A new Flutter project. -publish_to: 'none' +publish_to: none version: 1.0.0+1 # Note: The environment configuration and dependency versions are managed by Melos. diff --git a/packages/stream_chat_flutter_core/example/pubspec.yaml b/packages/stream_chat_flutter_core/example/pubspec.yaml index 0a229f2889..939ec51b23 100644 --- a/packages/stream_chat_flutter_core/example/pubspec.yaml +++ b/packages/stream_chat_flutter_core/example/pubspec.yaml @@ -1,6 +1,6 @@ name: stream_chat_flutter_core_example description: Example app for testing stream_chat_flutter_core -publish_to: 'none' +publish_to: none version: 1.0.0+1 # Note: The environment configuration and dependency versions are managed by Melos. diff --git a/packages/stream_chat_localizations/example/pubspec.yaml b/packages/stream_chat_localizations/example/pubspec.yaml index 656c228538..fbf5b96f75 100644 --- a/packages/stream_chat_localizations/example/pubspec.yaml +++ b/packages/stream_chat_localizations/example/pubspec.yaml @@ -1,7 +1,7 @@ name: stream_chat_localizations_example description: A new Flutter project. -publish_to: 'none' +publish_to: none version: 1.0.0+1 # Note: The environment configuration and dependency versions are managed by Melos. diff --git a/packages/stream_chat_persistence/example/pubspec.yaml b/packages/stream_chat_persistence/example/pubspec.yaml index eed6a16463..6eb699fc20 100644 --- a/packages/stream_chat_persistence/example/pubspec.yaml +++ b/packages/stream_chat_persistence/example/pubspec.yaml @@ -1,6 +1,6 @@ name: stream_chat_persistence_example description: A new Flutter project. -publish_to: 'none' +publish_to: none version: 1.0.0+1 # Note: The environment configuration and dependency versions are managed by Melos. diff --git a/sample_app/pubspec.yaml b/sample_app/pubspec.yaml index df1f92ef49..378549d7a0 100644 --- a/sample_app/pubspec.yaml +++ b/sample_app/pubspec.yaml @@ -1,6 +1,6 @@ name: sample_app description: A new Flutter project. -publish_to: "none" +publish_to: none version: 2.2.0 # Note: The environment configuration and dependency versions are managed by Melos. From 72ffc275ea23c29729599b6f99fadc0e25bfc524 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Thu, 13 Feb 2025 01:33:46 +0530 Subject: [PATCH 172/172] fix: fix command name --- .github/workflows/stream_flutter_workflow.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stream_flutter_workflow.yml b/.github/workflows/stream_flutter_workflow.yml index 566a5ec17b..aacc1634de 100644 --- a/.github/workflows/stream_flutter_workflow.yml +++ b/.github/workflows/stream_flutter_workflow.yml @@ -80,7 +80,7 @@ jobs: run: melos bootstrap - name: ๐Ÿงช Run Tests - run: melos run test:packages:changed + run: melos run test:changes - name: ๐Ÿ“Š Collect Coverage run: melos run coverage:ignore-file --no-select

<>5{8FHRmJLp8Fp#2t+eq`i$^Rvu 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 a7>|51E`i^42A=kpjhvdvOZI-QC?@{_j2a z+;cxX^L&}fWRm%1l1U~;O+^6{jT8+40AMO9%4)p+JO2B?$gi!&q9Y0bARwwFE2ZUY za%7C+OVB%?lPZs@h$EYX8!PLNDkrSyl0U<%B|CLcZ?rIN$`S2P@J9DAw$)M!!fFhG zBrQup_9hKsbYJgwvgefeYj?7;#OQ@WGj{xPCEdNpj)xyc0-f5ZWd)Wz|GxkK8@6hB zV=GVswA+?W!G?4Td@j6*a5MS7;naaJ1zxvd>&b2hU);P|6)A$*u8sd#&Ezh8kakb< z;$>4vvDHp_caX$YhokiEha&0GK(M#DM1X5_$cE34TbomTBe;WG;$!AfQ=Qr_VZ3$r zl2|=Hsj_oHJ+WU4R}mMDL|<^*$SK9cjYi}M#sjemXO_)?87J{ik`mNMvi9zkQ<6Z! znbrAkk0y=9jXtC=?17AJ3z|cG|>f(=Zf`=Dvt-1<7MrJp=zbp zx%s|{lz7>rXf=WDnp}lNNCH}zjSZTG`=s^PJnG2X9CE4Tu~qMBL5sF-%g5|f=YQMB zPhKrkWIT{26&EgibKCEe{PA?D#KD%0tC83k6o6u`bAe&MYHK*-lPoSKfi`P^Feg*&iVavBSl8kxJfziz?Y)UP8O|R^) zn$%?`P_lC&{&OB}K0vD{vuvMkf_1iIxewX<2lwoxrY8RMS2N&=vw!-VAb8u`Zw)+B zOsRhp4fxP*7%+uusTC2|iznWH?(B_cv=$d3VfTst#CcK%YinUs?RZZ%WIlTv&w� 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 diff --git a/stream_chat_v1/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/stream_chat_v1/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 6a602c324673cce1bfcc909227ee84295c5eb2ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14197 zcmY*=WmKF`%kpjhvdvOZI-QC?@{_j2a z+;cxX^L&}fWRm%1l1U~;O+^6{jT8+40AMO9%4)p+JO2B?$gi!&q9Y0bARwwFE2ZUY za%7C+OVB%?lPZs@h$EYX8!PLNDkrSyl0U<%B|CLcZ?rIN$`S2P@J9DAw$)M!!fFhG zBrQup_9hKsbYJgwvgefeYj?7;#OQ@WGj{xPCEdNpj)xyc0-f5ZWd)Wz|GxkK8@6hB zV=GVswA+?W!G?4Td@j6*a5MS7;naaJ1zxvd>&b2hU);P|6)A$*u8sd#&Ezh8kakb< z;$>4vvDHp_caX$YhokiEha&0GK(M#DM1X5_$cE34TbomTBe;WG;$!AfQ=Qr_VZ3$r zl2|=Hsj_oHJ+WU4R}mMDL|<^*$SK9cjYi}M#sjemXO_)?87J{ik`mNMvi9zkQ<6Z! znbrAkk0y=9jXtC=?17AJ3z|cG|>f(=Zf`=Dvt-1<7MrJp=zbp zx%s|{lz7>rXf=WDnp}lNNCH}zjSZTG`=s^PJnG2X9CE4Tu~qMBL5sF-%g5|f=YQMB zPhKrkWIT{26&EgibKCEe{PA?D#KD%0tC83k6o6u`bAe&MYHK*-lPoSKfi`P^Feg*&iVavBSl8kxJfziz?Y)UP8O|R^) zn$%?`P_lC&{&OB}K0vD{vuvMkf_1iIxewX<2lwoxrY8RMS2N&=vw!-VAb8u`Zw)+B zOsRhp4fxP*7%+uusTC2|iznWH?(B_cv=$d3VfTst#CcK%YinUs?RZZ%WIlTv&w� z^lp%J1ljo$Lz^k5c9&?f{pD7PXi&uw+|~9^MPgtk?|rItAn~uv+tJXxoZXhiXW13+ z;XRjDQhbYA+!qFe-uNk#It)S#LoYSHN02FwRlCV%P=dIR0AX`Pb7^z14jNh7l3#R{ z&7+!Rnf%XOpNqCH@2ilJ#w+}HM(U8s!pGPUXy7{g9d?L#LY?(l!7o{f5iMMkY|(5d z6%r|4kD;QqZ8|<^#C|$(gur);37?!p`Q!S5!F#;-29)a#Ud5crx@@E}reiS_n`gs& z+orYb#ibdFI)=qIPp;u|V2G@;ipzmFhL^|qd80srTZPBiCN9+;`aaYapT*rh0g57G7D(gLtCp!0e1}?o|1wte1~}Xo zohT}CA~{=S9e=0%wMltiVA&)wToUD-lNu!2Pg>MM_WbVcLdfUpQz~Tl&FC>3V}UBy zCf=)-U)hzFjW*P4vC`<1!oh`1FAl zQHZBKuE-jbrU06DeQ7kwDJDBeG@81G5_M72?x+jOzo7MLZ)bSfLS#nV+Zjx1l@UZ? z7wOhZk>JDQ<6;A{zkeP=_zt1V7E_KqjC}7(f*MK}a^AFEfrn*xZd%!Kt$giqS=w!N zx_uzT$nHlyaImvtmtsox`wOcXaj~^J_jwOHx7CxEpP>67-`+lX&`t{x2F_*t+Z)pAA*udrxzwcJ&Ih*c}m@=xG=df~jt@NiUPkohcjZ7MlVLUpE!f zjTC(O=pbDDijzWbBai)(J?J@nVqH_^T@3yuFx*7|W<{hn+#_f0Q47;kIz^m!vY5}W zVRRvrO`qd08Q-55l74MP;N|rtAtdfqP)&YzSnxQ;*QZX3e0M^jTTS#}eDFltMlF(B zWK?7|+vZg?a(Pb2Xkb)C>M2m!E_Ib0;LCT%7l?=#R>YHrF?YwlqsE>atB4oH(WrRd zyJm1QE+5&@JpZ&8_%1}cdp99I-gp5OoeLO?^8%gO@P`=@KWi3o76TB zw`i1F6vFTpv838}a!F|wiFNyhIFJsC5@~oth?G?zv_d;Si>@J#)?JIrxIv*i1biGX zDy`IBFW~MR@k3X!OuP_F*P>|UyEawAYR4rS=A8%Q-r0M;(VA+l2-!RI@Ap>XE-9wE zZsTAq2oWQRQUn@-pFEk|c1m-p@seD+m|@~$0m&L6npzAr+PK1xKR_2JrU z>jd0SPf5d56&VIs6JX5Y*^Ul239iZ*RDm}b7WoefNt>6{^QY5bYQ*A5s-mKkpS+_@ z(ut6`G;Ja~o>s)KPha-uOlj*nSX@7*NEzxT-=e(rI3}>4uN&{CQJlQ{dU;r-4(Mq5 z;7A}StCYLt<95uKPFXnl(=0RVNrZ!`m(tPe<4*tcI4Nl-f~a&L!R)VO-g_6J(N5_z zw5{Rio&Uxsaq0rC(JxKh1$N9r1Hv~CsRZ%`|2}=OTQV(_?9`;2W#KgYYp+4AJ_|x> zMvGQ7LL~8$4+!Q(LkM%|zSfv@=p-KP4U5CtxqT{BwBL3Vdw7USC&QdSHHY(uOy$w{ z&A(J8V|O%76f-Ls2_(AVM7jcdk&2Eb9$iIJJUHvcbEZ)37ahiLh{!xoxZuYU&f|0C znDd)282j!Q`k2_O6Kii?_vt8f$-1!F27z7D6nby~p5o{(JCBcj*}*mK zeSDAnBRKI%7!w8qEJ0Nyeno@9eWzV? zCU1vhK87PX*=~IAo#dbR2GgoF!tctL0D3XP<*_CbZcDvJ@le~8lsh$wjr;8MW;UA>yvzNIY+cki~qv zRL&n=596i!+nmOuc^`uK@L_SZSela#6Cpwha2E_!$iC{dIeq$ltt1$hpJ2)XxDyfk zFy5{@H+aOVlEY_PWz*X__28h_aRDFIm~1ucz=bGLv{3Y20NhS z-Tg`7&8?iJBCvbk?*7t#1yl2z8dHMGkKf`v+}LgcroYwtg&Ey6C3;jMb4ZP9g+QED zngo>}o?8poDV7JZEpLC_U<%*0EUvWH4&>3A^6k!DT#qSNJpax6&eVE3GX(;!;R@RfDs3utT`%WbR~W(3sY1e zx><1tRS#$}uv@F@a8n!rd#vKNFd42()xo{_s*T*b{%_G?5fuQS_Prs(L03CLFdE?8 zoyx6;G$J*|u(*p6{q7SQY9dpNEO{45TO_E|#;MyPam3_ZD|PZR?2#rAmmD(4AMi1e z5eP6-cx)WKum@@Hk7CzDHswC=VTs8otq>@a*eJUl$D%HdFFVXYf#h<#Ap+$?-`h39tjE^V*v0!w zsi=1ZozSGx`K2yA_h|`Pe=crDWvl$Z;1TO7=aTW_%lSn zq=`-AsH2-Nv)&!GNl0Y7hKE)%rk17%_mq~fnvQfc$4oJnJ~Ye7nr>o?H(cL|4dc(= z|HUxirz5FSgA*$xQ_NpIFbeq~MLpFZtjZi=5R?ci2|sw3T)vcWb&0GG?rH*CZ#RXc z#7l_c8c02_N#Vhd<)=w7z1_=&6@lH|8I1W8Ke)HAMhUgsP3%W(Ek#^Pp55<3*EXqw zomvH4E^}42U9W5s-%7wKh3#G_V+cZsd7q^oyi{P~%>4`nnJ>64e}#XFAH0M~rJ4xr zQdDrfjND(Ay697l*#xyt<*n3+n+`jE^$H>J9K+#a$Z;eja3%a*-|>tQ+FgerPf=Vn zBb~*pX5>0sHFX@4eNE+l0a{E12sZD<~S@N%iD_L*-jsoAwGHr=rX)`5(qg8eQHF>VRN0SanXJ zQom|>4O!GMK*dicN&6_T3)z}E2~altQAXMfvbOYlg@@#nvTB$>itS2FTM!2T;JNH^ z5mktzM)d955<$v;F|+?0if3Vc?d8R$Xjaf6Ti9mPF~AirKn_iyiryhtA>N6ieslE# zbeK<>I^@YmgGuq75k9?n3qwPeXuJP-ys8BNRIsSYbS00g06TkPzqMI*DDog!AT;FA z&$Q2f^_az$nUxc6AG&1Jh{t#sa$i(G6_ZS#TTVBvLm{ZG`pb(Hf(U?h1NP&p?!5&; zmQUNDF|05EwWyRR&ExcstZt_q1?MDM89g*fH}1!Av9QN{)n^s7V)M&FmTJnJum{ij^D^9X$$Q4czl1R^1SMg z?J37 zqUn`tMY5hR=A=8-t3PFcP}FLm#o#VaZsZ@pFOYa(<9ya(b_8Y9wkljDo!ZDpky^6t zeT0a6EA6M@0in;;^XbM%; zCp{({N6kAwFoHNS?j#yZ@Rfum7`2eA(Gcs}OdU=HO`*EsQvw-)Md$Vg4oMBNaB!H% z3FGxiHHb_PVtFd?9fARbt(tFz7rzY>M-?QF{M{2hJT-jY@SrMQ;v4ts^?PH{`dCr)Kr$#8&f_Jf=o z%hf{#AY)&QDW3Pr1Q${r5=81dm|}(sfa#0fd5v*_F6UGanUVK$sW7ByXjC8VDx>Zj@a($ zzWz|&8nq|v744x#U$z@_-2h1x6FPK7YZtRD(NhRo+8zRC9TPlV+Cu9D`D0}(s9LQe zFGum5kB{2472xjxz%KgkOinn!`EQjjX&^_<~3Hz(W;cpcG+8t;oT@z63rmW>@ID|Mn8~muh#;mGFXiAjIHUa$+DR+fB@l_nU>I~4@;VI zA8!AsYoe5*Hb%90qGOOBhfX8v$1WRvoxY~sSe|UKqra!VgLqAmrA|MfG;oeRp>$;+LV~f z?y$F~lDGR_ESwwEQ^J{fNKI)y#`!rTM6G=m{F^uAXCO$__F8y_1EyDQ>#VM|Fqu< zl4C*wBsJaVPqyNqpVkT6Sfd4?TNaz>LRUc@b)P#$*poh|2Dq{7w)XGXRu5rNe4!KD z@iyBWV|oV!?2AJSn(Y;op-?z1!9QETOg}0%oS?_>NCmM)tsCX;x(%FB1+E8#lcv8z zepIdCE!&T-IcF56Y}tN^Y4ZG(X|kz(nW+MLD^p5@tWeVSrMs(AUYl8pLN0- z2SId_^2bZb^s2622OI;WX)N}b zXW{xJkxs#gmneD!)ic+}iE<;9bgQLZ07Kv>QV7@4Q^j74TP^n{BLMnl@iW^C?N8(W z){O^e9zc)WI94a?%ObOJkTsAEST zZPBsuk?k&jC44bmZPdh-!=n4nL&CRe3GV6S zXelfFOB*7J3W!d`cXl*UNJ6y=?+|ih?xOWxv7s3u`#LslbB^MRB}l5));BoXAT5=d zfi@8`BCa9A7V0sV44B$WkkorqD%6au)K<;BhzO8uYi}sxqZ{ZnEHoixC;CIyDh!I1s9~Rqb-Q%ppGUDKxAIuy#DAWRnzD#3uVd=6R;usY-Gr*B5 ze!GI8)DR`t{4A?SdD4_M_Sg9F4ojoSP;7LoaWs7@2p`Zy5}6cBx3}oB#smN;MrA?0 zlIZekWfHZk&X5?V#sgx#d!z48PHvB=u=XCc=oYCw?mNZ3)$ zhxQ$9uGv-RwIdp~-{Y;~EWW~?!t|{n`eTBD39If1n+-y^0AfsnfnCk*$n;Y@z%0Vc zeUG>x?zqj%Mg3EA7$66evec#xZ-F5jf(HuCw%!-hHoFQ9K6ZMMEeX9bsFNceU8^BI zotH%BNLlcpm+RsulS;%ErS@|vBIxX*X{k?LuOsXEkT3o;qQ%snvp`|$s* zN}fci1dlN;*D}y2eTu;tdUUr<>b>99T}Hnke7$w+cdH&y)XuFpGe_$v!AtXeI5zyx zu{d-)W5#`h2q0JkH>F^#+*Ckd> zG(ri`GcxW_S;HyG)I|Nd(9qTHDDN}`nWt>n1qbf)qL}v1dquLk!-hU0LQ|%cx=j9@ zTXis~6AOfYP!9_==ZNz(^-`l-wPOYgP+ppsAaKgJ5{%Vve#UX|4;I=a>_6Pz!dUJ8sIMR zQW(TZ2PIb=d(|tlq`$A5>n#O;q8VOHS<2Z6J!6Dh{8)Z^)g#%Tgbt^#RCbvXgrw)W zLLQOF^YwAhXZ=*-z+ADQ`?@1>T*z+j%nl`rb_XP)2Ki)|;m7x9xJRQjjSe6Rq*jXZ zTk?Zal#ei1DfbvMma2#(XyNHMNw}gXdR^>K0w%nV@ro7f0b+C$Yd(sl@^1ic2zy*o zkCMTC#?W_21&y;`@|GpktUi30XgO|<>+9{EDAO*#4`(-S9;XoTo<05sQV<)Y@Ii{? zt>v{?zyDh_0Y?ywV)Z60?iGZnuMkUNKva%cVPf1_AYrr^ zfB=aFt4xWO4dmb0TnuOyr70aq3I}3k8;{^ge@uQ9)nUI1sOYE^NW)iOp;sf92+n%G z$bBhFPEJlss8_X}uVXf@xBqlxatsUZ=<{Qg`VC9Ac8)%&4Wx=WfIoG7Q2d0LfxMOq z$g9Dgk>bSgmi)lIzX>u&v5Ke@)ZqjaEM3$*uq6RNvYfoxj`*E`e~r3Dw5x~gCEWXt ziJg&OPy&)`;xO+dm){l*5v<;lB!4Y@HU`xo9V&pm&Cu<~#BLU4;)pn$X`4hEjo1y! zb=aD%M@ZZ3OKvU@ixg;el5)+d$n{2151udHUN24~MQsFPg$+hx$2CiaYthhRz2ni& zt0n?S`YUOryoFBA-}pUvvA9y*&gB=Zl3t0wnlMikuy)+btj%j~CfSU*E$24_6f@=D zZ<3qm)yKPw%j*S~VlFN&{(=DM?nunNKc85gZqAWrUBgkOg4$QR@nJY2nv-6AU$R=l zy2VjCt-7NMm6{NZ0tu8BUE6!{@P9>C6DTfA_h?gKpoU*8Ih90F0Qu}E-?_E6$S_wo zL-%9t(Pl3b6di+u0|?YYSNUZP!tVu8iF?()O`TvP_J5?<5DxM5tV`HDhGkIMkDau? z9NTW|hO(tRJL{cO=ySqq2a_b2?H)$|{$Cbq`#>y7?56bF#~A1?GP7uo;Wva#(!F5E zO;{%I=UR^fT~gE6qqXVIckve0r7qE;g_6G%r2%Ti3Qw(wTD;)=d-71Im{|6*-%j?& zshs(G2b6cgfU8WkFWNz4c{G^FoN|P=$acb92_6lB4kc&e{QxVT!p=p1cGYzkhhdC0 ziP%``H=RnC39kq=>*xZ=m2rByU7eis4EXuE`n!HP>u)=+jLet(QT%@A8Q?r*=+gR0 zUQTW<`WV%HTlZv(V>KV$`a|q*PTCH|u!B}lj#92Vww=muXu4w;!P~MfJgv{reA}rr zs<>EcN2J9l4*~yQD2q-tvU?Jahka!nKkz5mQ9YLhJM{_Djo^X zXS3l)ojlW28EeQ8!nq13!mY^bogZZJ2M9Z9j9qOmoE4vbt4GT6(_qq(DiPl+oNJlG zH1}a8N#X$|l(XT9e~|M*zu)eAyoHX;8rnzUSy@|8iX1n>30ZZ9$7wiRPrKrT^%`Ae&2!X%J=vw@1s4Rcm$V2&-KK!$le;zKdMo~1Y{Urkb z#R=Q#80Eeq0SPv=c--Ag)WgqSw+jmyfNt7WtoeXVnJ#!>sTk zIcM_Unhri2CtygNdZ{bMoFX35z#lXylEM%#{j)09opU*1pE`|8eHdZ$9v3454;2>( z&=5{c6BkKu=MMtxwy&Xh2W_I-4Ccx(z0nJbP1EzqEa3A9Z@7}1hHyUUK|kVB-@jcg zv`d6*6iEm;C11})a^*D7uLaK8^0^uJ`HkO=;5S&zcg?q8(_T##|YPrW|| zN-}h)yFZnmzUWea%QUCOpy~LCX*O3xO)m3?KZ0@B-o#E|>v2U+8xzENp^~*Gq)js= zd0Ku~c)hbe=3O}JTWPYvs*)|dHLw~nuUV`@(QMuwnN%*O(=i7V>)n5NNZ?I=+1PJ5 z7mR7APxh#PM>|`o@p7XK7!RkAWTBx1#Kcz5tISu_ z$0qQ~168f93Bd8B(So955omS- zG>Nq#H*sDt($NX3IHEHot>?G3=R%IhIz`g&FaFeK6^4~Zo8SF-8DcmBkYJZclZsDe z&}FlxX86OqyRlC(Z?V}5Y`T{u4enkrhaS70Zz>5}4-@Cw1m}Gi z`b>Rw@qp%116eWm50NLg-XDuck}Z*lFWh?k1Gt(hBGpRi;jfTQvRrby&JO%5h2tF) zNvpP?Kp)FUF615_5D++h$8{m#@Nf8NIAnL6y4i7#yV+_GHy1Yc{B*PO%f=lA?ryPjqZL9%n5><14Y~x3=o3`O!sRHl1e%{4l3o z&?qA>kKDTT*^vD16%LK)?$k1#9WdZWon(He`P(}BNwOrX*%zb$s@so?_Y##k7e1-1 zcm{Zt&qfGWjL@6n7V9#pB3@<^(+Ek-{hJ5nZI(PFsG_8p+9#&t(`jAPyH_auFl_k# zmEY;-lFiHWQ`Y1DPHVnGBBkd_ThOlnA*948#578$&k`h$DD+3m4@t1pu&)Ep7@7C9 zhLxmRW&DRQ`=T?M)>m(mv7QuP^l<}0M167XaIW_9`QfCPUiot!&JQraO_Ls!Vj zKR?X*NKWo20l(UuYD0Sm@GI2?u*=qX)W~&Tbzr7?Vwot`r=+q7A+%j=9mKA4nEB|u)I9CY5faK1gY!xEp+mq`AdrFNS7NiUYOYL&+^CW(kMA;7eTEd5 zMr==C=Xf-&lc_Rwp{mWEHdL@<4POQ1p@*8|yN+s5Ad5<7o?q;;*f`-m5{iJbd%D&g zr1A*{^V*+^nL*GvApk>gZbVqqbeV?>Dxb?SCU27$gou>?l?*qLgs*-n{!E5XtJ^_b z`A6*w#(bOFEJ)6>J5Uf|ODC|DDl=7KVnJ98Vd~Tb>>_Mcgp2dlcc>)68UwTw3~jv;Lww8 z@)&;RNHESm0RoX!Ac8x2#zeah9(@1opxi0M6R(vZt1bL;YJ!&Dpdov|IE94d zLTz4p>eG0$JtcO`VuaJ4}H|J+#YYeS)Vv7~Pq%dF0j zqQRb<$l^FU7dQQmf6ixJUE9b!@8~_KO=&_zI?>`z|UP^sr1mhjUnly(kKqAQy^$ z<9B5M-D)cFy5v+{X)snIJs^ z|NI`)vtvxq>|pTSOjaNtdFHd9awQW0^Q)cry4m4_JCc^Brq>Fogk}VHZVz3&f(X+A zik7p@Xj2Sl4c9a>FQRW23xpL0O!Lwm^B%&0n|JRrxO;7$s5)3UZAQueJC9{yZlj_1 zqdDdycNsouQ^Z{99&9IvRPGzPPC8#o1eGg%uM7@tMECd~Uc)vf0y68Lby9~Yu7~#3 z{3k=7p#1#*(;u8(pbajH;G7)bcKix`P07S;`3f8k6_*Qx7qWy=Bx#BqoZk z9GjJ@sw4L3Y1H(UvPOCQG3*QBVu$uAo;t;fh_DBV3!{-yW(Z@tpj*M1vl^hc<}3F*^Ha(5)N}*kLqV8U!Cw}Zw}LHx2lJ3#YLGi@x7_(hcD;&chY&$y6 zqpEtt&p(wKO5PNkWZ;*peR-;&a_f%&0%^76Kn9MRP)C8SYm8W{aXUD#uc|Tf{IB*s zdt(VcfMg~Ff^}7e#SKm2gPdb zFl5Q}4)wXIM8vEel@#DXurSzaBHbO4(fdC`ru10q;*$<9@rY zfmXEOOO{MY2k5wXco!r1y&mF1LxVA#+@%sTWrk_7fw!@k_UhQgjAPT037S`E+63E7UJAZb{doul^+fr)CY&1Q&AG8Ow+ zQSG}EQ%~`NHJKNX&AVf>hacKksOa4@nziN9vp?`W=)I44<9AOdc=VQsTM-PvkCJm| z>xkauy!p5s7U#NaKIJ3qGt0^WjN56w=3R35NzMC*Pbe>n@?Z)s6CW@L`3XwQr* zE|TUbR4MD^N;ZS^jyVgLVS(LJPZ1zG9+OC7LAT7ENAhgY?D#quo{56-gM(2jRe;2;@Rz*G(Oj2k7Tt2OMss&We+fZLOkV@5-K*K4}ChV^JgMnbQirAIC?bTp5EH4)s~_Kr3V#QFk$(7oC~4kJ@K zde*=Hlt@1U7R(k!UegG@D)VN*t3cP-kq)9Ky0+m{S@rVDS}a)|s`xTz%=aqL1Y~mN z6#w>O>v|Ncm@CpEt@_AAo5F!xw{FGUZzy#TL=?3+h~R;^ej`my72vCy7L5qd{uatZ zP^Pk>kVV?WBKiCzII^W?mAy&l3hU8v>Jg%D1b$R(m8dYzY2z?T@vrWNh4aPy6#8u=|)WmoBhv$swq=DJI^=?;{QPqRUn*L#m){x02xb zu;ycOBX(D?D{9zpA1*Nr=3uA^{aRZ7m+_#0rC~3Ei=k!)I{4$W&~?hA-15eTL#i~4 zNIu#yOBjw7Q`(~&Rx&wLM=da%rHbsFPvfKb#psOzC*FcuyM!C2SAB?!o7Nu75$7+u zZI*YQDUZYfuB$((+Z}z?n_~J{5QX@qJUu-ABwofZ z^IrnrM2se)V%aCYeOB&T+N*2A1DWIXq@_xa^A?N@r5Zo!6d8i7=h?x^r$LlmvvLGc zITvFJb-wpV@zi~j1A3E^g<9bI2af?Z{2`JjtknfV*zB0exPp=v>ueV6c0C9N$iu~*re zRFug2^D$}ZSqE*N-epLR#goKTf`O9z=wU{a)6A`6nU9~pqlIF8jzPog zaiqTcxKR@nIrRS5=}Ff@-==fsePrRkjt1|D4N)Q zaXFIg)xQ!}(@C6R8IfikPtm6)|60g+VW$DMI)}wwhb=irhD-!P#9NA4&{GrrmmQ$N}F9lI$>e#c4e~PNVhAIC)j8z zL)^;B`xj+qjeF29x;X!`O2d-;#SfITp5fVsOKl?f6XzMadbtfhhwok8-hM){46pg= z@6UVpI*lLWIG~_aNmB24Lw>Jh`to^2nq!R0dBep`s zoBUp9_@3bFnK)6ccptzrl&f>rHb?^Ty>?7d`BXFM6g}4#Y3i;X7)TTz-FLHewEx)a zuDi08A!wqoNuZC^$$QA|z|<4P12iOfU?1}Idc19jzV})As{AZsm zQEF!mNcC?6T?9L_DQinL)mdaCNHq(ctJLo09>+UAVO3$ZU z=V@EZabqpQfsM0t!P1q@-JU_0Y$qG!#w)@H4n#IUKA&>nrHW%wYre3k;Ho`lphv3}o2*z>Ld$dzytgD{CyaL+()@ zbg(ec+^}dddOO*I;Du6(q2@E*uxokAcW*RyA2BsPp|b#}7&#BNxzcJ+A+@d zs>?80y9HY#I*}K7_bz(7fMcR~*Klu5ed%lFW5jqxd1x7-IlR6O`<;|onfl;QVl#HI zI{lyeINQrrgjan%t?r*)0MjWTM*2E$4wT4r2$9L6UljYs{(Dt z^O$HNa1yWbBh}~-4l?m*p-Q?v?g$^g6G)v{I(essjYpKR^;T^3^(_QG<5SivKUBkU zw)|(M11uDHY_&m}ml06$szpYdz{?Ce@q65$*tTiP98RY)gCevrBb;|+p*^YTvwdAb znUF;2;7GJj1IKwL zsR+qvqiY{e9k-|Y;Y{g#nU?WeRk;e{Fy*E5`1Mu^}AK?CnJ`Wr@X zbE2yTsruL?q+pcjGFZzOS%%jN6*j_`E*RSBD#gIh+X9oE!!+gB$2 zBKKD*76&%Fxb_<%5aOIcqHy6YZ@!Kfo(QOvY1BRF3Z3!5Y%8?d+{5ohd#`di?j!e4 zmu{a8l3R=rr}G3~{_A))chs?*>{hs%o8aEsNOG;%GReuu|Hq=9CXy8C&}5LkF~RD} zM_Qq-4o{0xhEKzmJew5|sFBv*ABx6#Etf?KoDqh1v9?!><;h3Ox45-6E${4exg?f9V2jMYtqnC@*eeuD zK3aJM-B{Vr;oV}D@Th-d@u^EP#$Bcp1LqblOI9_cP@dRkAAJ+iByD&VqHQf2NR;?k z2g!<4`UOd9^AD^88>9PRwx0|wlxavCwMIHEt)~_(0@2essZLw#%$=g(kLe80&#tQ{ zT2>ztT)+1>=E>9duLbMvXCl`EfylYNeB1RJE)89eZ7Gi=;Rf9~F?iz0F?O>N5jK6b z8x*JPzKp-gmM4}RU9R?R*G<>oqlI~C!%Pid6aFb`IA+Assvl{aK-4IlKt>GAqk-Nci0Pvt{_&Um1e+;h!0Ca<0t<1idN437EG$E0G$k|BBY%Zw zHPH{Re9gr}?03X!rMT%5b8`tqX+vL$IqBnB)jxfga_Xxi%9BHJl9ysKcHKOe$!HFX zg*qWKL);@IX^5xLAlNL(*2YOVJe<)a3W!Q;cFEE-p(G1v2P^;kNNXdyk?1%kU_<28 z_*NxQAV+HSH04yIxWCq6@?g7BKcX{Ra)1CN3pW5ZP=llOi6ZH(%^-NST#B(~E&fd~-G9 zM^^flWET0EHCkk#UD+MMUH;2WuTLXw%m3+}vaQ0T)tS^q4eWXg>o_)hioY`OllZio xdDt8wSDP}P>ROUy<*i^(uph*?2A_JSLS>iWPOpA>Ej$DOl;l)oE2YiC{s$?93CI8d diff --git a/stream_chat_v1/android/app/src/main/res/values-night/styles.xml b/stream_chat_v1/android/app/src/main/res/values-night/styles.xml index 449a9f9308..06952be745 100644 --- a/stream_chat_v1/android/app/src/main/res/values-night/styles.xml +++ b/stream_chat_v1/android/app/src/main/res/values-night/styles.xml @@ -3,14 +3,14 @@ + + diff --git a/stream_chat_v1/assets/android_icon.png b/stream_chat_v1/assets/android_icon.png deleted file mode 100644 index 3b85d6c36f7b5e617a7bca1c85d5c9b524890d5b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15354 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 diff --git a/stream_chat_v1/assets/ios_icon.png b/stream_chat_v1/assets/ic_launcher.png similarity index 100% rename from stream_chat_v1/assets/ios_icon.png rename to stream_chat_v1/assets/ic_launcher.png diff --git a/stream_chat_v1/assets/ic_launcher_background.png b/stream_chat_v1/assets/ic_launcher_background.png new file mode 100644 index 0000000000000000000000000000000000000000..651c64f978fcbcbd87d9e3dc8316fba6ae6069c8 GIT binary patch literal 4234 zcmeAS@N?(olHy`uVBq!ia0y~yVB7%09Be?56MhC-K#H+A$lZxy-8q?;3=9G;o-U3d z6>)E`GIBB)@Gu_?efekgiv&HnbzFy*POvQhZo$ODA)p{2EWs?6?Gppy{9s}`qb#7{ z(BKespg}cTcoqXA6ARA_d7ubGafue8%<-QxpK6)7%gB&tEADoa`{gTe~DWM4f@Q*gM literal 0 HcmV?d00001 diff --git a/stream_chat_v1/assets/ic_launcher_foreground.png b/stream_chat_v1/assets/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..fc3d22efa40dfc6dd952b2ceaafefc22304f28f9 GIT binary patch literal 13908 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 IC)RKN2bN8Mpa1{> literal 0 HcmV?d00001 diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png b/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..5fa61524ca999bfa5baeba2d016791b61fbe6fae GIT binary patch literal 1910 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 literal 0 HcmV?d00001 diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png b/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..527ae4cfa0e94ecece0fbf431b2daacd36438004 GIT binary patch literal 4779 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 N>dM+mH42uY{{s-LDoy|Z literal 0 HcmV?d00001 diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png b/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..8ec56ee792d137eb68a716c4a44e2e1ef96be32c GIT binary patch literal 2988 zcmbW3XFD4T1BPQ&C8%R0Mm0u0~>o!IOQseeG> z)C(pV7nChUM6ia!4kf8{nrNn$2&aZXU!|7lBk;^w1tUU2dis}q*gKX@?U%uzt2`#g zH#hZtZG3#geSaSP+@%ZEcV>rzs{AtgL({Aq`2P_&oBHRfFB0@id3?0 z>rL3xo;?SOpWICt9W@rzkq7iXOB9Q^w_X`^VdL#|`BgJLYM~qUp7|9vDbSM{%EQ?j zol*rtNFJo|7L@3rrA)cZ<>mUm)fH&Ay=|7?LVuK68bnLKcE$W9ncqHxy?O2`&+eUh zp+n^7j&aoG4>D5fXd@#N_nbAhmMKh< z3C}rt#auo2@p{yysfc=r?hcj^W;{Zd4i+@XktEVX^vY5L!B0+=iQc(N>|QTVSz5CN zIpRLw))Hi_vVTcHcg|P5XV}IZ&~(^q{lYVZ2w8ER-Ug=cWx`%O`MU6r4j*A#4~pDd z1<`9|h+kM@_|_f}IH+NL$>{Ox0ab$&?>wmNsbie&JKeU!Q2M;@#;{Q1U5j&7fEIq4 zl{U@qXO|xKi>N0cbj*nS=hZ`&N`Ym=5hhaT_?jK+;1IW|8Ye%3;R zCy;i6T^alLs0nUxFPXJ1z(?L+MTooyUpRNjy&{v5MCj)t?#xxHNX72*oDdShYOK0h z@Hy2p_dHp2JY!!RjrJ%Ief4QgmKzESkuISc<&LPzBAh&cilirXbNAOXZ9=Y?TeR(n zdEt1~ZWwkTZr##ueN2jg?mnW7_o-eF0I1{JUGF~@;@o2D>cm9TQXP;c{AF&}=621~ zzaQ))`)jxlLQAFn^E}xWXUJI>4H~2?m!jJ&vqsg_E)QCAdG~~^hsvItas?|8x{AZyo3Bn?WG3VY4KaJz2?>k)|IG8bn(?&3&T{^NCHI+VXr?`acay_ig1S@p8&s@tgMT;WPWuym5=KTNA~ z!PSOT+5g%xs21(&JEt5_MATibmpX&byu0JrcMpA2i_GnPnx(wl{zd%TDU(oRlFBxt zZd@F&l=K4Q{s{;DDdx}2{^)Ak-IZu~zpfkDPZD(1_KV;C?2>06)g5(3l}`SNR58=q(Z1Lpcp>s-LV*Y2V~8YFxFIgw}f;4OH@`9=8#x z;B9IJU|3Llu-Lx_kmX77F{p{)rB(?y3snk(66-8^d<_BYxLVLUoiOCUp|Q6j!P1rS z_&1b8)$Yt{feMdH@nIxxA`|^QVC?C;Z?6E@Tr!nJ=}t;9oZ)~<5e$DpH-TsIN&Dij!F{A>T#$- zp)vP~J7%=+f|<1x(jY!R1=KSr|1tCKm`c|#f$Y^d;LoOx1P9v`6p(khP$uF5D&fya zS@YdQPZ-XvRg}A*r;eSlAEDQSPvTCBq|MaoT&KAW*&2`Sgda~CeNd7&uwxGU~& zL-x|*{o7;lL&LZnwV;~#O8HrzHx6;J%}n{Cg5juU51KJ1lo zr4n?fK=yrQD9lM~pf8ZD`lm6i3dsHo`k;v;zzYe`SLhiR>9 z5k~!z0p#5iO=8It_{#1^=RLbE{R|)d9R{Co;Q}Y9Q)SMDB9rfixsDj$bP9Q|i8~aT z3br5+3LbjkV>mxlzJ9c7dQHV>UpKEd@C1BvKi65~70nTnH#$0+%;I03E8NJI;T#?1 zspby+%4Z#Oi+Du=@~-I&;}_NJ19Ce8d7#W&Xqn|{Q@ttt+#$cA)}$L+9**pGExXF$ zGze|H9%;qLz`JD!L5hkG%a7+sVuk1!h9*r^7>q-s19CkoO&CgGfwk_34_5! zsFrZ`*bLn%gh5%PP&?+j zy1PM*6~Awr4NKRX1_eK#$O>w~{~Rj~+gcZcO9?C|#ONaqLPF9eP-u*aBsPmk$nvfF z?8$DA5ZPS(C&@!pT9MHbp?Ze@yj(4^)FvN;&iI;>dC86Am=_~}T>}eM>JM-94@{BI;HtU)eO8^NF-9(%uS26XBX!01d^4dYhu+jErwt^zFPKCN4b(Pie8Xg@FlIK(HQFL$+KXY!s9r?nK ztSL1P(T(%4y-PT;sb1p3rb=(Gj47^Yza!iaaTOQ=;h!?F4t3mJ2R`R;YeM2xKZ@O_ z+z%5y0-2baWX!}htF69EOraxI+P^Xl@gJ~%GBmbszL=R;G}kv4d~|$f%=*Y_zIaV| zQeUg)hr#OiuPz5)02Nsmzc~rVilIgv^MiXTX)mQ;ea!ryN_)zk@gwS!k~@|D+rj}B MrZy&3M(*+d0pjzbVgLXD literal 0 HcmV?d00001 diff --git a/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png b/stream_chat_v1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..89492aaa6155a2ab0e3f37c2cc737315565016f6 GIT binary patch literal 6422 zcmd5><6v;_poC1ok;?k<;Rm+p=wWdZ4uE8G#ov2* zZ*707_cupkRV`Vxap!NGb&D9{#FvCZEUBEW(J~po{{Jru2~4`c1B{2BJR3M>2L^Q^ z1y7a9iEe8V&!I|OGZiSuVOQyqOiBz|wH;^T`?>wvi)eQqZm3dQxry2Uira>!pK5FK ztJibIje&VZUp!a>F%JVTDYZCLP;nq^_#~HuDEN|<#w%<*VO6~?@tY4ejFo_|Ou-HP z;WeAICc?NM#htq&`yDwm4F%)Uq@^NS5|$>*;Ou++{ORvRE_v}od)CpGNLmag>a|v9 zw1jS-|2^mVO^5i_-xQAH(%02Iyp^aD{-ew0a__$WTNAmv zpDYsTP>K&0*zbb9+=_k=fQ)qt6pyD3MmT973i24NWlk2x`M89pwLF6D9Pt7or~t<+ z$5IhTS9H|uE;lE?H&}gjpU?#@Tb8u74Oev{W6ZTchK(*S-D?;B>F|O3H^HAneI;9hyNyMrAKSY znvRA1fV)vA!&MN2Oc4`FRrvjhHWYD(Ptdogi>}zzqg!_*_zlkg5Gc7EwS9iw@F%gn zpI}I+B1?4T%~Q!S{p(L53aAB&Rivi8pyLUyqC&{rCvISaY9F%%$&YPnVZA(Y#CeSd zAq9C-`ccrYrTD;Um(SJqq-T2z>dTi8LchKSMPw(W-Ca-+?-C&zI_ zpyn%~i}qEV{Jh-(hD+LMtnvLtkzHlLr9P?3EYU+LFQlkGO2QQ8DO_k|S=h+m_&ES< z)gB*#PD}s$Y!s(BmN7Iodg{s8887x$R=&&^){WfcMv^y#+5?)+irb@Ym$mos2Bk9d zmq=9_TXKl@H+Bcb6`Nk0yzz!H>kGWoKN8vZ!jam_=tiF>ldTzKmjRMoY#`~Dmn$qE z;5t*nj%)_YdyWRw_qTi*)CO}Ah6D}{lRveme~x0ojBtTGwO!UuVH94UuY)G6HqcqJ zaAs@TQ5?R^Vn?u@|0($&=p0JJB`XoxIG$Qf?pOu^#XTH4sV1n>~9cQsJOYZf*q(jnI&&`F{mCD6fAimNYvXdl^x z9{BnRE-Hd#PdBB=q>dXdWHaz)YU2x&I2KzOV_2c7c*p`mUR4JQDj$fhzxstqJc895 zf5E+qS(@#5a!IPA!76+&OS~}l7ow7_J@lFaI%^m752Bh zEabyCmbmPL^bx5U#K~RAoGB@N!HU5$I(IXS`>9CO+eGKrDaD>f9j=3X){&a1+wZBH z;%5zm438De!T^b5J_Mz5+;eN;NQI2>x-gt{*K>zcf3KNJsDxKpXVxIwgnSR=d&q#6 zkynbPyD4xJcWRI5OoJQr$K-Q9NwFIq2$~urxjiv<;@D@qp8|ycC$QJKFDMK|`Y~uZ zo>4JhC+(tih3ooWAtU{6jbWY5JP$+D$sCJj6n&qc);gk|HT@p4V?$$7AWQ=Hdb54m zMnXVQ1MoYQFzQb$lzf>}=MkJ2t&I;BkZdCa!kz zPKAW~6;z1ydo$0}GfriuY)B?lWZCCQV zk2y3$_W>M30=|Cj)gqeIe!v=OX896#mg6PC?x2xO(maww z=FZ^?@0`nFi$>N&n6-)gH+VpcL5aewb#L_kI9|s_;h2z7v}JWnklSvSOVzAFS1~g0 zztfnt@VqBcxl<=2IGm1ZS??1`8Ll(g8l(anJw3!b=a^?sW}C4T77Oh+CipT^L}`%1 zh3oGwaSYzC05y@q6@goIypaNo8&X$TCTR+%k=#%932F(HU@6xLxbAgn6YyS((d~$EmvGO;Fd%rSeyY>*PNqdJ2v|X}|ceih5-JkxI z*#BPUBbh1A_4~rYuY=p$S0@D>DKwWiWq~BepX}FN`1V&Js5|VdpQLfJKb6m0%~Wdk zIiT|*0iUN_FQfMvZvqd}VjD~LR@EiXy*Pi(c8m?2pjHhWhx zP*{Iu-Enm^B)mht^(3^i>3WAD?*;iHNL8BAWN56H=C3a8tIG+%KMx+LR%e_pZl~_Y^ zmf)Fm^)E0voK6lr__>oG*QC{Lkk<>zQR&1Croa7Akfid*JvHz7FNb5}K&gSWjv_=i zq3U7lt*7id;rqBEwH05DuL~i{0Uc`ny`)l&ULHb)KOfUEb-Zt0r$Rg{0j4x2JnX+d z_tjTKCj!D^Xr&bkT}CQ&iDZ0q62qBG7hi+>a|&)wJfcc^{vw@8S5_?@B7)9wnK`>N zyzw$3n896q%3JmbR8B*~!^8SOxqk(tI8%#w6dZHCA7jx!rl_kdgo0U?-}-<|fSw52 zm8m!UZge@I=`ZUI$63hpl(8kE&_aV;=b%3w(dD9Rk6MuVFP1@by;rX%R<|4-Iuc%k z>Q=pGB$=+MXnVlZaf{7$z5UPlXo<;EX3BZiE3ET^>szQ8E}mj|j*_Y>ZE5YuX%Z+4 zs^|&Z$>zI0Q5``))y(KdoEeiRN%LK~g5p<$-WEFrfE@w=;~{pyYH)vYYlqs zP5ROi&+%Ucyd;0+@<~8+ThOiE@xusD>-7tU&{~2jJW$Kfl*#vh-bI@3OQgZcA}|h* zX;{%^LwbuH|AG8;iCZDLdv)Q1p_5o>bj*}L8~5zrn6-64qD3vX02EN@AgOp{-)(dO zhP}!hdf1w5>3b!%70%e66_9CFrau{B_^w#ZAc*BEI@oJL>VCE`6>Rw{OO{z$Br_i zDz%@JAxbG|`^^TB#sewYcRgE+WZC^Jxr6`}=!D`{75z*YBG>hyV_#B|?;wb0<`bT>4JeF{q(b-?*%L z<~#1}y%qj)^mH~~2M8wcXggf_L*Y1B^p@kL zvR-gtIgi&YnWfFoYM=ScR^boplP6O>xvpj{_QLp|s54T5BEc~n6%Xm<;tdvILsj$`&m~sIxEz7?zEoy@-JRN!d9B$AP6d^ z^`xUObZV>rMqWAmJSF)9Xr^@ptl5dYAkThT5L^mb-<_$T`tjq(-*85_%b%flA>Hv@ zI69G&MVU+eFHMOfx(Q8>#%(vyzw`zTZv$Um_}A**Keu~(PwR5b_KKGzfmuyOqGH@o(v90@=2Gl2mW+s+Z!`p)H;%h}yj?y# zy1n~JlFcEOJUVno1`t?q;v1tU?6;b(s~WvF-u&?sJJVM74`z`DPWXUd1`sLGpK_V^z_yO5e=h+uwDxVEWlc#%={#tE|{^?Im z7n^lqX6uesy6Zw2pZIDjPSxH3{kIi~78ZLcZ-BZzu1qSLnT&Km|b8bMlHE!JMB zkGO8%6*CFq89(yVJB1X(6KeUGV%q1HmzNg+j1g<$?lt+7dj(T|$WrCJeHk>Q`OO zFg<-+^zJcA_#6UwipYvqDY~DYj<~YV5>=_N$XMNEe_n1n?A(3?h+89`8x4I10V)&B z`UCqN&|u4!${_F4w4Vz49B!u0$^c@H^6nSHh}`JJSrCP2F?&x2mi1A`wqCiGc z{d-Nn-xddkp81WQly+~-9pKzL3H%VQ!cP5e4I&;ZSLS%G*+aQ!O5-C^B*!0CAcER1 zXPd92Tsyc0fr!#*0{OH3Xsp#Hz(=TXJh~w%8fC?*yybsoLZ__;Z$-Ji zQ-m_g#w@4J-^hc4j=-5hHtTwn&Q4B+c0G|6ZGNzPG`OJ4b*i|NY~`(=fS=qke;JTR zr_5aGIP;$Nhv`>p-z&DbfmBs4LK(qh*RoK|UOBYQFCS+_F#r5KAmDI`+PcMS{H!4i zvlkafO!Mt`;!ngEL$*mrRu;Bt?)5y_oY^x$9oMuBvou|Jt(Q35W&ERLC{1(Fv2EX3 z+kbEISefp_if8bt8L+8?%5RHIRsDnu)AA}!zkEdSv`iQqtQRFmmZ`s41zu;hMH3N> zcrq#!iDGZwx394A37nGS8&PW*tx^8Q;bY<9TlP1Z%{)s|vjA&n3Jp9Vlk@p~{6~Z) zJ($4CoX2WCm$)2D^mR4665EJSz7k7xcf_q4H5tTun4GNc(7ui#<ZRIFbWbqoJXu>uzoyNY?=jq+`AU+?H;LgH6cR2bUL z|HC4k50+b)MsOQRHZB7;Svo!HEpC;#84AtHHc{^*)PEuS16S%eyj z?W00OyHGx_aaq4Wapu-FW`NrOQUBfsA*&yjkn@zwNsgaF%3z<UEzI4`o(DWlhvM*sz{X4A1eJMP6LXl{oX?5VgR+;hBI73$P<#ZxFK} zdD^I&>%Zc|>jxp!6X81(R)1Tv1nY<4BsQbRkrY#~Ml$4inn+^~RkaMhZAsnTZS+G2 z`#A$@xHbT)1R=k9_fcALR>Z#vU$tH1X0L8jcaA8Lx>5kz&6!y7NbFoiWczR>+eHou3g8!6$N2xN5CHy&eJ literal 0 HcmV?d00001 diff --git a/stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index a2ec33f19f..96d3fee1a2 100644 --- a/stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,68 +1,68 @@ { - "images" : [ - { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_16.png", - "scale" : "1x" + "info": { + "version": 1, + "author": "xcode" }, - { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "2x" - }, - { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "1x" - }, - { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_64.png", - "scale" : "2x" - }, - { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_128.png", - "scale" : "1x" - }, - { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "2x" - }, - { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "1x" - }, - { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "2x" - }, - { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "1x" - }, - { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_1024.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} + "images": [ + { + "size": "16x16", + "idiom": "mac", + "filename": "app_icon_16.png", + "scale": "1x" + }, + { + "size": "16x16", + "idiom": "mac", + "filename": "app_icon_32.png", + "scale": "2x" + }, + { + "size": "32x32", + "idiom": "mac", + "filename": "app_icon_32.png", + "scale": "1x" + }, + { + "size": "32x32", + "idiom": "mac", + "filename": "app_icon_64.png", + "scale": "2x" + }, + { + "size": "128x128", + "idiom": "mac", + "filename": "app_icon_128.png", + "scale": "1x" + }, + { + "size": "128x128", + "idiom": "mac", + "filename": "app_icon_256.png", + "scale": "2x" + }, + { + "size": "256x256", + "idiom": "mac", + "filename": "app_icon_256.png", + "scale": "1x" + }, + { + "size": "256x256", + "idiom": "mac", + "filename": "app_icon_512.png", + "scale": "2x" + }, + { + "size": "512x512", + "idiom": "mac", + "filename": "app_icon_512.png", + "scale": "1x" + }, + { + "size": "512x512", + "idiom": "mac", + "filename": "app_icon_1024.png", + "scale": "2x" + } + ] +} \ No newline at end of file diff --git a/stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png index 3c4935a7ca84f0976aca34b7f2895d65fb94d1ea..6286cc9f763187f78f678193a66633449b2b2484 100644 GIT binary patch literal 52126 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 NeyIK+|DM^q{{wI=gKz)< literal 46993 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 diff --git a/stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png index ed4cc16421680a50164ba74381b4b35ceaa0ccfc..c8b042eda520e127e229b2451d68f3d7785b3f52 100644 GIT binary patch literal 5468 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 N;OXk;vd$@?2>?>Ex^Vyi diff --git a/stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/stream_chat_v1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png index bcbf36df2f2aaaa0a63c7dabc94e600184229d0d..1003e61babdaf9d49c1978707fc750ba97592b27 100644 GIT binary patch literal 11508 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 literal 5933 zcmZ{Idpwix|Np(&m_yAF>K&UIn{t*2ZOdsShYs(MibU!|=pZCJq~7E>B$QJr)hC5| zmk?V?ES039lQ~RC!kjkl-TU4?|NZ{>J$CPLUH9vHy`Hbhhnc~SD_vpzBp6Xw4`$%jfmPw(;etLCccvfU-s)1A zLl8-RiSx!#?Kwzd0E&>h;Fc z^;S84cUH7gMe#2}MHYcDXgbkI+Qh^X4BV~6y<@s`gMSNX!4@g8?ojjj5hZj5X4g9D zavr_NoeZ=4vim%!Y`GnF-?2_Gb)g$xAo>#zCOLB-jPww8a%c|r&DC=eVdE;y+HwH@ zy`JK(oq+Yw^-hLvWO4B8orWwLiKT!hX!?xw`kz%INd5f)>k1PZ`ZfM&&Ngw)HiXA| ze=+%KkiLe1hd>h!ZO2O$45alH0O|E+>G2oCiJ|3y2c$;XedBozx93BprOr$#d{W5sb*hQQ~M@+v_m!8s?9+{Q0adM?ip3qQ*P5$R~dFvP+5KOH_^A+l-qu5flE*KLJp!rtjqTVqJsmpc1 zo>T>*ja-V&ma7)K?CE9RTsKQKk7lhx$L`9d6-Gq`_zKDa6*>csToQ{&0rWf$mD7x~S3{oA z1wUZl&^{qbX>y*T71~3NWd1Wfgjg)<~BnK96Ro#om&~8mU{}D!Fu# zTrKKSM8gY^*47b2Vr|ZZe&m9Y`n+Y8lHvtlBbIjNl3pGxU{!#Crl5RPIO~!L5Y({ym~8%Ox-9g>IW8 zSz2G6D#F|L^lcotrZx4cFdfw6f){tqITj6>HSW&ijlgTJTGbc7Q#=)*Be0-s0$fCk z^YaG;7Q1dfJq#p|EJ~YYmqjs`M0jPl=E`Id{+h%Lo*|8xp6K7yfgjqiH7{61$4x~A zNnH+65?QCtL;_w(|mDNJXybin=rOy-i7A@lXEu z&jY(5jhjlP{TsjMe$*b^2kp8LeAXu~*q&5;|3v|4w4Ij_4c{4GG8={;=K#lh{#C8v z&t9d7bf{@9aUaE94V~4wtQ|LMT*Ruuu0Ndjj*vh2pWW@|KeeXi(vt!YXi~I6?r5PG z$_{M*wrccE6x42nPaJUO#tBu$l#MInrZhej_Tqki{;BT0VZeb$Ba%;>L!##cvieb2 zwn(_+o!zhMk@l~$$}hivyebloEnNQmOy6biopy`GL?=hN&2)hsA0@fj=A^uEv~TFE z<|ZJIWplBEmufYI)<>IXMv(c+I^y6qBthESbAnk?0N(PI>4{ASayV1ErZ&dsM4Z@E-)F&V0>tIF+Oubl zin^4Qx@`Un4kRiPq+LX5{4*+twI#F~PE7g{FpJ`{)K()FH+VG^>)C-VgK>S=PH!m^ zE$+Cfz!Ja`s^Vo(fd&+U{W|K$e(|{YG;^9{D|UdadmUW;j;&V!rU)W_@kqQj*Frp~ z7=kRxk)d1$$38B03-E_|v=<*~p3>)2w*eXo(vk%HCXeT5lf_Z+D}(Uju=(WdZ4xa( zg>98lC^Z_`s-=ra9ZC^lAF?rIvQZpAMz8-#EgX;`lc6*53ckpxG}(pJp~0XBd9?RP zq!J-f`h0dC*nWxKUh~8YqN{SjiJ6vLBkMRo?;|eA(I!akhGm^}JXoL_sHYkGEQWWf zTR_u*Ga~Y!hUuqb`h|`DS-T)yCiF#s<KR}hC~F%m)?xjzj6w#Za%~XsXFS@P0E3t*qs)tR43%!OUxs(|FTR4Sjz(N zppN>{Ip2l3esk9rtB#+To92s~*WGK`G+ECt6D>Bvm|0`>Img`jUr$r@##&!1Ud{r| zgC@cPkNL_na`74%fIk)NaP-0UGq`|9gB}oHRoRU7U>Uqe!U61fY7*Nj(JiFa-B7Av z;VNDv7Xx&CTwh(C2ZT{ot`!E~1i1kK;VtIh?;a1iLWifv8121n6X!{C%kw|h-Z8_U z9Y8M38M2QG^=h+dW*$CJFmuVcrvD*0hbFOD=~wU?C5VqNiIgAs#4axofE*WFYd|K;Et18?xaI|v-0hN#D#7j z5I{XH)+v0)ZYF=-qloGQ>!)q_2S(Lg3<=UsLn%O)V-mhI-nc_cJZu(QWRY)*1il%n zOR5Kdi)zL-5w~lOixilSSF9YQ29*H+Br2*T2lJ?aSLKBwv7}*ZfICEb$t>z&A+O3C z^@_rpf0S7MO<3?73G5{LWrDWfhy-c7%M}E>0!Q(Iu71MYB(|gk$2`jH?!>ND0?xZu z1V|&*VsEG9U zm)!4#oTcgOO6Hqt3^vcHx>n}%pyf|NSNyTZX*f+TODT`F%IyvCpY?BGELP#s<|D{U z9lUTj%P6>^0Y$fvIdSj5*=&VVMy&nms=!=2y<5DP8x;Z13#YXf7}G)sc$_TQQ=4BD zQ1Le^y+BwHl7T6)`Q&9H&A2fJ@IPa;On5n!VNqWUiA*XXOnvoSjEIKW<$V~1?#zts>enlSTQaG2A|Ck4WkZWQoeOu(te znV;souKbA2W=)YWldqW@fV^$6EuB`lFmXYm%WqI}X?I1I7(mQ8U-pm+Ya* z|7o6wac&1>GuQfIvzU7YHIz_|V;J*CMLJolXMx^9CI;I+{Nph?sf2pX@%OKT;N@Uz9Y zzuNq11Ccdwtr(TDLx}N!>?weLLkv~i!xfI0HGWff*!12E*?7QzzZT%TX{5b7{8^*A z3ut^C4uxSDf=~t4wZ%L%gO_WS7SR4Ok7hJ;tvZ9QBfVE%2)6hE>xu9y*2%X5y%g$8 z*8&(XxwN?dO?2b4VSa@On~5A?zZZ{^s3rXm54Cfi-%4hBFSk|zY9u(3d1ButJuZ1@ zfOHtpSt)uJnL`zg9bBvUkjbPO0xNr{^{h0~$I$XQzel_OIEkgT5L!dW1uSnKsEMVp z9t^dfkxq=BneR9`%b#nWSdj)u1G=Ehv0$L@xe_eG$Ac%f7 zy`*X(p0r3FdCTa1AX^BtmPJNR4%S1nyu-AM-8)~t-KII9GEJU)W^ng7C@3%&3lj$2 z4niLa8)fJ2g>%`;;!re+Vh{3V^}9osx@pH8>b0#d8p`Dgm{I?y@dUJ4QcSB<+FAuT)O9gMlwrERIy z6)DFLaEhJkQ7S4^Qr!JA6*SYni$THFtE)0@%!vAw%X7y~!#k0?-|&6VIpFY9>5GhK zr;nM-Z`Omh>1>7;&?VC5JQoKi<`!BU_&GLzR%92V$kMohNpMDB=&NzMB&w-^SF~_# zNsTca>J{Y555+z|IT75yW;wi5A1Z zyzv|4l|xZ-Oy8r8_c8X)h%|a8#(oWcgS5P6gtuCA_vA!t=)IFTL{nnh8iW!B$i=Kd zj1ILrL;ht_4aRKF(l1%^dUyVxgK!2QsL)-{x$`q5wWjjN6B!Cj)jB=bii;9&Ee-;< zJfVk(8EOrbM&5mUciP49{Z43|TLoE#j(nQN_MaKt16dp#T6jF7z?^5*KwoT-Y`rs$ z?}8)#5Dg-Rx!PTa2R5; zx0zhW{BOpx_wKPlTu;4ev-0dUwp;g3qqIi|UMC@A?zEb3RXY`z_}gbwju zzlNht0WR%g@R5CVvg#+fb)o!I*Zpe?{_+oGq*wOmCWQ=(Ra-Q9mx#6SsqWAp*-Jzb zKvuPthpH(Fn_k>2XPu!=+C{vZsF8<9p!T}U+ICbNtO}IAqxa57*L&T>M6I0ogt&l> z^3k#b#S1--$byAaU&sZL$6(6mrf)OqZXpUPbVW%T|4T}20q9SQ&;3?oRz6rSDP4`b z(}J^?+mzbp>MQDD{ziSS0K(2^V4_anz9JV|Y_5{kF3spgW%EO6JpJ(rnnIN%;xkKf zn~;I&OGHKII3ZQ&?sHlEy)jqCyfeusjPMo7sLVr~??NAknqCbuDmo+7tp8vrKykMb z(y`R)pVp}ZgTErmi+z`UyQU*G5stQRsx*J^XW}LHi_af?(bJ8DPho0b)^PT|(`_A$ zFCYCCF={BknK&KYTAVaHE{lqJs4g6B@O&^5oTPLkmqAB#T#m!l9?wz!C}#a6w)Z~Z z6jx{dsXhI(|D)x%Yu49%ioD-~4}+hCA8Q;w_A$79%n+X84jbf?Nh?kRNRzyAi{_oV zU)LqH-yRdPxp;>vBAWqH4E z(WL)}-rb<_R^B~fI%ddj?Qxhp^5_~)6-aB`D~Nd$S`LY_O&&Fme>Id)+iI>%9V-68 z3crl=15^%0qA~}ksw@^dpZ`p;m=ury;-OV63*;zQyRs4?1?8lbUL!bR+C~2Zz1O+E@6ZQW!wvv z|NLqSP0^*J2Twq@yws%~V0^h05B8BMNHv_ZZT+=d%T#i{faiqN+ut5Bc`uQPM zgO+b1uj;)i!N94RJ>5RjTNXN{gAZel|L8S4r!NT{7)_=|`}D~ElU#2er}8~UE$Q>g zZryBhOd|J-U72{1q;Lb!^3mf+H$x6(hJHn$ZJRqCp^In_PD+>6KWnCnCXA35(}g!X z;3YI1luR&*1IvESL~*aF8(?4deU`9!cxB{8IO?PpZ{O5&uY<0DIERh2wEoAP@bayv z#$WTjR*$bN8^~AGZu+85uHo&AulFjmh*pupai?o?+>rZ7@@Xk4muI}ZqH`n&<@_Vn zvT!GF-_Ngd$B7kLge~&3qC;TE=tEid(nQB*qzXI0m46ma*2d(Sd*M%@Zc{kCFcs;1 zky%U)Pyg3wm_g12J`lS4n+Sg=L)-Y`bU705E5wk&zVEZw`eM#~AHHW96@D>bz#7?- zV`xlac^e`Zh_O+B5-kO=$04{<cKUG?R&#bnF}-?4(Jq+?Ph!9g zx@s~F)Uwub>Ratv&v85!6}3{n$bYb+p!w(l8Na6cSyEx#{r7>^YvIj8L?c*{mcB^x zqnv*lu-B1ORFtrmhfe}$I8~h*3!Ys%FNQv!P2tA^wjbH f$KZHO*s&vt|9^w-6P?|#0pRK8n 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 literal 14800 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 diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index cfc14b8d6f..9ce8c22e61 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -32,7 +32,7 @@ dependencies: yaml: ^3.1.0 uuid: ^3.0.5 streaming_shared_preferences: ^2.0.0 - lottie: ^2.0.0 + lottie: ^2.3.2 collection: ^1.15.0 sentry_flutter: ^6.5.0 flutter_slidable: ^2.0.0 @@ -40,8 +40,7 @@ dependencies: provider: ^6.0.3 dev_dependencies: - flutter_launcher_icons: ^0.9.2 - test: any + flutter_launcher_icons: ^0.12.0 flutter_lints: ^2.0.0 dependency_overrides: @@ -62,13 +61,20 @@ dependency_overrides: path: packages/stream_chat_flutter flutter: + uses-material-design: true assets: - assets/ - - pubspec.lock - uses-material-design: true flutter_icons: + image_path: "assets/ic_launcher.png" + android: true + adaptive_icon_background: "assets/ic_launcher_background.png" + adaptive_icon_foreground: "assets/ic_launcher_foreground.png" ios: true - image_path_android: "assets/android_icon.png" - image_path_ios: "assets/ios_icon.png" + web: + generate: true + windows: + generate: true + macos: + generate: true diff --git a/stream_chat_v1/web/favicon.png b/stream_chat_v1/web/favicon.png index 8aaa46ac1ae21512746f852a42ba87e4165dfdd1..bc3b6c570989759098b92914fbb3299a177f4b1e 100644 GIT binary patch delta 451 zcmV;!0X+Vd2iyaYBYy#-Nkl$*!Qv?+eBMxS1gD%F_s>!?e^}eSdrc{tj zUbr02xtx#lec!p}^WHx$1st=G=0^aaYu8cUqtZP9E<@b`41XQ^N3$x^{tsXUpf#v- zdJdU$*N?B7O?FcfP4)G66!CRM@U#TVOEf<&Y)LM%HvoBokR2d9?%jLVE`KV8d?^Z9fo+l6r zg-9e4M59qEtE&ClKQ?;YJQwoM@SMZPSQp7;l5{%F_dK63_;vAsO`P74%AqS7?RR|H tlPqrK{D~j5%G*b-y3S2@y;ueRg}(`ikeOe+5|97@002ovPDHLkV1iu0*9ias literal 917 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|I14-?iy0X7 zltGxWVyS%@P(fs7NJL45ua8x7ey(0(N`6wRUPW#JP&EUCO@$SZnVVXYs8ErclUHn2 zVXFjIVFhG^g!Ppaz)DK8ZIvQ?0~DO|i&7O#^-S~(l1AfjnEK zjFOT9D}DX)@^Za$W4-*MbbUihOG|wNBYh(yU7!lx;>x^|#0uTKVr7USFmqf|i<65o z3raHc^AtelCMM;Vme?vOfh>Xph&xL%(-1c06+^uR^q@XSM&D4+Kp$>4P^%3{)XKjo zGZknv$b36P8?Z_gF{nK@`XI}Z90TzwSQO}0J1!f2c(B=V`5aP@1P1a|PZ!4!3&Gl8 zTYqUsf!gYFyJnXpu0!n&N*SYAX-%d(5gVjrHJWqXQshj@!Zm{!01WsQrH~9=kTxW#6SvuapgMqt>$=j#%eyGrQzr zP{L-3gsMA^$I1&gsBAEL+vxi1*Igl=8#8`5?A-T5=z-sk46WA1IUT)AIZHx1rdUrf zVJrJn<74DDw`j)Ki#gt}mIT-Q`XRa2-jQXQoI%w`nb|XblvzK${ZzlV)m-XcwC(od z71_OEC5Bt9GEXosOXaPTYOia#R4ID2TiU~`zVMl08TV_C%DnU4^+HE>9(CE4D6?Fz oujB08i7adh9xk7*FX66dWH6F5TM;?E2b5PlUHx3vIVCg!0Dx9vYXATM diff --git a/stream_chat_v1/web/icons/Icon-192.png b/stream_chat_v1/web/icons/Icon-192.png index b749bfef07473333cf1dd31e9eed89862a5d52aa..dd30e06e2861798f277a9e4e444417f0f444e3f4 100644 GIT binary patch literal 8762 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