feat(chat): bubbles

This commit is contained in:
mso7nueh
2024-06-13 17:28:53 +03:00
parent 46d374d87e
commit b52251a9d1
53 changed files with 2331 additions and 481 deletions

View File

@@ -1,7 +1,9 @@
plugins{
id 'com.android.application'
id 'kotlin-android'
plugins {
id "com.android.application"
id "kotlin-android"
id "dev.flutter.flutter-gradle-plugin"
}
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
@@ -10,11 +12,6 @@ if (localPropertiesFile.exists()) {
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
@@ -25,11 +22,18 @@ if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion flutter.compileSdkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
@@ -61,7 +65,4 @@ flutter {
source '../..'
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "androidx.multidex:multidex:2.0.1"
}
dependencies {}

View File

@@ -1,20 +1,7 @@
buildscript {
ext.kotlin_version = '1.7.20'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.2.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
jcenter()
mavenCentral()
}
}

View File

@@ -1,3 +1,3 @@
org.gradle.jvmargs=-Xmx1536M
org.gradle.jvmargs=-Xmx4G
android.useAndroidX=true
android.enableJetifier=true

View File

@@ -1,6 +1,5 @@
#Fri Jun 23 08:50:38 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip

View File

@@ -1,11 +1,26 @@
include ':app'
pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}
settings.ext.flutterSdkPath = flutterSdkPath()
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
def properties = new Properties()
includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle")
assert localPropertiesFile.exists()
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "7.3.0" apply false
id "org.jetbrains.kotlin.android" version "1.7.10" apply false
}
include ":app"

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1 +1,2 @@
extensions:
- provider: true

View File

@@ -1,6 +1,7 @@
import 'package:eatvio_app/core/token_storage.dart';
import 'package:eatvio_app/features/chat/presentation/pages/chat_screen.dart';
import 'package:eatvio_app/features/chat/presentation/pages/chat_select_screen/chat_select_screen.dart';
import 'package:eatvio_app/presentation/auth/auth_screen/auth_screen.dart';
import 'package:eatvio_app/presentation/chat/chat_screen/chat_screen.dart';
import 'package:eatvio_app/presentation/chat/chat_select_screen/chat_select_screen.dart';
import 'package:eatvio_app/presentation/diary/diary_edit_screen/diary_edit_screen.dart';
import 'package:eatvio_app/presentation/diets/diet_create_screen/diet_create_screen.dart';
import 'package:eatvio_app/presentation/diets/diet_select_screen/diet_select_screen.dart';
@@ -31,7 +32,6 @@ import 'package:eatvio_app/presentation/registration/weight_screen/weight_screen
import 'package:eatvio_app/widgets/bottom_navigation_bar_widget.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:hive_flutter/hive_flutter.dart';
class AppRouter {
static GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
@@ -44,11 +44,7 @@ class AppRouter {
path: '/auth-screen',
name: 'authScreen',
redirect: (context, state) async {
final box = await Hive.openBox('token');
final token = box.get('token');
if (token != null) {
return '/my-profile-screen';
}
if (await TokenStorage.haveTokenInStorage()) return '/my-profile-screen';
return null;
},
builder: (context, state) => AuthScreen.builder(context),
@@ -209,7 +205,7 @@ class AppRouter {
GoRoute(
path: 'chat-screen',
name: 'chatScreen',
builder: (context, state) => ChatScreen.builder(context, state.extra),
builder: (context, state) => ChatScreen(chatId: state.extra as String),
),
],
),

View File

@@ -0,0 +1,32 @@
import 'package:dio/dio.dart';
import 'package:eatvio_app/locator_service.dart';
import 'package:hive_flutter/hive_flutter.dart';
abstract class TokenStorage {
static addTokenToDioHeader(String token) {
sl<Dio>().options.headers['Authorization'] = 'Bearer $token';
}
static haveTokenInStorage() async {
final box = await Hive.openBox('token');
final token = box.get('token');
if (token == null) {
return false;
} else {
addTokenToDioHeader(token);
return true;
}
}
static getTokenFromStorage() async => await Hive.openBox('token')
..get('token');
static saveTokenInStorage(String token) async {
await Hive.openBox('token')
..put('token', token);
addTokenToDioHeader(token);
}
static removeTokenInStorage(String token) async => await Hive.openBox('token')
..delete('token');
}

View File

@@ -1,5 +1,5 @@
import 'package:hive/hive.dart';
/// https://pub.dev/packages/flutter_secure_storage TODO replace hive to secure_storage for token storage
@HiveType(typeId: 0)
class TokenModel {
@HiveField(0)

View File

@@ -0,0 +1,18 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'chat_message_model.freezed.dart';
part 'chat_message_model.g.dart';
@freezed
class ChatMessageModel with _$ChatMessageModel {
const factory ChatMessageModel({
required int id,
required String data,
@JsonKey(name: 'media_data') required List<dynamic> mediaData,
@JsonKey(name: 'author_id') required int authorId,
@JsonKey(name: 'updated_at') required String updatedAt,
}) = _ChatMessageModel;
factory ChatMessageModel.fromJson(Map<String, Object?> json) => _$ChatMessageModelFromJson(json);
}

View File

@@ -0,0 +1,257 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'chat_message_model.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
ChatMessageModel _$ChatMessageModelFromJson(Map<String, dynamic> json) {
return _ChatMessageModel.fromJson(json);
}
/// @nodoc
mixin _$ChatMessageModel {
int get id => throw _privateConstructorUsedError;
String get data => throw _privateConstructorUsedError;
@JsonKey(name: 'media_data')
List<dynamic> get mediaData => throw _privateConstructorUsedError;
@JsonKey(name: 'author_id')
int get authorId => throw _privateConstructorUsedError;
@JsonKey(name: 'updated_at')
String get updatedAt => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$ChatMessageModelCopyWith<ChatMessageModel> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $ChatMessageModelCopyWith<$Res> {
factory $ChatMessageModelCopyWith(
ChatMessageModel value, $Res Function(ChatMessageModel) then) =
_$ChatMessageModelCopyWithImpl<$Res, ChatMessageModel>;
@useResult
$Res call(
{int id,
String data,
@JsonKey(name: 'media_data') List<dynamic> mediaData,
@JsonKey(name: 'author_id') int authorId,
@JsonKey(name: 'updated_at') String updatedAt});
}
/// @nodoc
class _$ChatMessageModelCopyWithImpl<$Res, $Val extends ChatMessageModel>
implements $ChatMessageModelCopyWith<$Res> {
_$ChatMessageModelCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? data = null,
Object? mediaData = null,
Object? authorId = null,
Object? updatedAt = null,
}) {
return _then(_value.copyWith(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as int,
data: null == data
? _value.data
: data // ignore: cast_nullable_to_non_nullable
as String,
mediaData: null == mediaData
? _value.mediaData
: mediaData // ignore: cast_nullable_to_non_nullable
as List<dynamic>,
authorId: null == authorId
? _value.authorId
: authorId // ignore: cast_nullable_to_non_nullable
as int,
updatedAt: null == updatedAt
? _value.updatedAt
: updatedAt // ignore: cast_nullable_to_non_nullable
as String,
) as $Val);
}
}
/// @nodoc
abstract class _$$ChatMessageModelImplCopyWith<$Res>
implements $ChatMessageModelCopyWith<$Res> {
factory _$$ChatMessageModelImplCopyWith(_$ChatMessageModelImpl value,
$Res Function(_$ChatMessageModelImpl) then) =
__$$ChatMessageModelImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{int id,
String data,
@JsonKey(name: 'media_data') List<dynamic> mediaData,
@JsonKey(name: 'author_id') int authorId,
@JsonKey(name: 'updated_at') String updatedAt});
}
/// @nodoc
class __$$ChatMessageModelImplCopyWithImpl<$Res>
extends _$ChatMessageModelCopyWithImpl<$Res, _$ChatMessageModelImpl>
implements _$$ChatMessageModelImplCopyWith<$Res> {
__$$ChatMessageModelImplCopyWithImpl(_$ChatMessageModelImpl _value,
$Res Function(_$ChatMessageModelImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? data = null,
Object? mediaData = null,
Object? authorId = null,
Object? updatedAt = null,
}) {
return _then(_$ChatMessageModelImpl(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as int,
data: null == data
? _value.data
: data // ignore: cast_nullable_to_non_nullable
as String,
mediaData: null == mediaData
? _value._mediaData
: mediaData // ignore: cast_nullable_to_non_nullable
as List<dynamic>,
authorId: null == authorId
? _value.authorId
: authorId // ignore: cast_nullable_to_non_nullable
as int,
updatedAt: null == updatedAt
? _value.updatedAt
: updatedAt // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
/// @nodoc
@JsonSerializable()
class _$ChatMessageModelImpl implements _ChatMessageModel {
const _$ChatMessageModelImpl(
{required this.id,
required this.data,
@JsonKey(name: 'media_data') required final List<dynamic> mediaData,
@JsonKey(name: 'author_id') required this.authorId,
@JsonKey(name: 'updated_at') required this.updatedAt})
: _mediaData = mediaData;
factory _$ChatMessageModelImpl.fromJson(Map<String, dynamic> json) =>
_$$ChatMessageModelImplFromJson(json);
@override
final int id;
@override
final String data;
final List<dynamic> _mediaData;
@override
@JsonKey(name: 'media_data')
List<dynamic> get mediaData {
if (_mediaData is EqualUnmodifiableListView) return _mediaData;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_mediaData);
}
@override
@JsonKey(name: 'author_id')
final int authorId;
@override
@JsonKey(name: 'updated_at')
final String updatedAt;
@override
String toString() {
return 'ChatMessageModel(id: $id, data: $data, mediaData: $mediaData, authorId: $authorId, updatedAt: $updatedAt)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ChatMessageModelImpl &&
(identical(other.id, id) || other.id == id) &&
(identical(other.data, data) || other.data == data) &&
const DeepCollectionEquality()
.equals(other._mediaData, _mediaData) &&
(identical(other.authorId, authorId) ||
other.authorId == authorId) &&
(identical(other.updatedAt, updatedAt) ||
other.updatedAt == updatedAt));
}
@JsonKey(ignore: true)
@override
int get hashCode => Object.hash(runtimeType, id, data,
const DeepCollectionEquality().hash(_mediaData), authorId, updatedAt);
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$ChatMessageModelImplCopyWith<_$ChatMessageModelImpl> get copyWith =>
__$$ChatMessageModelImplCopyWithImpl<_$ChatMessageModelImpl>(
this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$ChatMessageModelImplToJson(
this,
);
}
}
abstract class _ChatMessageModel implements ChatMessageModel {
const factory _ChatMessageModel(
{required final int id,
required final String data,
@JsonKey(name: 'media_data') required final List<dynamic> mediaData,
@JsonKey(name: 'author_id') required final int authorId,
@JsonKey(name: 'updated_at') required final String updatedAt}) =
_$ChatMessageModelImpl;
factory _ChatMessageModel.fromJson(Map<String, dynamic> json) =
_$ChatMessageModelImpl.fromJson;
@override
int get id;
@override
String get data;
@override
@JsonKey(name: 'media_data')
List<dynamic> get mediaData;
@override
@JsonKey(name: 'author_id')
int get authorId;
@override
@JsonKey(name: 'updated_at')
String get updatedAt;
@override
@JsonKey(ignore: true)
_$$ChatMessageModelImplCopyWith<_$ChatMessageModelImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@@ -0,0 +1,27 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'chat_message_model.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_$ChatMessageModelImpl _$$ChatMessageModelImplFromJson(
Map<String, dynamic> json) =>
_$ChatMessageModelImpl(
id: (json['id'] as num).toInt(),
data: json['data'] as String,
mediaData: json['media_data'] as List<dynamic>,
authorId: (json['author_id'] as num).toInt(),
updatedAt: json['updated_at'] as String,
);
Map<String, dynamic> _$$ChatMessageModelImplToJson(
_$ChatMessageModelImpl instance) =>
<String, dynamic>{
'id': instance.id,
'data': instance.data,
'media_data': instance.mediaData,
'author_id': instance.authorId,
'updated_at': instance.updatedAt,
};

View File

@@ -0,0 +1,20 @@
import 'package:eatvio_app/features/chat/models/chat_message_model.dart';
import 'package:eatvio_app/features/chat/models/chat_room_settings_model.dart';
import 'package:eatvio_app/features/chat/models/chat_user_model.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'chat_room_model.freezed.dart';
part 'chat_room_model.g.dart';
@freezed
class ChatRoomModel with _$ChatRoomModel {
const factory ChatRoomModel({
required String id,
@JsonKey(name: 'chat_room_setting') required ChatRoomSettingsModel chatRoomSettings,
required List<ChatMessageModel> messages,
required Map<String, ChatUserModel> users,
}) = _ChatRoomModel;
factory ChatRoomModel.fromJson(Map<String, Object?> json) => _$ChatRoomModelFromJson(json);
}

View File

@@ -0,0 +1,255 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'chat_room_model.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
ChatRoomModel _$ChatRoomModelFromJson(Map<String, dynamic> json) {
return _ChatRoomModel.fromJson(json);
}
/// @nodoc
mixin _$ChatRoomModel {
String get id => throw _privateConstructorUsedError;
@JsonKey(name: 'chat_room_setting')
ChatRoomSettingsModel get chatRoomSettings =>
throw _privateConstructorUsedError;
List<ChatMessageModel> get messages => throw _privateConstructorUsedError;
Map<String, ChatUserModel> get users => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$ChatRoomModelCopyWith<ChatRoomModel> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $ChatRoomModelCopyWith<$Res> {
factory $ChatRoomModelCopyWith(
ChatRoomModel value, $Res Function(ChatRoomModel) then) =
_$ChatRoomModelCopyWithImpl<$Res, ChatRoomModel>;
@useResult
$Res call(
{String id,
@JsonKey(name: 'chat_room_setting')
ChatRoomSettingsModel chatRoomSettings,
List<ChatMessageModel> messages,
Map<String, ChatUserModel> users});
$ChatRoomSettingsModelCopyWith<$Res> get chatRoomSettings;
}
/// @nodoc
class _$ChatRoomModelCopyWithImpl<$Res, $Val extends ChatRoomModel>
implements $ChatRoomModelCopyWith<$Res> {
_$ChatRoomModelCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? chatRoomSettings = null,
Object? messages = null,
Object? users = null,
}) {
return _then(_value.copyWith(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as String,
chatRoomSettings: null == chatRoomSettings
? _value.chatRoomSettings
: chatRoomSettings // ignore: cast_nullable_to_non_nullable
as ChatRoomSettingsModel,
messages: null == messages
? _value.messages
: messages // ignore: cast_nullable_to_non_nullable
as List<ChatMessageModel>,
users: null == users
? _value.users
: users // ignore: cast_nullable_to_non_nullable
as Map<String, ChatUserModel>,
) as $Val);
}
@override
@pragma('vm:prefer-inline')
$ChatRoomSettingsModelCopyWith<$Res> get chatRoomSettings {
return $ChatRoomSettingsModelCopyWith<$Res>(_value.chatRoomSettings,
(value) {
return _then(_value.copyWith(chatRoomSettings: value) as $Val);
});
}
}
/// @nodoc
abstract class _$$ChatRoomModelImplCopyWith<$Res>
implements $ChatRoomModelCopyWith<$Res> {
factory _$$ChatRoomModelImplCopyWith(
_$ChatRoomModelImpl value, $Res Function(_$ChatRoomModelImpl) then) =
__$$ChatRoomModelImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{String id,
@JsonKey(name: 'chat_room_setting')
ChatRoomSettingsModel chatRoomSettings,
List<ChatMessageModel> messages,
Map<String, ChatUserModel> users});
@override
$ChatRoomSettingsModelCopyWith<$Res> get chatRoomSettings;
}
/// @nodoc
class __$$ChatRoomModelImplCopyWithImpl<$Res>
extends _$ChatRoomModelCopyWithImpl<$Res, _$ChatRoomModelImpl>
implements _$$ChatRoomModelImplCopyWith<$Res> {
__$$ChatRoomModelImplCopyWithImpl(
_$ChatRoomModelImpl _value, $Res Function(_$ChatRoomModelImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? chatRoomSettings = null,
Object? messages = null,
Object? users = null,
}) {
return _then(_$ChatRoomModelImpl(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as String,
chatRoomSettings: null == chatRoomSettings
? _value.chatRoomSettings
: chatRoomSettings // ignore: cast_nullable_to_non_nullable
as ChatRoomSettingsModel,
messages: null == messages
? _value._messages
: messages // ignore: cast_nullable_to_non_nullable
as List<ChatMessageModel>,
users: null == users
? _value._users
: users // ignore: cast_nullable_to_non_nullable
as Map<String, ChatUserModel>,
));
}
}
/// @nodoc
@JsonSerializable()
class _$ChatRoomModelImpl implements _ChatRoomModel {
const _$ChatRoomModelImpl(
{required this.id,
@JsonKey(name: 'chat_room_setting') required this.chatRoomSettings,
required final List<ChatMessageModel> messages,
required final Map<String, ChatUserModel> users})
: _messages = messages,
_users = users;
factory _$ChatRoomModelImpl.fromJson(Map<String, dynamic> json) =>
_$$ChatRoomModelImplFromJson(json);
@override
final String id;
@override
@JsonKey(name: 'chat_room_setting')
final ChatRoomSettingsModel chatRoomSettings;
final List<ChatMessageModel> _messages;
@override
List<ChatMessageModel> get messages {
if (_messages is EqualUnmodifiableListView) return _messages;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_messages);
}
final Map<String, ChatUserModel> _users;
@override
Map<String, ChatUserModel> get users {
if (_users is EqualUnmodifiableMapView) return _users;
// ignore: implicit_dynamic_type
return EqualUnmodifiableMapView(_users);
}
@override
String toString() {
return 'ChatRoomModel(id: $id, chatRoomSettings: $chatRoomSettings, messages: $messages, users: $users)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ChatRoomModelImpl &&
(identical(other.id, id) || other.id == id) &&
(identical(other.chatRoomSettings, chatRoomSettings) ||
other.chatRoomSettings == chatRoomSettings) &&
const DeepCollectionEquality().equals(other._messages, _messages) &&
const DeepCollectionEquality().equals(other._users, _users));
}
@JsonKey(ignore: true)
@override
int get hashCode => Object.hash(
runtimeType,
id,
chatRoomSettings,
const DeepCollectionEquality().hash(_messages),
const DeepCollectionEquality().hash(_users));
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$ChatRoomModelImplCopyWith<_$ChatRoomModelImpl> get copyWith =>
__$$ChatRoomModelImplCopyWithImpl<_$ChatRoomModelImpl>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$ChatRoomModelImplToJson(
this,
);
}
}
abstract class _ChatRoomModel implements ChatRoomModel {
const factory _ChatRoomModel(
{required final String id,
@JsonKey(name: 'chat_room_setting')
required final ChatRoomSettingsModel chatRoomSettings,
required final List<ChatMessageModel> messages,
required final Map<String, ChatUserModel> users}) = _$ChatRoomModelImpl;
factory _ChatRoomModel.fromJson(Map<String, dynamic> json) =
_$ChatRoomModelImpl.fromJson;
@override
String get id;
@override
@JsonKey(name: 'chat_room_setting')
ChatRoomSettingsModel get chatRoomSettings;
@override
List<ChatMessageModel> get messages;
@override
Map<String, ChatUserModel> get users;
@override
@JsonKey(ignore: true)
_$$ChatRoomModelImplCopyWith<_$ChatRoomModelImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@@ -0,0 +1,29 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'chat_room_model.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_$ChatRoomModelImpl _$$ChatRoomModelImplFromJson(Map<String, dynamic> json) =>
_$ChatRoomModelImpl(
id: json['id'] as String,
chatRoomSettings: ChatRoomSettingsModel.fromJson(
json['chat_room_setting'] as Map<String, dynamic>),
messages: (json['messages'] as List<dynamic>)
.map((e) => ChatMessageModel.fromJson(e as Map<String, dynamic>))
.toList(),
users: (json['users'] as Map<String, dynamic>).map(
(k, e) =>
MapEntry(k, ChatUserModel.fromJson(e as Map<String, dynamic>)),
),
);
Map<String, dynamic> _$$ChatRoomModelImplToJson(_$ChatRoomModelImpl instance) =>
<String, dynamic>{
'id': instance.id,
'chat_room_setting': instance.chatRoomSettings,
'messages': instance.messages,
'users': instance.users,
};

View File

@@ -0,0 +1,18 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'chat_room_settings_model.freezed.dart';
part 'chat_room_settings_model.g.dart';
@freezed
class ChatRoomSettingsModel with _$ChatRoomSettingsModel {
const factory ChatRoomSettingsModel({
required int id,
@JsonKey(name: 'room_name') required String roomName,
required String state,
@JsonKey(name: 'access_level') required String accessLevel,
@JsonKey(name: 'updated_at') required String updatedAt,
}) = _ChatRoomSettingsModel;
factory ChatRoomSettingsModel.fromJson(Map<String, Object?> json) => _$ChatRoomSettingsModelFromJson(json);
}

View File

@@ -0,0 +1,254 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'chat_room_settings_model.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
ChatRoomSettingsModel _$ChatRoomSettingsModelFromJson(
Map<String, dynamic> json) {
return _ChatRoomSettingsModel.fromJson(json);
}
/// @nodoc
mixin _$ChatRoomSettingsModel {
int get id => throw _privateConstructorUsedError;
@JsonKey(name: 'room_name')
String get roomName => throw _privateConstructorUsedError;
String get state => throw _privateConstructorUsedError;
@JsonKey(name: 'access_level')
String get accessLevel => throw _privateConstructorUsedError;
@JsonKey(name: 'updated_at')
String get updatedAt => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$ChatRoomSettingsModelCopyWith<ChatRoomSettingsModel> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $ChatRoomSettingsModelCopyWith<$Res> {
factory $ChatRoomSettingsModelCopyWith(ChatRoomSettingsModel value,
$Res Function(ChatRoomSettingsModel) then) =
_$ChatRoomSettingsModelCopyWithImpl<$Res, ChatRoomSettingsModel>;
@useResult
$Res call(
{int id,
@JsonKey(name: 'room_name') String roomName,
String state,
@JsonKey(name: 'access_level') String accessLevel,
@JsonKey(name: 'updated_at') String updatedAt});
}
/// @nodoc
class _$ChatRoomSettingsModelCopyWithImpl<$Res,
$Val extends ChatRoomSettingsModel>
implements $ChatRoomSettingsModelCopyWith<$Res> {
_$ChatRoomSettingsModelCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? roomName = null,
Object? state = null,
Object? accessLevel = null,
Object? updatedAt = null,
}) {
return _then(_value.copyWith(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as int,
roomName: null == roomName
? _value.roomName
: roomName // ignore: cast_nullable_to_non_nullable
as String,
state: null == state
? _value.state
: state // ignore: cast_nullable_to_non_nullable
as String,
accessLevel: null == accessLevel
? _value.accessLevel
: accessLevel // ignore: cast_nullable_to_non_nullable
as String,
updatedAt: null == updatedAt
? _value.updatedAt
: updatedAt // ignore: cast_nullable_to_non_nullable
as String,
) as $Val);
}
}
/// @nodoc
abstract class _$$ChatRoomSettingsModelImplCopyWith<$Res>
implements $ChatRoomSettingsModelCopyWith<$Res> {
factory _$$ChatRoomSettingsModelImplCopyWith(
_$ChatRoomSettingsModelImpl value,
$Res Function(_$ChatRoomSettingsModelImpl) then) =
__$$ChatRoomSettingsModelImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{int id,
@JsonKey(name: 'room_name') String roomName,
String state,
@JsonKey(name: 'access_level') String accessLevel,
@JsonKey(name: 'updated_at') String updatedAt});
}
/// @nodoc
class __$$ChatRoomSettingsModelImplCopyWithImpl<$Res>
extends _$ChatRoomSettingsModelCopyWithImpl<$Res,
_$ChatRoomSettingsModelImpl>
implements _$$ChatRoomSettingsModelImplCopyWith<$Res> {
__$$ChatRoomSettingsModelImplCopyWithImpl(_$ChatRoomSettingsModelImpl _value,
$Res Function(_$ChatRoomSettingsModelImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? roomName = null,
Object? state = null,
Object? accessLevel = null,
Object? updatedAt = null,
}) {
return _then(_$ChatRoomSettingsModelImpl(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as int,
roomName: null == roomName
? _value.roomName
: roomName // ignore: cast_nullable_to_non_nullable
as String,
state: null == state
? _value.state
: state // ignore: cast_nullable_to_non_nullable
as String,
accessLevel: null == accessLevel
? _value.accessLevel
: accessLevel // ignore: cast_nullable_to_non_nullable
as String,
updatedAt: null == updatedAt
? _value.updatedAt
: updatedAt // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
/// @nodoc
@JsonSerializable()
class _$ChatRoomSettingsModelImpl implements _ChatRoomSettingsModel {
const _$ChatRoomSettingsModelImpl(
{required this.id,
@JsonKey(name: 'room_name') required this.roomName,
required this.state,
@JsonKey(name: 'access_level') required this.accessLevel,
@JsonKey(name: 'updated_at') required this.updatedAt});
factory _$ChatRoomSettingsModelImpl.fromJson(Map<String, dynamic> json) =>
_$$ChatRoomSettingsModelImplFromJson(json);
@override
final int id;
@override
@JsonKey(name: 'room_name')
final String roomName;
@override
final String state;
@override
@JsonKey(name: 'access_level')
final String accessLevel;
@override
@JsonKey(name: 'updated_at')
final String updatedAt;
@override
String toString() {
return 'ChatRoomSettingsModel(id: $id, roomName: $roomName, state: $state, accessLevel: $accessLevel, updatedAt: $updatedAt)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ChatRoomSettingsModelImpl &&
(identical(other.id, id) || other.id == id) &&
(identical(other.roomName, roomName) ||
other.roomName == roomName) &&
(identical(other.state, state) || other.state == state) &&
(identical(other.accessLevel, accessLevel) ||
other.accessLevel == accessLevel) &&
(identical(other.updatedAt, updatedAt) ||
other.updatedAt == updatedAt));
}
@JsonKey(ignore: true)
@override
int get hashCode =>
Object.hash(runtimeType, id, roomName, state, accessLevel, updatedAt);
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$ChatRoomSettingsModelImplCopyWith<_$ChatRoomSettingsModelImpl>
get copyWith => __$$ChatRoomSettingsModelImplCopyWithImpl<
_$ChatRoomSettingsModelImpl>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$ChatRoomSettingsModelImplToJson(
this,
);
}
}
abstract class _ChatRoomSettingsModel implements ChatRoomSettingsModel {
const factory _ChatRoomSettingsModel(
{required final int id,
@JsonKey(name: 'room_name') required final String roomName,
required final String state,
@JsonKey(name: 'access_level') required final String accessLevel,
@JsonKey(name: 'updated_at') required final String updatedAt}) =
_$ChatRoomSettingsModelImpl;
factory _ChatRoomSettingsModel.fromJson(Map<String, dynamic> json) =
_$ChatRoomSettingsModelImpl.fromJson;
@override
int get id;
@override
@JsonKey(name: 'room_name')
String get roomName;
@override
String get state;
@override
@JsonKey(name: 'access_level')
String get accessLevel;
@override
@JsonKey(name: 'updated_at')
String get updatedAt;
@override
@JsonKey(ignore: true)
_$$ChatRoomSettingsModelImplCopyWith<_$ChatRoomSettingsModelImpl>
get copyWith => throw _privateConstructorUsedError;
}

View File

@@ -0,0 +1,27 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'chat_room_settings_model.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_$ChatRoomSettingsModelImpl _$$ChatRoomSettingsModelImplFromJson(
Map<String, dynamic> json) =>
_$ChatRoomSettingsModelImpl(
id: (json['id'] as num).toInt(),
roomName: json['room_name'] as String,
state: json['state'] as String,
accessLevel: json['access_level'] as String,
updatedAt: json['updated_at'] as String,
);
Map<String, dynamic> _$$ChatRoomSettingsModelImplToJson(
_$ChatRoomSettingsModelImpl instance) =>
<String, dynamic>{
'id': instance.id,
'room_name': instance.roomName,
'state': instance.state,
'access_level': instance.accessLevel,
'updated_at': instance.updatedAt,
};

View File

@@ -0,0 +1,19 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'chat_user_model.freezed.dart';
part 'chat_user_model.g.dart';
@freezed
class ChatUserModel with _$ChatUserModel {
const factory ChatUserModel({
required int id,
required String name,
@JsonKey(name: 'profile_photo_path')
String? profilePhotoPath,
@JsonKey(name: 'profile_photo_url')
String? profilePhotoUrl,
}) = _ChatUserModel;
factory ChatUserModel.fromJson(Map<String, Object?> json) => _$ChatUserModelFromJson(json);
}

View File

@@ -0,0 +1,225 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'chat_user_model.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
ChatUserModel _$ChatUserModelFromJson(Map<String, dynamic> json) {
return _ChatUserModel.fromJson(json);
}
/// @nodoc
mixin _$ChatUserModel {
int get id => throw _privateConstructorUsedError;
String get name => throw _privateConstructorUsedError;
@JsonKey(name: 'profile_photo_path')
String? get profilePhotoPath => throw _privateConstructorUsedError;
@JsonKey(name: 'profile_photo_url')
String? get profilePhotoUrl => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$ChatUserModelCopyWith<ChatUserModel> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $ChatUserModelCopyWith<$Res> {
factory $ChatUserModelCopyWith(
ChatUserModel value, $Res Function(ChatUserModel) then) =
_$ChatUserModelCopyWithImpl<$Res, ChatUserModel>;
@useResult
$Res call(
{int id,
String name,
@JsonKey(name: 'profile_photo_path') String? profilePhotoPath,
@JsonKey(name: 'profile_photo_url') String? profilePhotoUrl});
}
/// @nodoc
class _$ChatUserModelCopyWithImpl<$Res, $Val extends ChatUserModel>
implements $ChatUserModelCopyWith<$Res> {
_$ChatUserModelCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? name = null,
Object? profilePhotoPath = freezed,
Object? profilePhotoUrl = freezed,
}) {
return _then(_value.copyWith(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as int,
name: null == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String,
profilePhotoPath: freezed == profilePhotoPath
? _value.profilePhotoPath
: profilePhotoPath // ignore: cast_nullable_to_non_nullable
as String?,
profilePhotoUrl: freezed == profilePhotoUrl
? _value.profilePhotoUrl
: profilePhotoUrl // ignore: cast_nullable_to_non_nullable
as String?,
) as $Val);
}
}
/// @nodoc
abstract class _$$ChatUserModelImplCopyWith<$Res>
implements $ChatUserModelCopyWith<$Res> {
factory _$$ChatUserModelImplCopyWith(
_$ChatUserModelImpl value, $Res Function(_$ChatUserModelImpl) then) =
__$$ChatUserModelImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{int id,
String name,
@JsonKey(name: 'profile_photo_path') String? profilePhotoPath,
@JsonKey(name: 'profile_photo_url') String? profilePhotoUrl});
}
/// @nodoc
class __$$ChatUserModelImplCopyWithImpl<$Res>
extends _$ChatUserModelCopyWithImpl<$Res, _$ChatUserModelImpl>
implements _$$ChatUserModelImplCopyWith<$Res> {
__$$ChatUserModelImplCopyWithImpl(
_$ChatUserModelImpl _value, $Res Function(_$ChatUserModelImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? name = null,
Object? profilePhotoPath = freezed,
Object? profilePhotoUrl = freezed,
}) {
return _then(_$ChatUserModelImpl(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as int,
name: null == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String,
profilePhotoPath: freezed == profilePhotoPath
? _value.profilePhotoPath
: profilePhotoPath // ignore: cast_nullable_to_non_nullable
as String?,
profilePhotoUrl: freezed == profilePhotoUrl
? _value.profilePhotoUrl
: profilePhotoUrl // ignore: cast_nullable_to_non_nullable
as String?,
));
}
}
/// @nodoc
@JsonSerializable()
class _$ChatUserModelImpl implements _ChatUserModel {
const _$ChatUserModelImpl(
{required this.id,
required this.name,
@JsonKey(name: 'profile_photo_path') this.profilePhotoPath,
@JsonKey(name: 'profile_photo_url') this.profilePhotoUrl});
factory _$ChatUserModelImpl.fromJson(Map<String, dynamic> json) =>
_$$ChatUserModelImplFromJson(json);
@override
final int id;
@override
final String name;
@override
@JsonKey(name: 'profile_photo_path')
final String? profilePhotoPath;
@override
@JsonKey(name: 'profile_photo_url')
final String? profilePhotoUrl;
@override
String toString() {
return 'ChatUserModel(id: $id, name: $name, profilePhotoPath: $profilePhotoPath, profilePhotoUrl: $profilePhotoUrl)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ChatUserModelImpl &&
(identical(other.id, id) || other.id == id) &&
(identical(other.name, name) || other.name == name) &&
(identical(other.profilePhotoPath, profilePhotoPath) ||
other.profilePhotoPath == profilePhotoPath) &&
(identical(other.profilePhotoUrl, profilePhotoUrl) ||
other.profilePhotoUrl == profilePhotoUrl));
}
@JsonKey(ignore: true)
@override
int get hashCode =>
Object.hash(runtimeType, id, name, profilePhotoPath, profilePhotoUrl);
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$ChatUserModelImplCopyWith<_$ChatUserModelImpl> get copyWith =>
__$$ChatUserModelImplCopyWithImpl<_$ChatUserModelImpl>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$ChatUserModelImplToJson(
this,
);
}
}
abstract class _ChatUserModel implements ChatUserModel {
const factory _ChatUserModel(
{required final int id,
required final String name,
@JsonKey(name: 'profile_photo_path') final String? profilePhotoPath,
@JsonKey(name: 'profile_photo_url') final String? profilePhotoUrl}) =
_$ChatUserModelImpl;
factory _ChatUserModel.fromJson(Map<String, dynamic> json) =
_$ChatUserModelImpl.fromJson;
@override
int get id;
@override
String get name;
@override
@JsonKey(name: 'profile_photo_path')
String? get profilePhotoPath;
@override
@JsonKey(name: 'profile_photo_url')
String? get profilePhotoUrl;
@override
@JsonKey(ignore: true)
_$$ChatUserModelImplCopyWith<_$ChatUserModelImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@@ -0,0 +1,23 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'chat_user_model.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_$ChatUserModelImpl _$$ChatUserModelImplFromJson(Map<String, dynamic> json) =>
_$ChatUserModelImpl(
id: (json['id'] as num).toInt(),
name: json['name'] as String,
profilePhotoPath: json['profile_photo_path'] as String?,
profilePhotoUrl: json['profile_photo_url'] as String?,
);
Map<String, dynamic> _$$ChatUserModelImplToJson(_$ChatUserModelImpl instance) =>
<String, dynamic>{
'id': instance.id,
'name': instance.name,
'profile_photo_path': instance.profilePhotoPath,
'profile_photo_url': instance.profilePhotoUrl,
};

View File

@@ -0,0 +1,20 @@
import 'package:eatvio_app/features/chat/presentation/bloc/chat_room_cubit/chat_room_state.dart';
import 'package:eatvio_app/features/chat/repositories/chat_repository.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class ChatRoomCubit extends Cubit<ChatRoomState> {
final ChatRepository chatRepository;
ChatRoomCubit({
required this.chatRepository,
}) : super(ChatRoomState.loading());
initChat(String chatId) async {
try {
final chatRoomModel = await chatRepository.getChatRoom(chatId);
emit(ChatRoomState.loaded(chatRoomModel: chatRoomModel));
} catch (e) {
emit(ChatRoomState.error(errorMessage: 'Ошибка получеия данных'));
}
}
}

View File

@@ -0,0 +1,19 @@
import 'package:eatvio_app/features/chat/models/chat_room_model.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'chat_room_state.freezed.dart';
@freezed
abstract class ChatRoomState with _$ChatRoomState {
const factory ChatRoomState() = _ChatRoomState;
const factory ChatRoomState.loading() = ChatRoomStateLoading;
const factory ChatRoomState.loaded({
required ChatRoomModel chatRoomModel,
}) = ChatRoomStateLoaded;
const factory ChatRoomState.error({
required String errorMessage,
}) = ChatRoomStateError;
}

View File

@@ -0,0 +1,622 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'chat_room_state.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
/// @nodoc
mixin _$ChatRoomState {
@optionalTypeArgs
TResult when<TResult extends Object?>(
TResult Function() $default, {
required TResult Function() loading,
required TResult Function(ChatRoomModel chatRoomModel) loaded,
required TResult Function(String errorMessage) error,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>(
TResult? Function()? $default, {
TResult? Function()? loading,
TResult? Function(ChatRoomModel chatRoomModel)? loaded,
TResult? Function(String errorMessage)? error,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>(
TResult Function()? $default, {
TResult Function()? loading,
TResult Function(ChatRoomModel chatRoomModel)? loaded,
TResult Function(String errorMessage)? error,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult map<TResult extends Object?>(
TResult Function(_ChatRoomState value) $default, {
required TResult Function(ChatRoomStateLoading value) loading,
required TResult Function(ChatRoomStateLoaded value) loaded,
required TResult Function(ChatRoomStateError value) error,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>(
TResult? Function(_ChatRoomState value)? $default, {
TResult? Function(ChatRoomStateLoading value)? loading,
TResult? Function(ChatRoomStateLoaded value)? loaded,
TResult? Function(ChatRoomStateError value)? error,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>(
TResult Function(_ChatRoomState value)? $default, {
TResult Function(ChatRoomStateLoading value)? loading,
TResult Function(ChatRoomStateLoaded value)? loaded,
TResult Function(ChatRoomStateError value)? error,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $ChatRoomStateCopyWith<$Res> {
factory $ChatRoomStateCopyWith(
ChatRoomState value, $Res Function(ChatRoomState) then) =
_$ChatRoomStateCopyWithImpl<$Res, ChatRoomState>;
}
/// @nodoc
class _$ChatRoomStateCopyWithImpl<$Res, $Val extends ChatRoomState>
implements $ChatRoomStateCopyWith<$Res> {
_$ChatRoomStateCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
}
/// @nodoc
abstract class _$$ChatRoomStateImplCopyWith<$Res> {
factory _$$ChatRoomStateImplCopyWith(
_$ChatRoomStateImpl value, $Res Function(_$ChatRoomStateImpl) then) =
__$$ChatRoomStateImplCopyWithImpl<$Res>;
}
/// @nodoc
class __$$ChatRoomStateImplCopyWithImpl<$Res>
extends _$ChatRoomStateCopyWithImpl<$Res, _$ChatRoomStateImpl>
implements _$$ChatRoomStateImplCopyWith<$Res> {
__$$ChatRoomStateImplCopyWithImpl(
_$ChatRoomStateImpl _value, $Res Function(_$ChatRoomStateImpl) _then)
: super(_value, _then);
}
/// @nodoc
class _$ChatRoomStateImpl implements _ChatRoomState {
const _$ChatRoomStateImpl();
@override
String toString() {
return 'ChatRoomState()';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType && other is _$ChatRoomStateImpl);
}
@override
int get hashCode => runtimeType.hashCode;
@override
@optionalTypeArgs
TResult when<TResult extends Object?>(
TResult Function() $default, {
required TResult Function() loading,
required TResult Function(ChatRoomModel chatRoomModel) loaded,
required TResult Function(String errorMessage) error,
}) {
return $default();
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>(
TResult? Function()? $default, {
TResult? Function()? loading,
TResult? Function(ChatRoomModel chatRoomModel)? loaded,
TResult? Function(String errorMessage)? error,
}) {
return $default?.call();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>(
TResult Function()? $default, {
TResult Function()? loading,
TResult Function(ChatRoomModel chatRoomModel)? loaded,
TResult Function(String errorMessage)? error,
required TResult orElse(),
}) {
if ($default != null) {
return $default();
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>(
TResult Function(_ChatRoomState value) $default, {
required TResult Function(ChatRoomStateLoading value) loading,
required TResult Function(ChatRoomStateLoaded value) loaded,
required TResult Function(ChatRoomStateError value) error,
}) {
return $default(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>(
TResult? Function(_ChatRoomState value)? $default, {
TResult? Function(ChatRoomStateLoading value)? loading,
TResult? Function(ChatRoomStateLoaded value)? loaded,
TResult? Function(ChatRoomStateError value)? error,
}) {
return $default?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>(
TResult Function(_ChatRoomState value)? $default, {
TResult Function(ChatRoomStateLoading value)? loading,
TResult Function(ChatRoomStateLoaded value)? loaded,
TResult Function(ChatRoomStateError value)? error,
required TResult orElse(),
}) {
if ($default != null) {
return $default(this);
}
return orElse();
}
}
abstract class _ChatRoomState implements ChatRoomState {
const factory _ChatRoomState() = _$ChatRoomStateImpl;
}
/// @nodoc
abstract class _$$ChatRoomStateLoadingImplCopyWith<$Res> {
factory _$$ChatRoomStateLoadingImplCopyWith(_$ChatRoomStateLoadingImpl value,
$Res Function(_$ChatRoomStateLoadingImpl) then) =
__$$ChatRoomStateLoadingImplCopyWithImpl<$Res>;
}
/// @nodoc
class __$$ChatRoomStateLoadingImplCopyWithImpl<$Res>
extends _$ChatRoomStateCopyWithImpl<$Res, _$ChatRoomStateLoadingImpl>
implements _$$ChatRoomStateLoadingImplCopyWith<$Res> {
__$$ChatRoomStateLoadingImplCopyWithImpl(_$ChatRoomStateLoadingImpl _value,
$Res Function(_$ChatRoomStateLoadingImpl) _then)
: super(_value, _then);
}
/// @nodoc
class _$ChatRoomStateLoadingImpl implements ChatRoomStateLoading {
const _$ChatRoomStateLoadingImpl();
@override
String toString() {
return 'ChatRoomState.loading()';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ChatRoomStateLoadingImpl);
}
@override
int get hashCode => runtimeType.hashCode;
@override
@optionalTypeArgs
TResult when<TResult extends Object?>(
TResult Function() $default, {
required TResult Function() loading,
required TResult Function(ChatRoomModel chatRoomModel) loaded,
required TResult Function(String errorMessage) error,
}) {
return loading();
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>(
TResult? Function()? $default, {
TResult? Function()? loading,
TResult? Function(ChatRoomModel chatRoomModel)? loaded,
TResult? Function(String errorMessage)? error,
}) {
return loading?.call();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>(
TResult Function()? $default, {
TResult Function()? loading,
TResult Function(ChatRoomModel chatRoomModel)? loaded,
TResult Function(String errorMessage)? error,
required TResult orElse(),
}) {
if (loading != null) {
return loading();
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>(
TResult Function(_ChatRoomState value) $default, {
required TResult Function(ChatRoomStateLoading value) loading,
required TResult Function(ChatRoomStateLoaded value) loaded,
required TResult Function(ChatRoomStateError value) error,
}) {
return loading(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>(
TResult? Function(_ChatRoomState value)? $default, {
TResult? Function(ChatRoomStateLoading value)? loading,
TResult? Function(ChatRoomStateLoaded value)? loaded,
TResult? Function(ChatRoomStateError value)? error,
}) {
return loading?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>(
TResult Function(_ChatRoomState value)? $default, {
TResult Function(ChatRoomStateLoading value)? loading,
TResult Function(ChatRoomStateLoaded value)? loaded,
TResult Function(ChatRoomStateError value)? error,
required TResult orElse(),
}) {
if (loading != null) {
return loading(this);
}
return orElse();
}
}
abstract class ChatRoomStateLoading implements ChatRoomState {
const factory ChatRoomStateLoading() = _$ChatRoomStateLoadingImpl;
}
/// @nodoc
abstract class _$$ChatRoomStateLoadedImplCopyWith<$Res> {
factory _$$ChatRoomStateLoadedImplCopyWith(_$ChatRoomStateLoadedImpl value,
$Res Function(_$ChatRoomStateLoadedImpl) then) =
__$$ChatRoomStateLoadedImplCopyWithImpl<$Res>;
@useResult
$Res call({ChatRoomModel chatRoomModel});
$ChatRoomModelCopyWith<$Res> get chatRoomModel;
}
/// @nodoc
class __$$ChatRoomStateLoadedImplCopyWithImpl<$Res>
extends _$ChatRoomStateCopyWithImpl<$Res, _$ChatRoomStateLoadedImpl>
implements _$$ChatRoomStateLoadedImplCopyWith<$Res> {
__$$ChatRoomStateLoadedImplCopyWithImpl(_$ChatRoomStateLoadedImpl _value,
$Res Function(_$ChatRoomStateLoadedImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? chatRoomModel = null,
}) {
return _then(_$ChatRoomStateLoadedImpl(
chatRoomModel: null == chatRoomModel
? _value.chatRoomModel
: chatRoomModel // ignore: cast_nullable_to_non_nullable
as ChatRoomModel,
));
}
@override
@pragma('vm:prefer-inline')
$ChatRoomModelCopyWith<$Res> get chatRoomModel {
return $ChatRoomModelCopyWith<$Res>(_value.chatRoomModel, (value) {
return _then(_value.copyWith(chatRoomModel: value));
});
}
}
/// @nodoc
class _$ChatRoomStateLoadedImpl implements ChatRoomStateLoaded {
const _$ChatRoomStateLoadedImpl({required this.chatRoomModel});
@override
final ChatRoomModel chatRoomModel;
@override
String toString() {
return 'ChatRoomState.loaded(chatRoomModel: $chatRoomModel)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ChatRoomStateLoadedImpl &&
(identical(other.chatRoomModel, chatRoomModel) ||
other.chatRoomModel == chatRoomModel));
}
@override
int get hashCode => Object.hash(runtimeType, chatRoomModel);
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$ChatRoomStateLoadedImplCopyWith<_$ChatRoomStateLoadedImpl> get copyWith =>
__$$ChatRoomStateLoadedImplCopyWithImpl<_$ChatRoomStateLoadedImpl>(
this, _$identity);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>(
TResult Function() $default, {
required TResult Function() loading,
required TResult Function(ChatRoomModel chatRoomModel) loaded,
required TResult Function(String errorMessage) error,
}) {
return loaded(chatRoomModel);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>(
TResult? Function()? $default, {
TResult? Function()? loading,
TResult? Function(ChatRoomModel chatRoomModel)? loaded,
TResult? Function(String errorMessage)? error,
}) {
return loaded?.call(chatRoomModel);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>(
TResult Function()? $default, {
TResult Function()? loading,
TResult Function(ChatRoomModel chatRoomModel)? loaded,
TResult Function(String errorMessage)? error,
required TResult orElse(),
}) {
if (loaded != null) {
return loaded(chatRoomModel);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>(
TResult Function(_ChatRoomState value) $default, {
required TResult Function(ChatRoomStateLoading value) loading,
required TResult Function(ChatRoomStateLoaded value) loaded,
required TResult Function(ChatRoomStateError value) error,
}) {
return loaded(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>(
TResult? Function(_ChatRoomState value)? $default, {
TResult? Function(ChatRoomStateLoading value)? loading,
TResult? Function(ChatRoomStateLoaded value)? loaded,
TResult? Function(ChatRoomStateError value)? error,
}) {
return loaded?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>(
TResult Function(_ChatRoomState value)? $default, {
TResult Function(ChatRoomStateLoading value)? loading,
TResult Function(ChatRoomStateLoaded value)? loaded,
TResult Function(ChatRoomStateError value)? error,
required TResult orElse(),
}) {
if (loaded != null) {
return loaded(this);
}
return orElse();
}
}
abstract class ChatRoomStateLoaded implements ChatRoomState {
const factory ChatRoomStateLoaded(
{required final ChatRoomModel chatRoomModel}) = _$ChatRoomStateLoadedImpl;
ChatRoomModel get chatRoomModel;
@JsonKey(ignore: true)
_$$ChatRoomStateLoadedImplCopyWith<_$ChatRoomStateLoadedImpl> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class _$$ChatRoomStateErrorImplCopyWith<$Res> {
factory _$$ChatRoomStateErrorImplCopyWith(_$ChatRoomStateErrorImpl value,
$Res Function(_$ChatRoomStateErrorImpl) then) =
__$$ChatRoomStateErrorImplCopyWithImpl<$Res>;
@useResult
$Res call({String errorMessage});
}
/// @nodoc
class __$$ChatRoomStateErrorImplCopyWithImpl<$Res>
extends _$ChatRoomStateCopyWithImpl<$Res, _$ChatRoomStateErrorImpl>
implements _$$ChatRoomStateErrorImplCopyWith<$Res> {
__$$ChatRoomStateErrorImplCopyWithImpl(_$ChatRoomStateErrorImpl _value,
$Res Function(_$ChatRoomStateErrorImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? errorMessage = null,
}) {
return _then(_$ChatRoomStateErrorImpl(
errorMessage: null == errorMessage
? _value.errorMessage
: errorMessage // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
/// @nodoc
class _$ChatRoomStateErrorImpl implements ChatRoomStateError {
const _$ChatRoomStateErrorImpl({required this.errorMessage});
@override
final String errorMessage;
@override
String toString() {
return 'ChatRoomState.error(errorMessage: $errorMessage)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ChatRoomStateErrorImpl &&
(identical(other.errorMessage, errorMessage) ||
other.errorMessage == errorMessage));
}
@override
int get hashCode => Object.hash(runtimeType, errorMessage);
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$ChatRoomStateErrorImplCopyWith<_$ChatRoomStateErrorImpl> get copyWith =>
__$$ChatRoomStateErrorImplCopyWithImpl<_$ChatRoomStateErrorImpl>(
this, _$identity);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>(
TResult Function() $default, {
required TResult Function() loading,
required TResult Function(ChatRoomModel chatRoomModel) loaded,
required TResult Function(String errorMessage) error,
}) {
return error(errorMessage);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>(
TResult? Function()? $default, {
TResult? Function()? loading,
TResult? Function(ChatRoomModel chatRoomModel)? loaded,
TResult? Function(String errorMessage)? error,
}) {
return error?.call(errorMessage);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>(
TResult Function()? $default, {
TResult Function()? loading,
TResult Function(ChatRoomModel chatRoomModel)? loaded,
TResult Function(String errorMessage)? error,
required TResult orElse(),
}) {
if (error != null) {
return error(errorMessage);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>(
TResult Function(_ChatRoomState value) $default, {
required TResult Function(ChatRoomStateLoading value) loading,
required TResult Function(ChatRoomStateLoaded value) loaded,
required TResult Function(ChatRoomStateError value) error,
}) {
return error(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>(
TResult? Function(_ChatRoomState value)? $default, {
TResult? Function(ChatRoomStateLoading value)? loading,
TResult? Function(ChatRoomStateLoaded value)? loaded,
TResult? Function(ChatRoomStateError value)? error,
}) {
return error?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>(
TResult Function(_ChatRoomState value)? $default, {
TResult Function(ChatRoomStateLoading value)? loading,
TResult Function(ChatRoomStateLoaded value)? loaded,
TResult Function(ChatRoomStateError value)? error,
required TResult orElse(),
}) {
if (error != null) {
return error(this);
}
return orElse();
}
}
abstract class ChatRoomStateError implements ChatRoomState {
const factory ChatRoomStateError({required final String errorMessage}) =
_$ChatRoomStateErrorImpl;
String get errorMessage;
@JsonKey(ignore: true)
_$$ChatRoomStateErrorImplCopyWith<_$ChatRoomStateErrorImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@@ -0,0 +1,161 @@
import 'package:eatvio_app/features/chat/presentation/bloc/chat_room_cubit/chat_room_cubit.dart';
import 'package:eatvio_app/features/chat/presentation/bloc/chat_room_cubit/chat_room_state.dart';
import 'package:eatvio_app/features/chat/presentation/widgets/chat_bubble_widget.dart';
import 'package:eatvio_app/locator_service.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:eatvio_app/core/app_export.dart';
import 'package:flutter/material.dart';
class ChatScreen extends StatelessWidget {
final String chatId;
const ChatScreen({
required this.chatId,
super.key,
});
Widget build(BuildContext context) {
return BlocProvider<ChatRoomCubit>(
create: (BuildContext context) => sl()..initChat(chatId),
child: BlocBuilder<ChatRoomCubit, ChatRoomState>(
builder: (context, state) {
if (state is ChatRoomStateLoading) {
return Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
} else if (state is ChatRoomStateLoaded) {
return _buildChat(context, state);
} else if (state is ChatRoomStateError) {
return Center(child: Text(state.errorMessage));
} else {
return Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}
},
),
);
}
_buildChat(BuildContext context, ChatRoomStateLoaded state) {
mediaQueryData = MediaQuery.of(context);
return Scaffold(
resizeToAvoidBottomInset: true,
appBar: AppBar(
titleSpacing: 0,
centerTitle: false,
title: Row(
children: [
ClipOval(
child: SvgPicture.network(
width: 40,
height: 40,
state.chatRoomModel.users['to_chat_user']!.profilePhotoUrl!,
placeholderBuilder: (context) => CircleAvatar(
foregroundColor: PrimaryColors().backgroundAvatar,
),
),
),
SizedBox(width: 16),
Text(
state.chatRoomModel.users['to_chat_user']!.name,
style: CustomTextStyles.titleSmallBold.copyWith(color: PrimaryColors().blueGray800),
),
],
),
),
body: Column(
mainAxisSize: MainAxisSize.min,
children: [
Expanded(
child: Container(
width: double.maxFinite,
child: ListView.builder(
reverse: true,
padding: EdgeInsets.symmetric(vertical: 16),
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return ChatBubbleWidget(
text: state.chatRoomModel.messages[state.chatRoomModel.messages.length - index - 1].data,
isCurrentUser: state.chatRoomModel.users['to_chat_user']!.id != state.chatRoomModel.messages[index].authorId,
);
},
itemCount: state.chatRoomModel.messages.length,
),
),
),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(width: 8),
InkWell(
onTap: () {},
borderRadius: BorderRadius.circular(16),
child: Ink(
height: 32,
width: 32,
child: Icon(
Icons.attach_file_rounded,
size: 28,
),
),
),
SizedBox(width: 8),
SizedBox(
width: mediaQueryData.size.width - 96,
child: TextFormField(
maxLines: 5,
minLines: 1,
keyboardType: TextInputType.multiline,
decoration: InputDecoration(
contentPadding: EdgeInsets.symmetric(horizontal: 8, vertical: 0),
hintText: 'Сообщение',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
borderSide: BorderSide(
color: Color(0xFFD1D1D6),
width: 1,
),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
borderSide: BorderSide(
color: Color(0xFFD1D1D6),
width: 1,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
borderSide: BorderSide(
color: Color(0xFFD1D1D6),
width: 1,
),
),
),
),
),
SizedBox(width: 8),
InkWell(
borderRadius: BorderRadius.circular(16),
onTap: () {},
child: Ink(
height: 32,
width: 32,
child: Icon(
Icons.send,
size: 28,
),
),
),
SizedBox(width: 8),
],
),
],
),
);
}
}

View File

@@ -1,4 +1,6 @@
import 'package:eatvio_app/app_router.dart';
import 'package:eatvio_app/features/chat/presentation/pages/chat_select_screen/models/chat_entry.dart';
import 'package:eatvio_app/features/chat/presentation/pages/chat_select_screen/models/chat_select_model.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
@@ -8,8 +10,6 @@ import 'package:intl/intl.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'dart:convert';
import '/core/app_export.dart';
import 'package:eatvio_app/presentation/chat/chat_select_screen/models/chat_select_model.dart';
import 'package:eatvio_app/presentation/chat/chat_select_screen/models/chat_entry.dart';
import 'package:go_router/go_router.dart';
part 'chat_select_event.dart';

View File

@@ -1,10 +1,12 @@
import 'package:eatvio_app/features/chat/presentation/pages/chat_select_screen/models/chat_entry.dart';
import 'package:eatvio_app/features/chat/presentation/pages/chat_select_screen/widgets/chat_entry_widget.dart';
import 'bloc/chat_select_bloc.dart';
import 'models/chat_select_model.dart';
import 'package:eatvio_app/core/app_export.dart';
import '../chat_select_screen/chat_search_view.dart';
import 'chat_search_view.dart';
import 'package:flutter/material.dart';
import 'package:eatvio_app/presentation/chat/chat_select_screen/models/chat_entry.dart'; // ignore: must_be_immutable
import 'package:eatvio_app/presentation/chat/chat_select_screen/widgets/chat_entry_widget.dart'; // ignore: must_be_immutable
class ChatSelectScreen extends StatelessWidget {
const ChatSelectScreen({Key? key}) : super(key: key);

View File

@@ -1,7 +1,7 @@
// ignore_for_file: must_be_immutable
import 'package:eatvio_app/features/chat/presentation/pages/chat_select_screen/models/chat_entry.dart';
import 'package:equatable/equatable.dart';
import 'package:eatvio_app/presentation/chat/chat_select_screen/models/chat_entry.dart';
/// This class defines the variables used in the [chat_select_screen],
/// and is typically used to hold data that is passed between different parts of the application.

View File

@@ -1,9 +1,9 @@
// ignore_for_file: must_be_immutable
import 'package:eatvio_app/features/chat/presentation/pages/chat_select_screen/models/chat_entry.dart';
import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:eatvio_app/core/app_export.dart';
import 'package:eatvio_app/presentation/chat/chat_select_screen/models/chat_entry.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:go_router/go_router.dart';

View File

@@ -0,0 +1,37 @@
import 'package:flutter/material.dart';
class ChatBubbleWidget extends StatelessWidget {
const ChatBubbleWidget({
super.key,
required this.text,
required this.isCurrentUser,
});
final String text;
final bool isCurrentUser;
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.fromLTRB(isCurrentUser ? 64 : 16, 4, isCurrentUser ? 16 : 64, 4),
child: Align(
alignment: isCurrentUser ? Alignment.centerRight : Alignment.centerLeft,
child: DecoratedBox(
decoration: BoxDecoration(
color: isCurrentUser ? Colors.blue : Colors.grey[300],
borderRadius: BorderRadius.circular(16),
),
child: Padding(
padding: const EdgeInsets.all(12),
child: Text(
text,
style: TextStyle(
color: isCurrentUser ? Colors.white : Colors.black87,
),
),
),
),
),
);
}
}

View File

@@ -0,0 +1,20 @@
import 'package:eatvio_app/features/chat/models/chat_room_model.dart';
import 'package:eatvio_app/features/chat/services/chat_service.dart';
class ChatRepository {
final ChatService chatService;
ChatRepository({
required this.chatService,
});
/// TODO use "dartz" package because need Either<Failure, Result> for error handling
Future<ChatRoomModel> getChatRoom(String chatId) async {
try {
return (await chatService.getChatRoomModel(chatId))['chatRoom']!;
} catch (e) {
print(e);
throw (e);
}
}
}

View File

@@ -0,0 +1,13 @@
import 'package:eatvio_app/features/chat/models/chat_room_model.dart';
import 'package:dio/dio.dart';
import 'package:retrofit/retrofit.dart';
part 'chat_service.g.dart';
@RestApi()
abstract class ChatService {
factory ChatService(Dio dio) = _ChatService;
@GET('/chat/show/{id}')
Future<Map<String, ChatRoomModel>> getChatRoomModel(@Path() String id);
}

View File

@@ -0,0 +1,78 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'chat_service.dart';
// **************************************************************************
// RetrofitGenerator
// **************************************************************************
// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers
class _ChatService implements ChatService {
_ChatService(
this._dio, {
this.baseUrl,
});
final Dio _dio;
String? baseUrl;
@override
Future<Map<String, ChatRoomModel>> getChatRoomModel(String id) async {
final _extra = <String, dynamic>{};
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
const Map<String, dynamic>? _data = null;
final _result = await _dio.fetch<Map<String, dynamic>>(
_setStreamType<Map<String, ChatRoomModel>>(Options(
method: 'GET',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/chat/show/${id}',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
))));
var value = _result.data!.map((k, dynamic v) =>
MapEntry(k, ChatRoomModel.fromJson(v as Map<String, dynamic>)));
return value;
}
RequestOptions _setStreamType<T>(RequestOptions requestOptions) {
if (T != dynamic &&
!(requestOptions.responseType == ResponseType.bytes ||
requestOptions.responseType == ResponseType.stream)) {
if (T == String) {
requestOptions.responseType = ResponseType.plain;
} else {
requestOptions.responseType = ResponseType.json;
}
}
return requestOptions;
}
String _combineBaseUrls(
String dioBaseUrl,
String? baseUrl,
) {
if (baseUrl == null || baseUrl.trim().isEmpty) {
return dioBaseUrl;
}
final url = Uri.parse(baseUrl);
if (url.isAbsolute) {
return url.toString();
}
return Uri.parse(dioBaseUrl).resolveUri(url).toString();
}
}

28
lib/locator_service.dart Normal file
View File

@@ -0,0 +1,28 @@
import 'package:dio/dio.dart';
import 'package:eatvio_app/features/chat/presentation/bloc/chat_room_cubit/chat_room_cubit.dart';
import 'package:eatvio_app/features/chat/repositories/chat_repository.dart';
import 'package:eatvio_app/features/chat/services/chat_service.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:get_it/get_it.dart';
final sl = GetIt.instance;
Future<void> init() async {
// BLoC
sl.registerFactory<ChatRoomCubit>(() => ChatRoomCubit(chatRepository: sl()));
// Repository
sl.registerLazySingleton<ChatRepository>(() => ChatRepository(chatService: sl()));
// Services
sl.registerLazySingleton<ChatService>(() => ChatService(sl()));
// External
sl.registerLazySingleton(
() => Dio(
BaseOptions(
baseUrl: dotenv.env['SERVER_ROOT']!,
),
),
);
}

View File

@@ -1,6 +1,6 @@
import 'package:eatvio_app/app_router.dart';
import 'package:eatvio_app/presentation/chat/chat_select_screen/bloc/chat_select_bloc.dart';
import 'package:eatvio_app/presentation/chat/chat_select_screen/models/chat_select_model.dart';
import 'package:eatvio_app/features/chat/presentation/pages/chat_select_screen/bloc/chat_select_bloc.dart';
import 'package:eatvio_app/features/chat/presentation/pages/chat_select_screen/models/chat_select_model.dart';
import 'package:eatvio_app/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart';
import 'package:eatvio_app/presentation/diary/diary_edit_screen/models/diary_edit_model.dart';
import 'package:eatvio_app/presentation/feed/feed_screen/bloc/feed_bloc.dart';
@@ -15,11 +15,13 @@ import 'package:hive_flutter/hive_flutter.dart';
import 'package:path_provider/path_provider.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:keyboard_dismisser/keyboard_dismisser.dart';
import 'package:eatvio_app/locator_service.dart' as di;
var globalMessengerKey = GlobalKey<ScaffoldMessengerState>();
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await di.init();
final appDocumentDir = await getApplicationDocumentsDirectory();
final path = appDocumentDir.path;
await dotenv.load(fileName: ".env");

View File

@@ -1,3 +1,4 @@
import 'package:eatvio_app/core/token_storage.dart';
import 'package:go_router/go_router.dart';
import 'bloc/auth_bloc.dart';
@@ -106,6 +107,7 @@ class AuthScreen extends StatelessWidget {
final box = await Hive.openBox('token');
final token = res['token'];
box.put('token', token);
TokenStorage.saveTokenInStorage(token);
GoRouter.of(context).go('/my-profile-screen');
} else {
showDialog(

View File

@@ -1,76 +0,0 @@
import 'package:eatvio_app/app_router.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:hive/hive.dart';
import 'package:http/http.dart' as http;
import 'package:go_router/go_router.dart';
import 'dart:convert';
import '/core/app_export.dart';
import 'package:eatvio_app/presentation/chat/chat_screen/models/chat_model.dart';
import 'package:eatvio_app/presentation/chat/chat_screen/models/chat_message_model.dart';
part 'chat_event.dart';
part 'chat_state.dart';
/// A bloc that manages the state of a Chat according to the event that is dispatched to it.
class ChatBloc extends Bloc<ChatEvent, ChatState> {
ChatBloc(ChatState initialState) : super(initialState) {
on<ChatInitialEvent>(_onInitialize);
}
_onInitialize(
ChatInitialEvent event,
Emitter<ChatState> emit,
) async {
try {
final box = await Hive.openBox('token');
final token = box.get('token');
if (token == null) {
AppRouter.navigatorKey.currentContext?.goNamed('authScreen');
}
final String? chatID = state.chatModelObj?.chatID;
final response = await http.get(
Uri.parse(dotenv.env['SERVER_ROOT']! + '/chat/show/$chatID'),
headers: {
'Authorization': 'Bearer $token',
},
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
if (data is Map<String, dynamic> && data.containsKey('chatRoom') && data['chatRoom'].containsKey('messages')) {
if (state is ChatLoadedState) {
var currentState = state as ChatLoadedState;
emit(currentState.copyWith(chatModelObj: currentState.chatModelObj, messages: currentState.messages));
} else {
emit(ChatLoadedState(messages: fillMessages(data['chatRoom']['messages'])));
}
} else {
// Один или несколько ключевых полей отсутствуют, обрабатываем ошибку
emit(ChatErrorState('Некоторые необходимые данные отсутствуют.'));
}
} else {
// Статус ответа не равен 200, обрабатываем ошибку
emit(ChatErrorState('Ошибка сервера: ${response.statusCode}'));
}
} catch (e) {
// Ошибка при декодировании JSON или другая ошибка выполнения
emit(ChatErrorState('Ошибка при получении данных о чатах: $e'));
}
}
List<ChatMessageModel> fillMessages(List<dynamic> messagesJSON) {
List<ChatMessageModel> messages = [];
for (int i = 0; i < messagesJSON.length; i++) {
messages.add(ChatMessageModel(
id: messagesJSON[i]['id'],
data: messagesJSON[i]['data'],
mediaData: messagesJSON[i]['mediaData'] ?? [],
updatedAt: messagesJSON[i]['updated_at'],
authorId: messagesJSON[i]['author_id']));
}
return messages;
}
}

View File

@@ -1,16 +0,0 @@
// ignore_for_file: must_be_immutable
part of 'chat_bloc.dart';
/// Abstract class for all events that can be dispatched from the
///Chat widget.
///
/// Events must be immutable and implement the [Equatable] interface.
@immutable
abstract class ChatEvent extends Equatable {}
/// Event that is dispatched when the Chat widget is first created.
class ChatInitialEvent extends ChatEvent {
@override
List<Object?> get props => [];
}

View File

@@ -1,53 +0,0 @@
// ignore_for_file: must_be_immutable
part of 'chat_bloc.dart';
/// Represents the state of Chat in the application.
///
class ChatState extends Equatable {
ChatState({
this.chatModelObj,
});
ChatModel? chatModelObj;
@override
List<Object?> get props => [chatModelObj];
ChatState copyWith({ChatModel? chatModelObj}) {
return ChatState(
chatModelObj: chatModelObj ?? this.chatModelObj,
);
}
}
class ChatLoadedState extends ChatState {
ChatLoadedState({this.chatModelObj, this.messages});
ChatModel? chatModelObj;
List<ChatMessageModel>? messages;
@override
List<Object?> get props => [chatModelObj, messages];
ChatLoadedState copyWith({ChatModel? chatModelObj, List<ChatMessageModel>? messages}) {
return ChatLoadedState(
chatModelObj: chatModelObj ?? this.chatModelObj,
messages: messages ?? this.messages,
);
}
}
class ChatErrorState extends ChatState {
final String errorMessage;
ChatErrorState(this.errorMessage);
@override
List<Object> get props => [errorMessage];
}
class ChatInitialState extends ChatState {
ChatInitialState({required ChatModel chatModelObj}) : super(chatModelObj: chatModelObj);
}

View File

@@ -1,186 +0,0 @@
import 'package:go_router/go_router.dart';
import 'bloc/chat_bloc.dart';
import 'models/chat_model.dart';
import 'package:eatvio_app/core/app_export.dart';
import 'package:flutter/material.dart';
import 'package:eatvio_app/widgets/app_bar/custom_app_bar.dart';
import 'package:eatvio_app/widgets/app_bar/appbar_subtitle.dart';
import 'package:eatvio_app/widgets/app_bar/appbar_leading_image.dart';
class ChatScreen extends StatelessWidget {
const ChatScreen({Key? key}) : super(key: key);
static Widget builder(BuildContext context, chatID) {
return BlocProvider<ChatBloc>(
create: (context) => ChatBloc(ChatState(chatModelObj: ChatModel(chatID: chatID.toString())))
..add(
ChatInitialEvent(),
),
child: ChatScreen(),
);
}
Widget build(BuildContext context) {
return BlocBuilder<ChatBloc, ChatState>(
builder: (context, state) {
if (state is ChatInitialState) {
return Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
} else if (state is ChatLoadedState) {
// Данные загружены, можно строить экран.
return _buildChat(context, state);
} else if (state is ChatErrorState) {
// Произошла ошибка при загрузке данных.
return Center(child: Text(state.errorMessage));
} else {
return Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}
},
);
}
_buildChat(BuildContext context, ChatLoadedState state) {
mediaQueryData = MediaQuery.of(context);
return Scaffold(
resizeToAvoidBottomInset: true,
appBar: _buildAppbar(context, state),
body: SizedBox(
width: double.maxFinite,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
width: double.maxFinite,
decoration: AppDecoration.fillGray,
child: ListView(
shrinkWrap: true,
children: [
for (int i = 0; i < state.messages!.length; i++) ...[Text(state.messages![i].data)]
],
),
),
const Spacer(),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(width: 8),
InkWell(
onTap: () {},
borderRadius: BorderRadius.circular(16),
child: Ink(
height: 32,
width: 32,
child: Icon(
Icons.attach_file_rounded,
size: 28,
),
),
),
SizedBox(width: 8),
SizedBox(
width: mediaQueryData.size.width - 96,
child: TextFormField(
maxLines: 5,
minLines: 1,
keyboardType: TextInputType.multiline,
decoration: InputDecoration(
contentPadding: EdgeInsets.symmetric(horizontal: 8, vertical: 0),
hintText: 'Сообщение',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
borderSide: BorderSide(
color: Color(0xFFD1D1D6),
width: 1,
),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
borderSide: BorderSide(
color: Color(0xFFD1D1D6),
width: 1,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
borderSide: BorderSide(
color: Color(0xFFD1D1D6),
width: 1,
),
),
),
),
),
SizedBox(width: 8),
InkWell(
borderRadius: BorderRadius.circular(16),
onTap: () {},
child: Ink(
height: 32,
width: 32,
child: Icon(
Icons.send,
size: 28,
),
),
),
SizedBox(width: 8),
],
),
],
),
),
);
}
/// Section Widget
_buildAppbar(BuildContext context, ChatLoadedState state) {
return CustomAppBar(
leadingWidth: 26.h,
leading: AppbarLeadingImage(
imagePath: ImageConstant.imgArrowLeft,
margin: EdgeInsets.only(
left: 16.h,
top: 18.v,
bottom: 25.v,
),
onTap: () => onTapArrowleftone(context),
),
title: Padding(
padding: EdgeInsets.only(left: 12.h),
child: Row(
children: [
Padding(
padding: EdgeInsets.only(
left: 12.h,
top: 2.v,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AppbarSubtitle(
text: 'username',
),
SizedBox(height: 3.v),
Text("Был в сети вчера", style: theme.textTheme.bodySmall!)
],
),
)
],
),
),
);
}
/// Navigates to the previous screen.
onTapArrowleftone(BuildContext context) {
GoRouter.of(context).pop();
}
}

View File

@@ -1,36 +0,0 @@
import 'package:equatable/equatable.dart';
class ChatMessageModel extends Equatable {
final int id;
final String data;
final List<dynamic> mediaData;
final int authorId;
final String updatedAt;
ChatMessageModel({
required this.id,
required this.data,
required this.mediaData,
required this.authorId,
required this.updatedAt,
});
ChatMessageModel copyWith({
int? id,
String? data,
List<dynamic>? mediaData,
int? authorId,
String? updatedAt,
}) {
return ChatMessageModel(
id: id ?? this.id,
data: data ?? this.data,
mediaData: mediaData ?? this.mediaData,
authorId: authorId ?? this.authorId,
updatedAt: updatedAt ?? this.updatedAt,
);
}
@override
List<Object?> get props => [id, data, mediaData, authorId, updatedAt];
}

View File

@@ -1,19 +0,0 @@
// ignore_for_file: must_be_immutable
import 'package:equatable/equatable.dart';
/// This class defines the variables used in the [chat_screen],
/// and is typically used to hold data that is passed between different parts of the application.
class ChatModel extends Equatable {
final String chatID;
ChatModel({required String chatID}) : chatID = chatID;
ChatModel copyWith(String chatID) {
return ChatModel(chatID: chatID);
}
@override
List<Object?> get props => [chatID];
}

View File

@@ -8,155 +8,171 @@ import '../core/app_export.dart';
class CustomTextStyles {
// Headline style
static get headlineSmallMulish => theme.textTheme.headlineSmall!.mulish;
// Title text style
static get titleMediumSegoeUI =>
theme.textTheme.titleMedium!.segoeUI.copyWith(
static get titleMediumSegoeUI => theme.textTheme.titleMedium!.segoeUI.copyWith(
fontWeight: FontWeight.w600,
);
static get bodyMediumBlack900 => theme.textTheme.bodyMedium!.copyWith(
color: appTheme.black900,
);
static get bodyMediumBlack90013 => theme.textTheme.bodyMedium!.copyWith(
color: appTheme.black900,
fontSize: 13.fSize,
);
static get bodyMediumBluegray800 => theme.textTheme.bodyMedium!.copyWith(
color: appTheme.blueGray800,
);
static get bodyMediumBluegray800_1 => theme.textTheme.bodyMedium!.copyWith(
color: appTheme.blueGray800,
);
static get bodyMediumBluegray800_2 => theme.textTheme.bodyMedium!.copyWith(
color: appTheme.blueGray800,
);
static get bodyMediumWhiteA700 => theme.textTheme.bodyMedium!.copyWith(
color: appTheme.whiteA700,
);
static get bodySmallMulishBlack900 =>
theme.textTheme.bodySmall!.mulish.copyWith(
static get bodySmallMulishBlack900 => theme.textTheme.bodySmall!.mulish.copyWith(
color: appTheme.black900,
fontSize: 12.fSize,
);
static get bodySmallMulishBluegray800 =>
theme.textTheme.bodySmall!.mulish.copyWith(
static get bodySmallMulishBluegray800 => theme.textTheme.bodySmall!.mulish.copyWith(
color: appTheme.blueGray800,
fontSize: 12.fSize,
);
static get bodySmallMulishBluegray80012 =>
theme.textTheme.bodySmall!.mulish.copyWith(
static get bodySmallMulishBluegray80012 => theme.textTheme.bodySmall!.mulish.copyWith(
color: appTheme.blueGray800,
fontSize: 12.fSize,
);
static get bodySmallMulishBluegray80012_1 =>
theme.textTheme.bodySmall!.mulish.copyWith(
static get bodySmallMulishBluegray80012_1 => theme.textTheme.bodySmall!.mulish.copyWith(
color: appTheme.blueGray800,
fontSize: 12.fSize,
);
static get bodySmallMulishBluegray900 =>
theme.textTheme.bodySmall!.mulish.copyWith(
static get bodySmallMulishBluegray900 => theme.textTheme.bodySmall!.mulish.copyWith(
color: appTheme.blueGray900,
fontSize: 12.fSize,
);
static get bodySmallMulishGray600 =>
theme.textTheme.bodySmall!.mulish.copyWith(
static get bodySmallMulishGray600 => theme.textTheme.bodySmall!.mulish.copyWith(
color: appTheme.gray600,
);
static get bodySmallMulishPrimary =>
theme.textTheme.bodySmall!.mulish.copyWith(
static get bodySmallMulishPrimary => theme.textTheme.bodySmall!.mulish.copyWith(
color: theme.colorScheme.primary,
fontSize: 12.fSize,
);
static get bodySmallSegoeUIBlack900 =>
theme.textTheme.bodySmall!.segoeUI.copyWith(
static get bodySmallSegoeUIBlack900 => theme.textTheme.bodySmall!.segoeUI.copyWith(
color: appTheme.black900,
fontSize: 12.fSize,
);
// Label text style
static get labelLargeGray60003 => theme.textTheme.labelLarge!.copyWith(
color: appTheme.gray60003,
);
static get labelLargeWhiteA700 => theme.textTheme.labelLarge!.copyWith(
color: appTheme.whiteA700,
);
// Title text style
static get titleMedium16 => theme.textTheme.titleMedium!.copyWith(
fontSize: 16.fSize,
);
static get titleMediumBlack => theme.textTheme.titleMedium!.copyWith(
fontSize: 17.fSize,
fontWeight: FontWeight.w900,
);
static get titleMediumBlack900 => theme.textTheme.titleMedium!.copyWith(
color: appTheme.black900,
);
static get titleMediumSemiBold => theme.textTheme.titleMedium!.copyWith(
fontWeight: FontWeight.w600,
);
static get titleMediumWhiteA700 => theme.textTheme.titleMedium!.copyWith(
color: appTheme.whiteA700,
fontWeight: FontWeight.w600,
);
static get titleSmallBlue800 => theme.textTheme.titleSmall!.copyWith(
color: appTheme.blue800,
fontWeight: FontWeight.w800,
);
static get titleSmallBluegray800 => theme.textTheme.titleSmall!.copyWith(
color: appTheme.blueGray800,
);
static get titleSmallBluegray800Bold => theme.textTheme.titleSmall!.copyWith(
color: appTheme.blueGray800,
fontWeight: FontWeight.w700,
);
static get titleSmallBluegray800ExtraBold =>
theme.textTheme.titleSmall!.copyWith(
static get titleSmallBluegray800ExtraBold => theme.textTheme.titleSmall!.copyWith(
color: appTheme.blueGray800,
fontWeight: FontWeight.w800,
);
static get titleSmallBold => theme.textTheme.titleSmall!.copyWith(
fontSize: 15.fSize,
fontWeight: FontWeight.w700,
);
static get titleSmallGreenA70001 => theme.textTheme.titleSmall!.copyWith(
color: appTheme.greenA70001,
);
static get titleSmallGreenA70001ExtraBold =>
theme.textTheme.titleSmall!.copyWith(
static get titleSmallGreenA70001ExtraBold => theme.textTheme.titleSmall!.copyWith(
color: appTheme.greenA70001,
fontWeight: FontWeight.w800,
);
static get titleSmallLightgreen300 => theme.textTheme.titleSmall!.copyWith(
color: appTheme.lightGreen300,
fontWeight: FontWeight.w800,
);
static get titleSmallRed200 => theme.textTheme.titleSmall!.copyWith(
color: appTheme.red200,
fontWeight: FontWeight.w800,
);
static get titleSmallSecondaryContainer =>
theme.textTheme.titleSmall!.copyWith(
static get titleSmallSecondaryContainer => theme.textTheme.titleSmall!.copyWith(
color: theme.colorScheme.secondaryContainer,
fontWeight: FontWeight.w800,
);
static get titleSmallSecondaryContainer_1 =>
theme.textTheme.titleSmall!.copyWith(
static get titleSmallSecondaryContainer_1 => theme.textTheme.titleSmall!.copyWith(
color: theme.colorScheme.secondaryContainer,
);
static get titleSmallSegoeUIOnPrimary =>
theme.textTheme.titleSmall!.segoeUI.copyWith(
static get titleSmallSegoeUIOnPrimary => theme.textTheme.titleSmall!.segoeUI.copyWith(
color: theme.colorScheme.onPrimary,
);
}
extension on TextStyle {
TextStyle get mulish {
return copyWith(
fontFamily: 'Mulish',
);
return copyWith();
}
TextStyle get segoeUI {
return copyWith(
fontFamily: 'Segoe UI',
);
return copyWith();
}
}

View File

@@ -195,6 +195,8 @@ class PrimaryColors {
// White
Color get whiteA700 => Color(0XFFFFFFFF);
Color get backgroundAvatar => Color(0xFFEBF4FF);
}
PrimaryColors get appTheme => ThemeHelper().themeColor();

View File

@@ -31,9 +31,20 @@ dependencies:
go_router: ^14.1.4
keyboard_dismisser: ^3.0.0
freezed_annotation: ^2.4.1
json_annotation: ^4.9.0
retrofit: ^4.1.0
get_it: ^7.7.0
dio: ^5.4.3+1
dev_dependencies:
dart_code_metrics: ^5.7.6
dart_code_metrics_presets: ^1.8.0
build_runner: ^2.4.9
freezed: ^2.5.2
json_serializable: ^6.8.0
retrofit_generator: ^8.1.0
flutter_test:
sdk: flutter
@@ -43,13 +54,13 @@ flutter:
- assets/
- assets/images/
- .env
fonts:
fonts:
- family: Segoe UI
fonts:
fonts:
- asset: assets/fonts/SegoeUISemibold.ttf
weight: 600
- family: Mulish
fonts:
fonts:
- asset: assets/fonts/MulishBold.ttf
weight: 700
- asset: assets/fonts/MulishRegular.ttf