From 26c9fe81e5bda5330c80c813f42fb89971cb8a40 Mon Sep 17 00:00:00 2001 From: Magellan <39908400+CubeRomanMagellan@users.noreply.github.com> Date: Mon, 10 Nov 2025 16:47:36 +0200 Subject: [PATCH 01/17] SK-567: flutter sdk development (#90) * create monorepo * add api * remove client old api * add tokens management * rename sama_chat_api to sama_sdk --- lib/src/api/connection/exceptions.dart | 18 - .../conversation_remote_datasource.dart | 16 - lib/src/db/sama_db.dart | 50 -- lib/src/shared/utils/api_utils.dart | 2 - .env.example => sama_chat_client/.env.example | 0 sama_chat_client/.gitignore | 31 + sama_chat_client/.metadata | 45 ++ sama_chat_client/CHANGELOG.md | 135 ++++ sama_chat_client/LICENSE | 674 ++++++++++++++++++ sama_chat_client/README.md | 51 ++ .../analysis_options.yaml | 0 .../android}/.gitignore | 0 .../android}/app/build.gradle | 0 .../android}/app/google-services.json | 0 .../app/src/debug/AndroidManifest.xml | 0 .../android}/app/src/main/AndroidManifest.xml | 0 .../app/src/main/ic_launcher-playstore.png | Bin .../sama/sama_client_flutter/MainActivity.kt | 0 .../drawable-anydpi-v24/ic_notification.xml | 0 .../res/drawable-hdpi/ic_notification.png | Bin .../res/drawable-mdpi/ic_notification.png | Bin .../res/drawable-v21/launch_background.xml | 0 .../res/drawable-xhdpi/ic_notification.png | Bin .../res/drawable-xxhdpi/ic_notification.png | Bin .../res/drawable-xxxhdpi/ic_notification.png | Bin .../res/drawable/ic_launcher_foreground.xml | 0 .../main/res/drawable/launch_background.xml | 0 .../res/mipmap-anydpi-v26/ic_launcher.xml | 0 .../mipmap-anydpi-v26/ic_launcher_round.xml | 0 .../src/main/res/mipmap-hdpi/ic_launcher.webp | Bin .../mipmap-hdpi/ic_launcher_foreground.webp | Bin .../res/mipmap-hdpi/ic_launcher_round.webp | Bin .../src/main/res/mipmap-mdpi/ic_launcher.webp | Bin .../mipmap-mdpi/ic_launcher_foreground.webp | Bin .../res/mipmap-mdpi/ic_launcher_round.webp | Bin .../main/res/mipmap-xhdpi/ic_launcher.webp | Bin .../mipmap-xhdpi/ic_launcher_foreground.webp | Bin .../res/mipmap-xhdpi/ic_launcher_round.webp | Bin .../main/res/mipmap-xxhdpi/ic_launcher.webp | Bin .../mipmap-xxhdpi/ic_launcher_foreground.webp | Bin .../res/mipmap-xxhdpi/ic_launcher_round.webp | Bin .../main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin .../ic_launcher_foreground.webp | Bin .../res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin .../app/src/main/res/values-night/styles.xml | 0 .../res/values/ic_launcher_background.xml | 0 .../app/src/main/res/values/styles.xml | 0 .../app/src/profile/AndroidManifest.xml | 0 .../android}/build.gradle | 0 .../android}/gradle.properties | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 0 .../android}/sama_client_flutter_android.iml | 0 .../android}/settings.gradle | 0 .../assets}/images/1.5x/sama_background.png | Bin .../assets}/images/2.0x/sama_background.png | Bin .../assets}/images/3.0x/sama_background.png | Bin .../assets}/images/4.0x/sama_background.png | Bin .../assets}/images/Sama_Icon.png | Bin .../assets}/images/sama_background.png | Bin .../assets}/images/vector_logo.png | Bin .../devtools_options.yaml | 0 {ios => sama_chat_client/ios}/.gitignore | 0 .../ios}/Flutter/AppFrameworkInfo.plist | 0 .../ios}/Flutter/Debug.xcconfig | 0 .../ios}/Flutter/Release.xcconfig | 0 {ios => sama_chat_client/ios}/Gemfile | 0 {ios => sama_chat_client/ios}/Gemfile.lock | 0 .../ios}/NotificationService/Info.plist | 0 .../NotificationService.entitlements | 0 .../NotificationService.swift | 0 {ios => sama_chat_client/ios}/Podfile | 0 {ios => sama_chat_client/ios}/Podfile.lock | 151 ++-- .../ios}/Runner.xcodeproj/project.pbxproj | 0 .../contents.xcworkspacedata | 0 .../xcshareddata/IDEWorkspaceChecks.plist | 0 .../xcshareddata/WorkspaceSettings.xcsettings | 0 .../xcshareddata/xcschemes/Runner.xcscheme | 0 .../contents.xcworkspacedata | 0 .../xcshareddata/IDEWorkspaceChecks.plist | 0 .../xcshareddata/WorkspaceSettings.xcsettings | 0 .../ios}/Runner/AppDelegate.swift | 0 .../AppIcon.appiconset/Contents.json | 0 .../Icon-App-1024x1024@1x.png | Bin .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin .../AppIcon.appiconset/Icon-App-50x50@1x.png | Bin .../AppIcon.appiconset/Icon-App-50x50@2x.png | Bin .../AppIcon.appiconset/Icon-App-57x57@1x.png | Bin .../AppIcon.appiconset/Icon-App-57x57@2x.png | Bin .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin .../AppIcon.appiconset/Icon-App-72x72@1x.png | Bin .../AppIcon.appiconset/Icon-App-72x72@2x.png | Bin .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin .../Icon-App-83.5x83.5@2x.png | Bin .../AppIcon.appiconset/ItunesArtwork@2x.png | Bin .../ios}/Runner/Assets.xcassets/Contents.json | 0 .../LaunchImage.imageset/Contents.json | 0 .../LaunchImage.imageset/README.md | 0 .../LaunchImage.imageset/sama_1024.png | Bin .../Assets.xcassets/iTunesArtwork@1x.png | Bin .../Assets.xcassets/iTunesArtwork@2x.png | Bin .../Assets.xcassets/iTunesArtwork@3x.png | Bin .../Runner/Base.lproj/LaunchScreen.storyboard | 0 .../ios}/Runner/Base.lproj/Main.storyboard | 0 .../ios}/Runner/GoogleService-Info.plist | 0 .../ios}/Runner/Info.plist | 0 .../ios}/Runner/Runner-Bridging-Header.h | 0 .../ios}/Runner/Runner.entitlements | 0 .../ios}/RunnerTests/RunnerTests.swift | 0 .../Base.lproj/MainInterface.storyboard | 0 .../ios}/Share Extension/Info.plist | 0 .../Share Extension.entitlements | 0 .../Share Extension/ShareViewController.swift | 0 .../ios}/fastlane/Appfile | 0 .../ios}/fastlane/Fastfile | 0 .../ios}/firebase_app_id_file.json | 0 {lib => sama_chat_client/lib}/main.dart | 4 +- .../lib}/main.dart.run.xml | 0 .../lib}/objectbox-model.json | 0 .../lib}/objectbox.g.dart | 0 .../lib}/sama_firebase_options.dart | 0 .../lib}/src/db/db_service.dart | 0 .../db/local/attachment_local_datasource.dart | 0 .../local/conversation_local_datasource.dart | 0 .../db/local/message_local_datasource.dart | 0 .../src/db/local/user_local_datasource.dart | 0 .../lib}/src/db/models/attachment_model.dart | 16 +- .../lib}/src/db/models/avatar_model.dart | 3 +- .../src/db/models/conversation_model.dart | 0 .../lib}/src/db/models/message_model.dart | 2 +- .../lib}/src/db/models/models.dart | 0 .../lib}/src/db/models/user_model.dart | 2 +- .../lib}/src/db/network_bound_resource.dart | 0 .../lib}/src/db/resource.dart | 0 .../lib/src/features}/config.dart | 0 .../bloc/ai_message/ai_message_bloc.dart | 2 +- .../bloc/ai_message/ai_message_event.dart | 0 .../bloc/ai_message/ai_message_state.dart | 0 .../conversation/bloc/conversation_bloc.dart | 2 +- .../conversation/bloc/conversation_event.dart | 0 .../conversation/bloc/conversation_state.dart | 0 .../delete_messages/delete_messages_bloc.dart | 2 +- .../delete_messages_event.dart | 0 .../delete_messages_state.dart | 0 .../forward_messages_bloc.dart | 0 .../forward_messages_event.dart | 0 .../forward_messages_state.dart | 0 .../media_attachment_bloc.dart | 0 .../media_attachment_event.dart | 0 .../media_attachment_state.dart | 0 .../bloc/media_sender/media_sender_bloc.dart | 3 +- .../bloc/media_sender/media_sender_event.dart | 0 .../bloc/media_sender/media_sender_state.dart | 0 .../bloc/send_message/send_message_bloc.dart | 2 +- .../bloc/send_message/send_message_event.dart | 0 .../bloc/send_message/send_message_state.dart | 0 .../conversation/models/chat_message.dart | 0 .../features/conversation/models/models.dart | 0 .../models/selected_messages.dart | 4 +- .../conversation/view/conversation_page.dart | 8 +- .../conversation/view/media_sender.dart | 0 .../conversation/view/message_input.dart | 0 .../conversation/view/messages_list.dart | 3 +- .../widgets/focused_popup_menu.dart | 0 .../forward_messages/forward_bubble.dart | 0 .../forward_messages_widget.dart | 0 .../forward_messages/forward_search_form.dart | 0 .../widgets/header_input_box.dart | 0 .../widgets/media_attachment.dart | 0 .../widgets/media_attachment_widget.dart | 0 .../conversation/widgets/message_bubble.dart | 0 .../widgets/message_edit_widget.dart | 0 .../widgets/message_status_widget.dart | 0 .../conversation/widgets/reply_bubble.dart | 0 .../conversation/widgets/select_input.dart | 6 +- .../widgets/service_message_bubble.dart | 0 .../conversation/widgets/text_message.dart | 0 .../widgets/text_message_item.dart | 0 .../widgets/unsupported_message.dart | 0 .../bloc/conversation_create_bloc.dart | 0 .../bloc/conversation_create_event.dart | 0 .../bloc/conversation_create_state.dart | 0 .../bloc/group_bloc.dart | 0 .../bloc/group_event.dart | 0 .../bloc/group_state.dart | 0 .../models/avatar.dart | 0 .../models/groupname.dart | 0 .../models/participants.dart | 0 .../view/group_create_form.dart | 0 .../view/group_create_page.dart | 0 .../bloc/conversations_list_bloc.dart | 3 +- .../bloc/conversations_list_event.dart | 0 .../bloc/conversations_list_state.dart | 0 .../conversations_list.dart | 2 +- .../view/conversations_list.dart | 0 .../view/conversations_page.dart | 0 .../conversations_list/view/view.dart | 0 .../widgets/avatar_group_icon.dart | 0 .../widgets/avatar_letter_icon.dart | 0 .../widgets/conversation_list_item.dart | 2 +- .../conversations_list/widgets/widgets.dart | 0 .../group_info/bloc/group_info_bloc.dart | 2 +- .../group_info/bloc/group_info_event.dart | 0 .../group_info/bloc/group_info_state.dart | 0 .../group_info/models/group_avatar.dart | 0 .../group_info/models/group_description.dart | 0 .../group_info/models/group_name.dart | 0 .../group_info/models/group_participants.dart | 0 .../features/group_info/models/models.dart | 0 .../group_info/view/group_info_form.dart | 0 .../group_info/view/group_info_page.dart | 0 .../src/features/login/bloc/login_bloc.dart | 0 .../src/features/login/bloc/login_event.dart | 0 .../src/features/login/bloc/login_state.dart | 0 .../src/features/login/models/models.dart | 0 .../src/features/login/models/username.dart | 0 .../src/features/login/view/login_form.dart | 0 .../src/features/login/view/login_page.dart | 0 .../features/profile/bloc/profile_bloc.dart | 1 - .../features/profile/bloc/profile_event.dart | 0 .../features/profile/bloc/profile_state.dart | 0 .../src/features/profile/models/models.dart | 0 .../features/profile/models/user_avatar.dart | 0 .../features/profile/models/user_email.dart | 0 .../profile/models/user_firstname.dart | 0 .../profile/models/user_lastname.dart | 0 .../profile/models/user_password.dart | 0 .../features/profile/models/user_phone.dart | 0 .../features/profile/view/profile_form.dart | 0 .../features/profile/view/profile_page.dart | 0 .../bloc/reset_password_bloc.dart | 0 .../bloc/reset_password_event.dart | 0 .../bloc/reset_password_state.dart | 0 .../bloc/timer_bloc/timer_bloc.dart | 0 .../bloc/timer_bloc/timer_event.dart | 0 .../bloc/timer_bloc/timer_state.dart | 0 .../models/confirm_password.dart | 0 .../reset_password/models/models.dart | 0 .../features/reset_password/models/otp.dart | 0 .../src/features/reset_password/ticker.dart | 0 .../view/reset_password_page.dart | 0 .../reset_password/view/send_email_form.dart | 0 .../reset_password/view/send_otp_form.dart | 0 .../view/send_reset_password_form.dart | 0 .../search/bloc/global_search_bloc.dart | 0 .../search/bloc/global_search_event.dart | 0 .../search/bloc/global_search_state.dart | 0 .../src/features/search/models/models.dart | 0 .../features/search/models/search_result.dart | 0 .../search/models/search_result_error.dart | 0 .../src/features/search/view/search_bar.dart | 0 .../src/features/search/view/search_form.dart | 0 .../src/features/search/view/search_page.dart | 0 .../lib}/src/features/splash_page.dart | 0 .../user_info/view/user_info_form.dart | 0 .../user_info/view/user_info_page.dart | 1 - .../lib}/src/navigation/app_router.dart | 0 .../lib}/src/navigation/constants.dart | 0 .../attachments/attachments_repository.dart | 3 +- .../authentication_repository.dart | 66 +- .../conversation/conversation_repository.dart | 41 +- .../global_search_repository.dart | 8 +- .../messages/messages_repository.dart | 2 +- .../src/repository/user/user_repository.dart | 17 +- .../lib}/src/shared/auth/bloc/auth_bloc.dart | 16 +- .../lib}/src/shared/auth/bloc/auth_event.dart | 0 .../lib}/src/shared/auth/bloc/auth_state.dart | 0 .../connection/bloc/connection_bloc.dart | 4 +- .../connection/bloc/connection_event.dart | 0 .../connection/bloc/connection_state.dart | 0 .../connection/view/connection_checker.dart | 0 .../connection/view/connection_title.dart | 0 .../lib}/src/shared/errors/exceptions.dart | 0 .../messages_collector.dart | 6 +- .../lib}/src/shared/models/email.dart | 0 .../lib}/src/shared/models/password.dart | 0 .../bloc/push_notifications_bloc.dart | 2 +- .../bloc/push_notifications_event.dart | 0 .../bloc/push_notifications_state.dart | 0 .../push_notifications_manager.dart | 39 +- .../lib}/src/shared/secure_storage.dart | 27 +- .../sharing/bloc/sharing_intent_bloc.dart | 0 .../sharing/bloc/sharing_intent_event.dart | 0 .../sharing/bloc/sharing_intent_state.dart | 0 .../lib}/src/shared/ui/colors.dart | 0 .../src/shared/ui/view/loading_overlay.dart | 0 .../shared/ui/view/participants_forms.dart | 0 .../lib}/src/shared/ui/view/user_forms.dart | 0 .../lib/src/shared/utils/api_utils.dart | 3 + .../lib}/src/shared/utils/date_utils.dart | 0 .../lib}/src/shared/utils/file_utils.dart | 0 .../lib}/src/shared/utils/media_utils.dart | 0 .../lib}/src/shared/utils/observer_utils.dart | 0 .../lib}/src/shared/utils/regexp_utils.dart | 0 .../lib}/src/shared/utils/screen_factor.dart | 0 .../lib}/src/shared/utils/string_utils.dart | 3 +- .../src/shared/widget/env_dialog_widget.dart | 4 +- .../src/shared/widget/keyboard_listener.dart | 0 .../shared/widget/link_preview_widget.dart | 2 +- .../lib}/src/shared/widget/loaders.dart | 0 .../lib}/src/shared/widget/logo_app_bar.dart | 0 .../shared/widget/multi_gesture_detector.dart | 0 .../lib}/src/shared/widget/popup_menu.dart | 0 .../lib}/src/shared/widget/swipe_to.dart | 0 .../src/shared/widget/typing_indicator.dart | 0 .../lib}/src/shared/widget/vertical_line.dart | 0 pubspec.yaml => sama_chat_client/pubspec.yaml | 2 + .../sama_chat_client.iml | 5 +- .../test}/widget_test.dart | 0 sama_sdk/.gitignore | 31 + sama_sdk/.metadata | 10 + sama_sdk/analysis_options.yaml | 4 + {lib/src => sama_sdk/lib}/api/api.dart | 6 +- .../lib}/api/chats/attachments_api.dart | 0 .../lib}/api/chats/messages_api.dart | 1 - .../api/chats/realtime/messages_manager.dart | 0 .../realtime/models/message_statuses.dart | 0 .../api/chats/realtime/models/models.dart | 0 .../chats/realtime/models/system_message.dart | 1 + .../api/chats/realtime/typing_manager.dart | 0 .../lib}/api/connection/connection.dart | 111 +-- sama_sdk/lib/api/connection/exceptions.dart | 15 + .../lib}/api/connection/http_request.dart | 8 +- .../managers/connection_manager.dart | 32 + .../managers}/connectivity_manager.dart | 4 +- .../managers}/reconnection_manager.dart | 29 +- .../api/conversations/conversations_api.dart | 1 + .../api/conversations/models/attachment.dart | 47 +- .../lib}/api/conversations/models/avatar.dart | 0 .../conversations/models/conversation.dart | 0 .../conversations/models/link_preview.dart | 0 .../api/conversations/models/message.dart | 0 .../lib}/api/conversations/models/models.dart | 0 .../api/push_notifications/models/models.dart | 0 .../push_notifications/models/push_event.dart | 0 .../models/push_event_message.dart | 0 .../models/push_message_data.dart | 0 .../models/push_subscription.dart | 0 .../push_notifications_api.dart | 0 sama_sdk/lib/api/settings.dart | 23 + .../lib}/api/users/models/access_token.dart | 0 .../lib}/api/users/models/models.dart | 1 + .../lib/api/users/models/refresh_token.dart | 21 + .../lib}/api/users/models/user.dart | 3 +- .../api/users/realtime/users_manager.dart | 0 .../lib}/api/users/users_api.dart | 51 +- .../lib}/api/utils/logger.dart | 2 +- sama_sdk/pubspec.yaml | 27 + sama_sdk/sama_sdk.iml | 19 + sama_sdk/test/sama_chat_api_test.dart | 7 + 359 files changed, 1534 insertions(+), 415 deletions(-) delete mode 100644 lib/src/api/connection/exceptions.dart delete mode 100644 lib/src/db/remote/conversation_remote_datasource.dart delete mode 100644 lib/src/db/sama_db.dart delete mode 100644 lib/src/shared/utils/api_utils.dart rename .env.example => sama_chat_client/.env.example (100%) create mode 100644 sama_chat_client/.gitignore create mode 100644 sama_chat_client/.metadata create mode 100644 sama_chat_client/CHANGELOG.md create mode 100644 sama_chat_client/LICENSE create mode 100644 sama_chat_client/README.md rename analysis_options.yaml => sama_chat_client/analysis_options.yaml (100%) rename {android => sama_chat_client/android}/.gitignore (100%) rename {android => sama_chat_client/android}/app/build.gradle (100%) rename {android => sama_chat_client/android}/app/google-services.json (100%) rename {android => sama_chat_client/android}/app/src/debug/AndroidManifest.xml (100%) rename {android => sama_chat_client/android}/app/src/main/AndroidManifest.xml (100%) rename {android => sama_chat_client/android}/app/src/main/ic_launcher-playstore.png (100%) rename {android => sama_chat_client/android}/app/src/main/kotlin/com/sama/sama_client_flutter/MainActivity.kt (100%) rename {android => sama_chat_client/android}/app/src/main/res/drawable-anydpi-v24/ic_notification.xml (100%) rename {android => sama_chat_client/android}/app/src/main/res/drawable-hdpi/ic_notification.png (100%) rename {android => sama_chat_client/android}/app/src/main/res/drawable-mdpi/ic_notification.png (100%) rename {android => sama_chat_client/android}/app/src/main/res/drawable-v21/launch_background.xml (100%) rename {android => sama_chat_client/android}/app/src/main/res/drawable-xhdpi/ic_notification.png (100%) rename {android => sama_chat_client/android}/app/src/main/res/drawable-xxhdpi/ic_notification.png (100%) rename {android => sama_chat_client/android}/app/src/main/res/drawable-xxxhdpi/ic_notification.png (100%) rename {android => sama_chat_client/android}/app/src/main/res/drawable/ic_launcher_foreground.xml (100%) rename {android => sama_chat_client/android}/app/src/main/res/drawable/launch_background.xml (100%) rename {android => sama_chat_client/android}/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml (100%) rename {android => sama_chat_client/android}/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml (100%) rename {android => sama_chat_client/android}/app/src/main/res/mipmap-hdpi/ic_launcher.webp (100%) rename {android => sama_chat_client/android}/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp (100%) rename {android => sama_chat_client/android}/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp (100%) rename {android => sama_chat_client/android}/app/src/main/res/mipmap-mdpi/ic_launcher.webp (100%) rename {android => sama_chat_client/android}/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp (100%) rename {android => sama_chat_client/android}/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp (100%) rename {android => sama_chat_client/android}/app/src/main/res/mipmap-xhdpi/ic_launcher.webp (100%) rename {android => sama_chat_client/android}/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp (100%) rename {android => sama_chat_client/android}/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp (100%) rename {android => sama_chat_client/android}/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp (100%) rename {android => sama_chat_client/android}/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp (100%) rename {android => sama_chat_client/android}/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp (100%) rename {android => sama_chat_client/android}/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp (100%) rename {android => sama_chat_client/android}/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp (100%) rename {android => sama_chat_client/android}/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp (100%) rename {android => sama_chat_client/android}/app/src/main/res/values-night/styles.xml (100%) rename {android => sama_chat_client/android}/app/src/main/res/values/ic_launcher_background.xml (100%) rename {android => sama_chat_client/android}/app/src/main/res/values/styles.xml (100%) rename {android => sama_chat_client/android}/app/src/profile/AndroidManifest.xml (100%) rename {android => sama_chat_client/android}/build.gradle (100%) rename {android => sama_chat_client/android}/gradle.properties (81%) rename {android => sama_chat_client/android}/gradle/wrapper/gradle-wrapper.properties (100%) rename {android => sama_chat_client/android}/sama_client_flutter_android.iml (100%) rename {android => sama_chat_client/android}/settings.gradle (100%) rename {assets => sama_chat_client/assets}/images/1.5x/sama_background.png (100%) rename {assets => sama_chat_client/assets}/images/2.0x/sama_background.png (100%) rename {assets => sama_chat_client/assets}/images/3.0x/sama_background.png (100%) rename {assets => sama_chat_client/assets}/images/4.0x/sama_background.png (100%) rename {assets => sama_chat_client/assets}/images/Sama_Icon.png (100%) rename {assets => sama_chat_client/assets}/images/sama_background.png (100%) rename {assets => sama_chat_client/assets}/images/vector_logo.png (100%) rename devtools_options.yaml => sama_chat_client/devtools_options.yaml (100%) rename {ios => sama_chat_client/ios}/.gitignore (100%) rename {ios => sama_chat_client/ios}/Flutter/AppFrameworkInfo.plist (100%) rename {ios => sama_chat_client/ios}/Flutter/Debug.xcconfig (100%) rename {ios => sama_chat_client/ios}/Flutter/Release.xcconfig (100%) rename {ios => sama_chat_client/ios}/Gemfile (100%) rename {ios => sama_chat_client/ios}/Gemfile.lock (100%) rename {ios => sama_chat_client/ios}/NotificationService/Info.plist (100%) rename {ios => sama_chat_client/ios}/NotificationService/NotificationService.entitlements (100%) rename {ios => sama_chat_client/ios}/NotificationService/NotificationService.swift (100%) rename {ios => sama_chat_client/ios}/Podfile (100%) rename {ios => sama_chat_client/ios}/Podfile.lock (69%) rename {ios => sama_chat_client/ios}/Runner.xcodeproj/project.pbxproj (100%) rename {ios => sama_chat_client/ios}/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata (100%) rename {ios => sama_chat_client/ios}/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist (100%) rename {ios => sama_chat_client/ios}/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings (100%) rename {ios => sama_chat_client/ios}/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme (100%) rename {ios => sama_chat_client/ios}/Runner.xcworkspace/contents.xcworkspacedata (100%) rename {ios => sama_chat_client/ios}/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist (100%) rename {ios => sama_chat_client/ios}/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings (100%) rename {ios => sama_chat_client/ios}/Runner/AppDelegate.swift (100%) rename {ios => sama_chat_client/ios}/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json (100%) rename {ios => sama_chat_client/ios}/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png (100%) rename {ios => sama_chat_client/ios}/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png (100%) rename {ios => sama_chat_client/ios}/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png (100%) rename {ios => sama_chat_client/ios}/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png (100%) rename {ios => sama_chat_client/ios}/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png (100%) rename {ios => sama_chat_client/ios}/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png (100%) rename {ios => sama_chat_client/ios}/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png (100%) rename {ios => sama_chat_client/ios}/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png (100%) rename {ios => sama_chat_client/ios}/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png (100%) rename {ios => sama_chat_client/ios}/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png (100%) rename {ios => sama_chat_client/ios}/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png (100%) rename {ios => sama_chat_client/ios}/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png (100%) rename {ios => sama_chat_client/ios}/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png (100%) rename {ios => sama_chat_client/ios}/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png (100%) rename {ios => sama_chat_client/ios}/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png (100%) rename {ios => sama_chat_client/ios}/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png (100%) rename {ios => sama_chat_client/ios}/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png (100%) rename {ios => sama_chat_client/ios}/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png (100%) rename {ios => sama_chat_client/ios}/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png (100%) rename {ios => sama_chat_client/ios}/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png (100%) rename {ios => sama_chat_client/ios}/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png (100%) rename {ios => sama_chat_client/ios}/Runner/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png (100%) rename {ios => sama_chat_client/ios}/Runner/Assets.xcassets/Contents.json (100%) rename {ios => sama_chat_client/ios}/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json (100%) rename {ios => sama_chat_client/ios}/Runner/Assets.xcassets/LaunchImage.imageset/README.md (100%) rename {ios => sama_chat_client/ios}/Runner/Assets.xcassets/LaunchImage.imageset/sama_1024.png (100%) rename {ios => sama_chat_client/ios}/Runner/Assets.xcassets/iTunesArtwork@1x.png (100%) rename {ios => sama_chat_client/ios}/Runner/Assets.xcassets/iTunesArtwork@2x.png (100%) rename {ios => sama_chat_client/ios}/Runner/Assets.xcassets/iTunesArtwork@3x.png (100%) rename {ios => sama_chat_client/ios}/Runner/Base.lproj/LaunchScreen.storyboard (100%) rename {ios => sama_chat_client/ios}/Runner/Base.lproj/Main.storyboard (100%) rename {ios => sama_chat_client/ios}/Runner/GoogleService-Info.plist (100%) rename {ios => sama_chat_client/ios}/Runner/Info.plist (100%) rename {ios => sama_chat_client/ios}/Runner/Runner-Bridging-Header.h (100%) rename {ios => sama_chat_client/ios}/Runner/Runner.entitlements (100%) rename {ios => sama_chat_client/ios}/RunnerTests/RunnerTests.swift (100%) rename {ios => sama_chat_client/ios}/Share Extension/Base.lproj/MainInterface.storyboard (100%) rename {ios => sama_chat_client/ios}/Share Extension/Info.plist (100%) rename {ios => sama_chat_client/ios}/Share Extension/Share Extension.entitlements (100%) rename {ios => sama_chat_client/ios}/Share Extension/ShareViewController.swift (100%) rename {ios => sama_chat_client/ios}/fastlane/Appfile (100%) rename {ios => sama_chat_client/ios}/fastlane/Fastfile (100%) rename {ios => sama_chat_client/ios}/firebase_app_id_file.json (100%) rename {lib => sama_chat_client/lib}/main.dart (98%) rename {lib => sama_chat_client/lib}/main.dart.run.xml (100%) rename {lib => sama_chat_client/lib}/objectbox-model.json (100%) rename {lib => sama_chat_client/lib}/objectbox.g.dart (100%) rename {lib => sama_chat_client/lib}/sama_firebase_options.dart (100%) rename {lib => sama_chat_client/lib}/src/db/db_service.dart (100%) rename {lib => sama_chat_client/lib}/src/db/local/attachment_local_datasource.dart (100%) rename {lib => sama_chat_client/lib}/src/db/local/conversation_local_datasource.dart (100%) rename {lib => sama_chat_client/lib}/src/db/local/message_local_datasource.dart (100%) rename {lib => sama_chat_client/lib}/src/db/local/user_local_datasource.dart (100%) rename {lib => sama_chat_client/lib}/src/db/models/attachment_model.dart (81%) rename {lib => sama_chat_client/lib}/src/db/models/avatar_model.dart (92%) rename {lib => sama_chat_client/lib}/src/db/models/conversation_model.dart (100%) rename {lib => sama_chat_client/lib}/src/db/models/message_model.dart (98%) rename {lib => sama_chat_client/lib}/src/db/models/models.dart (100%) rename {lib => sama_chat_client/lib}/src/db/models/user_model.dart (97%) rename {lib => sama_chat_client/lib}/src/db/network_bound_resource.dart (100%) rename {lib => sama_chat_client/lib}/src/db/resource.dart (100%) rename {lib/src/api/utils => sama_chat_client/lib/src/features}/config.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/bloc/ai_message/ai_message_bloc.dart (97%) rename {lib => sama_chat_client/lib}/src/features/conversation/bloc/ai_message/ai_message_event.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/bloc/ai_message/ai_message_state.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/bloc/conversation_bloc.dart (99%) rename {lib => sama_chat_client/lib}/src/features/conversation/bloc/conversation_event.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/bloc/conversation_state.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/bloc/delete_messages/delete_messages_bloc.dart (96%) rename {lib => sama_chat_client/lib}/src/features/conversation/bloc/delete_messages/delete_messages_event.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/bloc/delete_messages/delete_messages_state.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/bloc/forward_message/forward_messages_bloc.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/bloc/forward_message/forward_messages_event.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/bloc/forward_message/forward_messages_state.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/bloc/media_attachment/media_attachment_bloc.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/bloc/media_attachment/media_attachment_event.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/bloc/media_attachment/media_attachment_state.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/bloc/media_sender/media_sender_bloc.dart (98%) rename {lib => sama_chat_client/lib}/src/features/conversation/bloc/media_sender/media_sender_event.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/bloc/media_sender/media_sender_state.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/bloc/send_message/send_message_bloc.dart (99%) rename {lib => sama_chat_client/lib}/src/features/conversation/bloc/send_message/send_message_event.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/bloc/send_message/send_message_state.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/models/chat_message.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/models/models.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/models/selected_messages.dart (86%) rename {lib => sama_chat_client/lib}/src/features/conversation/view/conversation_page.dart (97%) rename {lib => sama_chat_client/lib}/src/features/conversation/view/media_sender.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/view/message_input.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/view/messages_list.dart (99%) rename {lib => sama_chat_client/lib}/src/features/conversation/widgets/focused_popup_menu.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/widgets/forward_messages/forward_bubble.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/widgets/forward_messages/forward_messages_widget.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/widgets/forward_messages/forward_search_form.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/widgets/header_input_box.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/widgets/media_attachment.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/widgets/media_attachment_widget.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/widgets/message_bubble.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/widgets/message_edit_widget.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/widgets/message_status_widget.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/widgets/reply_bubble.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/widgets/select_input.dart (98%) rename {lib => sama_chat_client/lib}/src/features/conversation/widgets/service_message_bubble.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/widgets/text_message.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/widgets/text_message_item.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation/widgets/unsupported_message.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation_create/bloc/conversation_create_bloc.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation_create/bloc/conversation_create_event.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation_create/bloc/conversation_create_state.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation_group_create/bloc/group_bloc.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation_group_create/bloc/group_event.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation_group_create/bloc/group_state.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation_group_create/models/avatar.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation_group_create/models/groupname.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation_group_create/models/participants.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation_group_create/view/group_create_form.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversation_group_create/view/group_create_page.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversations_list/bloc/conversations_list_bloc.dart (98%) rename {lib => sama_chat_client/lib}/src/features/conversations_list/bloc/conversations_list_event.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversations_list/bloc/conversations_list_state.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversations_list/conversations_list.dart (60%) rename {lib => sama_chat_client/lib}/src/features/conversations_list/view/conversations_list.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversations_list/view/conversations_page.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversations_list/view/view.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversations_list/widgets/avatar_group_icon.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversations_list/widgets/avatar_letter_icon.dart (100%) rename {lib => sama_chat_client/lib}/src/features/conversations_list/widgets/conversation_list_item.dart (99%) rename {lib => sama_chat_client/lib}/src/features/conversations_list/widgets/widgets.dart (100%) rename {lib => sama_chat_client/lib}/src/features/group_info/bloc/group_info_bloc.dart (99%) rename {lib => sama_chat_client/lib}/src/features/group_info/bloc/group_info_event.dart (100%) rename {lib => sama_chat_client/lib}/src/features/group_info/bloc/group_info_state.dart (100%) rename {lib => sama_chat_client/lib}/src/features/group_info/models/group_avatar.dart (100%) rename {lib => sama_chat_client/lib}/src/features/group_info/models/group_description.dart (100%) rename {lib => sama_chat_client/lib}/src/features/group_info/models/group_name.dart (100%) rename {lib => sama_chat_client/lib}/src/features/group_info/models/group_participants.dart (100%) rename {lib => sama_chat_client/lib}/src/features/group_info/models/models.dart (100%) rename {lib => sama_chat_client/lib}/src/features/group_info/view/group_info_form.dart (100%) rename {lib => sama_chat_client/lib}/src/features/group_info/view/group_info_page.dart (100%) rename {lib => sama_chat_client/lib}/src/features/login/bloc/login_bloc.dart (100%) rename {lib => sama_chat_client/lib}/src/features/login/bloc/login_event.dart (100%) rename {lib => sama_chat_client/lib}/src/features/login/bloc/login_state.dart (100%) rename {lib => sama_chat_client/lib}/src/features/login/models/models.dart (100%) rename {lib => sama_chat_client/lib}/src/features/login/models/username.dart (100%) rename {lib => sama_chat_client/lib}/src/features/login/view/login_form.dart (100%) rename {lib => sama_chat_client/lib}/src/features/login/view/login_page.dart (100%) rename {lib => sama_chat_client/lib}/src/features/profile/bloc/profile_bloc.dart (99%) rename {lib => sama_chat_client/lib}/src/features/profile/bloc/profile_event.dart (100%) rename {lib => sama_chat_client/lib}/src/features/profile/bloc/profile_state.dart (100%) rename {lib => sama_chat_client/lib}/src/features/profile/models/models.dart (100%) rename {lib => sama_chat_client/lib}/src/features/profile/models/user_avatar.dart (100%) rename {lib => sama_chat_client/lib}/src/features/profile/models/user_email.dart (100%) rename {lib => sama_chat_client/lib}/src/features/profile/models/user_firstname.dart (100%) rename {lib => sama_chat_client/lib}/src/features/profile/models/user_lastname.dart (100%) rename {lib => sama_chat_client/lib}/src/features/profile/models/user_password.dart (100%) rename {lib => sama_chat_client/lib}/src/features/profile/models/user_phone.dart (100%) rename {lib => sama_chat_client/lib}/src/features/profile/view/profile_form.dart (100%) rename {lib => sama_chat_client/lib}/src/features/profile/view/profile_page.dart (100%) rename {lib => sama_chat_client/lib}/src/features/reset_password/bloc/reset_password_bloc.dart (100%) rename {lib => sama_chat_client/lib}/src/features/reset_password/bloc/reset_password_event.dart (100%) rename {lib => sama_chat_client/lib}/src/features/reset_password/bloc/reset_password_state.dart (100%) rename {lib => sama_chat_client/lib}/src/features/reset_password/bloc/timer_bloc/timer_bloc.dart (100%) rename {lib => sama_chat_client/lib}/src/features/reset_password/bloc/timer_bloc/timer_event.dart (100%) rename {lib => sama_chat_client/lib}/src/features/reset_password/bloc/timer_bloc/timer_state.dart (100%) rename {lib => sama_chat_client/lib}/src/features/reset_password/models/confirm_password.dart (100%) rename {lib => sama_chat_client/lib}/src/features/reset_password/models/models.dart (100%) rename {lib => sama_chat_client/lib}/src/features/reset_password/models/otp.dart (100%) rename {lib => sama_chat_client/lib}/src/features/reset_password/ticker.dart (100%) rename {lib => sama_chat_client/lib}/src/features/reset_password/view/reset_password_page.dart (100%) rename {lib => sama_chat_client/lib}/src/features/reset_password/view/send_email_form.dart (100%) rename {lib => sama_chat_client/lib}/src/features/reset_password/view/send_otp_form.dart (100%) rename {lib => sama_chat_client/lib}/src/features/reset_password/view/send_reset_password_form.dart (100%) rename {lib => sama_chat_client/lib}/src/features/search/bloc/global_search_bloc.dart (100%) rename {lib => sama_chat_client/lib}/src/features/search/bloc/global_search_event.dart (100%) rename {lib => sama_chat_client/lib}/src/features/search/bloc/global_search_state.dart (100%) rename {lib => sama_chat_client/lib}/src/features/search/models/models.dart (100%) rename {lib => sama_chat_client/lib}/src/features/search/models/search_result.dart (100%) rename {lib => sama_chat_client/lib}/src/features/search/models/search_result_error.dart (100%) rename {lib => sama_chat_client/lib}/src/features/search/view/search_bar.dart (100%) rename {lib => sama_chat_client/lib}/src/features/search/view/search_form.dart (100%) rename {lib => sama_chat_client/lib}/src/features/search/view/search_page.dart (100%) rename {lib => sama_chat_client/lib}/src/features/splash_page.dart (100%) rename {lib => sama_chat_client/lib}/src/features/user_info/view/user_info_form.dart (100%) rename {lib => sama_chat_client/lib}/src/features/user_info/view/user_info_page.dart (97%) rename {lib => sama_chat_client/lib}/src/navigation/app_router.dart (100%) rename {lib => sama_chat_client/lib}/src/navigation/constants.dart (100%) rename {lib => sama_chat_client/lib}/src/repository/attachments/attachments_repository.dart (91%) rename {lib => sama_chat_client/lib}/src/repository/authentication/authentication_repository.dart (61%) rename {lib => sama_chat_client/lib}/src/repository/conversation/conversation_repository.dart (93%) rename {lib => sama_chat_client/lib}/src/repository/global_search/global_search_repository.dart (79%) rename {lib => sama_chat_client/lib}/src/repository/messages/messages_repository.dart (99%) rename {lib => sama_chat_client/lib}/src/repository/user/user_repository.dart (90%) rename {lib => sama_chat_client/lib}/src/shared/auth/bloc/auth_bloc.dart (87%) rename {lib => sama_chat_client/lib}/src/shared/auth/bloc/auth_event.dart (100%) rename {lib => sama_chat_client/lib}/src/shared/auth/bloc/auth_state.dart (100%) rename {lib => sama_chat_client/lib}/src/shared/connection/bloc/connection_bloc.dart (96%) rename {lib => sama_chat_client/lib}/src/shared/connection/bloc/connection_event.dart (100%) rename {lib => sama_chat_client/lib}/src/shared/connection/bloc/connection_state.dart (100%) rename {lib => sama_chat_client/lib}/src/shared/connection/view/connection_checker.dart (100%) rename {lib => sama_chat_client/lib}/src/shared/connection/view/connection_title.dart (100%) rename {lib => sama_chat_client/lib}/src/shared/errors/exceptions.dart (100%) rename {lib => sama_chat_client/lib}/src/shared/messages_collector/messages_collector.dart (95%) rename {lib => sama_chat_client/lib}/src/shared/models/email.dart (100%) rename {lib => sama_chat_client/lib}/src/shared/models/password.dart (100%) rename {lib => sama_chat_client/lib}/src/shared/push_notifications/bloc/push_notifications_bloc.dart (98%) rename {lib => sama_chat_client/lib}/src/shared/push_notifications/bloc/push_notifications_event.dart (100%) rename {lib => sama_chat_client/lib}/src/shared/push_notifications/bloc/push_notifications_state.dart (100%) rename {lib/src/api => sama_chat_client/lib/src/shared}/push_notifications/push_notifications_manager.dart (91%) rename {lib => sama_chat_client/lib}/src/shared/secure_storage.dart (88%) rename {lib => sama_chat_client/lib}/src/shared/sharing/bloc/sharing_intent_bloc.dart (100%) rename {lib => sama_chat_client/lib}/src/shared/sharing/bloc/sharing_intent_event.dart (100%) rename {lib => sama_chat_client/lib}/src/shared/sharing/bloc/sharing_intent_state.dart (100%) rename {lib => sama_chat_client/lib}/src/shared/ui/colors.dart (100%) rename {lib => sama_chat_client/lib}/src/shared/ui/view/loading_overlay.dart (100%) rename {lib => sama_chat_client/lib}/src/shared/ui/view/participants_forms.dart (100%) rename {lib => sama_chat_client/lib}/src/shared/ui/view/user_forms.dart (100%) create mode 100644 sama_chat_client/lib/src/shared/utils/api_utils.dart rename {lib => sama_chat_client/lib}/src/shared/utils/date_utils.dart (100%) rename {lib => sama_chat_client/lib}/src/shared/utils/file_utils.dart (100%) rename {lib => sama_chat_client/lib}/src/shared/utils/media_utils.dart (100%) rename {lib => sama_chat_client/lib}/src/shared/utils/observer_utils.dart (100%) rename {lib => sama_chat_client/lib}/src/shared/utils/regexp_utils.dart (100%) rename {lib => sama_chat_client/lib}/src/shared/utils/screen_factor.dart (100%) rename {lib => sama_chat_client/lib}/src/shared/utils/string_utils.dart (97%) rename {lib => sama_chat_client/lib}/src/shared/widget/env_dialog_widget.dart (97%) rename {lib => sama_chat_client/lib}/src/shared/widget/keyboard_listener.dart (100%) rename {lib => sama_chat_client/lib}/src/shared/widget/link_preview_widget.dart (99%) rename {lib => sama_chat_client/lib}/src/shared/widget/loaders.dart (100%) rename {lib => sama_chat_client/lib}/src/shared/widget/logo_app_bar.dart (100%) rename {lib => sama_chat_client/lib}/src/shared/widget/multi_gesture_detector.dart (100%) rename {lib => sama_chat_client/lib}/src/shared/widget/popup_menu.dart (100%) rename {lib => sama_chat_client/lib}/src/shared/widget/swipe_to.dart (100%) rename {lib => sama_chat_client/lib}/src/shared/widget/typing_indicator.dart (100%) rename {lib => sama_chat_client/lib}/src/shared/widget/vertical_line.dart (100%) rename pubspec.yaml => sama_chat_client/pubspec.yaml (97%) rename sama_client_flutter.iml => sama_chat_client/sama_chat_client.iml (92%) rename {test => sama_chat_client/test}/widget_test.dart (100%) create mode 100644 sama_sdk/.gitignore create mode 100644 sama_sdk/.metadata create mode 100644 sama_sdk/analysis_options.yaml rename {lib/src => sama_sdk/lib}/api/api.dart (75%) rename {lib/src => sama_sdk/lib}/api/chats/attachments_api.dart (100%) rename {lib/src => sama_sdk/lib}/api/chats/messages_api.dart (98%) rename {lib/src => sama_sdk/lib}/api/chats/realtime/messages_manager.dart (100%) rename {lib/src => sama_sdk/lib}/api/chats/realtime/models/message_statuses.dart (100%) rename {lib/src => sama_sdk/lib}/api/chats/realtime/models/models.dart (100%) rename {lib/src => sama_sdk/lib}/api/chats/realtime/models/system_message.dart (95%) rename {lib/src => sama_sdk/lib}/api/chats/realtime/typing_manager.dart (100%) rename {lib/src => sama_sdk/lib}/api/connection/connection.dart (78%) create mode 100644 sama_sdk/lib/api/connection/exceptions.dart rename {lib/src => sama_sdk/lib}/api/connection/http_request.dart (91%) create mode 100644 sama_sdk/lib/api/connection/managers/connection_manager.dart rename {lib/src/api/utils => sama_sdk/lib/api/connection/managers}/connectivity_manager.dart (97%) rename {lib/src/api/utils => sama_sdk/lib/api/connection/managers}/reconnection_manager.dart (81%) rename {lib/src => sama_sdk/lib}/api/conversations/conversations_api.dart (99%) rename {lib/src => sama_sdk/lib}/api/conversations/models/attachment.dart (52%) rename {lib/src => sama_sdk/lib}/api/conversations/models/avatar.dart (100%) rename {lib/src => sama_sdk/lib}/api/conversations/models/conversation.dart (100%) rename {lib/src => sama_sdk/lib}/api/conversations/models/link_preview.dart (100%) rename {lib/src => sama_sdk/lib}/api/conversations/models/message.dart (100%) rename {lib/src => sama_sdk/lib}/api/conversations/models/models.dart (100%) rename {lib/src => sama_sdk/lib}/api/push_notifications/models/models.dart (100%) rename {lib/src => sama_sdk/lib}/api/push_notifications/models/push_event.dart (100%) rename {lib/src => sama_sdk/lib}/api/push_notifications/models/push_event_message.dart (100%) rename {lib/src => sama_sdk/lib}/api/push_notifications/models/push_message_data.dart (100%) rename {lib/src => sama_sdk/lib}/api/push_notifications/models/push_subscription.dart (100%) rename {lib/src => sama_sdk/lib}/api/push_notifications/push_notifications_api.dart (100%) create mode 100644 sama_sdk/lib/api/settings.dart rename {lib/src => sama_sdk/lib}/api/users/models/access_token.dart (100%) rename {lib/src => sama_sdk/lib}/api/users/models/models.dart (62%) create mode 100644 sama_sdk/lib/api/users/models/refresh_token.dart rename {lib/src => sama_sdk/lib}/api/users/models/user.dart (98%) rename {lib/src => sama_sdk/lib}/api/users/realtime/users_manager.dart (100%) rename {lib/src => sama_sdk/lib}/api/users/users_api.dart (80%) rename {lib/src => sama_sdk/lib}/api/utils/logger.dart (99%) create mode 100644 sama_sdk/pubspec.yaml create mode 100644 sama_sdk/sama_sdk.iml create mode 100644 sama_sdk/test/sama_chat_api_test.dart diff --git a/lib/src/api/connection/exceptions.dart b/lib/src/api/connection/exceptions.dart deleted file mode 100644 index 94a09e0d..00000000 --- a/lib/src/api/connection/exceptions.dart +++ /dev/null @@ -1,18 +0,0 @@ -class ResponseException { - int? status; - String? message; - - ResponseException.fromJson(Map json) - : status = int.tryParse(json['status']?.toString() ?? ''), - message = json['message'].toString(); - - Map toJson() => { - 'status': status, - 'message': message, - }; - - @override - String toString() { - return toJson().toString(); - } -} diff --git a/lib/src/db/remote/conversation_remote_datasource.dart b/lib/src/db/remote/conversation_remote_datasource.dart deleted file mode 100644 index b13fc5a0..00000000 --- a/lib/src/db/remote/conversation_remote_datasource.dart +++ /dev/null @@ -1,16 +0,0 @@ - -//here can be all remote requests like in api folder -// Future> fetchConversations([int startIndex = 0]) async { -// return SamaConnectionService.instance -// .sendRequest(conversationsRequest, {}).then((response) { -// List conversations; -// List items = List.of(response['conversations']); -// if (items.isEmpty) { -// conversations = []; -// } else { -// conversations = -// items.map((element) => Conversation.fromJson(element)).toList(); -// } -// return conversations; -// }); -// } \ No newline at end of file diff --git a/lib/src/db/sama_db.dart b/lib/src/db/sama_db.dart deleted file mode 100644 index 98fbd708..00000000 --- a/lib/src/db/sama_db.dart +++ /dev/null @@ -1,50 +0,0 @@ -import 'package:path/path.dart'; -import 'package:sqflite/sqflite.dart'; - - -const int dbVersion = 1; -const String dbName = 'sama_db.db'; - -class SamaDB { - static final SamaDB instance = SamaDB._internal(); - - static Database? _database; - - SamaDB._internal(); - - Future get database async { - if (_database != null) { - return _database!; - } - - _database = await _initDatabase(); - return _database!; - } - - Future _initDatabase() async { - var path = await getDBPath(); - - return openDatabase( - path, - version: dbVersion, - onCreate: _createDatabase, - ); - } - - Future> _createDatabase(Database db, int version) async { - return await Future.wait([ - // createUsersTable(db, version), - ]); - } - - Future getDBPath() async { - final databasePath = await getDatabasesPath(); - return join(databasePath, dbName); - } - - Future deleteDB() { - return getDBPath().then((path) { - return deleteDatabase(path); - }); - } -} diff --git a/lib/src/shared/utils/api_utils.dart b/lib/src/shared/utils/api_utils.dart deleted file mode 100644 index 667e9ed1..00000000 --- a/lib/src/shared/utils/api_utils.dart +++ /dev/null @@ -1,2 +0,0 @@ -const int maxParticipantsCount = 50 - 1; // minus current user -const int maxChatsSelected = 20; diff --git a/.env.example b/sama_chat_client/.env.example similarity index 100% rename from .env.example rename to sama_chat_client/.env.example diff --git a/sama_chat_client/.gitignore b/sama_chat_client/.gitignore new file mode 100644 index 00000000..0acbc627 --- /dev/null +++ b/sama_chat_client/.gitignore @@ -0,0 +1,31 @@ +# See https://www.dartlang.org/guides/libraries/private-files + +# Files and directories created by pub +.dart_tool/ +.packages +build/ +# If you're building an application, you may want to check-in your pubspec.lock +pubspec.lock + +# Directory created by dartdoc +# If you don't generate documentation locally you can remove this line. +doc/api/ + +# dotenv environment variables file +.env + +# Avoid committing generated Javascript files: +*.dart.js +*.info.json # Produced by the --dump-info flag. +*.js # When generated by dart2js. Don't specify *.js if your + # project includes source files written in JavaScript. +*.js_ +*.js.deps +*.js.map + +.flutter-plugins +.flutter-plugins-dependencies + +.idea/ + +.DS_Store \ No newline at end of file diff --git a/sama_chat_client/.metadata b/sama_chat_client/.metadata new file mode 100644 index 00000000..3268d005 --- /dev/null +++ b/sama_chat_client/.metadata @@ -0,0 +1,45 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "a402d9a4376add5bc2d6b1e33e53edaae58c07f8" + channel: "stable" + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: a402d9a4376add5bc2d6b1e33e53edaae58c07f8 + base_revision: a402d9a4376add5bc2d6b1e33e53edaae58c07f8 + - platform: android + create_revision: a402d9a4376add5bc2d6b1e33e53edaae58c07f8 + base_revision: a402d9a4376add5bc2d6b1e33e53edaae58c07f8 + - platform: ios + create_revision: a402d9a4376add5bc2d6b1e33e53edaae58c07f8 + base_revision: a402d9a4376add5bc2d6b1e33e53edaae58c07f8 + - platform: linux + create_revision: a402d9a4376add5bc2d6b1e33e53edaae58c07f8 + base_revision: a402d9a4376add5bc2d6b1e33e53edaae58c07f8 + - platform: macos + create_revision: a402d9a4376add5bc2d6b1e33e53edaae58c07f8 + base_revision: a402d9a4376add5bc2d6b1e33e53edaae58c07f8 + - platform: web + create_revision: a402d9a4376add5bc2d6b1e33e53edaae58c07f8 + base_revision: a402d9a4376add5bc2d6b1e33e53edaae58c07f8 + - platform: windows + create_revision: a402d9a4376add5bc2d6b1e33e53edaae58c07f8 + base_revision: a402d9a4376add5bc2d6b1e33e53edaae58c07f8 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/sama_chat_client/CHANGELOG.md b/sama_chat_client/CHANGELOG.md new file mode 100644 index 00000000..d4ccc95a --- /dev/null +++ b/sama_chat_client/CHANGELOG.md @@ -0,0 +1,135 @@ +# Changelog + +## 0.14.0 + +### Features +- Implemented the option to edit messages +- Implemented the option to delete messages +- Implemented reset password feature +- Integrated AI agent for changing tone of messages and summarizing them + +## 0.13.0 + +### Features +- Implemented Forward messages feature +- Improved Link preview functionality + +## 0.12.0 + +### Features +- Implemented Typing status +- Implemented Link preview for message +- Implemented message Reply functionality + +### Improvements +- Minor bug fixes and improvements + +## 0.11.2 + +### Features: +- Added support for Programmable Chat attachments +- Added new attachments fields + +## 0.11.1 + +### Fixes: +- Added organization id for production environment + +## 0.11.0 + +### Features: +- Implemented the Draft feature to locally save unsent messages +- Added support for Programmable Chat +- Added support for verifying that a user belongs to a specific organization + +### Fixes: +- Improved real-time updates for Online status to enhance compatibility with the web app + +## 0.10.0 + +### Features: +- Implemented a new view for media items within the app +- Improved thumbnail quality for media item previews +- Added caching to display media items in offline mode +- Added a new media player to play videos within the app + +### Fixes: +- Improved and stabilized the logic for the “Last Seen” user functionality + +## 0.9.0 + +### Features: +- Implemented offline mode for chats +- Implemented offline mode for messages +- Improved message attachments caching + +## 0.8.0 + +### Features: +- Implemented local database for Chats +- Implemented local database for Messages +- Enhance app by adding offline stubs for some functionalities +- Implemented CI + +## 0.7.0 + +### Features: + +- Implemented a progressive authentication flow to enhance security +- Implemented push notifications for the iOS platform + +### Fixes: +- Fixed minor UI bugs for the iOS app + +## 0.6.0 + +### Enhancements: + +- Implement Pending/Sent/Read receipts +- Quick display the chats instead of login screen after app was run +- Re-design Create Group chat screen + +### Fixes: +- Resolve issue when chats aren’t displayed while the user tries to share some text +- Fix send empty text message + +## 0.5.0 + +### Released Fifth Phase + +- Enabled push notifications for Android devices. +- Added server-side support for push notifications. +- Improved chat functionality to auto-hide the keyboard during scrolling. +- Updated link highlight color within chat for better visibility. +- Made minor UI improvements to user and group chat descriptions. + +### Fixes: +- Resolved an issue where users remained in chats after deletion. +- Updated messaging when maximum participant limit is reached. + +## 0.4.0 + +### Released Forth Phase + +- Updated app name +- Implemented 1-1 info screen +- Implemented group info screen + +### Fixes +- iOS UI issues +- iOS ShareTo +- Attachments blinking download + +## 0.1.0 + +### Released all core features + +### Released Third Phase + +- Implemented avatars for conversations +- Implemented links highlighting in chat +- Added ShareTo (text only) + +### Fixes + +- Block 'x' buttons for separate items while sending attachments \ No newline at end of file diff --git a/sama_chat_client/LICENSE b/sama_chat_client/LICENSE new file mode 100644 index 00000000..f288702d --- /dev/null +++ b/sama_chat_client/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/sama_chat_client/README.md b/sama_chat_client/README.md new file mode 100644 index 00000000..ab2d0d56 --- /dev/null +++ b/sama_chat_client/README.md @@ -0,0 +1,51 @@ +# Flutter client for SAMA chat server + +ClientImage + +## Overview + +This is a Flutter app for the SAMA chat server https://github.com/SAMA-Communications/sama-server + +Read a complete medium post **Introducing SAMA** about what is SAMA and what problems we are trying to solve with it https://medium.com/sama-communications/introducing-sama-simple-but-advanced-messaging-alternative-chat-server-524a532e2040 + +## Development + +### Preparations + +1. Prepare environment for Flutter and clone the project. Versions: Flutter SDK version: 3.29.2, Dart Version: 3.7.2 +2. Install dependencies via `flutter pub get` +3. Generate config file `firebase_options.dart` via https://firebase.google.com/docs/flutter/setup and put it in `lib/firebase_options.dart`; + +### Run on Android: +- Open project in Android Studio +- Right mouse button click on `main.dart` +- Chose 'Run 'main.dart'' + +The app will automatically run on your Android device. + +### Run on iOS: +- Start Xcode +- Select `Runner.xcworkspace` to run Xcode project +- Press the' Build' button to start project building + +The app will automatically run on a selected iOS device or simulator. + +## Community and Support + +Join our community for support and discussions: + +- [GitHub Issues - SAMA server](https://github.com/SAMA-Communications/sama-server/issues), [GitHub Issues - SAMA Flutter client](https://github.com/SAMA-Communications/sama-client-flutter/issues) +- [SAMA on Medium](https://medium.com/sama-communications) +- Get help - [Discord 💬](https://discord.gg/bHSm9a7DpC) + +## License + +[GPL-3.0](LICENSE) + +## Help us! + +Any thoughts, feedback is welcome! Please create a GitHub issue for any feedback you have. + +Want to support us? + +Buy Me A Coffee diff --git a/analysis_options.yaml b/sama_chat_client/analysis_options.yaml similarity index 100% rename from analysis_options.yaml rename to sama_chat_client/analysis_options.yaml diff --git a/android/.gitignore b/sama_chat_client/android/.gitignore similarity index 100% rename from android/.gitignore rename to sama_chat_client/android/.gitignore diff --git a/android/app/build.gradle b/sama_chat_client/android/app/build.gradle similarity index 100% rename from android/app/build.gradle rename to sama_chat_client/android/app/build.gradle diff --git a/android/app/google-services.json b/sama_chat_client/android/app/google-services.json similarity index 100% rename from android/app/google-services.json rename to sama_chat_client/android/app/google-services.json diff --git a/android/app/src/debug/AndroidManifest.xml b/sama_chat_client/android/app/src/debug/AndroidManifest.xml similarity index 100% rename from android/app/src/debug/AndroidManifest.xml rename to sama_chat_client/android/app/src/debug/AndroidManifest.xml diff --git a/android/app/src/main/AndroidManifest.xml b/sama_chat_client/android/app/src/main/AndroidManifest.xml similarity index 100% rename from android/app/src/main/AndroidManifest.xml rename to sama_chat_client/android/app/src/main/AndroidManifest.xml diff --git a/android/app/src/main/ic_launcher-playstore.png b/sama_chat_client/android/app/src/main/ic_launcher-playstore.png similarity index 100% rename from android/app/src/main/ic_launcher-playstore.png rename to sama_chat_client/android/app/src/main/ic_launcher-playstore.png diff --git a/android/app/src/main/kotlin/com/sama/sama_client_flutter/MainActivity.kt b/sama_chat_client/android/app/src/main/kotlin/com/sama/sama_client_flutter/MainActivity.kt similarity index 100% rename from android/app/src/main/kotlin/com/sama/sama_client_flutter/MainActivity.kt rename to sama_chat_client/android/app/src/main/kotlin/com/sama/sama_client_flutter/MainActivity.kt diff --git a/android/app/src/main/res/drawable-anydpi-v24/ic_notification.xml b/sama_chat_client/android/app/src/main/res/drawable-anydpi-v24/ic_notification.xml similarity index 100% rename from android/app/src/main/res/drawable-anydpi-v24/ic_notification.xml rename to sama_chat_client/android/app/src/main/res/drawable-anydpi-v24/ic_notification.xml diff --git a/android/app/src/main/res/drawable-hdpi/ic_notification.png b/sama_chat_client/android/app/src/main/res/drawable-hdpi/ic_notification.png similarity index 100% rename from android/app/src/main/res/drawable-hdpi/ic_notification.png rename to sama_chat_client/android/app/src/main/res/drawable-hdpi/ic_notification.png diff --git a/android/app/src/main/res/drawable-mdpi/ic_notification.png b/sama_chat_client/android/app/src/main/res/drawable-mdpi/ic_notification.png similarity index 100% rename from android/app/src/main/res/drawable-mdpi/ic_notification.png rename to sama_chat_client/android/app/src/main/res/drawable-mdpi/ic_notification.png diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/sama_chat_client/android/app/src/main/res/drawable-v21/launch_background.xml similarity index 100% rename from android/app/src/main/res/drawable-v21/launch_background.xml rename to sama_chat_client/android/app/src/main/res/drawable-v21/launch_background.xml diff --git a/android/app/src/main/res/drawable-xhdpi/ic_notification.png b/sama_chat_client/android/app/src/main/res/drawable-xhdpi/ic_notification.png similarity index 100% rename from android/app/src/main/res/drawable-xhdpi/ic_notification.png rename to sama_chat_client/android/app/src/main/res/drawable-xhdpi/ic_notification.png diff --git a/android/app/src/main/res/drawable-xxhdpi/ic_notification.png b/sama_chat_client/android/app/src/main/res/drawable-xxhdpi/ic_notification.png similarity index 100% rename from android/app/src/main/res/drawable-xxhdpi/ic_notification.png rename to sama_chat_client/android/app/src/main/res/drawable-xxhdpi/ic_notification.png diff --git a/android/app/src/main/res/drawable-xxxhdpi/ic_notification.png b/sama_chat_client/android/app/src/main/res/drawable-xxxhdpi/ic_notification.png similarity index 100% rename from android/app/src/main/res/drawable-xxxhdpi/ic_notification.png rename to sama_chat_client/android/app/src/main/res/drawable-xxxhdpi/ic_notification.png diff --git a/android/app/src/main/res/drawable/ic_launcher_foreground.xml b/sama_chat_client/android/app/src/main/res/drawable/ic_launcher_foreground.xml similarity index 100% rename from android/app/src/main/res/drawable/ic_launcher_foreground.xml rename to sama_chat_client/android/app/src/main/res/drawable/ic_launcher_foreground.xml diff --git a/android/app/src/main/res/drawable/launch_background.xml b/sama_chat_client/android/app/src/main/res/drawable/launch_background.xml similarity index 100% rename from android/app/src/main/res/drawable/launch_background.xml rename to sama_chat_client/android/app/src/main/res/drawable/launch_background.xml diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/sama_chat_client/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml similarity index 100% rename from android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml rename to sama_chat_client/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/sama_chat_client/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml similarity index 100% rename from android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml rename to sama_chat_client/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/sama_chat_client/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp similarity index 100% rename from android/app/src/main/res/mipmap-hdpi/ic_launcher.webp rename to sama_chat_client/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp b/sama_chat_client/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp similarity index 100% rename from android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp rename to sama_chat_client/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/sama_chat_client/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp similarity index 100% rename from android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp rename to sama_chat_client/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/sama_chat_client/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp similarity index 100% rename from android/app/src/main/res/mipmap-mdpi/ic_launcher.webp rename to sama_chat_client/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp b/sama_chat_client/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp similarity index 100% rename from android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp rename to sama_chat_client/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/sama_chat_client/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp similarity index 100% rename from android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp rename to sama_chat_client/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/sama_chat_client/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp similarity index 100% rename from android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp rename to sama_chat_client/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp b/sama_chat_client/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp similarity index 100% rename from android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp rename to sama_chat_client/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/sama_chat_client/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp similarity index 100% rename from android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp rename to sama_chat_client/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/sama_chat_client/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp similarity index 100% rename from android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp rename to sama_chat_client/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp b/sama_chat_client/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp similarity index 100% rename from android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp rename to sama_chat_client/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/sama_chat_client/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp similarity index 100% rename from android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp rename to sama_chat_client/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/sama_chat_client/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp similarity index 100% rename from android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp rename to sama_chat_client/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp b/sama_chat_client/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp similarity index 100% rename from android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp rename to sama_chat_client/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/sama_chat_client/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp similarity index 100% rename from android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp rename to sama_chat_client/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp diff --git a/android/app/src/main/res/values-night/styles.xml b/sama_chat_client/android/app/src/main/res/values-night/styles.xml similarity index 100% rename from android/app/src/main/res/values-night/styles.xml rename to sama_chat_client/android/app/src/main/res/values-night/styles.xml diff --git a/android/app/src/main/res/values/ic_launcher_background.xml b/sama_chat_client/android/app/src/main/res/values/ic_launcher_background.xml similarity index 100% rename from android/app/src/main/res/values/ic_launcher_background.xml rename to sama_chat_client/android/app/src/main/res/values/ic_launcher_background.xml diff --git a/android/app/src/main/res/values/styles.xml b/sama_chat_client/android/app/src/main/res/values/styles.xml similarity index 100% rename from android/app/src/main/res/values/styles.xml rename to sama_chat_client/android/app/src/main/res/values/styles.xml diff --git a/android/app/src/profile/AndroidManifest.xml b/sama_chat_client/android/app/src/profile/AndroidManifest.xml similarity index 100% rename from android/app/src/profile/AndroidManifest.xml rename to sama_chat_client/android/app/src/profile/AndroidManifest.xml diff --git a/android/build.gradle b/sama_chat_client/android/build.gradle similarity index 100% rename from android/build.gradle rename to sama_chat_client/android/build.gradle diff --git a/android/gradle.properties b/sama_chat_client/android/gradle.properties similarity index 81% rename from android/gradle.properties rename to sama_chat_client/android/gradle.properties index 002aa016..a700745f 100644 --- a/android/gradle.properties +++ b/sama_chat_client/android/gradle.properties @@ -1,5 +1,5 @@ org.gradle.jvmargs=-Xmx4G android.useAndroidX=true android.enableJetifier=true -kotlinVersion=1.9.20 +kotlinVersion=2.2.0 agpVersion=8.9.0 \ No newline at end of file diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/sama_chat_client/android/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from android/gradle/wrapper/gradle-wrapper.properties rename to sama_chat_client/android/gradle/wrapper/gradle-wrapper.properties diff --git a/android/sama_client_flutter_android.iml b/sama_chat_client/android/sama_client_flutter_android.iml similarity index 100% rename from android/sama_client_flutter_android.iml rename to sama_chat_client/android/sama_client_flutter_android.iml diff --git a/android/settings.gradle b/sama_chat_client/android/settings.gradle similarity index 100% rename from android/settings.gradle rename to sama_chat_client/android/settings.gradle diff --git a/assets/images/1.5x/sama_background.png b/sama_chat_client/assets/images/1.5x/sama_background.png similarity index 100% rename from assets/images/1.5x/sama_background.png rename to sama_chat_client/assets/images/1.5x/sama_background.png diff --git a/assets/images/2.0x/sama_background.png b/sama_chat_client/assets/images/2.0x/sama_background.png similarity index 100% rename from assets/images/2.0x/sama_background.png rename to sama_chat_client/assets/images/2.0x/sama_background.png diff --git a/assets/images/3.0x/sama_background.png b/sama_chat_client/assets/images/3.0x/sama_background.png similarity index 100% rename from assets/images/3.0x/sama_background.png rename to sama_chat_client/assets/images/3.0x/sama_background.png diff --git a/assets/images/4.0x/sama_background.png b/sama_chat_client/assets/images/4.0x/sama_background.png similarity index 100% rename from assets/images/4.0x/sama_background.png rename to sama_chat_client/assets/images/4.0x/sama_background.png diff --git a/assets/images/Sama_Icon.png b/sama_chat_client/assets/images/Sama_Icon.png similarity index 100% rename from assets/images/Sama_Icon.png rename to sama_chat_client/assets/images/Sama_Icon.png diff --git a/assets/images/sama_background.png b/sama_chat_client/assets/images/sama_background.png similarity index 100% rename from assets/images/sama_background.png rename to sama_chat_client/assets/images/sama_background.png diff --git a/assets/images/vector_logo.png b/sama_chat_client/assets/images/vector_logo.png similarity index 100% rename from assets/images/vector_logo.png rename to sama_chat_client/assets/images/vector_logo.png diff --git a/devtools_options.yaml b/sama_chat_client/devtools_options.yaml similarity index 100% rename from devtools_options.yaml rename to sama_chat_client/devtools_options.yaml diff --git a/ios/.gitignore b/sama_chat_client/ios/.gitignore similarity index 100% rename from ios/.gitignore rename to sama_chat_client/ios/.gitignore diff --git a/ios/Flutter/AppFrameworkInfo.plist b/sama_chat_client/ios/Flutter/AppFrameworkInfo.plist similarity index 100% rename from ios/Flutter/AppFrameworkInfo.plist rename to sama_chat_client/ios/Flutter/AppFrameworkInfo.plist diff --git a/ios/Flutter/Debug.xcconfig b/sama_chat_client/ios/Flutter/Debug.xcconfig similarity index 100% rename from ios/Flutter/Debug.xcconfig rename to sama_chat_client/ios/Flutter/Debug.xcconfig diff --git a/ios/Flutter/Release.xcconfig b/sama_chat_client/ios/Flutter/Release.xcconfig similarity index 100% rename from ios/Flutter/Release.xcconfig rename to sama_chat_client/ios/Flutter/Release.xcconfig diff --git a/ios/Gemfile b/sama_chat_client/ios/Gemfile similarity index 100% rename from ios/Gemfile rename to sama_chat_client/ios/Gemfile diff --git a/ios/Gemfile.lock b/sama_chat_client/ios/Gemfile.lock similarity index 100% rename from ios/Gemfile.lock rename to sama_chat_client/ios/Gemfile.lock diff --git a/ios/NotificationService/Info.plist b/sama_chat_client/ios/NotificationService/Info.plist similarity index 100% rename from ios/NotificationService/Info.plist rename to sama_chat_client/ios/NotificationService/Info.plist diff --git a/ios/NotificationService/NotificationService.entitlements b/sama_chat_client/ios/NotificationService/NotificationService.entitlements similarity index 100% rename from ios/NotificationService/NotificationService.entitlements rename to sama_chat_client/ios/NotificationService/NotificationService.entitlements diff --git a/ios/NotificationService/NotificationService.swift b/sama_chat_client/ios/NotificationService/NotificationService.swift similarity index 100% rename from ios/NotificationService/NotificationService.swift rename to sama_chat_client/ios/NotificationService/NotificationService.swift diff --git a/ios/Podfile b/sama_chat_client/ios/Podfile similarity index 100% rename from ios/Podfile rename to sama_chat_client/ios/Podfile diff --git a/ios/Podfile.lock b/sama_chat_client/ios/Podfile.lock similarity index 69% rename from ios/Podfile.lock rename to sama_chat_client/ios/Podfile.lock index 9ce19584..4b707d66 100644 --- a/ios/Podfile.lock +++ b/sama_chat_client/ios/Podfile.lock @@ -1,9 +1,8 @@ PODS: - - app_set_id (1.2.1): + - app_set_id (1.3.0): - Flutter - connectivity_plus (0.0.1): - Flutter - - FlutterMacOS - DKImagePickerController/Core (4.3.9): - DKImagePickerController/ImageDataManager - DKImagePickerController/Resource @@ -38,37 +37,37 @@ PODS: - file_picker (0.0.1): - DKImagePickerController/PhotoGallery - Flutter - - Firebase/CoreOnly (11.4.0): - - FirebaseCore (= 11.4.0) - - Firebase/Messaging (11.4.0): + - Firebase/CoreOnly (11.15.0): + - FirebaseCore (~> 11.15.0) + - Firebase/Messaging (11.15.0): - Firebase/CoreOnly - - FirebaseMessaging (~> 11.4.0) - - firebase_core (3.7.0): - - Firebase/CoreOnly (= 11.4.0) + - FirebaseMessaging (~> 11.15.0) + - firebase_core (3.15.2): + - Firebase/CoreOnly (= 11.15.0) - Flutter - - firebase_messaging (15.1.4): - - Firebase/Messaging (= 11.4.0) + - firebase_messaging (15.2.10): + - Firebase/Messaging (= 11.15.0) - firebase_core - Flutter - - FirebaseCore (11.4.0): - - FirebaseCoreInternal (~> 11.0) - - GoogleUtilities/Environment (~> 8.0) - - GoogleUtilities/Logger (~> 8.0) - - FirebaseCoreInternal (11.4.2): - - "GoogleUtilities/NSData+zlib (~> 8.0)" - - FirebaseInstallations (11.4.0): - - FirebaseCore (~> 11.0) - - GoogleUtilities/Environment (~> 8.0) - - GoogleUtilities/UserDefaults (~> 8.0) + - FirebaseCore (11.15.0): + - FirebaseCoreInternal (~> 11.15.0) + - GoogleUtilities/Environment (~> 8.1) + - GoogleUtilities/Logger (~> 8.1) + - FirebaseCoreInternal (11.15.0): + - "GoogleUtilities/NSData+zlib (~> 8.1)" + - FirebaseInstallations (11.15.0): + - FirebaseCore (~> 11.15.0) + - GoogleUtilities/Environment (~> 8.1) + - GoogleUtilities/UserDefaults (~> 8.1) - PromisesObjC (~> 2.4) - - FirebaseMessaging (11.4.0): - - FirebaseCore (~> 11.0) + - FirebaseMessaging (11.15.0): + - FirebaseCore (~> 11.15.0) - FirebaseInstallations (~> 11.0) - GoogleDataTransport (~> 10.0) - - GoogleUtilities/AppDelegateSwizzler (~> 8.0) - - GoogleUtilities/Environment (~> 8.0) - - GoogleUtilities/Reachability (~> 8.0) - - GoogleUtilities/UserDefaults (~> 8.0) + - GoogleUtilities/AppDelegateSwizzler (~> 8.1) + - GoogleUtilities/Environment (~> 8.1) + - GoogleUtilities/Reachability (~> 8.1) + - GoogleUtilities/UserDefaults (~> 8.1) - nanopb (~> 3.30910.0) - Flutter (1.0.0) - flutter_image_compress_common (1.0.0): @@ -86,41 +85,41 @@ PODS: - GoogleDataTransport (10.1.0): - nanopb (~> 3.30910.0) - PromisesObjC (~> 2.4) - - GoogleUtilities/AppDelegateSwizzler (8.0.2): + - GoogleUtilities/AppDelegateSwizzler (8.1.0): - GoogleUtilities/Environment - GoogleUtilities/Logger - GoogleUtilities/Network - GoogleUtilities/Privacy - - GoogleUtilities/Environment (8.0.2): + - GoogleUtilities/Environment (8.1.0): - GoogleUtilities/Privacy - - GoogleUtilities/Logger (8.0.2): + - GoogleUtilities/Logger (8.1.0): - GoogleUtilities/Environment - GoogleUtilities/Privacy - - GoogleUtilities/Network (8.0.2): + - GoogleUtilities/Network (8.1.0): - GoogleUtilities/Logger - "GoogleUtilities/NSData+zlib" - GoogleUtilities/Privacy - GoogleUtilities/Reachability - - "GoogleUtilities/NSData+zlib (8.0.2)": + - "GoogleUtilities/NSData+zlib (8.1.0)": - GoogleUtilities/Privacy - - GoogleUtilities/Privacy (8.0.2) - - GoogleUtilities/Reachability (8.0.2): + - GoogleUtilities/Privacy (8.1.0) + - GoogleUtilities/Reachability (8.1.0): - GoogleUtilities/Logger - GoogleUtilities/Privacy - - GoogleUtilities/UserDefaults (8.0.2): + - GoogleUtilities/UserDefaults (8.1.0): - GoogleUtilities/Logger - GoogleUtilities/Privacy - - libwebp (1.3.2): - - libwebp/demux (= 1.3.2) - - libwebp/mux (= 1.3.2) - - libwebp/sharpyuv (= 1.3.2) - - libwebp/webp (= 1.3.2) - - libwebp/demux (1.3.2): + - libwebp (1.5.0): + - libwebp/demux (= 1.5.0) + - libwebp/mux (= 1.5.0) + - libwebp/sharpyuv (= 1.5.0) + - libwebp/webp (= 1.5.0) + - libwebp/demux (1.5.0): - libwebp/webp - - libwebp/mux (1.3.2): + - libwebp/mux (1.5.0): - libwebp/demux - - libwebp/sharpyuv (1.3.2) - - libwebp/webp (1.3.2): + - libwebp/sharpyuv (1.5.0) + - libwebp/webp (1.5.0): - libwebp/sharpyuv - Mantle (2.2.0): - Mantle/extobjc (= 2.2.0) @@ -130,10 +129,10 @@ PODS: - nanopb/encode (= 3.30910.0) - nanopb/decode (3.30910.0) - nanopb/encode (3.30910.0) - - ObjectBox (4.1.0) + - ObjectBox (4.4.1) - objectbox_flutter_libs (0.0.1): - Flutter - - ObjectBox (= 4.1.0) + - ObjectBox (= 4.4.1) - package_info_plus (0.4.5): - Flutter - path_provider_foundation (0.0.1): @@ -142,16 +141,16 @@ PODS: - PromisesObjC (2.4.0) - receive_sharing_intent (1.8.1): - Flutter - - SDWebImage (5.20.0): - - SDWebImage/Core (= 5.20.0) - - SDWebImage/Core (5.20.0) + - SDWebImage (5.21.3): + - SDWebImage/Core (= 5.21.3) + - SDWebImage/Core (5.21.3) - SDWebImageWebPCoder (0.14.6): - libwebp (~> 1.0) - SDWebImage/Core (~> 5.17) - shared_preferences_foundation (0.0.1): - Flutter - FlutterMacOS - - sqflite (0.0.3): + - sqflite_darwin (0.0.4): - Flutter - FlutterMacOS - SwiftyGif (5.4.5) @@ -167,7 +166,7 @@ PODS: DEPENDENCIES: - app_set_id (from `.symlinks/plugins/app_set_id/ios`) - - connectivity_plus (from `.symlinks/plugins/connectivity_plus/darwin`) + - connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`) - file_picker (from `.symlinks/plugins/file_picker/ios`) - firebase_core (from `.symlinks/plugins/firebase_core/ios`) - firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`) @@ -181,7 +180,7 @@ DEPENDENCIES: - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - receive_sharing_intent (from `.symlinks/plugins/receive_sharing_intent/ios`) - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) - - sqflite (from `.symlinks/plugins/sqflite/darwin`) + - sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`) - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) - video_compress (from `.symlinks/plugins/video_compress/ios`) - video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/darwin`) @@ -211,7 +210,7 @@ EXTERNAL SOURCES: app_set_id: :path: ".symlinks/plugins/app_set_id/ios" connectivity_plus: - :path: ".symlinks/plugins/connectivity_plus/darwin" + :path: ".symlinks/plugins/connectivity_plus/ios" file_picker: :path: ".symlinks/plugins/file_picker/ios" firebase_core: @@ -238,8 +237,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/receive_sharing_intent/ios" shared_preferences_foundation: :path: ".symlinks/plugins/shared_preferences_foundation/darwin" - sqflite: - :path: ".symlinks/plugins/sqflite/darwin" + sqflite_darwin: + :path: ".symlinks/plugins/sqflite_darwin/darwin" url_launcher_ios: :path: ".symlinks/plugins/url_launcher_ios/ios" video_compress: @@ -250,43 +249,43 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/wakelock_plus/ios" SPEC CHECKSUMS: - app_set_id: e0349a05a0ecc6d5c937d42869aa941f90801c9c - connectivity_plus: ddd7f30999e1faaef5967c23d5b6d503d10434db + app_set_id: 0e0db3830db2bca1b67eecec1e2ab80b2bec48fa + connectivity_plus: 2a701ffec2c0ae28a48cf7540e279787e77c447d DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60 - file_picker: 09aa5ec1ab24135ccd7a1621c46c84134bfd6655 - Firebase: cf1b19f21410b029b6786a54e9764a0cacad3c99 - firebase_core: f8c5b220a8f9c436fdbd075ae321cef3d96ef181 - firebase_messaging: a7f18d98006bbd8fd0918f4db64b9a70df29aaa8 - FirebaseCore: e0510f1523bc0eb21653cac00792e1e2bd6f1771 - FirebaseCoreInternal: 35731192cab10797b88411be84940d2beb33a238 - FirebaseInstallations: 6ef4a1c7eb2a61ee1f74727d7f6ce2e72acf1414 - FirebaseMessaging: f8a160d99c2c2e5babbbcc90c4a3e15db036aee2 - Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 + file_picker: b159e0c068aef54932bb15dc9fd1571818edaf49 + Firebase: d99ac19b909cd2c548339c2241ecd0d1599ab02e + firebase_core: 99a37263b3c27536063a7b601d9e2a49400a433c + firebase_messaging: bf6697c61f31c7cc0f654131212ff04c0115c2c7 + FirebaseCore: efb3893e5b94f32b86e331e3bd6dadf18b66568e + FirebaseCoreInternal: 9afa45b1159304c963da48addb78275ef701c6b4 + FirebaseInstallations: 317270fec08a5d418fdbc8429282238cab3ac843 + FirebaseMessaging: 3b26e2cee503815e01c3701236b020aa9b576f09 + Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 flutter_image_compress_common: ec1d45c362c9d30a3f6a0426c297f47c52007e3e flutter_local_notifications: df98d66e515e1ca797af436137b4459b160ad8c9 flutter_secure_storage: d33dac7ae2ea08509be337e775f6b59f1ff45f12 get_thumbnail_video: b9a180957daed3e9179e66268db51d8798e41f65 GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7 - GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d - libwebp: 1786c9f4ff8a279e4dac1e8f385004d5fc253009 + GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1 + libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8 Mantle: c5aa8794a29a022dfbbfc9799af95f477a69b62d nanopb: fad817b59e0457d11a5dfbde799381cd727c1275 - ObjectBox: bf3d4b51075d52868422d5d1f2f2141b1d630d30 - objectbox_flutter_libs: 2f30755c12b0fe104d75445c3ba879e3072eda54 + ObjectBox: 7da4aceb5013d041bfafdbc6d744a26918b09757 + objectbox_flutter_libs: 7a6ea1d74b43f5d970e6571d1b79e4b181b33d81 package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4 - path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 + path_provider_foundation: 0b743cbb62d8e47eab856f09262bb8c1ddcfe6ba PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 receive_sharing_intent: 79c848f5b045674ad60b9fea3bafea59962ad2c1 - SDWebImage: 73c6079366fea25fa4bb9640d5fb58f0893facd8 + SDWebImage: 16309af6d214ba3f77a7c6f6fdda888cb313a50a SDWebImageWebPCoder: e38c0a70396191361d60c092933e22c20d5b1380 - shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 - sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec + shared_preferences_foundation: 5086985c1d43c5ba4d5e69a4e8083a389e2909e6 + sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 - url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe + url_launcher_ios: bb13df5870e8c4234ca12609d04010a21be43dfa video_compress: fce97e4fb1dfd88175aa07d2ffc8a2f297f87fbe - video_player_avfoundation: 7c6c11d8470e1675df7397027218274b6d2360b3 - wakelock_plus: 373cfe59b235a6dd5837d0fb88791d2f13a90d56 + video_player_avfoundation: 7993f492ae0bd77edaea24d9dc051d8bb2cd7c86 + wakelock_plus: 76957ab028e12bfa4e66813c99e46637f367fc7e PODFILE CHECKSUM: c7e19d55b5c9decda9f4c0789c7514ec65be5713 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/sama_chat_client/ios/Runner.xcodeproj/project.pbxproj similarity index 100% rename from ios/Runner.xcodeproj/project.pbxproj rename to sama_chat_client/ios/Runner.xcodeproj/project.pbxproj diff --git a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/sama_chat_client/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to sama_chat_client/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/sama_chat_client/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 100% rename from ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to sama_chat_client/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/sama_chat_client/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings similarity index 100% rename from ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings rename to sama_chat_client/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/sama_chat_client/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme similarity index 100% rename from ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme rename to sama_chat_client/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/sama_chat_client/ios/Runner.xcworkspace/contents.xcworkspacedata similarity index 100% rename from ios/Runner.xcworkspace/contents.xcworkspacedata rename to sama_chat_client/ios/Runner.xcworkspace/contents.xcworkspacedata diff --git a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/sama_chat_client/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 100% rename from ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to sama_chat_client/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/sama_chat_client/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings similarity index 100% rename from ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings rename to sama_chat_client/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings diff --git a/ios/Runner/AppDelegate.swift b/sama_chat_client/ios/Runner/AppDelegate.swift similarity index 100% rename from ios/Runner/AppDelegate.swift rename to sama_chat_client/ios/Runner/AppDelegate.swift diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json rename to sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png similarity index 100% rename from ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png rename to sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png similarity index 100% rename from ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png rename to sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png similarity index 100% rename from ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png rename to sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png similarity index 100% rename from ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png rename to sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png similarity index 100% rename from ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png rename to sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png similarity index 100% rename from ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png rename to sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png similarity index 100% rename from ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png rename to sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png similarity index 100% rename from ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png rename to sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png similarity index 100% rename from ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png rename to sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png similarity index 100% rename from ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png rename to sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png b/sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png similarity index 100% rename from ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png rename to sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png b/sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png similarity index 100% rename from ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png rename to sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png b/sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png similarity index 100% rename from ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png rename to sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png b/sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png similarity index 100% rename from ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png rename to sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png similarity index 100% rename from ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png rename to sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png similarity index 100% rename from ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png rename to sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png b/sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png similarity index 100% rename from ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png rename to sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png b/sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png similarity index 100% rename from ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png rename to sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png similarity index 100% rename from ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png rename to sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png similarity index 100% rename from ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png rename to sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png similarity index 100% rename from ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png rename to sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png b/sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png similarity index 100% rename from ios/Runner/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png rename to sama_chat_client/ios/Runner/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png diff --git a/ios/Runner/Assets.xcassets/Contents.json b/sama_chat_client/ios/Runner/Assets.xcassets/Contents.json similarity index 100% rename from ios/Runner/Assets.xcassets/Contents.json rename to sama_chat_client/ios/Runner/Assets.xcassets/Contents.json diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/sama_chat_client/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json similarity index 100% rename from ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json rename to sama_chat_client/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/sama_chat_client/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md similarity index 100% rename from ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md rename to sama_chat_client/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/sama_1024.png b/sama_chat_client/ios/Runner/Assets.xcassets/LaunchImage.imageset/sama_1024.png similarity index 100% rename from ios/Runner/Assets.xcassets/LaunchImage.imageset/sama_1024.png rename to sama_chat_client/ios/Runner/Assets.xcassets/LaunchImage.imageset/sama_1024.png diff --git a/ios/Runner/Assets.xcassets/iTunesArtwork@1x.png b/sama_chat_client/ios/Runner/Assets.xcassets/iTunesArtwork@1x.png similarity index 100% rename from ios/Runner/Assets.xcassets/iTunesArtwork@1x.png rename to sama_chat_client/ios/Runner/Assets.xcassets/iTunesArtwork@1x.png diff --git a/ios/Runner/Assets.xcassets/iTunesArtwork@2x.png b/sama_chat_client/ios/Runner/Assets.xcassets/iTunesArtwork@2x.png similarity index 100% rename from ios/Runner/Assets.xcassets/iTunesArtwork@2x.png rename to sama_chat_client/ios/Runner/Assets.xcassets/iTunesArtwork@2x.png diff --git a/ios/Runner/Assets.xcassets/iTunesArtwork@3x.png b/sama_chat_client/ios/Runner/Assets.xcassets/iTunesArtwork@3x.png similarity index 100% rename from ios/Runner/Assets.xcassets/iTunesArtwork@3x.png rename to sama_chat_client/ios/Runner/Assets.xcassets/iTunesArtwork@3x.png diff --git a/ios/Runner/Base.lproj/LaunchScreen.storyboard b/sama_chat_client/ios/Runner/Base.lproj/LaunchScreen.storyboard similarity index 100% rename from ios/Runner/Base.lproj/LaunchScreen.storyboard rename to sama_chat_client/ios/Runner/Base.lproj/LaunchScreen.storyboard diff --git a/ios/Runner/Base.lproj/Main.storyboard b/sama_chat_client/ios/Runner/Base.lproj/Main.storyboard similarity index 100% rename from ios/Runner/Base.lproj/Main.storyboard rename to sama_chat_client/ios/Runner/Base.lproj/Main.storyboard diff --git a/ios/Runner/GoogleService-Info.plist b/sama_chat_client/ios/Runner/GoogleService-Info.plist similarity index 100% rename from ios/Runner/GoogleService-Info.plist rename to sama_chat_client/ios/Runner/GoogleService-Info.plist diff --git a/ios/Runner/Info.plist b/sama_chat_client/ios/Runner/Info.plist similarity index 100% rename from ios/Runner/Info.plist rename to sama_chat_client/ios/Runner/Info.plist diff --git a/ios/Runner/Runner-Bridging-Header.h b/sama_chat_client/ios/Runner/Runner-Bridging-Header.h similarity index 100% rename from ios/Runner/Runner-Bridging-Header.h rename to sama_chat_client/ios/Runner/Runner-Bridging-Header.h diff --git a/ios/Runner/Runner.entitlements b/sama_chat_client/ios/Runner/Runner.entitlements similarity index 100% rename from ios/Runner/Runner.entitlements rename to sama_chat_client/ios/Runner/Runner.entitlements diff --git a/ios/RunnerTests/RunnerTests.swift b/sama_chat_client/ios/RunnerTests/RunnerTests.swift similarity index 100% rename from ios/RunnerTests/RunnerTests.swift rename to sama_chat_client/ios/RunnerTests/RunnerTests.swift diff --git a/ios/Share Extension/Base.lproj/MainInterface.storyboard b/sama_chat_client/ios/Share Extension/Base.lproj/MainInterface.storyboard similarity index 100% rename from ios/Share Extension/Base.lproj/MainInterface.storyboard rename to sama_chat_client/ios/Share Extension/Base.lproj/MainInterface.storyboard diff --git a/ios/Share Extension/Info.plist b/sama_chat_client/ios/Share Extension/Info.plist similarity index 100% rename from ios/Share Extension/Info.plist rename to sama_chat_client/ios/Share Extension/Info.plist diff --git a/ios/Share Extension/Share Extension.entitlements b/sama_chat_client/ios/Share Extension/Share Extension.entitlements similarity index 100% rename from ios/Share Extension/Share Extension.entitlements rename to sama_chat_client/ios/Share Extension/Share Extension.entitlements diff --git a/ios/Share Extension/ShareViewController.swift b/sama_chat_client/ios/Share Extension/ShareViewController.swift similarity index 100% rename from ios/Share Extension/ShareViewController.swift rename to sama_chat_client/ios/Share Extension/ShareViewController.swift diff --git a/ios/fastlane/Appfile b/sama_chat_client/ios/fastlane/Appfile similarity index 100% rename from ios/fastlane/Appfile rename to sama_chat_client/ios/fastlane/Appfile diff --git a/ios/fastlane/Fastfile b/sama_chat_client/ios/fastlane/Fastfile similarity index 100% rename from ios/fastlane/Fastfile rename to sama_chat_client/ios/fastlane/Fastfile diff --git a/ios/firebase_app_id_file.json b/sama_chat_client/ios/firebase_app_id_file.json similarity index 100% rename from ios/firebase_app_id_file.json rename to sama_chat_client/ios/firebase_app_id_file.json diff --git a/lib/main.dart b/sama_chat_client/lib/main.dart similarity index 98% rename from lib/main.dart rename to sama_chat_client/lib/main.dart index eac707a0..e88de838 100644 --- a/lib/main.dart +++ b/sama_chat_client/lib/main.dart @@ -4,12 +4,13 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'sama_firebase_options.dart'; -import 'src/api/api.dart'; + import 'src/db/db_service.dart'; import 'src/db/local/attachment_local_datasource.dart'; import 'src/db/local/conversation_local_datasource.dart'; import 'src/db/local/message_local_datasource.dart'; import 'src/db/local/user_local_datasource.dart'; +import 'src/shared/push_notifications/push_notifications_manager.dart'; import 'src/navigation/app_router.dart'; import 'src/repository/attachments/attachments_repository.dart'; import 'src/repository/authentication/authentication_repository.dart'; @@ -59,6 +60,7 @@ class _AppState extends State { @override void initState() { super.initState(); + initSettings(); clearKeychainValuesIfUninstall(); _conversationLocalDatasource = ConversationLocalDatasource(); _messageLocalDatasource = MessageLocalDatasource(); diff --git a/lib/main.dart.run.xml b/sama_chat_client/lib/main.dart.run.xml similarity index 100% rename from lib/main.dart.run.xml rename to sama_chat_client/lib/main.dart.run.xml diff --git a/lib/objectbox-model.json b/sama_chat_client/lib/objectbox-model.json similarity index 100% rename from lib/objectbox-model.json rename to sama_chat_client/lib/objectbox-model.json diff --git a/lib/objectbox.g.dart b/sama_chat_client/lib/objectbox.g.dart similarity index 100% rename from lib/objectbox.g.dart rename to sama_chat_client/lib/objectbox.g.dart diff --git a/lib/sama_firebase_options.dart b/sama_chat_client/lib/sama_firebase_options.dart similarity index 100% rename from lib/sama_firebase_options.dart rename to sama_chat_client/lib/sama_firebase_options.dart diff --git a/lib/src/db/db_service.dart b/sama_chat_client/lib/src/db/db_service.dart similarity index 100% rename from lib/src/db/db_service.dart rename to sama_chat_client/lib/src/db/db_service.dart diff --git a/lib/src/db/local/attachment_local_datasource.dart b/sama_chat_client/lib/src/db/local/attachment_local_datasource.dart similarity index 100% rename from lib/src/db/local/attachment_local_datasource.dart rename to sama_chat_client/lib/src/db/local/attachment_local_datasource.dart diff --git a/lib/src/db/local/conversation_local_datasource.dart b/sama_chat_client/lib/src/db/local/conversation_local_datasource.dart similarity index 100% rename from lib/src/db/local/conversation_local_datasource.dart rename to sama_chat_client/lib/src/db/local/conversation_local_datasource.dart diff --git a/lib/src/db/local/message_local_datasource.dart b/sama_chat_client/lib/src/db/local/message_local_datasource.dart similarity index 100% rename from lib/src/db/local/message_local_datasource.dart rename to sama_chat_client/lib/src/db/local/message_local_datasource.dart diff --git a/lib/src/db/local/user_local_datasource.dart b/sama_chat_client/lib/src/db/local/user_local_datasource.dart similarity index 100% rename from lib/src/db/local/user_local_datasource.dart rename to sama_chat_client/lib/src/db/local/user_local_datasource.dart diff --git a/lib/src/db/models/attachment_model.dart b/sama_chat_client/lib/src/db/models/attachment_model.dart similarity index 81% rename from lib/src/db/models/attachment_model.dart rename to sama_chat_client/lib/src/db/models/attachment_model.dart index 87f29ec2..a49068b9 100644 --- a/lib/src/db/models/attachment_model.dart +++ b/sama_chat_client/lib/src/db/models/attachment_model.dart @@ -1,7 +1,6 @@ import 'package:equatable/equatable.dart'; import 'package:objectbox/objectbox.dart'; - -import '../../api/conversations/models/models.dart'; +import 'package:sama_sdk/api/conversations/models/attachment.dart'; @Entity() // ignore: must_be_immutable @@ -72,3 +71,16 @@ extension AttachmentModelExtension on Attachment { fileWidth: fileWidth); } } + +extension AttachmentExtension on AttachmentModel { + Attachment toAttachment() { + return Attachment( + fileId: fileId, + fileName: fileName, + fileBlurHash: fileBlurHash, + // fileUrl: url, // not available on server + fileContentType: contentType, + fileHeight: fileHeight, + fileWidth: fileWidth); + } +} diff --git a/lib/src/db/models/avatar_model.dart b/sama_chat_client/lib/src/db/models/avatar_model.dart similarity index 92% rename from lib/src/db/models/avatar_model.dart rename to sama_chat_client/lib/src/db/models/avatar_model.dart index 98cdbb71..3a348699 100644 --- a/lib/src/db/models/avatar_model.dart +++ b/sama_chat_client/lib/src/db/models/avatar_model.dart @@ -1,7 +1,6 @@ import 'package:equatable/equatable.dart'; import 'package:objectbox/objectbox.dart'; - -import '../../api/conversations/models/models.dart'; +import 'package:sama_sdk/api/conversations/models/avatar.dart'; @Entity() // ignore: must_be_immutable diff --git a/lib/src/db/models/conversation_model.dart b/sama_chat_client/lib/src/db/models/conversation_model.dart similarity index 100% rename from lib/src/db/models/conversation_model.dart rename to sama_chat_client/lib/src/db/models/conversation_model.dart diff --git a/lib/src/db/models/message_model.dart b/sama_chat_client/lib/src/db/models/message_model.dart similarity index 98% rename from lib/src/db/models/message_model.dart rename to sama_chat_client/lib/src/db/models/message_model.dart index 020a04e3..4db5a243 100644 --- a/lib/src/db/models/message_model.dart +++ b/sama_chat_client/lib/src/db/models/message_model.dart @@ -2,8 +2,8 @@ import 'dart:convert'; import 'package:equatable/equatable.dart'; import 'package:objectbox/objectbox.dart'; +import 'package:sama_sdk/api/conversations/models/message.dart'; -import '../../api/conversations/models/models.dart'; import 'models.dart'; @Entity() diff --git a/lib/src/db/models/models.dart b/sama_chat_client/lib/src/db/models/models.dart similarity index 100% rename from lib/src/db/models/models.dart rename to sama_chat_client/lib/src/db/models/models.dart diff --git a/lib/src/db/models/user_model.dart b/sama_chat_client/lib/src/db/models/user_model.dart similarity index 97% rename from lib/src/db/models/user_model.dart rename to sama_chat_client/lib/src/db/models/user_model.dart index 6cd1792d..cc362a67 100644 --- a/lib/src/db/models/user_model.dart +++ b/sama_chat_client/lib/src/db/models/user_model.dart @@ -1,7 +1,7 @@ import 'package:equatable/equatable.dart'; import 'package:objectbox/objectbox.dart'; +import 'package:sama_sdk/api/users/models/user.dart'; -import '../../api/users/models/models.dart'; import 'avatar_model.dart'; @Entity() diff --git a/lib/src/db/network_bound_resource.dart b/sama_chat_client/lib/src/db/network_bound_resource.dart similarity index 100% rename from lib/src/db/network_bound_resource.dart rename to sama_chat_client/lib/src/db/network_bound_resource.dart diff --git a/lib/src/db/resource.dart b/sama_chat_client/lib/src/db/resource.dart similarity index 100% rename from lib/src/db/resource.dart rename to sama_chat_client/lib/src/db/resource.dart diff --git a/lib/src/api/utils/config.dart b/sama_chat_client/lib/src/features/config.dart similarity index 100% rename from lib/src/api/utils/config.dart rename to sama_chat_client/lib/src/features/config.dart diff --git a/lib/src/features/conversation/bloc/ai_message/ai_message_bloc.dart b/sama_chat_client/lib/src/features/conversation/bloc/ai_message/ai_message_bloc.dart similarity index 97% rename from lib/src/features/conversation/bloc/ai_message/ai_message_bloc.dart rename to sama_chat_client/lib/src/features/conversation/bloc/ai_message/ai_message_bloc.dart index ca32e82a..a16f2784 100644 --- a/lib/src/features/conversation/bloc/ai_message/ai_message_bloc.dart +++ b/sama_chat_client/lib/src/features/conversation/bloc/ai_message/ai_message_bloc.dart @@ -2,8 +2,8 @@ import 'dart:async'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; +import 'package:sama_sdk/api/api.dart'; -import '../../../../api/api.dart'; import '../../../../db/models/models.dart'; import '../../../../repository/messages/messages_repository.dart'; diff --git a/lib/src/features/conversation/bloc/ai_message/ai_message_event.dart b/sama_chat_client/lib/src/features/conversation/bloc/ai_message/ai_message_event.dart similarity index 100% rename from lib/src/features/conversation/bloc/ai_message/ai_message_event.dart rename to sama_chat_client/lib/src/features/conversation/bloc/ai_message/ai_message_event.dart diff --git a/lib/src/features/conversation/bloc/ai_message/ai_message_state.dart b/sama_chat_client/lib/src/features/conversation/bloc/ai_message/ai_message_state.dart similarity index 100% rename from lib/src/features/conversation/bloc/ai_message/ai_message_state.dart rename to sama_chat_client/lib/src/features/conversation/bloc/ai_message/ai_message_state.dart diff --git a/lib/src/features/conversation/bloc/conversation_bloc.dart b/sama_chat_client/lib/src/features/conversation/bloc/conversation_bloc.dart similarity index 99% rename from lib/src/features/conversation/bloc/conversation_bloc.dart rename to sama_chat_client/lib/src/features/conversation/bloc/conversation_bloc.dart index 76d9399c..10270d87 100644 --- a/lib/src/features/conversation/bloc/conversation_bloc.dart +++ b/sama_chat_client/lib/src/features/conversation/bloc/conversation_bloc.dart @@ -5,9 +5,9 @@ import 'package:bloc_concurrency/bloc_concurrency.dart'; import 'package:collection/collection.dart'; import 'package:equatable/equatable.dart'; import 'package:formz/formz.dart'; +import 'package:sama_sdk/api/api.dart'; import 'package:stream_transform/stream_transform.dart'; -import '../../../api/api.dart'; import '../../../db/models/models.dart'; import '../../../db/resource.dart'; import '../../../repository/conversation/conversation_repository.dart'; diff --git a/lib/src/features/conversation/bloc/conversation_event.dart b/sama_chat_client/lib/src/features/conversation/bloc/conversation_event.dart similarity index 100% rename from lib/src/features/conversation/bloc/conversation_event.dart rename to sama_chat_client/lib/src/features/conversation/bloc/conversation_event.dart diff --git a/lib/src/features/conversation/bloc/conversation_state.dart b/sama_chat_client/lib/src/features/conversation/bloc/conversation_state.dart similarity index 100% rename from lib/src/features/conversation/bloc/conversation_state.dart rename to sama_chat_client/lib/src/features/conversation/bloc/conversation_state.dart diff --git a/lib/src/features/conversation/bloc/delete_messages/delete_messages_bloc.dart b/sama_chat_client/lib/src/features/conversation/bloc/delete_messages/delete_messages_bloc.dart similarity index 96% rename from lib/src/features/conversation/bloc/delete_messages/delete_messages_bloc.dart rename to sama_chat_client/lib/src/features/conversation/bloc/delete_messages/delete_messages_bloc.dart index 6b95860e..746bdcbd 100644 --- a/lib/src/features/conversation/bloc/delete_messages/delete_messages_bloc.dart +++ b/sama_chat_client/lib/src/features/conversation/bloc/delete_messages/delete_messages_bloc.dart @@ -2,8 +2,8 @@ import 'dart:async'; import 'package:equatable/equatable.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:sama_sdk/api/api.dart'; -import '../../../../api/api.dart'; import '../../../../db/models/conversation_model.dart'; import '../../../../repository/messages/messages_repository.dart'; import '../../models/chat_message.dart'; diff --git a/lib/src/features/conversation/bloc/delete_messages/delete_messages_event.dart b/sama_chat_client/lib/src/features/conversation/bloc/delete_messages/delete_messages_event.dart similarity index 100% rename from lib/src/features/conversation/bloc/delete_messages/delete_messages_event.dart rename to sama_chat_client/lib/src/features/conversation/bloc/delete_messages/delete_messages_event.dart diff --git a/lib/src/features/conversation/bloc/delete_messages/delete_messages_state.dart b/sama_chat_client/lib/src/features/conversation/bloc/delete_messages/delete_messages_state.dart similarity index 100% rename from lib/src/features/conversation/bloc/delete_messages/delete_messages_state.dart rename to sama_chat_client/lib/src/features/conversation/bloc/delete_messages/delete_messages_state.dart diff --git a/lib/src/features/conversation/bloc/forward_message/forward_messages_bloc.dart b/sama_chat_client/lib/src/features/conversation/bloc/forward_message/forward_messages_bloc.dart similarity index 100% rename from lib/src/features/conversation/bloc/forward_message/forward_messages_bloc.dart rename to sama_chat_client/lib/src/features/conversation/bloc/forward_message/forward_messages_bloc.dart diff --git a/lib/src/features/conversation/bloc/forward_message/forward_messages_event.dart b/sama_chat_client/lib/src/features/conversation/bloc/forward_message/forward_messages_event.dart similarity index 100% rename from lib/src/features/conversation/bloc/forward_message/forward_messages_event.dart rename to sama_chat_client/lib/src/features/conversation/bloc/forward_message/forward_messages_event.dart diff --git a/lib/src/features/conversation/bloc/forward_message/forward_messages_state.dart b/sama_chat_client/lib/src/features/conversation/bloc/forward_message/forward_messages_state.dart similarity index 100% rename from lib/src/features/conversation/bloc/forward_message/forward_messages_state.dart rename to sama_chat_client/lib/src/features/conversation/bloc/forward_message/forward_messages_state.dart diff --git a/lib/src/features/conversation/bloc/media_attachment/media_attachment_bloc.dart b/sama_chat_client/lib/src/features/conversation/bloc/media_attachment/media_attachment_bloc.dart similarity index 100% rename from lib/src/features/conversation/bloc/media_attachment/media_attachment_bloc.dart rename to sama_chat_client/lib/src/features/conversation/bloc/media_attachment/media_attachment_bloc.dart diff --git a/lib/src/features/conversation/bloc/media_attachment/media_attachment_event.dart b/sama_chat_client/lib/src/features/conversation/bloc/media_attachment/media_attachment_event.dart similarity index 100% rename from lib/src/features/conversation/bloc/media_attachment/media_attachment_event.dart rename to sama_chat_client/lib/src/features/conversation/bloc/media_attachment/media_attachment_event.dart diff --git a/lib/src/features/conversation/bloc/media_attachment/media_attachment_state.dart b/sama_chat_client/lib/src/features/conversation/bloc/media_attachment/media_attachment_state.dart similarity index 100% rename from lib/src/features/conversation/bloc/media_attachment/media_attachment_state.dart rename to sama_chat_client/lib/src/features/conversation/bloc/media_attachment/media_attachment_state.dart diff --git a/lib/src/features/conversation/bloc/media_sender/media_sender_bloc.dart b/sama_chat_client/lib/src/features/conversation/bloc/media_sender/media_sender_bloc.dart similarity index 98% rename from lib/src/features/conversation/bloc/media_sender/media_sender_bloc.dart rename to sama_chat_client/lib/src/features/conversation/bloc/media_sender/media_sender_bloc.dart index 9428e097..2c7f7960 100644 --- a/lib/src/features/conversation/bloc/media_sender/media_sender_bloc.dart +++ b/sama_chat_client/lib/src/features/conversation/bloc/media_sender/media_sender_bloc.dart @@ -5,14 +5,13 @@ import 'package:equatable/equatable.dart'; import 'package:file_picker/file_picker.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:path/path.dart'; +import 'package:sama_sdk/api/api.dart'; -import '../../../../api/api.dart'; import '../../../../db/models/conversation_model.dart'; import '../../../../db/models/message_model.dart'; import '../../../../repository/messages/messages_repository.dart'; import '../../../../shared/utils/file_utils.dart'; import '../../../../shared/utils/media_utils.dart'; -import '../../models/chat_message.dart'; part 'media_sender_event.dart'; diff --git a/lib/src/features/conversation/bloc/media_sender/media_sender_event.dart b/sama_chat_client/lib/src/features/conversation/bloc/media_sender/media_sender_event.dart similarity index 100% rename from lib/src/features/conversation/bloc/media_sender/media_sender_event.dart rename to sama_chat_client/lib/src/features/conversation/bloc/media_sender/media_sender_event.dart diff --git a/lib/src/features/conversation/bloc/media_sender/media_sender_state.dart b/sama_chat_client/lib/src/features/conversation/bloc/media_sender/media_sender_state.dart similarity index 100% rename from lib/src/features/conversation/bloc/media_sender/media_sender_state.dart rename to sama_chat_client/lib/src/features/conversation/bloc/media_sender/media_sender_state.dart diff --git a/lib/src/features/conversation/bloc/send_message/send_message_bloc.dart b/sama_chat_client/lib/src/features/conversation/bloc/send_message/send_message_bloc.dart similarity index 99% rename from lib/src/features/conversation/bloc/send_message/send_message_bloc.dart rename to sama_chat_client/lib/src/features/conversation/bloc/send_message/send_message_bloc.dart index bea916ee..a54e2cfe 100644 --- a/lib/src/features/conversation/bloc/send_message/send_message_bloc.dart +++ b/sama_chat_client/lib/src/features/conversation/bloc/send_message/send_message_bloc.dart @@ -3,9 +3,9 @@ import 'dart:async'; import 'package:bloc_concurrency/bloc_concurrency.dart'; import 'package:equatable/equatable.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:sama_sdk/api/api.dart'; import 'package:stream_transform/stream_transform.dart'; -import '../../../../api/api.dart'; import '../../../../db/models/conversation_model.dart'; import '../../../../db/models/message_model.dart'; import '../../../../repository/conversation/conversation_repository.dart'; diff --git a/lib/src/features/conversation/bloc/send_message/send_message_event.dart b/sama_chat_client/lib/src/features/conversation/bloc/send_message/send_message_event.dart similarity index 100% rename from lib/src/features/conversation/bloc/send_message/send_message_event.dart rename to sama_chat_client/lib/src/features/conversation/bloc/send_message/send_message_event.dart diff --git a/lib/src/features/conversation/bloc/send_message/send_message_state.dart b/sama_chat_client/lib/src/features/conversation/bloc/send_message/send_message_state.dart similarity index 100% rename from lib/src/features/conversation/bloc/send_message/send_message_state.dart rename to sama_chat_client/lib/src/features/conversation/bloc/send_message/send_message_state.dart diff --git a/lib/src/features/conversation/models/chat_message.dart b/sama_chat_client/lib/src/features/conversation/models/chat_message.dart similarity index 100% rename from lib/src/features/conversation/models/chat_message.dart rename to sama_chat_client/lib/src/features/conversation/models/chat_message.dart diff --git a/lib/src/features/conversation/models/models.dart b/sama_chat_client/lib/src/features/conversation/models/models.dart similarity index 100% rename from lib/src/features/conversation/models/models.dart rename to sama_chat_client/lib/src/features/conversation/models/models.dart diff --git a/lib/src/features/conversation/models/selected_messages.dart b/sama_chat_client/lib/src/features/conversation/models/selected_messages.dart similarity index 86% rename from lib/src/features/conversation/models/selected_messages.dart rename to sama_chat_client/lib/src/features/conversation/models/selected_messages.dart index c282219d..81fe022c 100644 --- a/lib/src/features/conversation/models/selected_messages.dart +++ b/sama_chat_client/lib/src/features/conversation/models/selected_messages.dart @@ -1,6 +1,6 @@ import 'package:formz/formz.dart'; +import 'package:sama_sdk/api/settings.dart'; -import '../../../shared/utils/api_utils.dart'; import 'chat_message.dart'; enum SelectedChatsValidationError { @@ -17,7 +17,7 @@ class SelectedMessages @override SelectedChatsValidationError? validator(Set value) { if (value.isEmpty) return SelectedChatsValidationError.empty; - if (value.length > maxChatsSelected) { + if (value.length > maxChatsToSelect) { return SelectedChatsValidationError.long; } return null; diff --git a/lib/src/features/conversation/view/conversation_page.dart b/sama_chat_client/lib/src/features/conversation/view/conversation_page.dart similarity index 97% rename from lib/src/features/conversation/view/conversation_page.dart rename to sama_chat_client/lib/src/features/conversation/view/conversation_page.dart index ffe402bc..1436f48d 100644 --- a/lib/src/features/conversation/view/conversation_page.dart +++ b/sama_chat_client/lib/src/features/conversation/view/conversation_page.dart @@ -4,8 +4,8 @@ import 'package:flutter/material.dart' hide ConnectionState; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:go_router/go_router.dart'; import 'package:intl/intl.dart'; +import 'package:sama_sdk/api/chats/realtime/typing_manager.dart'; -import '../../../api/api.dart' show TypingState; import '../../../db/models/conversation_model.dart'; import '../../../navigation/constants.dart'; import '../../../repository/attachments/attachments_repository.dart'; @@ -92,8 +92,10 @@ class ConversationPage extends StatelessWidget { title: BlocBuilder( builder: (BuildContext context, aiState) { return aiState.status == AiMessageStatus.processing - ? const TitleLoader(black, Text('AI processing', - style: TextStyle(color: black, fontSize: 20.0))) + ? const TitleLoader( + black, + Text('AI processing', + style: TextStyle(color: black, fontSize: 20.0))) : ConnectionTitle( color: black, title: Padding( diff --git a/lib/src/features/conversation/view/media_sender.dart b/sama_chat_client/lib/src/features/conversation/view/media_sender.dart similarity index 100% rename from lib/src/features/conversation/view/media_sender.dart rename to sama_chat_client/lib/src/features/conversation/view/media_sender.dart diff --git a/lib/src/features/conversation/view/message_input.dart b/sama_chat_client/lib/src/features/conversation/view/message_input.dart similarity index 100% rename from lib/src/features/conversation/view/message_input.dart rename to sama_chat_client/lib/src/features/conversation/view/message_input.dart diff --git a/lib/src/features/conversation/view/messages_list.dart b/sama_chat_client/lib/src/features/conversation/view/messages_list.dart similarity index 99% rename from lib/src/features/conversation/view/messages_list.dart rename to sama_chat_client/lib/src/features/conversation/view/messages_list.dart index 552deb0e..3036e741 100644 --- a/lib/src/features/conversation/view/messages_list.dart +++ b/sama_chat_client/lib/src/features/conversation/view/messages_list.dart @@ -1,7 +1,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:sama_sdk/api/api.dart' hide DeleteMessagesStatus; import 'package:scrollable_positioned_list/scrollable_positioned_list.dart'; -import '../../../api/api.dart' hide DeleteMessagesStatus; + import '../../../db/models/models.dart'; import '../../../shared/ui/colors.dart'; import '../../../shared/utils/screen_factor.dart'; diff --git a/lib/src/features/conversation/widgets/focused_popup_menu.dart b/sama_chat_client/lib/src/features/conversation/widgets/focused_popup_menu.dart similarity index 100% rename from lib/src/features/conversation/widgets/focused_popup_menu.dart rename to sama_chat_client/lib/src/features/conversation/widgets/focused_popup_menu.dart diff --git a/lib/src/features/conversation/widgets/forward_messages/forward_bubble.dart b/sama_chat_client/lib/src/features/conversation/widgets/forward_messages/forward_bubble.dart similarity index 100% rename from lib/src/features/conversation/widgets/forward_messages/forward_bubble.dart rename to sama_chat_client/lib/src/features/conversation/widgets/forward_messages/forward_bubble.dart diff --git a/lib/src/features/conversation/widgets/forward_messages/forward_messages_widget.dart b/sama_chat_client/lib/src/features/conversation/widgets/forward_messages/forward_messages_widget.dart similarity index 100% rename from lib/src/features/conversation/widgets/forward_messages/forward_messages_widget.dart rename to sama_chat_client/lib/src/features/conversation/widgets/forward_messages/forward_messages_widget.dart diff --git a/lib/src/features/conversation/widgets/forward_messages/forward_search_form.dart b/sama_chat_client/lib/src/features/conversation/widgets/forward_messages/forward_search_form.dart similarity index 100% rename from lib/src/features/conversation/widgets/forward_messages/forward_search_form.dart rename to sama_chat_client/lib/src/features/conversation/widgets/forward_messages/forward_search_form.dart diff --git a/lib/src/features/conversation/widgets/header_input_box.dart b/sama_chat_client/lib/src/features/conversation/widgets/header_input_box.dart similarity index 100% rename from lib/src/features/conversation/widgets/header_input_box.dart rename to sama_chat_client/lib/src/features/conversation/widgets/header_input_box.dart diff --git a/lib/src/features/conversation/widgets/media_attachment.dart b/sama_chat_client/lib/src/features/conversation/widgets/media_attachment.dart similarity index 100% rename from lib/src/features/conversation/widgets/media_attachment.dart rename to sama_chat_client/lib/src/features/conversation/widgets/media_attachment.dart diff --git a/lib/src/features/conversation/widgets/media_attachment_widget.dart b/sama_chat_client/lib/src/features/conversation/widgets/media_attachment_widget.dart similarity index 100% rename from lib/src/features/conversation/widgets/media_attachment_widget.dart rename to sama_chat_client/lib/src/features/conversation/widgets/media_attachment_widget.dart diff --git a/lib/src/features/conversation/widgets/message_bubble.dart b/sama_chat_client/lib/src/features/conversation/widgets/message_bubble.dart similarity index 100% rename from lib/src/features/conversation/widgets/message_bubble.dart rename to sama_chat_client/lib/src/features/conversation/widgets/message_bubble.dart diff --git a/lib/src/features/conversation/widgets/message_edit_widget.dart b/sama_chat_client/lib/src/features/conversation/widgets/message_edit_widget.dart similarity index 100% rename from lib/src/features/conversation/widgets/message_edit_widget.dart rename to sama_chat_client/lib/src/features/conversation/widgets/message_edit_widget.dart diff --git a/lib/src/features/conversation/widgets/message_status_widget.dart b/sama_chat_client/lib/src/features/conversation/widgets/message_status_widget.dart similarity index 100% rename from lib/src/features/conversation/widgets/message_status_widget.dart rename to sama_chat_client/lib/src/features/conversation/widgets/message_status_widget.dart diff --git a/lib/src/features/conversation/widgets/reply_bubble.dart b/sama_chat_client/lib/src/features/conversation/widgets/reply_bubble.dart similarity index 100% rename from lib/src/features/conversation/widgets/reply_bubble.dart rename to sama_chat_client/lib/src/features/conversation/widgets/reply_bubble.dart diff --git a/lib/src/features/conversation/widgets/select_input.dart b/sama_chat_client/lib/src/features/conversation/widgets/select_input.dart similarity index 98% rename from lib/src/features/conversation/widgets/select_input.dart rename to sama_chat_client/lib/src/features/conversation/widgets/select_input.dart index 5c945fc2..b668bf89 100644 --- a/lib/src/features/conversation/widgets/select_input.dart +++ b/sama_chat_client/lib/src/features/conversation/widgets/select_input.dart @@ -1,10 +1,10 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:sama_sdk/api/api.dart'; +import 'package:sama_sdk/api/settings.dart'; -import '../../../api/api.dart'; import '../../../shared/connection/view/connection_checker.dart'; import '../../../shared/ui/colors.dart'; -import '../../../shared/utils/api_utils.dart'; import '../bloc/conversation_bloc.dart'; import '../bloc/delete_messages/delete_messages_bloc.dart'; import 'forward_messages/forward_messages_widget.dart'; @@ -109,7 +109,7 @@ class _SelectInputState extends State { color: dullGray, ), Text( - '${state.selectedMessages.value.length} of $maxChatsSelected selected', + '${state.selectedMessages.value.length} of $maxChatsToSelect selected', style: const TextStyle(fontSize: 15)), IconButton( icon: const Icon(Icons.forward_outlined), diff --git a/lib/src/features/conversation/widgets/service_message_bubble.dart b/sama_chat_client/lib/src/features/conversation/widgets/service_message_bubble.dart similarity index 100% rename from lib/src/features/conversation/widgets/service_message_bubble.dart rename to sama_chat_client/lib/src/features/conversation/widgets/service_message_bubble.dart diff --git a/lib/src/features/conversation/widgets/text_message.dart b/sama_chat_client/lib/src/features/conversation/widgets/text_message.dart similarity index 100% rename from lib/src/features/conversation/widgets/text_message.dart rename to sama_chat_client/lib/src/features/conversation/widgets/text_message.dart diff --git a/lib/src/features/conversation/widgets/text_message_item.dart b/sama_chat_client/lib/src/features/conversation/widgets/text_message_item.dart similarity index 100% rename from lib/src/features/conversation/widgets/text_message_item.dart rename to sama_chat_client/lib/src/features/conversation/widgets/text_message_item.dart diff --git a/lib/src/features/conversation/widgets/unsupported_message.dart b/sama_chat_client/lib/src/features/conversation/widgets/unsupported_message.dart similarity index 100% rename from lib/src/features/conversation/widgets/unsupported_message.dart rename to sama_chat_client/lib/src/features/conversation/widgets/unsupported_message.dart diff --git a/lib/src/features/conversation_create/bloc/conversation_create_bloc.dart b/sama_chat_client/lib/src/features/conversation_create/bloc/conversation_create_bloc.dart similarity index 100% rename from lib/src/features/conversation_create/bloc/conversation_create_bloc.dart rename to sama_chat_client/lib/src/features/conversation_create/bloc/conversation_create_bloc.dart diff --git a/lib/src/features/conversation_create/bloc/conversation_create_event.dart b/sama_chat_client/lib/src/features/conversation_create/bloc/conversation_create_event.dart similarity index 100% rename from lib/src/features/conversation_create/bloc/conversation_create_event.dart rename to sama_chat_client/lib/src/features/conversation_create/bloc/conversation_create_event.dart diff --git a/lib/src/features/conversation_create/bloc/conversation_create_state.dart b/sama_chat_client/lib/src/features/conversation_create/bloc/conversation_create_state.dart similarity index 100% rename from lib/src/features/conversation_create/bloc/conversation_create_state.dart rename to sama_chat_client/lib/src/features/conversation_create/bloc/conversation_create_state.dart diff --git a/lib/src/features/conversation_group_create/bloc/group_bloc.dart b/sama_chat_client/lib/src/features/conversation_group_create/bloc/group_bloc.dart similarity index 100% rename from lib/src/features/conversation_group_create/bloc/group_bloc.dart rename to sama_chat_client/lib/src/features/conversation_group_create/bloc/group_bloc.dart diff --git a/lib/src/features/conversation_group_create/bloc/group_event.dart b/sama_chat_client/lib/src/features/conversation_group_create/bloc/group_event.dart similarity index 100% rename from lib/src/features/conversation_group_create/bloc/group_event.dart rename to sama_chat_client/lib/src/features/conversation_group_create/bloc/group_event.dart diff --git a/lib/src/features/conversation_group_create/bloc/group_state.dart b/sama_chat_client/lib/src/features/conversation_group_create/bloc/group_state.dart similarity index 100% rename from lib/src/features/conversation_group_create/bloc/group_state.dart rename to sama_chat_client/lib/src/features/conversation_group_create/bloc/group_state.dart diff --git a/lib/src/features/conversation_group_create/models/avatar.dart b/sama_chat_client/lib/src/features/conversation_group_create/models/avatar.dart similarity index 100% rename from lib/src/features/conversation_group_create/models/avatar.dart rename to sama_chat_client/lib/src/features/conversation_group_create/models/avatar.dart diff --git a/lib/src/features/conversation_group_create/models/groupname.dart b/sama_chat_client/lib/src/features/conversation_group_create/models/groupname.dart similarity index 100% rename from lib/src/features/conversation_group_create/models/groupname.dart rename to sama_chat_client/lib/src/features/conversation_group_create/models/groupname.dart diff --git a/lib/src/features/conversation_group_create/models/participants.dart b/sama_chat_client/lib/src/features/conversation_group_create/models/participants.dart similarity index 100% rename from lib/src/features/conversation_group_create/models/participants.dart rename to sama_chat_client/lib/src/features/conversation_group_create/models/participants.dart diff --git a/lib/src/features/conversation_group_create/view/group_create_form.dart b/sama_chat_client/lib/src/features/conversation_group_create/view/group_create_form.dart similarity index 100% rename from lib/src/features/conversation_group_create/view/group_create_form.dart rename to sama_chat_client/lib/src/features/conversation_group_create/view/group_create_form.dart diff --git a/lib/src/features/conversation_group_create/view/group_create_page.dart b/sama_chat_client/lib/src/features/conversation_group_create/view/group_create_page.dart similarity index 100% rename from lib/src/features/conversation_group_create/view/group_create_page.dart rename to sama_chat_client/lib/src/features/conversation_group_create/view/group_create_page.dart diff --git a/lib/src/features/conversations_list/bloc/conversations_list_bloc.dart b/sama_chat_client/lib/src/features/conversations_list/bloc/conversations_list_bloc.dart similarity index 98% rename from lib/src/features/conversations_list/bloc/conversations_list_bloc.dart rename to sama_chat_client/lib/src/features/conversations_list/bloc/conversations_list_bloc.dart index 93685338..ce95b566 100644 --- a/lib/src/features/conversations_list/bloc/conversations_list_bloc.dart +++ b/sama_chat_client/lib/src/features/conversations_list/bloc/conversations_list_bloc.dart @@ -4,9 +4,8 @@ import 'package:bloc/bloc.dart'; import 'package:bloc_concurrency/bloc_concurrency.dart'; import 'package:equatable/equatable.dart'; import 'package:stream_transform/stream_transform.dart'; +import 'package:sama_sdk/api/api.dart'; -import '../../../api/api.dart'; -import '../../../db/models/conversation_model.dart'; import '../../../db/models/models.dart'; import '../../../db/resource.dart'; import '../../../repository/conversation/conversation_repository.dart'; diff --git a/lib/src/features/conversations_list/bloc/conversations_list_event.dart b/sama_chat_client/lib/src/features/conversations_list/bloc/conversations_list_event.dart similarity index 100% rename from lib/src/features/conversations_list/bloc/conversations_list_event.dart rename to sama_chat_client/lib/src/features/conversations_list/bloc/conversations_list_event.dart diff --git a/lib/src/features/conversations_list/bloc/conversations_list_state.dart b/sama_chat_client/lib/src/features/conversations_list/bloc/conversations_list_state.dart similarity index 100% rename from lib/src/features/conversations_list/bloc/conversations_list_state.dart rename to sama_chat_client/lib/src/features/conversations_list/bloc/conversations_list_state.dart diff --git a/lib/src/features/conversations_list/conversations_list.dart b/sama_chat_client/lib/src/features/conversations_list/conversations_list.dart similarity index 60% rename from lib/src/features/conversations_list/conversations_list.dart rename to sama_chat_client/lib/src/features/conversations_list/conversations_list.dart index 1bfee8e3..e01947e1 100644 --- a/lib/src/features/conversations_list/conversations_list.dart +++ b/sama_chat_client/lib/src/features/conversations_list/conversations_list.dart @@ -1,4 +1,4 @@ export 'bloc/conversations_list_bloc.dart'; -export '../../api/conversations/models/models.dart'; +export 'package:sama_sdk/api/conversations/models/models.dart'; export 'view/view.dart'; export 'widgets/widgets.dart'; diff --git a/lib/src/features/conversations_list/view/conversations_list.dart b/sama_chat_client/lib/src/features/conversations_list/view/conversations_list.dart similarity index 100% rename from lib/src/features/conversations_list/view/conversations_list.dart rename to sama_chat_client/lib/src/features/conversations_list/view/conversations_list.dart diff --git a/lib/src/features/conversations_list/view/conversations_page.dart b/sama_chat_client/lib/src/features/conversations_list/view/conversations_page.dart similarity index 100% rename from lib/src/features/conversations_list/view/conversations_page.dart rename to sama_chat_client/lib/src/features/conversations_list/view/conversations_page.dart diff --git a/lib/src/features/conversations_list/view/view.dart b/sama_chat_client/lib/src/features/conversations_list/view/view.dart similarity index 100% rename from lib/src/features/conversations_list/view/view.dart rename to sama_chat_client/lib/src/features/conversations_list/view/view.dart diff --git a/lib/src/features/conversations_list/widgets/avatar_group_icon.dart b/sama_chat_client/lib/src/features/conversations_list/widgets/avatar_group_icon.dart similarity index 100% rename from lib/src/features/conversations_list/widgets/avatar_group_icon.dart rename to sama_chat_client/lib/src/features/conversations_list/widgets/avatar_group_icon.dart diff --git a/lib/src/features/conversations_list/widgets/avatar_letter_icon.dart b/sama_chat_client/lib/src/features/conversations_list/widgets/avatar_letter_icon.dart similarity index 100% rename from lib/src/features/conversations_list/widgets/avatar_letter_icon.dart rename to sama_chat_client/lib/src/features/conversations_list/widgets/avatar_letter_icon.dart diff --git a/lib/src/features/conversations_list/widgets/conversation_list_item.dart b/sama_chat_client/lib/src/features/conversations_list/widgets/conversation_list_item.dart similarity index 99% rename from lib/src/features/conversations_list/widgets/conversation_list_item.dart rename to sama_chat_client/lib/src/features/conversations_list/widgets/conversation_list_item.dart index 0bf2de33..4a83b3e4 100644 --- a/lib/src/features/conversations_list/widgets/conversation_list_item.dart +++ b/sama_chat_client/lib/src/features/conversations_list/widgets/conversation_list_item.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_blurhash/flutter_blurhash.dart'; import 'package:go_router/go_router.dart'; +import 'package:sama_sdk/api/api.dart'; -import '../../../api/api.dart'; import '../../../db/models/conversation_model.dart'; import '../../../features/conversations_list/widgets/avatar_group_icon.dart'; import '../../../navigation/constants.dart'; diff --git a/lib/src/features/conversations_list/widgets/widgets.dart b/sama_chat_client/lib/src/features/conversations_list/widgets/widgets.dart similarity index 100% rename from lib/src/features/conversations_list/widgets/widgets.dart rename to sama_chat_client/lib/src/features/conversations_list/widgets/widgets.dart diff --git a/lib/src/features/group_info/bloc/group_info_bloc.dart b/sama_chat_client/lib/src/features/group_info/bloc/group_info_bloc.dart similarity index 99% rename from lib/src/features/group_info/bloc/group_info_bloc.dart rename to sama_chat_client/lib/src/features/group_info/bloc/group_info_bloc.dart index 7dec98ad..4e11171b 100644 --- a/lib/src/features/group_info/bloc/group_info_bloc.dart +++ b/sama_chat_client/lib/src/features/group_info/bloc/group_info_bloc.dart @@ -4,8 +4,8 @@ import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:file_picker/file_picker.dart'; import 'package:formz/formz.dart'; +import 'package:sama_sdk/api/api.dart'; -import '../../../api/api.dart'; import '../../../db/models/models.dart'; import '../../../repository/conversation/conversation_repository.dart'; import '../../../repository/user/user_repository.dart'; diff --git a/lib/src/features/group_info/bloc/group_info_event.dart b/sama_chat_client/lib/src/features/group_info/bloc/group_info_event.dart similarity index 100% rename from lib/src/features/group_info/bloc/group_info_event.dart rename to sama_chat_client/lib/src/features/group_info/bloc/group_info_event.dart diff --git a/lib/src/features/group_info/bloc/group_info_state.dart b/sama_chat_client/lib/src/features/group_info/bloc/group_info_state.dart similarity index 100% rename from lib/src/features/group_info/bloc/group_info_state.dart rename to sama_chat_client/lib/src/features/group_info/bloc/group_info_state.dart diff --git a/lib/src/features/group_info/models/group_avatar.dart b/sama_chat_client/lib/src/features/group_info/models/group_avatar.dart similarity index 100% rename from lib/src/features/group_info/models/group_avatar.dart rename to sama_chat_client/lib/src/features/group_info/models/group_avatar.dart diff --git a/lib/src/features/group_info/models/group_description.dart b/sama_chat_client/lib/src/features/group_info/models/group_description.dart similarity index 100% rename from lib/src/features/group_info/models/group_description.dart rename to sama_chat_client/lib/src/features/group_info/models/group_description.dart diff --git a/lib/src/features/group_info/models/group_name.dart b/sama_chat_client/lib/src/features/group_info/models/group_name.dart similarity index 100% rename from lib/src/features/group_info/models/group_name.dart rename to sama_chat_client/lib/src/features/group_info/models/group_name.dart diff --git a/lib/src/features/group_info/models/group_participants.dart b/sama_chat_client/lib/src/features/group_info/models/group_participants.dart similarity index 100% rename from lib/src/features/group_info/models/group_participants.dart rename to sama_chat_client/lib/src/features/group_info/models/group_participants.dart diff --git a/lib/src/features/group_info/models/models.dart b/sama_chat_client/lib/src/features/group_info/models/models.dart similarity index 100% rename from lib/src/features/group_info/models/models.dart rename to sama_chat_client/lib/src/features/group_info/models/models.dart diff --git a/lib/src/features/group_info/view/group_info_form.dart b/sama_chat_client/lib/src/features/group_info/view/group_info_form.dart similarity index 100% rename from lib/src/features/group_info/view/group_info_form.dart rename to sama_chat_client/lib/src/features/group_info/view/group_info_form.dart diff --git a/lib/src/features/group_info/view/group_info_page.dart b/sama_chat_client/lib/src/features/group_info/view/group_info_page.dart similarity index 100% rename from lib/src/features/group_info/view/group_info_page.dart rename to sama_chat_client/lib/src/features/group_info/view/group_info_page.dart diff --git a/lib/src/features/login/bloc/login_bloc.dart b/sama_chat_client/lib/src/features/login/bloc/login_bloc.dart similarity index 100% rename from lib/src/features/login/bloc/login_bloc.dart rename to sama_chat_client/lib/src/features/login/bloc/login_bloc.dart diff --git a/lib/src/features/login/bloc/login_event.dart b/sama_chat_client/lib/src/features/login/bloc/login_event.dart similarity index 100% rename from lib/src/features/login/bloc/login_event.dart rename to sama_chat_client/lib/src/features/login/bloc/login_event.dart diff --git a/lib/src/features/login/bloc/login_state.dart b/sama_chat_client/lib/src/features/login/bloc/login_state.dart similarity index 100% rename from lib/src/features/login/bloc/login_state.dart rename to sama_chat_client/lib/src/features/login/bloc/login_state.dart diff --git a/lib/src/features/login/models/models.dart b/sama_chat_client/lib/src/features/login/models/models.dart similarity index 100% rename from lib/src/features/login/models/models.dart rename to sama_chat_client/lib/src/features/login/models/models.dart diff --git a/lib/src/features/login/models/username.dart b/sama_chat_client/lib/src/features/login/models/username.dart similarity index 100% rename from lib/src/features/login/models/username.dart rename to sama_chat_client/lib/src/features/login/models/username.dart diff --git a/lib/src/features/login/view/login_form.dart b/sama_chat_client/lib/src/features/login/view/login_form.dart similarity index 100% rename from lib/src/features/login/view/login_form.dart rename to sama_chat_client/lib/src/features/login/view/login_form.dart diff --git a/lib/src/features/login/view/login_page.dart b/sama_chat_client/lib/src/features/login/view/login_page.dart similarity index 100% rename from lib/src/features/login/view/login_page.dart rename to sama_chat_client/lib/src/features/login/view/login_page.dart diff --git a/lib/src/features/profile/bloc/profile_bloc.dart b/sama_chat_client/lib/src/features/profile/bloc/profile_bloc.dart similarity index 99% rename from lib/src/features/profile/bloc/profile_bloc.dart rename to sama_chat_client/lib/src/features/profile/bloc/profile_bloc.dart index 934e22c8..dfae6562 100644 --- a/lib/src/features/profile/bloc/profile_bloc.dart +++ b/sama_chat_client/lib/src/features/profile/bloc/profile_bloc.dart @@ -5,7 +5,6 @@ import 'package:equatable/equatable.dart'; import 'package:file_picker/file_picker.dart'; import 'package:formz/formz.dart'; -import '../../../api/api.dart'; import '../../../db/models/models.dart'; import '../../../repository/user/user_repository.dart'; import '../models/models.dart'; diff --git a/lib/src/features/profile/bloc/profile_event.dart b/sama_chat_client/lib/src/features/profile/bloc/profile_event.dart similarity index 100% rename from lib/src/features/profile/bloc/profile_event.dart rename to sama_chat_client/lib/src/features/profile/bloc/profile_event.dart diff --git a/lib/src/features/profile/bloc/profile_state.dart b/sama_chat_client/lib/src/features/profile/bloc/profile_state.dart similarity index 100% rename from lib/src/features/profile/bloc/profile_state.dart rename to sama_chat_client/lib/src/features/profile/bloc/profile_state.dart diff --git a/lib/src/features/profile/models/models.dart b/sama_chat_client/lib/src/features/profile/models/models.dart similarity index 100% rename from lib/src/features/profile/models/models.dart rename to sama_chat_client/lib/src/features/profile/models/models.dart diff --git a/lib/src/features/profile/models/user_avatar.dart b/sama_chat_client/lib/src/features/profile/models/user_avatar.dart similarity index 100% rename from lib/src/features/profile/models/user_avatar.dart rename to sama_chat_client/lib/src/features/profile/models/user_avatar.dart diff --git a/lib/src/features/profile/models/user_email.dart b/sama_chat_client/lib/src/features/profile/models/user_email.dart similarity index 100% rename from lib/src/features/profile/models/user_email.dart rename to sama_chat_client/lib/src/features/profile/models/user_email.dart diff --git a/lib/src/features/profile/models/user_firstname.dart b/sama_chat_client/lib/src/features/profile/models/user_firstname.dart similarity index 100% rename from lib/src/features/profile/models/user_firstname.dart rename to sama_chat_client/lib/src/features/profile/models/user_firstname.dart diff --git a/lib/src/features/profile/models/user_lastname.dart b/sama_chat_client/lib/src/features/profile/models/user_lastname.dart similarity index 100% rename from lib/src/features/profile/models/user_lastname.dart rename to sama_chat_client/lib/src/features/profile/models/user_lastname.dart diff --git a/lib/src/features/profile/models/user_password.dart b/sama_chat_client/lib/src/features/profile/models/user_password.dart similarity index 100% rename from lib/src/features/profile/models/user_password.dart rename to sama_chat_client/lib/src/features/profile/models/user_password.dart diff --git a/lib/src/features/profile/models/user_phone.dart b/sama_chat_client/lib/src/features/profile/models/user_phone.dart similarity index 100% rename from lib/src/features/profile/models/user_phone.dart rename to sama_chat_client/lib/src/features/profile/models/user_phone.dart diff --git a/lib/src/features/profile/view/profile_form.dart b/sama_chat_client/lib/src/features/profile/view/profile_form.dart similarity index 100% rename from lib/src/features/profile/view/profile_form.dart rename to sama_chat_client/lib/src/features/profile/view/profile_form.dart diff --git a/lib/src/features/profile/view/profile_page.dart b/sama_chat_client/lib/src/features/profile/view/profile_page.dart similarity index 100% rename from lib/src/features/profile/view/profile_page.dart rename to sama_chat_client/lib/src/features/profile/view/profile_page.dart diff --git a/lib/src/features/reset_password/bloc/reset_password_bloc.dart b/sama_chat_client/lib/src/features/reset_password/bloc/reset_password_bloc.dart similarity index 100% rename from lib/src/features/reset_password/bloc/reset_password_bloc.dart rename to sama_chat_client/lib/src/features/reset_password/bloc/reset_password_bloc.dart diff --git a/lib/src/features/reset_password/bloc/reset_password_event.dart b/sama_chat_client/lib/src/features/reset_password/bloc/reset_password_event.dart similarity index 100% rename from lib/src/features/reset_password/bloc/reset_password_event.dart rename to sama_chat_client/lib/src/features/reset_password/bloc/reset_password_event.dart diff --git a/lib/src/features/reset_password/bloc/reset_password_state.dart b/sama_chat_client/lib/src/features/reset_password/bloc/reset_password_state.dart similarity index 100% rename from lib/src/features/reset_password/bloc/reset_password_state.dart rename to sama_chat_client/lib/src/features/reset_password/bloc/reset_password_state.dart diff --git a/lib/src/features/reset_password/bloc/timer_bloc/timer_bloc.dart b/sama_chat_client/lib/src/features/reset_password/bloc/timer_bloc/timer_bloc.dart similarity index 100% rename from lib/src/features/reset_password/bloc/timer_bloc/timer_bloc.dart rename to sama_chat_client/lib/src/features/reset_password/bloc/timer_bloc/timer_bloc.dart diff --git a/lib/src/features/reset_password/bloc/timer_bloc/timer_event.dart b/sama_chat_client/lib/src/features/reset_password/bloc/timer_bloc/timer_event.dart similarity index 100% rename from lib/src/features/reset_password/bloc/timer_bloc/timer_event.dart rename to sama_chat_client/lib/src/features/reset_password/bloc/timer_bloc/timer_event.dart diff --git a/lib/src/features/reset_password/bloc/timer_bloc/timer_state.dart b/sama_chat_client/lib/src/features/reset_password/bloc/timer_bloc/timer_state.dart similarity index 100% rename from lib/src/features/reset_password/bloc/timer_bloc/timer_state.dart rename to sama_chat_client/lib/src/features/reset_password/bloc/timer_bloc/timer_state.dart diff --git a/lib/src/features/reset_password/models/confirm_password.dart b/sama_chat_client/lib/src/features/reset_password/models/confirm_password.dart similarity index 100% rename from lib/src/features/reset_password/models/confirm_password.dart rename to sama_chat_client/lib/src/features/reset_password/models/confirm_password.dart diff --git a/lib/src/features/reset_password/models/models.dart b/sama_chat_client/lib/src/features/reset_password/models/models.dart similarity index 100% rename from lib/src/features/reset_password/models/models.dart rename to sama_chat_client/lib/src/features/reset_password/models/models.dart diff --git a/lib/src/features/reset_password/models/otp.dart b/sama_chat_client/lib/src/features/reset_password/models/otp.dart similarity index 100% rename from lib/src/features/reset_password/models/otp.dart rename to sama_chat_client/lib/src/features/reset_password/models/otp.dart diff --git a/lib/src/features/reset_password/ticker.dart b/sama_chat_client/lib/src/features/reset_password/ticker.dart similarity index 100% rename from lib/src/features/reset_password/ticker.dart rename to sama_chat_client/lib/src/features/reset_password/ticker.dart diff --git a/lib/src/features/reset_password/view/reset_password_page.dart b/sama_chat_client/lib/src/features/reset_password/view/reset_password_page.dart similarity index 100% rename from lib/src/features/reset_password/view/reset_password_page.dart rename to sama_chat_client/lib/src/features/reset_password/view/reset_password_page.dart diff --git a/lib/src/features/reset_password/view/send_email_form.dart b/sama_chat_client/lib/src/features/reset_password/view/send_email_form.dart similarity index 100% rename from lib/src/features/reset_password/view/send_email_form.dart rename to sama_chat_client/lib/src/features/reset_password/view/send_email_form.dart diff --git a/lib/src/features/reset_password/view/send_otp_form.dart b/sama_chat_client/lib/src/features/reset_password/view/send_otp_form.dart similarity index 100% rename from lib/src/features/reset_password/view/send_otp_form.dart rename to sama_chat_client/lib/src/features/reset_password/view/send_otp_form.dart diff --git a/lib/src/features/reset_password/view/send_reset_password_form.dart b/sama_chat_client/lib/src/features/reset_password/view/send_reset_password_form.dart similarity index 100% rename from lib/src/features/reset_password/view/send_reset_password_form.dart rename to sama_chat_client/lib/src/features/reset_password/view/send_reset_password_form.dart diff --git a/lib/src/features/search/bloc/global_search_bloc.dart b/sama_chat_client/lib/src/features/search/bloc/global_search_bloc.dart similarity index 100% rename from lib/src/features/search/bloc/global_search_bloc.dart rename to sama_chat_client/lib/src/features/search/bloc/global_search_bloc.dart diff --git a/lib/src/features/search/bloc/global_search_event.dart b/sama_chat_client/lib/src/features/search/bloc/global_search_event.dart similarity index 100% rename from lib/src/features/search/bloc/global_search_event.dart rename to sama_chat_client/lib/src/features/search/bloc/global_search_event.dart diff --git a/lib/src/features/search/bloc/global_search_state.dart b/sama_chat_client/lib/src/features/search/bloc/global_search_state.dart similarity index 100% rename from lib/src/features/search/bloc/global_search_state.dart rename to sama_chat_client/lib/src/features/search/bloc/global_search_state.dart diff --git a/lib/src/features/search/models/models.dart b/sama_chat_client/lib/src/features/search/models/models.dart similarity index 100% rename from lib/src/features/search/models/models.dart rename to sama_chat_client/lib/src/features/search/models/models.dart diff --git a/lib/src/features/search/models/search_result.dart b/sama_chat_client/lib/src/features/search/models/search_result.dart similarity index 100% rename from lib/src/features/search/models/search_result.dart rename to sama_chat_client/lib/src/features/search/models/search_result.dart diff --git a/lib/src/features/search/models/search_result_error.dart b/sama_chat_client/lib/src/features/search/models/search_result_error.dart similarity index 100% rename from lib/src/features/search/models/search_result_error.dart rename to sama_chat_client/lib/src/features/search/models/search_result_error.dart diff --git a/lib/src/features/search/view/search_bar.dart b/sama_chat_client/lib/src/features/search/view/search_bar.dart similarity index 100% rename from lib/src/features/search/view/search_bar.dart rename to sama_chat_client/lib/src/features/search/view/search_bar.dart diff --git a/lib/src/features/search/view/search_form.dart b/sama_chat_client/lib/src/features/search/view/search_form.dart similarity index 100% rename from lib/src/features/search/view/search_form.dart rename to sama_chat_client/lib/src/features/search/view/search_form.dart diff --git a/lib/src/features/search/view/search_page.dart b/sama_chat_client/lib/src/features/search/view/search_page.dart similarity index 100% rename from lib/src/features/search/view/search_page.dart rename to sama_chat_client/lib/src/features/search/view/search_page.dart diff --git a/lib/src/features/splash_page.dart b/sama_chat_client/lib/src/features/splash_page.dart similarity index 100% rename from lib/src/features/splash_page.dart rename to sama_chat_client/lib/src/features/splash_page.dart diff --git a/lib/src/features/user_info/view/user_info_form.dart b/sama_chat_client/lib/src/features/user_info/view/user_info_form.dart similarity index 100% rename from lib/src/features/user_info/view/user_info_form.dart rename to sama_chat_client/lib/src/features/user_info/view/user_info_form.dart diff --git a/lib/src/features/user_info/view/user_info_page.dart b/sama_chat_client/lib/src/features/user_info/view/user_info_page.dart similarity index 97% rename from lib/src/features/user_info/view/user_info_page.dart rename to sama_chat_client/lib/src/features/user_info/view/user_info_page.dart index dc5336f6..c00355dd 100644 --- a/lib/src/features/user_info/view/user_info_page.dart +++ b/sama_chat_client/lib/src/features/user_info/view/user_info_page.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import '../../../api/api.dart'; import '../../../db/models/user_model.dart'; import '../../../features/user_info/view/user_info_form.dart'; import '../../../repository/conversation/conversation_repository.dart'; diff --git a/lib/src/navigation/app_router.dart b/sama_chat_client/lib/src/navigation/app_router.dart similarity index 100% rename from lib/src/navigation/app_router.dart rename to sama_chat_client/lib/src/navigation/app_router.dart diff --git a/lib/src/navigation/constants.dart b/sama_chat_client/lib/src/navigation/constants.dart similarity index 100% rename from lib/src/navigation/constants.dart rename to sama_chat_client/lib/src/navigation/constants.dart diff --git a/lib/src/repository/attachments/attachments_repository.dart b/sama_chat_client/lib/src/repository/attachments/attachments_repository.dart similarity index 91% rename from lib/src/repository/attachments/attachments_repository.dart rename to sama_chat_client/lib/src/repository/attachments/attachments_repository.dart index 1c0fb360..1293d2bc 100644 --- a/lib/src/repository/attachments/attachments_repository.dart +++ b/sama_chat_client/lib/src/repository/attachments/attachments_repository.dart @@ -1,4 +1,5 @@ -import '../../api/api.dart' as api; +import 'package:sama_sdk/api/api.dart' as api; + import '../../db/local/attachment_local_datasource.dart'; import '../../db/models/attachment_model.dart'; diff --git a/lib/src/repository/authentication/authentication_repository.dart b/sama_chat_client/lib/src/repository/authentication/authentication_repository.dart similarity index 61% rename from lib/src/repository/authentication/authentication_repository.dart rename to sama_chat_client/lib/src/repository/authentication/authentication_repository.dart index d4b29b3f..50462039 100644 --- a/lib/src/repository/authentication/authentication_repository.dart +++ b/sama_chat_client/lib/src/repository/authentication/authentication_repository.dart @@ -1,9 +1,12 @@ import 'dart:async'; import 'package:app_set_id/app_set_id.dart'; +import 'package:sama_sdk/api/api.dart'; +import 'package:sama_sdk/api/api.dart' as api; +import 'package:sama_sdk/api/connection/managers/connection_manager.dart'; -import '../../api/api.dart' as api; -import '../../api/api.dart'; import '../../db/db_service.dart'; +import '../../db/models/models.dart'; +import '../../shared/push_notifications/push_notifications_manager.dart'; import '../../shared/secure_storage.dart'; import '../user/user_repository.dart'; @@ -18,7 +21,9 @@ class AuthenticationRepository { final _controller = StreamController.broadcast(); final UserRepository userRepository; - AuthenticationRepository(this.userRepository); + AuthenticationRepository(this.userRepository) { + initListeners(); + } Stream get status async* { //TODO RP not clear why this delay is needed, commented for now @@ -29,6 +34,27 @@ class AuthenticationRepository { yield* _controller.stream; } + StreamSubscription? reconnectionStream; + StreamSubscription? connectionManagerStream; + + void initListeners() { + if (reconnectionStream != null) return; + + reconnectionStream = ReconnectionManager.instance.reconnectionStateStream + .listen((state) async { + if (state == ReconnectionState.tokenExpired) { + await logOut(); + _controller.add(AuthenticationStatus.unauthenticated); + } + }); + + connectionManagerStream = ConnectionManager.instance.connectionManagerStream + .listen((tokens) async { + SecureStorage.instance.saveAccessToken(tokens.accessToken); + SecureStorage.instance.saveRefreshToken(tokens.refreshToken); + }); + } + Future login({ required String username, String? password, @@ -39,9 +65,15 @@ class AuthenticationRepository { login: username, password: password, deviceId: deviceId ?? await AppSetId().getIdentifier()); - var (accessToken, loggedUser) = await api.loginHttp(user); - await loginWithAccessToken(accessToken); - await userRepository.updateUserLocal(loggedUser); + var (accessToken, refreshToken, loggedUser) = await api.loginHttp(user); + var loggedUserModel = loggedUser.toUserModel(); + + SecureStorage.instance.saveAccessToken(accessToken); + SecureStorage.instance.saveRefreshToken(refreshToken); + SecureStorage.instance.saveCurrentUserIfNeed(loggedUserModel); + + await loginWithAccessToken(accessToken, refreshToken); + await userRepository.updateUserLocal(loggedUserModel); return Future.value(null); } catch (e) { _controller.add(AuthenticationStatus.unauthenticated); @@ -50,13 +82,13 @@ class AuthenticationRepository { } } - Future loginWithAccessToken([AccessToken? accessToken]) async { + Future loginWithAccessToken( + AccessToken accessToken, RefreshToken refreshToken) async { ReconnectionManager.instance.init(); DatabaseService.instance.init(); try { - await api.loginWithToken(accessToken); - - api.PushNotificationsManager.instance.subscribe(); + await api.loginWithToken(accessToken, refreshToken); + PushNotificationsManager.instance.subscribe(); _controller.add(AuthenticationStatus.authenticated); return Future.value(null); } catch (e) { @@ -94,14 +126,14 @@ class AuthenticationRepository { } Future logOut() async { - await api.PushNotificationsManager.instance.unsubscribe(); + await PushNotificationsManager.instance.unsubscribe(); await api.logout().whenComplete(() { disposeCurrentUser(); }); } Future signOut() async { - await api.PushNotificationsManager.instance.unsubscribe(); + await PushNotificationsManager.instance.unsubscribe(); await api.signOut().then((success) { disposeCurrentUser(); }); @@ -128,11 +160,17 @@ class AuthenticationRepository { disposeCurrentUser() async { await SecureStorage.instance.deleteCurrentUser(); - api.ReconnectionManager.instance.destroy(); + ReconnectionManager.instance.destroy(); api.SamaConnectionService.instance.closeConnection(); DatabaseService.instance.drop(); _controller.add(AuthenticationStatus.unauthenticated); } - void dispose() => _controller.close(); + void dispose() { + reconnectionStream?.cancel(); + reconnectionStream = null; + connectionManagerStream?.cancel(); + connectionManagerStream = null; + _controller.close(); + } } diff --git a/lib/src/repository/conversation/conversation_repository.dart b/sama_chat_client/lib/src/repository/conversation/conversation_repository.dart similarity index 93% rename from lib/src/repository/conversation/conversation_repository.dart rename to sama_chat_client/lib/src/repository/conversation/conversation_repository.dart index 6a3b810a..8fb9ac37 100644 --- a/lib/src/repository/conversation/conversation_repository.dart +++ b/sama_chat_client/lib/src/repository/conversation/conversation_repository.dart @@ -5,14 +5,15 @@ import 'dart:async'; import 'dart:io'; import 'package:path/path.dart'; +import 'package:sama_sdk/api/api.dart' as api; +import 'package:sama_sdk/api/api.dart'; +import 'package:sama_sdk/api/push_notifications/models/models.dart'; -import '../../api/api.dart' as api; -import '../../api/api.dart'; -import '../../api/push_notifications/models/models.dart'; import '../../db/models/models.dart'; import '../../db/network_bound_resource.dart'; import '../../db/resource.dart'; import '../../features/conversation/models/chat_message.dart'; +import '../../shared/push_notifications/push_notifications_manager.dart'; import '../../repository/messages/messages_repository.dart'; import '../../shared/utils/media_utils.dart'; import '../../shared/utils/string_utils.dart'; @@ -34,9 +35,9 @@ class ConversationRepository { initChatListeners(); } - StreamSubscription? incomingSystemMessagesSubscription; + StreamSubscription? incomingSystemMessagesSubscription; StreamSubscription? incomingMessagesSubscription; - StreamSubscription? statusMessagesSubscription; + StreamSubscription? statusMessagesSubscription; StreamSubscription? typingMessageSubscription; final StreamController _conversationsController = @@ -45,10 +46,10 @@ class ConversationRepository { Stream get updateConversationStream => _conversationsController.stream; - final StreamController _typingMessageController = + final StreamController _typingMessageController = StreamController.broadcast(); - Stream get typingMessageStream => + Stream get typingMessageStream => _typingMessageController.stream; bool _chatsFilter(ConversationModel c) => @@ -57,8 +58,8 @@ class ConversationRepository { void initChatListeners() { if (incomingSystemMessagesSubscription != null) return; - incomingSystemMessagesSubscription = api - .MessagesManager.instance.systemChatMessagesStream + incomingSystemMessagesSubscription = MessagesManager + .instance.systemChatMessagesStream .listen((message) async { var (participants, users) = await getParticipants([message.conversation!.id!]); @@ -94,7 +95,7 @@ class ConversationRepository { } _conversationsController.add(conversation); - api.showNotificationIfAppPaused(PushMessageData( + showNotificationIfAppPaused(PushMessageData( cid: conversation.id, title: conversation.name, body: getSystemMessagePushBody(conversation, message, opponent))); @@ -125,7 +126,7 @@ class ConversationRepository { await localDatasource.updateConversationLocal(updatedConversation); _conversationsController.add(updatedConversation); - api.showNotificationIfAppPaused(PushMessageData( + showNotificationIfAppPaused(PushMessageData( cid: updatedConversation.id, title: updatedConversation.name, body: updatedConversation.lastMessage?.body, @@ -158,8 +159,8 @@ class ConversationRepository { } }); - typingMessageSubscription = api.TypingManager.instance.typingStatusStream - .listen((typingStatus) async { + typingMessageSubscription = + TypingManager.instance.typingStatusStream.listen((typingStatus) async { _typingMessageController.add(typingStatus); }); } @@ -173,8 +174,8 @@ class ConversationRepository { statusMessagesSubscription = null; typingMessageSubscription?.cancel(); typingMessageSubscription = null; - api.MessagesManager.instance.destroy(); - api.TypingManager.instance.destroy(); + MessagesManager.instance.destroy(); + TypingManager.instance.destroy(); } Future resetUnreadMessagesCount(String conversationId) async { @@ -192,14 +193,14 @@ class ConversationRepository { Future<(Map>, List)> getParticipants( List cids) async { - var (participants, users) = await api.fetchParticipants(cids); + var (participants, users) = await fetchParticipants(cids); var usersModels = users.map((element) => element.toUserModel()).toList(); var usersLocal = await userRepository.saveUsersLocal(usersModels); return (participants, usersLocal); } Future> updateParticipants(String cid) async { - var (participants, users) = await api.fetchParticipants([cid]); + var (participants, users) = await fetchParticipants([cid]); var usersModels = users.map((element) => element.toUserModel()).toList(); var usersLocal = await userRepository.saveUsersLocal(usersModels); return usersLocal; @@ -247,7 +248,7 @@ class ConversationRepository { Future> _fetchConversationsWithParticipants( {DateTime? ltDate, int limit = 100}) async { - final conversations = await api.fetchConversations({ + final conversations = await fetchConversations({ if (ltDate != null) 'updated_at': { 'lt': ltDate.toUtc().toIso8601String(), @@ -320,7 +321,7 @@ class ConversationRepository { var compressedFile = await compressImageFile(avatarUrl, const Size(640, 480)); final blur = await getImageHashInIsolate(compressedFile); - final id = await api.uploadAvatarFile(compressedFile); + final id = await uploadAvatarFile(compressedFile); final name = basename(compressedFile.path); avatar = Avatar(fileId: id, fileName: name, fileBlurHash: blur); } @@ -363,7 +364,7 @@ class ConversationRepository { var compressedFile = await compressImageFile(avatarUrl, const Size(640, 480)); final blur = await getImageHashInIsolate(compressedFile); - final id = await api.uploadAvatarFile(compressedFile); + final id = await uploadAvatarFile(compressedFile); final name = basename(compressedFile.path); avatar = Avatar(fileId: id, fileName: name, fileBlurHash: blur); } diff --git a/lib/src/repository/global_search/global_search_repository.dart b/sama_chat_client/lib/src/repository/global_search/global_search_repository.dart similarity index 79% rename from lib/src/repository/global_search/global_search_repository.dart rename to sama_chat_client/lib/src/repository/global_search/global_search_repository.dart index 00f6582f..40407e06 100644 --- a/lib/src/repository/global_search/global_search_repository.dart +++ b/sama_chat_client/lib/src/repository/global_search/global_search_repository.dart @@ -1,7 +1,7 @@ -import '../../api/api.dart' as api; import 'dart:async'; -import '../../api/api.dart'; +import 'package:sama_sdk/api/api.dart'; + import '../../db/models/models.dart'; import '../../features/search/models/models.dart'; import '../conversation/conversation_repository.dart'; @@ -17,8 +17,8 @@ class GlobalSearchRepository { }); Future search(String term) async { - final List users = await api.searchUsersByKeyword(term); - final List ids = await api.searchConversationsIdsByName(term); + final List users = await searchUsersByKeyword(term); + final List ids = await searchConversationsIdsByName(term); final List conversations = await conversationRepository.getConversationsByIds(ids); final List userModels = await userRepository diff --git a/lib/src/repository/messages/messages_repository.dart b/sama_chat_client/lib/src/repository/messages/messages_repository.dart similarity index 99% rename from lib/src/repository/messages/messages_repository.dart rename to sama_chat_client/lib/src/repository/messages/messages_repository.dart index 555b50a2..c8aebae9 100644 --- a/lib/src/repository/messages/messages_repository.dart +++ b/sama_chat_client/lib/src/repository/messages/messages_repository.dart @@ -2,8 +2,8 @@ import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:uuid/uuid.dart'; +import 'package:sama_sdk/api/api.dart' as api; -import '../../api/api.dart' as api; import '../../db/local/message_local_datasource.dart'; import '../../db/models/models.dart'; import '../../db/network_bound_resource.dart'; diff --git a/lib/src/repository/user/user_repository.dart b/sama_chat_client/lib/src/repository/user/user_repository.dart similarity index 90% rename from lib/src/repository/user/user_repository.dart rename to sama_chat_client/lib/src/repository/user/user_repository.dart index b2469ca6..b5a80bd7 100644 --- a/lib/src/repository/user/user_repository.dart +++ b/sama_chat_client/lib/src/repository/user/user_repository.dart @@ -3,9 +3,9 @@ import 'dart:async'; import 'dart:io'; import 'package:path/path.dart'; +import 'package:sama_sdk/api/api.dart'; +import 'package:sama_sdk/api/api.dart' as api; -import '../../api/api.dart'; -import '../../api/api.dart' as api; import '../../db/local/user_local_datasource.dart'; import '../../db/models/models.dart'; import '../../shared/secure_storage.dart'; @@ -29,9 +29,8 @@ class UserRepository { void initListeners() { if (_lastActivitySubscription != null) return; - _lastActivitySubscription = api - .UsersManager.instance.lastActivityControllerStream - .listen((data) async { + _lastActivitySubscription = + UsersManager.instance.lastActivityControllerStream.listen((data) async { _lastActivityController.add(data); }); } @@ -66,7 +65,7 @@ class UserRepository { avatar: avatar); if (avatar != null) { - final filesUrls = await api.getFilesUrls({avatar.fileId!}); + final filesUrls = await getFilesUrls({avatar.fileId!}); avatar = avatar.copyWith(imageUrl: filesUrls[avatar.fileId!]); user = user.copyWith(avatar: avatar); } @@ -79,7 +78,7 @@ class UserRepository { var compressedFile = await compressImageFile(avatarUrl, const Size(640, 480)); final blur = await getImageHashInIsolate(compressedFile); - final id = await api.uploadAvatarFile(compressedFile); + final id = await uploadAvatarFile(compressedFile); final name = basename(compressedFile.path); Avatar avatar = Avatar(fileId: id, fileName: name, fileBlurHash: blur); @@ -103,7 +102,7 @@ class UserRepository { } Future> getUsersByCids(List cids) async { - return (await api.fetchParticipants(cids)) + return (await fetchParticipants(cids)) .$2 .map((element) => element.toUserModel()) .toList(); @@ -138,6 +137,6 @@ class UserRepository { void dispose() { _lastActivitySubscription?.cancel(); - api.UsersManager.instance.destroy(); + UsersManager.instance.destroy(); } } diff --git a/lib/src/shared/auth/bloc/auth_bloc.dart b/sama_chat_client/lib/src/shared/auth/bloc/auth_bloc.dart similarity index 87% rename from lib/src/shared/auth/bloc/auth_bloc.dart rename to sama_chat_client/lib/src/shared/auth/bloc/auth_bloc.dart index 1ff62bd1..55255a0f 100644 --- a/lib/src/shared/auth/bloc/auth_bloc.dart +++ b/sama_chat_client/lib/src/shared/auth/bloc/auth_bloc.dart @@ -2,9 +2,8 @@ import 'dart:async'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; +import 'package:sama_sdk/api/api.dart'; -import '../../../api/api.dart' as api; -import '../../../api/utils/logger.dart'; import '../../../db/models/models.dart'; import '../../../repository/authentication/authentication_repository.dart'; import '../../secure_storage.dart'; @@ -25,11 +24,11 @@ class AuthenticationBloc _authenticationStatusSubscription = _authenticationRepository.status.listen( (status) => add(_AuthenticationStatusChanged(status)), ); - _connectionStateSubscription = api - .SamaConnectionService.instance.connectionStateStream + _connectionStateSubscription = SamaConnectionService + .instance.connectionStateStream .listen((status) async { //fix to set authenticated when open app without network - if (status == api.ConnectionState.connected && + if (status == ConnectionState.connected && state.status == AuthenticationStatus.unauthenticated && await tryGetHasCurrentUser()) { tryAuthUser(); @@ -40,7 +39,7 @@ class AuthenticationBloc final AuthenticationRepository _authenticationRepository; late StreamSubscription _authenticationStatusSubscription; - late StreamSubscription _connectionStateSubscription; + late StreamSubscription _connectionStateSubscription; @override Future close() { @@ -100,7 +99,10 @@ class AuthenticationBloc Future tryAuthUser() async { try { - await _authenticationRepository.loginWithAccessToken(); + var accessToken = await SecureStorage.instance.getAccessToken(); + var refreshToken = await SecureStorage.instance.getRefreshToken(); + await _authenticationRepository.loginWithAccessToken( + accessToken!, refreshToken!); } catch (e) { log('tryAuthUser e= $e'); //TODO RP CHECK ME (use checking with code 422) diff --git a/lib/src/shared/auth/bloc/auth_event.dart b/sama_chat_client/lib/src/shared/auth/bloc/auth_event.dart similarity index 100% rename from lib/src/shared/auth/bloc/auth_event.dart rename to sama_chat_client/lib/src/shared/auth/bloc/auth_event.dart diff --git a/lib/src/shared/auth/bloc/auth_state.dart b/sama_chat_client/lib/src/shared/auth/bloc/auth_state.dart similarity index 100% rename from lib/src/shared/auth/bloc/auth_state.dart rename to sama_chat_client/lib/src/shared/auth/bloc/auth_state.dart diff --git a/lib/src/shared/connection/bloc/connection_bloc.dart b/sama_chat_client/lib/src/shared/connection/bloc/connection_bloc.dart similarity index 96% rename from lib/src/shared/connection/bloc/connection_bloc.dart rename to sama_chat_client/lib/src/shared/connection/bloc/connection_bloc.dart index 5ae2c10e..53b85b96 100644 --- a/lib/src/shared/connection/bloc/connection_bloc.dart +++ b/sama_chat_client/lib/src/shared/connection/bloc/connection_bloc.dart @@ -2,9 +2,9 @@ import 'dart:async'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; +import 'package:sama_sdk/api/api.dart'; +import 'package:sama_sdk/api/connection/connection.dart' as conn; -import '../../../api/api.dart'; -import '../../../api/connection/connection.dart' as conn; import '../../../repository/authentication/authentication_repository.dart'; part 'connection_event.dart'; diff --git a/lib/src/shared/connection/bloc/connection_event.dart b/sama_chat_client/lib/src/shared/connection/bloc/connection_event.dart similarity index 100% rename from lib/src/shared/connection/bloc/connection_event.dart rename to sama_chat_client/lib/src/shared/connection/bloc/connection_event.dart diff --git a/lib/src/shared/connection/bloc/connection_state.dart b/sama_chat_client/lib/src/shared/connection/bloc/connection_state.dart similarity index 100% rename from lib/src/shared/connection/bloc/connection_state.dart rename to sama_chat_client/lib/src/shared/connection/bloc/connection_state.dart diff --git a/lib/src/shared/connection/view/connection_checker.dart b/sama_chat_client/lib/src/shared/connection/view/connection_checker.dart similarity index 100% rename from lib/src/shared/connection/view/connection_checker.dart rename to sama_chat_client/lib/src/shared/connection/view/connection_checker.dart diff --git a/lib/src/shared/connection/view/connection_title.dart b/sama_chat_client/lib/src/shared/connection/view/connection_title.dart similarity index 100% rename from lib/src/shared/connection/view/connection_title.dart rename to sama_chat_client/lib/src/shared/connection/view/connection_title.dart diff --git a/lib/src/shared/errors/exceptions.dart b/sama_chat_client/lib/src/shared/errors/exceptions.dart similarity index 100% rename from lib/src/shared/errors/exceptions.dart rename to sama_chat_client/lib/src/shared/errors/exceptions.dart diff --git a/lib/src/shared/messages_collector/messages_collector.dart b/sama_chat_client/lib/src/shared/messages_collector/messages_collector.dart similarity index 95% rename from lib/src/shared/messages_collector/messages_collector.dart rename to sama_chat_client/lib/src/shared/messages_collector/messages_collector.dart index c141ffcd..4aeec805 100644 --- a/lib/src/shared/messages_collector/messages_collector.dart +++ b/sama_chat_client/lib/src/shared/messages_collector/messages_collector.dart @@ -1,11 +1,11 @@ import 'dart:async'; -import '../../api/api.dart'; +import 'package:sama_sdk/api/api.dart'; +import 'package:sama_sdk/api/connection/connection.dart' as conn; + import '../../repository/conversation/conversation_repository.dart'; import '../../repository/messages/messages_repository.dart'; -import '../../api/connection/connection.dart' as conn; - class MessagesCollector { MessagesCollector._(); diff --git a/lib/src/shared/models/email.dart b/sama_chat_client/lib/src/shared/models/email.dart similarity index 100% rename from lib/src/shared/models/email.dart rename to sama_chat_client/lib/src/shared/models/email.dart diff --git a/lib/src/shared/models/password.dart b/sama_chat_client/lib/src/shared/models/password.dart similarity index 100% rename from lib/src/shared/models/password.dart rename to sama_chat_client/lib/src/shared/models/password.dart diff --git a/lib/src/shared/push_notifications/bloc/push_notifications_bloc.dart b/sama_chat_client/lib/src/shared/push_notifications/bloc/push_notifications_bloc.dart similarity index 98% rename from lib/src/shared/push_notifications/bloc/push_notifications_bloc.dart rename to sama_chat_client/lib/src/shared/push_notifications/bloc/push_notifications_bloc.dart index 981fcb97..aad7a633 100644 --- a/lib/src/shared/push_notifications/bloc/push_notifications_bloc.dart +++ b/sama_chat_client/lib/src/shared/push_notifications/bloc/push_notifications_bloc.dart @@ -3,8 +3,8 @@ import 'dart:convert'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; -import '../../../api/api.dart'; import '../../../db/models/conversation_model.dart'; +import '../push_notifications_manager.dart'; import '../../../repository/conversation/conversation_repository.dart'; part 'push_notifications_event.dart'; diff --git a/lib/src/shared/push_notifications/bloc/push_notifications_event.dart b/sama_chat_client/lib/src/shared/push_notifications/bloc/push_notifications_event.dart similarity index 100% rename from lib/src/shared/push_notifications/bloc/push_notifications_event.dart rename to sama_chat_client/lib/src/shared/push_notifications/bloc/push_notifications_event.dart diff --git a/lib/src/shared/push_notifications/bloc/push_notifications_state.dart b/sama_chat_client/lib/src/shared/push_notifications/bloc/push_notifications_state.dart similarity index 100% rename from lib/src/shared/push_notifications/bloc/push_notifications_state.dart rename to sama_chat_client/lib/src/shared/push_notifications/bloc/push_notifications_state.dart diff --git a/lib/src/api/push_notifications/push_notifications_manager.dart b/sama_chat_client/lib/src/shared/push_notifications/push_notifications_manager.dart similarity index 91% rename from lib/src/api/push_notifications/push_notifications_manager.dart rename to sama_chat_client/lib/src/shared/push_notifications/push_notifications_manager.dart index 669ea08c..c69dae90 100644 --- a/lib/src/api/push_notifications/push_notifications_manager.dart +++ b/sama_chat_client/lib/src/shared/push_notifications/push_notifications_manager.dart @@ -4,14 +4,12 @@ import 'dart:io'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/material.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; +import 'package:sama_sdk/api/api.dart'; +import 'package:sama_sdk/api/push_notifications/models/models.dart'; -import '../../shared/utils/media_utils.dart'; -import '../../shared/secure_storage.dart'; -import '../../shared/ui/colors.dart'; -import '../api.dart'; -import '/src/api/push_notifications/push_notifications_api.dart'; -import 'models/models.dart'; -import 'models/push_message_data.dart'; +import '../utils/media_utils.dart'; +import '../secure_storage.dart'; +import '../ui/colors.dart'; const String channelId = 'sama_messages_channel_id'; const String channelName = 'Sama messages'; @@ -129,7 +127,8 @@ class PushNotificationsManager { ? 'ios' : ''; - String? deviceId = (await SecureStorage.instance.getCurrentUser())?.deviceId; + String? deviceId = + (await SecureStorage.instance.getCurrentUser())?.deviceId; if (deviceId == null) { print('[subscribe] skip subscription for unregistered user'); return; @@ -145,17 +144,21 @@ class PushNotificationsManager { } Future unsubscribe() { - return SecureStorage.instance.getCurrentUser().then((user) { - String? deviceId = user?.deviceId; - if (deviceId != null) { - return deleteSubscription(deviceId).whenComplete(() { - FirebaseMessaging.instance.deleteToken(); + return SecureStorage.instance + .getCurrentUser() + .then((user) { + String? deviceId = user?.deviceId; + if (deviceId != null) { + return deleteSubscription(deviceId).whenComplete(() { + FirebaseMessaging.instance.deleteToken(); + }); + } + return Future.value(); + }) + .timeout(logoutRequestTimeout) + .catchError((onError) { + print('[unsubscribe] ERROR: $onError'); }); - } - return Future.value(); - }).timeout(logoutRequestTimeout).catchError((onError) { - print('[unsubscribe] ERROR: $onError'); - }); } Future onDidReceiveLocalNotification( diff --git a/lib/src/shared/secure_storage.dart b/sama_chat_client/lib/src/shared/secure_storage.dart similarity index 88% rename from lib/src/shared/secure_storage.dart rename to sama_chat_client/lib/src/shared/secure_storage.dart index 5f32155b..61b82b66 100644 --- a/lib/src/shared/secure_storage.dart +++ b/sama_chat_client/lib/src/shared/secure_storage.dart @@ -1,8 +1,9 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:sama_sdk/api/api.dart'; +import 'package:sama_sdk/api/settings.dart'; import 'package:shared_preferences/shared_preferences.dart'; -import '../api/api.dart'; -import '../api/utils/config.dart'; +import '../features/config.dart'; import '../db/models/models.dart'; const String storageUserId = "storage_user_id"; @@ -126,12 +127,13 @@ class SecureStorage { return AccessToken(token: token, expiredAt: expiredAt); } - saveRefreshToken(String token) { - _storage.write(key: storageRefreshToken, value: token); + saveRefreshToken(RefreshToken token) { + _storage.write(key: storageRefreshToken, value: token.token); } - Future getRefreshToken() { - return _storage.read(key: storageRefreshToken); + Future getRefreshToken() async { + String? token = await _storage.read(key: storageRefreshToken); + return RefreshToken(token: token); } saveSubscriptionToken(String token) { @@ -142,10 +144,15 @@ class SecureStorage { return _storage.read(key: storageSubscriptionToken); } - saveEnvironmentType(EnvType type) { + Future saveEnvironmentType(EnvType type) async { _storage.write(key: storageEnvironmentType, value: type.name); } + Future updateSettings(EnvType type) async { + await saveEnvironmentType(type); + initSettings(); + } + Future getDevEnvironmentType() async { return EnvType.values .byName(await _storage.read(key: storageEnvironmentType) ?? 'dev'); @@ -160,6 +167,12 @@ class SecureStorage { } } +void initSettings() async { + final url = await SecureStorage.instance.getEnvironmentUrl(); + final orgId = await SecureStorage.instance.getEnvironmentOrgId(); + SamaSettings.instance.setEndpoints(url, orgId); +} + //fix to clear iOS data when uninstall app (can/should be removed when app is stable) void clearKeychainValuesIfUninstall() async { final prefs = await SharedPreferences.getInstance(); diff --git a/lib/src/shared/sharing/bloc/sharing_intent_bloc.dart b/sama_chat_client/lib/src/shared/sharing/bloc/sharing_intent_bloc.dart similarity index 100% rename from lib/src/shared/sharing/bloc/sharing_intent_bloc.dart rename to sama_chat_client/lib/src/shared/sharing/bloc/sharing_intent_bloc.dart diff --git a/lib/src/shared/sharing/bloc/sharing_intent_event.dart b/sama_chat_client/lib/src/shared/sharing/bloc/sharing_intent_event.dart similarity index 100% rename from lib/src/shared/sharing/bloc/sharing_intent_event.dart rename to sama_chat_client/lib/src/shared/sharing/bloc/sharing_intent_event.dart diff --git a/lib/src/shared/sharing/bloc/sharing_intent_state.dart b/sama_chat_client/lib/src/shared/sharing/bloc/sharing_intent_state.dart similarity index 100% rename from lib/src/shared/sharing/bloc/sharing_intent_state.dart rename to sama_chat_client/lib/src/shared/sharing/bloc/sharing_intent_state.dart diff --git a/lib/src/shared/ui/colors.dart b/sama_chat_client/lib/src/shared/ui/colors.dart similarity index 100% rename from lib/src/shared/ui/colors.dart rename to sama_chat_client/lib/src/shared/ui/colors.dart diff --git a/lib/src/shared/ui/view/loading_overlay.dart b/sama_chat_client/lib/src/shared/ui/view/loading_overlay.dart similarity index 100% rename from lib/src/shared/ui/view/loading_overlay.dart rename to sama_chat_client/lib/src/shared/ui/view/loading_overlay.dart diff --git a/lib/src/shared/ui/view/participants_forms.dart b/sama_chat_client/lib/src/shared/ui/view/participants_forms.dart similarity index 100% rename from lib/src/shared/ui/view/participants_forms.dart rename to sama_chat_client/lib/src/shared/ui/view/participants_forms.dart diff --git a/lib/src/shared/ui/view/user_forms.dart b/sama_chat_client/lib/src/shared/ui/view/user_forms.dart similarity index 100% rename from lib/src/shared/ui/view/user_forms.dart rename to sama_chat_client/lib/src/shared/ui/view/user_forms.dart diff --git a/sama_chat_client/lib/src/shared/utils/api_utils.dart b/sama_chat_client/lib/src/shared/utils/api_utils.dart new file mode 100644 index 00000000..e7bf3458 --- /dev/null +++ b/sama_chat_client/lib/src/shared/utils/api_utils.dart @@ -0,0 +1,3 @@ +import 'package:sama_sdk/api/settings.dart'; + +const int maxParticipantsCount = maxParticipants - 1; // minus current user diff --git a/lib/src/shared/utils/date_utils.dart b/sama_chat_client/lib/src/shared/utils/date_utils.dart similarity index 100% rename from lib/src/shared/utils/date_utils.dart rename to sama_chat_client/lib/src/shared/utils/date_utils.dart diff --git a/lib/src/shared/utils/file_utils.dart b/sama_chat_client/lib/src/shared/utils/file_utils.dart similarity index 100% rename from lib/src/shared/utils/file_utils.dart rename to sama_chat_client/lib/src/shared/utils/file_utils.dart diff --git a/lib/src/shared/utils/media_utils.dart b/sama_chat_client/lib/src/shared/utils/media_utils.dart similarity index 100% rename from lib/src/shared/utils/media_utils.dart rename to sama_chat_client/lib/src/shared/utils/media_utils.dart diff --git a/lib/src/shared/utils/observer_utils.dart b/sama_chat_client/lib/src/shared/utils/observer_utils.dart similarity index 100% rename from lib/src/shared/utils/observer_utils.dart rename to sama_chat_client/lib/src/shared/utils/observer_utils.dart diff --git a/lib/src/shared/utils/regexp_utils.dart b/sama_chat_client/lib/src/shared/utils/regexp_utils.dart similarity index 100% rename from lib/src/shared/utils/regexp_utils.dart rename to sama_chat_client/lib/src/shared/utils/regexp_utils.dart diff --git a/lib/src/shared/utils/screen_factor.dart b/sama_chat_client/lib/src/shared/utils/screen_factor.dart similarity index 100% rename from lib/src/shared/utils/screen_factor.dart rename to sama_chat_client/lib/src/shared/utils/screen_factor.dart diff --git a/lib/src/shared/utils/string_utils.dart b/sama_chat_client/lib/src/shared/utils/string_utils.dart similarity index 97% rename from lib/src/shared/utils/string_utils.dart rename to sama_chat_client/lib/src/shared/utils/string_utils.dart index 03d9a527..0de254bd 100644 --- a/lib/src/shared/utils/string_utils.dart +++ b/sama_chat_client/lib/src/shared/utils/string_utils.dart @@ -1,4 +1,5 @@ -import '../../api/api.dart'; +import 'package:sama_sdk/api/api.dart'; + import '../../db/models/models.dart'; String getUserName(UserModel? user) { diff --git a/lib/src/shared/widget/env_dialog_widget.dart b/sama_chat_client/lib/src/shared/widget/env_dialog_widget.dart similarity index 97% rename from lib/src/shared/widget/env_dialog_widget.dart rename to sama_chat_client/lib/src/shared/widget/env_dialog_widget.dart index b5c9ed69..163cace0 100644 --- a/lib/src/shared/widget/env_dialog_widget.dart +++ b/sama_chat_client/lib/src/shared/widget/env_dialog_widget.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import '../../api/utils/config.dart'; +import '../../features/config.dart'; import '../../shared/auth/bloc/auth_bloc.dart'; import '../secure_storage.dart'; import '../ui/colors.dart'; @@ -29,7 +29,7 @@ class EnvDialogInput extends StatelessWidget { child: const Text("Save"), onPressed: () { if (envType != null) { - SecureStorage.instance.saveEnvironmentType(envType!); + SecureStorage.instance.updateSettings(envType!); ScaffoldMessenger.of(context) ..hideCurrentSnackBar() ..showSnackBar( diff --git a/lib/src/shared/widget/keyboard_listener.dart b/sama_chat_client/lib/src/shared/widget/keyboard_listener.dart similarity index 100% rename from lib/src/shared/widget/keyboard_listener.dart rename to sama_chat_client/lib/src/shared/widget/keyboard_listener.dart diff --git a/lib/src/shared/widget/link_preview_widget.dart b/sama_chat_client/lib/src/shared/widget/link_preview_widget.dart similarity index 99% rename from lib/src/shared/widget/link_preview_widget.dart rename to sama_chat_client/lib/src/shared/widget/link_preview_widget.dart index 0e7710a0..c05e2054 100644 --- a/lib/src/shared/widget/link_preview_widget.dart +++ b/sama_chat_client/lib/src/shared/widget/link_preview_widget.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_cache_manager/flutter_cache_manager.dart'; +import 'package:sama_sdk/api/api.dart'; -import '../../api/api.dart'; import '../ui/colors.dart'; import '../utils/file_utils.dart'; diff --git a/lib/src/shared/widget/loaders.dart b/sama_chat_client/lib/src/shared/widget/loaders.dart similarity index 100% rename from lib/src/shared/widget/loaders.dart rename to sama_chat_client/lib/src/shared/widget/loaders.dart diff --git a/lib/src/shared/widget/logo_app_bar.dart b/sama_chat_client/lib/src/shared/widget/logo_app_bar.dart similarity index 100% rename from lib/src/shared/widget/logo_app_bar.dart rename to sama_chat_client/lib/src/shared/widget/logo_app_bar.dart diff --git a/lib/src/shared/widget/multi_gesture_detector.dart b/sama_chat_client/lib/src/shared/widget/multi_gesture_detector.dart similarity index 100% rename from lib/src/shared/widget/multi_gesture_detector.dart rename to sama_chat_client/lib/src/shared/widget/multi_gesture_detector.dart diff --git a/lib/src/shared/widget/popup_menu.dart b/sama_chat_client/lib/src/shared/widget/popup_menu.dart similarity index 100% rename from lib/src/shared/widget/popup_menu.dart rename to sama_chat_client/lib/src/shared/widget/popup_menu.dart diff --git a/lib/src/shared/widget/swipe_to.dart b/sama_chat_client/lib/src/shared/widget/swipe_to.dart similarity index 100% rename from lib/src/shared/widget/swipe_to.dart rename to sama_chat_client/lib/src/shared/widget/swipe_to.dart diff --git a/lib/src/shared/widget/typing_indicator.dart b/sama_chat_client/lib/src/shared/widget/typing_indicator.dart similarity index 100% rename from lib/src/shared/widget/typing_indicator.dart rename to sama_chat_client/lib/src/shared/widget/typing_indicator.dart diff --git a/lib/src/shared/widget/vertical_line.dart b/sama_chat_client/lib/src/shared/widget/vertical_line.dart similarity index 100% rename from lib/src/shared/widget/vertical_line.dart rename to sama_chat_client/lib/src/shared/widget/vertical_line.dart diff --git a/pubspec.yaml b/sama_chat_client/pubspec.yaml similarity index 97% rename from pubspec.yaml rename to sama_chat_client/pubspec.yaml index 8da7dec9..478d04de 100644 --- a/pubspec.yaml +++ b/sama_chat_client/pubspec.yaml @@ -47,6 +47,8 @@ dependencies: git: url: https://github.com/KasemJaffer/receive_sharing_intent ref: 2cea396843cd3ab1b5ec4334be4233864637874e + sama_sdk: + path: ../sama_sdk scrollable_positioned_list: ^0.3.8 shared_preferences: ^2.5.2 sqflite: ^2.3.3+1 diff --git a/sama_client_flutter.iml b/sama_chat_client/sama_chat_client.iml similarity index 92% rename from sama_client_flutter.iml rename to sama_chat_client/sama_chat_client.iml index f66303d5..c05162dd 100644 --- a/sama_client_flutter.iml +++ b/sama_chat_client/sama_chat_client.iml @@ -5,13 +5,14 @@ - + + - + \ No newline at end of file diff --git a/test/widget_test.dart b/sama_chat_client/test/widget_test.dart similarity index 100% rename from test/widget_test.dart rename to sama_chat_client/test/widget_test.dart diff --git a/sama_sdk/.gitignore b/sama_sdk/.gitignore new file mode 100644 index 00000000..0acbc627 --- /dev/null +++ b/sama_sdk/.gitignore @@ -0,0 +1,31 @@ +# See https://www.dartlang.org/guides/libraries/private-files + +# Files and directories created by pub +.dart_tool/ +.packages +build/ +# If you're building an application, you may want to check-in your pubspec.lock +pubspec.lock + +# Directory created by dartdoc +# If you don't generate documentation locally you can remove this line. +doc/api/ + +# dotenv environment variables file +.env + +# Avoid committing generated Javascript files: +*.dart.js +*.info.json # Produced by the --dump-info flag. +*.js # When generated by dart2js. Don't specify *.js if your + # project includes source files written in JavaScript. +*.js_ +*.js.deps +*.js.map + +.flutter-plugins +.flutter-plugins-dependencies + +.idea/ + +.DS_Store \ No newline at end of file diff --git a/sama_sdk/.metadata b/sama_sdk/.metadata new file mode 100644 index 00000000..39a37ed9 --- /dev/null +++ b/sama_sdk/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "a402d9a4376add5bc2d6b1e33e53edaae58c07f8" + channel: "stable" + +project_type: package diff --git a/sama_sdk/analysis_options.yaml b/sama_sdk/analysis_options.yaml new file mode 100644 index 00000000..a5744c1c --- /dev/null +++ b/sama_sdk/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/lib/src/api/api.dart b/sama_sdk/lib/api/api.dart similarity index 75% rename from lib/src/api/api.dart rename to sama_sdk/lib/api/api.dart index 8f3b9d98..5371765a 100644 --- a/lib/src/api/api.dart +++ b/sama_sdk/lib/api/api.dart @@ -7,10 +7,10 @@ export 'connection/connection.dart'; export 'connection/exceptions.dart'; export 'conversations/models/models.dart'; export 'conversations/conversations_api.dart'; -export 'push_notifications/push_notifications_manager.dart'; +export 'push_notifications/push_notifications_api.dart'; export 'users/models/models.dart'; export 'users/realtime/users_manager.dart'; export 'users/users_api.dart'; -export 'utils/connectivity_manager.dart'; +export 'connection/managers/connectivity_manager.dart'; +export 'connection/managers/reconnection_manager.dart'; export 'utils/logger.dart'; -export 'utils/reconnection_manager.dart'; diff --git a/lib/src/api/chats/attachments_api.dart b/sama_sdk/lib/api/chats/attachments_api.dart similarity index 100% rename from lib/src/api/chats/attachments_api.dart rename to sama_sdk/lib/api/chats/attachments_api.dart diff --git a/lib/src/api/chats/messages_api.dart b/sama_sdk/lib/api/chats/messages_api.dart similarity index 98% rename from lib/src/api/chats/messages_api.dart rename to sama_sdk/lib/api/chats/messages_api.dart index 4eb21a69..87905658 100644 --- a/lib/src/api/chats/messages_api.dart +++ b/sama_sdk/lib/api/chats/messages_api.dart @@ -119,7 +119,6 @@ Future sendTypingStatus(TypingMessageStatus typing) { return SamaConnectionService.instance .sendRequest(messageTypingName, typing.toJson(), shouldAwaiting: false) .then((response) { - print('sendTypingStatus response $response'); return true; }); } diff --git a/lib/src/api/chats/realtime/messages_manager.dart b/sama_sdk/lib/api/chats/realtime/messages_manager.dart similarity index 100% rename from lib/src/api/chats/realtime/messages_manager.dart rename to sama_sdk/lib/api/chats/realtime/messages_manager.dart diff --git a/lib/src/api/chats/realtime/models/message_statuses.dart b/sama_sdk/lib/api/chats/realtime/models/message_statuses.dart similarity index 100% rename from lib/src/api/chats/realtime/models/message_statuses.dart rename to sama_sdk/lib/api/chats/realtime/models/message_statuses.dart diff --git a/lib/src/api/chats/realtime/models/models.dart b/sama_sdk/lib/api/chats/realtime/models/models.dart similarity index 100% rename from lib/src/api/chats/realtime/models/models.dart rename to sama_sdk/lib/api/chats/realtime/models/models.dart diff --git a/lib/src/api/chats/realtime/models/system_message.dart b/sama_sdk/lib/api/chats/realtime/models/system_message.dart similarity index 95% rename from lib/src/api/chats/realtime/models/system_message.dart rename to sama_sdk/lib/api/chats/realtime/models/system_message.dart index ed1f6550..4bc663c9 100644 --- a/lib/src/api/chats/realtime/models/system_message.dart +++ b/sama_sdk/lib/api/chats/realtime/models/system_message.dart @@ -1,4 +1,5 @@ import '../../../../api/api.dart'; +import '../../../conversations/models/conversation.dart'; abstract class SystemMessage { String cid; diff --git a/lib/src/api/chats/realtime/typing_manager.dart b/sama_sdk/lib/api/chats/realtime/typing_manager.dart similarity index 100% rename from lib/src/api/chats/realtime/typing_manager.dart rename to sama_sdk/lib/api/chats/realtime/typing_manager.dart diff --git a/lib/src/api/connection/connection.dart b/sama_sdk/lib/api/connection/connection.dart similarity index 78% rename from lib/src/api/connection/connection.dart rename to sama_sdk/lib/api/connection/connection.dart index 83cf1a21..17df3aa0 100644 --- a/lib/src/api/connection/connection.dart +++ b/sama_sdk/lib/api/connection/connection.dart @@ -3,10 +3,10 @@ import 'dart:convert'; import 'dart:io'; import 'package:uuid/uuid.dart'; -import 'package:web_socket_channel/status.dart' as status; import 'package:web_socket_channel/web_socket_channel.dart'; +import 'package:web_socket_channel/status.dart' as status; -import '../../shared/secure_storage.dart'; +import '../settings.dart'; import '../api.dart'; const unauthorizedTimeout = Duration(seconds: 5); @@ -48,9 +48,12 @@ class SamaConnectionService { } }); //fix for iOS https://github.com/dart-lang/http/issues/1487 - ConnectivityManager.instance.connectivityStream - .listen((networkConnectionState) { - log('[SamaConnectionService][network connection changed to $networkConnectionState]'); + ConnectivityManager.instance.connectivityStream.listen(( + networkConnectionState, + ) { + log( + '[SamaConnectionService][network connection changed to $networkConnectionState]', + ); if (networkConnectionState == ConnectivityState.none) { _updateConnectionState(ConnectionState.failed); } @@ -58,14 +61,11 @@ class SamaConnectionService { } Future connect() async { - log( - '[SamaConnectionService][connect]', - ); + log('[SamaConnectionService][connect]'); _updateConnectionState(ConnectionState.connecting); - final wssUrl = - Uri.parse('wss://${await SecureStorage.instance.getEnvironmentUrl()}'); + final wssUrl = Uri.parse('wss://${SamaSettings.instance.apiEndpoint}'); final channel = WebSocketChannel.connect(wssUrl); return channel.ready.then((_) { @@ -96,8 +96,9 @@ class SamaConnectionService { }); } - Future getConnection( - {bool forciblyRecreateConnection = false}) { + Future getConnection({ + bool forciblyRecreateConnection = false, + }) { if (!forciblyRecreateConnection && openConnectionFeature != null) { return openConnectionFeature!; } else if (!forciblyRecreateConnection && connection != null) { @@ -129,17 +130,15 @@ class SamaConnectionService { if (shouldAwaiting) { awaitingRequests[requestId] = RequestInfo( - name: requestName, - data: requestData, - completer: requestCompleter, - shouldRetry: shouldRetry); + name: requestName, + data: requestData, + completer: requestCompleter, + shouldRetry: shouldRetry, + ); } var request = { - 'request': { - requestName: requestData, - 'id': requestId, - } + 'request': {requestName: requestData, 'id': requestId}, }; log('request', jsonData: request); @@ -151,19 +150,29 @@ class SamaConnectionService { awaitingRequests.remove(requestId); if (onError is SocketException) { log('request', stringData: 'SocketException'); - requestCompleter.completeError(ResponseException.fromJson( - {'status': -1, 'message': onError.message})); + requestCompleter.completeError( + ResponseException.fromJson({ + 'status': -1, + 'message': onError.message, + }), + ); } else if (onError is WebSocketChannelException) { log('request', stringData: 'WebSocketChannelException'); - requestCompleter.completeError(ResponseException.fromJson( - {'status': -1, 'message': onError.message})); + requestCompleter.completeError( + ResponseException.fromJson({ + 'status': -1, + 'message': onError.message, + }), + ); } else { log('request', stringData: 'Exception: ${onError.toString()}'); - requestCompleter.completeError(ResponseException.fromJson({ - 'status': -1, - 'message': - 'Unknown error happens. Please check internet connection and try again' - })); + requestCompleter.completeError( + ResponseException.fromJson({ + 'status': -1, + 'message': + 'Unknown error happens. Please check internet connection and try again', + }), + ); } }); @@ -176,7 +185,10 @@ class SamaConnectionService { log('[SamaConnectionService][reconnect]', stringData: 'reconnected'); return true; }).catchError((exception) { - log('[SamaConnectionService][reconnect]', stringData: 'reconnect failed'); + log( + '[SamaConnectionService][reconnect]', + stringData: 'reconnect failed', + ); return false; }); } @@ -190,17 +202,11 @@ class SamaConnectionService { } void _processError(error) { - log( - '[SamaConnectionService][_processError]', - stringData: error.toString(), - ); + log('[SamaConnectionService][_processError]', stringData: error.toString()); } void _processData(String data) { - log( - '[SamaConnectionService][_processData]', - stringData: data, - ); + log('[SamaConnectionService][_processData]', stringData: data); try { var jsonData = jsonDecode(data); @@ -243,15 +249,17 @@ class SamaConnectionService { var error = response['error']; if (error != null) { var responseException = ResponseException.fromJson( - error); //CHECK AFTER FIX https://connectycube-apps.atlassian.net/browse/FM-114 + error, + ); //CHECK AFTER FIX https://connectycube-apps.atlassian.net/browse/FM-114 if (responseException.status == HttpStatus.unauthorized) { - print( - 'Unauthorized wait to reconnect $unauthorizedTimeout seconds'); + log( + 'Unauthorized wait to reconnect $unauthorizedTimeout seconds', + ); //Unauthorized wait to reconnect awaitingRequests[responseId] = requestInfo; Future.delayed(unauthorizedTimeout, () { if (awaitingRequests[responseId] != null) { - print('Unauthorized completeError'); + log('Unauthorized completeError'); awaitingRequests.remove(responseId); completer.completeError(responseException); } @@ -263,8 +271,12 @@ class SamaConnectionService { completer.complete(response); } } catch (e) { - completer.completeError(ResponseException.fromJson( - ({'status': -1, 'message': 'Unexpected error'}))); + completer.completeError( + ResponseException.fromJson(({ + 'status': -1, + 'message': 'Unexpected error', + })), + ); } } } @@ -300,9 +312,10 @@ class RequestInfo { final Completer> completer; final bool shouldRetry; - RequestInfo( - {required this.name, - required this.data, - required this.completer, - required this.shouldRetry}); + RequestInfo({ + required this.name, + required this.data, + required this.completer, + required this.shouldRetry, + }); } diff --git a/sama_sdk/lib/api/connection/exceptions.dart b/sama_sdk/lib/api/connection/exceptions.dart new file mode 100644 index 00000000..12d497db --- /dev/null +++ b/sama_sdk/lib/api/connection/exceptions.dart @@ -0,0 +1,15 @@ +class ResponseException { + int? status; + String? message; + + ResponseException.fromJson(Map json) + : status = int.tryParse(json['status']?.toString() ?? ''), + message = json['message'].toString(); + + Map toJson() => {'status': status, 'message': message}; + + @override + String toString() { + return toJson().toString(); + } +} diff --git a/lib/src/api/connection/http_request.dart b/sama_sdk/lib/api/connection/http_request.dart similarity index 91% rename from lib/src/api/connection/http_request.dart rename to sama_sdk/lib/api/connection/http_request.dart index 3ed47b1a..7f247d2b 100644 --- a/lib/src/api/connection/http_request.dart +++ b/sama_sdk/lib/api/connection/http_request.dart @@ -3,8 +3,8 @@ import 'dart:convert'; import 'dart:io'; import 'package:http/http.dart'; -import '../../shared/secure_storage.dart'; import '../api.dart'; +import '../settings.dart'; const _headers = {HttpHeaders.contentTypeHeader: 'application/json'}; @@ -23,7 +23,7 @@ Future> sendHTTPRequest( try { response = await post(urlQuery, headers: headers, body: body); } catch (e) { - print('response e = ${e}'); + log('response e = ${e}'); } log('HTTP response statusCode ${response!.statusCode}, headers $headers ${response.headers} body ${response.body}'); @@ -71,8 +71,8 @@ Future> sendHTTPRequest( Future> sendSamaHTTPRequest( String requestName, dynamic requestData, [Map? requestHeaders]) async { - final url = 'https://${await SecureStorage.instance.getEnvironmentUrl()}'; - final orgId = await SecureStorage.instance.getEnvironmentOrgId(); + final url = 'https://${SamaSettings.instance.apiEndpoint}'; + final orgId = SamaSettings.instance.organizationId; requestData['organization_id'] = orgId; return sendHTTPRequest(url, requestName, requestData, requestHeaders); diff --git a/sama_sdk/lib/api/connection/managers/connection_manager.dart b/sama_sdk/lib/api/connection/managers/connection_manager.dart new file mode 100644 index 00000000..5546d01a --- /dev/null +++ b/sama_sdk/lib/api/connection/managers/connection_manager.dart @@ -0,0 +1,32 @@ +import 'dart:async'; + +import '../../users/models/models.dart'; + +typedef ConnectionTokens = ({ + AccessToken accessToken, + RefreshToken refreshToken +}); + +class ConnectionManager { + ConnectionManager._(); + + static final _instance = ConnectionManager._(); + + static ConnectionManager get instance { + return _instance; + } + + final StreamController _connectionManagerStreamController = + StreamController.broadcast(); + + Stream get connectionManagerStream => + _connectionManagerStreamController.stream; + + AccessToken? accessToken; + RefreshToken? refreshToken; + + updateTokens(AccessToken accessToken, RefreshToken refreshToken) { + _connectionManagerStreamController + .add((accessToken: accessToken, refreshToken: refreshToken)); + } +} diff --git a/lib/src/api/utils/connectivity_manager.dart b/sama_sdk/lib/api/connection/managers/connectivity_manager.dart similarity index 97% rename from lib/src/api/utils/connectivity_manager.dart rename to sama_sdk/lib/api/connection/managers/connectivity_manager.dart index e1a2ece3..b8f308ad 100644 --- a/lib/src/api/utils/connectivity_manager.dart +++ b/sama_sdk/lib/api/connection/managers/connectivity_manager.dart @@ -10,12 +10,12 @@ class ConnectivityManager { final Connectivity _connectivity = Connectivity(); final StreamController _connectivityController = - StreamController.broadcast(); + StreamController.broadcast(); ConnectivityNetwork? _currentConnectivityNetwork; final StreamController _connectivityChangedController = - StreamController.broadcast(); + StreamController.broadcast(); ConnectivityManager._() { _connectivity.onConnectivityChanged diff --git a/lib/src/api/utils/reconnection_manager.dart b/sama_sdk/lib/api/connection/managers/reconnection_manager.dart similarity index 81% rename from lib/src/api/utils/reconnection_manager.dart rename to sama_sdk/lib/api/connection/managers/reconnection_manager.dart index b040993d..81034bcd 100644 --- a/lib/src/api/utils/reconnection_manager.dart +++ b/sama_sdk/lib/api/connection/managers/reconnection_manager.dart @@ -1,10 +1,7 @@ import 'dart:async'; -import 'package:flutter_bloc/flutter_bloc.dart'; - -import '../../../main.dart'; -import '../../shared/auth/bloc/auth_bloc.dart'; -import '../api.dart'; +import '../../api.dart'; +import 'connection_manager.dart'; const int reconnectionTimeout = 5; const int statusTokenExpired = 422; @@ -18,6 +15,12 @@ class ReconnectionManager { return _instance; } + final StreamController _reconnectionStateStreamController = + StreamController.broadcast(); + + Stream get reconnectionStateStream => + _reconnectionStateStreamController.stream; + Timer? _reconnectionTimer; bool _isReconnecting = false; @@ -71,23 +74,21 @@ class ReconnectionManager { if (reconnected) { log('[ReconnectionManager]', stringData: 'reconnected'); _reconnectionTime = 0; - loginWithToken().then((_) { + var accessToken = ConnectionManager.instance.accessToken; + var refreshToken = ConnectionManager.instance.refreshToken; + loginWithToken(accessToken!, refreshToken!).then((_) { SamaConnectionService.instance.resendAwaitingRequests(); }).catchError((onError) async { if (onError is ResponseException) { - loginWithToken().then((_) { + loginWithToken(accessToken, refreshToken).then((_) { SamaConnectionService.instance.resendAwaitingRequests(); }).catchError((onError) { var ex = onError as ResponseException; log('[ReconnectionManager]', stringData: 'reconnected error ${ex.message}'); if (ex.status == statusTokenExpired) { - final context = navigatorKey.currentState?.context; - if (context!.mounted) { - context - .read() - .add(AuthenticationLogoutRequested()); - } + _reconnectionStateStreamController + .add(ReconnectionState.tokenExpired); } }); } else { @@ -114,3 +115,5 @@ class ReconnectionManager { _networkConnectionStateSubscription = null; } } + +enum ReconnectionState { idle, tokenExpired } diff --git a/lib/src/api/conversations/conversations_api.dart b/sama_sdk/lib/api/conversations/conversations_api.dart similarity index 99% rename from lib/src/api/conversations/conversations_api.dart rename to sama_sdk/lib/api/conversations/conversations_api.dart index ac4adcaa..c9c7a541 100644 --- a/lib/src/api/conversations/conversations_api.dart +++ b/sama_sdk/lib/api/conversations/conversations_api.dart @@ -16,6 +16,7 @@ const String conversationDelete = 'conversation_delete'; Future> fetchConversations( Map? params) async { + return SamaConnectionService.instance .sendRequest(conversationsRequest, params) .then((response) { diff --git a/lib/src/api/conversations/models/attachment.dart b/sama_sdk/lib/api/conversations/models/attachment.dart similarity index 52% rename from lib/src/api/conversations/models/attachment.dart rename to sama_sdk/lib/api/conversations/models/attachment.dart index e0930d6a..2f991a27 100644 --- a/lib/src/api/conversations/models/attachment.dart +++ b/sama_sdk/lib/api/conversations/models/attachment.dart @@ -1,7 +1,5 @@ import 'package:equatable/equatable.dart'; -import '../../../db/models/attachment_model.dart'; - class Attachment extends Equatable { final String? fileId; //file_id final String? fileName; //file_name @@ -31,38 +29,25 @@ class Attachment extends Equatable { fileWidth = json['file_width']; Map toJson() => { - 'file_id': fileId, - 'file_name': fileName, - 'file_blur_hash': fileBlurHash, - if (fileUrl != null) 'file_url': fileUrl, - if (fileContentType != null) 'file_content_type': fileContentType, - if (fileHeight != null) 'file_height': fileHeight, - if (fileWidth != null) 'file_width': fileWidth, - }; + 'file_id': fileId, + 'file_name': fileName, + 'file_blur_hash': fileBlurHash, + if (fileUrl != null) 'file_url': fileUrl, + if (fileContentType != null) 'file_content_type': fileContentType, + if (fileHeight != null) 'file_height': fileHeight, + if (fileWidth != null) 'file_width': fileWidth, + }; @override List get props => [ - fileId, - fileName, - fileBlurHash, - fileUrl, - fileContentType, - fileHeight, - fileWidth - ]; + fileId, + fileName, + fileBlurHash, + fileUrl, + fileContentType, + fileHeight, + fileWidth + ]; static const empty = Attachment(); } - -extension AttachmentExtension on AttachmentModel { - Attachment toAttachment() { - return Attachment( - fileId: fileId, - fileName: fileName, - fileBlurHash: fileBlurHash, - // fileUrl: url, // not available on server - fileContentType: contentType, - fileHeight: fileHeight, - fileWidth: fileWidth); - } -} diff --git a/lib/src/api/conversations/models/avatar.dart b/sama_sdk/lib/api/conversations/models/avatar.dart similarity index 100% rename from lib/src/api/conversations/models/avatar.dart rename to sama_sdk/lib/api/conversations/models/avatar.dart diff --git a/lib/src/api/conversations/models/conversation.dart b/sama_sdk/lib/api/conversations/models/conversation.dart similarity index 100% rename from lib/src/api/conversations/models/conversation.dart rename to sama_sdk/lib/api/conversations/models/conversation.dart diff --git a/lib/src/api/conversations/models/link_preview.dart b/sama_sdk/lib/api/conversations/models/link_preview.dart similarity index 100% rename from lib/src/api/conversations/models/link_preview.dart rename to sama_sdk/lib/api/conversations/models/link_preview.dart diff --git a/lib/src/api/conversations/models/message.dart b/sama_sdk/lib/api/conversations/models/message.dart similarity index 100% rename from lib/src/api/conversations/models/message.dart rename to sama_sdk/lib/api/conversations/models/message.dart diff --git a/lib/src/api/conversations/models/models.dart b/sama_sdk/lib/api/conversations/models/models.dart similarity index 100% rename from lib/src/api/conversations/models/models.dart rename to sama_sdk/lib/api/conversations/models/models.dart diff --git a/lib/src/api/push_notifications/models/models.dart b/sama_sdk/lib/api/push_notifications/models/models.dart similarity index 100% rename from lib/src/api/push_notifications/models/models.dart rename to sama_sdk/lib/api/push_notifications/models/models.dart diff --git a/lib/src/api/push_notifications/models/push_event.dart b/sama_sdk/lib/api/push_notifications/models/push_event.dart similarity index 100% rename from lib/src/api/push_notifications/models/push_event.dart rename to sama_sdk/lib/api/push_notifications/models/push_event.dart diff --git a/lib/src/api/push_notifications/models/push_event_message.dart b/sama_sdk/lib/api/push_notifications/models/push_event_message.dart similarity index 100% rename from lib/src/api/push_notifications/models/push_event_message.dart rename to sama_sdk/lib/api/push_notifications/models/push_event_message.dart diff --git a/lib/src/api/push_notifications/models/push_message_data.dart b/sama_sdk/lib/api/push_notifications/models/push_message_data.dart similarity index 100% rename from lib/src/api/push_notifications/models/push_message_data.dart rename to sama_sdk/lib/api/push_notifications/models/push_message_data.dart diff --git a/lib/src/api/push_notifications/models/push_subscription.dart b/sama_sdk/lib/api/push_notifications/models/push_subscription.dart similarity index 100% rename from lib/src/api/push_notifications/models/push_subscription.dart rename to sama_sdk/lib/api/push_notifications/models/push_subscription.dart diff --git a/lib/src/api/push_notifications/push_notifications_api.dart b/sama_sdk/lib/api/push_notifications/push_notifications_api.dart similarity index 100% rename from lib/src/api/push_notifications/push_notifications_api.dart rename to sama_sdk/lib/api/push_notifications/push_notifications_api.dart diff --git a/sama_sdk/lib/api/settings.dart b/sama_sdk/lib/api/settings.dart new file mode 100644 index 00000000..44669b5b --- /dev/null +++ b/sama_sdk/lib/api/settings.dart @@ -0,0 +1,23 @@ +const int maxParticipants = 50; +const int maxChatsToSelect = 20; + +class SamaSettings { + String apiEndpoint = ''; + String organizationId = ''; + + static final SamaSettings _instance = SamaSettings._internal(); + + SamaSettings._internal(); + + static SamaSettings get instance => _instance; + + setEndpoints(String apiEndpoint, String organizationId) { + if (apiEndpoint.isEmpty || organizationId.isEmpty) { + throw ArgumentError( + "'apiEndpoint' and(or) 'organizationId' can not be empty or null"); + } + + this.apiEndpoint = apiEndpoint; + this.organizationId = organizationId; + } +} diff --git a/lib/src/api/users/models/access_token.dart b/sama_sdk/lib/api/users/models/access_token.dart similarity index 100% rename from lib/src/api/users/models/access_token.dart rename to sama_sdk/lib/api/users/models/access_token.dart diff --git a/lib/src/api/users/models/models.dart b/sama_sdk/lib/api/users/models/models.dart similarity index 62% rename from lib/src/api/users/models/models.dart rename to sama_sdk/lib/api/users/models/models.dart index 1c16bc46..88fd05a3 100644 --- a/lib/src/api/users/models/models.dart +++ b/sama_sdk/lib/api/users/models/models.dart @@ -1,2 +1,3 @@ export 'access_token.dart'; +export 'refresh_token.dart'; export 'user.dart'; diff --git a/sama_sdk/lib/api/users/models/refresh_token.dart b/sama_sdk/lib/api/users/models/refresh_token.dart new file mode 100644 index 00000000..f3962bf7 --- /dev/null +++ b/sama_sdk/lib/api/users/models/refresh_token.dart @@ -0,0 +1,21 @@ +import 'package:equatable/equatable.dart'; + +class RefreshToken extends Equatable { + final String? token; + + const RefreshToken({this.token}); + + RefreshToken.fromJson(Map json) + : token = json['refresh_token']; + + Map toJson() => {'refresh_token': token}; + + @override + List get props => [token]; + + RefreshToken copyWith({String? token}) { + return RefreshToken(token: token ?? this.token); + } + + static const empty = RefreshToken(); +} diff --git a/lib/src/api/users/models/user.dart b/sama_sdk/lib/api/users/models/user.dart similarity index 98% rename from lib/src/api/users/models/user.dart rename to sama_sdk/lib/api/users/models/user.dart index 943307f8..195a7b60 100644 --- a/lib/src/api/users/models/user.dart +++ b/sama_sdk/lib/api/users/models/user.dart @@ -1,5 +1,6 @@ import 'package:equatable/equatable.dart'; -import '../../../api/api.dart'; + +import '../../conversations/models/avatar.dart'; class User extends Equatable { final String? id; //_id diff --git a/lib/src/api/users/realtime/users_manager.dart b/sama_sdk/lib/api/users/realtime/users_manager.dart similarity index 100% rename from lib/src/api/users/realtime/users_manager.dart rename to sama_sdk/lib/api/users/realtime/users_manager.dart diff --git a/lib/src/api/users/users_api.dart b/sama_sdk/lib/api/users/users_api.dart similarity index 80% rename from lib/src/api/users/users_api.dart rename to sama_sdk/lib/api/users/users_api.dart index 79cd7cfd..71a15427 100644 --- a/lib/src/api/users/users_api.dart +++ b/sama_sdk/lib/api/users/users_api.dart @@ -2,12 +2,13 @@ import 'dart:io'; import 'package:app_set_id/app_set_id.dart'; -import '../../db/models/models.dart'; -import '../../features/conversations_list/conversations_list.dart'; -import '../../shared/secure_storage.dart'; import '../connection/connection.dart'; import '../connection/http_request.dart'; +import '../connection/managers/connection_manager.dart'; +import '../conversations/models/avatar.dart'; +import '../settings.dart'; import 'models/models.dart'; +import '../utils/logger.dart'; const String userCreateRequestName = 'user_create'; const String userLoginRequestName = 'user_login'; @@ -38,7 +39,7 @@ Future createUser({ 'password': password, 'email': email, 'device_id': deviceId, - 'organization_id': await SecureStorage.instance.getEnvironmentOrgId(), + 'organization_id': SamaSettings.instance.organizationId, if (phone != null) 'phone': phone, if (firstName != null) 'first_name': firstName, if (lastName != null) 'last_name': lastName, @@ -47,33 +48,31 @@ Future createUser({ }); } -Future<(AccessToken, UserModel)> loginHttp(User user) { +Future<(AccessToken, RefreshToken, User)> loginHttp(User user) { return sendSamaHTTPRequest(httpLoginRequestName, { 'login': user.login, 'password': user.password, 'device_id': user.deviceId, }).then((response) { - var loggedUser = User.fromJson(response['user']) - .copyWith(deviceId: user.deviceId) - .toUserModel(); + var loggedUser = + User.fromJson(response['user']).copyWith(deviceId: user.deviceId); var accessToken = AccessToken.fromJson(response); - var refreshToken = response['refresh_token']; - SecureStorage.instance.saveCurrentUserIfNeed(loggedUser); - SecureStorage.instance.saveAccessToken(accessToken); - SecureStorage.instance.saveRefreshToken(refreshToken); - return (accessToken, loggedUser); + var refreshToken = RefreshToken.fromJson(response); + + return (accessToken, refreshToken, loggedUser); }); } -Future loginWithToken([AccessToken? accessToken]) async { - var deviceId = await AppSetId().getIdentifier(); - accessToken ??= await SecureStorage.instance.getAccessToken(); +Future loginWithToken(AccessToken accessToken, RefreshToken refreshToken, + [String? deviceId]) async { + deviceId ??= await AppSetId().getIdentifier(); + ConnectionManager.instance.accessToken = accessToken; + ConnectionManager.instance.refreshToken = refreshToken; - if (accessToken!.expiredAt! < DateTime.now().millisecondsSinceEpoch) { - print('loginWithAccessToken accessToken is expired, so refresh Token'); - final refreshToken = await SecureStorage.instance.getRefreshToken(); + if (accessToken.expiredAt! < DateTime.now().millisecondsSinceEpoch) { + log('loginWithAccessToken accessToken is expired, so refresh Token'); accessToken = - await _refreshToken(accessToken.token!, refreshToken!, deviceId!); + await _refreshToken(accessToken.token!, refreshToken.token!, deviceId!); } return _loginWithAccessToken(accessToken.token!, deviceId!); } @@ -95,10 +94,12 @@ Future _refreshToken( HttpHeaders.cookieHeader: 'refresh_token=$refreshToken' }).then((response) { var accessToken = AccessToken.fromJson(response); - var refreshToken = response['refresh_token']; + var refreshToken = RefreshToken.fromJson(response); + + ConnectionManager.instance.accessToken = accessToken; + ConnectionManager.instance.refreshToken = refreshToken; - SecureStorage.instance.saveAccessToken(accessToken); - SecureStorage.instance.saveRefreshToken(refreshToken); + ConnectionManager.instance.updateTokens(accessToken, refreshToken); return accessToken; }); } @@ -136,7 +137,7 @@ Future sendOtpEmail(String email) async { return SamaConnectionService.instance.sendRequest(userSendOtp, { 'email': email, 'device_id': await AppSetId().getIdentifier(), - 'organization_id': await SecureStorage.instance.getEnvironmentOrgId(), + 'organization_id': SamaSettings.instance.organizationId, }).then((response) { return bool.tryParse(response['success']?.toString() ?? 'false') ?? false; }); @@ -149,7 +150,7 @@ Future sendResetPassword( 'token': token, 'new_password': newPassword, 'device_id': await AppSetId().getIdentifier(), - 'organization_id': await SecureStorage.instance.getEnvironmentOrgId(), + 'organization_id': SamaSettings.instance.organizationId, }).then((response) { return bool.tryParse(response['success']?.toString() ?? 'false') ?? false; }); diff --git a/lib/src/api/utils/logger.dart b/sama_sdk/lib/api/utils/logger.dart similarity index 99% rename from lib/src/api/utils/logger.dart rename to sama_sdk/lib/api/utils/logger.dart index 5cd17a41..cf59cb30 100644 --- a/lib/src/api/utils/logger.dart +++ b/sama_sdk/lib/api/utils/logger.dart @@ -20,4 +20,4 @@ log(String subTag, {Map? jsonData, String? stringData}) { print( '$samaLogTag: $subTag ${jsonData != null ? ':\n${const JsonEncoder.withIndent(' ').convert(jsonData)}' : stringData != null ? ': $stringData' : ''}'); } -} +} \ No newline at end of file diff --git a/sama_sdk/pubspec.yaml b/sama_sdk/pubspec.yaml new file mode 100644 index 00000000..509fa3bd --- /dev/null +++ b/sama_sdk/pubspec.yaml @@ -0,0 +1,27 @@ +name: sama_sdk +description: "The SAMA api for Flutter" +version: 0.0.1 +issue_tracker: https://github.com/SAMA-Communications/sama-client-flutter/issues +documentation: https://github.com/SAMA-Communications/sama-client-flutter/blob/master/README.md +repository: https://github.com/SAMA-Communications/sama-client-flutter + +environment: + sdk: '>=3.3.0 <4.0.0' + +dependencies: + app_set_id: ^1.2.0 + connectivity_plus: ^6.0.3 + equatable: ^2.0.5 + flutter: + sdk: flutter + flutter_dotenv: ^5.2.1 + http: ^1.2.2 + mime: ^1.0.5 + path: ^1.9.0 + uuid: ^4.4.0 + web_socket_channel: ^3.0.0 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^5.0.0 diff --git a/sama_sdk/sama_sdk.iml b/sama_sdk/sama_sdk.iml new file mode 100644 index 00000000..7b18a930 --- /dev/null +++ b/sama_sdk/sama_sdk.iml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sama_sdk/test/sama_chat_api_test.dart b/sama_sdk/test/sama_chat_api_test.dart new file mode 100644 index 00000000..524f07c7 --- /dev/null +++ b/sama_sdk/test/sama_chat_api_test.dart @@ -0,0 +1,7 @@ +import 'package:flutter_test/flutter_test.dart'; + + +void main() { + test('some test', () { + }); +} From 41d1788dee7d9c53252af9d07b767e5d338d6566 Mon Sep 17 00:00:00 2001 From: Magellan <39908400+CubeRomanMagellan@users.noreply.github.com> Date: Sun, 23 Nov 2025 14:40:24 +0200 Subject: [PATCH 02/17] SK-578: share to image (#91) * create monorepo * add api * remove client old api * add tokens management * rename sama_chat_api to sama_sdk * add image share to support * fix Popup with Send Image after share again --------- Co-authored-by: Magellan --- .../android/app/src/main/AndroidManifest.xml | 7 +- .../ios/Share Extension/Info.plist | 2 + .../bloc/media_sender/media_sender_bloc.dart | 13 ++- .../bloc/media_sender/media_sender_event.dart | 4 +- .../conversation/view/conversation_page.dart | 5 +- .../conversation/view/media_sender.dart | 15 +++- .../conversation/view/message_input.dart | 81 ++++++++++++------- 7 files changed, 84 insertions(+), 43 deletions(-) diff --git a/sama_chat_client/android/app/src/main/AndroidManifest.xml b/sama_chat_client/android/app/src/main/AndroidManifest.xml index 07532c0b..1ef1481d 100644 --- a/sama_chat_client/android/app/src/main/AndroidManifest.xml +++ b/sama_chat_client/android/app/src/main/AndroidManifest.xml @@ -15,7 +15,7 @@ + + + + + diff --git a/sama_chat_client/ios/Share Extension/Info.plist b/sama_chat_client/ios/Share Extension/Info.plist index cefa32f1..8a760099 100644 --- a/sama_chat_client/ios/Share Extension/Info.plist +++ b/sama_chat_client/ios/Share Extension/Info.plist @@ -14,6 +14,8 @@ NSExtensionActivationSupportsWebURLWithMaxCount 1 + NSExtensionActivationSupportsImageWithMaxCount + 100 NSExtensionMainStoryboard diff --git a/sama_chat_client/lib/src/features/conversation/bloc/media_sender/media_sender_bloc.dart b/sama_chat_client/lib/src/features/conversation/bloc/media_sender/media_sender_bloc.dart index 2c7f7960..d34f4bcc 100644 --- a/sama_chat_client/lib/src/features/conversation/bloc/media_sender/media_sender_bloc.dart +++ b/sama_chat_client/lib/src/features/conversation/bloc/media_sender/media_sender_bloc.dart @@ -36,7 +36,7 @@ class MediaSenderBloc extends Bloc { _onMessageChanged, ); - on<_AddFiles>( + on( _onFilesAdded, ); @@ -55,8 +55,6 @@ class MediaSenderBloc extends Bloc { on( _onCancelSelection, ); - - _pickMedia(); } FutureOr _onPickFiles( @@ -65,8 +63,7 @@ class MediaSenderBloc extends Bloc { _pickMedia(); } - FutureOr _onFilesAdded( - _AddFiles event, Emitter emit) { + FutureOr _onFilesAdded(AddFiles event, Emitter emit) { emit(state.copyWith(status: MediaSelectorStatus.mediaSelected)); if (event.error?.isNotEmpty ?? false) { emit(state.copyWith(error: event.error)); @@ -191,16 +188,16 @@ class MediaSenderBloc extends Bloc { .then((result) { var files = result?.files; if (files?.isEmpty ?? true) { - add(const _AddFiles([])); + add(const AddFiles([])); } else { var files = List.from(result?.files .map((platformFile) => File(platformFile.path!)) .toList() ?? []); - add(_AddFiles(files)); + add(AddFiles(files)); } }).catchError((onError) { - add(const _AddFiles([], + add(const AddFiles([], error: 'Please allow permission access to Gallery')); }); } diff --git a/sama_chat_client/lib/src/features/conversation/bloc/media_sender/media_sender_event.dart b/sama_chat_client/lib/src/features/conversation/bloc/media_sender/media_sender_event.dart index 2c1f774e..a014b75f 100644 --- a/sama_chat_client/lib/src/features/conversation/bloc/media_sender/media_sender_event.dart +++ b/sama_chat_client/lib/src/features/conversation/bloc/media_sender/media_sender_event.dart @@ -7,11 +7,11 @@ class MediaSenderEvent extends Equatable { List get props => []; } -final class _AddFiles extends MediaSenderEvent { +final class AddFiles extends MediaSenderEvent { final List selectedFiles; final String? error; - const _AddFiles(this.selectedFiles, {this.error}); + const AddFiles(this.selectedFiles, {this.error}); } final class PickMoreFiles extends MediaSenderEvent { diff --git a/sama_chat_client/lib/src/features/conversation/view/conversation_page.dart b/sama_chat_client/lib/src/features/conversation/view/conversation_page.dart index 1436f48d..6ee6b98e 100644 --- a/sama_chat_client/lib/src/features/conversation/view/conversation_page.dart +++ b/sama_chat_client/lib/src/features/conversation/view/conversation_page.dart @@ -143,12 +143,11 @@ class ConversationPage extends StatelessWidget { }, child: ConnectionChecker( child: MessageInput( - sharedText: context + sharedMessage: context .read() .state .sharedFiles - .firstOrNull - ?.path)), + .firstOrNull)), ) : const MessageInput() : const SelectInput()) diff --git a/sama_chat_client/lib/src/features/conversation/view/media_sender.dart b/sama_chat_client/lib/src/features/conversation/view/media_sender.dart index 461612c1..8e8f23db 100644 --- a/sama_chat_client/lib/src/features/conversation/view/media_sender.dart +++ b/sama_chat_client/lib/src/features/conversation/view/media_sender.dart @@ -9,6 +9,7 @@ import 'package:path/path.dart'; import '../../../db/models/conversation_model.dart'; import '../../../db/models/message_model.dart'; import '../../../repository/messages/messages_repository.dart'; +import '../../../shared/sharing/bloc/sharing_intent_bloc.dart'; import '../../../shared/ui/colors.dart'; import '../../../shared/utils/date_utils.dart'; import '../../../shared/utils/media_utils.dart'; @@ -16,13 +17,15 @@ import '../bloc/media_sender/media_sender_bloc.dart'; class MediaSender extends StatelessWidget { final MessageModel? replyMessage; + final String? path; - const MediaSender(this.replyMessage, {super.key}); + const MediaSender(this.replyMessage, this.path, {super.key}); static Widget create({ Key? key, required ConversationModel currentConversation, required MessageModel? replyMessage, + required String? path, }) { return BlocProvider( create: (context) => MediaSenderBloc( @@ -31,6 +34,7 @@ class MediaSender extends StatelessWidget { RepositoryProvider.of(context)), child: MediaSender( replyMessage, + path, key: key, ), ); @@ -38,11 +42,20 @@ class MediaSender extends StatelessWidget { @override Widget build(BuildContext context) { + if (path != null) { + BlocProvider.of(context).add(AddFiles([File(path!)])); + } else { + BlocProvider.of(context).add(const PickMoreFiles()); + } return BlocListener( listener: (context, state) { if (state.status == MediaSelectorStatus.processingFinished || state.status == MediaSelectorStatus.canceled) { context.pop(); + if (context.read().state.status == + SharingIntentStatus.processing) { + context.read().add(SharingIntentCompleted()); + } } }, child: BlocBuilder( diff --git a/sama_chat_client/lib/src/features/conversation/view/message_input.dart b/sama_chat_client/lib/src/features/conversation/view/message_input.dart index 743790af..064b699e 100644 --- a/sama_chat_client/lib/src/features/conversation/view/message_input.dart +++ b/sama_chat_client/lib/src/features/conversation/view/message_input.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:go_router/go_router.dart'; +import 'package:receive_sharing_intent/receive_sharing_intent.dart'; import '../../../shared/connection/view/connection_checker.dart'; import '../../../shared/ui/colors.dart'; @@ -11,9 +13,9 @@ import '../widgets/header_input_box.dart'; import 'media_sender.dart'; class MessageInput extends StatefulWidget { - final String? sharedText; + final SharedMediaFile? sharedMessage; - const MessageInput({super.key, this.sharedText}); + const MessageInput({super.key, this.sharedMessage}); @override State createState() { @@ -23,17 +25,33 @@ class MessageInput extends StatefulWidget { class _MessageInputState extends State { late final TextEditingController textEditingController = - TextEditingController(text: widget.sharedText); + TextEditingController( + text: widget.sharedMessage?.type == SharedMediaType.text || + widget.sharedMessage?.type == SharedMediaType.url + ? widget.sharedMessage?.path + : null); final FocusNode showFocusNode = FocusNode(); + BuildContext? dialogContext; + + @override + void initState() { + super.initState(); + if (widget.sharedMessage?.type == SharedMediaType.image) { + WidgetsBinding.instance.addPostFrameCallback((_) { + showMedia(widget.sharedMessage?.path); + }); + } + } @override Widget build(BuildContext context) { var showReply = false; var showEdit = false; - if (widget.sharedText != null) { + if (widget.sharedMessage?.type == SharedMediaType.text || + widget.sharedMessage?.type == SharedMediaType.url) { BlocProvider.of(context) - .add(TextMessageChanged(widget.sharedText!)); + .add(TextMessageChanged(widget.sharedMessage!.path)); } return MultiBlocListener( listeners: [ @@ -57,7 +75,7 @@ class _MessageInputState extends State { return (previous.draftMessage != current.draftMessage || previous.replyMessage != current.replyMessage || previous.editMessage != current.editMessage) && - widget.sharedText == null; + widget.sharedMessage == null; }, listener: (context, state) { showReply = state.replyMessage != null; @@ -121,28 +139,7 @@ class _MessageInputState extends State { icon: const Icon(Icons.attach_file_outlined), color: dullGray, onPressed: () { - connectionChecker( - context, - () => showDialog( - barrierDismissible: false, - context: context, - builder: (context) { - return AlertDialog( - contentPadding: const EdgeInsets.symmetric( - vertical: 8.0, horizontal: 10.0), - actionsPadding: EdgeInsets.zero, - buttonPadding: EdgeInsets.zero, - content: SizedBox( - width: double.maxFinite, - child: MediaSender.create( - currentConversation: rootContext - .watch() - .currentConversation, - replyMessage: state.replyMessage), - ), - ); - }, - )); + connectionChecker(context, () => showMedia()); }, ), Flexible( @@ -195,8 +192,36 @@ class _MessageInputState extends State { } } + showMedia([String? path]) { + showDialog( + barrierDismissible: false, + context: context, + builder: (ctx) { + dialogContext = ctx; + return AlertDialog( + contentPadding: + const EdgeInsets.symmetric(vertical: 8.0, horizontal: 10.0), + actionsPadding: EdgeInsets.zero, + buttonPadding: EdgeInsets.zero, + content: SizedBox( + width: double.maxFinite, + child: MediaSender.create( + currentConversation: + context.watch().currentConversation, + replyMessage: BlocProvider.of(context) + .state + .replyMessage, + path: path), + )); + }, + ).then((result) async { + dialogContext = null; + }); + } + @override void dispose() { + if (dialogContext != null && dialogContext!.mounted) dialogContext!.pop(); showFocusNode.dispose(); super.dispose(); } From 72acc9a0dbc98dab7e45c4439884408458450abc Mon Sep 17 00:00:00 2001 From: Magellan <39908400+CubeRomanMagellan@users.noreply.github.com> Date: Sun, 23 Nov 2025 17:11:48 +0200 Subject: [PATCH 03/17] add check for deleted user opponent (#93) Co-authored-by: Magellan --- .../lib/src/features/conversation/bloc/conversation_bloc.dart | 3 ++- .../lib/src/repository/messages/messages_repository.dart | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/sama_chat_client/lib/src/features/conversation/bloc/conversation_bloc.dart b/sama_chat_client/lib/src/features/conversation/bloc/conversation_bloc.dart index 10270d87..466576d5 100644 --- a/sama_chat_client/lib/src/features/conversation/bloc/conversation_bloc.dart +++ b/sama_chat_client/lib/src/features/conversation/bloc/conversation_bloc.dart @@ -193,7 +193,8 @@ class ConversationBloc extends Bloc { } subscribeOpponentLastActivity() async { - if (currentConversation.type == 'u') { + if (currentConversation.type == 'u' && + currentConversation.opponent != null) { var recentActivity = await userRepository .subscribeUserLastActivity(currentConversation.opponent!.id!); _updateOpponentRecentActivity(recentActivity); diff --git a/sama_chat_client/lib/src/repository/messages/messages_repository.dart b/sama_chat_client/lib/src/repository/messages/messages_repository.dart index c8aebae9..9c357622 100644 --- a/sama_chat_client/lib/src/repository/messages/messages_repository.dart +++ b/sama_chat_client/lib/src/repository/messages/messages_repository.dart @@ -459,7 +459,8 @@ class MessagesRepository { var message = messages[i]; var isOwn = currentUser?.id == message.from; var sender = participants[message.from] ?? - await userRepository.getUserById(message.from!); + await userRepository.getUserById(message.from!) ?? + UserModel(); var messageModel = message.toMessageModel(isOwn, sender); result.add(messageModel); } From 586bf9d7440af3fdd021d9b7d8908b1765be755e Mon Sep 17 00:00:00 2001 From: Magellan <39908400+CubeRomanMagellan@users.noreply.github.com> Date: Sun, 23 Nov 2025 17:45:52 +0200 Subject: [PATCH 04/17] add MediaAttachmentBloc to menu (#95) Co-authored-by: Magellan --- .../features/conversation/view/messages_list.dart | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/sama_chat_client/lib/src/features/conversation/view/messages_list.dart b/sama_chat_client/lib/src/features/conversation/view/messages_list.dart index 3036e741..bf6e7e20 100644 --- a/sama_chat_client/lib/src/features/conversation/view/messages_list.dart +++ b/sama_chat_client/lib/src/features/conversation/view/messages_list.dart @@ -352,11 +352,14 @@ class MessageItem extends StatelessWidget { }), ], context: context, - child: BlocProvider.value( - value: - BlocProvider.of( - context), - child: this), + child: MultiBlocProvider(providers: [ + BlocProvider.value( + value: BlocProvider.of< + MediaAttachmentBloc>(context)), + BlocProvider.value( + value: BlocProvider.of< + ConversationBloc>(context)), + ], child: this), stickToRight: message.isOwn) .show(); }), From 3e176b23eb455391bb7948208729bd8e150c2ae5 Mon Sep 17 00:00:00 2001 From: Magellan <39908400+CubeRomanMagellan@users.noreply.github.com> Date: Tue, 25 Nov 2025 17:14:40 +0200 Subject: [PATCH 05/17] SK-589: implement ability to take a photo (#92) * create monorepo * add api * remove client old api * add tokens management * rename sama_chat_api to sama_sdk * add image share to support * add image_picker * add camera picker * update agpVersion --------- Co-authored-by: Magellan --- sama_chat_client/android/gradle.properties | 2 +- sama_chat_client/ios/Runner/Info.plist | 2 + .../bloc/media_sender/media_sender_bloc.dart | 54 +++++++----- .../bloc/media_sender/media_sender_event.dart | 8 +- .../conversation/view/media_sender.dart | 83 +++++++++++-------- .../conversation/view/message_input.dart | 7 +- .../bloc/group_bloc.dart | 8 +- .../group_info/bloc/group_info_bloc.dart | 8 +- .../features/profile/bloc/profile_bloc.dart | 8 +- sama_chat_client/pubspec.yaml | 2 +- 10 files changed, 105 insertions(+), 77 deletions(-) diff --git a/sama_chat_client/android/gradle.properties b/sama_chat_client/android/gradle.properties index a700745f..66b601e9 100644 --- a/sama_chat_client/android/gradle.properties +++ b/sama_chat_client/android/gradle.properties @@ -2,4 +2,4 @@ org.gradle.jvmargs=-Xmx4G android.useAndroidX=true android.enableJetifier=true kotlinVersion=2.2.0 -agpVersion=8.9.0 \ No newline at end of file +agpVersion=8.9.1 \ No newline at end of file diff --git a/sama_chat_client/ios/Runner/Info.plist b/sama_chat_client/ios/Runner/Info.plist index db2094c4..347fde01 100644 --- a/sama_chat_client/ios/Runner/Info.plist +++ b/sama_chat_client/ios/Runner/Info.plist @@ -48,6 +48,8 @@ NSPhotoLibraryUsageDescription To upload photos, please allow permission to access your photo library. + NSCameraUsageDescription + To upload photos from camera UIApplicationSupportsIndirectInputEvents UIBackgroundModes diff --git a/sama_chat_client/lib/src/features/conversation/bloc/media_sender/media_sender_bloc.dart b/sama_chat_client/lib/src/features/conversation/bloc/media_sender/media_sender_bloc.dart index d34f4bcc..394b8fc7 100644 --- a/sama_chat_client/lib/src/features/conversation/bloc/media_sender/media_sender_bloc.dart +++ b/sama_chat_client/lib/src/features/conversation/bloc/media_sender/media_sender_bloc.dart @@ -2,8 +2,8 @@ import 'dart:async'; import 'dart:io'; import 'package:equatable/equatable.dart'; -import 'package:file_picker/file_picker.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:image_picker/image_picker.dart'; import 'package:path/path.dart'; import 'package:sama_sdk/api/api.dart'; @@ -23,13 +23,18 @@ const maxAttachmentsCount = 10; class MediaSenderBloc extends Bloc { final ConversationModel currentConversation; final MessagesRepository messagesRepository; + final ImagePicker picker = ImagePicker(); MediaSenderBloc({ required this.currentConversation, required this.messagesRepository, }) : super(MediaSenderState()) { - on( - _onPickFiles, + on( + _onPickMedia, + ); + + on( + _onPickCamera, ); on( @@ -57,12 +62,17 @@ class MediaSenderBloc extends Bloc { ); } - FutureOr _onPickFiles( - PickMoreFiles event, Emitter emit) { + FutureOr _onPickMedia(PickMedia event, Emitter emit) { emit(state.copyWith(status: MediaSelectorStatus.picking)); _pickMedia(); } + FutureOr _onPickCamera( + PickCamera event, Emitter emit) { + emit(state.copyWith(status: MediaSelectorStatus.picking)); + _pickCamera(); + } + FutureOr _onFilesAdded(AddFiles event, Emitter emit) { emit(state.copyWith(status: MediaSelectorStatus.mediaSelected)); if (event.error?.isNotEmpty ?? false) { @@ -175,25 +185,12 @@ class MediaSenderBloc extends Bloc { } void _pickMedia() { - FilePicker.platform - .pickFiles( - type: FileType.media, - //TODO RP remove this if it's all ok on both android and iOS sides - // allowedExtensions: [ - // ...supportedImageAttachmentExtentions, - // ...supportedVideoAttachmentExtentions - // ], - allowMultiple: true, - compressionQuality: 0) - .then((result) { - var files = result?.files; - if (files?.isEmpty ?? true) { + picker.pickMultipleMedia().then((result) { + if (result.isEmpty) { add(const AddFiles([])); } else { - var files = List.from(result?.files - .map((platformFile) => File(platformFile.path!)) - .toList() ?? - []); + var files = List.from( + result.map((platformFile) => File(platformFile.path)).toList()); add(AddFiles(files)); } }).catchError((onError) { @@ -202,6 +199,19 @@ class MediaSenderBloc extends Bloc { }); } + void _pickCamera() { + picker.pickImage(source: ImageSource.camera).then((result) { + if (result?.path.isEmpty ?? true) { + add(const AddFiles([])); + } else { + add(AddFiles([File(result!.path)])); + } + }).catchError((onError) { + add(const AddFiles([], + error: 'Please allow permission access to Gallery')); + }); + } + FutureOr _onMessageChanged( ChangeMessage event, Emitter emit) { emit(state.copyWith(message: event.message)); diff --git a/sama_chat_client/lib/src/features/conversation/bloc/media_sender/media_sender_event.dart b/sama_chat_client/lib/src/features/conversation/bloc/media_sender/media_sender_event.dart index a014b75f..91757ba1 100644 --- a/sama_chat_client/lib/src/features/conversation/bloc/media_sender/media_sender_event.dart +++ b/sama_chat_client/lib/src/features/conversation/bloc/media_sender/media_sender_event.dart @@ -14,8 +14,12 @@ final class AddFiles extends MediaSenderEvent { const AddFiles(this.selectedFiles, {this.error}); } -final class PickMoreFiles extends MediaSenderEvent { - const PickMoreFiles(); +final class PickCamera extends MediaSenderEvent { + const PickCamera(); +} + +final class PickMedia extends MediaSenderEvent { + const PickMedia(); } final class ChangeMessage extends MediaSenderEvent { diff --git a/sama_chat_client/lib/src/features/conversation/view/media_sender.dart b/sama_chat_client/lib/src/features/conversation/view/media_sender.dart index 8e8f23db..222da81f 100644 --- a/sama_chat_client/lib/src/features/conversation/view/media_sender.dart +++ b/sama_chat_client/lib/src/features/conversation/view/media_sender.dart @@ -44,8 +44,6 @@ class MediaSender extends StatelessWidget { Widget build(BuildContext context) { if (path != null) { BlocProvider.of(context).add(AddFiles([File(path!)])); - } else { - BlocProvider.of(context).add(const PickMoreFiles()); } return BlocListener( listener: (context, state) { @@ -74,18 +72,7 @@ class MediaSender extends StatelessWidget { const SizedBox( height: 8, ), - if (state.selectedFiles.isEmpty && - state.status == MediaSelectorStatus.initial) - Container( - padding: const EdgeInsets.all(8), - width: 48, - height: 48, - child: const CircularProgressIndicator( - strokeWidth: 3.0, - ), - ), - if (state.selectedFiles.isEmpty && - state.status != MediaSelectorStatus.initial) + if (state.selectedFiles.isEmpty) const Center( child: Text( 'Select files', @@ -131,25 +118,55 @@ class MediaSender extends StatelessWidget { ), Row( children: [ - TextButton( - onPressed: () { - if (state.selectedFiles.length < 10 && - state.status != - MediaSelectorStatus.processing) { - BlocProvider.of(context) - .add(const PickMoreFiles()); - } - }, - child: Text( - 'Add', - style: TextStyle( - color: state.selectedFiles.length < 10 && - state.status != - MediaSelectorStatus.processing - ? slateBlue - : whiteAluminum), - ), - ), + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TextButton( + onPressed: () { + if (state.selectedFiles.length < 10 && + state.status != + MediaSelectorStatus.processing) { + BlocProvider.of(context) + .add(const PickCamera()); + } + }, + style: TextButton.styleFrom( + tapTargetSize: + MaterialTapTargetSize.shrinkWrap), + child: Text( + 'Camera', + style: TextStyle( + color: state.selectedFiles.length < 10 && + state.status != + MediaSelectorStatus.processing + ? slateBlue + : whiteAluminum), + ), + ), + TextButton( + onPressed: () { + if (state.selectedFiles.length < 10 && + state.status != + MediaSelectorStatus.processing) { + BlocProvider.of(context) + .add(const PickMedia()); + } + }, + style: TextButton.styleFrom( + tapTargetSize: + MaterialTapTargetSize.shrinkWrap), + child: Text( + 'Media', + style: TextStyle( + color: state.selectedFiles.length < 10 && + state.status != + MediaSelectorStatus.processing + ? slateBlue + : whiteAluminum), + ), + ), + ]), const Expanded(child: SizedBox.shrink()), TextButton( onPressed: () { diff --git a/sama_chat_client/lib/src/features/conversation/view/message_input.dart b/sama_chat_client/lib/src/features/conversation/view/message_input.dart index 064b699e..f133c813 100644 --- a/sama_chat_client/lib/src/features/conversation/view/message_input.dart +++ b/sama_chat_client/lib/src/features/conversation/view/message_input.dart @@ -196,8 +196,7 @@ class _MessageInputState extends State { showDialog( barrierDismissible: false, context: context, - builder: (ctx) { - dialogContext = ctx; + builder: (_) { return AlertDialog( contentPadding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 10.0), @@ -214,9 +213,7 @@ class _MessageInputState extends State { path: path), )); }, - ).then((result) async { - dialogContext = null; - }); + ); } @override diff --git a/sama_chat_client/lib/src/features/conversation_group_create/bloc/group_bloc.dart b/sama_chat_client/lib/src/features/conversation_group_create/bloc/group_bloc.dart index ae01d367..3821ee99 100644 --- a/sama_chat_client/lib/src/features/conversation_group_create/bloc/group_bloc.dart +++ b/sama_chat_client/lib/src/features/conversation_group_create/bloc/group_bloc.dart @@ -2,8 +2,8 @@ import 'dart:io'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; -import 'package:file_picker/file_picker.dart'; import 'package:formz/formz.dart'; +import 'package:image_picker/image_picker.dart'; import '../../../db/models/user_model.dart'; import '../models/avatar.dart'; @@ -41,11 +41,9 @@ class GroupBloc extends Bloc { GroupAvatarPicked event, Emitter emit, ) async { - await FilePicker.platform - .pickFiles(type: FileType.image, compressionQuality: 0) - .then((result) { + await ImagePicker().pickImage(source: ImageSource.gallery).then((result) { if (result != null) { - File file = File(result.files.single.path!); + File file = File(result.path); final avatarUrl = GroupAvatar.dirty(file); emit( state.copyWith( diff --git a/sama_chat_client/lib/src/features/group_info/bloc/group_info_bloc.dart b/sama_chat_client/lib/src/features/group_info/bloc/group_info_bloc.dart index 4e11171b..336d0b4c 100644 --- a/sama_chat_client/lib/src/features/group_info/bloc/group_info_bloc.dart +++ b/sama_chat_client/lib/src/features/group_info/bloc/group_info_bloc.dart @@ -2,8 +2,8 @@ import 'dart:io'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; -import 'package:file_picker/file_picker.dart'; import 'package:formz/formz.dart'; +import 'package:image_picker/image_picker.dart'; import 'package:sama_sdk/api/api.dart'; import '../../../db/models/models.dart'; @@ -60,11 +60,11 @@ class GroupInfoBloc extends Bloc { GroupAvatarPicked event, Emitter emit, ) async { - await FilePicker.platform - .pickFiles(type: FileType.image, compressionQuality: 0) + await ImagePicker() + .pickImage(source: ImageSource.gallery) .then((result) async { if (result != null) { - File file = File(result.files.single.path!); + File file = File(result.path); try { final chat = await _conversationRepository.updateConversation( id: state.conversation.id, avatarUrl: file); diff --git a/sama_chat_client/lib/src/features/profile/bloc/profile_bloc.dart b/sama_chat_client/lib/src/features/profile/bloc/profile_bloc.dart index dfae6562..8c5ca4aa 100644 --- a/sama_chat_client/lib/src/features/profile/bloc/profile_bloc.dart +++ b/sama_chat_client/lib/src/features/profile/bloc/profile_bloc.dart @@ -2,8 +2,8 @@ import 'dart:io'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; -import 'package:file_picker/file_picker.dart'; import 'package:formz/formz.dart'; +import 'package:image_picker/image_picker.dart'; import '../../../db/models/models.dart'; import '../../../repository/user/user_repository.dart'; @@ -56,11 +56,11 @@ class ProfileBloc extends Bloc { ProfileAvatarPicked event, Emitter emit, ) async { - await FilePicker.platform - .pickFiles(type: FileType.image, compressionQuality: 0) + await ImagePicker() + .pickImage(source: ImageSource.gallery) .then((result) async { if (result != null) { - File file = File(result.files.single.path!); + File file = File(result.path); try { final user = await _userRepository.updateAvatar(file); emit(state.copyWith( diff --git a/sama_chat_client/pubspec.yaml b/sama_chat_client/pubspec.yaml index 478d04de..e8eb88d1 100644 --- a/sama_chat_client/pubspec.yaml +++ b/sama_chat_client/pubspec.yaml @@ -18,7 +18,6 @@ dependencies: connectivity_plus: ^6.0.3 cupertino_icons: ^1.0.6 equatable: ^2.0.5 - file_picker: ^8.0.6 firebase_core: ^3.6.0 firebase_messaging: ^15.1.3 flutter: @@ -35,6 +34,7 @@ dependencies: go_router: ^14.8.1 http: ^1.2.2 image: ^4.2.0 + image_picker: ^1.2.0 intl: ^0.20.0 mime: ^1.0.5 objectbox: ^4.0.3 From bcb6aacc5e305c30f6b6a34aa3303a1052cf35ba Mon Sep 17 00:00:00 2001 From: Magellan <39908400+CubeRomanMagellan@users.noreply.github.com> Date: Tue, 25 Nov 2025 18:13:47 +0200 Subject: [PATCH 06/17] SK-587: Hard back does not work (#94) * add pop invoke * minor fix didPop * add swipe ios impl --------- Co-authored-by: Magellan --- .../conversation/view/conversation_page.dart | 18 +++++++++++++----- .../group_info/view/group_info_page.dart | 15 ++++++++++----- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/sama_chat_client/lib/src/features/conversation/view/conversation_page.dart b/sama_chat_client/lib/src/features/conversation/view/conversation_page.dart index 6ee6b98e..4b79ca63 100644 --- a/sama_chat_client/lib/src/features/conversation/view/conversation_page.dart +++ b/sama_chat_client/lib/src/features/conversation/view/conversation_page.dart @@ -20,6 +20,7 @@ import '../../../shared/ui/colors.dart'; import '../../../shared/utils/string_utils.dart'; import '../../../shared/widget/loaders.dart'; import '../../../shared/widget/typing_indicator.dart'; +import '../../group_info/view/group_info_page.dart'; import '../bloc/ai_message/ai_message_bloc.dart'; import '../bloc/conversation_bloc.dart'; import '../bloc/delete_messages/delete_messages_bloc.dart'; @@ -289,10 +290,17 @@ Future _infoAction(BuildContext context) async { if (state.conversation.type == 'u') { context.push(userInfoPath, extra: state.conversation.opponent); } else { - bool conversationUpdated = - await context.push(groupInfoPath, extra: state.conversation) as bool; - if (conversationUpdated && context.mounted) { - context.read().add(const ParticipantsReceived()); - } + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => GroupInfoPage.route(state.conversation, + onResult: (conversationUpdated) { + if (conversationUpdated && context.mounted) { + context + .read() + .add(const ParticipantsReceived()); + } + })), + ); } } diff --git a/sama_chat_client/lib/src/features/group_info/view/group_info_page.dart b/sama_chat_client/lib/src/features/group_info/view/group_info_page.dart index 0518af2b..8c08d3a2 100644 --- a/sama_chat_client/lib/src/features/group_info/view/group_info_page.dart +++ b/sama_chat_client/lib/src/features/group_info/view/group_info_page.dart @@ -10,12 +10,15 @@ import '../../../shared/ui/colors.dart'; import '../bloc/group_info_bloc.dart'; import 'group_info_form.dart'; +typedef GroupInfoPageCallback = void Function(bool result); + class GroupInfoPage extends StatelessWidget { final ConversationModel conversation; + final GroupInfoPageCallback? onResult; - const GroupInfoPage({required this.conversation, super.key}); + const GroupInfoPage({required this.conversation, this.onResult, super.key}); - static BlocProvider route(Object? extra) { + static BlocProvider route(Object? extra, {GroupInfoPageCallback? onResult}) { ConversationModel conversation = extra as ConversationModel; return BlocProvider( @@ -23,7 +26,7 @@ class GroupInfoPage extends StatelessWidget { RepositoryProvider.of(context), RepositoryProvider.of(context), conversation: conversation), - child: GroupInfoPage(conversation: conversation), + child: GroupInfoPage(conversation: conversation, onResult: onResult), ); } @@ -32,7 +35,9 @@ class GroupInfoPage extends StatelessWidget { return BlocBuilder( builder: (context, state) { return PopScope( - canPop: false, + onPopInvokedWithResult: (didPop, result) { + onResult?.call(state.status.isSuccess); + }, child: Scaffold( backgroundColor: black, resizeToAvoidBottomInset: false, @@ -40,7 +45,7 @@ class GroupInfoPage extends StatelessWidget { backgroundColor: black, leading: IconButton( icon: const Icon(Icons.arrow_back_outlined, color: white), - onPressed: () => context.pop(state.status.isSuccess), + onPressed: () => context.pop(), ), title: Text( state.name.value, From da088cc496c668775e9d862263beeb56450f3cc6 Mon Sep 17 00:00:00 2001 From: Magellan <39908400+CubeRomanMagellan@users.noreply.github.com> Date: Tue, 2 Dec 2025 19:54:34 +0200 Subject: [PATCH 07/17] fix app routing (#96) Co-authored-by: Magellan --- .../conversation/view/conversation_page.dart | 62 ++++++++++--------- .../lib/src/navigation/app_router.dart | 7 --- 2 files changed, 33 insertions(+), 36 deletions(-) diff --git a/sama_chat_client/lib/src/features/conversation/view/conversation_page.dart b/sama_chat_client/lib/src/features/conversation/view/conversation_page.dart index 4b79ca63..1f09181a 100644 --- a/sama_chat_client/lib/src/features/conversation/view/conversation_page.dart +++ b/sama_chat_client/lib/src/features/conversation/view/conversation_page.dart @@ -36,41 +36,45 @@ class ConversationPage extends StatelessWidget { static MultiBlocProvider route(Object? extra) { ConversationModel currentConversation = extra as ConversationModel; - return MultiBlocProvider(providers: [ - BlocProvider( - create: (context) => ConversationBloc( + return MultiBlocProvider( + key: Key(currentConversation.id), + providers: [ + BlocProvider( + create: (context) => ConversationBloc( + currentConversation: currentConversation, + conversationRepository: + RepositoryProvider.of(context), + messagesRepository: + RepositoryProvider.of(context), + userRepository: + RepositoryProvider.of(context)) + ..add(const MessagesRequested())), + BlocProvider( + create: (context) => SendMessageBloc( currentConversation: currentConversation, conversationRepository: RepositoryProvider.of(context), messagesRepository: RepositoryProvider.of(context), - userRepository: RepositoryProvider.of(context)) - ..add(const MessagesRequested())), - BlocProvider( - create: (context) => SendMessageBloc( - currentConversation: currentConversation, - conversationRepository: - RepositoryProvider.of(context), - messagesRepository: - RepositoryProvider.of(context), - ), - ), - BlocProvider( - create: (context) => DeleteMessagesBloc( - messagesRepository: - RepositoryProvider.of(context), - ), - ), - BlocProvider( - create: (context) => MediaAttachmentBloc( - attachmentsRepository: - RepositoryProvider.of(context))), - BlocProvider( - create: (context) => AiMessageBloc( - currentConversation: currentConversation, + ), + ), + BlocProvider( + create: (context) => DeleteMessagesBloc( messagesRepository: - RepositoryProvider.of(context))), - ], child: const ConversationPage()); + RepositoryProvider.of(context), + ), + ), + BlocProvider( + create: (context) => MediaAttachmentBloc( + attachmentsRepository: + RepositoryProvider.of(context))), + BlocProvider( + create: (context) => AiMessageBloc( + currentConversation: currentConversation, + messagesRepository: + RepositoryProvider.of(context))), + ], + child: const ConversationPage()); } @override diff --git a/sama_chat_client/lib/src/navigation/app_router.dart b/sama_chat_client/lib/src/navigation/app_router.dart index 40fcff9d..48c0c396 100644 --- a/sama_chat_client/lib/src/navigation/app_router.dart +++ b/sama_chat_client/lib/src/navigation/app_router.dart @@ -143,13 +143,6 @@ GoRouter router(BuildContext context, navigatorKey) => GoRouter( } if (status == AuthenticationStatus.authenticated) { - // fix for https://github.com/flutter/flutter/issues/146616 - ignoring Failed assertion for now - if (state.fullPath == - '$conversationListScreenPath/$conversationScreenSubPath' && - state.extra == null) { - context.goNamed(state.matchedLocation); - } - return state.fullPath == loginScreenPath ? rootScreenPath : state.fullPath; From 5ee84b6e4b1a9d423573d5c3429a170b3aa5a878 Mon Sep 17 00:00:00 2001 From: Magellan <39908400+CubeRomanMagellan@users.noreply.github.com> Date: Tue, 2 Dec 2025 20:30:07 +0200 Subject: [PATCH 08/17] add blocking (#97) Co-authored-by: Magellan --- .../conversation/view/message_input.dart | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/sama_chat_client/lib/src/features/conversation/view/message_input.dart b/sama_chat_client/lib/src/features/conversation/view/message_input.dart index f133c813..3b802828 100644 --- a/sama_chat_client/lib/src/features/conversation/view/message_input.dart +++ b/sama_chat_client/lib/src/features/conversation/view/message_input.dart @@ -48,6 +48,9 @@ class _MessageInputState extends State { Widget build(BuildContext context) { var showReply = false; var showEdit = false; + var currentChat = context.read().currentConversation; + var blockSending = currentChat.type == 'u' && currentChat.opponent == null; + if (widget.sharedMessage?.type == SharedMediaType.text || widget.sharedMessage?.type == SharedMediaType.url) { BlocProvider.of(context) @@ -138,20 +141,23 @@ class _MessageInputState extends State { IconButton( icon: const Icon(Icons.attach_file_outlined), color: dullGray, - onPressed: () { - connectionChecker(context, () => showMedia()); - }, + onPressed: blockSending + ? null + : () => {connectionChecker(context, () => showMedia())}, ), Flexible( child: TextField( focusNode: showFocusNode, + enabled: !blockSending, keyboardType: TextInputType.multiline, maxLines: null, style: const TextStyle(fontSize: 15.0), controller: textEditingController, - decoration: const InputDecoration.collapsed( - hintText: 'Type your message...', - hintStyle: TextStyle(color: dullGray), + decoration: InputDecoration.collapsed( + hintText: blockSending + ? 'Can\'t send message' + : 'Type your message...', + hintStyle: const TextStyle(color: dullGray), ), onChanged: (text) { BlocProvider.of(rootContext) From 969d62a64fe817179604d3a3a1b662aeb0e383b0 Mon Sep 17 00:00:00 2001 From: Magellan <39908400+CubeRomanMagellan@users.noreply.github.com> Date: Tue, 9 Dec 2025 21:58:28 +0200 Subject: [PATCH 09/17] add auto complete (#98) Co-authored-by: Magellan --- .../reset_password/view/send_otp_form.dart | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/sama_chat_client/lib/src/features/reset_password/view/send_otp_form.dart b/sama_chat_client/lib/src/features/reset_password/view/send_otp_form.dart index 86a85c00..d25f6e0d 100644 --- a/sama_chat_client/lib/src/features/reset_password/view/send_otp_form.dart +++ b/sama_chat_client/lib/src/features/reset_password/view/send_otp_form.dart @@ -117,6 +117,8 @@ class _ContinueButton extends StatelessWidget { } class OtpInput extends StatefulWidget { + static const otpSize = 6; + const OtpInput({super.key}); @override @@ -125,9 +127,10 @@ class OtpInput extends StatefulWidget { class OtpInputState extends State { final List _controllers = - List.generate(6, (_) => TextEditingController()); + List.generate(OtpInput.otpSize, (_) => TextEditingController()); - final List _focusNodes = List.generate(6, (_) => FocusNode()); + final List _focusNodes = + List.generate(OtpInput.otpSize, (_) => FocusNode()); @override Widget build(BuildContext context) { @@ -147,7 +150,7 @@ class OtpInputState extends State { padding: const EdgeInsets.all(8.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, - children: List.generate(6, (index) { + children: List.generate(OtpInput.otpSize, (index) { return digitField(index); }), ), @@ -166,8 +169,21 @@ class OtpInputState extends State { focusNode: _focusNodes[index], keyboardType: TextInputType.number, textAlign: TextAlign.center, - maxLength: 1, + autofocus: true, onChanged: (value) { + if (value.characters.length == OtpInput.otpSize) { + for (final (index, controller) in _controllers.indexed) { + controller.text = value.characters.elementAt(index); + if (index < 5) { + FocusScope.of(context).requestFocus(_focusNodes[index + 1]); + } + context + .read() + .add(OtpChanged(index, value.characters.elementAt(index))); + } + return; + } + if (value.isNotEmpty && index < 5) { FocusScope.of(context).requestFocus(_focusNodes[index + 1]); } else if (value.isEmpty && index > 0) { From e7d956b483aadefab7b6a61853e78faa9702426d Mon Sep 17 00:00:00 2001 From: Magellan <39908400+CubeRomanMagellan@users.noreply.github.com> Date: Tue, 9 Dec 2025 22:30:55 +0200 Subject: [PATCH 10/17] fix reply bubble (#99) Co-authored-by: Magellan --- .../features/conversation/widgets/reply_bubble.dart | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/sama_chat_client/lib/src/features/conversation/widgets/reply_bubble.dart b/sama_chat_client/lib/src/features/conversation/widgets/reply_bubble.dart index a9dc6e6b..49bb579e 100644 --- a/sama_chat_client/lib/src/features/conversation/widgets/reply_bubble.dart +++ b/sama_chat_client/lib/src/features/conversation/widgets/reply_bubble.dart @@ -110,11 +110,15 @@ class ReplyBubble extends StatelessWidget { var isImageType = isImage(attachment.fileName, attachment.contentType); return FutureBuilder( - future: isImageType - ? Future.value(attachment.url ?? '') - : getVideoThumbnailByUrl(attachment.url!, attachment.fileId), + future: attachment.url == null + ? Future.value('') + : isImageType + ? Future.value(attachment.url!) + : getVideoThumbnailByUrl(attachment.url!, attachment.fileId), builder: (context, snapshot) { - if (snapshot.hasError || !snapshot.hasData) { + if (snapshot.hasError || + !snapshot.hasData || + snapshot.data!.isEmpty) { return const SizedBox(height: 40, width: 40); } return Container( From cae8d00f743c15e9d88cfc6dd820768ecf81cf20 Mon Sep 17 00:00:00 2001 From: Magellan Date: Sun, 14 Dec 2025 00:42:20 +0200 Subject: [PATCH 11/17] update login page --- .../src/features/login/view/login_form.dart | 192 +++++------------- .../src/shared/ui/view/text_field_form.dart | 64 ++++++ 2 files changed, 115 insertions(+), 141 deletions(-) create mode 100644 sama_chat_client/lib/src/shared/ui/view/text_field_form.dart diff --git a/sama_chat_client/lib/src/features/login/view/login_form.dart b/sama_chat_client/lib/src/features/login/view/login_form.dart index ab000692..de5524a5 100644 --- a/sama_chat_client/lib/src/features/login/view/login_form.dart +++ b/sama_chat_client/lib/src/features/login/view/login_form.dart @@ -6,6 +6,7 @@ import 'package:go_router/go_router.dart'; import '../../../navigation/constants.dart'; import '../../../shared/ui/colors.dart'; +import '../../../shared/ui/view/text_field_form.dart'; import '../bloc/login_bloc.dart'; import '../models/models.dart'; @@ -105,20 +106,6 @@ class LoginFormState extends State { const Padding(padding: EdgeInsets.all(8)), _EmailInput(), const Padding(padding: EdgeInsets.all(4)), - Row( - children: [ - Checkbox( - checkColor: white, - activeColor: whiteAluminum, - value: loginWithNewUser, - onChanged: (checked) { - setState(() { - loginWithNewUser = checked ?? true; - }); - }), - const Text('* Sign in automatically') - ], - ), ] else ...[ const Padding(padding: EdgeInsets.all(4)), Align( @@ -170,40 +157,16 @@ class _UsernameInput extends StatelessWidget { return BlocBuilder( buildWhen: (previous, current) => previous.username != current.username, builder: (context, state) { - return Container( - padding: const EdgeInsets.all(4), - decoration: const BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(12)), - color: gainsborough, - ), - child: TextField( - key: const Key('loginForm_usernameInput_textField'), - keyboardType: TextInputType.text, + return TextFieldForm( onChanged: (username) => context.read().add(LoginUsernameChanged(username)), - decoration: InputDecoration( - border: InputBorder.none, - label: const Row( - children: [ - Icon( - Icons.person_outlined, - size: 16, - color: dullGray, - ), - Text( - 'Username', - style: TextStyle(color: dullGray, fontSize: 16), - ) - ], - ), - errorText: state.username.displayError != null - ? state.username.displayError == UsernameValidationError.short - ? 'User name is too short' - : null - : null, - ), - ), - ); + iconData: Icons.person_outlined, + hint: 'Username', + error: state.username.displayError != null + ? state.username.displayError == UsernameValidationError.short + ? 'User name is too short' + : null + : null); }, ); } @@ -224,68 +187,41 @@ class _PasswordInputState extends State<_PasswordInput> { return BlocBuilder( buildWhen: (previous, current) => previous.password != current.password, builder: (context, state) { - return Container( - padding: const EdgeInsets.all(4), - decoration: const BoxDecoration( - borderRadius: BorderRadius.all( - Radius.circular(12), - ), - color: gainsborough, - ), - child: TextField( - key: const Key('loginForm_passwordInput_textField'), + return TextFieldForm( keyboardType: TextInputType.visiblePassword, onChanged: (password) => context.read().add(LoginPasswordChanged(password)), + iconData: Icons.lock_outline, obscureText: isPasswordInvisible, - obscuringCharacter: '*', - enableSuggestions: false, - autocorrect: false, - decoration: InputDecoration( - border: InputBorder.none, - label: const Row( - children: [ - Icon( - Icons.lock_outline, - size: 16, - color: dullGray, - ), - Text( - 'Password', - style: TextStyle(color: dullGray, fontSize: 16), - ) - ], - ), - errorText: state.password.displayError != null - ? state.password.displayError == PasswordValidationError.short - ? 'Password is too short' - : state.password.displayError == - PasswordValidationError.long - ? 'Password is too long' - : state.password.displayError == - PasswordValidationError.unavailableSymbols - ? 'Password contains not allowed symbols' - : null - : null, - suffixIcon: Padding( - padding: const EdgeInsets.only(right: 8), - child: IconButton( - onPressed: () { - setState(() { - isPasswordInvisible = !isPasswordInvisible; - }); - }, - icon: Icon( - isPasswordInvisible - ? Icons.visibility_off_outlined - : Icons.visibility_outlined, - color: dullGray, - ), + suffix: Padding( + padding: const EdgeInsets.only(right: 8), + child: IconButton( + onPressed: () { + setState(() { + isPasswordInvisible = !isPasswordInvisible; + }); + }, + icon: Icon( + isPasswordInvisible + ? Icons.visibility_off_outlined + : Icons.visibility_outlined, + color: dullGray, + size: 20, ), ), ), - ), - ); + hint: 'Password', + error: state.password.displayError != null + ? state.password.displayError == PasswordValidationError.short + ? 'Password is too short' + : state.password.displayError == + PasswordValidationError.long + ? 'Password is too long' + : state.password.displayError == + PasswordValidationError.unavailableSymbols + ? 'Password contains not allowed symbols' + : null + : null); }, ); } @@ -297,46 +233,19 @@ class _EmailInput extends StatelessWidget { return BlocBuilder( buildWhen: (previous, current) => previous.email != current.email, builder: (context, state) { - return Container( - padding: const EdgeInsets.all(4), - decoration: const BoxDecoration( - borderRadius: BorderRadius.all( - Radius.circular(12), - ), - color: gainsborough, - ), - child: TextField( - keyboardType: TextInputType.emailAddress, + return TextFieldForm( onChanged: (email) => context.read().add(LoginEmailChanged(email)), - enableSuggestions: false, - autocorrect: false, - decoration: InputDecoration( - border: InputBorder.none, - label: const Row( - children: [ - Icon( - Icons.email_outlined, - size: 16, - color: dullGray, - ), - Padding(padding: EdgeInsets.all(4)), - Text( - 'Email', - style: TextStyle(color: dullGray, fontSize: 16), - ) - ], - ), - errorText: state.email.displayError != null - ? state.email.displayError == EmailValidationError.empty - ? 'Email is too short' - : state.email.displayError == - EmailValidationError.incorrect - ? 'The format of the email address is incorrect' - : null - : null), - ), - ); + iconData: Icons.email_outlined, + keyboardType: TextInputType.emailAddress, + hint: 'Email', + error: state.email.displayError != null + ? state.email.displayError == EmailValidationError.empty + ? 'Email is too short' + : state.email.displayError == EmailValidationError.incorrect + ? 'The format of the email address is incorrect' + : null + : null); }, ); } @@ -374,7 +283,7 @@ class _LoginButton extends StatelessWidget { isSignInValid || isSignUpValid ? white : gainsborough), shape: WidgetStatePropertyAll( RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12.0), + borderRadius: BorderRadius.circular(22), ), ), ), @@ -386,7 +295,8 @@ class _LoginButton extends StatelessWidget { ); } : null, - child: Text(isSignup ? 'Create account' : 'Login'), + child: Text(isSignup ? 'Create account' : 'Login', + style: const TextStyle(fontSize: 16)), ), ); }, diff --git a/sama_chat_client/lib/src/shared/ui/view/text_field_form.dart b/sama_chat_client/lib/src/shared/ui/view/text_field_form.dart new file mode 100644 index 00000000..303f10ed --- /dev/null +++ b/sama_chat_client/lib/src/shared/ui/view/text_field_form.dart @@ -0,0 +1,64 @@ +import 'package:flutter/material.dart'; + +import '../colors.dart'; + +class TextFieldForm extends StatelessWidget { + final ValueChanged? onChanged; + final IconData iconData; + final String hint; + final TextInputType? keyboardType; + final String? error; + final Widget? suffix; + final bool? obscureText; + + const TextFieldForm( + {super.key, + required this.onChanged, + required this.iconData, + required this.hint, + this.keyboardType, + this.error, + this.suffix, + this.obscureText}); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.all(4), + height: 55, + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(28)), + color: gainsborough, + ), + child: TextField( + keyboardType: keyboardType, + style: const TextStyle(fontSize: 17), + autocorrect: false, + enableSuggestions: false, + obscuringCharacter: '*', + obscureText: obscureText ?? false, + onChanged: (username) => onChanged, + decoration: InputDecoration( + border: InputBorder.none, + contentPadding: const EdgeInsets.only(left: 12.0), + isDense: true, + label: Row( + spacing: 10, + children: [ + Icon( + iconData, + size: 26, + color: dullGray, + ), + Text( + hint, + style: const TextStyle(color: dullGray, fontSize: 16), + ) + ], + ), + errorText: error, + suffixIcon: suffix ?? const SizedBox(), + ), + )); + } +} From 4632163789e3e041d69a5f08680471f983d6f687 Mon Sep 17 00:00:00 2001 From: Magellan Date: Tue, 16 Dec 2025 19:51:49 +0200 Subject: [PATCH 12/17] add expending to reset password --- .../src/features/login/view/login_form.dart | 76 ++---- .../view/reset_password_page.dart | 26 +- .../reset_password/view/send_email_form.dart | 128 ++++------ .../reset_password/view/send_otp_form.dart | 123 +++++---- .../view/send_reset_password_form.dart | 240 ++++++------------ ...field_form.dart => text_button_forms.dart} | 52 +++- 6 files changed, 276 insertions(+), 369 deletions(-) rename sama_chat_client/lib/src/shared/ui/view/{text_field_form.dart => text_button_forms.dart} (53%) diff --git a/sama_chat_client/lib/src/features/login/view/login_form.dart b/sama_chat_client/lib/src/features/login/view/login_form.dart index de5524a5..6f919739 100644 --- a/sama_chat_client/lib/src/features/login/view/login_form.dart +++ b/sama_chat_client/lib/src/features/login/view/login_form.dart @@ -6,7 +6,7 @@ import 'package:go_router/go_router.dart'; import '../../../navigation/constants.dart'; import '../../../shared/ui/colors.dart'; -import '../../../shared/ui/view/text_field_form.dart'; +import '../../../shared/ui/view/text_button_forms.dart'; import '../bloc/login_bloc.dart'; import '../models/models.dart'; @@ -193,21 +193,18 @@ class _PasswordInputState extends State<_PasswordInput> { context.read().add(LoginPasswordChanged(password)), iconData: Icons.lock_outline, obscureText: isPasswordInvisible, - suffix: Padding( - padding: const EdgeInsets.only(right: 8), - child: IconButton( - onPressed: () { - setState(() { - isPasswordInvisible = !isPasswordInvisible; - }); - }, - icon: Icon( - isPasswordInvisible - ? Icons.visibility_off_outlined - : Icons.visibility_outlined, - color: dullGray, - size: 20, - ), + suffix: IconButton( + onPressed: () { + setState(() { + isPasswordInvisible = !isPasswordInvisible; + }); + }, + icon: Icon( + isPasswordInvisible + ? Icons.visibility_off_outlined + : Icons.visibility_outlined, + color: dullGray, + size: 22, ), ), hint: 'Password', @@ -265,40 +262,19 @@ class _LoginButton extends StatelessWidget { var isSignUpValid = state.isValidSignup && isSignup; return state.status.isInProgress ? const CircularProgressIndicator() - : Container( - decoration: const BoxDecoration( - borderRadius: BorderRadius.all( - Radius.circular(12), - ), - ), - height: 46, - width: double.infinity, - child: FilledButton( - style: ButtonStyle( - backgroundColor: WidgetStatePropertyAll( - isSignInValid || isSignUpValid - ? slateBlue - : whiteAluminum), - foregroundColor: WidgetStatePropertyAll( - isSignInValid || isSignUpValid ? white : gainsborough), - shape: WidgetStatePropertyAll( - RoundedRectangleBorder( - borderRadius: BorderRadius.circular(22), - ), - ), - ), - key: const Key('loginForm_continue_raisedButton'), - onPressed: isSignInValid || isSignUpValid - ? () { - context.read().add( - LoginSubmitted(isSignup, isSighupWithLogin), - ); - } - : null, - child: Text(isSignup ? 'Create account' : 'Login', - style: const TextStyle(fontSize: 16)), - ), - ); + : ButtonForm( + onPressed: isSignInValid || isSignUpValid + ? () { + context.read().add( + LoginSubmitted(isSignup, isSighupWithLogin), + ); + } + : null, + backgroundColor: WidgetStatePropertyAll( + isSignInValid || isSignUpValid ? slateBlue : whiteAluminum), + foregroundColor: WidgetStatePropertyAll( + isSignInValid || isSignUpValid ? white : gainsborough), + hint: isSignup ? 'Create account' : 'Login'); }, ); } diff --git a/sama_chat_client/lib/src/features/reset_password/view/reset_password_page.dart b/sama_chat_client/lib/src/features/reset_password/view/reset_password_page.dart index 9a862ff5..a4c6392b 100644 --- a/sama_chat_client/lib/src/features/reset_password/view/reset_password_page.dart +++ b/sama_chat_client/lib/src/features/reset_password/view/reset_password_page.dart @@ -54,16 +54,24 @@ class ResetPasswordPage extends StatelessWidget { context.read().add(const OnBackCurrentForm()); } }), - body: Container( - alignment: Alignment.topCenter, - padding: const EdgeInsets.symmetric(horizontal: 28), - child: ConstrainedBox( - constraints: const BoxConstraints(maxWidth: 400), - child: SingleChildScrollView( - child: forms[state.currentForm], + body: LayoutBuilder(builder: (context, constraint) { + return Container( + alignment: Alignment.topCenter, + padding: const EdgeInsets.symmetric(horizontal: 28), + child: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 400), + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: + BoxConstraints(minHeight: constraint.maxHeight), + child: IntrinsicHeight( + child: forms[state.currentForm], + ), + ), + ), ), - ), - ), + ); + }), bottomNavigationBar: SafeArea( child: SizedBox( height: 18, diff --git a/sama_chat_client/lib/src/features/reset_password/view/send_email_form.dart b/sama_chat_client/lib/src/features/reset_password/view/send_email_form.dart index 6bc62ccb..40b7a2d3 100644 --- a/sama_chat_client/lib/src/features/reset_password/view/send_email_form.dart +++ b/sama_chat_client/lib/src/features/reset_password/view/send_email_form.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:formz/formz.dart'; +import '../../../shared/ui/view/text_button_forms.dart'; import '../../../shared/utils/date_utils.dart'; import '../bloc/timer_bloc/timer_bloc.dart'; import '../models/models.dart'; @@ -37,7 +38,9 @@ class SendEmailForm extends StatelessWidget { const Padding(padding: EdgeInsets.all(8)), _EmailInput(), const Padding(padding: EdgeInsets.all(8)), - _ContinueButton() + const Spacer(), + _ContinueButton(), + const Padding(padding: EdgeInsets.all(16)) ], ), ); @@ -50,46 +53,19 @@ class _EmailInput extends StatelessWidget { return BlocBuilder( buildWhen: (previous, current) => previous.email != current.email, builder: (context, state) { - return Container( - padding: const EdgeInsets.all(8), - decoration: const BoxDecoration( - borderRadius: BorderRadius.all( - Radius.circular(12), - ), - color: gainsborough, - ), - child: TextField( - keyboardType: TextInputType.emailAddress, + return TextFieldForm( onChanged: (email) => context.read().add(EmailChanged(email)), - enableSuggestions: false, - autocorrect: false, - decoration: InputDecoration( - border: InputBorder.none, - label: const Row( - children: [ - Icon( - Icons.email_outlined, - size: 16, - color: dullGray, - ), - Padding(padding: EdgeInsets.all(4)), - Text( - 'Email', - style: TextStyle(color: dullGray, fontSize: 16), - ) - ], - ), - errorText: state.email.displayError != null - ? state.email.displayError == EmailValidationError.empty - ? 'Email is too short' - : state.email.displayError == - EmailValidationError.incorrect - ? 'The format of the email address is incorrect' - : null - : null), - ), - ); + iconData: Icons.email_outlined, + keyboardType: TextInputType.emailAddress, + hint: 'Email', + error: state.email.displayError != null + ? state.email.displayError == EmailValidationError.empty + ? 'Email is too short' + : state.email.displayError == EmailValidationError.incorrect + ? 'The format of the email address is incorrect' + : null + : null); }, ); } @@ -107,53 +83,37 @@ class _ContinueButton extends StatelessWidget { builder: (context, state) { return state.status.isInProgress ? const CircularProgressIndicator() - : Container( - decoration: const BoxDecoration( - borderRadius: BorderRadius.all( - Radius.circular(12), - ), - ), - height: 46, - width: double.infinity, - child: FilledButton( - style: ButtonStyle( - backgroundColor: WidgetStatePropertyAll( - state.isEmailValid ? slateBlue : whiteAluminum), - foregroundColor: WidgetStatePropertyAll( - state.isEmailValid ? white : gainsborough), - shape: WidgetStatePropertyAll( - RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12.0), - ), - ), - ), - onPressed: state.isEmailValid - ? () { - hideKeyboard(); - var time = context.read().state.duration; - if (time != 0) { - ScaffoldMessenger.of(context) - ..hideCurrentSnackBar() - ..showSnackBar( - SnackBar( - content: ValueListenableBuilder( - valueListenable: snackBarText, - builder: (context, currentText, child) { - return Text(currentText, - textAlign: TextAlign.center); - }, - ), + : ButtonForm( + onPressed: state.isEmailValid + ? () { + hideKeyboard(); + var time = context.read().state.duration; + if (time != 0) { + ScaffoldMessenger.of(context) + ..hideCurrentSnackBar() + ..showSnackBar( + SnackBar( + content: ValueListenableBuilder( + valueListenable: snackBarText, + builder: (context, currentText, child) { + return Text(currentText, + textAlign: TextAlign.center); + }, ), - ); - } else { - context - .read() - .add(const EmailSubmitted()); - } + ), + ); + } else { + context + .read() + .add(const EmailSubmitted()); } - : null, - child: const Text('Continue'), - )); + } + : null, + backgroundColor: WidgetStatePropertyAll( + state.isEmailValid ? slateBlue : whiteAluminum), + foregroundColor: WidgetStatePropertyAll( + state.isEmailValid ? white : gainsborough), + hint: 'Continue'); }, )); } diff --git a/sama_chat_client/lib/src/features/reset_password/view/send_otp_form.dart b/sama_chat_client/lib/src/features/reset_password/view/send_otp_form.dart index d25f6e0d..8413852c 100644 --- a/sama_chat_client/lib/src/features/reset_password/view/send_otp_form.dart +++ b/sama_chat_client/lib/src/features/reset_password/view/send_otp_form.dart @@ -4,6 +4,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:formz/formz.dart'; import '../../../shared/ui/colors.dart'; +import '../../../shared/ui/view/text_button_forms.dart'; import '../../../shared/utils/date_utils.dart'; import '../../../shared/utils/screen_factor.dart'; import '../bloc/reset_password_bloc.dart'; @@ -38,6 +39,7 @@ class SendOtpForm extends StatelessWidget { const Padding(padding: EdgeInsets.all(8)), const OtpInput(), const Padding(padding: EdgeInsets.all(8)), + const Spacer(), _ContinueButton(), const Padding(padding: EdgeInsets.all(8)), const Text('Didn\'t receive the email?'), @@ -67,6 +69,7 @@ class SendOtpForm extends StatelessWidget { ], ), ), + const Padding(padding: EdgeInsets.all(16)) ], ); })); @@ -80,37 +83,20 @@ class _ContinueButton extends StatelessWidget { builder: (context, state) { return state.status.isInProgress ? const CircularProgressIndicator() - : Container( - decoration: const BoxDecoration( - borderRadius: BorderRadius.all( - Radius.circular(12), - ), - ), - height: 46, - width: double.infinity, - child: FilledButton( - style: ButtonStyle( - backgroundColor: WidgetStatePropertyAll( - state.isOTPValid ? slateBlue : whiteAluminum), - foregroundColor: WidgetStatePropertyAll( - state.isOTPValid ? white : gainsborough), - shape: WidgetStatePropertyAll( - RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12.0), - ), - ), - ), - onPressed: state.isOTPValid - ? () { - hideKeyboard(); - context - .read() - .add(const OtpSubmitted()); - } - : null, - child: const Text('Continue'), - ), - ); + : ButtonForm( + onPressed: state.isOTPValid + ? () { + hideKeyboard(); + context + .read() + .add(const OtpSubmitted()); + } + : null, + backgroundColor: WidgetStatePropertyAll( + state.isOTPValid ? slateBlue : whiteAluminum), + foregroundColor: WidgetStatePropertyAll( + state.isOTPValid ? white : gainsborough), + hint: 'Continue'); }, ); } @@ -160,43 +146,50 @@ class OtpInputState extends State { } Widget digitField(int index) { - return SizedBox( - width: 45, - height: 45, - child: TextField( - style: const TextStyle(fontSize: 22), - controller: _controllers[index], - focusNode: _focusNodes[index], - keyboardType: TextInputType.number, - textAlign: TextAlign.center, - autofocus: true, - onChanged: (value) { - if (value.characters.length == OtpInput.otpSize) { - for (final (index, controller) in _controllers.indexed) { - controller.text = value.characters.elementAt(index); - if (index < 5) { - FocusScope.of(context).requestFocus(_focusNodes[index + 1]); + return Material( + elevation: 8.0, + borderRadius: BorderRadius.circular(5.0), + shadowColor: black.withValues(alpha: 0.6), + child: SizedBox( + width: 45, + height: 45, + child: TextField( + style: const TextStyle(fontSize: 22), + controller: _controllers[index], + focusNode: _focusNodes[index], + keyboardType: TextInputType.number, + textAlign: TextAlign.center, + autofocus: true, + onChanged: (value) { + if (value.characters.length == OtpInput.otpSize) { + for (final (index, controller) in _controllers.indexed) { + controller.text = value.characters.elementAt(index); + if (index < 5) { + FocusScope.of(context).requestFocus(_focusNodes[index + 1]); + } + context + .read() + .add(OtpChanged(index, value.characters.elementAt(index))); } - context - .read() - .add(OtpChanged(index, value.characters.elementAt(index))); + return; } - return; - } - if (value.isNotEmpty && index < 5) { - FocusScope.of(context).requestFocus(_focusNodes[index + 1]); - } else if (value.isEmpty && index > 0) { - FocusScope.of(context).requestFocus(_focusNodes[index - 1]); - } - context.read().add(OtpChanged(index, value)); - }, - decoration: const InputDecoration( - counterText: '', - border: OutlineInputBorder(), - contentPadding: EdgeInsets.only( - bottom: 10, - )), + if (value.isNotEmpty && index < 5) { + FocusScope.of(context).requestFocus(_focusNodes[index + 1]); + } else if (value.isEmpty && index > 0) { + FocusScope.of(context).requestFocus(_focusNodes[index - 1]); + } + context.read().add(OtpChanged(index, value)); + }, + decoration: const InputDecoration( + counterText: '', + border: OutlineInputBorder( + borderSide: BorderSide.none, + ), + contentPadding: EdgeInsets.only( + bottom: 10, + )), + ), ), ); } diff --git a/sama_chat_client/lib/src/features/reset_password/view/send_reset_password_form.dart b/sama_chat_client/lib/src/features/reset_password/view/send_reset_password_form.dart index 96967ca8..9d5b39e2 100644 --- a/sama_chat_client/lib/src/features/reset_password/view/send_reset_password_form.dart +++ b/sama_chat_client/lib/src/features/reset_password/view/send_reset_password_form.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:formz/formz.dart'; -import '../bloc/timer_bloc/timer_bloc.dart'; +import '../../../shared/ui/view/text_button_forms.dart'; import '../models/models.dart'; import '../../../shared/ui/colors.dart'; @@ -32,20 +32,19 @@ class SendResetPasswordForm extends StatelessWidget { Navigator.popUntil(context, (route) => route.isFirst); } }, - child: Align( - alignment: const Alignment(0, -1 / 3), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - const Text('Set new password'), - const Padding(padding: EdgeInsets.all(8)), - _PasswordInput(), - const Padding(padding: EdgeInsets.all(8)), - _ConfirmPasswordInput(), - const Padding(padding: EdgeInsets.all(8)), - _ContinueButton() - ], - ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const Text('Set new password'), + const Padding(padding: EdgeInsets.all(8)), + _PasswordInput(), + const Padding(padding: EdgeInsets.all(8)), + _ConfirmPasswordInput(), + const Padding(padding: EdgeInsets.all(8)), + const Spacer(), + _ContinueButton(), + const Padding(padding: EdgeInsets.all(16)) + ], ), ); } @@ -66,67 +65,38 @@ class _PasswordInputState extends State<_PasswordInput> { return BlocBuilder( buildWhen: (previous, current) => previous.password != current.password, builder: (context, state) { - return Container( - padding: const EdgeInsets.all(8), - decoration: const BoxDecoration( - borderRadius: BorderRadius.all( - Radius.circular(12), - ), - color: gainsborough, - ), - child: TextField( + return TextFieldForm( keyboardType: TextInputType.visiblePassword, onChanged: (psw) => context.read().add(PasswordChanged(psw)), + iconData: Icons.lock_outline, obscureText: isPasswordInvisible, - obscuringCharacter: '*', - enableSuggestions: false, - autocorrect: false, - decoration: InputDecoration( - border: InputBorder.none, - label: const Row( - children: [ - Icon( - Icons.lock_outline, - size: 16, - color: dullGray, - ), - Text( - 'Password', - style: TextStyle(color: dullGray, fontSize: 16), - ) - ], - ), - errorText: state.password.displayError != null - ? state.password.displayError == PasswordValidationError.short - ? 'Password is too short' - : state.password.displayError == - PasswordValidationError.long - ? 'Password is too long' - : state.password.displayError == - PasswordValidationError.unavailableSymbols - ? 'Password contains not allowed symbols' - : null - : null, - suffixIcon: Padding( - padding: const EdgeInsets.only(right: 8), - child: IconButton( - onPressed: () { - setState(() { - isPasswordInvisible = !isPasswordInvisible; - }); - }, - icon: Icon( - isPasswordInvisible - ? Icons.visibility_off_outlined - : Icons.visibility_outlined, - color: dullGray, - ), - ), + suffix: IconButton( + onPressed: () { + setState(() { + isPasswordInvisible = !isPasswordInvisible; + }); + }, + icon: Icon( + isPasswordInvisible + ? Icons.visibility_off_outlined + : Icons.visibility_outlined, + size: 22, + color: dullGray, ), ), - ), - ); + hint: 'Password', + error: state.password.displayError != null + ? state.password.displayError == PasswordValidationError.short + ? 'Password is too short' + : state.password.displayError == + PasswordValidationError.long + ? 'Password is too long' + : state.password.displayError == + PasswordValidationError.unavailableSymbols + ? 'Password contains not allowed symbols' + : null + : null); }, ); } @@ -148,63 +118,34 @@ class _ConfirmPasswordInputState extends State<_ConfirmPasswordInput> { buildWhen: (previous, current) => previous.confirmPassword != current.confirmPassword, builder: (context, state) { - return Container( - padding: const EdgeInsets.all(8), - decoration: const BoxDecoration( - borderRadius: BorderRadius.all( - Radius.circular(12), - ), - color: gainsborough, - ), - child: TextField( - keyboardType: TextInputType.visiblePassword, - onChanged: (psw) => context - .read() - .add(ConfirmPasswordChanged(psw)), - obscureText: isPasswordInvisible, - obscuringCharacter: '*', - enableSuggestions: false, - autocorrect: false, - decoration: InputDecoration( - border: InputBorder.none, - label: const Row( - children: [ - Icon( - Icons.lock_outline, - size: 16, - color: dullGray, - ), - Text( - 'Confirm password', - style: TextStyle(color: dullGray, fontSize: 16), - ) - ], - ), - errorText: state.confirmPassword.displayError != null - ? state.confirmPassword.displayError == - ConfirmPasswordValidationError.empty - ? 'Password is too short' - : state.confirmPassword.displayError == - ConfirmPasswordValidationError.notMatching - ? 'Passwords do NOT match' - : null - : null, - suffixIcon: Padding( - padding: const EdgeInsets.only(right: 8), - child: IconButton( - onPressed: () { - setState(() { - isPasswordInvisible = !isPasswordInvisible; - }); - }, - icon: Icon( - isPasswordInvisible - ? Icons.visibility_off_outlined - : Icons.visibility_outlined, - color: dullGray, - ), - ), - ), + return TextFieldForm( + keyboardType: TextInputType.visiblePassword, + onChanged: (psw) => context + .read() + .add(ConfirmPasswordChanged(psw)), + iconData: Icons.lock_outline, + hint: 'Confirm password', + error: state.confirmPassword.displayError != null + ? state.confirmPassword.displayError == + ConfirmPasswordValidationError.empty + ? 'Password is too short' + : state.confirmPassword.displayError == + ConfirmPasswordValidationError.notMatching + ? 'Passwords do NOT match' + : null + : null, + suffix: IconButton( + onPressed: () { + setState(() { + isPasswordInvisible = !isPasswordInvisible; + }); + }, + icon: Icon( + isPasswordInvisible + ? Icons.visibility_off_outlined + : Icons.visibility_outlined, + size: 22, + color: dullGray, ), ), ); @@ -220,37 +161,20 @@ class _ContinueButton extends StatelessWidget { builder: (context, state) { return state.status.isInProgress ? const CircularProgressIndicator() - : Container( - decoration: const BoxDecoration( - borderRadius: BorderRadius.all( - Radius.circular(12), - ), - ), - height: 46, - width: double.infinity, - child: FilledButton( - style: ButtonStyle( - backgroundColor: WidgetStatePropertyAll( - state.isPasswordValid ? slateBlue : whiteAluminum), - foregroundColor: WidgetStatePropertyAll( - state.isPasswordValid ? white : gainsborough), - shape: WidgetStatePropertyAll( - RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12.0), - ), - ), - ), - onPressed: state.isPasswordValid - ? () { - hideKeyboard(); - context - .read() - .add(const PasswordSubmitted()); - } - : null, - child: const Text('Continue'), - ), - ); + : ButtonForm( + onPressed: state.isPasswordValid + ? () { + hideKeyboard(); + context + .read() + .add(const PasswordSubmitted()); + } + : null, + backgroundColor: WidgetStatePropertyAll( + state.isPasswordValid ? slateBlue : whiteAluminum), + foregroundColor: WidgetStatePropertyAll( + state.isPasswordValid ? white : gainsborough), + hint: 'Continue'); }, ); } diff --git a/sama_chat_client/lib/src/shared/ui/view/text_field_form.dart b/sama_chat_client/lib/src/shared/ui/view/text_button_forms.dart similarity index 53% rename from sama_chat_client/lib/src/shared/ui/view/text_field_form.dart rename to sama_chat_client/lib/src/shared/ui/view/text_button_forms.dart index 303f10ed..47822a48 100644 --- a/sama_chat_client/lib/src/shared/ui/view/text_field_form.dart +++ b/sama_chat_client/lib/src/shared/ui/view/text_button_forms.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; import '../colors.dart'; class TextFieldForm extends StatelessWidget { - final ValueChanged? onChanged; + final ValueChanged onChanged; final IconData iconData; final String hint; final TextInputType? keyboardType; @@ -37,9 +37,12 @@ class TextFieldForm extends StatelessWidget { enableSuggestions: false, obscuringCharacter: '*', obscureText: obscureText ?? false, - onChanged: (username) => onChanged, + onChanged: (username) => onChanged(username), decoration: InputDecoration( border: InputBorder.none, + floatingLabelBehavior: error != null + ? FloatingLabelBehavior.never + : FloatingLabelBehavior.auto, contentPadding: const EdgeInsets.only(left: 12.0), isDense: true, label: Row( @@ -57,8 +60,51 @@ class TextFieldForm extends StatelessWidget { ], ), errorText: error, - suffixIcon: suffix ?? const SizedBox(), + suffixIcon: Padding( + padding: const EdgeInsets.only(right: 8), + child: suffix ?? const SizedBox(), + ), ), )); } } + +class ButtonForm extends StatelessWidget { + final VoidCallback? onPressed; + final WidgetStateProperty? backgroundColor; + final WidgetStateProperty? foregroundColor; + final String hint; + + const ButtonForm( + {super.key, + required this.onPressed, + required this.backgroundColor, + required this.foregroundColor, + required this.hint}); + + @override + Widget build(BuildContext context) { + return Container( + decoration: const BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(12), + ), + ), + height: 46, + width: double.infinity, + child: FilledButton( + style: ButtonStyle( + backgroundColor: backgroundColor, + foregroundColor: foregroundColor, + shape: WidgetStatePropertyAll( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(22), + ), + ), + ), + onPressed: onPressed, + child: Text(hint), + ), + ); + } +} From 9e934304e7d1561af408170632ece18a00e10b2b Mon Sep 17 00:00:00 2001 From: Magellan Date: Fri, 19 Dec 2025 22:34:26 +0200 Subject: [PATCH 13/17] add fresh icons to chat list --- .../view/conversations_page.dart | 26 +++++-------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/sama_chat_client/lib/src/features/conversations_list/view/conversations_page.dart b/sama_chat_client/lib/src/features/conversations_list/view/conversations_page.dart index 04da0742..86333a6c 100644 --- a/sama_chat_client/lib/src/features/conversations_list/view/conversations_page.dart +++ b/sama_chat_client/lib/src/features/conversations_list/view/conversations_page.dart @@ -46,22 +46,7 @@ class HomePage extends StatelessWidget { } }, child: const ConversationsList(), - ), - floatingActionButton: state.status == SharingIntentStatus.processing - ? null - : ConnectionChecker( - child: FloatingActionButton( - // fix error https://github.com/flutter/flutter/issues/115358 - heroTag: null, - child: const Padding( - padding: EdgeInsets.only(top: 4.0), - child: Icon(Icons.add_comment_outlined, size: 32.0), - ), - onPressed: () { - context.push(groupCreateScreenPath); - }, - ), - )); + )); }); } } @@ -104,8 +89,8 @@ class ChatAppBar extends StatelessWidget implements PreferredSizeWidget { leading: Align( alignment: Alignment.centerRight, child: IconButton( - icon: - const Icon(Icons.person_outline, color: lightWhite, size: 32.0), + icon: const Icon(Icons.account_circle_outlined, + color: lightWhite, size: 32.0), tooltip: 'Profile', onPressed: () { context.push(profilePath); @@ -119,7 +104,7 @@ class ChatAppBar extends StatelessWidget implements PreferredSizeWidget { child: IconButton( onPressed: () => _openSearch(context), icon: const Icon( - Icons.search, + Icons.add_circle_outline, color: white, size: 32, ), @@ -130,7 +115,8 @@ class ChatAppBar extends StatelessWidget implements PreferredSizeWidget { } _openSearch(BuildContext context) { - context.push(globalSearchPath); + context.push(groupCreateScreenPath); + // context.push(globalSearchPath); } @override From 2aed2ede63e9d5879c497c6d1b000b112c67f9dc Mon Sep 17 00:00:00 2001 From: Magellan Date: Tue, 23 Dec 2025 19:28:25 +0200 Subject: [PATCH 14/17] update avatar view --- .../lib/src/shared/ui/view/user_forms.dart | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/sama_chat_client/lib/src/shared/ui/view/user_forms.dart b/sama_chat_client/lib/src/shared/ui/view/user_forms.dart index ae63b113..ba19429e 100644 --- a/sama_chat_client/lib/src/shared/ui/view/user_forms.dart +++ b/sama_chat_client/lib/src/shared/ui/view/user_forms.dart @@ -14,25 +14,26 @@ class AvatarForm extends StatelessWidget { return Container( decoration: BoxDecoration( color: black, - borderRadius: BorderRadius.circular(5.0), + shape: BoxShape.circle, + border: Border.all(color: white, width: 2), ), - padding: const EdgeInsets.all(4.0), height: 85.0, width: 85.0, child: Center(child: () { if (avatar == null || avatar!.isEmpty) { return _defaultIcon(); } else { - return Image.network( + return ClipOval( + child: Image.network( avatar!, - height: 75.0, - width: 75.0, + height: 85.0, + width: 85.0, fit: BoxFit.cover, errorBuilder: (BuildContext context, Object exception, StackTrace? stackTrace) { return _defaultIcon(); }, - ); + )); } }())); } From 7613aa31882c7988b8f37f3f7e8a4862d1ade56b Mon Sep 17 00:00:00 2001 From: Magellan Date: Tue, 23 Dec 2025 23:09:32 +0200 Subject: [PATCH 15/17] update profile card --- .../src/features/profile/view/profile_form.dart | 2 +- .../lib/src/shared/ui/view/user_forms.dart | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/sama_chat_client/lib/src/features/profile/view/profile_form.dart b/sama_chat_client/lib/src/features/profile/view/profile_form.dart index 0302248a..8ef42cad 100644 --- a/sama_chat_client/lib/src/features/profile/view/profile_form.dart +++ b/sama_chat_client/lib/src/features/profile/view/profile_form.dart @@ -185,7 +185,7 @@ class _UsernameForm extends StatelessWidget { } class _PhoneForm extends StatelessWidget { - const _PhoneForm({super.key}); + const _PhoneForm(); @override Widget build(BuildContext context) { diff --git a/sama_chat_client/lib/src/shared/ui/view/user_forms.dart b/sama_chat_client/lib/src/shared/ui/view/user_forms.dart index ba19429e..69ef2450 100644 --- a/sama_chat_client/lib/src/shared/ui/view/user_forms.dart +++ b/sama_chat_client/lib/src/shared/ui/view/user_forms.dart @@ -16,6 +16,14 @@ class AvatarForm extends StatelessWidget { color: black, shape: BoxShape.circle, border: Border.all(color: white, width: 2), + boxShadow: [ + BoxShadow( + color: black.withValues(alpha: 0.5), + spreadRadius: 3, + blurRadius: 7, + offset: const Offset(0, 3), // Controls the shadow's position + ), + ], ), height: 85.0, width: 85.0, @@ -91,19 +99,19 @@ class UserPhoneForm extends StatelessWidget { return Ink( padding: const EdgeInsets.all(8), decoration: BoxDecoration( - color: lightWhite, + color: white, border: Border.all( color: lightWhite, ), - borderRadius: BorderRadius.circular(10), + borderRadius: BorderRadius.circular(20), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Row( - crossAxisAlignment: CrossAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.center, children: [ - Icon(Icons.local_phone_outlined, color: dullGray, size: 25), + Icon(Icons.local_phone_outlined, color: dullGray, size: 26), Text( ' Mobile phone', style: TextStyle(fontWeight: FontWeight.w300), From f3ab5c6f407469a1581ad5318b25532c2c63ff4d Mon Sep 17 00:00:00 2001 From: Magellan Date: Mon, 5 Jan 2026 19:47:46 +0200 Subject: [PATCH 16/17] add card to profile --- .../view/conversations_page.dart | 4 +- .../features/profile/view/profile_form.dart | 145 +++++++++--------- .../lib/src/shared/ui/colors.dart | 1 + .../lib/src/shared/ui/view/user_forms.dart | 4 +- 4 files changed, 81 insertions(+), 73 deletions(-) diff --git a/sama_chat_client/lib/src/features/conversations_list/view/conversations_page.dart b/sama_chat_client/lib/src/features/conversations_list/view/conversations_page.dart index 86333a6c..ab9a2c57 100644 --- a/sama_chat_client/lib/src/features/conversations_list/view/conversations_page.dart +++ b/sama_chat_client/lib/src/features/conversations_list/view/conversations_page.dart @@ -104,8 +104,8 @@ class ChatAppBar extends StatelessWidget implements PreferredSizeWidget { child: IconButton( onPressed: () => _openSearch(context), icon: const Icon( - Icons.add_circle_outline, - color: white, + Icons.edit_note_outlined, + color: lightWhite, size: 32, ), ), diff --git a/sama_chat_client/lib/src/features/profile/view/profile_form.dart b/sama_chat_client/lib/src/features/profile/view/profile_form.dart index 8ef42cad..3da03f18 100644 --- a/sama_chat_client/lib/src/features/profile/view/profile_form.dart +++ b/sama_chat_client/lib/src/features/profile/view/profile_form.dart @@ -44,19 +44,18 @@ class AvatarNameTile extends StatelessWidget { @override Widget build(BuildContext context) { - return ListTile( + return IntrinsicWidth( + child: ListTile( titleAlignment: ListTileTitleAlignment.top, - title: Center( - child: Padding( - padding: const EdgeInsets.only(top: 8), - child: _UserAvatar(), - ), + title: Padding( + padding: const EdgeInsets.only(top: 8), + child: _UserAvatar(), ), subtitle: Padding( padding: const EdgeInsets.only(bottom: 4), child: _UserFullName(), ), - ); + )); } } @@ -72,20 +71,32 @@ class ProfileCard extends StatelessWidget { child: Card( child: Padding( padding: EdgeInsets.all(15), - child: Column( - mainAxisSize: MainAxisSize.min, + child: Stack( children: [ - ConnectionChecker(child: AvatarNameTile()), - ConnectionChecker(child: _UsernameForm()), - SizedBox(height: columnItemMargin), - ConnectionChecker(child: _PhoneForm()), - SizedBox(height: columnItemMargin), - ConnectionChecker(child: _EmailForm()), - SizedBox(height: columnItemMargin), - ConnectionChecker(child: _AccountForm()), - Expanded( - child: Align( - alignment: Alignment.bottomRight, child: _LogoutForm())) + Card( + color: paleMallow, + margin: EdgeInsets.only(top: 60), + child: Padding( + padding: EdgeInsets.only(top: 100, left: 4, right: 4), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ConnectionChecker(child: _UsernameForm()), + SizedBox(height: columnItemMargin), + ConnectionChecker(child: _PhoneForm()), + SizedBox(height: columnItemMargin), + ConnectionChecker(child: _EmailForm()), + SizedBox(height: columnItemMargin), + ConnectionChecker(child: _AccountForm()), + ], + ), + ), + ), + Align(alignment: Alignment.bottomRight, child: _LogoutForm()), + Align( + alignment: Alignment.topCenter, + child: ConnectionChecker(child: AvatarNameTile()), + ), ], ), ), @@ -122,50 +133,48 @@ class _UserFullName extends StatelessWidget { previous.userLastname != current.userLastname && current.userLastname.isPure, builder: (context, state) { - return Align( - alignment: Alignment.center, - child: TextButton( - onPressed: () { - showDialog( - context: context, - builder: (_) { - return BlocProvider.value( - value: BlocProvider.of(context), - child: const NameDialogInput(), - ); - }); - }, - style: TextButton.styleFrom( - minimumSize: Size.zero, - tapTargetSize: MaterialTapTargetSize.shrinkWrap, - alignment: Alignment.center), - child: Column(children: [ - Text( - state.userFirstname.value.isEmpty - ? "First name" - : state.userFirstname.value, - style: TextStyle( - fontSize: 22, - fontWeight: state.userFirstname.value.isEmpty - ? FontWeight.w200 - : FontWeight.bold, - color: signalBlack), - overflow: TextOverflow.ellipsis, - ), - Text( - state.userLastname.value.isEmpty - ? "Last name" - : state.userLastname.value, - style: TextStyle( - fontSize: 18, - color: signalBlack, - fontWeight: state.userLastname.value.isEmpty - ? FontWeight.w200 - : FontWeight.normal), - overflow: TextOverflow.ellipsis, - ), - ]), - )); + return TextButton( + onPressed: () { + showDialog( + context: context, + builder: (_) { + return BlocProvider.value( + value: BlocProvider.of(context), + child: const NameDialogInput(), + ); + }); + }, + style: TextButton.styleFrom( + minimumSize: Size.zero, + tapTargetSize: MaterialTapTargetSize.shrinkWrap, + alignment: Alignment.center), + child: Column(mainAxisSize: MainAxisSize.min, children: [ + Text( + state.userFirstname.value.isEmpty + ? "First name" + : state.userFirstname.value, + style: TextStyle( + fontSize: 22, + fontWeight: state.userFirstname.value.isEmpty + ? FontWeight.w200 + : FontWeight.bold, + color: signalBlack), + overflow: TextOverflow.ellipsis, + ), + Text( + state.userLastname.value.isEmpty + ? "Last name" + : state.userLastname.value, + style: TextStyle( + fontSize: 18, + color: signalBlack, + fontWeight: state.userLastname.value.isEmpty + ? FontWeight.w200 + : FontWeight.normal), + overflow: TextOverflow.ellipsis, + ), + ]), + ); }); } } @@ -325,15 +334,13 @@ class _LogoutForm extends StatelessWidget { @override Widget build(BuildContext context) { - return TextButton.icon( + return ElevatedButton.icon( onPressed: () { context.read().add(AuthenticationLogoutRequested()); }, icon: const Icon(Icons.exit_to_app_outlined, color: dullGray, size: 25), style: TextButton.styleFrom( - minimumSize: Size.zero, - tapTargetSize: MaterialTapTargetSize.shrinkWrap, - alignment: Alignment.centerLeft), + backgroundColor: paleMallow, alignment: Alignment.centerLeft), label: const Text( 'Logout', style: TextStyle(fontWeight: FontWeight.w300), @@ -451,7 +458,7 @@ class InfoDialogInput extends StatelessWidget { return AlertDialog( title: const Text('Edit personal info'), actionsPadding: const EdgeInsets.only(bottom: 8), - contentPadding: const EdgeInsets.fromLTRB(16, 16, 16, 8), + contentPadding: const EdgeInsets.fromLTRB(26, 16, 16, 8), content: Column(mainAxisSize: MainAxisSize.min, children: [ Container( padding: const EdgeInsets.all(8), diff --git a/sama_chat_client/lib/src/shared/ui/colors.dart b/sama_chat_client/lib/src/shared/ui/colors.dart index fdd9e78c..e6d520fc 100644 --- a/sama_chat_client/lib/src/shared/ui/colors.dart +++ b/sama_chat_client/lib/src/shared/ui/colors.dart @@ -11,6 +11,7 @@ const Color dullGray = Color(0xFF6D6D6D); const Color signalBlack = Color(0xFF2A2A2A); const Color blackBlue = Color(0xFF1B1B1D); const Color black = Color(0xFF000000); +const Color paleMallow = Color(0xFFE6E7F8); const Color lightMallow = Color(0xFFDBDCFC); const Color slateBlue = Color(0xFF7678E5); const Color cyan = Color(0xFF00FFFF); diff --git a/sama_chat_client/lib/src/shared/ui/view/user_forms.dart b/sama_chat_client/lib/src/shared/ui/view/user_forms.dart index 69ef2450..2d83b91e 100644 --- a/sama_chat_client/lib/src/shared/ui/view/user_forms.dart +++ b/sama_chat_client/lib/src/shared/ui/view/user_forms.dart @@ -103,7 +103,7 @@ class UserPhoneForm extends StatelessWidget { border: Border.all( color: lightWhite, ), - borderRadius: BorderRadius.circular(20), + borderRadius: BorderRadius.circular(22), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -146,7 +146,7 @@ class UserEmailForm extends StatelessWidget { border: Border.all( color: lightWhite, ), - borderRadius: BorderRadius.circular(10), + borderRadius: BorderRadius.circular(22), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, From 66758f6b07b573a640032574a7c958a9a3d82c60 Mon Sep 17 00:00:00 2001 From: Magellan Date: Fri, 9 Jan 2026 00:22:35 +0200 Subject: [PATCH 17/17] make fields more round --- sama_chat_client/lib/src/shared/ui/view/user_forms.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sama_chat_client/lib/src/shared/ui/view/user_forms.dart b/sama_chat_client/lib/src/shared/ui/view/user_forms.dart index 2d83b91e..e5f4c712 100644 --- a/sama_chat_client/lib/src/shared/ui/view/user_forms.dart +++ b/sama_chat_client/lib/src/shared/ui/view/user_forms.dart @@ -103,7 +103,7 @@ class UserPhoneForm extends StatelessWidget { border: Border.all( color: lightWhite, ), - borderRadius: BorderRadius.circular(22), + borderRadius: BorderRadius.circular(30), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -146,7 +146,7 @@ class UserEmailForm extends StatelessWidget { border: Border.all( color: lightWhite, ), - borderRadius: BorderRadius.circular(22), + borderRadius: BorderRadius.circular(30), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start,