Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions lib/core/misc/json/json_search.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2025 BitCodersNN

import 'package:unn_mobile/core/misc/json/json_utils.dart';

T? findFirstNonNullNotesDeep<T>(dynamic data, String key) {
if (data is! JsonMap && data is! List) {
return null;
}

if (data is JsonMap && data.containsKey(key) && data[key] is T) {
return data[key]! as T;
}

Iterable<dynamic> items;
if (data is JsonMap) {
items = data.values;
} else {
items = data;
}

for (final item in items) {
final result = findFirstNonNullNotesDeep<T>(item, key);
if (result != null) {
return result;
}
}

return null;
}

void collectFirstValues(
dynamic data,
Set<String> keys,
JsonMap results,
) {
if (data is! JsonMap && data is! List) {
return;
}

if (results.length == keys.length) {
return;
}

Iterable<dynamic> items;
if (data is JsonMap) {
for (final key in keys) {
if (results.containsKey(key)) {
continue;
}
final value = data[key];
if (value != null) {
results[key] = value;
}
}
items = data.values;
} else {
items = data;
}

for (final item in items) {
collectFirstValues(item, keys, results);
if (results.length == keys.length) {
return;
}
}
}
19 changes: 11 additions & 8 deletions lib/core/models/profile/employee/employee_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,16 @@ import 'package:unn_mobile/core/models/profile/user_data.dart';

class _EmployeeDataJsonKeys {
static const String profiles = 'profiles';
static const String user = 'user';
static const String syncId = 'sync_id';
}

class EmployeeData extends UserData {
static Set<String> get jsonKeys => {
_EmployeeDataJsonKeys.syncId,
_EmployeeDataJsonKeys.profiles,
...UserData.jsonKeys,
};

final String syncId;
final List<EmployeeProfile> profiles;

Expand All @@ -25,6 +30,8 @@ class EmployeeData extends UserData {
required super.phone,
required super.sex,
required super.notes,
required super.web,
required super.birthdate,
required this.syncId,
required this.profiles,
});
Expand All @@ -43,6 +50,8 @@ class EmployeeData extends UserData {
sex: userData.sex,
photoSrc: userData.photoSrc,
notes: userData.notes,
web: userData.web,
birthdate: userData.birthdate,
);

@override
Expand All @@ -55,13 +64,7 @@ class EmployeeData extends UserData {
};

factory EmployeeData.fromJson(JsonMap json) => EmployeeData.withUserData(
userData: UserData.fromJson(
// Если сделать каст, ужасно ломается форматирование
// ignore: avoid_dynamic_calls
(json[_EmployeeDataJsonKeys.profiles]! as List)[0]
[_EmployeeDataJsonKeys.user] ??
json,
),
userData: UserData.fromJson(json),
syncId: json[_EmployeeDataJsonKeys.syncId]! as String,
profiles: [
for (final item in json[_EmployeeDataJsonKeys.profiles]! as List)
Expand Down
9 changes: 9 additions & 0 deletions lib/core/models/profile/student/base_edu_info.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ class _BaseEduInfoJsonKeys {
/// форму обучения, курс, уровень образования, факультет, направление подготовки,
/// учебную группу и, при наличии, специализацию.
class BaseEduInfo {
static Set<String> get jsonKeys => {
_BaseEduInfoJsonKeys.eduForm,
_BaseEduInfoJsonKeys.eduCourse,
_BaseEduInfoJsonKeys.eduLevel,
_BaseEduInfoJsonKeys.eduDirection,
_BaseEduInfoJsonKeys.eduGroup,
_BaseEduInfoJsonKeys.eduSpecialization,
_BaseEduInfoJsonKeys.faculty,
};
final String eduForm;
final int eduCourse;
final String eduLevel;
Expand Down
11 changes: 11 additions & 0 deletions lib/core/models/profile/student/student_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ class _StudentDataJsonKeys {
}

class StudentData extends UserData {
static Set<String> get jsonKeys => {
_StudentDataJsonKeys.eduStatus,
_StudentDataJsonKeys.eduYear,
...BaseEduInfo.jsonKeys,
...UserData.jsonKeys,
};

final BaseEduInfo baseEduInfo;
final String eduStatus;
final int eduYear;
Expand All @@ -25,6 +32,8 @@ class StudentData extends UserData {
required super.phone,
required super.sex,
required super.notes,
required super.web,
required super.birthdate,
required this.baseEduInfo,
required this.eduStatus,
required this.eduYear,
Expand All @@ -45,6 +54,8 @@ class StudentData extends UserData {
sex: userData.sex,
photoSrc: userData.photoSrc,
notes: userData.notes,
web: userData.web,
birthdate: userData.birthdate,
);

factory StudentData.fromJson(JsonMap json) => StudentData.withUserData(
Expand Down
23 changes: 23 additions & 0 deletions lib/core/models/profile/user_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,30 @@ class _UserDataJsonKeys {
static const String phone = 'phone';
static const String sex = 'sex';
static const String notes = 'notes';
static const String web = 'web';
static const String birthdate = 'birthdate';
}

class UserData extends UserShortInfo {
static Set<String> get jsonKeys => {
_UserDataJsonKeys.id,
_UserDataJsonKeys.login,
_UserDataJsonKeys.email,
_UserDataJsonKeys.phone,
_UserDataJsonKeys.sex,
_UserDataJsonKeys.notes,
_UserDataJsonKeys.web,
_UserDataJsonKeys.birthdate,
...UserShortInfo.profileJsonKeys,
};
final int userId;
final String? login;
final String? email;
final String? phone;
final String sex;
final String? notes;
final String? web;
final DateTime? birthdate;

UserData({
required super.bitrixId,
Expand All @@ -32,16 +47,20 @@ class UserData extends UserShortInfo {
required this.phone,
required this.sex,
required this.notes,
required this.web,
required this.birthdate,
});

UserData.withUserShortInfo({
required UserShortInfo userShortInfo,
required this.userId,
required this.sex,
this.birthdate,
this.login,
this.email,
this.phone,
this.notes,
this.web,
}) : super(
bitrixId: userShortInfo.bitrixId,
fullname: userShortInfo.fullname,
Expand All @@ -58,6 +77,10 @@ class UserData extends UserShortInfo {
phone: userJsonMap[_UserDataJsonKeys.phone] as String?,
sex: userJsonMap[_UserDataJsonKeys.sex]! as String,
notes: userJsonMap[_UserDataJsonKeys.notes] as String?,
web: userJsonMap[_UserDataJsonKeys.web] as String?,
birthdate: DateTime.tryParse(
userJsonMap[_UserDataJsonKeys.birthdate] as String? ?? '',
),
);
}

Expand Down
6 changes: 6 additions & 0 deletions lib/core/models/profile/user_short_info.dart
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ class UserShortInfo
BlogPostJsonSerializable,
MessageJsonSerializable,
ProfileJsonSerializable {
static const _profileJsonKeys = _ProfileUserInfoKeys();
static Set<String> get profileJsonKeys => {
_profileJsonKeys.fullname,
_profileJsonKeys.id,
_profileJsonKeys.photoSrc,
};
final int? bitrixId;
final String? fullname;
final String? photoSrc;
Expand Down
38 changes: 27 additions & 11 deletions lib/core/services/implementations/profile/profile_service_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'package:unn_mobile/core/constants/profiles_strings.dart';
import 'package:unn_mobile/core/misc/dio_interceptor/response_data_type.dart';
import 'package:unn_mobile/core/misc/dio_interceptor/response_type_interceptor.dart';
import 'package:unn_mobile/core/misc/dio_options_factory/options_with_expected_type_factory.dart';
import 'package:unn_mobile/core/misc/json/json_search.dart';
import 'package:unn_mobile/core/misc/json/json_utils.dart';
import 'package:unn_mobile/core/models/profile/employee/employee_data.dart';
import 'package:unn_mobile/core/models/profile/student/student_data.dart';
Expand Down Expand Up @@ -40,31 +41,32 @@ class ProfileServiceImpl implements ProfileService {
return null;
}

final data = response.data as JsonMap;
final userType = data[ProfilesStrings.type] ??
((data[ProfilesStrings.profilesKey]! as List)[0]
final responseData = response.data as JsonMap;
final userType = responseData[ProfilesStrings.type] ??
((responseData[ProfilesStrings.profilesKey]! as List)[0]
as JsonMap)[ProfilesStrings.type];

UserData? userData;
try {
userData = switch (userType) {
ProfilesStrings.student => StudentData.fromJson(response.data),
ProfilesStrings.employee => EmployeeData.fromJson(response.data),
_ => UserData.fromJson(response.data),
ProfilesStrings.student =>
StudentData.fromJson(_getStudentJson(responseData)),
ProfilesStrings.employee =>
EmployeeData.fromJson(_getEmployeeJson(responseData)),
_ => UserData.fromJson(_getUserJson(responseData)),
};
} catch (error, stackTrace) {
_loggerService.logError(
error,
stackTrace,
information: [response.data.toString()],
information: [responseData.toString()],
);
}

return userData;
}

@override
Future<UserData?> getProfileByBitrixId(int bitrixId) async {
Future<UserData?> getProfileByBitrixId({required int bitrixId}) async {
final userId = await _getUserIdByBitrixId(bitrixId: bitrixId);
if (userId == null) {
return null;
Expand All @@ -74,11 +76,11 @@ class ProfileServiceImpl implements ProfileService {

@override
Future<UserData?> getProfileByAuthorId({required int authorId}) =>
getProfileByBitrixId(authorId);
getProfileByBitrixId(bitrixId: authorId);

@override
Future<UserData?> getProfileByDialogId({required int dialogId}) =>
getProfileByBitrixId(dialogId);
getProfileByBitrixId(bitrixId: dialogId);

Future<int?> _getUserIdByBitrixId({required int bitrixId}) async {
final path =
Expand Down Expand Up @@ -108,4 +110,18 @@ class ProfileServiceImpl implements ProfileService {

return id;
}

JsonMap _extractJson(JsonMap json, Set<String> keys) {
final JsonMap results = {};
collectFirstValues(json, keys, results);
return results;
}

JsonMap _getStudentJson(JsonMap json) =>
_extractJson(json, StudentData.jsonKeys);

JsonMap _getEmployeeJson(JsonMap json) =>
_extractJson(json, EmployeeData.jsonKeys);

JsonMap _getUserJson(JsonMap json) => _extractJson(json, UserData.jsonKeys);
}
2 changes: 1 addition & 1 deletion lib/core/services/interfaces/profile/profile_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ abstract interface class ProfileService {
/// Возвращает [StudentData] или [EmployeeData] — наследников [UserData], или null, если:
/// 1. Не удалось получить userId по bitrixId (ошибка API, отсутствие id в ответе)
/// 2. Не вышло получить профиль по найденному userId (ошибка API, некорректный ответ, ошибка декодирования)
Future<UserData?> getProfileByBitrixId(int bitrixId);
Future<UserData?> getProfileByBitrixId({required int bitrixId});

/// Получает профиль по id автора поста или комменатрия
///
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: unn_mobile
description: A mobile application for UNN Portal website
publish_to: 'none'

version: 0.6.0+375
version: 0.6.0+376

environment:
sdk: '>=3.1.2 <4.0.0'
Expand Down