From e3a415d88bde4366b679d8c8be3c3dedb70445f4 Mon Sep 17 00:00:00 2001 From: codeme5 Date: Wed, 21 Aug 2024 10:45:59 +0500 Subject: [PATCH 1/2] added the update details screen and the profile screen along with client side logic fro Stream login, logout and delete --- .flutter-plugins-dependencies | 1 + functions/.gitignore | 7 + functions/index.js | 99 ++ images/Generic Image.png | Bin 0 -> 55797 bytes ios/Podfile.lock | 1351 +++++++++++++++++ ios/Runner.xcodeproj/project.pbxproj | 105 ++ .../xcshareddata/WorkspaceSettings.xcsettings | 4 + lib/constants.dart | 229 +++ lib/helpers/channel_info.dart | 58 + lib/helpers/helpers.dart | 3 + lib/main.dart | 74 + lib/screens/home_pages/contacts.dart | 124 ++ lib/screens/home_pages/messages.dart | 298 ++++ lib/screens/home_screen.dart | 237 +++ lib/screens/login_screen.dart | 176 ++- lib/screens/profile_screen.dart | 299 ++++ lib/screens/registration_screen.dart | 132 ++ lib/screens/update_details_screen.dart | 177 +++ lib/screens/verification_screen.dart | 88 ++ lib/screens/welcome_screen.dart | 103 ++ lib/services/otherSignIn.dart | 31 + lib/theme.dart | 59 + lib/widgets/avatar.dart | 34 + pubspec.lock | 511 +++++++ pubspec.yaml | 23 + test/widget_test.dart | 32 + 26 files changed, 4254 insertions(+), 1 deletion(-) create mode 100644 .flutter-plugins-dependencies create mode 100644 functions/.gitignore create mode 100644 functions/index.js create mode 100644 images/Generic Image.png create mode 100644 ios/Podfile.lock create mode 100644 lib/helpers/channel_info.dart create mode 100644 lib/helpers/helpers.dart create mode 100644 lib/screens/home_pages/contacts.dart create mode 100644 lib/screens/home_pages/messages.dart create mode 100644 lib/screens/home_screen.dart create mode 100644 lib/screens/profile_screen.dart create mode 100644 lib/screens/update_details_screen.dart create mode 100644 lib/screens/verification_screen.dart create mode 100644 lib/services/otherSignIn.dart create mode 100644 lib/theme.dart create mode 100644 lib/widgets/avatar.dart create mode 100644 test/widget_test.dart diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies new file mode 100644 index 0000000000..8c3cd86a28 --- /dev/null +++ b/.flutter-plugins-dependencies @@ -0,0 +1 @@ +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"cloud_firestore","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/cloud_firestore-5.2.1/","native_build":true,"dependencies":["firebase_core"]},{"name":"cloud_functions","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/cloud_functions-5.0.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"connectivity_plus","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/connectivity_plus-6.0.4/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"firebase_auth","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_auth-5.1.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_core","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_core-3.3.0/","native_build":true,"dependencies":[]},{"name":"firebase_database","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_database-11.0.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_messaging","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_messaging-15.0.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_storage","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_storage-12.1.3/","native_build":true,"dependencies":["firebase_core"]},{"name":"google_sign_in_ios","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/google_sign_in_ios-5.7.6/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"image_picker_ios","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/image_picker_ios-0.8.12/","native_build":true,"dependencies":[]},{"name":"path_provider_foundation","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.0/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"sqflite","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/sqflite-2.3.3+1/","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"android":[{"name":"cloud_firestore","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/cloud_firestore-5.2.1/","native_build":true,"dependencies":["firebase_core"]},{"name":"cloud_functions","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/cloud_functions-5.0.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"connectivity_plus","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/connectivity_plus-6.0.4/","native_build":true,"dependencies":[]},{"name":"firebase_auth","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_auth-5.1.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_core","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_core-3.3.0/","native_build":true,"dependencies":[]},{"name":"firebase_database","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_database-11.0.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_messaging","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_messaging-15.0.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_storage","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_storage-12.1.3/","native_build":true,"dependencies":["firebase_core"]},{"name":"flutter_plugin_android_lifecycle","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/flutter_plugin_android_lifecycle-2.0.21/","native_build":true,"dependencies":[]},{"name":"google_sign_in_android","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/google_sign_in_android-6.1.28/","native_build":true,"dependencies":[]},{"name":"image_picker_android","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/image_picker_android-0.8.12+11/","native_build":true,"dependencies":["flutter_plugin_android_lifecycle"]},{"name":"path_provider_android","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/path_provider_android-2.2.9/","native_build":true,"dependencies":[]},{"name":"sqflite","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/sqflite-2.3.3+1/","native_build":true,"dependencies":[]}],"macos":[{"name":"cloud_firestore","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/cloud_firestore-5.2.1/","native_build":true,"dependencies":["firebase_core"]},{"name":"cloud_functions","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/cloud_functions-5.0.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"connectivity_plus","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/connectivity_plus-6.0.4/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"file_selector_macos","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/file_selector_macos-0.9.4/","native_build":true,"dependencies":[]},{"name":"firebase_auth","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_auth-5.1.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_core","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_core-3.3.0/","native_build":true,"dependencies":[]},{"name":"firebase_database","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_database-11.0.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_messaging","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_messaging-15.0.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_storage","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_storage-12.1.3/","native_build":true,"dependencies":["firebase_core"]},{"name":"google_sign_in_ios","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/google_sign_in_ios-5.7.6/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"image_picker_macos","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/image_picker_macos-0.2.1+1/","native_build":false,"dependencies":["file_selector_macos"]},{"name":"path_provider_foundation","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.0/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"sqflite","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/sqflite-2.3.3+1/","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"linux":[{"name":"connectivity_plus","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/connectivity_plus-6.0.4/","native_build":false,"dependencies":[]},{"name":"file_selector_linux","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/file_selector_linux-0.9.2+1/","native_build":true,"dependencies":[]},{"name":"image_picker_linux","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/image_picker_linux-0.2.1+1/","native_build":false,"dependencies":["file_selector_linux"]},{"name":"path_provider_linux","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/","native_build":false,"dependencies":[]}],"windows":[{"name":"cloud_firestore","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/cloud_firestore-5.2.1/","native_build":true,"dependencies":["firebase_core"]},{"name":"connectivity_plus","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/connectivity_plus-6.0.4/","native_build":true,"dependencies":[]},{"name":"file_selector_windows","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/file_selector_windows-0.9.3+2/","native_build":true,"dependencies":[]},{"name":"firebase_auth","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_auth-5.1.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_core","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_core-3.3.0/","native_build":true,"dependencies":[]},{"name":"firebase_storage","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_storage-12.1.3/","native_build":true,"dependencies":["firebase_core"]},{"name":"image_picker_windows","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/image_picker_windows-0.2.1+1/","native_build":false,"dependencies":["file_selector_windows"]},{"name":"path_provider_windows","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/","native_build":false,"dependencies":[]}],"web":[{"name":"cloud_firestore_web","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/cloud_firestore_web-4.1.1/","dependencies":["firebase_core_web"]},{"name":"cloud_functions_web","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/cloud_functions_web-4.9.11/","dependencies":["firebase_core_web"]},{"name":"connectivity_plus","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/connectivity_plus-6.0.4/","dependencies":[]},{"name":"firebase_auth_web","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_auth_web-5.12.5/","dependencies":["firebase_core_web"]},{"name":"firebase_core_web","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_core_web-2.17.4/","dependencies":[]},{"name":"firebase_database_web","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_database_web-0.2.5+12/","dependencies":["firebase_core_web"]},{"name":"firebase_messaging_web","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_messaging_web-3.8.12/","dependencies":["firebase_core_web"]},{"name":"firebase_storage_web","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_storage_web-3.9.12/","dependencies":["firebase_core_web"]},{"name":"google_sign_in_web","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/google_sign_in_web-0.12.4+2/","dependencies":[]},{"name":"image_picker_for_web","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/image_picker_for_web-3.0.5/","dependencies":[]}]},"dependencyGraph":[{"name":"cloud_firestore","dependencies":["cloud_firestore_web","firebase_core"]},{"name":"cloud_firestore_web","dependencies":["firebase_core","firebase_core_web"]},{"name":"cloud_functions","dependencies":["cloud_functions_web","firebase_core"]},{"name":"cloud_functions_web","dependencies":["firebase_core","firebase_core_web"]},{"name":"connectivity_plus","dependencies":[]},{"name":"file_selector_linux","dependencies":[]},{"name":"file_selector_macos","dependencies":[]},{"name":"file_selector_windows","dependencies":[]},{"name":"firebase_auth","dependencies":["firebase_auth_web","firebase_core"]},{"name":"firebase_auth_web","dependencies":["firebase_core","firebase_core_web"]},{"name":"firebase_core","dependencies":["firebase_core_web"]},{"name":"firebase_core_web","dependencies":[]},{"name":"firebase_database","dependencies":["firebase_core","firebase_database_web"]},{"name":"firebase_database_web","dependencies":["firebase_core","firebase_core_web"]},{"name":"firebase_messaging","dependencies":["firebase_core","firebase_messaging_web"]},{"name":"firebase_messaging_web","dependencies":["firebase_core","firebase_core_web"]},{"name":"firebase_storage","dependencies":["firebase_core","firebase_storage_web"]},{"name":"firebase_storage_web","dependencies":["firebase_core","firebase_core_web"]},{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"google_sign_in","dependencies":["google_sign_in_android","google_sign_in_ios","google_sign_in_web"]},{"name":"google_sign_in_android","dependencies":[]},{"name":"google_sign_in_ios","dependencies":[]},{"name":"google_sign_in_web","dependencies":[]},{"name":"image_picker","dependencies":["image_picker_android","image_picker_for_web","image_picker_ios","image_picker_linux","image_picker_macos","image_picker_windows"]},{"name":"image_picker_android","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"image_picker_for_web","dependencies":[]},{"name":"image_picker_ios","dependencies":[]},{"name":"image_picker_linux","dependencies":["file_selector_linux"]},{"name":"image_picker_macos","dependencies":["file_selector_macos"]},{"name":"image_picker_windows","dependencies":["file_selector_windows"]},{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"sqflite","dependencies":[]}],"date_created":"2024-08-21 10:45:10.665798","version":"3.22.2"} \ No newline at end of file diff --git a/functions/.gitignore b/functions/.gitignore new file mode 100644 index 0000000000..0654b65a83 --- /dev/null +++ b/functions/.gitignore @@ -0,0 +1,7 @@ +.env +node_modules/ +<<<<<<< Updated upstream +*.local +======= +*.local +>>>>>>> Stashed changes diff --git a/functions/index.js b/functions/index.js new file mode 100644 index 0000000000..d0762c33ea --- /dev/null +++ b/functions/index.js @@ -0,0 +1,99 @@ +/** + * Import function triggers from their respective submodules: + * + * const {onCall} = require("firebase-functions/v2/https"); + * const {onDocumentWritten} = require("firebase-functions/v2/firestore"); + * + * See a full list of supported triggers at https://firebase.google.com/docs/functions + */ + + +if (process.env.NODE_ENV !== 'production') { + require('dotenv').config(); +} +const StreamChat = require('stream-chat').StreamChat; +const functions = require("firebase-functions"); +const admin = require("firebase-admin"); + +admin.initializeApp(); + +const serverClient = StreamChat.getInstance(process.env.STREAM_KEY, process.env.STREAM_SECRET); + + +// When a user is deleted from Firebase their associated Stream account is also deleted. +exports.deleteStreamUser = functions.auth.user().onDelete((user, context) => { + console.log(user.uid); + return serverClient.deleteUser(user.uid); +}); + +// Create a Stream user and return auth token. +exports.createStreamUserAndGetToken = functions.https.onCall(async (data, context) => { + // Checking that the user is authenticated. + if (!context.auth) { + // Throwing an HttpsError so that the client gets the error details. + throw new functions.https.HttpsError('failed-precondition', 'The function must be called ' + + 'while authenticated.'); + } else { + try { + // Create user using the serverClient. + await serverClient.upsertUser({ + id: context.auth.uid, + name: context.auth.token.name, + email: context.auth.token.email, + image: context.auth.token.picture, + }); + + /// Create and return user auth token. + return serverClient.createToken(context.auth.uid); + } catch (err) { + console.error(`Unable to create user with ID ${context.auth.uid} on Stream. Error ${err}`); + // Throwing an HttpsError so that the client gets the error details. + throw new functions.https.HttpsError('aborted', "Could not create Stream user"); + } + } +}); + +// Get Stream user token. +exports.getStreamUserToken = functions.https.onCall((data, context) => { + // Checking that the user is authenticated. + if (!context.auth) { + // Throwing an HttpsError so that the client gets the error details. + throw new functions.https.HttpsError('failed-precondition', 'The function must be called ' + + 'while authenticated.'); + } else { + try { + return serverClient.createToken(context.auth.uid); + } catch (err) { + console.error(`Unable to get user token with ID ${context.auth.uid} on Stream. Error ${err}`); + // Throwing an HttpsError so that the client gets the error details. + throw new functions.https.HttpsError('aborted', "Could not get Stream user"); + } + } +}); + +// Revoke the authenticated user's Stream chat token. +exports.revokeStreamUserToken = functions.https.onCall((data, context) => { + // Checking that the user is authenticated. + if (!context.auth) { + // Throwing an HttpsError so that the client gets the error details. + throw new functions.https.HttpsError('failed-precondition', 'The function must be called ' + + 'while authenticated.'); + } else { + try { + return serverClient.revokeUserToken(context.auth.uid); + } catch (err) { + console.error(`Unable to revoke user token with ID ${context.auth.uid} on Stream. Error ${err}`); + // Throwing an HttpsError so that the client gets the error details. + throw new functions.https.HttpsError('aborted', "Could not get Stream user"); + } + } +}); + + +// Create and deploy your first functions +// https://firebase.google.com/docs/functions/get-started + +// exports.helloWorld = onRequest((request, response) => { +// logger.info("Hello logs!", {structuredData: true}); +// response.send("Hello from Firebase!"); +// }); diff --git a/images/Generic Image.png b/images/Generic Image.png new file mode 100644 index 0000000000000000000000000000000000000000..c6d3028af099f1e3efd96f4194f1afdac757c0a4 GIT binary patch literal 55797 zcmY&AcRbbI|L0!UR=H%BTqClgkfOLrTxBIGN-4=~+pAAQDeDr7!Y#8TGO|Z9ij1tX zqCwfEMCR}Pxt{MIKd;yGJok0aIq$vCxzBAg6N6P;qFe}}RfaS@bA;IF_&*$M@QtgK z*em!C=LMS8WrVo-@P7!ceE|yyQIMhDZVRu6V|^~JHs52#=j!qlZ@+Xjca!Rhlx&R= zt25r(>r^0n-GuvMi(G139$m8$#T#u7dy!QmQ_(( zMgOSB#NSC4gm`WsPJ{~6v~K9wUr@aqzHGDPz59^Ch_&9c>BT^o0@lL?%jYH5B6Pu& zD2ptjM=0+W4#|0QL+}zOqcQq|s+0L9a}~9; zW}cSma@!|A9t3nBD=O#�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 literal 0 HcmV?d00001 diff --git a/ios/Podfile.lock b/ios/Podfile.lock new file mode 100644 index 0000000000..d1540e468b --- /dev/null +++ b/ios/Podfile.lock @@ -0,0 +1,1351 @@ +PODS: + - abseil/algorithm (1.20240116.2): + - abseil/algorithm/algorithm (= 1.20240116.2) + - abseil/algorithm/container (= 1.20240116.2) + - abseil/algorithm/algorithm (1.20240116.2): + - abseil/base/config + - abseil/xcprivacy + - abseil/algorithm/container (1.20240116.2): + - abseil/algorithm/algorithm + - abseil/base/core_headers + - abseil/base/nullability + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/base (1.20240116.2): + - abseil/base/atomic_hook (= 1.20240116.2) + - abseil/base/base (= 1.20240116.2) + - abseil/base/base_internal (= 1.20240116.2) + - abseil/base/config (= 1.20240116.2) + - abseil/base/core_headers (= 1.20240116.2) + - abseil/base/cycleclock_internal (= 1.20240116.2) + - abseil/base/dynamic_annotations (= 1.20240116.2) + - abseil/base/endian (= 1.20240116.2) + - abseil/base/errno_saver (= 1.20240116.2) + - abseil/base/fast_type_id (= 1.20240116.2) + - abseil/base/log_severity (= 1.20240116.2) + - abseil/base/malloc_internal (= 1.20240116.2) + - abseil/base/no_destructor (= 1.20240116.2) + - abseil/base/nullability (= 1.20240116.2) + - abseil/base/prefetch (= 1.20240116.2) + - abseil/base/pretty_function (= 1.20240116.2) + - abseil/base/raw_logging_internal (= 1.20240116.2) + - abseil/base/spinlock_wait (= 1.20240116.2) + - abseil/base/strerror (= 1.20240116.2) + - abseil/base/throw_delegate (= 1.20240116.2) + - abseil/base/atomic_hook (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/xcprivacy + - abseil/base/base (1.20240116.2): + - abseil/base/atomic_hook + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/base/cycleclock_internal + - abseil/base/dynamic_annotations + - abseil/base/log_severity + - abseil/base/nullability + - abseil/base/raw_logging_internal + - abseil/base/spinlock_wait + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/base/base_internal (1.20240116.2): + - abseil/base/config + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/base/config (1.20240116.2): + - abseil/xcprivacy + - abseil/base/core_headers (1.20240116.2): + - abseil/base/config + - abseil/xcprivacy + - abseil/base/cycleclock_internal (1.20240116.2): + - abseil/base/base_internal + - abseil/base/config + - abseil/xcprivacy + - abseil/base/dynamic_annotations (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/xcprivacy + - abseil/base/endian (1.20240116.2): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/nullability + - abseil/xcprivacy + - abseil/base/errno_saver (1.20240116.2): + - abseil/base/config + - abseil/xcprivacy + - abseil/base/fast_type_id (1.20240116.2): + - abseil/base/config + - abseil/xcprivacy + - abseil/base/log_severity (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/xcprivacy + - abseil/base/malloc_internal (1.20240116.2): + - abseil/base/base + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/raw_logging_internal + - abseil/xcprivacy + - abseil/base/no_destructor (1.20240116.2): + - abseil/base/config + - abseil/xcprivacy + - abseil/base/nullability (1.20240116.2): + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/base/prefetch (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/xcprivacy + - abseil/base/pretty_function (1.20240116.2): + - abseil/xcprivacy + - abseil/base/raw_logging_internal (1.20240116.2): + - abseil/base/atomic_hook + - abseil/base/config + - abseil/base/core_headers + - abseil/base/errno_saver + - abseil/base/log_severity + - abseil/xcprivacy + - abseil/base/spinlock_wait (1.20240116.2): + - abseil/base/base_internal + - abseil/base/core_headers + - abseil/base/errno_saver + - abseil/xcprivacy + - abseil/base/strerror (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/errno_saver + - abseil/xcprivacy + - abseil/base/throw_delegate (1.20240116.2): + - abseil/base/config + - abseil/base/raw_logging_internal + - abseil/xcprivacy + - abseil/cleanup/cleanup (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/cleanup/cleanup_internal + - abseil/xcprivacy + - abseil/cleanup/cleanup_internal (1.20240116.2): + - abseil/base/base_internal + - abseil/base/core_headers + - abseil/utility/utility + - abseil/xcprivacy + - abseil/container/common (1.20240116.2): + - abseil/meta/type_traits + - abseil/types/optional + - abseil/xcprivacy + - abseil/container/common_policy_traits (1.20240116.2): + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/container/compressed_tuple (1.20240116.2): + - abseil/utility/utility + - abseil/xcprivacy + - abseil/container/container_memory (1.20240116.2): + - abseil/base/config + - abseil/memory/memory + - abseil/meta/type_traits + - abseil/utility/utility + - abseil/xcprivacy + - abseil/container/fixed_array (1.20240116.2): + - abseil/algorithm/algorithm + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/throw_delegate + - abseil/container/compressed_tuple + - abseil/memory/memory + - abseil/xcprivacy + - abseil/container/flat_hash_map (1.20240116.2): + - abseil/algorithm/container + - abseil/base/core_headers + - abseil/container/container_memory + - abseil/container/hash_function_defaults + - abseil/container/raw_hash_map + - abseil/memory/memory + - abseil/xcprivacy + - abseil/container/flat_hash_set (1.20240116.2): + - abseil/algorithm/container + - abseil/base/core_headers + - abseil/container/container_memory + - abseil/container/hash_function_defaults + - abseil/container/raw_hash_set + - abseil/memory/memory + - abseil/xcprivacy + - abseil/container/hash_function_defaults (1.20240116.2): + - abseil/base/config + - abseil/hash/hash + - abseil/strings/cord + - abseil/strings/strings + - abseil/xcprivacy + - abseil/container/hash_policy_traits (1.20240116.2): + - abseil/container/common_policy_traits + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/container/hashtable_debug_hooks (1.20240116.2): + - abseil/base/config + - abseil/xcprivacy + - abseil/container/hashtablez_sampler (1.20240116.2): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/raw_logging_internal + - abseil/debugging/stacktrace + - abseil/memory/memory + - abseil/profiling/exponential_biased + - abseil/profiling/sample_recorder + - abseil/synchronization/synchronization + - abseil/time/time + - abseil/utility/utility + - abseil/xcprivacy + - abseil/container/inlined_vector (1.20240116.2): + - abseil/algorithm/algorithm + - abseil/base/core_headers + - abseil/base/throw_delegate + - abseil/container/inlined_vector_internal + - abseil/memory/memory + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/container/inlined_vector_internal (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/container/compressed_tuple + - abseil/memory/memory + - abseil/meta/type_traits + - abseil/types/span + - abseil/xcprivacy + - abseil/container/layout (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/debugging/demangle_internal + - abseil/meta/type_traits + - abseil/strings/strings + - abseil/types/span + - abseil/utility/utility + - abseil/xcprivacy + - abseil/container/raw_hash_map (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/throw_delegate + - abseil/container/container_memory + - abseil/container/raw_hash_set + - abseil/xcprivacy + - abseil/container/raw_hash_set (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/endian + - abseil/base/prefetch + - abseil/base/raw_logging_internal + - abseil/container/common + - abseil/container/compressed_tuple + - abseil/container/container_memory + - abseil/container/hash_policy_traits + - abseil/container/hashtable_debug_hooks + - abseil/container/hashtablez_sampler + - abseil/hash/hash + - abseil/memory/memory + - abseil/meta/type_traits + - abseil/numeric/bits + - abseil/utility/utility + - abseil/xcprivacy + - abseil/crc/cpu_detect (1.20240116.2): + - abseil/base/base + - abseil/base/config + - abseil/xcprivacy + - abseil/crc/crc32c (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/base/prefetch + - abseil/crc/cpu_detect + - abseil/crc/crc_internal + - abseil/crc/non_temporal_memcpy + - abseil/strings/str_format + - abseil/strings/strings + - abseil/xcprivacy + - abseil/crc/crc_cord_state (1.20240116.2): + - abseil/base/config + - abseil/crc/crc32c + - abseil/numeric/bits + - abseil/strings/strings + - abseil/xcprivacy + - abseil/crc/crc_internal (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/base/prefetch + - abseil/base/raw_logging_internal + - abseil/crc/cpu_detect + - abseil/memory/memory + - abseil/numeric/bits + - abseil/xcprivacy + - abseil/crc/non_temporal_arm_intrinsics (1.20240116.2): + - abseil/base/config + - abseil/xcprivacy + - abseil/crc/non_temporal_memcpy (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/crc/non_temporal_arm_intrinsics + - abseil/xcprivacy + - abseil/debugging/debugging_internal (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/errno_saver + - abseil/base/raw_logging_internal + - abseil/xcprivacy + - abseil/debugging/demangle_internal (1.20240116.2): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/xcprivacy + - abseil/debugging/stacktrace (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/raw_logging_internal + - abseil/debugging/debugging_internal + - abseil/xcprivacy + - abseil/debugging/symbolize (1.20240116.2): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/malloc_internal + - abseil/base/raw_logging_internal + - abseil/debugging/debugging_internal + - abseil/debugging/demangle_internal + - abseil/strings/strings + - abseil/xcprivacy + - abseil/flags/commandlineflag (1.20240116.2): + - abseil/base/config + - abseil/base/fast_type_id + - abseil/flags/commandlineflag_internal + - abseil/strings/strings + - abseil/types/optional + - abseil/xcprivacy + - abseil/flags/commandlineflag_internal (1.20240116.2): + - abseil/base/config + - abseil/base/fast_type_id + - abseil/xcprivacy + - abseil/flags/config (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/flags/path_util + - abseil/flags/program_name + - abseil/strings/strings + - abseil/synchronization/synchronization + - abseil/xcprivacy + - abseil/flags/flag (1.20240116.2): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/flags/config + - abseil/flags/flag_internal + - abseil/flags/reflection + - abseil/strings/strings + - abseil/xcprivacy + - abseil/flags/flag_internal (1.20240116.2): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/flags/commandlineflag + - abseil/flags/commandlineflag_internal + - abseil/flags/config + - abseil/flags/marshalling + - abseil/flags/reflection + - abseil/memory/memory + - abseil/meta/type_traits + - abseil/strings/strings + - abseil/synchronization/synchronization + - abseil/utility/utility + - abseil/xcprivacy + - abseil/flags/marshalling (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/log_severity + - abseil/numeric/int128 + - abseil/strings/str_format + - abseil/strings/strings + - abseil/types/optional + - abseil/xcprivacy + - abseil/flags/path_util (1.20240116.2): + - abseil/base/config + - abseil/strings/strings + - abseil/xcprivacy + - abseil/flags/private_handle_accessor (1.20240116.2): + - abseil/base/config + - abseil/flags/commandlineflag + - abseil/flags/commandlineflag_internal + - abseil/strings/strings + - abseil/xcprivacy + - abseil/flags/program_name (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/flags/path_util + - abseil/strings/strings + - abseil/synchronization/synchronization + - abseil/xcprivacy + - abseil/flags/reflection (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/no_destructor + - abseil/container/flat_hash_map + - abseil/flags/commandlineflag + - abseil/flags/commandlineflag_internal + - abseil/flags/config + - abseil/flags/private_handle_accessor + - abseil/strings/strings + - abseil/synchronization/synchronization + - abseil/xcprivacy + - abseil/functional/any_invocable (1.20240116.2): + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/utility/utility + - abseil/xcprivacy + - abseil/functional/bind_front (1.20240116.2): + - abseil/base/base_internal + - abseil/container/compressed_tuple + - abseil/meta/type_traits + - abseil/utility/utility + - abseil/xcprivacy + - abseil/functional/function_ref (1.20240116.2): + - abseil/base/base_internal + - abseil/base/core_headers + - abseil/functional/any_invocable + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/hash/city (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/xcprivacy + - abseil/hash/hash (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/container/fixed_array + - abseil/functional/function_ref + - abseil/hash/city + - abseil/hash/low_level_hash + - abseil/meta/type_traits + - abseil/numeric/bits + - abseil/numeric/int128 + - abseil/strings/strings + - abseil/types/optional + - abseil/types/variant + - abseil/utility/utility + - abseil/xcprivacy + - abseil/hash/low_level_hash (1.20240116.2): + - abseil/base/config + - abseil/base/endian + - abseil/base/prefetch + - abseil/numeric/int128 + - abseil/xcprivacy + - abseil/memory (1.20240116.2): + - abseil/memory/memory (= 1.20240116.2) + - abseil/memory/memory (1.20240116.2): + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/meta (1.20240116.2): + - abseil/meta/type_traits (= 1.20240116.2) + - abseil/meta/type_traits (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/xcprivacy + - abseil/numeric/bits (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/xcprivacy + - abseil/numeric/int128 (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/numeric/bits + - abseil/xcprivacy + - abseil/numeric/representation (1.20240116.2): + - abseil/base/config + - abseil/xcprivacy + - abseil/profiling/exponential_biased (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/xcprivacy + - abseil/profiling/sample_recorder (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/synchronization/synchronization + - abseil/time/time + - abseil/xcprivacy + - abseil/random/bit_gen_ref (1.20240116.2): + - abseil/base/core_headers + - abseil/base/fast_type_id + - abseil/meta/type_traits + - abseil/random/internal/distribution_caller + - abseil/random/internal/fast_uniform_bits + - abseil/random/random + - abseil/xcprivacy + - abseil/random/distributions (1.20240116.2): + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/numeric/bits + - abseil/random/internal/distribution_caller + - abseil/random/internal/fast_uniform_bits + - abseil/random/internal/fastmath + - abseil/random/internal/generate_real + - abseil/random/internal/iostream_state_saver + - abseil/random/internal/traits + - abseil/random/internal/uniform_helper + - abseil/random/internal/wide_multiply + - abseil/strings/strings + - abseil/xcprivacy + - abseil/random/internal/distribution_caller (1.20240116.2): + - abseil/base/config + - abseil/base/fast_type_id + - abseil/utility/utility + - abseil/xcprivacy + - abseil/random/internal/fast_uniform_bits (1.20240116.2): + - abseil/base/config + - abseil/meta/type_traits + - abseil/random/internal/traits + - abseil/xcprivacy + - abseil/random/internal/fastmath (1.20240116.2): + - abseil/numeric/bits + - abseil/xcprivacy + - abseil/random/internal/generate_real (1.20240116.2): + - abseil/meta/type_traits + - abseil/numeric/bits + - abseil/random/internal/fastmath + - abseil/random/internal/traits + - abseil/xcprivacy + - abseil/random/internal/iostream_state_saver (1.20240116.2): + - abseil/meta/type_traits + - abseil/numeric/int128 + - abseil/xcprivacy + - abseil/random/internal/nonsecure_base (1.20240116.2): + - abseil/base/core_headers + - abseil/container/inlined_vector + - abseil/meta/type_traits + - abseil/random/internal/pool_urbg + - abseil/random/internal/salted_seed_seq + - abseil/random/internal/seed_material + - abseil/types/span + - abseil/xcprivacy + - abseil/random/internal/pcg_engine (1.20240116.2): + - abseil/base/config + - abseil/meta/type_traits + - abseil/numeric/bits + - abseil/numeric/int128 + - abseil/random/internal/fastmath + - abseil/random/internal/iostream_state_saver + - abseil/xcprivacy + - abseil/random/internal/platform (1.20240116.2): + - abseil/base/config + - abseil/xcprivacy + - abseil/random/internal/pool_urbg (1.20240116.2): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/base/raw_logging_internal + - abseil/random/internal/randen + - abseil/random/internal/seed_material + - abseil/random/internal/traits + - abseil/random/seed_gen_exception + - abseil/types/span + - abseil/xcprivacy + - abseil/random/internal/randen (1.20240116.2): + - abseil/base/raw_logging_internal + - abseil/random/internal/platform + - abseil/random/internal/randen_hwaes + - abseil/random/internal/randen_slow + - abseil/xcprivacy + - abseil/random/internal/randen_engine (1.20240116.2): + - abseil/base/endian + - abseil/meta/type_traits + - abseil/random/internal/iostream_state_saver + - abseil/random/internal/randen + - abseil/xcprivacy + - abseil/random/internal/randen_hwaes (1.20240116.2): + - abseil/base/config + - abseil/random/internal/platform + - abseil/random/internal/randen_hwaes_impl + - abseil/xcprivacy + - abseil/random/internal/randen_hwaes_impl (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/numeric/int128 + - abseil/random/internal/platform + - abseil/xcprivacy + - abseil/random/internal/randen_slow (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/numeric/int128 + - abseil/random/internal/platform + - abseil/xcprivacy + - abseil/random/internal/salted_seed_seq (1.20240116.2): + - abseil/container/inlined_vector + - abseil/meta/type_traits + - abseil/random/internal/seed_material + - abseil/types/optional + - abseil/types/span + - abseil/xcprivacy + - abseil/random/internal/seed_material (1.20240116.2): + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/raw_logging_internal + - abseil/random/internal/fast_uniform_bits + - abseil/strings/strings + - abseil/types/optional + - abseil/types/span + - abseil/xcprivacy + - abseil/random/internal/traits (1.20240116.2): + - abseil/base/config + - abseil/numeric/bits + - abseil/numeric/int128 + - abseil/xcprivacy + - abseil/random/internal/uniform_helper (1.20240116.2): + - abseil/base/config + - abseil/meta/type_traits + - abseil/numeric/int128 + - abseil/random/internal/traits + - abseil/xcprivacy + - abseil/random/internal/wide_multiply (1.20240116.2): + - abseil/base/config + - abseil/numeric/bits + - abseil/numeric/int128 + - abseil/random/internal/traits + - abseil/xcprivacy + - abseil/random/random (1.20240116.2): + - abseil/random/distributions + - abseil/random/internal/nonsecure_base + - abseil/random/internal/pcg_engine + - abseil/random/internal/pool_urbg + - abseil/random/internal/randen_engine + - abseil/random/seed_sequences + - abseil/xcprivacy + - abseil/random/seed_gen_exception (1.20240116.2): + - abseil/base/config + - abseil/xcprivacy + - abseil/random/seed_sequences (1.20240116.2): + - abseil/base/config + - abseil/random/internal/pool_urbg + - abseil/random/internal/salted_seed_seq + - abseil/random/internal/seed_material + - abseil/random/seed_gen_exception + - abseil/types/span + - abseil/xcprivacy + - abseil/status/status (1.20240116.2): + - abseil/base/atomic_hook + - abseil/base/config + - abseil/base/core_headers + - abseil/base/no_destructor + - abseil/base/nullability + - abseil/base/raw_logging_internal + - abseil/base/strerror + - abseil/container/inlined_vector + - abseil/debugging/stacktrace + - abseil/debugging/symbolize + - abseil/functional/function_ref + - abseil/memory/memory + - abseil/strings/cord + - abseil/strings/str_format + - abseil/strings/strings + - abseil/types/optional + - abseil/types/span + - abseil/xcprivacy + - abseil/status/statusor (1.20240116.2): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/nullability + - abseil/base/raw_logging_internal + - abseil/meta/type_traits + - abseil/status/status + - abseil/strings/has_ostream_operator + - abseil/strings/str_format + - abseil/strings/strings + - abseil/types/variant + - abseil/utility/utility + - abseil/xcprivacy + - abseil/strings/charset (1.20240116.2): + - abseil/base/core_headers + - abseil/strings/string_view + - abseil/xcprivacy + - abseil/strings/cord (1.20240116.2): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/base/nullability + - abseil/base/raw_logging_internal + - abseil/container/inlined_vector + - abseil/crc/crc32c + - abseil/crc/crc_cord_state + - abseil/functional/function_ref + - abseil/meta/type_traits + - abseil/numeric/bits + - abseil/strings/cord_internal + - abseil/strings/cordz_functions + - abseil/strings/cordz_info + - abseil/strings/cordz_statistics + - abseil/strings/cordz_update_scope + - abseil/strings/cordz_update_tracker + - abseil/strings/internal + - abseil/strings/strings + - abseil/types/optional + - abseil/types/span + - abseil/xcprivacy + - abseil/strings/cord_internal (1.20240116.2): + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/base/raw_logging_internal + - abseil/base/throw_delegate + - abseil/container/compressed_tuple + - abseil/container/container_memory + - abseil/container/inlined_vector + - abseil/container/layout + - abseil/crc/crc_cord_state + - abseil/functional/function_ref + - abseil/meta/type_traits + - abseil/strings/strings + - abseil/types/span + - abseil/xcprivacy + - abseil/strings/cordz_functions (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/raw_logging_internal + - abseil/profiling/exponential_biased + - abseil/xcprivacy + - abseil/strings/cordz_handle (1.20240116.2): + - abseil/base/base + - abseil/base/config + - abseil/base/raw_logging_internal + - abseil/synchronization/synchronization + - abseil/xcprivacy + - abseil/strings/cordz_info (1.20240116.2): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/raw_logging_internal + - abseil/container/inlined_vector + - abseil/debugging/stacktrace + - abseil/strings/cord_internal + - abseil/strings/cordz_functions + - abseil/strings/cordz_handle + - abseil/strings/cordz_statistics + - abseil/strings/cordz_update_tracker + - abseil/synchronization/synchronization + - abseil/time/time + - abseil/types/span + - abseil/xcprivacy + - abseil/strings/cordz_statistics (1.20240116.2): + - abseil/base/config + - abseil/strings/cordz_update_tracker + - abseil/xcprivacy + - abseil/strings/cordz_update_scope (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/strings/cord_internal + - abseil/strings/cordz_info + - abseil/strings/cordz_update_tracker + - abseil/xcprivacy + - abseil/strings/cordz_update_tracker (1.20240116.2): + - abseil/base/config + - abseil/xcprivacy + - abseil/strings/has_ostream_operator (1.20240116.2): + - abseil/base/config + - abseil/xcprivacy + - abseil/strings/internal (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/base/raw_logging_internal + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/strings/str_format (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/nullability + - abseil/strings/str_format_internal + - abseil/strings/string_view + - abseil/types/span + - abseil/xcprivacy + - abseil/strings/str_format_internal (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/container/fixed_array + - abseil/container/inlined_vector + - abseil/functional/function_ref + - abseil/meta/type_traits + - abseil/numeric/bits + - abseil/numeric/int128 + - abseil/numeric/representation + - abseil/strings/strings + - abseil/types/optional + - abseil/types/span + - abseil/utility/utility + - abseil/xcprivacy + - abseil/strings/string_view (1.20240116.2): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/nullability + - abseil/base/throw_delegate + - abseil/xcprivacy + - abseil/strings/strings (1.20240116.2): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/base/nullability + - abseil/base/raw_logging_internal + - abseil/base/throw_delegate + - abseil/memory/memory + - abseil/meta/type_traits + - abseil/numeric/bits + - abseil/numeric/int128 + - abseil/strings/charset + - abseil/strings/internal + - abseil/strings/string_view + - abseil/xcprivacy + - abseil/synchronization/graphcycles_internal (1.20240116.2): + - abseil/base/base + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/base/malloc_internal + - abseil/base/raw_logging_internal + - abseil/xcprivacy + - abseil/synchronization/kernel_timeout_internal (1.20240116.2): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/raw_logging_internal + - abseil/time/time + - abseil/xcprivacy + - abseil/synchronization/synchronization (1.20240116.2): + - abseil/base/atomic_hook + - abseil/base/base + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/malloc_internal + - abseil/base/raw_logging_internal + - abseil/debugging/stacktrace + - abseil/debugging/symbolize + - abseil/synchronization/graphcycles_internal + - abseil/synchronization/kernel_timeout_internal + - abseil/time/time + - abseil/xcprivacy + - abseil/time (1.20240116.2): + - abseil/time/internal (= 1.20240116.2) + - abseil/time/time (= 1.20240116.2) + - abseil/time/internal (1.20240116.2): + - abseil/time/internal/cctz (= 1.20240116.2) + - abseil/time/internal/cctz (1.20240116.2): + - abseil/time/internal/cctz/civil_time (= 1.20240116.2) + - abseil/time/internal/cctz/time_zone (= 1.20240116.2) + - abseil/time/internal/cctz/civil_time (1.20240116.2): + - abseil/base/config + - abseil/xcprivacy + - abseil/time/internal/cctz/time_zone (1.20240116.2): + - abseil/base/config + - abseil/time/internal/cctz/civil_time + - abseil/xcprivacy + - abseil/time/time (1.20240116.2): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/raw_logging_internal + - abseil/numeric/int128 + - abseil/strings/strings + - abseil/time/internal/cctz/civil_time + - abseil/time/internal/cctz/time_zone + - abseil/types/optional + - abseil/xcprivacy + - abseil/types (1.20240116.2): + - abseil/types/any (= 1.20240116.2) + - abseil/types/bad_any_cast (= 1.20240116.2) + - abseil/types/bad_any_cast_impl (= 1.20240116.2) + - abseil/types/bad_optional_access (= 1.20240116.2) + - abseil/types/bad_variant_access (= 1.20240116.2) + - abseil/types/compare (= 1.20240116.2) + - abseil/types/optional (= 1.20240116.2) + - abseil/types/span (= 1.20240116.2) + - abseil/types/variant (= 1.20240116.2) + - abseil/types/any (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/fast_type_id + - abseil/meta/type_traits + - abseil/types/bad_any_cast + - abseil/utility/utility + - abseil/xcprivacy + - abseil/types/bad_any_cast (1.20240116.2): + - abseil/base/config + - abseil/types/bad_any_cast_impl + - abseil/xcprivacy + - abseil/types/bad_any_cast_impl (1.20240116.2): + - abseil/base/config + - abseil/base/raw_logging_internal + - abseil/xcprivacy + - abseil/types/bad_optional_access (1.20240116.2): + - abseil/base/config + - abseil/base/raw_logging_internal + - abseil/xcprivacy + - abseil/types/bad_variant_access (1.20240116.2): + - abseil/base/config + - abseil/base/raw_logging_internal + - abseil/xcprivacy + - abseil/types/compare (1.20240116.2): + - abseil/base/config + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/types/optional (1.20240116.2): + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/base/nullability + - abseil/memory/memory + - abseil/meta/type_traits + - abseil/types/bad_optional_access + - abseil/utility/utility + - abseil/xcprivacy + - abseil/types/span (1.20240116.2): + - abseil/algorithm/algorithm + - abseil/base/core_headers + - abseil/base/nullability + - abseil/base/throw_delegate + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/types/variant (1.20240116.2): + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/types/bad_variant_access + - abseil/utility/utility + - abseil/xcprivacy + - abseil/utility/utility (1.20240116.2): + - abseil/base/base_internal + - abseil/base/config + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/xcprivacy (1.20240116.2) + - AppAuth (1.7.5): + - AppAuth/Core (= 1.7.5) + - AppAuth/ExternalUserAgent (= 1.7.5) + - AppAuth/Core (1.7.5) + - AppAuth/ExternalUserAgent (1.7.5): + - AppAuth/Core + - BoringSSL-GRPC (0.0.32): + - BoringSSL-GRPC/Implementation (= 0.0.32) + - BoringSSL-GRPC/Interface (= 0.0.32) + - BoringSSL-GRPC/Implementation (0.0.32): + - BoringSSL-GRPC/Interface (= 0.0.32) + - BoringSSL-GRPC/Interface (0.0.32) + - cloud_firestore (5.2.1): + - Firebase/Firestore (= 10.29.0) + - firebase_core + - Flutter + - cloud_functions (5.0.4): + - Firebase/Functions (= 10.29.0) + - firebase_core + - Flutter + - connectivity_plus (0.0.1): + - Flutter + - FlutterMacOS + - Firebase/Auth (10.29.0): + - Firebase/CoreOnly + - FirebaseAuth (~> 10.29.0) + - Firebase/CoreOnly (10.29.0): + - FirebaseCore (= 10.29.0) + - Firebase/Database (10.29.0): + - Firebase/CoreOnly + - FirebaseDatabase (~> 10.29.0) + - Firebase/Firestore (10.29.0): + - Firebase/CoreOnly + - FirebaseFirestore (~> 10.29.0) + - Firebase/Functions (10.29.0): + - Firebase/CoreOnly + - FirebaseFunctions (~> 10.29.0) + - Firebase/Messaging (10.29.0): + - Firebase/CoreOnly + - FirebaseMessaging (~> 10.29.0) + - Firebase/Storage (10.29.0): + - Firebase/CoreOnly + - FirebaseStorage (~> 10.29.0) + - firebase_auth (5.1.4): + - Firebase/Auth (= 10.29.0) + - firebase_core + - Flutter + - firebase_core (3.3.0): + - Firebase/CoreOnly (= 10.29.0) + - Flutter + - firebase_database (11.0.4): + - Firebase/Database (= 10.29.0) + - firebase_core + - Flutter + - firebase_messaging (15.0.4): + - Firebase/Messaging (= 10.29.0) + - firebase_core + - Flutter + - firebase_storage (12.1.3): + - Firebase/Storage (= 10.29.0) + - firebase_core + - Flutter + - FirebaseAppCheckInterop (10.29.0) + - FirebaseAuth (10.29.0): + - FirebaseAppCheckInterop (~> 10.17) + - FirebaseCore (~> 10.0) + - GoogleUtilities/AppDelegateSwizzler (~> 7.8) + - GoogleUtilities/Environment (~> 7.8) + - GTMSessionFetcher/Core (< 4.0, >= 2.1) + - RecaptchaInterop (~> 100.0) + - FirebaseAuthInterop (10.29.0) + - FirebaseCore (10.29.0): + - FirebaseCoreInternal (~> 10.0) + - GoogleUtilities/Environment (~> 7.12) + - GoogleUtilities/Logger (~> 7.12) + - FirebaseCoreExtension (10.29.0): + - FirebaseCore (~> 10.0) + - FirebaseCoreInternal (10.29.0): + - "GoogleUtilities/NSData+zlib (~> 7.8)" + - FirebaseDatabase (10.29.0): + - FirebaseAppCheckInterop (~> 10.17) + - FirebaseCore (~> 10.0) + - FirebaseSharedSwift (~> 10.0) + - GoogleUtilities/UserDefaults (~> 7.13) + - leveldb-library (~> 1.22) + - FirebaseFirestore (10.29.0): + - FirebaseCore (~> 10.0) + - FirebaseCoreExtension (~> 10.0) + - FirebaseFirestoreInternal (= 10.29.0) + - FirebaseSharedSwift (~> 10.0) + - FirebaseFirestoreInternal (10.29.0): + - abseil/algorithm (~> 1.20240116.1) + - abseil/base (~> 1.20240116.1) + - abseil/container/flat_hash_map (~> 1.20240116.1) + - abseil/memory (~> 1.20240116.1) + - abseil/meta (~> 1.20240116.1) + - abseil/strings/strings (~> 1.20240116.1) + - abseil/time (~> 1.20240116.1) + - abseil/types (~> 1.20240116.1) + - FirebaseAppCheckInterop (~> 10.17) + - FirebaseCore (~> 10.0) + - "gRPC-C++ (~> 1.62.0)" + - gRPC-Core (~> 1.62.0) + - leveldb-library (~> 1.22) + - nanopb (< 2.30911.0, >= 2.30908.0) + - FirebaseFunctions (10.29.0): + - FirebaseAppCheckInterop (~> 10.10) + - FirebaseAuthInterop (~> 10.25) + - FirebaseCore (~> 10.0) + - FirebaseCoreExtension (~> 10.0) + - FirebaseMessagingInterop (~> 10.0) + - FirebaseSharedSwift (~> 10.0) + - GTMSessionFetcher/Core (< 4.0, >= 2.1) + - FirebaseInstallations (10.29.0): + - FirebaseCore (~> 10.0) + - GoogleUtilities/Environment (~> 7.8) + - GoogleUtilities/UserDefaults (~> 7.8) + - PromisesObjC (~> 2.1) + - FirebaseMessaging (10.29.0): + - FirebaseCore (~> 10.0) + - FirebaseInstallations (~> 10.0) + - GoogleDataTransport (~> 9.3) + - GoogleUtilities/AppDelegateSwizzler (~> 7.8) + - GoogleUtilities/Environment (~> 7.8) + - GoogleUtilities/Reachability (~> 7.8) + - GoogleUtilities/UserDefaults (~> 7.8) + - nanopb (< 2.30911.0, >= 2.30908.0) + - FirebaseMessagingInterop (10.29.0) + - FirebaseSharedSwift (10.29.0) + - FirebaseStorage (10.29.0): + - FirebaseAppCheckInterop (~> 10.0) + - FirebaseAuthInterop (~> 10.25) + - FirebaseCore (~> 10.0) + - FirebaseCoreExtension (~> 10.0) + - GoogleUtilities/Environment (~> 7.12) + - GTMSessionFetcher/Core (< 4.0, >= 2.1) + - Flutter (1.0.0) + - google_sign_in_ios (0.0.1): + - AppAuth (>= 1.7.4) + - Flutter + - FlutterMacOS + - GoogleSignIn (~> 7.1) + - GTMSessionFetcher (>= 3.4.0) + - GoogleDataTransport (9.4.1): + - GoogleUtilities/Environment (~> 7.7) + - nanopb (< 2.30911.0, >= 2.30908.0) + - PromisesObjC (< 3.0, >= 1.2) + - GoogleSignIn (7.1.0): + - AppAuth (< 2.0, >= 1.7.3) + - GTMAppAuth (< 5.0, >= 4.1.1) + - GTMSessionFetcher/Core (~> 3.3) + - GoogleUtilities/AppDelegateSwizzler (7.13.3): + - GoogleUtilities/Environment + - GoogleUtilities/Logger + - GoogleUtilities/Network + - GoogleUtilities/Privacy + - GoogleUtilities/Environment (7.13.3): + - GoogleUtilities/Privacy + - PromisesObjC (< 3.0, >= 1.2) + - GoogleUtilities/Logger (7.13.3): + - GoogleUtilities/Environment + - GoogleUtilities/Privacy + - GoogleUtilities/Network (7.13.3): + - GoogleUtilities/Logger + - "GoogleUtilities/NSData+zlib" + - GoogleUtilities/Privacy + - GoogleUtilities/Reachability + - "GoogleUtilities/NSData+zlib (7.13.3)": + - GoogleUtilities/Privacy + - GoogleUtilities/Privacy (7.13.3) + - GoogleUtilities/Reachability (7.13.3): + - GoogleUtilities/Logger + - GoogleUtilities/Privacy + - GoogleUtilities/UserDefaults (7.13.3): + - GoogleUtilities/Logger + - GoogleUtilities/Privacy + - "gRPC-C++ (1.62.5)": + - "gRPC-C++/Implementation (= 1.62.5)" + - "gRPC-C++/Interface (= 1.62.5)" + - "gRPC-C++/Implementation (1.62.5)": + - abseil/algorithm/container (~> 1.20240116.2) + - abseil/base/base (~> 1.20240116.2) + - abseil/base/config (~> 1.20240116.2) + - abseil/base/core_headers (~> 1.20240116.2) + - abseil/cleanup/cleanup (~> 1.20240116.2) + - abseil/container/flat_hash_map (~> 1.20240116.2) + - abseil/container/flat_hash_set (~> 1.20240116.2) + - abseil/container/inlined_vector (~> 1.20240116.2) + - abseil/flags/flag (~> 1.20240116.2) + - abseil/flags/marshalling (~> 1.20240116.2) + - abseil/functional/any_invocable (~> 1.20240116.2) + - abseil/functional/bind_front (~> 1.20240116.2) + - abseil/functional/function_ref (~> 1.20240116.2) + - abseil/hash/hash (~> 1.20240116.2) + - abseil/memory/memory (~> 1.20240116.2) + - abseil/meta/type_traits (~> 1.20240116.2) + - abseil/random/bit_gen_ref (~> 1.20240116.2) + - abseil/random/distributions (~> 1.20240116.2) + - abseil/random/random (~> 1.20240116.2) + - abseil/status/status (~> 1.20240116.2) + - abseil/status/statusor (~> 1.20240116.2) + - abseil/strings/cord (~> 1.20240116.2) + - abseil/strings/str_format (~> 1.20240116.2) + - abseil/strings/strings (~> 1.20240116.2) + - abseil/synchronization/synchronization (~> 1.20240116.2) + - abseil/time/time (~> 1.20240116.2) + - abseil/types/optional (~> 1.20240116.2) + - abseil/types/span (~> 1.20240116.2) + - abseil/types/variant (~> 1.20240116.2) + - abseil/utility/utility (~> 1.20240116.2) + - "gRPC-C++/Interface (= 1.62.5)" + - "gRPC-C++/Privacy (= 1.62.5)" + - gRPC-Core (= 1.62.5) + - "gRPC-C++/Interface (1.62.5)" + - "gRPC-C++/Privacy (1.62.5)" + - gRPC-Core (1.62.5): + - gRPC-Core/Implementation (= 1.62.5) + - gRPC-Core/Interface (= 1.62.5) + - gRPC-Core/Implementation (1.62.5): + - abseil/algorithm/container (~> 1.20240116.2) + - abseil/base/base (~> 1.20240116.2) + - abseil/base/config (~> 1.20240116.2) + - abseil/base/core_headers (~> 1.20240116.2) + - abseil/cleanup/cleanup (~> 1.20240116.2) + - abseil/container/flat_hash_map (~> 1.20240116.2) + - abseil/container/flat_hash_set (~> 1.20240116.2) + - abseil/container/inlined_vector (~> 1.20240116.2) + - abseil/flags/flag (~> 1.20240116.2) + - abseil/flags/marshalling (~> 1.20240116.2) + - abseil/functional/any_invocable (~> 1.20240116.2) + - abseil/functional/bind_front (~> 1.20240116.2) + - abseil/functional/function_ref (~> 1.20240116.2) + - abseil/hash/hash (~> 1.20240116.2) + - abseil/memory/memory (~> 1.20240116.2) + - abseil/meta/type_traits (~> 1.20240116.2) + - abseil/random/bit_gen_ref (~> 1.20240116.2) + - abseil/random/distributions (~> 1.20240116.2) + - abseil/random/random (~> 1.20240116.2) + - abseil/status/status (~> 1.20240116.2) + - abseil/status/statusor (~> 1.20240116.2) + - abseil/strings/cord (~> 1.20240116.2) + - abseil/strings/str_format (~> 1.20240116.2) + - abseil/strings/strings (~> 1.20240116.2) + - abseil/synchronization/synchronization (~> 1.20240116.2) + - abseil/time/time (~> 1.20240116.2) + - abseil/types/optional (~> 1.20240116.2) + - abseil/types/span (~> 1.20240116.2) + - abseil/types/variant (~> 1.20240116.2) + - abseil/utility/utility (~> 1.20240116.2) + - BoringSSL-GRPC (= 0.0.32) + - gRPC-Core/Interface (= 1.62.5) + - gRPC-Core/Privacy (= 1.62.5) + - gRPC-Core/Interface (1.62.5) + - gRPC-Core/Privacy (1.62.5) + - GTMAppAuth (4.1.1): + - AppAuth/Core (~> 1.7) + - GTMSessionFetcher/Core (< 4.0, >= 3.3) + - GTMSessionFetcher (3.5.0): + - GTMSessionFetcher/Full (= 3.5.0) + - GTMSessionFetcher/Core (3.5.0) + - GTMSessionFetcher/Full (3.5.0): + - GTMSessionFetcher/Core + - image_picker_ios (0.0.1): + - Flutter + - leveldb-library (1.22.5) + - nanopb (2.30910.0): + - nanopb/decode (= 2.30910.0) + - nanopb/encode (= 2.30910.0) + - nanopb/decode (2.30910.0) + - nanopb/encode (2.30910.0) + - path_provider_foundation (0.0.1): + - Flutter + - FlutterMacOS + - PromisesObjC (2.4.0) + - RecaptchaInterop (100.0.0) + - sqflite (0.0.3): + - Flutter + - FlutterMacOS + +DEPENDENCIES: + - cloud_firestore (from `.symlinks/plugins/cloud_firestore/ios`) + - cloud_functions (from `.symlinks/plugins/cloud_functions/ios`) + - connectivity_plus (from `.symlinks/plugins/connectivity_plus/darwin`) + - firebase_auth (from `.symlinks/plugins/firebase_auth/ios`) + - firebase_core (from `.symlinks/plugins/firebase_core/ios`) + - firebase_database (from `.symlinks/plugins/firebase_database/ios`) + - firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`) + - firebase_storage (from `.symlinks/plugins/firebase_storage/ios`) + - Flutter (from `Flutter`) + - google_sign_in_ios (from `.symlinks/plugins/google_sign_in_ios/darwin`) + - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) + - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) + - sqflite (from `.symlinks/plugins/sqflite/darwin`) + +SPEC REPOS: + trunk: + - abseil + - AppAuth + - BoringSSL-GRPC + - Firebase + - FirebaseAppCheckInterop + - FirebaseAuth + - FirebaseAuthInterop + - FirebaseCore + - FirebaseCoreExtension + - FirebaseCoreInternal + - FirebaseDatabase + - FirebaseFirestore + - FirebaseFirestoreInternal + - FirebaseFunctions + - FirebaseInstallations + - FirebaseMessaging + - FirebaseMessagingInterop + - FirebaseSharedSwift + - FirebaseStorage + - GoogleDataTransport + - GoogleSignIn + - GoogleUtilities + - "gRPC-C++" + - gRPC-Core + - GTMAppAuth + - GTMSessionFetcher + - leveldb-library + - nanopb + - PromisesObjC + - RecaptchaInterop + +EXTERNAL SOURCES: + cloud_firestore: + :path: ".symlinks/plugins/cloud_firestore/ios" + cloud_functions: + :path: ".symlinks/plugins/cloud_functions/ios" + connectivity_plus: + :path: ".symlinks/plugins/connectivity_plus/darwin" + firebase_auth: + :path: ".symlinks/plugins/firebase_auth/ios" + firebase_core: + :path: ".symlinks/plugins/firebase_core/ios" + firebase_database: + :path: ".symlinks/plugins/firebase_database/ios" + firebase_messaging: + :path: ".symlinks/plugins/firebase_messaging/ios" + firebase_storage: + :path: ".symlinks/plugins/firebase_storage/ios" + Flutter: + :path: Flutter + google_sign_in_ios: + :path: ".symlinks/plugins/google_sign_in_ios/darwin" + image_picker_ios: + :path: ".symlinks/plugins/image_picker_ios/ios" + path_provider_foundation: + :path: ".symlinks/plugins/path_provider_foundation/darwin" + sqflite: + :path: ".symlinks/plugins/sqflite/darwin" + +SPEC CHECKSUMS: + abseil: d121da9ef7e2ff4cab7666e76c5a3e0915ae08c3 + AppAuth: 501c04eda8a8d11f179dbe8637b7a91bb7e5d2fa + BoringSSL-GRPC: 1e2348957acdbcad360b80a264a90799984b2ba6 + cloud_firestore: 8a2ff2bb050f87d0ca996866625cefbe2395a83b + cloud_functions: b499cfa8500e51c7d6d1ced8ee8f4e7d3cdc5827 + connectivity_plus: ddd7f30999e1faaef5967c23d5b6d503d10434db + Firebase: cec914dab6fd7b1bd8ab56ea07ce4e03dd251c2d + firebase_auth: 8dbfcdd635cc4fb2ea213aeee8c9a979b3d3373b + firebase_core: 57aeb91680e5d5e6df6b888064be7c785f146efb + firebase_database: 23904308e9dea71b611df90ccf1d31230f140fea + firebase_messaging: c862b3d2b973ecc769194dc8de09bd22c77ae757 + firebase_storage: a099c6305aead7bed5dc7272db64c57195cd8fea + FirebaseAppCheckInterop: 6a1757cfd4067d8e00fccd14fcc1b8fd78cfac07 + FirebaseAuth: e2ebfaf9fb4638a1c9a3b0efd17d1b90943987cd + FirebaseAuthInterop: 17db81e9b198afb0f95ce48c133825727eed55d3 + FirebaseCore: 30e9c1cbe3d38f5f5e75f48bfcea87d7c358ec16 + FirebaseCoreExtension: 705ca5b14bf71d2564a0ddc677df1fc86ffa600f + FirebaseCoreInternal: df84dd300b561c27d5571684f389bf60b0a5c934 + FirebaseDatabase: 1fecbdd38d325c78bd430c06b8e71794ce415dc7 + FirebaseFirestore: f258936f52d712337233182b90042a76ff48dce0 + FirebaseFirestoreInternal: f43d25cc04835ec3aa1885f4fc946a1a4f9e1c56 + FirebaseFunctions: 6ccbc8546a950b8e4dac3d3d8c8f66e23ab647a2 + FirebaseInstallations: 913cf60d0400ebd5d6b63a28b290372ab44590dd + FirebaseMessaging: 7b5d8033e183ab59eb5b852a53201559e976d366 + FirebaseMessagingInterop: afa5a4da1d615d109cf9fcf37479af96f6c3623a + FirebaseSharedSwift: 20530f495084b8d840f78a100d8c5ee613375f6e + FirebaseStorage: 436c30aa46f2177ba152f268fe4452118b8a4856 + Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 + google_sign_in_ios: 07375bfbf2620bc93a602c0e27160d6afc6ead38 + GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a + GoogleSignIn: d4281ab6cf21542b1cfaff85c191f230b399d2db + GoogleUtilities: ea963c370a38a8069cc5f7ba4ca849a60b6d7d15 + "gRPC-C++": e725ef63c4475d7cdb7e2cf16eb0fde84bd9ee51 + gRPC-Core: eee4be35df218649fe66d721a05a7f27a28f069b + GTMAppAuth: f69bd07d68cd3b766125f7e072c45d7340dea0de + GTMSessionFetcher: 5aea5ba6bd522a239e236100971f10cb71b96ab6 + image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1 + leveldb-library: e8eadf9008a61f9e1dde3978c086d2b6d9b9dc28 + nanopb: 438bc412db1928dac798aa6fd75726007be04262 + path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 + PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 + RecaptchaInterop: 7d1a4a01a6b2cb1610a47ef3f85f0c411434cb21 + sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec + +PODFILE CHECKSUM: fe242131aa9e88ddb5a5ab965ae64815e4f19ce2 + +COCOAPODS: 1.15.2 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index fea3ffcefe..43aba00480 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -219,6 +219,111 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; +<<<<<<< Updated upstream +======= + EC4CD229C0209B6C2C8F3349 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/AppAuth/AppAuth.framework", + "${BUILT_PRODUCTS_DIR}/BoringSSL-GRPC/openssl_grpc.framework", + "${BUILT_PRODUCTS_DIR}/FirebaseAppCheckInterop/FirebaseAppCheckInterop.framework", + "${BUILT_PRODUCTS_DIR}/FirebaseAuth/FirebaseAuth.framework", + "${BUILT_PRODUCTS_DIR}/FirebaseAuthInterop/FirebaseAuthInterop.framework", + "${BUILT_PRODUCTS_DIR}/FirebaseCore/FirebaseCore.framework", + "${BUILT_PRODUCTS_DIR}/FirebaseCoreExtension/FirebaseCoreExtension.framework", + "${BUILT_PRODUCTS_DIR}/FirebaseCoreInternal/FirebaseCoreInternal.framework", + "${BUILT_PRODUCTS_DIR}/FirebaseDatabase/FirebaseDatabase.framework", + "${BUILT_PRODUCTS_DIR}/FirebaseFirestore/FirebaseFirestore.framework", + "${BUILT_PRODUCTS_DIR}/FirebaseFirestoreInternal/FirebaseFirestoreInternal.framework", + "${BUILT_PRODUCTS_DIR}/FirebaseFunctions/FirebaseFunctions.framework", + "${BUILT_PRODUCTS_DIR}/FirebaseInstallations/FirebaseInstallations.framework", + "${BUILT_PRODUCTS_DIR}/FirebaseMessaging/FirebaseMessaging.framework", + "${BUILT_PRODUCTS_DIR}/FirebaseMessagingInterop/FirebaseMessagingInterop.framework", + "${BUILT_PRODUCTS_DIR}/FirebaseSharedSwift/FirebaseSharedSwift.framework", + "${BUILT_PRODUCTS_DIR}/FirebaseStorage/FirebaseStorage.framework", + "${BUILT_PRODUCTS_DIR}/GTMAppAuth/GTMAppAuth.framework", + "${BUILT_PRODUCTS_DIR}/GTMSessionFetcher/GTMSessionFetcher.framework", + "${BUILT_PRODUCTS_DIR}/GoogleDataTransport/GoogleDataTransport.framework", + "${BUILT_PRODUCTS_DIR}/GoogleSignIn/GoogleSignIn.framework", + "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework", + "${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework", + "${BUILT_PRODUCTS_DIR}/RecaptchaInterop/RecaptchaInterop.framework", + "${BUILT_PRODUCTS_DIR}/abseil/absl.framework", + "${BUILT_PRODUCTS_DIR}/connectivity_plus/connectivity_plus.framework", + "${BUILT_PRODUCTS_DIR}/gRPC-C++/grpcpp.framework", + "${BUILT_PRODUCTS_DIR}/gRPC-Core/grpc.framework", + "${BUILT_PRODUCTS_DIR}/image_picker_ios/image_picker_ios.framework", + "${BUILT_PRODUCTS_DIR}/leveldb-library/leveldb.framework", + "${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework", + "${BUILT_PRODUCTS_DIR}/path_provider_foundation/path_provider_foundation.framework", + "${BUILT_PRODUCTS_DIR}/sqflite/sqflite.framework", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AppAuth.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/openssl_grpc.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseAppCheckInterop.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseAuth.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseAuthInterop.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCore.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreExtension.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreInternal.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseDatabase.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseFirestore.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseFirestoreInternal.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseFunctions.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseInstallations.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseMessaging.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseMessagingInterop.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseSharedSwift.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseStorage.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GTMAppAuth.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GTMSessionFetcher.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleDataTransport.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleSignIn.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBLPromises.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RecaptchaInterop.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/absl.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/connectivity_plus.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/grpcpp.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/grpc.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/image_picker_ios.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/leveldb.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/nanopb.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider_foundation.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqflite.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + F5678B8B99FE273FD3E63FC1 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh", + "${PODS_CONFIGURATION_BUILD_DIR}/firebase_messaging/firebase_messaging_Privacy.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/google_sign_in_ios/google_sign_in_ios_privacy.bundle", + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/firebase_messaging_Privacy.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/google_sign_in_ios_privacy.bundle", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; +>>>>>>> Stashed changes /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ diff --git a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings index 949b678982..7c19437257 100644 --- a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -1,8 +1,12 @@ +<<<<<<< Updated upstream BuildSystemType Original +======= + +>>>>>>> Stashed changes diff --git a/lib/constants.dart b/lib/constants.dart index 25e5f5c22f..e76ff76817 100644 --- a/lib/constants.dart +++ b/lib/constants.dart @@ -1,4 +1,21 @@ import 'package:flutter/material.dart'; +<<<<<<< Updated upstream +======= +import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; +import 'package:logger/logger.dart' as log; + +const kBlueBody = Color(0x90002DE3); +const kBlue2 = Color(0xFF002DE3); +const kDarkThemeBlue = Color(0xFF879FFF); +const kWhite = Color(0xFFF7F7F7); +const kCardColor = Color(0xFF1B2B48); +const kBackgroundColor = Color(0xFF152033); +const kGreen = Color(0xFF2CC069); +const streamApi = 'chvdm4sex6zq'; +final logger = log.Logger(); +const genericUrl = + 'https://firebasestorage.googleapis.com/v0/b/chateo-72766.appspot.com/o/profile_pictures%2FGeneric%20Image.png?alt=media&token=995355af-474e-40e8-8f43-daff2ff93918'; +>>>>>>> Stashed changes const kSendButtonTextStyle = TextStyle( color: Colors.lightBlueAccent, @@ -17,3 +34,215 @@ const kMessageContainerDecoration = BoxDecoration( top: BorderSide(color: Colors.lightBlueAccent, width: 2.0), ), ); +<<<<<<< Updated upstream +======= + +TextStyle kHeadingStyle1( + {double fontSize = 32.0, Color color = const Color(0xFF0F1828)}) { + return TextStyle( + color: color, + fontFamily: 'Mulish', + fontSize: fontSize, + fontWeight: FontWeight.w900, + fontVariations: const [FontVariation('wght', 900)], + ); +} + +TextStyle kHeadingStyle2( + {double fontSize = 24.0, Color color = const Color(0xFF0F1828)}) { + return TextStyle( + color: color, + fontFamily: 'Mulish', + fontSize: fontSize, + fontWeight: FontWeight.w700, + fontVariations: const [FontVariation('wght', 900)], + ); +} + +TextStyle kSubheadingStyle1( + {double fontSize = 18.0, Color color = const Color(0xFF0F1828)}) { + return TextStyle( + color: color, + fontFamily: 'Mulish', + fontSize: fontSize, + fontWeight: FontWeight.w700, + fontVariations: const [FontVariation('wght', 700)], + ); +} + +TextStyle kSubheadingStyle2( + {double fontSize = 16.0, Color color = const Color(0xFF0F1828)}) { + return TextStyle( + color: color, + fontFamily: 'Mulish', + fontSize: fontSize, + fontWeight: FontWeight.w700, + fontVariations: const [FontVariation('wght', 700)], + ); +} + +TextStyle kBodyStyle1( + {double fontSize = 14.0, Color color = const Color(0xFF0F1828)}) { + return TextStyle( + color: color, + fontFamily: 'Mulish', + fontSize: fontSize, + fontWeight: FontWeight.w700, + fontVariations: const [FontVariation('wght', 700)], + ); +} + +TextStyle kBodyStyle2( + {double fontSize = 14.0, Color color = const Color(0xFF0F1828)}) { + return TextStyle( + color: color, + fontFamily: 'Mulish', + fontSize: fontSize, + fontWeight: FontWeight.w600, + fontVariations: const [FontVariation('wght', 600)], + ); +} + +TextStyle kMetadataStyle1( + {double fontSize = 12.0, Color color = const Color(0xFF0F1828)}) { + return TextStyle( + color: color, + fontFamily: 'Mulish', + fontSize: fontSize, + fontWeight: FontWeight.w600, + fontVariations: const [FontVariation('wght', 600)], + ); +} + +TextStyle kErrorStyle1( + {double fontSize = 12.0, + Color color = const Color.fromARGB(255, 156, 51, 51)}) { + return TextStyle( + color: color, + fontFamily: 'Mulish', + fontSize: fontSize, + fontWeight: FontWeight.w600, + fontVariations: const [FontVariation('wght', 600)], + ); +} + +TextStyle kMetadataStyle2( + {double fontSize = 10.0, Color color = const Color(0xFF0F1828)}) { + return TextStyle( + color: color, + fontFamily: 'Mulish', + fontSize: fontSize, + fontWeight: FontWeight.w600, + fontVariations: const [FontVariation('wght', 600)], + ); +} + +TextStyle kMetadataStyle3( + {double fontSize = 10.0, Color color = const Color(0xFF0F1828)}) { + return TextStyle( + color: color, + fontFamily: 'Mulish', + fontSize: fontSize, + fontWeight: FontWeight.w700, + fontVariations: const [FontVariation('wght', 700)], + ); +} + +InputDecoration getInputDecor(String hint) { + return InputDecoration( + hintText: hint, + hintStyle: kBodyStyle1(color: const Color(0xFFADB5BD)), + fillColor: Colors.grey.withOpacity(0.1), + filled: true, + contentPadding: + const EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(16.0)), + ), + enabledBorder: const OutlineInputBorder( + borderSide: BorderSide(color: Colors.transparent, width: 1.0), + borderRadius: BorderRadius.all(Radius.circular(8.0)), + ), + focusedBorder: const OutlineInputBorder( + borderSide: BorderSide(color: AppColors.primary, width: 2.0), + borderRadius: BorderRadius.all(Radius.circular(16.0)), + ), + ); +} + +Widget getButton(String text, + {required VoidCallback onPressed, required BuildContext context}) { + return Material( + color: Theme.of(context).primaryColor, + borderRadius: const BorderRadius.all(Radius.circular(30.0)), + elevation: 1.0, + child: InkWell( + splashColor: Theme.of(context).primaryColorDark, + child: MaterialButton( + onPressed: () { + onPressed(); + }, + minWidth: 200.0, + height: 42.0, + child: Text( + text, + style: Theme.of(context) + .textTheme + .titleSmall + ?.copyWith(color: Colors.white), + ), + ), + ), + ); +} + +Widget getImageButton( + String text, { + required VoidCallback onPressed, + required BuildContext context, + required String image, +}) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 16.0), + child: Material( + color: Theme.of(context).primaryColor, + borderRadius: const BorderRadius.all(Radius.circular(30.0)), + elevation: 1.0, + child: InkWell( + splashColor: Theme.of(context).primaryColorDark, + child: MaterialButton( + onPressed: () { + onPressed(); + }, + minWidth: 200.0, + height: 42.0, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + // Image.asset('images/' + image), + Image( + image: AssetImage('images/' + image), + width: 20, + height: 20, + ), + const SizedBox(width: 8.0), + Text( + text, + style: Theme.of(context) + .textTheme + .titleSmall + ?.copyWith(color: Colors.white), + ), + ], + ), + ), + ), + ), + ); +} + +extension StreaChatContext on BuildContext { + String? get userImage => StreamChatCore.of(this).currentUser!.image; + User? get user => StreamChatCore.of(this).currentUser; +} +>>>>>>> Stashed changes diff --git a/lib/helpers/channel_info.dart b/lib/helpers/channel_info.dart new file mode 100644 index 0000000000..8be3f67913 --- /dev/null +++ b/lib/helpers/channel_info.dart @@ -0,0 +1,58 @@ +import 'package:jiffy/jiffy.dart'; +import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; + +String getChannelName(Channel channel, User currentUser) { + if (channel.name != null && channel.name != '') { + return channel.name!; + } else { + final otherMembers = channel.state!.members + .where((e) => e.userId != currentUser.id) + .toList(); + if (otherMembers.length == 1) { + return otherMembers.first.user!.name; + } else if (otherMembers.length > 1) { + return otherMembers.map((e) => e.user!.name).join(', '); + } + } + + return ''; +} + +String getChannelImage(Channel channel, User currentUser) { + if (channel.image != null && channel.image != '') { + return channel.image!; + } else { + final otherMembers = channel.state!.members + .where((e) => e.userId != currentUser.id) + .toList(); + if (otherMembers.isEmpty) { + return 'Me'; + } else if (otherMembers.length == 1) { + return otherMembers.first.user!.image!; + } + return otherMembers.first.user!.image!; + } +} + +String getFormattedLastMessageAt(dynamic data) { + final lastMessageAt = data.toLocal(); + String stringDate; + final now = DateTime.now(); + + final startOfDay = DateTime(now.year, now.month, now.day); + + if (lastMessageAt.millisecondsSinceEpoch >= + startOfDay.millisecondsSinceEpoch) { + stringDate = Jiffy.parseFromDateTime(lastMessageAt.toLocal()).jm; + } else if (lastMessageAt.millisecondsSinceEpoch >= + startOfDay.subtract(const Duration(days: 1)).millisecondsSinceEpoch) { + stringDate = 'YESTERDAY'; + } else if (startOfDay.difference(lastMessageAt).inDays < 7) { + stringDate = Jiffy.parseFromDateTime(lastMessageAt.toLocal()).EEEE; + } else { + stringDate = Jiffy.parseFromDateTime(lastMessageAt.toLocal()).yMd; + } + return stringDate; +} + + diff --git a/lib/helpers/helpers.dart b/lib/helpers/helpers.dart new file mode 100644 index 0000000000..cd1b3e669b --- /dev/null +++ b/lib/helpers/helpers.dart @@ -0,0 +1,3 @@ +export './random_image.dart'; +export './random_date.dart'; +export './channel_info.dart'; diff --git a/lib/main.dart b/lib/main.dart index 6ea23d095c..45822b2145 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,3 +1,4 @@ +<<<<<<< Updated upstream import 'package:flutter/material.dart'; import 'package:flash_chat/screens/welcome_screen.dart'; import 'package:flash_chat/screens/login_screen.dart'; @@ -16,6 +17,79 @@ class FlashChat extends StatelessWidget { ), ), home: WelcomeScreen(), +======= +import 'package:cloud_functions/cloud_functions.dart'; +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:flash_chat/constants.dart'; + +import 'package:flash_chat/screens/chat_screen.dart'; +import 'package:flash_chat/screens/profile_screen.dart'; +import 'package:flash_chat/screens/update_details_screen.dart'; +import 'package:flash_chat/screens/verification_screen.dart'; +import 'package:flutter/material.dart'; +import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart' + as stream_chat; +import './screens/welcome_screen.dart'; +import './screens/login_screen.dart'; +import './screens/registration_screen.dart'; +import 'screens/home_screen.dart'; +import 'package:firebase_core/firebase_core.dart'; +import './theme.dart'; + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + await Firebase.initializeApp(); + // Use the local Firebase Functions emulator + FirebaseFunctions functions = FirebaseFunctions.instance; + final client = + stream_chat.StreamChatClient(streamApi, logLevel: stream_chat.Level.INFO); + + // Replace `10.0.2.2` with `localhost` if you're using an iOS simulator + functions.useFunctionsEmulator('localhost', 5001); + + runApp(Chateo( + client: client, + )); +} + +class Chateo extends StatelessWidget { + Chateo({super.key, required this.client}); + final stream_chat.StreamChatClient client; + final _auth = FirebaseAuth.instance; + initState() { + _auth.authStateChanges().listen((User? user) { + if (user == null) { + print('User is currently signed out!'); + } else { + print('User is signed in!'); + } + }); + } + + @override + Widget build(BuildContext context) { + return MaterialApp( + themeMode: ThemeMode.system, + theme: AppTheme.light(ThemeData.light()), + darkTheme: AppTheme.dark(ThemeData.dark()), + builder: (context, child) { + return stream_chat.StreamChatCore( + client: client, + child: child!, + ); + }, + initialRoute: '/', + routes: { + '/': (context) => WelcomeScreen(), + '/login': (context) => LoginScreen(), + '/register': (context) => RegistrationScreen(), + '/home': (context) => const HomeScreen(), + '/chat': (context) => const ChatScreen(), + '/verify': (context) => VerificationScreen(), + '/update_details': (context) => const UpdateDetailsScreen(), + '/profile': (context) => const ProfileScreen(), + }, +>>>>>>> Stashed changes ); } } diff --git a/lib/screens/home_pages/contacts.dart b/lib/screens/home_pages/contacts.dart new file mode 100644 index 0000000000..c466cfe4e6 --- /dev/null +++ b/lib/screens/home_pages/contacts.dart @@ -0,0 +1,124 @@ +import 'package:flash_chat/constants.dart'; +import 'package:flash_chat/widgets/widgets.dart'; +import 'package:flutter/material.dart'; +import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; + +class ContactScreen extends StatefulWidget { + const ContactScreen({super.key}); + + @override + State createState() => _ContactScreenState(); +} + +class _ContactScreenState extends State { + late final userListController = StreamUserListController( + client: StreamChatCore.of(context).client, + filter: Filter.and([ + Filter.notEqual('id', context.user!.id), + // Filter.equal('isDeleted', true) + ])); + @override + void initState() { + userListController.doInitialLoad(); + super.initState(); + } + + @override + void dispose() { + userListController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return PagedValueListenableBuilder( + valueListenable: userListController, + builder: (context, value, child) { + return value.when( + (users, nextPageKey, error) => LazyLoadScrollView( + onEndOfPage: () async { + if (nextPageKey != null) { + userListController.loadMore(nextPageKey); + } + }, + child: ListView.builder( + /// We're using the users length when there are no more + /// pages to load and there are no errors with pagination. + /// In case we need to show a loading indicator or and error + /// tile we're increasing the count by 1. + itemCount: (nextPageKey != null || error != null) + ? users.length + 1 + : users.length, + itemBuilder: (BuildContext context, int index) { + if (index == users.length) { + if (error != null) { + return TextButton( + onPressed: () { + userListController.retry(); + }, + child: Text(error.message), + ); + } + return const CircularProgressIndicator(); + } + + final _user = users[index]; + return _ContactTile( + user: _user, + ); + }, + ), + ), + loading: () => const Center( + child: SizedBox( + height: 100, + width: 100, + child: CircularProgressIndicator(), + ), + ), + error: (e) => Center( + child: Text( + 'Oh no, something went wrong. ' + 'Please check your config. $e', + ), + ), + ); + }, + ); + } +} + +class _ContactTile extends StatefulWidget { + const _ContactTile({ + super.key, + required this.user, + }); + final User user; + @override + State<_ContactTile> createState() => _ContactTileState(); +} + +class _ContactTileState extends State<_ContactTile> { + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: Card( + color: Theme.of(context).cardColor.withOpacity(0.8), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + children: [ + Avatar.medium(imageUrl: widget.user.image ?? genericUrl), + const SizedBox(width: 16), + Text( + widget.user.extraData['email'].toString(), + style: Theme.of(context).textTheme.bodyLarge, + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/screens/home_pages/messages.dart b/lib/screens/home_pages/messages.dart new file mode 100644 index 0000000000..dd891f6f6b --- /dev/null +++ b/lib/screens/home_pages/messages.dart @@ -0,0 +1,298 @@ +import 'package:faker/faker.dart'; +import 'package:flash_chat/constants.dart'; +import 'package:flash_chat/helpers/helpers.dart'; +import 'package:flutter/material.dart'; +import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; + +import '../../models/models.dart'; +import '../../widgets/widgets.dart'; + +class MessageScreen extends StatefulWidget { + const MessageScreen({super.key}); + + @override + State createState() => _MessageScreenState(); +} + +class _MessageScreenState extends State { + late final channelListController = StreamChannelListController( + client: StreamChatCore.of(context).client, + filter: Filter.and([ + Filter.equal('type', 'messaging'), + Filter.in_('members', [StreamChatCore.of(context).currentUser!.id]), + ])); + @override + void initState() { + channelListController.doInitialLoad(); + super.initState(); + } + + @override + void dispose() { + channelListController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return PagedValueListenableBuilder( + valueListenable: channelListController, + builder: (context, value, child) { + return value.when( + (channels, nextPageKey, error) => LazyLoadScrollView( + onEndOfPage: () async { + if (nextPageKey != null) { + channelListController.loadMore(nextPageKey); + } + }, + child: channels.isNotEmpty + ? CustomScrollView(slivers: [ + const SliverToBoxAdapter( + child: _Story(), + ), + SliverList( + delegate: SliverChildBuilderDelegate((context, index) { + return _MessageCard( + channel: channels[index], + ); + }, + childCount: (nextPageKey != null || error != null) + ? channels.length + 1 + : channels.length), + ) + ]) + : const Center( + child: Text('No messages yet, start a new conversation!'), + ), + ), + loading: () => const Center( + child: SizedBox( + height: 100, + width: 100, + child: CircularProgressIndicator(), + ), + ), + error: (e) => Center( + child: Text( + 'Oh no, something went wrong. ' + 'Please check your config. $e', + ), + ), + ); + }, + ); + + // return CustomScrollView(slivers: [ + // const SliverToBoxAdapter( + // child: _Story(), + // ), + // SliverList(delegate: SliverChildBuilderDelegate((context, index) { + // DateTime date = randomDate(); + // return _MessageCard( + // messageData: MessageData( + // name: faker.person.name(), + // message: faker.lorem.sentence(), + // profilePicture: randomImageUrl(), + // messageDate: date, + // dateMessage: Jiffy.parseFromDateTime(date).fromNow(), + // ), + // ); + // })) + // ]); + } +} + +class _MessageCard extends StatefulWidget { + const _MessageCard({required this.channel}); + final Channel channel; + @override + State<_MessageCard> createState() => _MessageCardState(); +} + +class _MessageCardState extends State<_MessageCard> { + @override + Widget build(BuildContext context) { + return InkWell( + onTap: () { + Navigator.pushNamed(context, '/chat', arguments: widget.channel); + }, + child: SizedBox( + height: 80, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.symmetric( + vertical: 8.0, horizontal: 12.0), + child: Avatar.medium( + imageUrl: getChannelImage(widget.channel, context.user!)), + ), + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + getChannelName(widget.channel, context.user!), + style: Theme.of(context).textTheme.titleLarge?.copyWith( + fontSize: 16, + color: Theme.of(context).primaryColorDark), + overflow: TextOverflow.ellipsis, + ), + + // const SizedBox(height: 4), + const SizedBox( + height: 4.0, + ), + SizedBox( + height: 20.0, + child: _getLastMessage(), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.only( + top: 14.0, bottom: 14.0, right: 20.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + _getLastMessageAt(), + const SizedBox( + height: 8.0, + ), + _getUnreadCount(), + ], + ), + ) + ], + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: Container( + color: Theme.of(context).disabledColor, + height: 1, + ), + ) + ], + ), + ), + ); + } + + Widget _getLastMessage() { + return BetterStreamBuilder( + stream: widget.channel.state!.lastMessageStream, + initialData: widget.channel.state!.lastMessage, + builder: (context, lastMessage) { + return Text( + lastMessage.text ?? '', + style: Theme.of(context).textTheme.bodyMedium, + overflow: TextOverflow.ellipsis, + ); + }, + ); + } + + Widget _getLastMessageAt() { + return BetterStreamBuilder( + stream: widget.channel.lastMessageAtStream, + initialData: widget.channel.lastMessageAt, + builder: (context, data) { + return Text( + getFormattedLastMessageAt(data).toUpperCase(), + style: Theme.of(context).textTheme.bodyLarge?.copyWith( + fontSize: 10, + ), + ); + }, + ); + } + + Widget _getUnreadCount() { + return BetterStreamBuilder( + stream: widget.channel.state!.unreadCountStream, + initialData: widget.channel.state?.unreadCount ?? 0, + builder: (context, count) { + if (count == 0) { + return const SizedBox(); + } + return CircleAvatar( + radius: 12, + backgroundColor: Theme.of(context).primaryColor, + child: Center( + child: Text( + count.toString(), + style: Theme.of(context) + .textTheme + .labelLarge + ?.copyWith(fontSize: 10, color: kWhite), + ), + ), + ); + }, + ); + } +} + +class _Story extends StatelessWidget { + const _Story(); + + @override + Widget build(BuildContext context) { + return SizedBox( + height: 134, + child: Card( + elevation: 0, + color: Theme.of(context).cardColor, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text('Stories', + style: kHeadingStyle1( + fontSize: 18, color: Theme.of(context).primaryColorDark)), + const SizedBox(height: 8), + Expanded( + child: ListView.builder( + itemBuilder: (BuildContext context, int index) { + return _StoryCard( + storyData: StoryData( + name: faker.person.firstName(), + url: randomImageUrl())); + }, + scrollDirection: Axis.horizontal, + ), + ) + ], + ), + ), + ), + ); + } +} + +class _StoryCard extends StatelessWidget { + const _StoryCard({super.key, required this.storyData}); + final StoryData storyData; + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.only(right: 10.0), + child: Column(crossAxisAlignment: CrossAxisAlignment.center, children: [ + Avatar.medium(imageUrl: storyData.url), + const SizedBox(height: 8), + Text(storyData.name, + style: kBodyStyle1(color: Theme.of(context).primaryColorDark)), + ]), + ); + } +} diff --git a/lib/screens/home_screen.dart b/lib/screens/home_screen.dart new file mode 100644 index 0000000000..7bf868dea4 --- /dev/null +++ b/lib/screens/home_screen.dart @@ -0,0 +1,237 @@ +import 'package:flash_chat/screens/home_pages/messages.dart'; +import 'package:flash_chat/screens/home_pages/contacts.dart'; +import 'package:flash_chat/screens/home_pages/calls.dart'; +import 'package:flash_chat/screens/home_pages/notifications.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flash_chat/constants.dart'; +import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart' + as stream_chat; +import '../widgets/widgets.dart'; + +class HomeScreen extends StatefulWidget { + const HomeScreen({super.key}); + @override + State createState() => _HomeScreenState(); +} + +class _HomeScreenState extends State { + final pages = const [ + MessageScreen(), + NotificationScreen(), + ContactScreen(), + CallScreen(), + ]; + final pageNames = const [ + 'Messages', + 'Notifications', + 'Contacts', + 'Calls', + ]; + + ValueNotifier pageIndex = ValueNotifier(0); + late final stream_chat.StreamChatClient client; + @override + initState() { + super.initState(); + client = stream_chat.StreamChatCore.of(context).client; + } + + @override + Widget build(BuildContext context) { + return PopScope( + canPop: false, + child: Scaffold( + appBar: AppBar( + backgroundColor: Theme.of(context).scaffoldBackgroundColor, + scrolledUnderElevation: 1, + elevation: 0, + leading: Align( + alignment: Alignment.centerRight, + child: IconButton2( + icon: CupertinoIcons.search, + onPressed: () { + logger.i('Search button pressed'); + }, + ), + ), + actions: [ + Padding( + padding: const EdgeInsets.only(right: 16.0), + child: Avatar.small( + imageUrl: context.user!.image!, + onPressed: () { + Navigator.pushNamed(context, '/profile'); + }, + ), + ) + ], + title: ValueListenableBuilder( + valueListenable: pageIndex, + builder: (BuildContext context, int index, _) { + return index != 4 + ? Text( + pageNames[index].toString(), + style: kHeadingStyle1( + fontSize: 20, + color: Theme.of(context).primaryColorDark), + ) + : Text( + pageNames[0].toString(), + style: kHeadingStyle1( + fontSize: 20, + color: Theme.of(context).primaryColorDark), + ); + }, + ), + ), + body: ValueListenableBuilder( + valueListenable: pageIndex, + builder: (BuildContext context, int index, _) { + return index != 4 ? pages[index] : pages[0]; + }, + ), + bottomNavigationBar: BottomNavigationBar( + itemChanged: (index) { + setState(() { + pageIndex.value = index; + }); + }, + ), + ), + ); + } +} + +class BottomNavigationBar extends StatefulWidget { + const BottomNavigationBar({super.key, required this.itemChanged}); + final ValueChanged itemChanged; + + @override + State createState() => BottomNavigationBarState(); +} + +class BottomNavigationBarState extends State { + int currentindex = 0; + + @override + Widget build(BuildContext context) { + return Container( + color: Theme.of(context).cardColor, + child: SafeArea( + top: false, + bottom: true, + child: Container( + color: Theme.of(context).cardColor, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + NavbarItem( + 0, + icon: CupertinoIcons.chat_bubble_2_fill, + isSelected: currentindex == 0, + label: 'Messages', + onTap: (index) { + setState(() { + currentindex = index; + widget.itemChanged(index); + }); + }, + ), + NavbarItem(3, + icon: CupertinoIcons.phone_fill, + label: 'Calls', + isSelected: currentindex == 3, onTap: (index) { + setState(() { + currentindex = index; + widget.itemChanged(index); + }); + }), + GlowingActionButton( + color: Theme.of(context).primaryColor, + size: 40, + onPressed: () {}, + icon: CupertinoIcons.add), + NavbarItem(2, + icon: CupertinoIcons.person_2_fill, + label: 'Contacts', + isSelected: currentindex == 2, onTap: (index) { + setState(() { + currentindex = index; + widget.itemChanged(index); + }); + }), + NavbarItem(1, + icon: CupertinoIcons.bell_fill, + label: 'Notifications', + isSelected: currentindex == 1, onTap: (index) { + setState(() { + currentindex = index; + widget.itemChanged(index); + }); + }), + ], + ), + ), + ), + ), + ); + } +} + +class NavbarItem extends StatefulWidget { + NavbarItem(this.index, + {super.key, + required this.icon, + required this.label, + required this.onTap, + this.isSelected = false}); + final IconData icon; + final String label; + final int index; + bool isSelected; + final ValueChanged onTap; + @override + State createState() => _NavbarItemState(); +} + +class _NavbarItemState extends State { + @override + Widget build(BuildContext context) { + return GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + widget.onTap(widget.index); + }, + child: SizedBox( + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Icon( + widget.icon, + size: widget.isSelected ? 18 : 16, + color: widget.isSelected + ? Theme.of(context).primaryColor + : Theme.of(context).iconTheme.color, + ), + const SizedBox(height: 4), + Text(widget.label, + style: widget.isSelected + ? Theme.of(context).textTheme.titleLarge?.copyWith( + fontSize: 11, + color: Theme.of(context).primaryColor, + letterSpacing: 0.5) + : Theme.of(context) + .textTheme + .bodyLarge + ?.copyWith(fontSize: 10)) + ], + ), + ), + ); + } +} diff --git a/lib/screens/login_screen.dart b/lib/screens/login_screen.dart index 852e116a19..deb84d1535 100644 --- a/lib/screens/login_screen.dart +++ b/lib/screens/login_screen.dart @@ -1,11 +1,25 @@ +<<<<<<< Updated upstream import 'package:flutter/material.dart'; +======= +import 'package:cloud_functions/cloud_functions.dart'; +import 'package:flash_chat/constants.dart'; +import 'package:flutter/material.dart'; +import 'package:firebase_auth/firebase_auth.dart'; +import '../services/otherSignIn.dart'; +import 'package:modal_progress_hud_alt/modal_progress_hud_alt.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart' + as stream_chat; +>>>>>>> Stashed changes class LoginScreen extends StatefulWidget { + const LoginScreen({super.key}); @override - _LoginScreenState createState() => _LoginScreenState(); + State createState() => _LoginScreenState(); } class _LoginScreenState extends State { +<<<<<<< Updated upstream @override Widget build(BuildContext context) { return Scaffold( @@ -44,6 +58,166 @@ class _LoginScreenState extends State { BorderSide(color: Colors.lightBlueAccent, width: 2.0), borderRadius: BorderRadius.all(Radius.circular(32.0)), ), +======= + String email = ''; + String password = ''; + final _auth = FirebaseAuth.instance; + final FirebaseFunctions _functions = FirebaseFunctions.instance; + bool loading = false; + String errorText = ''; + + Future signIn() async { + final callable = _functions.httpsCallable('getStreamUserToken'); + final results = await callable(); + final token = results.data; + logger.i('Stream token retrieved, token: $token'); + final client = stream_chat.StreamChatCore.of(context).client; + client.connectUser( + stream_chat.User( + id: _auth.currentUser!.uid, + extraData: { + 'name': _auth.currentUser!.displayName, + 'email': _auth.currentUser!.email, + }, + image: _auth.currentUser!.photoURL), + token); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Theme.of(context).scaffoldBackgroundColor, + body: ModalProgressHUD( + progressIndicator: SpinKitChasingDots( + color: Theme.of(context).primaryColor, + ), + inAsyncCall: loading, + child: Center( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 24.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Hero( + tag: 'logo', + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + height: 60.0, + child: Image.asset('images/logo.png')), + const SizedBox(width: 10.0), + Text( + 'Chateo', + style: Theme.of(context) + .textTheme + .titleLarge + ?.copyWith(fontSize: 65), + ) + ], + ), + ), + ), + Text( + 'Enter Your Log In Credentials', + style: kHeadingStyle2(fontSize: 22.0), + textAlign: TextAlign.center, + ), + const SizedBox( + height: 48.0, + ), + TextField( + onChanged: (value) { + email = value; + //Do something with the user input. + }, + style: Theme.of(context).textTheme.bodyLarge, + cursorColor: + Theme.of(context).primaryColorDark.withOpacity(0.6), + decoration: getInputDecor('Enter your email')), + const SizedBox( + height: 8.0, + ), + TextField( + obscureText: true, + onChanged: (value) { + password = value; + //Do something with the user input. + }, + style: Theme.of(context).textTheme.bodyLarge, + cursorColor: + Theme.of(context).primaryColorDark.withOpacity(0.6), + decoration: getInputDecor('Enter your password')), + Text(errorText, style: kErrorStyle1()), + const SizedBox( + height: 12.0, + ), + Center( + child: Text( + 'OR', + style: kBodyStyle1(color: const Color(0xFFADB5BD)), + ), + ), + getImageButton( + 'Sign In with Google', + context: context, + onPressed: () async { + final userCred = await signInWithGoogle(); + if (userCred.user != null) { + if (userCred.user?.emailVerified == true) { + try { + await signIn(); + Navigator.pushNamed(context, '/home'); + } catch (e) { + logger.e('Error signing in with google: $e'); + } + } else { + Navigator.pushNamed(context, '/verify'); + } + } + }, + image: 'google.png', + ), + const SizedBox( + height: 24.0, + ), + getButton('Log In', context: context, onPressed: () async { + setState(() { + loading = true; + }); + try { + final userCred = await _auth.signInWithEmailAndPassword( + email: email, password: password); + if (userCred.user != null) { + if (userCred.user?.emailVerified == true) { + if (userCred.user?.displayName == null) { + Navigator.pushNamed(context, '/update_details'); + } else { + try { + await signIn(); + Navigator.pushNamed(context, '/home'); + } catch (e) { + logger.e(e); + } + } + } else { + Navigator.pushNamed(context, '/verify'); + } + } + } catch (e) { + setState(() { + errorText = e.toString(); + }); + } + setState(() { + loading = false; + }); + }), + ], +>>>>>>> Stashed changes ), ), SizedBox( diff --git a/lib/screens/profile_screen.dart b/lib/screens/profile_screen.dart new file mode 100644 index 0000000000..aac03346ce --- /dev/null +++ b/lib/screens/profile_screen.dart @@ -0,0 +1,299 @@ +import 'package:cloud_functions/cloud_functions.dart'; +import 'package:firebase_auth/firebase_auth.dart' as fa; +import 'package:flash_chat/constants.dart'; +import 'package:flash_chat/theme.dart'; +import 'package:flash_chat/widgets/widgets.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:modal_progress_hud_alt/modal_progress_hud_alt.dart'; +import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; + +class ProfileScreen extends StatefulWidget { + const ProfileScreen({super.key}); + + @override + State createState() => _ProfileScreenState(); +} + +class _ProfileScreenState extends State { + final _auth = fa.FirebaseAuth.instance; + bool _loading = false; + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Theme.of(context).scaffoldBackgroundColor, + appBar: AppBar( + leading: IconButton( + icon: Icon( + CupertinoIcons.back, + color: Theme.of(context).primaryColorDark, + ), + onPressed: () { + Navigator.pop(context); + }, + ), + ), + body: SafeArea( + child: ModalProgressHUD( + progressIndicator: SpinKitChasingDots( + color: Theme.of(context).primaryColor, + ), + inAsyncCall: _loading, + child: CustomScrollView( + slivers: [ + SliverToBoxAdapter( + child: Padding( + padding: const EdgeInsets.only(bottom: 12.0), + child: Center( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Avatar( + radius: 100, + imageUrl: context.userImage!, + ), + Text( + context.user!.extraData['name'].toString(), + style: Theme.of(context).textTheme.titleMedium, + ), + Text( + context.user!.extraData['email'].toString(), + style: Theme.of(context).textTheme.titleSmall, + ), + ], + ), + ), + ), + ), + SliverList( + delegate: SliverChildBuilderDelegate( + (context, index) { + return Column( + children: [ + _PButton( + onPressed: () async { + await showMyDialog(context); + }, + icon: Icons.logout, + text: 'Log Out', + ), + _PButton( + onPressed: () async { + try { + showDeleteDialog(); + } catch (e) { + logger.e('Error deleting user: $e'); + } + }, + icon: Icons.heart_broken, + text: 'Delete', + ), + ], + ); + }, + childCount: 1, + ), + ), + ], + ), + ), + ), + ); + } + + Future showDeleteDialog() { + String password = ''; + late String provider; + for (final providerData in _auth.currentUser!.providerData) { + if (providerData.providerId == 'password') { + provider = 'password'; + } else if (providerData.providerId == 'google.com') { + provider = 'google.com'; + } + } + return showDialog( + context: context, + barrierDismissible: false, // user must tap button! + builder: (BuildContext context) { + return AlertDialog( + backgroundColor: Theme.of(context).cardColor, + title: Text('Delete Account', + style: Theme.of(context).textTheme.titleMedium), + content: SingleChildScrollView( + child: ListBody( + children: [ + Text( + provider == 'password' + ? 'Please Enter your password to proceed with the deletion' + : 'Clicking the button will take you to google to reauthenticate and then delete your account.', + style: Theme.of(context).textTheme.bodyMedium, + ), + provider == 'password' + ? TextField( + obscureText: true, + onChanged: (value) { + password = value; + //Do something with the user input. + }, + style: Theme.of(context).textTheme.bodyLarge, + cursorColor: + Theme.of(context).primaryColorDark.withOpacity(0.6), + decoration: getInputDecor('Enter your password'), + ) + : const SizedBox(), + ], + ), + ), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text( + 'Cancel', + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + color: Theme.of(context).primaryColor, fontSize: 14), + )), + TextButton( + onPressed: () async { + try { + StreamChatCore.of(context).client.updateUser( + User(id: context.user!.id, extraData: const { + 'deleted': true, + })); + if (provider == 'password') { + await _auth.currentUser!.reauthenticateWithCredential( + fa.EmailAuthProvider.credential( + email: _auth.currentUser!.email!, + password: password)); + } else if (provider == 'google.com') { + await _auth.currentUser! + .reauthenticateWithProvider(fa.GoogleAuthProvider()); + } + } catch (e) { + logger.e('Error reauthenticating user: $e'); + } + StreamChatCore.of(context).client.disconnectUser(); + await _auth.currentUser!.delete(); + logger.i('Stream user deleted'); + Navigator.pushNamedAndRemoveUntil(context, '/', (_) => false); + }, + child: Text( + 'Proceed', + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(color: AppColors.errorColor, fontSize: 14), + )) + ], + ); + }, + ); + } +} + +class _PButton extends StatelessWidget { + const _PButton( + {required this.onPressed, + required this.icon, + this.iconColor = AppColors.textFaded, + required this.text}); + final VoidCallback onPressed; + final IconData icon; + final Color? iconColor; + final String text; + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: onPressed, + child: Card( + color: Theme.of(context).cardColor.withOpacity(0.8), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + height: 40, + width: 40, + decoration: BoxDecoration( + color: iconColor?.withOpacity(0.1), + borderRadius: BorderRadius.circular(12.0), + ), + child: Icon( + icon, + color: Theme.of(context).primaryColorDark, + size: 20, + ), + ), + const SizedBox(width: 10), + Text( + text, + style: Theme.of(context).textTheme.bodyLarge, + ), + ], + ), + ), + ), + ); + } +} + +Future logout() async { + // Revoke Stream user token. + final auth = fa.FirebaseAuth.instance; + final functions = FirebaseFunctions.instance; + + final callable = functions.httpsCallable('revokeStreamUserToken'); + await callable(); + logger.i('Stream user token revoked'); + + // Sign out Firebase. + await auth.signOut(); + logger.i('Firebase signed out'); +} + +Future showMyDialog(BuildContext context) async { + return showDialog( + context: context, + barrierDismissible: false, // user must tap button! + builder: (BuildContext context) { + return AlertDialog( + backgroundColor: Theme.of(context).cardColor, + title: Text('Log Out', style: Theme.of(context).textTheme.titleMedium), + content: SingleChildScrollView( + child: ListBody( + children: [ + Text('Are you Sure you want to log out ?', + style: Theme.of(context).textTheme.bodyMedium), + ], + ), + ), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text( + 'Cancel', + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + color: Theme.of(context).primaryColor, fontSize: 14), + )), + TextButton( + onPressed: () async { + StreamChatCore.of(context).client.disconnectUser(); + await logout(); + Navigator.pushNamedAndRemoveUntil(context, '/', (_) => false); + }, + child: Text( + 'Yes', + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + color: Theme.of(context).primaryColor, fontSize: 14), + )) + ], + ); + }, + ); +} diff --git a/lib/screens/registration_screen.dart b/lib/screens/registration_screen.dart index bbc0d5195e..cb584a19b5 100644 --- a/lib/screens/registration_screen.dart +++ b/lib/screens/registration_screen.dart @@ -1,3 +1,8 @@ +<<<<<<< Updated upstream +======= +import 'package:cloud_functions/cloud_functions.dart'; +import 'package:flash_chat/constants.dart'; +>>>>>>> Stashed changes import 'package:flutter/material.dart'; class RegistrationScreen extends StatefulWidget { @@ -9,6 +14,7 @@ class _RegistrationScreenState extends State { @override Widget build(BuildContext context) { return Scaffold( +<<<<<<< Updated upstream backgroundColor: Colors.white, body: Padding( padding: EdgeInsets.symmetric(horizontal: 24.0), @@ -42,6 +48,132 @@ class _RegistrationScreenState extends State { borderSide: BorderSide(color: Colors.blueAccent, width: 2.0), borderRadius: BorderRadius.all(Radius.circular(32.0)), ), +======= + backgroundColor: Theme.of(context).scaffoldBackgroundColor, + body: ModalProgressHUD( + progressIndicator: SpinKitChasingDots( + color: Theme.of(context).primaryColor, + ), + inAsyncCall: loading, + child: Center( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 24.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Hero( + tag: 'logo', + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + height: 60.0, + child: Image.asset('images/logo.png')), + const SizedBox(width: 10.0), + Text( + 'Chateo', + style: Theme.of(context) + .textTheme + .titleLarge + ?.copyWith(fontSize: 65), + ) + ], + ), + ), + ), + Text( + 'Hi there! Let\'s Get You Registered', + style: kHeadingStyle2(fontSize: 22.0), + textAlign: TextAlign.center, + ), + const SizedBox( + height: 48.0, + ), + TextField( + textAlign: TextAlign.left, + keyboardType: TextInputType.emailAddress, + onChanged: (value) { + email = value; + }, + style: Theme.of(context).textTheme.bodyLarge, + cursorColor: + Theme.of(context).primaryColorDark.withOpacity(0.6), + decoration: getInputDecor('Enter your email')), + const SizedBox( + height: 8.0, + ), + TextField( + textAlign: TextAlign.left, + obscureText: true, + keyboardType: TextInputType.visiblePassword, + onChanged: (value) { + password = value; + }, + style: Theme.of(context).textTheme.bodyLarge, + cursorColor: + Theme.of(context).primaryColorDark.withOpacity(0.6), + decoration: getInputDecor('Enter your password'), + ), + const SizedBox( + height: 12.0, + ), + Center( + child: Text( + 'OR', + style: kBodyStyle1(color: const Color(0xFFADB5BD)), + ), + ), + getImageButton( + 'Sign In with Google', + context: context, + onPressed: () async { + final userCred = await signInWithGoogle(); + print(userCred.user); + if (userCred.user != null) { + if (userCred.user?.emailVerified == true) { + final callable = _functions + .httpsCallable('createStreamUserAndGetToken'); + final results = await callable(); + final token = results.data; + print( + 'Stream account created, token: $token'); + Navigator.pushNamed(context, '/home', arguments: token); + } else { + Navigator.pushNamed(context, '/verify'); + } + } + }, + image: 'google.png', + ), + const SizedBox( + height: 24.0, + ), + getButton( + 'Register', + context: context, + onPressed: () async { + setState(() { + loading = true; + }); + try { + final user = await _auth.createUserWithEmailAndPassword( + email: email, password: password); + if (user.user != null) { + Navigator.pushNamed(context, '/verify'); + } + } catch (e) { + print(e); + } + setState(() { + loading = false; + }); + }, + ) + ], +>>>>>>> Stashed changes ), ), SizedBox( diff --git a/lib/screens/update_details_screen.dart b/lib/screens/update_details_screen.dart new file mode 100644 index 0000000000..51efec9f96 --- /dev/null +++ b/lib/screens/update_details_screen.dart @@ -0,0 +1,177 @@ +import 'dart:io'; +import 'package:cloud_functions/cloud_functions.dart'; +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:flash_chat/constants.dart'; +import 'package:flash_chat/theme.dart'; +import 'package:flash_chat/widgets/widgets.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:image_picker/image_picker.dart'; +import 'package:firebase_storage/firebase_storage.dart'; +import 'package:modal_progress_hud_alt/modal_progress_hud_alt.dart'; +import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart' + as stream_chat; + +class UpdateDetailsScreen extends StatefulWidget { + const UpdateDetailsScreen({super.key}); + + @override + State createState() => _UpdateDetailsScreenState(); +} + +class _UpdateDetailsScreenState extends State { + String name = ''; + String imageUrl = genericUrl; + final _auth = FirebaseAuth.instance; + final _storage = FirebaseStorage.instance; + final _functions = FirebaseFunctions.instance; + String errorMessage = ''; + bool _loading = false; + @override + Widget build(BuildContext context) { + return ModalProgressHUD( + progressIndicator: SpinKitChasingDots( + color: Theme.of(context).primaryColor, + ), + inAsyncCall: _loading, + child: Scaffold( + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + children: [ + Padding( + padding: const EdgeInsets.all(12.0), + child: CircleAvatar( + radius: 50, + backgroundColor: Theme.of(context).primaryColor, + child: PopupMenuButton( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16)), + icon: imageUrl == genericUrl + ? const Icon( + Icons.add_a_photo, + color: AppColors.textLight, + size: 50, + ) + : null, + child: imageUrl == genericUrl + ? null + : Avatar(radius: 50, imageUrl: imageUrl), + onSelected: (ImageSource result) async { + ImagePicker imagePicker = ImagePicker(); + XFile? file; + try { + file = + await imagePicker.pickImage(source: result); + } catch (e) { + print(e); + } + ; + if (file != null) { + Reference ref = _storage + .ref() + .child('profile_pictures') + .child(_auth.currentUser!.email!); + try { + setState(() { + _loading = true; + }); + await ref.putFile(File(file.path)); + imageUrl = await ref.getDownloadURL(); + setState(() { + _loading = false; + imageUrl = imageUrl; + }); + } catch (e) { + print(e); + setState(() { + _loading = false; + imageUrl = genericUrl; + }); + } + } + }, + itemBuilder: (BuildContext context) => + >[ + PopupMenuItem( + value: ImageSource.gallery, + child: Text( + 'Gallery', + style: + Theme.of(context).textTheme.bodyLarge, + ), + ), + PopupMenuItem( + value: ImageSource.camera, + child: Text('Camera', + style: Theme.of(context) + .textTheme + .bodyLarge), + ), + ]), + ), + ), + Padding( + padding: const EdgeInsets.all(12.0), + child: TextField( + onChanged: (value) { + name = value; + //Do something with the user input. + }, + style: Theme.of(context).textTheme.bodyLarge, + cursorColor: Theme.of(context) + .primaryColorDark + .withOpacity(0.6), + decoration: getInputDecor('Enter your Display Name')), + ), + Text(errorMessage, + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(color: AppColors.errorColor)), + ], + ), + getButton('Next', onPressed: () async { + setState(() { + _loading = true; + }); + if (name.isEmpty) { + setState(() { + _loading = false; + errorMessage = 'Name cannot be empty'; + }); + } else { + await _auth.currentUser?.updateDisplayName(name); + await _auth.currentUser?.updatePhotoURL(imageUrl); + final callable = + _functions.httpsCallable('createStreamUserAndGetToken'); + final results = await callable(); + final token = results.data; + final client = + stream_chat.StreamChatCore.of(context).client; + client.connectUser( + stream_chat.User( + id: _auth.currentUser!.uid, + extraData: { + 'name': _auth.currentUser!.displayName, + 'email': _auth.currentUser!.email, + 'deleted': false, + }, + image: _auth.currentUser!.photoURL, + ), + token); + Navigator.pushNamed(context, '/home'); + } + }, context: context) + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/screens/verification_screen.dart b/lib/screens/verification_screen.dart new file mode 100644 index 0000000000..925e3d451a --- /dev/null +++ b/lib/screens/verification_screen.dart @@ -0,0 +1,88 @@ +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:flash_chat/constants.dart'; +import 'package:flutter/material.dart'; +import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; + +class VerificationScreen extends StatefulWidget { + const VerificationScreen({super.key}); + + @override + State createState() => _VerificationScreenState(); +} + +class _VerificationScreenState extends State { + final _auth = FirebaseAuth.instance; + + bool pop = false; + late RestartableTimer timer; + + @override + void initState() { + super.initState(); + + // ignore: unnecessary_set_literal + FirebaseAuth.instance.currentUser?.sendEmailVerification(); + timer = RestartableTimer(const Duration(seconds: 5), () async { + await _auth.currentUser?.reload(); + print('reloading'); + if (_auth.currentUser?.emailVerified == true) { + timer.cancel(); + + Navigator.pushNamed(context, '/update_details'); + } else { + timer.reset(); + } + }); + } + + Widget build(BuildContext context) { + return PopScope( + canPop: false, + child: Scaffold( + body: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: Text( + textAlign: TextAlign.center, + 'A verification link has been sent to your email. Please click on the link to verify.', + style: Theme.of(context).textTheme.titleSmall, + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Did not receive a link.', + style: Theme.of(context).textTheme.bodyMedium, + ), + TextButton( + style: null, + isSemanticButton: false, + onPressed: () { + _auth.currentUser?.sendEmailVerification(); + }, + child: Text( + 'Click Here', + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(color: Theme.of(context).primaryColor), + ), + ) + ], + ), + ), + getButton('Sign Out', onPressed: () { + _auth.signOut(); + Navigator.pushNamedAndRemoveUntil(context, '/', (_) => false); + }, context: context), + ], + ), + ), + ); + } +} diff --git a/lib/screens/welcome_screen.dart b/lib/screens/welcome_screen.dart index 6270ccf476..49746d4d80 100644 --- a/lib/screens/welcome_screen.dart +++ b/lib/screens/welcome_screen.dart @@ -1,11 +1,66 @@ +<<<<<<< Updated upstream import 'package:flutter/material.dart'; +======= +import 'package:cloud_functions/cloud_functions.dart'; +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:flash_chat/constants.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import 'package:animated_text_kit/animated_text_kit.dart'; +import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart' + as stream_chat; +>>>>>>> Stashed changes class WelcomeScreen extends StatefulWidget { @override _WelcomeScreenState createState() => _WelcomeScreenState(); } +<<<<<<< Updated upstream class _WelcomeScreenState extends State { +======= +class _WelcomeScreenState extends State + with SingleTickerProviderStateMixin { + bool _isFirstAnimationComplete = false; + final _auth = FirebaseAuth.instance; + final _functions = FirebaseFunctions.instance; + @override + void initState() { + super.initState(); + _auth.authStateChanges().listen((User? user) async { + if (user != null && user.emailVerified && user.displayName != null) { + final callable = _functions.httpsCallable('getStreamUserToken'); + final results = await callable(); + final token = results.data; + logger.i('Stream token retrieved, token: $token'); + final client = stream_chat.StreamChatCore.of(context).client; + client.connectUser( + stream_chat.User( + id: _auth.currentUser!.uid, + name: _auth.currentUser!.displayName, + extraData: { + 'email': _auth.currentUser!.email, + }, + image: _auth.currentUser!.photoURL), + token); + Navigator.pushNamed(context, '/home'); + } else if (user != null && user.emailVerified) { + Navigator.pushNamed(context, '/update_details'); + } else if (user != null) { + Navigator.pushNamed(context, '/verification'); + } else { + logger.i('User is currently signed out!'); + } + }); + // Set a delay to start the second animation after the first completes + Future.delayed(const Duration(milliseconds: 4000), () { + setState(() { + _isFirstAnimationComplete = true; + }); + }); + } + +>>>>>>> Stashed changes @override Widget build(BuildContext context) { return Scaffold( @@ -49,6 +104,54 @@ class _WelcomeScreenState extends State { child: Text( 'Log In', ), +<<<<<<< Updated upstream +======= + const SizedBox( + height: 10, + ), + if (_isFirstAnimationComplete) + Text( + 'Connecting you with the world!', + textAlign: TextAlign.center, + style: kHeadingStyle1( + fontSize: 20.0, + color: Theme.of(context).primaryColorDark), + ) + .animate() + .slideY( + duration: 1.seconds, + begin: 1.0, + end: 0.0, + curve: Curves.easeInOut, + ) + .fade( + duration: 1.seconds, + ) + ], + ), + SafeArea( + bottom: true, + top: false, + child: Column( + children: [ + getButton('Register', context: context, onPressed: () { + Navigator.pushNamed(context, '/register'); + }), + TextButton( + onPressed: () { + //Go to login screen. + Navigator.pushNamed(context, '/login'); + }, + child: Text( + 'Log In', + style: Theme.of(context) + .textTheme + .titleSmall + ?.copyWith(color: Theme.of(context).primaryColor), + ), + ), + ], +>>>>>>> Stashed changes ), ), ), diff --git a/lib/services/otherSignIn.dart b/lib/services/otherSignIn.dart new file mode 100644 index 0000000000..68a69817c9 --- /dev/null +++ b/lib/services/otherSignIn.dart @@ -0,0 +1,31 @@ +import 'package:google_sign_in/google_sign_in.dart'; +import 'package:firebase_auth/firebase_auth.dart'; + +Future signInWithGoogle() async { + // Trigger the authentication flow + final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn(); + + // Obtain the auth details from the request + final GoogleSignInAuthentication? googleAuth = + await googleUser?.authentication; + + // Create a new credential + final credential = GoogleAuthProvider.credential( + accessToken: googleAuth?.accessToken, + idToken: googleAuth?.idToken, + ); + + // Once signed in, return the UserCredential + return await FirebaseAuth.instance.signInWithCredential(credential); +} + +Future getGoogleCredentials() async { + final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn(); + + // Obtain the auth details from the request + final GoogleSignInAuthentication? googleAuth = + await googleUser?.authentication; + + // Create a new credential + return googleAuth!.idToken; +} diff --git a/lib/theme.dart b/lib/theme.dart new file mode 100644 index 0000000000..c5d49fdd4c --- /dev/null +++ b/lib/theme.dart @@ -0,0 +1,59 @@ +import 'package:flutter/material.dart'; +import './constants.dart'; + +class AppColors { + static const secondary = Color(0xFF001A83); + // static const primary = Color(0xFF002DE3); + static const primary = Color(0xFF7BCBCF); + static const accent = Color(0xFFCDE1FD); + static const textDark = Color(0xFF0F1828); + static const textLight = Color(0xFFF7F7FC); + static const textFaded = Color(0xFFADB5BD); + static const darkPrimary = Color(0xFF7BCBCF); + static const darkBackground = Color(0xFF0F1828); + static const darkCardColor = Color(0xFF152033); + static const cardColor = Color.fromARGB(255, 238, 243, 244); + static const backgroundColor = Color.fromARGB(255, 251, 251, 251); + static const errorColor = Color(0xFFE94242); +} + +class AppTheme { + static ThemeData light(ThemeData theme) => ThemeData( + appBarTheme: + const AppBarTheme(backgroundColor: AppColors.backgroundColor), + brightness: Brightness.light, + primaryColor: AppColors.primary, + primaryColorDark: AppColors.textDark, + disabledColor: AppColors.textFaded, + visualDensity: VisualDensity.adaptivePlatformDensity, + scaffoldBackgroundColor: AppColors.backgroundColor, + cardColor: AppColors.cardColor, + iconTheme: const IconThemeData(color: AppColors.textDark), + textTheme: TextTheme( + titleLarge: kHeadingStyle1(color: AppColors.textDark), + titleMedium: kHeadingStyle2(color: AppColors.textDark), + titleSmall: kSubheadingStyle1(color: AppColors.textDark), + bodyLarge: kBodyStyle1(color: AppColors.textDark), + bodyMedium: kBodyStyle2(fontSize: 12, color: AppColors.textDark), + labelLarge: kMetadataStyle1(color: AppColors.textDark), + labelMedium: kMetadataStyle2(color: AppColors.textDark), + labelSmall: kMetadataStyle3(color: AppColors.textDark))); + static ThemeData dark(ThemeData theme) => ThemeData( + appBarTheme: const AppBarTheme(backgroundColor: AppColors.darkBackground), + brightness: Brightness.dark, + primaryColor: AppColors.darkPrimary, + primaryColorDark: AppColors.textLight, + visualDensity: VisualDensity.adaptivePlatformDensity, + scaffoldBackgroundColor: AppColors.darkBackground, + cardColor: AppColors.darkCardColor, + iconTheme: const IconThemeData(color: AppColors.textLight), + textTheme: TextTheme( + titleLarge: kHeadingStyle1(color: AppColors.textLight), + titleMedium: kHeadingStyle2(color: AppColors.textLight), + titleSmall: kSubheadingStyle1(color: AppColors.textLight), + bodyLarge: kBodyStyle1(color: AppColors.textLight), + bodyMedium: kBodyStyle2(fontSize: 12, color: AppColors.textLight), + labelLarge: kMetadataStyle1(color: AppColors.textLight), + labelMedium: kMetadataStyle2(color: AppColors.textLight), + labelSmall: kMetadataStyle3(color: AppColors.textLight))); +} diff --git a/lib/widgets/avatar.dart b/lib/widgets/avatar.dart new file mode 100644 index 0000000000..f90d3fbd60 --- /dev/null +++ b/lib/widgets/avatar.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import '../constants.dart'; + +class Avatar extends StatelessWidget { + final double radius; + final String imageUrl; + final VoidCallback? onPressed; + const Avatar( + {super.key, + required this.radius, + required this.imageUrl, + this.onPressed}); + const Avatar.small({super.key, required this.imageUrl, this.onPressed}) + : radius = 16.0; + const Avatar.medium({super.key, required this.imageUrl, this.onPressed}) + : radius = 22.0; + const Avatar.large({super.key, required this.imageUrl, this.onPressed}) + : radius = 44.0; + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: onPressed, + child: CircleAvatar( + radius: radius, + backgroundImage: CachedNetworkImageProvider(imageUrl), + // backgroundImage: const CachedNetworkImageProvider( + // 'https://pixabay.com/photos/knit-cap-person-outdoors-sunlight-7600730/'), + backgroundColor: kCardColor, + ), + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index a48c6ef150..b79a620d32 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -49,7 +49,19 @@ packages: name: convert url: "https://pub.dartlang.org" source: hosted +<<<<<<< Updated upstream version: "2.1.1" +======= + version: "3.1.1" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" + url: "https://pub.dev" + source: hosted + version: "0.3.4+2" +>>>>>>> Stashed changes crypto: dependency: transitive description: @@ -63,12 +75,291 @@ packages: name: cupertino_icons url: "https://pub.dartlang.org" source: hosted +<<<<<<< Updated upstream version: "0.1.2" +======= + version: "1.0.8" + dbus: + dependency: transitive + description: + name: dbus + sha256: "365c771ac3b0e58845f39ec6deebc76e3276aa9922b0cc60840712094d9047ac" + url: "https://pub.dev" + source: hosted + version: "0.7.10" + dio: + dependency: transitive + description: + name: dio + sha256: e17f6b3097b8c51b72c74c9f071a605c47bcc8893839bd66732457a5ebe73714 + url: "https://pub.dev" + source: hosted + version: "5.5.0+1" + dio_web_adapter: + dependency: transitive + description: + name: dio_web_adapter + sha256: "36c5b2d79eb17cdae41e974b7a8284fec631651d2a6f39a8a2ff22327e90aeac" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + equatable: + dependency: transitive + description: + name: equatable + sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 + url: "https://pub.dev" + source: hosted + version: "2.0.5" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + faker: + dependency: "direct main" + description: + name: faker + sha256: "746e59f91d8b06a389e74cf76e909a05ed69c12691768e2f93557fdf29200fd0" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + ffi: + dependency: transitive + description: + name: ffi + sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + file: + dependency: transitive + description: + name: file + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + file_selector_linux: + dependency: transitive + description: + name: file_selector_linux + sha256: "045d372bf19b02aeb69cacf8b4009555fb5f6f0b7ad8016e5f46dd1387ddd492" + url: "https://pub.dev" + source: hosted + version: "0.9.2+1" + file_selector_macos: + dependency: transitive + description: + name: file_selector_macos + sha256: f42eacb83b318e183b1ae24eead1373ab1334084404c8c16e0354f9a3e55d385 + url: "https://pub.dev" + source: hosted + version: "0.9.4" + file_selector_platform_interface: + dependency: transitive + description: + name: file_selector_platform_interface + sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b + url: "https://pub.dev" + source: hosted + version: "2.6.2" + file_selector_windows: + dependency: transitive + description: + name: file_selector_windows + sha256: "2ad726953f6e8affbc4df8dc78b77c3b4a060967a291e528ef72ae846c60fb69" + url: "https://pub.dev" + source: hosted + version: "0.9.3+2" + firebase_auth: + dependency: "direct main" + description: + name: firebase_auth + sha256: "2457ac6cbc152fa464aad3fb35f98039b0c4ab8e9bedf476672508b291bdbc3a" + url: "https://pub.dev" + source: hosted + version: "5.1.4" + firebase_auth_platform_interface: + dependency: transitive + description: + name: firebase_auth_platform_interface + sha256: "0408e2ed74b1afa0490a93aa041fe90d7573af7ffc59a641edc6c5b5c1b8d2a4" + url: "https://pub.dev" + source: hosted + version: "7.4.3" + firebase_auth_web: + dependency: transitive + description: + name: firebase_auth_web + sha256: "7e0c6d0fa8c5c1b2ae126a78f2d1a206a77a913f78d20f155487bf746162dccc" + url: "https://pub.dev" + source: hosted + version: "5.12.5" + firebase_core: + dependency: "direct main" + description: + name: firebase_core + sha256: "3187f4f8e49968573fd7403011dca67ba95aae419bc0d8131500fae160d94f92" + url: "https://pub.dev" + source: hosted + version: "3.3.0" + firebase_core_platform_interface: + dependency: transitive + description: + name: firebase_core_platform_interface + sha256: "3c3a1e92d6f4916c32deea79c4a7587aa0e9dbbe5889c7a16afcf005a485ee02" + url: "https://pub.dev" + source: hosted + version: "5.2.0" + firebase_core_web: + dependency: transitive + description: + name: firebase_core_web + sha256: e8d1e22de72cb21cdcfc5eed7acddab3e99cd83f3b317f54f7a96c32f25fd11e + url: "https://pub.dev" + source: hosted + version: "2.17.4" + firebase_database: + dependency: "direct main" + description: + name: firebase_database + sha256: e758ef2be8530ba84cf9a483255a9bb1bf0df458884196155a0e643972db730c + url: "https://pub.dev" + source: hosted + version: "11.0.4" + firebase_database_platform_interface: + dependency: transitive + description: + name: firebase_database_platform_interface + sha256: a1a2c17effa98da2366c70b5444c45df758edc33aef27608ee55ab6d28159f39 + url: "https://pub.dev" + source: hosted + version: "0.2.5+40" + firebase_database_web: + dependency: transitive + description: + name: firebase_database_web + sha256: e89f2008fea74d9f9e54d39ff5039b68db11349ccaef5ac3ddfcffd6c1ea270e + url: "https://pub.dev" + source: hosted + version: "0.2.5+12" + firebase_messaging: + dependency: "direct main" + description: + name: firebase_messaging + sha256: "1b0a4f9ecbaf9007771bac152afad738ddfacc4b8431a7591c00829480d99553" + url: "https://pub.dev" + source: hosted + version: "15.0.4" + firebase_messaging_platform_interface: + dependency: transitive + description: + name: firebase_messaging_platform_interface + sha256: c5a6443e66ae064fe186901d740ee7ce648ca2a6fd0484b8c5e963849ac0fc28 + url: "https://pub.dev" + source: hosted + version: "4.5.42" + firebase_messaging_web: + dependency: transitive + description: + name: firebase_messaging_web + sha256: "232ef63b986467ae5b5577a09c2502b26e2e2aebab5b85e6c966a5ca9b038b89" + url: "https://pub.dev" + source: hosted + version: "3.8.12" + firebase_storage: + dependency: "direct main" + description: + name: firebase_storage + sha256: "9c837ed303aea5fb7d1f4ad097f6ab092310c33af9cd290e738c65670f3ce7f1" + url: "https://pub.dev" + source: hosted + version: "12.1.3" + firebase_storage_platform_interface: + dependency: transitive + description: + name: firebase_storage_platform_interface + sha256: "889db34d0369f7c0f3b40af058d6e1ea5a6622e0a4592483bf5923327071f5d0" + url: "https://pub.dev" + source: hosted + version: "5.1.27" + firebase_storage_web: + dependency: transitive + description: + name: firebase_storage_web + sha256: "95aeed3265f5aacee98f8ede842bae5b34360fe8a5f09b2a811688f3ac7f7c99" + url: "https://pub.dev" + source: hosted + version: "3.9.12" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" + source: hosted + version: "1.1.0" +>>>>>>> Stashed changes flutter: dependency: "direct main" description: flutter source: sdk version: "0.0.0" +<<<<<<< Updated upstream +======= + flutter_animate: + dependency: "direct main" + description: + name: flutter_animate + sha256: "7c8a6594a9252dad30cc2ef16e33270b6248c4dedc3b3d06c86c4f3f4dc05ae5" + url: "https://pub.dev" + source: hosted + version: "4.5.0" + flutter_cache_manager: + dependency: transitive + description: + name: flutter_cache_manager + sha256: a77f77806a790eb9ba0118a5a3a936e81c4fea2b61533033b2b0c3d50bbde5ea + url: "https://pub.dev" + source: hosted + version: "3.4.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c" + url: "https://pub.dev" + source: hosted + version: "4.0.0" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: "9d98bd47ef9d34e803d438f17fd32b116d31009f534a6fa5ce3a1167f189a6de" + url: "https://pub.dev" + source: hosted + version: "2.0.21" + flutter_shaders: + dependency: transitive + description: + name: flutter_shaders + sha256: "02750b545c01ff4d8e9bbe8f27a7731aa3778402506c67daa1de7f5fc3f4befe" + url: "https://pub.dev" + source: hosted + version: "0.1.2" + flutter_spinkit: + dependency: "direct main" + description: + name: flutter_spinkit + sha256: d2696eed13732831414595b98863260e33e8882fc069ee80ec35d4ac9ddb0472 + url: "https://pub.dev" + source: hosted + version: "5.2.1" +>>>>>>> Stashed changes flutter_test: dependency: "direct dev" description: flutter @@ -80,7 +371,227 @@ packages: name: image url: "https://pub.dartlang.org" source: hosted +<<<<<<< Updated upstream version: "2.1.4" +======= + version: "2.4.4" + google_identity_services_web: + dependency: transitive + description: + name: google_identity_services_web + sha256: "5be191523702ba8d7a01ca97c17fca096822ccf246b0a9f11923a6ded06199b6" + url: "https://pub.dev" + source: hosted + version: "0.3.1+4" + google_sign_in: + dependency: "direct main" + description: + name: google_sign_in + sha256: "0b8787cb9c1a68ad398e8010e8c8766bfa33556d2ab97c439fb4137756d7308f" + url: "https://pub.dev" + source: hosted + version: "6.2.1" + google_sign_in_android: + dependency: transitive + description: + name: google_sign_in_android + sha256: "5a47ebec9af97daf0822e800e4f101c3340b5ebc3f6898cf860c1a71b53cf077" + url: "https://pub.dev" + source: hosted + version: "6.1.28" + google_sign_in_ios: + dependency: transitive + description: + name: google_sign_in_ios + sha256: a058c9880be456f21e2e8571c1126eaacd570bdc5b6c6d9d15aea4bdf22ca9fe + url: "https://pub.dev" + source: hosted + version: "5.7.6" + google_sign_in_platform_interface: + dependency: transitive + description: + name: google_sign_in_platform_interface + sha256: "1f6e5787d7a120cc0359ddf315c92309069171306242e181c09472d1b00a2971" + url: "https://pub.dev" + source: hosted + version: "2.4.5" + google_sign_in_web: + dependency: transitive + description: + name: google_sign_in_web + sha256: "042805a21127a85b0dc46bba98a37926f17d2439720e8a459d27045d8ef68055" + url: "https://pub.dev" + source: hosted + version: "0.12.4+2" + http: + dependency: transitive + description: + name: http + sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 + url: "https://pub.dev" + source: hosted + version: "1.2.2" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + image_picker: + dependency: "direct main" + description: + name: image_picker + sha256: "021834d9c0c3de46bf0fe40341fa07168407f694d9b2bb18d532dc1261867f7a" + url: "https://pub.dev" + source: hosted + version: "1.1.2" + image_picker_android: + dependency: transitive + description: + name: image_picker_android + sha256: c0e72ecd170b00a5590bb71238d57dc8ad22ee14c60c6b0d1a4e05cafbc5db4b + url: "https://pub.dev" + source: hosted + version: "0.8.12+11" + image_picker_for_web: + dependency: transitive + description: + name: image_picker_for_web + sha256: "65d94623e15372c5c51bebbcb820848d7bcb323836e12dfdba60b5d3a8b39e50" + url: "https://pub.dev" + source: hosted + version: "3.0.5" + image_picker_ios: + dependency: transitive + description: + name: image_picker_ios + sha256: "6703696ad49f5c3c8356d576d7ace84d1faf459afb07accbb0fae780753ff447" + url: "https://pub.dev" + source: hosted + version: "0.8.12" + image_picker_linux: + dependency: transitive + description: + name: image_picker_linux + sha256: "4ed1d9bb36f7cd60aa6e6cd479779cc56a4cb4e4de8f49d487b1aaad831300fa" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" + image_picker_macos: + dependency: transitive + description: + name: image_picker_macos + sha256: "3f5ad1e8112a9a6111c46d0b57a7be2286a9a07fc6e1976fdf5be2bd31d4ff62" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" + image_picker_platform_interface: + dependency: transitive + description: + name: image_picker_platform_interface + sha256: "9ec26d410ff46f483c5519c29c02ef0e02e13a543f882b152d4bfd2f06802f80" + url: "https://pub.dev" + source: hosted + version: "2.10.0" + image_picker_windows: + dependency: transitive + description: + name: image_picker_windows + sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" + intl: + dependency: transitive + description: + name: intl + sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf + url: "https://pub.dev" + source: hosted + version: "0.19.0" + jiffy: + dependency: "direct main" + description: + name: jiffy + sha256: "3497caaa36d36a29033e66803c9739ce6bccbc7e241ca46070f76ee9e6f6eb0c" + url: "https://pub.dev" + source: hosted + version: "6.3.1" + jose: + dependency: transitive + description: + name: jose + sha256: "7955ec5d131960104e81fbf151abacb9d835c16c9e793ed394b2809f28b2198d" + url: "https://pub.dev" + source: hosted + version: "0.3.4" + js: + dependency: transitive + description: + name: js + sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf + url: "https://pub.dev" + source: hosted + version: "0.7.1" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" + url: "https://pub.dev" + source: hosted + version: "4.9.0" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" + url: "https://pub.dev" + source: hosted + version: "10.0.4" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" + url: "https://pub.dev" + source: hosted + version: "3.0.3" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" + lints: + dependency: transitive + description: + name: lints + sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235" + url: "https://pub.dev" + source: hosted + version: "4.0.0" + logger: + dependency: "direct main" + description: + name: logger + sha256: "697d067c60c20999686a0add96cf6aba723b3aa1f83ecf806a8097231529ec32" + url: "https://pub.dev" + source: hosted + version: "2.4.0" + logging: + dependency: transitive + description: + name: logging + sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" + url: "https://pub.dev" + source: hosted + version: "1.2.0" +>>>>>>> Stashed changes matcher: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index e6d5ae3d17..dd14fb4d8e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -9,8 +9,31 @@ environment: dependencies: flutter: sdk: flutter +<<<<<<< Updated upstream cupertino_icons: ^0.1.2 +======= + cupertino_icons: ^1.0.2 + flutter_animate: ^4.5.0 + animated_text_kit: ^4.2.2 + firebase_auth: ^5.1.1 + firebase_messaging: ^15.0.2 + firebase_database: ^11.0.2 + + firebase_core: ^3.1.1 + cloud_firestore: ^5.0.2 + google_sign_in: ^6.2.1 + modal_progress_hud_alt: ^1.0.0 + flutter_spinkit: ^5.2.1 + cached_network_image: ^3.4.0 + faker: ^2.1.0 + jiffy: ^6.3.1 + stream_chat_flutter_core: ^8.0.0 + logger: ^2.4.0 + cloud_functions: ^5.0.4 + image_picker: ^1.1.2 + firebase_storage: ^12.1.3 +>>>>>>> Stashed changes dev_dependencies: flutter_test: diff --git a/test/widget_test.dart b/test/widget_test.dart new file mode 100644 index 0000000000..ecf138dd8d --- /dev/null +++ b/test/widget_test.dart @@ -0,0 +1,32 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility in the flutter_test package. 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:flash_chat/main.dart'; +import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; + +void main() { + testWidgets('Counter increments smoke test', (WidgetTester tester) async { + // Build our app and trigger a frame. + StreamChatClient client = StreamChatClient('streamApi', logLevel: Level.INFO); + await tester.pumpWidget(Chateo(client: client,)); + + // 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 486db32fde4714e864fcaba92746eceb996c4319 Mon Sep 17 00:00:00 2001 From: codeme5 Date: Wed, 21 Aug 2024 14:12:35 +0500 Subject: [PATCH 2/2] added the update details screen and the profile screen along with client side logic fro Stream login, logout and delete --- .firebaserc | 5 + .flutter-plugins-dependencies | 2 +- analysis_options.yaml | 28 ++ firebase.json | 19 + firestore.indexes.json | 4 + firestore.rules | 19 + ios/Flutter/Debug.xcconfig | 1 + ios/Flutter/Flutter.podspec | 18 + ios/Flutter/Release.xcconfig | 1 + ios/Podfile | 41 ++ lib/constants.dart | 15 +- lib/helpers/helpers.dart | 4 +- lib/helpers/random_date.dart | 6 + lib/helpers/random_image.dart | 10 + lib/main.dart | 21 - lib/models/message_data.dart | 16 + lib/models/models.dart | 2 + lib/models/story_data.dart | 5 + lib/screens/chat_screen.dart | 279 ++++++++++-- lib/screens/home_pages/calls.dart | 13 + lib/screens/home_pages/contacts.dart | 4 +- lib/screens/home_pages/messages.dart | 1 + lib/screens/home_pages/notifications.dart | 13 + lib/screens/login_screen.dart | 94 +--- lib/screens/registration_screen.dart | 115 +---- lib/screens/welcome_screen.dart | 175 ++++--- lib/widgets/glowing_action_button.dart | 46 ++ lib/widgets/icon_button_2.dart | 59 +++ lib/widgets/widgets.dart | 3 + pubspec.lock | 530 ++++++++++++++++++---- pubspec.yaml | 12 +- 31 files changed, 1104 insertions(+), 457 deletions(-) create mode 100644 .firebaserc create mode 100644 analysis_options.yaml create mode 100644 firebase.json create mode 100644 firestore.indexes.json create mode 100644 firestore.rules create mode 100644 ios/Flutter/Flutter.podspec create mode 100644 ios/Podfile create mode 100644 lib/helpers/random_date.dart create mode 100644 lib/helpers/random_image.dart create mode 100644 lib/models/message_data.dart create mode 100644 lib/models/models.dart create mode 100644 lib/models/story_data.dart create mode 100644 lib/screens/home_pages/calls.dart create mode 100644 lib/screens/home_pages/notifications.dart create mode 100644 lib/widgets/glowing_action_button.dart create mode 100644 lib/widgets/icon_button_2.dart create mode 100644 lib/widgets/widgets.dart diff --git a/.firebaserc b/.firebaserc new file mode 100644 index 0000000000..c8ecc32596 --- /dev/null +++ b/.firebaserc @@ -0,0 +1,5 @@ +{ + "projects": { + "default": "chateo-72766" + } +} diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index 8c3cd86a28..948a6d51d1 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"cloud_firestore","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/cloud_firestore-5.2.1/","native_build":true,"dependencies":["firebase_core"]},{"name":"cloud_functions","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/cloud_functions-5.0.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"connectivity_plus","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/connectivity_plus-6.0.4/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"firebase_auth","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_auth-5.1.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_core","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_core-3.3.0/","native_build":true,"dependencies":[]},{"name":"firebase_database","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_database-11.0.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_messaging","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_messaging-15.0.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_storage","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_storage-12.1.3/","native_build":true,"dependencies":["firebase_core"]},{"name":"google_sign_in_ios","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/google_sign_in_ios-5.7.6/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"image_picker_ios","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/image_picker_ios-0.8.12/","native_build":true,"dependencies":[]},{"name":"path_provider_foundation","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.0/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"sqflite","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/sqflite-2.3.3+1/","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"android":[{"name":"cloud_firestore","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/cloud_firestore-5.2.1/","native_build":true,"dependencies":["firebase_core"]},{"name":"cloud_functions","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/cloud_functions-5.0.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"connectivity_plus","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/connectivity_plus-6.0.4/","native_build":true,"dependencies":[]},{"name":"firebase_auth","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_auth-5.1.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_core","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_core-3.3.0/","native_build":true,"dependencies":[]},{"name":"firebase_database","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_database-11.0.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_messaging","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_messaging-15.0.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_storage","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_storage-12.1.3/","native_build":true,"dependencies":["firebase_core"]},{"name":"flutter_plugin_android_lifecycle","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/flutter_plugin_android_lifecycle-2.0.21/","native_build":true,"dependencies":[]},{"name":"google_sign_in_android","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/google_sign_in_android-6.1.28/","native_build":true,"dependencies":[]},{"name":"image_picker_android","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/image_picker_android-0.8.12+11/","native_build":true,"dependencies":["flutter_plugin_android_lifecycle"]},{"name":"path_provider_android","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/path_provider_android-2.2.9/","native_build":true,"dependencies":[]},{"name":"sqflite","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/sqflite-2.3.3+1/","native_build":true,"dependencies":[]}],"macos":[{"name":"cloud_firestore","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/cloud_firestore-5.2.1/","native_build":true,"dependencies":["firebase_core"]},{"name":"cloud_functions","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/cloud_functions-5.0.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"connectivity_plus","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/connectivity_plus-6.0.4/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"file_selector_macos","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/file_selector_macos-0.9.4/","native_build":true,"dependencies":[]},{"name":"firebase_auth","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_auth-5.1.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_core","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_core-3.3.0/","native_build":true,"dependencies":[]},{"name":"firebase_database","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_database-11.0.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_messaging","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_messaging-15.0.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_storage","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_storage-12.1.3/","native_build":true,"dependencies":["firebase_core"]},{"name":"google_sign_in_ios","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/google_sign_in_ios-5.7.6/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"image_picker_macos","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/image_picker_macos-0.2.1+1/","native_build":false,"dependencies":["file_selector_macos"]},{"name":"path_provider_foundation","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.0/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"sqflite","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/sqflite-2.3.3+1/","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"linux":[{"name":"connectivity_plus","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/connectivity_plus-6.0.4/","native_build":false,"dependencies":[]},{"name":"file_selector_linux","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/file_selector_linux-0.9.2+1/","native_build":true,"dependencies":[]},{"name":"image_picker_linux","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/image_picker_linux-0.2.1+1/","native_build":false,"dependencies":["file_selector_linux"]},{"name":"path_provider_linux","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/","native_build":false,"dependencies":[]}],"windows":[{"name":"cloud_firestore","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/cloud_firestore-5.2.1/","native_build":true,"dependencies":["firebase_core"]},{"name":"connectivity_plus","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/connectivity_plus-6.0.4/","native_build":true,"dependencies":[]},{"name":"file_selector_windows","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/file_selector_windows-0.9.3+2/","native_build":true,"dependencies":[]},{"name":"firebase_auth","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_auth-5.1.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_core","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_core-3.3.0/","native_build":true,"dependencies":[]},{"name":"firebase_storage","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_storage-12.1.3/","native_build":true,"dependencies":["firebase_core"]},{"name":"image_picker_windows","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/image_picker_windows-0.2.1+1/","native_build":false,"dependencies":["file_selector_windows"]},{"name":"path_provider_windows","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/","native_build":false,"dependencies":[]}],"web":[{"name":"cloud_firestore_web","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/cloud_firestore_web-4.1.1/","dependencies":["firebase_core_web"]},{"name":"cloud_functions_web","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/cloud_functions_web-4.9.11/","dependencies":["firebase_core_web"]},{"name":"connectivity_plus","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/connectivity_plus-6.0.4/","dependencies":[]},{"name":"firebase_auth_web","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_auth_web-5.12.5/","dependencies":["firebase_core_web"]},{"name":"firebase_core_web","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_core_web-2.17.4/","dependencies":[]},{"name":"firebase_database_web","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_database_web-0.2.5+12/","dependencies":["firebase_core_web"]},{"name":"firebase_messaging_web","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_messaging_web-3.8.12/","dependencies":["firebase_core_web"]},{"name":"firebase_storage_web","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_storage_web-3.9.12/","dependencies":["firebase_core_web"]},{"name":"google_sign_in_web","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/google_sign_in_web-0.12.4+2/","dependencies":[]},{"name":"image_picker_for_web","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/image_picker_for_web-3.0.5/","dependencies":[]}]},"dependencyGraph":[{"name":"cloud_firestore","dependencies":["cloud_firestore_web","firebase_core"]},{"name":"cloud_firestore_web","dependencies":["firebase_core","firebase_core_web"]},{"name":"cloud_functions","dependencies":["cloud_functions_web","firebase_core"]},{"name":"cloud_functions_web","dependencies":["firebase_core","firebase_core_web"]},{"name":"connectivity_plus","dependencies":[]},{"name":"file_selector_linux","dependencies":[]},{"name":"file_selector_macos","dependencies":[]},{"name":"file_selector_windows","dependencies":[]},{"name":"firebase_auth","dependencies":["firebase_auth_web","firebase_core"]},{"name":"firebase_auth_web","dependencies":["firebase_core","firebase_core_web"]},{"name":"firebase_core","dependencies":["firebase_core_web"]},{"name":"firebase_core_web","dependencies":[]},{"name":"firebase_database","dependencies":["firebase_core","firebase_database_web"]},{"name":"firebase_database_web","dependencies":["firebase_core","firebase_core_web"]},{"name":"firebase_messaging","dependencies":["firebase_core","firebase_messaging_web"]},{"name":"firebase_messaging_web","dependencies":["firebase_core","firebase_core_web"]},{"name":"firebase_storage","dependencies":["firebase_core","firebase_storage_web"]},{"name":"firebase_storage_web","dependencies":["firebase_core","firebase_core_web"]},{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"google_sign_in","dependencies":["google_sign_in_android","google_sign_in_ios","google_sign_in_web"]},{"name":"google_sign_in_android","dependencies":[]},{"name":"google_sign_in_ios","dependencies":[]},{"name":"google_sign_in_web","dependencies":[]},{"name":"image_picker","dependencies":["image_picker_android","image_picker_for_web","image_picker_ios","image_picker_linux","image_picker_macos","image_picker_windows"]},{"name":"image_picker_android","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"image_picker_for_web","dependencies":[]},{"name":"image_picker_ios","dependencies":[]},{"name":"image_picker_linux","dependencies":["file_selector_linux"]},{"name":"image_picker_macos","dependencies":["file_selector_macos"]},{"name":"image_picker_windows","dependencies":["file_selector_windows"]},{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"sqflite","dependencies":[]}],"date_created":"2024-08-21 10:45:10.665798","version":"3.22.2"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"cloud_firestore","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/cloud_firestore-5.2.1/","native_build":true,"dependencies":["firebase_core"]},{"name":"cloud_functions","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/cloud_functions-5.0.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"connectivity_plus","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/connectivity_plus-6.0.5/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"firebase_auth","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_auth-5.1.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_core","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_core-3.3.0/","native_build":true,"dependencies":[]},{"name":"firebase_database","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_database-11.0.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_messaging","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_messaging-15.0.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_storage","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_storage-12.1.3/","native_build":true,"dependencies":["firebase_core"]},{"name":"google_sign_in_ios","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/google_sign_in_ios-5.7.6/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"image_picker_ios","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/image_picker_ios-0.8.12/","native_build":true,"dependencies":[]},{"name":"path_provider_foundation","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.0/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"sqflite","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/sqflite-2.3.3+1/","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"android":[{"name":"cloud_firestore","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/cloud_firestore-5.2.1/","native_build":true,"dependencies":["firebase_core"]},{"name":"cloud_functions","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/cloud_functions-5.0.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"connectivity_plus","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/connectivity_plus-6.0.5/","native_build":true,"dependencies":[]},{"name":"firebase_auth","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_auth-5.1.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_core","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_core-3.3.0/","native_build":true,"dependencies":[]},{"name":"firebase_database","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_database-11.0.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_messaging","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_messaging-15.0.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_storage","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_storage-12.1.3/","native_build":true,"dependencies":["firebase_core"]},{"name":"flutter_plugin_android_lifecycle","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/flutter_plugin_android_lifecycle-2.0.21/","native_build":true,"dependencies":[]},{"name":"google_sign_in_android","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/google_sign_in_android-6.1.28/","native_build":true,"dependencies":[]},{"name":"image_picker_android","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/image_picker_android-0.8.12+12/","native_build":true,"dependencies":["flutter_plugin_android_lifecycle"]},{"name":"path_provider_android","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/path_provider_android-2.2.10/","native_build":true,"dependencies":[]},{"name":"sqflite","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/sqflite-2.3.3+1/","native_build":true,"dependencies":[]}],"macos":[{"name":"cloud_firestore","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/cloud_firestore-5.2.1/","native_build":true,"dependencies":["firebase_core"]},{"name":"cloud_functions","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/cloud_functions-5.0.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"connectivity_plus","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/connectivity_plus-6.0.5/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"file_selector_macos","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/file_selector_macos-0.9.4/","native_build":true,"dependencies":[]},{"name":"firebase_auth","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_auth-5.1.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_core","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_core-3.3.0/","native_build":true,"dependencies":[]},{"name":"firebase_database","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_database-11.0.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_messaging","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_messaging-15.0.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_storage","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_storage-12.1.3/","native_build":true,"dependencies":["firebase_core"]},{"name":"google_sign_in_ios","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/google_sign_in_ios-5.7.6/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"image_picker_macos","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/image_picker_macos-0.2.1+1/","native_build":false,"dependencies":["file_selector_macos"]},{"name":"path_provider_foundation","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.0/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"sqflite","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/sqflite-2.3.3+1/","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"linux":[{"name":"connectivity_plus","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/connectivity_plus-6.0.5/","native_build":false,"dependencies":[]},{"name":"file_selector_linux","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/file_selector_linux-0.9.2+1/","native_build":true,"dependencies":[]},{"name":"image_picker_linux","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/image_picker_linux-0.2.1+1/","native_build":false,"dependencies":["file_selector_linux"]},{"name":"path_provider_linux","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/","native_build":false,"dependencies":[]}],"windows":[{"name":"cloud_firestore","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/cloud_firestore-5.2.1/","native_build":true,"dependencies":["firebase_core"]},{"name":"connectivity_plus","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/connectivity_plus-6.0.5/","native_build":true,"dependencies":[]},{"name":"file_selector_windows","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/file_selector_windows-0.9.3+2/","native_build":true,"dependencies":[]},{"name":"firebase_auth","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_auth-5.1.4/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_core","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_core-3.3.0/","native_build":true,"dependencies":[]},{"name":"firebase_storage","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_storage-12.1.3/","native_build":true,"dependencies":["firebase_core"]},{"name":"image_picker_windows","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/image_picker_windows-0.2.1+1/","native_build":false,"dependencies":["file_selector_windows"]},{"name":"path_provider_windows","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/","native_build":false,"dependencies":[]}],"web":[{"name":"cloud_firestore_web","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/cloud_firestore_web-4.1.1/","dependencies":["firebase_core_web"]},{"name":"cloud_functions_web","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/cloud_functions_web-4.9.11/","dependencies":["firebase_core_web"]},{"name":"connectivity_plus","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/connectivity_plus-6.0.5/","dependencies":[]},{"name":"firebase_auth_web","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_auth_web-5.12.5/","dependencies":["firebase_core_web"]},{"name":"firebase_core_web","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_core_web-2.17.4/","dependencies":[]},{"name":"firebase_database_web","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_database_web-0.2.5+12/","dependencies":["firebase_core_web"]},{"name":"firebase_messaging_web","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_messaging_web-3.8.12/","dependencies":["firebase_core_web"]},{"name":"firebase_storage_web","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/firebase_storage_web-3.9.12/","dependencies":["firebase_core_web"]},{"name":"google_sign_in_web","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/google_sign_in_web-0.12.4+2/","dependencies":[]},{"name":"image_picker_for_web","path":"/Users/meesumabbas/.pub-cache/hosted/pub.dev/image_picker_for_web-3.0.5/","dependencies":[]}]},"dependencyGraph":[{"name":"cloud_firestore","dependencies":["cloud_firestore_web","firebase_core"]},{"name":"cloud_firestore_web","dependencies":["firebase_core","firebase_core_web"]},{"name":"cloud_functions","dependencies":["cloud_functions_web","firebase_core"]},{"name":"cloud_functions_web","dependencies":["firebase_core","firebase_core_web"]},{"name":"connectivity_plus","dependencies":[]},{"name":"file_selector_linux","dependencies":[]},{"name":"file_selector_macos","dependencies":[]},{"name":"file_selector_windows","dependencies":[]},{"name":"firebase_auth","dependencies":["firebase_auth_web","firebase_core"]},{"name":"firebase_auth_web","dependencies":["firebase_core","firebase_core_web"]},{"name":"firebase_core","dependencies":["firebase_core_web"]},{"name":"firebase_core_web","dependencies":[]},{"name":"firebase_database","dependencies":["firebase_core","firebase_database_web"]},{"name":"firebase_database_web","dependencies":["firebase_core","firebase_core_web"]},{"name":"firebase_messaging","dependencies":["firebase_core","firebase_messaging_web"]},{"name":"firebase_messaging_web","dependencies":["firebase_core","firebase_core_web"]},{"name":"firebase_storage","dependencies":["firebase_core","firebase_storage_web"]},{"name":"firebase_storage_web","dependencies":["firebase_core","firebase_core_web"]},{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"google_sign_in","dependencies":["google_sign_in_android","google_sign_in_ios","google_sign_in_web"]},{"name":"google_sign_in_android","dependencies":[]},{"name":"google_sign_in_ios","dependencies":[]},{"name":"google_sign_in_web","dependencies":[]},{"name":"image_picker","dependencies":["image_picker_android","image_picker_for_web","image_picker_ios","image_picker_linux","image_picker_macos","image_picker_windows"]},{"name":"image_picker_android","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"image_picker_for_web","dependencies":[]},{"name":"image_picker_ios","dependencies":[]},{"name":"image_picker_linux","dependencies":["file_selector_linux"]},{"name":"image_picker_macos","dependencies":["file_selector_macos"]},{"name":"image_picker_windows","dependencies":["file_selector_windows"]},{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"sqflite","dependencies":[]}],"date_created":"2024-08-21 14:08:29.960398","version":"3.22.2"} \ No newline at end of file diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000000..0d2902135c --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,28 @@ +# 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.dev/lints. + # + # 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/firebase.json b/firebase.json new file mode 100644 index 0000000000..2a5ee701ac --- /dev/null +++ b/firebase.json @@ -0,0 +1,19 @@ +{ + "firestore": { + "rules": "firestore.rules", + "indexes": "firestore.indexes.json" + }, + "functions": [ + { + "source": "functions", + "codebase": "default", + "ignore": [ + "node_modules", + ".git", + "firebase-debug.log", + "firebase-debug.*.log", + "*.local" + ] + } + ] +} diff --git a/firestore.indexes.json b/firestore.indexes.json new file mode 100644 index 0000000000..415027e5dd --- /dev/null +++ b/firestore.indexes.json @@ -0,0 +1,4 @@ +{ + "indexes": [], + "fieldOverrides": [] +} diff --git a/firestore.rules b/firestore.rules new file mode 100644 index 0000000000..4f5f71f622 --- /dev/null +++ b/firestore.rules @@ -0,0 +1,19 @@ +rules_version = '2'; + +service cloud.firestore { + match /databases/{database}/documents { + + // This rule allows anyone with your Firestore database reference to view, edit, + // and delete all data in your Firestore database. It is useful for getting + // started, but it is configured to expire after 30 days because it + // leaves your app open to attackers. At that time, all client + // requests to your Firestore database will be denied. + // + // Make sure to write security rules for your app before that time, or else + // all client requests to your Firestore database will be denied until you Update + // your rules + match /{document=**} { + allow read, write: if request.time < timestamp.date(2024, 8, 31); + } + } +} \ No newline at end of file diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig index 592ceee85b..ec97fc6f30 100644 --- a/ios/Flutter/Debug.xcconfig +++ b/ios/Flutter/Debug.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" diff --git a/ios/Flutter/Flutter.podspec b/ios/Flutter/Flutter.podspec new file mode 100644 index 0000000000..98e1633950 --- /dev/null +++ b/ios/Flutter/Flutter.podspec @@ -0,0 +1,18 @@ +# +# This podspec is NOT to be published. It is only used as a local source! +# This is a generated file; do not edit or check into version control. +# + +Pod::Spec.new do |s| + s.name = 'Flutter' + s.version = '1.0.0' + s.summary = 'A UI toolkit for beautiful and fast apps.' + s.homepage = 'https://flutter.dev' + s.license = { :type => 'BSD' } + s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' } + s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s } + s.ios.deployment_target = '12.0' + # Framework linking is handled by Flutter tooling, not CocoaPods. + # Add a placeholder to satisfy `s.dependency 'Flutter'` plugin podspecs. + s.vendored_frameworks = 'path/to/nothing' +end diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig index 592ceee85b..c4855bfe20 100644 --- a/ios/Flutter/Release.xcconfig +++ b/ios/Flutter/Release.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" diff --git a/ios/Podfile b/ios/Podfile new file mode 100644 index 0000000000..c9339a034e --- /dev/null +++ b/ios/Podfile @@ -0,0 +1,41 @@ +# 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 + 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/lib/constants.dart b/lib/constants.dart index e76ff76817..fa5e5a4643 100644 --- a/lib/constants.dart +++ b/lib/constants.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; -<<<<<<< Updated upstream -======= + import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; import 'package:logger/logger.dart' as log; +import 'theme.dart'; const kBlueBody = Color(0x90002DE3); const kBlue2 = Color(0xFF002DE3); @@ -15,7 +15,6 @@ const streamApi = 'chvdm4sex6zq'; final logger = log.Logger(); const genericUrl = 'https://firebasestorage.googleapis.com/v0/b/chateo-72766.appspot.com/o/profile_pictures%2FGeneric%20Image.png?alt=media&token=995355af-474e-40e8-8f43-daff2ff93918'; ->>>>>>> Stashed changes const kSendButtonTextStyle = TextStyle( color: Colors.lightBlueAccent, @@ -34,8 +33,6 @@ const kMessageContainerDecoration = BoxDecoration( top: BorderSide(color: Colors.lightBlueAccent, width: 2.0), ), ); -<<<<<<< Updated upstream -======= TextStyle kHeadingStyle1( {double fontSize = 32.0, Color color = const Color(0xFF0F1828)}) { @@ -241,8 +238,10 @@ Widget getImageButton( ); } -extension StreaChatContext on BuildContext { - String? get userImage => StreamChatCore.of(this).currentUser!.image; +extension StreamChatContext on BuildContext { + /// Fetches the current user image. + String? get userImage => user!.image; + + /// Fetches the current user. User? get user => StreamChatCore.of(this).currentUser; } ->>>>>>> Stashed changes diff --git a/lib/helpers/helpers.dart b/lib/helpers/helpers.dart index cd1b3e669b..b2fbe088df 100644 --- a/lib/helpers/helpers.dart +++ b/lib/helpers/helpers.dart @@ -1,3 +1,3 @@ -export './random_image.dart'; -export './random_date.dart'; export './channel_info.dart'; +export './random_date.dart'; +export './random_image.dart'; diff --git a/lib/helpers/random_date.dart b/lib/helpers/random_date.dart new file mode 100644 index 0000000000..eafbdfd584 --- /dev/null +++ b/lib/helpers/random_date.dart @@ -0,0 +1,6 @@ +import 'dart:math'; + +DateTime randomDate() { + DateTime date = DateTime.now(); + return date.subtract(Duration(seconds: Random().nextInt(200000))); +} diff --git a/lib/helpers/random_image.dart b/lib/helpers/random_image.dart new file mode 100644 index 0000000000..3e3a986dad --- /dev/null +++ b/lib/helpers/random_image.dart @@ -0,0 +1,10 @@ +import 'dart:math'; + +int randomNumberGenerator() { + return Random().nextInt(1000); +} + +String randomImageUrl() { + final int randomNumber = randomNumberGenerator(); + return 'https://picsum.photos/seed/$randomNumber/200/300'; +} diff --git a/lib/main.dart b/lib/main.dart index 45822b2145..3337e46a96 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,23 +1,3 @@ -<<<<<<< Updated upstream -import 'package:flutter/material.dart'; -import 'package:flash_chat/screens/welcome_screen.dart'; -import 'package:flash_chat/screens/login_screen.dart'; -import 'package:flash_chat/screens/registration_screen.dart'; -import 'package:flash_chat/screens/chat_screen.dart'; - -void main() => runApp(FlashChat()); - -class FlashChat extends StatelessWidget { - @override - Widget build(BuildContext context) { - return MaterialApp( - theme: ThemeData.dark().copyWith( - textTheme: TextTheme( - body1: TextStyle(color: Colors.black54), - ), - ), - home: WelcomeScreen(), -======= import 'package:cloud_functions/cloud_functions.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flash_chat/constants.dart'; @@ -89,7 +69,6 @@ class Chateo extends StatelessWidget { '/update_details': (context) => const UpdateDetailsScreen(), '/profile': (context) => const ProfileScreen(), }, ->>>>>>> Stashed changes ); } } diff --git a/lib/models/message_data.dart b/lib/models/message_data.dart new file mode 100644 index 0000000000..8cb209efc5 --- /dev/null +++ b/lib/models/message_data.dart @@ -0,0 +1,16 @@ +import 'package:meta/meta.dart'; + +@immutable +class MessageData { + const MessageData( + {required this.name, + required this.message, + required this.profilePicture, + required this.messageDate, + required this.dateMessage}); + final String name; + final String message; + final String profilePicture; + final DateTime messageDate; + final String dateMessage; +} diff --git a/lib/models/models.dart b/lib/models/models.dart new file mode 100644 index 0000000000..e6a7de10f6 --- /dev/null +++ b/lib/models/models.dart @@ -0,0 +1,2 @@ +export './story_data.dart'; +export './message_data.dart'; diff --git a/lib/models/story_data.dart b/lib/models/story_data.dart new file mode 100644 index 0000000000..73f9064f3b --- /dev/null +++ b/lib/models/story_data.dart @@ -0,0 +1,5 @@ +class StoryData { + const StoryData({required this.url, required this.name}); + final String url; + final String name; +} diff --git a/lib/screens/chat_screen.dart b/lib/screens/chat_screen.dart index 42d8b67b9b..ac57de9e78 100644 --- a/lib/screens/chat_screen.dart +++ b/lib/screens/chat_screen.dart @@ -1,60 +1,263 @@ +import 'package:flash_chat/models/models.dart'; +import 'package:flash_chat/widgets/widgets.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:flash_chat/constants.dart'; +import 'package:flutter/widgets.dart'; + +import '../constants.dart'; class ChatScreen extends StatefulWidget { + const ChatScreen({super.key}); + @override - _ChatScreenState createState() => _ChatScreenState(); + State createState() => _ChatScreenState(); } class _ChatScreenState extends State { @override Widget build(BuildContext context) { + final messageData = + ModalRoute.of(context)!.settings.arguments as MessageData; return Scaffold( - appBar: AppBar( - leading: null, - actions: [ - IconButton( - icon: Icon(Icons.close), - onPressed: () { - //Implement logout functionality - }), + appBar: AppBar( + leading: Align( + alignment: Alignment.centerRight, + child: Avatar.medium(imageUrl: messageData.profilePicture), + ), + title: Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + messageData.name, + style: Theme.of(context) + .textTheme + .bodyLarge + ?.copyWith(fontWeight: FontWeight.w900), + ), + Text( + 'Online', + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(fontWeight: FontWeight.w500, color: kGreen), + ) + ], + ), + ], + ), + actions: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: IconButtonBorder( + onPressed: () {}, icon: CupertinoIcons.video_camera), + ), + Padding( + padding: const EdgeInsets.only(top: 8.0, right: 8.0, bottom: 8.0), + child: IconButtonBorder( + onPressed: () {}, icon: CupertinoIcons.phone), + ), + ], + ), + body: const Column( + children: [Expanded(child: _MessageList()), _ActionBar()], + )); + } +} + +class _MessageList extends StatefulWidget { + const _MessageList({super.key}); + + @override + State<_MessageList> createState() => _MessageListState(); +} + +class _MessageListState extends State<_MessageList> { + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: ListView( + children: const [ + DateLabel(label: "Yesterday"), + _Message(message: "Hi Meesum", date: "21/7/23"), + _Message(message: "Hello there", date: "21/7/23", byMe: true), + _Message( + message: + "I have heard that you are developing a stupid chat application", + date: "21/7/23"), + _Message(message: "How's it going?", date: "21/7/23"), + _Message( + message: + "Ahhh yess, Chateo. It is such a wonderful app and the Ui is almost ready. this is the last thing I need to complete", + date: "21/7/23", + byMe: true, + ), ], - title: Text('⚡️Chat'), - backgroundColor: Colors.lightBlueAccent, ), - body: SafeArea( - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Container( - decoration: kMessageContainerDecoration, - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Expanded( - child: TextField( - onChanged: (value) { - //Do something with the user input. - }, - decoration: kMessageTextFieldDecoration, + ); + } +} + +class _Message extends StatelessWidget { + final String message; + final String date; + final bool byMe; + static const double radius = 16; + const _Message( + {super.key, + required this.message, + required this.date, + this.byMe = false}); + + @override + Widget build(BuildContext context) { + final screenWidth = MediaQuery.of(context).size.width; + return Align( + alignment: byMe ? Alignment.centerRight : Alignment.centerLeft, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: + byMe ? CrossAxisAlignment.end : CrossAxisAlignment.start, + children: [ + Container( + decoration: byMe + ? BoxDecoration( + color: Theme.of(context).primaryColor, + borderRadius: const BorderRadius.only( + topRight: Radius.circular(radius), + bottomLeft: Radius.circular(radius), + topLeft: Radius.circular(radius), ), - ), - FlatButton( - onPressed: () { - //Implement send functionality. - }, - child: Text( - 'Send', - style: kSendButtonTextStyle, + ) + : BoxDecoration( + color: Theme.of(context).cardColor, + borderRadius: const BorderRadius.only( + topRight: Radius.circular(radius), + bottomLeft: Radius.circular(radius), + bottomRight: Radius.circular(radius), ), ), - ], + child: ConstrainedBox( + constraints: BoxConstraints(maxWidth: (screenWidth * (2 / 3))), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + message, + style: byMe + ? Theme.of(context) + .textTheme + .bodyLarge + ?.copyWith(color: kWhite) + : Theme.of(context).textTheme.bodyLarge, + ), ), ), - ], + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 4.0), + child: Text( + date, + style: Theme.of(context).textTheme.labelMedium, + ), + ) + ], + ), + ); + } +} + +class DateLabel extends StatelessWidget { + const DateLabel({super.key, required this.label}); + final String label; + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 12.0), + child: Center( + child: Card( + color: Theme.of(context).cardColor, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 12), + child: Text(label), + ), ), ), ); } } + +class _ActionBar extends StatefulWidget { + const _ActionBar({super.key}); + + @override + State<_ActionBar> createState() => _ActionBarState(); +} + +class _ActionBarState extends State<_ActionBar> { + @override + Widget build(BuildContext context) { + final screenWidth = MediaQuery.of(context).size.width; + return ConstrainedBox( + constraints: BoxConstraints(minWidth: screenWidth), + child: Container( + color: Theme.of(context).cardColor, + child: SafeArea( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: Row( + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + child: IconButton2( + onPressed: () { + print('Camera'); + }, + icon: CupertinoIcons.camera_fill), + ), + Expanded( + child: Padding( + padding: const EdgeInsets.only(right: 8.0), + child: Container( + alignment: Alignment.centerLeft, + height: 30, + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 2.5), + decoration: BoxDecoration( + color: + Theme.of(context).primaryColor.withOpacity(0.1), + borderRadius: BorderRadius.all(Radius.circular(24))), + child: TextField( + textAlign: TextAlign.left, + decoration: InputDecoration( + border: InputBorder.none, + hintText: 'Type Something...', + hintStyle: Theme.of(context) + .textTheme + .bodyLarge + ?.copyWith( + color: Theme.of(context).disabledColor)), + style: Theme.of(context).textTheme.bodyLarge, + ), + ), + ), + ), + Padding( + padding: const EdgeInsets.only(right: 8.0), + child: GlowingActionButton( + size: 30, + color: const Color(0xFF7BCBCF), + icon: Icons.send_rounded, + onPressed: () { + print('send'); + }), + ) + ], + ), + ), + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/screens/home_pages/calls.dart b/lib/screens/home_pages/calls.dart new file mode 100644 index 0000000000..58bc442084 --- /dev/null +++ b/lib/screens/home_pages/calls.dart @@ -0,0 +1,13 @@ +import 'package:flash_chat/constants.dart'; +import 'package:flutter/material.dart'; + +class CallScreen extends StatelessWidget { + const CallScreen({super.key}); + + @override + Widget build(BuildContext context) { + return Center( + child: Text('Calls Screen', style: kBodyStyle1(color: Theme.of(context).primaryColorDark)), + ); + } +} diff --git a/lib/screens/home_pages/contacts.dart b/lib/screens/home_pages/contacts.dart index c466cfe4e6..1a9f62ee06 100644 --- a/lib/screens/home_pages/contacts.dart +++ b/lib/screens/home_pages/contacts.dart @@ -1,5 +1,5 @@ -import 'package:flash_chat/constants.dart'; -import 'package:flash_chat/widgets/widgets.dart'; +import '../../constants.dart'; +import '../../widgets/widgets.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; diff --git a/lib/screens/home_pages/messages.dart b/lib/screens/home_pages/messages.dart index dd891f6f6b..19c234f534 100644 --- a/lib/screens/home_pages/messages.dart +++ b/lib/screens/home_pages/messages.dart @@ -6,6 +6,7 @@ import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; import '../../models/models.dart'; import '../../widgets/widgets.dart'; +import '../../constants.dart'; class MessageScreen extends StatefulWidget { const MessageScreen({super.key}); diff --git a/lib/screens/home_pages/notifications.dart b/lib/screens/home_pages/notifications.dart new file mode 100644 index 0000000000..42c87255c6 --- /dev/null +++ b/lib/screens/home_pages/notifications.dart @@ -0,0 +1,13 @@ +import 'package:flash_chat/constants.dart'; +import 'package:flutter/material.dart'; + +class NotificationScreen extends StatelessWidget { + const NotificationScreen({super.key}); + + @override + Widget build(BuildContext context) { + return Center( + child: Text('Notifications Screen', style: kBodyStyle1(color: Theme.of(context).primaryColorDark)), + ); + } +} diff --git a/lib/screens/login_screen.dart b/lib/screens/login_screen.dart index deb84d1535..2ec1730dc2 100644 --- a/lib/screens/login_screen.dart +++ b/lib/screens/login_screen.dart @@ -1,6 +1,5 @@ -<<<<<<< Updated upstream import 'package:flutter/material.dart'; -======= + import 'package:cloud_functions/cloud_functions.dart'; import 'package:flash_chat/constants.dart'; import 'package:flutter/material.dart'; @@ -10,7 +9,6 @@ import 'package:modal_progress_hud_alt/modal_progress_hud_alt.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart' as stream_chat; ->>>>>>> Stashed changes class LoginScreen extends StatefulWidget { const LoginScreen({super.key}); @@ -19,46 +17,6 @@ class LoginScreen extends StatefulWidget { } class _LoginScreenState extends State { -<<<<<<< Updated upstream - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Colors.white, - body: Padding( - padding: EdgeInsets.symmetric(horizontal: 24.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Container( - height: 200.0, - child: Image.asset('images/logo.png'), - ), - SizedBox( - height: 48.0, - ), - TextField( - onChanged: (value) { - //Do something with the user input. - }, - decoration: InputDecoration( - hintText: 'Enter your email', - contentPadding: - EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0), - border: OutlineInputBorder( - borderRadius: BorderRadius.all(Radius.circular(32.0)), - ), - enabledBorder: OutlineInputBorder( - borderSide: - BorderSide(color: Colors.lightBlueAccent, width: 1.0), - borderRadius: BorderRadius.all(Radius.circular(32.0)), - ), - focusedBorder: OutlineInputBorder( - borderSide: - BorderSide(color: Colors.lightBlueAccent, width: 2.0), - borderRadius: BorderRadius.all(Radius.circular(32.0)), - ), -======= String email = ''; String password = ''; final _auth = FirebaseAuth.instance; @@ -217,57 +175,9 @@ class _LoginScreenState extends State { }); }), ], ->>>>>>> Stashed changes - ), - ), - SizedBox( - height: 8.0, - ), - TextField( - onChanged: (value) { - //Do something with the user input. - }, - decoration: InputDecoration( - hintText: 'Enter your password.', - contentPadding: - EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0), - border: OutlineInputBorder( - borderRadius: BorderRadius.all(Radius.circular(32.0)), - ), - enabledBorder: OutlineInputBorder( - borderSide: - BorderSide(color: Colors.lightBlueAccent, width: 1.0), - borderRadius: BorderRadius.all(Radius.circular(32.0)), - ), - focusedBorder: OutlineInputBorder( - borderSide: - BorderSide(color: Colors.lightBlueAccent, width: 2.0), - borderRadius: BorderRadius.all(Radius.circular(32.0)), - ), - ), - ), - SizedBox( - height: 24.0, - ), - Padding( - padding: EdgeInsets.symmetric(vertical: 16.0), - child: Material( - color: Colors.lightBlueAccent, - borderRadius: BorderRadius.all(Radius.circular(30.0)), - elevation: 5.0, - child: MaterialButton( - onPressed: () { - //Implement login functionality. - }, - minWidth: 200.0, - height: 42.0, - child: Text( - 'Log In', - ), - ), ), ), - ], + ), ), ), ); diff --git a/lib/screens/registration_screen.dart b/lib/screens/registration_screen.dart index cb584a19b5..c67828d6da 100644 --- a/lib/screens/registration_screen.dart +++ b/lib/screens/registration_screen.dart @@ -1,9 +1,10 @@ -<<<<<<< Updated upstream -======= import 'package:cloud_functions/cloud_functions.dart'; import 'package:flash_chat/constants.dart'; ->>>>>>> Stashed changes import 'package:flutter/material.dart'; +import 'package:firebase_auth/firebase_auth.dart'; +import '../services/otherSignIn.dart'; +import 'package:modal_progress_hud_alt/modal_progress_hud_alt.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; class RegistrationScreen extends StatefulWidget { @override @@ -11,44 +12,14 @@ class RegistrationScreen extends StatefulWidget { } class _RegistrationScreenState extends State { + String email = ''; + String password = ''; + bool loading = false; + final FirebaseFunctions _functions = FirebaseFunctions.instance; + final _auth = FirebaseAuth.instance; @override Widget build(BuildContext context) { return Scaffold( -<<<<<<< Updated upstream - backgroundColor: Colors.white, - body: Padding( - padding: EdgeInsets.symmetric(horizontal: 24.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Container( - height: 200.0, - child: Image.asset('images/logo.png'), - ), - SizedBox( - height: 48.0, - ), - TextField( - onChanged: (value) { - //Do something with the user input. - }, - decoration: InputDecoration( - hintText: 'Enter your email', - contentPadding: - EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0), - border: OutlineInputBorder( - borderRadius: BorderRadius.all(Radius.circular(32.0)), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide(color: Colors.blueAccent, width: 1.0), - borderRadius: BorderRadius.all(Radius.circular(32.0)), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide(color: Colors.blueAccent, width: 2.0), - borderRadius: BorderRadius.all(Radius.circular(32.0)), - ), -======= backgroundColor: Theme.of(context).scaffoldBackgroundColor, body: ModalProgressHUD( progressIndicator: SpinKitChasingDots( @@ -130,21 +101,16 @@ class _RegistrationScreenState extends State { 'Sign In with Google', context: context, onPressed: () async { + setState(() { + loading = true; + }); final userCred = await signInWithGoogle(); - print(userCred.user); if (userCred.user != null) { - if (userCred.user?.emailVerified == true) { - final callable = _functions - .httpsCallable('createStreamUserAndGetToken'); - final results = await callable(); - final token = results.data; - print( - 'Stream account created, token: $token'); - Navigator.pushNamed(context, '/home', arguments: token); - } else { - Navigator.pushNamed(context, '/verify'); - } + Navigator.pushNamed(context, '/update_details'); } + setState(() { + loading = false; + }); }, image: 'google.png', ), @@ -173,56 +139,9 @@ class _RegistrationScreenState extends State { }, ) ], ->>>>>>> Stashed changes - ), - ), - SizedBox( - height: 8.0, - ), - TextField( - onChanged: (value) { - //Do something with the user input. - }, - decoration: InputDecoration( - hintText: 'Enter your password', - contentPadding: - EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0), - border: OutlineInputBorder( - borderRadius: BorderRadius.all(Radius.circular(32.0)), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide(color: Colors.blueAccent, width: 1.0), - borderRadius: BorderRadius.all(Radius.circular(32.0)), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide(color: Colors.blueAccent, width: 2.0), - borderRadius: BorderRadius.all(Radius.circular(32.0)), - ), - ), - ), - SizedBox( - height: 24.0, - ), - Padding( - padding: EdgeInsets.symmetric(vertical: 16.0), - child: Material( - color: Colors.blueAccent, - borderRadius: BorderRadius.all(Radius.circular(30.0)), - elevation: 5.0, - child: MaterialButton( - onPressed: () { - //Implement registration functionality. - }, - minWidth: 200.0, - height: 42.0, - child: Text( - 'Register', - style: TextStyle(color: Colors.white), - ), - ), ), ), - ], + ), ), ), ); diff --git a/lib/screens/welcome_screen.dart b/lib/screens/welcome_screen.dart index 49746d4d80..b41311df06 100644 --- a/lib/screens/welcome_screen.dart +++ b/lib/screens/welcome_screen.dart @@ -1,24 +1,17 @@ -<<<<<<< Updated upstream -import 'package:flutter/material.dart'; -======= import 'package:cloud_functions/cloud_functions.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flash_chat/constants.dart'; import 'package:flutter/material.dart'; import 'package:flutter_animate/flutter_animate.dart'; -import 'package:animated_text_kit/animated_text_kit.dart'; import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart' as stream_chat; ->>>>>>> Stashed changes +import 'package:animated_text_kit/animated_text_kit.dart'; class WelcomeScreen extends StatefulWidget { @override _WelcomeScreenState createState() => _WelcomeScreenState(); } -<<<<<<< Updated upstream -class _WelcomeScreenState extends State { -======= class _WelcomeScreenState extends State with SingleTickerProviderStateMixin { bool _isFirstAnimationComplete = false; @@ -60,73 +53,90 @@ class _WelcomeScreenState extends State }); } ->>>>>>> Stashed changes @override Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Colors.white, - body: Padding( - padding: EdgeInsets.symmetric(horizontal: 24.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Row( - children: [ - Container( - child: Image.asset('images/logo.png'), - height: 60.0, - ), - Text( - 'Flash Chat', - style: TextStyle( - fontSize: 45.0, - fontWeight: FontWeight.w900, - ), - ), - ], - ), - SizedBox( - height: 48.0, - ), - Padding( - padding: EdgeInsets.symmetric(vertical: 16.0), - child: Material( - elevation: 5.0, - color: Colors.lightBlueAccent, - borderRadius: BorderRadius.circular(30.0), - child: MaterialButton( - onPressed: () { - //Go to login screen. - }, - minWidth: 200.0, - height: 42.0, - child: Text( - 'Log In', - ), -<<<<<<< Updated upstream -======= - const SizedBox( - height: 10, + return PopScope( + canPop: false, + child: Scaffold( + backgroundColor: Theme.of(context).scaffoldBackgroundColor, + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 24.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Column( + children: [ + const SizedBox(height: 100.0), + SizedBox( + height: 250.0, + child: MediaQuery.of(context).platformBrightness == + Brightness.dark + ? Image.asset('images/first_dark.png') + : Image.asset('images/first.png')), + Hero( + tag: 'logo', + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + height: 45.0, + child: Image.asset('images/logo.png') + .animate() + .scale( + duration: 1.seconds, + begin: const Offset(0.5, 0.5), + end: const Offset(1.5, 1.5), + curve: Curves.bounceOut, + ) + .fade( + duration: 1.seconds, + ), + ), + const SizedBox(width: 20.0), + AnimatedTextKit( + isRepeatingAnimation: false, + animatedTexts: [ + TypewriterAnimatedText( + 'Chateo', + textStyle: Theme.of(context) + .textTheme + .titleLarge + ?.copyWith(fontSize: 45), + speed: const Duration(milliseconds: 500), + ), + ], + pause: const Duration(minutes: 2), + onTap: () { + print("Tap Event"); + }, + ), + ], + ), + ), ), if (_isFirstAnimationComplete) - Text( - 'Connecting you with the world!', - textAlign: TextAlign.center, - style: kHeadingStyle1( - fontSize: 20.0, - color: Theme.of(context).primaryColorDark), - ) - .animate() - .slideY( - duration: 1.seconds, - begin: 1.0, - end: 0.0, - curve: Curves.easeInOut, - ) - .fade( - duration: 1.seconds, - ) + SizedBox( + height: 10, + ), + Text( + 'Connecting you with the world!', + textAlign: TextAlign.center, + style: kHeadingStyle1( + fontSize: 20.0, + color: Theme.of(context).primaryColorDark), + ) + .animate() + .slideY( + duration: 1.seconds, + begin: 1.0, + end: 0.0, + curve: Curves.easeInOut, + ) + .fade( + duration: 1.seconds, + ) ], ), SafeArea( @@ -151,29 +161,10 @@ class _WelcomeScreenState extends State ), ), ], ->>>>>>> Stashed changes - ), - ), - ), - Padding( - padding: EdgeInsets.symmetric(vertical: 16.0), - child: Material( - color: Colors.blueAccent, - borderRadius: BorderRadius.circular(30.0), - elevation: 5.0, - child: MaterialButton( - onPressed: () { - //Go to registration screen. - }, - minWidth: 200.0, - height: 42.0, - child: Text( - 'Register', - ), ), ), - ), - ], + ], + ), ), ), ); diff --git a/lib/widgets/glowing_action_button.dart b/lib/widgets/glowing_action_button.dart new file mode 100644 index 0000000000..5c68b20946 --- /dev/null +++ b/lib/widgets/glowing_action_button.dart @@ -0,0 +1,46 @@ +import 'package:flash_chat/constants.dart'; +import 'package:flash_chat/theme.dart'; +import 'package:flutter/material.dart'; + +class GlowingActionButton extends StatelessWidget { + const GlowingActionButton( + {super.key, + required this.size, + required this.color, + required this.icon, + required this.onPressed, + this.iconSize, + this.iconColor}); + final double size; + final Color color; + final IconData icon; + final double? iconSize; + final Color? iconColor; + final VoidCallback onPressed; + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + color: color, + boxShadow: [ + BoxShadow( + color: color.withOpacity(0.2), spreadRadius: 10, blurRadius: 24) + ], + shape: BoxShape.circle), + child: ClipOval( + child: Material( + color: color, + child: InkWell( + onTap: onPressed, + splashColor: AppColors.darkCardColor, + child: SizedBox( + width: size, + height: size, + child: Icon(icon, + size: iconSize ?? size / 2, color: iconColor ?? kWhite)), + ), + ), + ), + ); + } +} diff --git a/lib/widgets/icon_button_2.dart b/lib/widgets/icon_button_2.dart new file mode 100644 index 0000000000..af77d11bef --- /dev/null +++ b/lib/widgets/icon_button_2.dart @@ -0,0 +1,59 @@ +import 'package:flutter/material.dart'; + +class IconButton2 extends StatelessWidget { + final VoidCallback onPressed; + final IconData icon; + final Color? splashColor; + const IconButton2( + {super.key, + required this.onPressed, + required this.icon, + this.splashColor}); + + @override + Widget build(BuildContext context) { + return Material( + color: Theme.of(context).cardColor, + borderRadius: BorderRadius.circular(6.0), + child: InkWell( + onTap: onPressed, + splashColor: splashColor ?? Theme.of(context).primaryColor, + borderRadius: BorderRadius.circular(6.0), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Icon(icon, color: Theme.of(context).iconTheme.color, size: 18), + ), + ), + ); + } +} + +class IconButtonBorder extends StatelessWidget { + final VoidCallback onPressed; + final IconData icon; + final Color? splashColor; + const IconButtonBorder( + {super.key, + required this.onPressed, + required this.icon, + this.splashColor}); + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + color: Colors.transparent, + border: Border.all(color: Theme.of(context).disabledColor), + borderRadius: const BorderRadius.all(Radius.circular(8))), + child: InkWell( + onTap: onPressed, + splashColor: splashColor ?? Theme.of(context).cardColor, + borderRadius: BorderRadius.circular(6.0), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Icon(icon, color: Theme.of(context).iconTheme.color, size: 18), + ), + ), + ); + } +} diff --git a/lib/widgets/widgets.dart b/lib/widgets/widgets.dart new file mode 100644 index 0000000000..54e01c2646 --- /dev/null +++ b/lib/widgets/widgets.dart @@ -0,0 +1,3 @@ +export 'avatar.dart'; +export 'icon_button_2.dart'; +export 'glowing_action_button.dart'; diff --git a/pubspec.lock b/pubspec.lock index b79a620d32..099c2e8a15 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,57 +1,173 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: - archive: + _flutterfire_internals: dependency: transitive description: - name: archive - url: "https://pub.dartlang.org" + name: _flutterfire_internals + sha256: b1595874fbc8f7a50da90f5d8f327bb0bfd6a95dc906c390efe991540c3b54aa + url: "https://pub.dev" + source: hosted + version: "1.3.40" + animated_text_kit: + dependency: "direct main" + description: + name: animated_text_kit + sha256: "37392a5376c9a1a503b02463c38bc0342ef814ddbb8f9977bc90f2a84b22fa92" + url: "https://pub.dev" source: hosted - version: "2.0.11" + version: "4.2.2" args: dependency: transitive description: name: args - url: "https://pub.dartlang.org" + sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" + url: "https://pub.dev" source: hosted - version: "1.5.2" + version: "2.5.0" + asn1lib: + dependency: transitive + description: + name: asn1lib + sha256: "58082b3f0dca697204dbab0ef9ff208bfaea7767ea771076af9a343488428dda" + url: "https://pub.dev" + source: hosted + version: "1.5.3" async: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.11.0" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dartlang.org" + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" source: hosted - version: "1.0.5" - charcode: + version: "2.1.1" + cached_network_image: + dependency: "direct main" + description: + name: cached_network_image + sha256: "4a5d8d2c728b0f3d0245f69f921d7be90cae4c2fd5288f773088672c0893f819" + url: "https://pub.dev" + source: hosted + version: "3.4.0" + cached_network_image_platform_interface: dependency: transitive description: - name: charcode - url: "https://pub.dartlang.org" + name: cached_network_image_platform_interface + sha256: "35814b016e37fbdc91f7ae18c8caf49ba5c88501813f73ce8a07027a395e2829" + url: "https://pub.dev" source: hosted - version: "1.1.2" + version: "4.1.1" + cached_network_image_web: + dependency: transitive + description: + name: cached_network_image_web + sha256: "6322dde7a5ad92202e64df659241104a43db20ed594c41ca18de1014598d7996" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + cloud_firestore: + dependency: "direct main" + description: + name: cloud_firestore + sha256: a31eec60eadaa859f0677bf661d9f86ed15961c716512f64884e59edcb341472 + url: "https://pub.dev" + source: hosted + version: "5.2.1" + cloud_firestore_platform_interface: + dependency: transitive + description: + name: cloud_firestore_platform_interface + sha256: "3224e6158441c8897325e74f9971140cde2c85ee75a26704407a91b969b50829" + url: "https://pub.dev" + source: hosted + version: "6.3.1" + cloud_firestore_web: + dependency: transitive + description: + name: cloud_firestore_web + sha256: c1312945cb7dd55921bcc10445f6c9a494bc04104b7d0821c3ed577b970ab088 + url: "https://pub.dev" + source: hosted + version: "4.1.1" + cloud_functions: + dependency: "direct main" + description: + name: cloud_functions + sha256: c1d73e3f107c4d8df0a196f5d28d324b3b654dba7f0a0ffc70ce3f9ddb8d200c + url: "https://pub.dev" + source: hosted + version: "5.0.4" + cloud_functions_platform_interface: + dependency: transitive + description: + name: cloud_functions_platform_interface + sha256: "69c6ea437f3a9e3078b6dd359c1b030e78a21d391cdfa7fa3b94b36a29f58ff3" + url: "https://pub.dev" + source: hosted + version: "5.5.33" + cloud_functions_web: + dependency: transitive + description: + name: cloud_functions_web + sha256: cdbd8782ff6d64687ad40f10034af748d400741741565e73f999854507bc55ee + url: "https://pub.dev" + source: hosted + version: "4.9.11" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + url: "https://pub.dev" + source: hosted + version: "1.18.0" + connectivity_plus: + dependency: transitive + description: + name: connectivity_plus + sha256: "2056db5241f96cdc0126bd94459fc4cdc13876753768fc7a31c425e50a7177d0" + url: "https://pub.dev" source: hosted - version: "1.14.11" + version: "6.0.5" + connectivity_plus_platform_interface: + dependency: transitive + description: + name: connectivity_plus_platform_interface + sha256: "42657c1715d48b167930d5f34d00222ac100475f73d10162ddf43e714932f204" + url: "https://pub.dev" + source: hosted + version: "2.0.1" convert: dependency: transitive description: name: convert - url: "https://pub.dartlang.org" + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" source: hosted -<<<<<<< Updated upstream - version: "2.1.1" -======= version: "3.1.1" cross_file: dependency: transitive @@ -61,23 +177,29 @@ packages: url: "https://pub.dev" source: hosted version: "0.3.4+2" ->>>>>>> Stashed changes crypto: dependency: transitive description: name: crypto - url: "https://pub.dartlang.org" + sha256: ec30d999af904f33454ba22ed9a86162b35e52b44ac4807d1d93c288041d7d27 + url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "3.0.5" + crypto_keys: + dependency: transitive + description: + name: crypto_keys + sha256: acc19abf34623d990a0e8aec69463d74a824c31f137128f42e2810befc509ad0 + url: "https://pub.dev" + source: hosted + version: "0.3.0+1" cupertino_icons: dependency: "direct main" description: name: cupertino_icons - url: "https://pub.dartlang.org" + sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 + url: "https://pub.dev" source: hosted -<<<<<<< Updated upstream - version: "0.1.2" -======= version: "1.0.8" dbus: dependency: transitive @@ -91,18 +213,18 @@ packages: dependency: transitive description: name: dio - sha256: e17f6b3097b8c51b72c74c9f071a605c47bcc8893839bd66732457a5ebe73714 + sha256: "0dfb6b6a1979dac1c1245e17cef824d7b452ea29bd33d3467269f9bef3715fb0" url: "https://pub.dev" source: hosted - version: "5.5.0+1" + version: "5.6.0" dio_web_adapter: dependency: transitive description: name: dio_web_adapter - sha256: "36c5b2d79eb17cdae41e974b7a8284fec631651d2a6f39a8a2ff22327e90aeac" + sha256: "33259a9276d6cea88774a0000cfae0d861003497755969c92faa223108620dc8" url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "2.0.0" equatable: dependency: transitive description: @@ -131,10 +253,10 @@ packages: dependency: transitive description: name: ffi - sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" + sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.3" file: dependency: transitive description: @@ -303,14 +425,11 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" ->>>>>>> Stashed changes flutter: dependency: "direct main" description: flutter source: sdk version: "0.0.0" -<<<<<<< Updated upstream -======= flutter_animate: dependency: "direct main" description: @@ -323,18 +442,10 @@ packages: dependency: transitive description: name: flutter_cache_manager - sha256: a77f77806a790eb9ba0118a5a3a936e81c4fea2b61533033b2b0c3d50bbde5ea + sha256: "400b6592f16a4409a7f2bb929a9a7e38c72cceb8ffb99ee57bbf2cb2cecf8386" url: "https://pub.dev" source: hosted - version: "3.4.0" - flutter_lints: - dependency: "direct dev" - description: - name: flutter_lints - sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c" - url: "https://pub.dev" - source: hosted - version: "4.0.0" + version: "3.4.1" flutter_plugin_android_lifecycle: dependency: transitive description: @@ -359,21 +470,23 @@ packages: url: "https://pub.dev" source: hosted version: "5.2.1" ->>>>>>> Stashed changes flutter_test: dependency: "direct dev" description: flutter source: sdk version: "0.0.0" - image: + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + freezed_annotation: dependency: transitive description: - name: image - url: "https://pub.dartlang.org" + name: freezed_annotation + sha256: c2e2d632dd9b8a2b7751117abcfc2b4888ecfe181bd9fca7170d9ef02e595fe2 + url: "https://pub.dev" source: hosted -<<<<<<< Updated upstream - version: "2.1.4" -======= version: "2.4.4" google_identity_services_web: dependency: transitive @@ -451,10 +564,10 @@ packages: dependency: transitive description: name: image_picker_android - sha256: c0e72ecd170b00a5590bb71238d57dc8ad22ee14c60c6b0d1a4e05cafbc5db4b + sha256: "8c5abf0dcc24fe6e8e0b4a5c0b51a5cf30cefdf6407a3213dae61edc75a70f56" url: "https://pub.dev" source: hosted - version: "0.8.12+11" + version: "0.8.12+12" image_picker_for_web: dependency: transitive description: @@ -567,14 +680,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.1" - lints: - dependency: transitive - description: - name: lints - sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235" - url: "https://pub.dev" - source: hosted - version: "4.0.0" logger: dependency: "direct main" description: @@ -591,49 +696,174 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" ->>>>>>> Stashed changes matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + url: "https://pub.dev" source: hosted - version: "0.12.6" + version: "0.12.16+1" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + url: "https://pub.dev" + source: hosted + version: "0.8.0" meta: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" + url: "https://pub.dev" + source: hosted + version: "1.12.0" + mime: + dependency: transitive + description: + name: mime + sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2" + url: "https://pub.dev" + source: hosted + version: "1.0.5" + modal_progress_hud_alt: + dependency: "direct main" + description: + name: modal_progress_hud_alt + sha256: "1964b25d2879d8732b8c84c22f972c060c1e508e6c88972e902a15dc92bc8db6" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + nm: + dependency: transitive + description: + name: nm + sha256: "2c9aae4127bdc8993206464fcc063611e0e36e72018696cd9631023a31b24254" + url: "https://pub.dev" + source: hosted + version: "0.5.0" + octo_image: + dependency: transitive + description: + name: octo_image + sha256: "34faa6639a78c7e3cbe79be6f9f96535867e879748ade7d17c9b1ae7536293bd" + url: "https://pub.dev" source: hosted - version: "1.1.8" + version: "2.1.0" path: dependency: transitive description: name: path - url: "https://pub.dartlang.org" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + url: "https://pub.dev" + source: hosted + version: "1.9.0" + path_provider: + dependency: transitive + description: + name: path_provider + sha256: fec0d61223fba3154d87759e3cc27fe2c8dc498f6386c6d6fc80d1afdd1bf378 + url: "https://pub.dev" + source: hosted + version: "2.1.4" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: "6f01f8e37ec30b07bc424b4deabac37cacb1bc7e2e515ad74486039918a37eb7" + url: "https://pub.dev" + source: hosted + version: "2.2.10" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16 + url: "https://pub.dev" source: hosted - version: "1.6.4" - pedantic: + version: "2.4.0" + path_provider_linux: dependency: transitive description: - name: pedantic - url: "https://pub.dartlang.org" + name: path_provider_linux + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://pub.dev" source: hosted - version: "1.8.0+1" + version: "2.2.1" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 + url: "https://pub.dev" + source: hosted + version: "2.3.0" petitparser: dependency: transitive description: name: petitparser - url: "https://pub.dartlang.org" + sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 + url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "6.0.2" + platform: + dependency: transitive + description: + name: platform + sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" + url: "https://pub.dev" + source: hosted + version: "3.1.5" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" + pointycastle: + dependency: transitive + description: + name: pointycastle + sha256: "4be0097fcf3fd3e8449e53730c631200ebc7b88016acecab2b0da2f0149222fe" + url: "https://pub.dev" + source: hosted + version: "3.9.1" quiver: dependency: transitive description: name: quiver - url: "https://pub.dartlang.org" + sha256: b1c1ac5ce6688d77f65f3375a9abb9319b3cb32486bdc7a1e0fdf004d7ba4e47 + url: "https://pub.dev" source: hosted - version: "2.0.5" + version: "3.2.1" + rate_limiter: + dependency: transitive + description: + name: rate_limiter + sha256: "2bae2e961adedf7fc2e8b0305d30e3a3619baf001d050c6907870c5c6235b559" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + rxdart: + dependency: transitive + description: + name: rxdart + sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb" + url: "https://pub.dev" + source: hosted + version: "0.27.7" sky_engine: dependency: transitive description: flutter @@ -643,64 +873,170 @@ packages: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" + source: hosted + version: "1.10.0" + sprintf: + dependency: transitive + description: + name: sprintf + sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + sqflite: + dependency: transitive + description: + name: sqflite + sha256: a43e5a27235518c03ca238e7b4732cf35eabe863a369ceba6cbefa537a66f16d + url: "https://pub.dev" + source: hosted + version: "2.3.3+1" + sqflite_common: + dependency: transitive + description: + name: sqflite_common + sha256: "3da423ce7baf868be70e2c0976c28a1bb2f73644268b7ffa7d2e08eab71f16a4" + url: "https://pub.dev" source: hosted - version: "1.5.5" + version: "2.5.4" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + url: "https://pub.dev" source: hosted - version: "1.9.3" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "2.1.2" + stream_chat: + dependency: transitive + description: + name: stream_chat + sha256: d3a8bd105c696afba9594c4bc45399d681a3ea2f78fd427473b9870146fffee2 + url: "https://pub.dev" + source: hosted + version: "8.0.0" + stream_chat_flutter_core: + dependency: "direct main" + description: + name: stream_chat_flutter_core + sha256: f6f5ff89b4bbca09ddffa0f394e855742275504d1228d8216c9dc9c640f20442 + url: "https://pub.dev" + source: hosted + version: "8.0.0" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" source: hosted - version: "1.0.5" + version: "1.2.0" + synchronized: + dependency: transitive + description: + name: synchronized + sha256: "539ef412b170d65ecdafd780f924e5be3f60032a1128df156adad6c5b373d558" + url: "https://pub.dev" + source: hosted + version: "3.1.0+1" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.2.1" test_api: dependency: transitive description: name: test_api - url: "https://pub.dartlang.org" + sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" + url: "https://pub.dev" source: hosted - version: "0.2.11" + version: "0.7.0" typed_data: dependency: transitive description: name: typed_data - url: "https://pub.dartlang.org" + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" + source: hosted + version: "1.3.2" + uuid: + dependency: transitive + description: + name: uuid + sha256: "83d37c7ad7aaf9aa8e275490669535c8080377cfa7a7004c24dfac53afffaa90" + url: "https://pub.dev" source: hosted - version: "1.1.6" + version: "4.4.2" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dartlang.org" + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" + url: "https://pub.dev" + source: hosted + version: "14.2.1" + web: + dependency: transitive + description: + name: web + sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" + url: "https://pub.dev" source: hosted - version: "2.0.8" + version: "0.5.1" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: "58c6666b342a38816b2e7e50ed0f1e261959630becd4c879c4f26bfa14aa5a42" + url: "https://pub.dev" + source: hosted + version: "2.4.5" + x509: + dependency: transitive + description: + name: x509 + sha256: "3262dc9a7d45b0876f886c01bfc7d5e765704f7dfd31f8cf5224fc875c17a6c6" + url: "https://pub.dev" + source: hosted + version: "0.2.4+2" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d + url: "https://pub.dev" + source: hosted + version: "1.0.4" xml: dependency: transitive description: name: xml - url: "https://pub.dartlang.org" + sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 + url: "https://pub.dev" source: hosted - version: "3.5.0" + version: "6.5.0" sdks: - dart: ">=2.4.0 <3.0.0" + dart: ">=3.4.0 <4.0.0" + flutter: ">=3.22.0" diff --git a/pubspec.yaml b/pubspec.yaml index dd14fb4d8e..5ce88d5eda 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,15 +4,12 @@ description: A new Flutter application. version: 1.0.0+1 environment: - sdk: ">=2.1.0<3.0.0" + sdk: '>=3.2.6 <4.0.0' dependencies: flutter: sdk: flutter -<<<<<<< Updated upstream - cupertino_icons: ^0.1.2 -======= cupertino_icons: ^1.0.2 flutter_animate: ^4.5.0 animated_text_kit: ^4.2.2 @@ -33,7 +30,6 @@ dependencies: cloud_functions: ^5.0.4 image_picker: ^1.1.2 firebase_storage: ^12.1.3 ->>>>>>> Stashed changes dev_dependencies: flutter_test: @@ -41,6 +37,10 @@ dev_dependencies: flutter: uses-material-design: true - + fonts: + - family: Mulish + fonts: + - asset: fonts/Mulish.ttf assets: - images/ + - fonts/