Added locate device screen, state and endpoints

This commit is contained in:
2026-02-12 15:48:11 +01:00
parent f8ff70c35d
commit a53cfb24ea
25 changed files with 1295 additions and 32 deletions

View File

@@ -62,6 +62,11 @@ void configureAppRouter() {
name: 'remote_connection',
pageBuilder: RemoteConnectionBuilder().buildPage,
),
GoRoute(
path: AppRoutes.locateDevice,
name: 'locate_device',
pageBuilder: LocateDeviceBuilder().buildPage,
),
GoRoute(
path: AppRoutes.login,

View File

@@ -1,3 +1,4 @@
import 'package:functions/src/core/data/models/entities/locate_device_request_entity.dart';
import 'package:functions/src/features/contacts/domain/entities/contact_entity.dart';
import 'package:functions/src/features/remote_connection/domain/entities/picture_entity.dart';
@@ -7,4 +8,6 @@ abstract class FunctionsRemoteDatasource {
Future<List<PictureEntity>> getPictures({required String userId});
Future<PictureEntity> takePicture({required String userId});
Future<void> locateDevice({required LocateDeviceRequestEntity request});
}

View File

@@ -3,6 +3,8 @@ import 'dart:convert';
import 'package:dio/dio.dart';
// import 'package:flutter/material.dart';
import 'package:functions/src/core/data/datasources/functions_remote_datasource.dart';
import 'package:functions/src/core/data/models/entities/locate_device_request_entity.dart';
import 'package:functions/src/core/data/models/send_command_request_model.dart';
import 'package:functions/src/features/contacts/domain/entities/contact_entity.dart';
import 'package:functions/src/features/remote_connection/domain/entities/picture_entity.dart';
import 'package:sf_infrastructure/sf_infrastructure.dart';
@@ -92,6 +94,22 @@ class FunctionsRemoteDatasourceImpl implements FunctionsRemoteDatasource {
}*/
return PictureEntity(id: '1', userId: '1111', createdAt: 1111);
}
@override
Future<void> locateDevice({required LocateDeviceRequestEntity request}) async {
try {
final body = request.toModel().toJson();
await _repository.post<void>(
'/commands',
body: body,
);
} on DioException catch (error) {
throw _mapDioError(
error,
defaultMessage: error.response?.data ?? 'Error to locate device',
);
}
}
}
Exception _mapDioError(DioException error, {required String defaultMessage}) {

View File

@@ -0,0 +1,11 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'locate_device_request_entity.freezed.dart';
@freezed
abstract class LocateDeviceRequestEntity with _$LocateDeviceRequestEntity {
const factory LocateDeviceRequestEntity({
required String deviceName,
}) = _LocateDeviceRequestEntity;
}

View File

@@ -0,0 +1,274 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
// coverage:ignore-file
// 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 'locate_device_request_entity.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
// dart format off
T _$identity<T>(T value) => value;
/// @nodoc
mixin _$LocateDeviceRequestEntity {
String get deviceName; dynamic get command;
/// Create a copy of LocateDeviceRequestEntity
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$LocateDeviceRequestEntityCopyWith<LocateDeviceRequestEntity> get copyWith => _$LocateDeviceRequestEntityCopyWithImpl<LocateDeviceRequestEntity>(this as LocateDeviceRequestEntity, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is LocateDeviceRequestEntity&&(identical(other.deviceName, deviceName) || other.deviceName == deviceName)&&const DeepCollectionEquality().equals(other.command, command));
}
@override
int get hashCode => Object.hash(runtimeType,deviceName,const DeepCollectionEquality().hash(command));
@override
String toString() {
return 'LocateDeviceRequestEntity(deviceName: $deviceName, command: $command)';
}
}
/// @nodoc
abstract mixin class $LocateDeviceRequestEntityCopyWith<$Res> {
factory $LocateDeviceRequestEntityCopyWith(LocateDeviceRequestEntity value, $Res Function(LocateDeviceRequestEntity) _then) = _$LocateDeviceRequestEntityCopyWithImpl;
@useResult
$Res call({
String deviceName, dynamic command
});
}
/// @nodoc
class _$LocateDeviceRequestEntityCopyWithImpl<$Res>
implements $LocateDeviceRequestEntityCopyWith<$Res> {
_$LocateDeviceRequestEntityCopyWithImpl(this._self, this._then);
final LocateDeviceRequestEntity _self;
final $Res Function(LocateDeviceRequestEntity) _then;
/// Create a copy of LocateDeviceRequestEntity
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? deviceName = null,Object? command = freezed,}) {
return _then(_self.copyWith(
deviceName: null == deviceName ? _self.deviceName : deviceName // ignore: cast_nullable_to_non_nullable
as String,command: freezed == command ? _self.command : command // ignore: cast_nullable_to_non_nullable
as dynamic,
));
}
}
/// Adds pattern-matching-related methods to [LocateDeviceRequestEntity].
extension LocateDeviceRequestEntityPatterns on LocateDeviceRequestEntity {
/// A variant of `map` that fallback to returning `orElse`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _LocateDeviceRequestEntity value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _LocateDeviceRequestEntity() when $default != null:
return $default(_that);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case final Subclass2 value:
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _LocateDeviceRequestEntity value) $default,){
final _that = this;
switch (_that) {
case _LocateDeviceRequestEntity():
return $default(_that);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _LocateDeviceRequestEntity value)? $default,){
final _that = this;
switch (_that) {
case _LocateDeviceRequestEntity() when $default != null:
return $default(_that);case _:
return null;
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String deviceName, dynamic command)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _LocateDeviceRequestEntity() when $default != null:
return $default(_that.deviceName,_that.command);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case Subclass2(:final field2):
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String deviceName, dynamic command) $default,) {final _that = this;
switch (_that) {
case _LocateDeviceRequestEntity():
return $default(_that.deviceName,_that.command);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `when` that fallback to returning `null`
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String deviceName, dynamic command)? $default,) {final _that = this;
switch (_that) {
case _LocateDeviceRequestEntity() when $default != null:
return $default(_that.deviceName,_that.command);case _:
return null;
}
}
}
/// @nodoc
class _LocateDeviceRequestEntity implements LocateDeviceRequestEntity {
const _LocateDeviceRequestEntity({required this.deviceName, this.command});
@override final String deviceName;
@override final dynamic command;
/// Create a copy of LocateDeviceRequestEntity
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$LocateDeviceRequestEntityCopyWith<_LocateDeviceRequestEntity> get copyWith => __$LocateDeviceRequestEntityCopyWithImpl<_LocateDeviceRequestEntity>(this, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _LocateDeviceRequestEntity&&(identical(other.deviceName, deviceName) || other.deviceName == deviceName)&&const DeepCollectionEquality().equals(other.command, command));
}
@override
int get hashCode => Object.hash(runtimeType,deviceName,const DeepCollectionEquality().hash(command));
@override
String toString() {
return 'LocateDeviceRequestEntity(deviceName: $deviceName, command: $command)';
}
}
/// @nodoc
abstract mixin class _$LocateDeviceRequestEntityCopyWith<$Res> implements $LocateDeviceRequestEntityCopyWith<$Res> {
factory _$LocateDeviceRequestEntityCopyWith(_LocateDeviceRequestEntity value, $Res Function(_LocateDeviceRequestEntity) _then) = __$LocateDeviceRequestEntityCopyWithImpl;
@override @useResult
$Res call({
String deviceName, dynamic command
});
}
/// @nodoc
class __$LocateDeviceRequestEntityCopyWithImpl<$Res>
implements _$LocateDeviceRequestEntityCopyWith<$Res> {
__$LocateDeviceRequestEntityCopyWithImpl(this._self, this._then);
final _LocateDeviceRequestEntity _self;
final $Res Function(_LocateDeviceRequestEntity) _then;
/// Create a copy of LocateDeviceRequestEntity
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? deviceName = null,Object? command = freezed,}) {
return _then(_LocateDeviceRequestEntity(
deviceName: null == deviceName ? _self.deviceName : deviceName // ignore: cast_nullable_to_non_nullable
as String,command: freezed == command ? _self.command : command // ignore: cast_nullable_to_non_nullable
as dynamic,
));
}
}
// dart format on

View File

@@ -0,0 +1,24 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:functions/src/core/data/models/entities/locate_device_request_entity.dart';
part 'send_command_request_model.freezed.dart';
part 'send_command_request_model.g.dart';
@freezed
abstract class SendCommandRequestModel with _$SendCommandRequestModel {
const factory SendCommandRequestModel({
required String deviceName,
required String command,
}) = _SendCommandRequestModel;
factory SendCommandRequestModel.fromJson(Map<String, dynamic> json) =>
_$SendCommandRequestModelFromJson(json);
}
extension SendCommandRequestModelMapper on LocateDeviceRequestEntity {
SendCommandRequestModel toModel() => SendCommandRequestModel(
deviceName: deviceName,
command: 'FIND_DEVICE',
);
}

View File

@@ -0,0 +1,280 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
// coverage:ignore-file
// 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 'send_command_request_model.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
// dart format off
T _$identity<T>(T value) => value;
/// @nodoc
mixin _$SendCommandRequestModel {
String get deviceName; String get command;
/// Create a copy of SendCommandRequestModel
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$SendCommandRequestModelCopyWith<SendCommandRequestModel> get copyWith => _$SendCommandRequestModelCopyWithImpl<SendCommandRequestModel>(this as SendCommandRequestModel, _$identity);
/// Serializes this SendCommandRequestModel to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SendCommandRequestModel&&(identical(other.deviceName, deviceName) || other.deviceName == deviceName)&&(identical(other.command, command) || other.command == command));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,deviceName,command);
@override
String toString() {
return 'SendCommandRequestModel(deviceName: $deviceName, command: $command)';
}
}
/// @nodoc
abstract mixin class $SendCommandRequestModelCopyWith<$Res> {
factory $SendCommandRequestModelCopyWith(SendCommandRequestModel value, $Res Function(SendCommandRequestModel) _then) = _$SendCommandRequestModelCopyWithImpl;
@useResult
$Res call({
String deviceName, String command
});
}
/// @nodoc
class _$SendCommandRequestModelCopyWithImpl<$Res>
implements $SendCommandRequestModelCopyWith<$Res> {
_$SendCommandRequestModelCopyWithImpl(this._self, this._then);
final SendCommandRequestModel _self;
final $Res Function(SendCommandRequestModel) _then;
/// Create a copy of SendCommandRequestModel
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? deviceName = null,Object? command = null,}) {
return _then(_self.copyWith(
deviceName: null == deviceName ? _self.deviceName : deviceName // ignore: cast_nullable_to_non_nullable
as String,command: null == command ? _self.command : command // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
/// Adds pattern-matching-related methods to [SendCommandRequestModel].
extension SendCommandRequestModelPatterns on SendCommandRequestModel {
/// A variant of `map` that fallback to returning `orElse`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _SendCommandRequestModel value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _SendCommandRequestModel() when $default != null:
return $default(_that);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case final Subclass2 value:
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _SendCommandRequestModel value) $default,){
final _that = this;
switch (_that) {
case _SendCommandRequestModel():
return $default(_that);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _SendCommandRequestModel value)? $default,){
final _that = this;
switch (_that) {
case _SendCommandRequestModel() when $default != null:
return $default(_that);case _:
return null;
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String deviceName, String command)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _SendCommandRequestModel() when $default != null:
return $default(_that.deviceName,_that.command);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case Subclass2(:final field2):
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String deviceName, String command) $default,) {final _that = this;
switch (_that) {
case _SendCommandRequestModel():
return $default(_that.deviceName,_that.command);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `when` that fallback to returning `null`
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String deviceName, String command)? $default,) {final _that = this;
switch (_that) {
case _SendCommandRequestModel() when $default != null:
return $default(_that.deviceName,_that.command);case _:
return null;
}
}
}
/// @nodoc
@JsonSerializable()
class _SendCommandRequestModel implements SendCommandRequestModel {
const _SendCommandRequestModel({required this.deviceName, required this.command});
factory _SendCommandRequestModel.fromJson(Map<String, dynamic> json) => _$SendCommandRequestModelFromJson(json);
@override final String deviceName;
@override final String command;
/// Create a copy of SendCommandRequestModel
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$SendCommandRequestModelCopyWith<_SendCommandRequestModel> get copyWith => __$SendCommandRequestModelCopyWithImpl<_SendCommandRequestModel>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$SendCommandRequestModelToJson(this, );
}
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SendCommandRequestModel&&(identical(other.deviceName, deviceName) || other.deviceName == deviceName)&&(identical(other.command, command) || other.command == command));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,deviceName,command);
@override
String toString() {
return 'SendCommandRequestModel(deviceName: $deviceName, command: $command)';
}
}
/// @nodoc
abstract mixin class _$SendCommandRequestModelCopyWith<$Res> implements $SendCommandRequestModelCopyWith<$Res> {
factory _$SendCommandRequestModelCopyWith(_SendCommandRequestModel value, $Res Function(_SendCommandRequestModel) _then) = __$SendCommandRequestModelCopyWithImpl;
@override @useResult
$Res call({
String deviceName, String command
});
}
/// @nodoc
class __$SendCommandRequestModelCopyWithImpl<$Res>
implements _$SendCommandRequestModelCopyWith<$Res> {
__$SendCommandRequestModelCopyWithImpl(this._self, this._then);
final _SendCommandRequestModel _self;
final $Res Function(_SendCommandRequestModel) _then;
/// Create a copy of SendCommandRequestModel
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? deviceName = null,Object? command = null,}) {
return _then(_SendCommandRequestModel(
deviceName: null == deviceName ? _self.deviceName : deviceName // ignore: cast_nullable_to_non_nullable
as String,command: null == command ? _self.command : command // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
// dart format on

View File

@@ -0,0 +1,21 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'send_command_request_model.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_SendCommandRequestModel _$SendCommandRequestModelFromJson(
Map<String, dynamic> json,
) => _SendCommandRequestModel(
deviceName: json['deviceName'] as String,
command: json['command'] as String,
);
Map<String, dynamic> _$SendCommandRequestModelToJson(
_SendCommandRequestModel instance,
) => <String, dynamic>{
'deviceName': instance.deviceName,
'command': instance.command,
};

View File

@@ -1,4 +1,5 @@
import 'package:functions/src/core/data/datasources/functions_remote_datasource.dart';
import 'package:functions/src/core/data/models/entities/locate_device_request_entity.dart';
import 'package:functions/src/core/domain/repositories/functions_repository.dart';
import 'package:functions/src/features/contacts/domain/entities/contact_entity.dart';
import 'package:functions/src/features/remote_connection/domain/entities/picture_entity.dart';
@@ -24,4 +25,10 @@ class FunctionsRepositoryImpl implements FunctionsRepository {
await Future<void>.delayed(const Duration(milliseconds: 2000));
return _remote.takePicture(userId: userId);
}
@override
Future<void> locateDevice({required LocateDeviceRequestEntity request}) async {
await Future<void>.delayed(const Duration(milliseconds: 2000));
return _remote.locateDevice(request: request);
}
}

View File

@@ -1,3 +1,4 @@
import 'package:functions/src/core/data/models/entities/locate_device_request_entity.dart';
import 'package:functions/src/features/contacts/domain/entities/contact_entity.dart';
import 'package:functions/src/features/remote_connection/domain/entities/picture_entity.dart';
@@ -7,4 +8,6 @@ abstract class FunctionsRepository {
Future<List<PictureEntity>> getPictures({required String userId});
Future<PictureEntity> takePicture({required String userId});
Future<void> locateDevice({required LocateDeviceRequestEntity request});
}

View File

@@ -70,12 +70,6 @@ class FunctionsScreen extends ConsumerWidget {
text: 'Do not disturb'
),
SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)),
AppSectionButton(
onPressed: (){},
icon: SFIcons.locationAreaCircle,
text: 'Safety zone'
),
SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)),
AppSectionButton(
onPressed: (){},
icon: SFIcons.videoCallCircle,
@@ -84,19 +78,13 @@ class FunctionsScreen extends ConsumerWidget {
SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)),
AppSectionButton(
onPressed: (){},
icon: SFIcons.fallCircle,
text: 'Fall notice'
icon: SFIcons.healthCircle,
text: 'Health'
),
SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)),
AppSectionButton(
onPressed: (){},
icon: SFIcons.medicationCircle,
text: 'Medication reminder'
),
SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)),
AppSectionButton(
onPressed: (){},
icon: SFIcons.activityCircle,
icon: SFIcons.healthCircle,
text: 'Activity meter'
),
SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)),
@@ -108,6 +96,30 @@ class FunctionsScreen extends ConsumerWidget {
SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)),
AppSectionButton(
onPressed: (){},
icon: Icons.call_outlined,
text: 'Call watch'
),
SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)),
AppSectionButton(
onPressed: (){},
icon: SFIcons.screenTime,
text: 'Apps use'
),
SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)),
AppSectionButton(
onPressed: (){},
icon: Icons.app_registration_sharp,
text: 'Apps supervision'
),
SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)),
AppSectionButton(
onPressed: (){},
icon: SFIcons.friendsCircle,
text: 'Make friends'
),
SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)),
AppSectionButton(
onPressed: (){navigationContract.pushTo(AppRoutes.locateDevice);},
icon: SFIcons.locateSfCircle,
text: 'Locate your SaveFamily'
),

View File

@@ -0,0 +1,5 @@
import 'package:functions/src/core/data/models/entities/locate_device_request_entity.dart';
abstract class LocateDeviceUseCase {
Future<void> locateDevice({required LocateDeviceRequestEntity request});
}

View File

@@ -0,0 +1,14 @@
import 'package:functions/src/core/data/models/entities/locate_device_request_entity.dart';
import 'package:functions/src/core/domain/repositories/functions_repository.dart';
import 'package:functions/src/features/locate_device/domain/locate_device_use_case.dart';
class LocateDeviceUseCaseImpl implements LocateDeviceUseCase {
LocateDeviceUseCaseImpl(this._repository);
final FunctionsRepository _repository;
@override
Future<void> locateDevice({required LocateDeviceRequestEntity request}) async {
return _repository.locateDevice(request: request);
}
}

View File

@@ -0,0 +1,18 @@
import 'package:flutter/material.dart';
import 'package:functions/src/features/locate_device/presentation/locate_device_screen.dart';
import 'package:go_router/go_router.dart';
import 'package:get_it/get_it.dart';
import 'package:navigation/navigation.dart';
class LocateDeviceBuilder {
const LocateDeviceBuilder();
Page<void> buildPage(BuildContext context, GoRouterState state) {
final NavigationContract navigationContract = GetIt.I<NavigationContract>();
return MaterialPage<void>(
key: state.pageKey,
child: LocateDeviceScreen(navigationContract: navigationContract),
);
}
}

View File

@@ -0,0 +1,148 @@
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:functions/src/features/locate_device/presentation/state/locate_device_view_model.dart';
import 'package:navigation/navigation.dart';
import 'package:sf_localizations/sf_localizations.dart';
import 'package:utils/utils.dart';
import 'package:legacy_shared/legacy_shared.dart';
class LocateDeviceScreen extends ConsumerWidget {
final NavigationContract navigationContract;
const LocateDeviceScreen({super.key, required this.navigationContract});
@override
Widget build(BuildContext context, WidgetRef ref) {
return PageLayout(
title: context.translate('Find your device'),
body: Container(
padding: SizeUtils.getByScreen(
small: EdgeInsets.symmetric(horizontal: 16),
big: EdgeInsets.symmetric(horizontal: 15)
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(context.translate('Locate your SaveFamily in nearby locations'),
style: TextStyle(
fontSize: SizeUtils.getByScreen(small: 18, big: 17),
fontWeight: FontWeight.w500,
)
),
SizedBox(height: SizeUtils.getByScreen(small: 10, big: 8)),
Text('This function allows you to find the device indoors or in places close to you. When you press the button, the smartwatch will start beeping and you will be able to hear it.',
style: TextStyle(
fontSize: 16
))
],
),
),
footer: Container(
padding: SizeUtils.getByScreen(
small: EdgeInsets.symmetric(vertical: 12, horizontal: 26),
big: EdgeInsets.symmetric(vertical: 10, horizontal: 25)
),
child: PrimaryButton(
onPressed: () {
showDialog(context: context, builder: (context)=>Dialog(
child: LocateDialog(),
));
},
text: context.translate('Locate my SaveFamily'),
color: Color(0xFF588EA5),
height: SizeUtils.getByScreen(small: 36, big: 35),
),
)
);
}
}
class LocateDialog extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final viewModel = ref.read(locateDeviceViewModelProvider.notifier);
final viewState = ref.watch(locateDeviceViewModelProvider);
return Container(
padding: SizeUtils.getByScreen(
small: EdgeInsets.symmetric(horizontal: 32, vertical: 30),
big: EdgeInsets.symmetric(horizontal: 30, vertical: 28)
),
width: SizeUtils.getByScreen(small: 360, big: 350),
height: SizeUtils.getByScreen(small: 210, big: 205),
child: Column(
children: [
if (viewState.isLoading)
Expanded(child: Center(child: Text(context.translate('Sending...'),
textAlign: TextAlign.center,
style: TextStyle(
fontSize: SizeUtils.getByScreen(small: 25, big: 24),
),
))),
if (viewState.isComplete)
Expanded(child: Center(child: Text(context.translate('Sent successfully'),
textAlign: TextAlign.center,
style: TextStyle(
fontSize: SizeUtils.getByScreen(small: 25, big: 24),
),
))),
if (viewState.errorMessage.isNotEmpty) ...[
Expanded(child: Center(child: Text(context.translate('The device is not connected to the Internet'),
textAlign: TextAlign.center,
style: TextStyle(
fontSize: SizeUtils.getByScreen(small: 20, big: 19),
),
))),
SizedBox(height: SizeUtils.getByScreen(small: 24, big: 23)),
Expanded(child: PrimaryButton(
onPressed: (){
Navigator.pop(context);
viewModel.endLocation();
},
text: context.translate('OK'),
color: Color(0xFF588EA5),
height: SizeUtils.getByScreen(small: 38, big: 36),
radius: SizeUtils.getByScreen(small: 32, big: 34),
)),
],
if (!viewState.isComplete && !viewState.isLoading && viewState.errorMessage.isEmpty) ...[
Text(context.translate('You are going to activate the remote location of your device. It will start ringing.'),
textAlign: TextAlign.center,
style: TextStyle(
fontSize: SizeUtils.getByScreen(small: 19, big: 18),
),
),
SizedBox(height: SizeUtils.getByScreen(small: 24, big: 23)),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(child: PrimaryButton(
onPressed: (){Navigator.pop(context);},
text: context.translate(I18n.legacyCancel),
color: Color(0xFF588EA5),
height: SizeUtils.getByScreen(small: 38, big: 36),
radius: SizeUtils.getByScreen(small: 32, big: 34),
)),
SizedBox(width: SizeUtils.getByScreen(small: 4, big: 16)),
Expanded(child: PrimaryButton(
onPressed: () {
viewModel.locateDevice();
},
text: context.translate(I18n.accept),
color: Color(0xFF588EA5),
height: SizeUtils.getByScreen(small: 38, big: 36),
radius: SizeUtils.getByScreen(small: 32, big: 34),
))
],
)
]
],
),
);
}
}

View File

@@ -0,0 +1,9 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:functions/src/core/providers/functions_repository_provider.dart';
import 'package:functions/src/features/locate_device/domain/locate_device_use_case.dart';
import 'package:functions/src/features/locate_device/domain/locate_device_use_case_impl.dart';
final locateDeviceUseCaseProvider = Provider.autoDispose<LocateDeviceUseCase>((ref) {
final functionsRepository = ref.read(functionsRepositoryProvider);
return LocateDeviceUseCaseImpl(functionsRepository);
});

View File

@@ -0,0 +1,62 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:functions/src/core/data/models/entities/locate_device_request_entity.dart';
import 'package:functions/src/features/locate_device/domain/locate_device_use_case.dart';
import 'package:functions/src/features/locate_device/presentation/providers/locate_device_use_case_provider.dart';
import 'package:functions/src/features/locate_device/presentation/state/locate_device_view_state.dart';
// import 'package:legacy_shared/src/providers/logged_user_provider.dart';
// import 'package:sf_localizations/sf_localizations.dart';
final locateDeviceViewModelProvider =
NotifierProvider.autoDispose<LocateDeviceViewModel, LocateDeviceViewState>(
LocateDeviceViewModel.new,
);
class LocateDeviceViewModel extends Notifier<LocateDeviceViewState> {
late final LocateDeviceUseCase _locateDeviceUseCase;
late final TextEditingController nameController;
late final TextEditingController phoneController;
// late final UserEntity loggedUser;
@override
LocateDeviceViewState build() {
_locateDeviceUseCase = ref.read(locateDeviceUseCaseProvider);
// loggedUser = ref.read(loggedUserProvider);
return const LocateDeviceViewState();
}
Future<void> locateDevice() async {
try {
state = state.copyWith(
isLoading: true,
isComplete: false,
errorMessage: '',
);
LocateDeviceRequestEntity request = LocateDeviceRequestEntity(deviceName: '');
await _locateDeviceUseCase.locateDevice(request: request);
state = state.copyWith(
isLoading: false,
isComplete: true,
);
} catch (e) {
state = state.copyWith(
isLoading: false,
isComplete: false,
errorMessage: e.toString(),
);
}
}
void endLocation() {
state = state.copyWith(
errorMessage: '',
);
}
}

View File

@@ -0,0 +1,11 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'locate_device_view_state.freezed.dart';
@freezed
abstract class LocateDeviceViewState with _$LocateDeviceViewState {
const factory LocateDeviceViewState({
@Default(false) bool isLoading,
@Default(false) bool isComplete,
@Default('') String errorMessage,
}) = _LocateDeviceViewState;
}

View File

@@ -0,0 +1,277 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
// coverage:ignore-file
// 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 'locate_device_view_state.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
// dart format off
T _$identity<T>(T value) => value;
/// @nodoc
mixin _$LocateDeviceViewState {
bool get isLoading; bool get isComplete; String get errorMessage;
/// Create a copy of LocateDeviceViewState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$LocateDeviceViewStateCopyWith<LocateDeviceViewState> get copyWith => _$LocateDeviceViewStateCopyWithImpl<LocateDeviceViewState>(this as LocateDeviceViewState, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is LocateDeviceViewState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isComplete, isComplete) || other.isComplete == isComplete)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage));
}
@override
int get hashCode => Object.hash(runtimeType,isLoading,isComplete,errorMessage);
@override
String toString() {
return 'LocateDeviceViewState(isLoading: $isLoading, isComplete: $isComplete, errorMessage: $errorMessage)';
}
}
/// @nodoc
abstract mixin class $LocateDeviceViewStateCopyWith<$Res> {
factory $LocateDeviceViewStateCopyWith(LocateDeviceViewState value, $Res Function(LocateDeviceViewState) _then) = _$LocateDeviceViewStateCopyWithImpl;
@useResult
$Res call({
bool isLoading, bool isComplete, String errorMessage
});
}
/// @nodoc
class _$LocateDeviceViewStateCopyWithImpl<$Res>
implements $LocateDeviceViewStateCopyWith<$Res> {
_$LocateDeviceViewStateCopyWithImpl(this._self, this._then);
final LocateDeviceViewState _self;
final $Res Function(LocateDeviceViewState) _then;
/// Create a copy of LocateDeviceViewState
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? isLoading = null,Object? isComplete = null,Object? errorMessage = null,}) {
return _then(_self.copyWith(
isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
as bool,isComplete: null == isComplete ? _self.isComplete : isComplete // ignore: cast_nullable_to_non_nullable
as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
/// Adds pattern-matching-related methods to [LocateDeviceViewState].
extension LocateDeviceViewStatePatterns on LocateDeviceViewState {
/// A variant of `map` that fallback to returning `orElse`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _LocateDeviceViewState value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _LocateDeviceViewState() when $default != null:
return $default(_that);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case final Subclass2 value:
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _LocateDeviceViewState value) $default,){
final _that = this;
switch (_that) {
case _LocateDeviceViewState():
return $default(_that);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _LocateDeviceViewState value)? $default,){
final _that = this;
switch (_that) {
case _LocateDeviceViewState() when $default != null:
return $default(_that);case _:
return null;
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( bool isLoading, bool isComplete, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _LocateDeviceViewState() when $default != null:
return $default(_that.isLoading,_that.isComplete,_that.errorMessage);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case Subclass2(:final field2):
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( bool isLoading, bool isComplete, String errorMessage) $default,) {final _that = this;
switch (_that) {
case _LocateDeviceViewState():
return $default(_that.isLoading,_that.isComplete,_that.errorMessage);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `when` that fallback to returning `null`
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( bool isLoading, bool isComplete, String errorMessage)? $default,) {final _that = this;
switch (_that) {
case _LocateDeviceViewState() when $default != null:
return $default(_that.isLoading,_that.isComplete,_that.errorMessage);case _:
return null;
}
}
}
/// @nodoc
class _LocateDeviceViewState implements LocateDeviceViewState {
const _LocateDeviceViewState({this.isLoading = false, this.isComplete = false, this.errorMessage = ''});
@override@JsonKey() final bool isLoading;
@override@JsonKey() final bool isComplete;
@override@JsonKey() final String errorMessage;
/// Create a copy of LocateDeviceViewState
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$LocateDeviceViewStateCopyWith<_LocateDeviceViewState> get copyWith => __$LocateDeviceViewStateCopyWithImpl<_LocateDeviceViewState>(this, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _LocateDeviceViewState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isComplete, isComplete) || other.isComplete == isComplete)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage));
}
@override
int get hashCode => Object.hash(runtimeType,isLoading,isComplete,errorMessage);
@override
String toString() {
return 'LocateDeviceViewState(isLoading: $isLoading, isComplete: $isComplete, errorMessage: $errorMessage)';
}
}
/// @nodoc
abstract mixin class _$LocateDeviceViewStateCopyWith<$Res> implements $LocateDeviceViewStateCopyWith<$Res> {
factory _$LocateDeviceViewStateCopyWith(_LocateDeviceViewState value, $Res Function(_LocateDeviceViewState) _then) = __$LocateDeviceViewStateCopyWithImpl;
@override @useResult
$Res call({
bool isLoading, bool isComplete, String errorMessage
});
}
/// @nodoc
class __$LocateDeviceViewStateCopyWithImpl<$Res>
implements _$LocateDeviceViewStateCopyWith<$Res> {
__$LocateDeviceViewStateCopyWithImpl(this._self, this._then);
final _LocateDeviceViewState _self;
final $Res Function(_LocateDeviceViewState) _then;
/// Create a copy of LocateDeviceViewState
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? isLoading = null,Object? isComplete = null,Object? errorMessage = null,}) {
return _then(_LocateDeviceViewState(
isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
as bool,isComplete: null == isComplete ? _self.isComplete : isComplete // ignore: cast_nullable_to_non_nullable
as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
// dart format on

View File

@@ -47,7 +47,7 @@ class LegacyDashboardScreen extends ConsumerWidget {
label: context.translate(I18n.functions),
),
NavigationDestination(
icon: Icon(Icons.location_on_outlined),
icon: Icon(SFIcons.locationOutlined),
label: context.translate(I18n.location),
),
NavigationDestination(

View File

@@ -41,7 +41,7 @@ class PageLayout extends StatelessWidget{
),
),
SizedBox(height: SizeUtils.getByScreen(small: 30, big: 28)),
body,
Expanded(child: body),
?footer
],
)

View File

@@ -1076,20 +1076,6 @@
"icon"
]
},
{
"uid": "d9ab0ada4a6bda3f4f974dd8d154b5bf",
"css": "activityCircle",
"code": 59527,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M672.8 298.3C624.2 285.8 582.8 302.2 550.3 339.4 532.9 359.4 517.4 381.4 500 404.1 479.6 378.4 462.6 353.5 442.2 331.8 398.2 285.1 325.6 281.9 279.9 322.3 231.3 365.6 226.3 433.3 269.7 484.6 334.8 562.1 400.1 639 465.5 716.2 475.7 728.3 486.2 740.5 497 753.6 577.9 660.3 657 569.6 735.2 478.3 757.2 452.4 764.1 420.2 756.9 386.7 747 340.7 718.5 310.1 672.8 298.3ZM500 0C224 0 0 223.7 0 500 0 776.3 224 1000 500 1000 776.3 1000 1000 776 1000 500 1000.3 223.7 776.3 0 500 0ZM776.6 522C693.8 618.6 610.1 714.2 526.6 810.1 503.6 836.4 489.8 836.1 467.8 810.1 385.7 713.2 303.5 616 221.4 518.7 176.4 465.5 169.5 388.6 203 326.2 235.2 265.8 302.6 230.3 371.2 236.5 423.8 241.5 465.5 265.4 500.7 306.5 535.1 265.8 576.5 241.8 628.5 236.9 698.8 230.3 765.8 265.4 798 326.5 831.5 391.3 824.2 466.5 776.6 522Z",
"width": 1000
},
"search": [
"icon"
]
},
{
"uid": "05dd5a74c484decee45995f6ee723ea2",
"css": "rewardsCircle",
@@ -1145,6 +1131,76 @@
"search": [
"icon"
]
},
{
"uid": "623cc2ff909ec2281a19d64b238c18a1",
"css": "screenTime",
"code": 59473,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M696.6 468.8C799.4 468.8 882.8 552.1 882.8 654.9 882.8 757.8 799.4 841.1 696.6 841.1 593.8 841.1 510.4 757.8 510.4 654.9 510.4 552.1 593.8 468.8 696.6 468.8ZM569.7 130.2C611.7 130.2 645.8 164.3 645.8 206.4L645.8 440.8C548.8 463.7 476.6 550.9 476.6 654.9 476.6 660.6 476.8 666.3 477.2 671.9L400.4 671.9C386.4 671.9 375 683.2 375 697.3 375 710.1 384.6 720.7 396.9 722.4L400.4 722.7H485L487.1 722.5C497.5 754.7 515 783.5 537.9 807.3L315.8 807.3C273.7 807.3 239.6 773.2 239.6 731.1V206.4C239.6 164.3 273.7 130.2 315.8 130.2H569.7ZM662.8 536.5C653.4 536.5 645.8 544 645.8 553.4V688.8C645.8 698.1 653.4 705.7 662.8 705.7H764.4C773.7 705.7 781.3 698.1 781.3 688.8 781.3 679.5 773.7 671.9 764.4 671.9H679.7V553.4C679.7 544 672.1 536.5 662.8 536.5Z",
"width": 1000
},
"search": [
"icon"
]
},
{
"uid": "f91b4ca494bb312e01f6e0981e7a05dc",
"css": "friendsCircle",
"code": 59474,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M632.1 435C674.4 435.3 709.6 400.5 709.6 358.1 709.6 316 675.1 281.2 633 280.9 590.7 280.6 555.8 315 555.5 357.1 555.2 399.8 589.7 434.6 632.1 435ZM292.4 542.7C294.3 527.9 286.5 513.1 272.7 510.2 260.2 507.6 246.7 508.5 233.9 507.6 233.9 528.3 233.9 547.3 233.9 567.3 244.4 567.3 254.6 567.7 264.5 567.3 278.3 567 290.4 556.2 292.4 542.7ZM386 435C428.1 435.3 463.2 400.5 463.5 358.4 463.9 315.7 429.4 280.9 387 280.9 344.6 280.9 309.5 315.4 309.5 357.8 309.1 400.1 343.6 434.6 386 435ZM534.5 470.8C531.9 470.8 530.6 470.4 528.9 470.4 475.4 470.4 422.1 470.4 368.6 470.4 359.7 470.4 350.9 471.4 342.3 473.1 329.2 475.7 317 480.6 305.5 488.2 325.9 507.9 333.4 531.5 324.2 557.8 312.7 591.3 286.8 604.1 252.3 602.8 252.3 641.9 252.3 680 252.3 718.8 265.8 718.8 278.6 718.8 292 718.8 292 715.8 292 713.9 292 711.6 292 689.9 292 667.9 292 646.2 292 643.9 292 641.6 292.4 639.3 294 630.1 302.2 623.9 310.8 624.5 320 625.2 327.2 632.4 327.2 641.9 327.5 665.2 327.2 688.6 327.2 712.2 327.2 714.5 327.2 716.8 327.2 719.1 379.1 719.1 430 719.1 481.3 719.1 481.3 716.5 481.3 714.2 481.3 711.9 481.3 669.8 480.9 627.8 481.3 585.7 481.6 542 498 505.3 529.6 475 531.9 473.7 532.8 472.4 534.5 470.8ZM500 0C223.7 0 0 224 0 500 0 776.3 224 1000 500 1000 776.3 1000 1000 776 1000 500 1000 223.7 776.3 0 500 0ZM801.6 589.7C798 597.6 792 602.8 782.5 603.2 782.5 605.8 782.5 608.1 782.5 610.1 782.5 651.1 782.5 692.2 782.5 733.2 782.5 747.7 775.6 754.6 761.2 754.6 586.7 754.6 412.3 754.6 237.8 754.6 223.4 754.6 216.5 747.7 216.5 733.2 216.5 692.2 216.5 651.1 216.5 610.1 216.5 607.8 216.5 605.5 216.5 602.8 206.6 602.8 201.4 597.2 197.4 589.7 197.4 555.2 197.4 520.4 197.4 485.9 201.7 475.7 209.6 472.1 220.4 472.7 234.6 473.4 248.7 473.1 262.8 472.7 264.5 472.7 266.8 472.7 267.7 471.7 281.2 460.2 296.3 451.1 313.1 444.5 256.2 394.9 266.8 317.7 304.9 279.2 345.3 238.8 408 233.9 453.7 268.4 475.7 285.2 489.8 307.5 495.4 334.8 503 372.2 493.1 405.1 467.8 434.3 495.4 434.3 521.7 434.3 549.3 434.3 527.3 409.3 517.1 381.1 519.7 348.9 522.3 316.4 536.8 289.4 562.4 269.4 607.1 234.2 670.2 237.8 710.2 277.6 730.9 298 742.4 322.9 743.8 352.2 745.4 392.6 729 424.8 698.1 448.8 708.9 456.3 719.1 463.9 729.6 471.1 731.3 472.1 733.6 472.7 735.5 472.7 749.7 472.7 763.8 473.4 777.9 472.7 788.8 472.4 796.6 476 800.9 485.9 801.6 520.7 801.6 555.2 801.6 589.7ZM678.1 565C664.9 536.5 671.8 510.5 694.2 488.2 670.2 473.4 644.9 467.5 617.6 471.4 557.5 480.3 517.7 527.6 517.7 588 517.7 629.4 517.7 670.8 517.7 712.2 517.7 714.2 517.7 716.5 517.7 718.5 569.3 718.5 620.6 718.5 671.8 718.5 671.8 715.8 671.8 713.9 671.8 711.6 671.8 688.2 671.8 664.9 671.8 641.6 671.8 632.1 679 624.8 688.6 624.2 697.4 623.5 705.3 630.1 707 639.3 707.3 641.6 707.3 643.9 707.3 646.2 707.3 668.2 707.3 690.2 707.3 712.2 707.3 714.2 707.6 716.5 707.6 718.8 721.1 718.8 733.9 718.8 747 718.8 747 679.7 747 641.3 747 602.8 715.8 604.5 691.2 594 678.1 565ZM707.3 537.1C707 552.6 718.5 566.4 733.6 567.3 744.4 568 754.9 567.3 766.1 567.3 766.1 547.3 766.1 527.9 766.1 508.5 755.3 508.5 745.1 508.2 734.6 508.5 719.4 508.9 707.6 521.7 707.3 537.1Z",
"width": 1000
},
"search": [
"icon"
]
},
{
"uid": "d9ab0ada4a6bda3f4f974dd8d154b5bf",
"css": "healthCircle",
"code": 59527,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M672.8 298.3C624.2 285.8 582.8 302.2 550.3 339.4 532.9 359.4 517.4 381.4 500 404.1 479.6 378.4 462.6 353.5 442.2 331.8 398.2 285.1 325.6 281.9 279.9 322.3 231.3 365.6 226.3 433.3 269.7 484.6 334.8 562.1 400.1 639 465.5 716.2 475.7 728.3 486.2 740.5 497 753.6 577.9 660.3 657 569.6 735.2 478.3 757.2 452.4 764.1 420.2 756.9 386.7 747 340.7 718.5 310.1 672.8 298.3ZM500 0C224 0 0 223.7 0 500 0 776.3 224 1000 500 1000 776.3 1000 1000 776 1000 500 1000.3 223.7 776.3 0 500 0ZM776.6 522C693.8 618.6 610.1 714.2 526.6 810.1 503.6 836.4 489.8 836.1 467.8 810.1 385.7 713.2 303.5 616 221.4 518.7 176.4 465.5 169.5 388.6 203 326.2 235.2 265.8 302.6 230.3 371.2 236.5 423.8 241.5 465.5 265.4 500.7 306.5 535.1 265.8 576.5 241.8 628.5 236.9 698.8 230.3 765.8 265.4 798 326.5 831.5 391.3 824.2 466.5 776.6 522Z",
"width": 1000
},
"search": [
"icon"
]
},
{
"uid": "505c0f357adb29dfe5230da603bd2b07",
"css": "temperature",
"code": 59475,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M621 665.3C621 691.6 613.2 717.4 598.5 739.2 583.9 761.1 563.1 778.2 538.8 788.3 514.5 798.3 487.8 801 461.9 795.8 436.1 790.7 412.4 778 393.8 759.4 375.2 740.8 362.5 717.1 357.4 691.3 352.3 665.5 354.9 638.7 365 614.4 375 590.1 392.1 569.3 414 554.7 435.9 540.1 461.6 532.3 487.9 532.3 523.2 532.3 557 546.3 582 571.2 606.9 596.2 621 630 621 665.3ZM798.4 665.3C798.4 706.2 790.3 746.6 774.7 784.3 759 822 736.1 856.3 707.2 885.1 678.3 914 644 936.8 606.2 952.4 568.5 967.9 528 975.9 487.2 975.8 474.9 975.8 462.7 975.1 450.5 973.6 383.8 965.1 321.6 935.3 273.1 888.7 224.7 842.1 192.5 781.1 181.3 714.8 171.9 657.1 179.1 597.9 202 544.1 224.8 490.3 262.5 444.1 310.5 410.8V177.4C310.5 130.4 329.2 85.2 362.4 52 395.7 18.7 440.8 0 487.9 0 535 0 580.1 18.7 613.4 52 646.6 85.2 665.3 130.4 665.3 177.4V410.8C706.3 439.4 739.8 477.5 762.9 521.8 786.1 566.1 798.3 615.3 798.4 665.3ZM709.7 665.3C709.6 626.4 699.3 588.3 679.8 554.6 660.4 521 632.4 493 598.8 473.5 592.1 469.6 586.5 464 582.6 457.3 578.7 450.5 576.6 442.9 576.6 435.1V177.4C576.6 153.9 567.3 131.3 550.6 114.7 534 98.1 511.4 88.7 487.9 88.7 464.4 88.7 441.8 98.1 425.2 114.7 408.5 131.3 399.2 153.9 399.2 177.4V435.1C399.2 442.9 397.1 450.5 393.2 457.3 389.3 464 383.8 469.6 377 473.5 343.3 493 315.3 521 295.8 554.7 276.4 588.4 266.1 626.7 266.1 665.6 266.1 704.5 276.4 742.8 295.9 776.5 315.4 810.2 343.4 838.2 377.1 857.7 410.8 877.1 449.1 887.3 488 887.3 527 887.3 565.2 877 598.9 857.5 632.6 838 660.6 810 680.1 776.3 699.5 742.5 709.7 704.3 709.7 665.3ZM221.8 88.7H44.4C32.6 88.7 21.3 93.4 13 101.7 4.7 110 0 121.3 0 133.1 0 144.8 4.7 156.1 13 164.4 21.3 172.7 32.6 177.4 44.4 177.4H221.8C233.5 177.4 244.8 172.7 253.1 164.4 261.5 156.1 266.1 144.8 266.1 133.1 266.1 121.3 261.5 110 253.1 101.7 244.8 93.4 233.5 88.7 221.8 88.7ZM266.1 310.5C266.1 298.7 261.5 287.4 253.1 279.1 244.8 270.8 233.5 266.1 221.8 266.1H133.1C121.3 266.1 110 270.8 101.7 279.1 93.4 287.4 88.7 298.7 88.7 310.5 88.7 322.2 93.4 333.5 101.7 341.8 110 350.2 121.3 354.8 133.1 354.8H221.8C233.5 354.8 244.8 350.2 253.1 341.8 261.5 333.5 266.1 322.2 266.1 310.5Z",
"width": 806
},
"search": [
"icon"
]
},
{
"uid": "415b9dee17fa463032aa6f9d83a6df07",
"css": "locationOutlined",
"code": 59478,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M191.8 423.4C191.8 296.4 300.4 193.5 434.4 193.5 568.4 193.5 677 296.4 677 423.4 677 550.3 568.4 653.2 434.4 653.2 300.4 653.2 191.8 550.3 191.8 423.4ZM434.4 266.1C342.8 266.1 268.4 336.5 268.4 423.4 268.4 510.2 342.8 580.6 434.4 580.6 526.1 580.6 600.4 510.2 600.4 423.4 600.4 336.5 526.1 266.1 434.4 266.1ZM1.5 368.1C19.6 160.1 203.1 0 423.4 0H445.5C665.8 0 849.2 160.1 867.3 368.1 877 479.8 840.6 590.7 765.7 677.5L520.9 961.2C476.2 1012.9 392.7 1012.9 348 961.2L103.2 677.5C28.3 590.7-8.2 479.8 1.5 368.1ZM423.4 72.6C243 72.6 92.7 203.7 77.9 374 69.8 467 100.1 559.4 162.5 631.6L407.3 915.2C421.3 931.5 447.6 931.5 461.6 915.2L706.4 631.6C768.7 559.4 799.1 467 791 374 776.1 203.7 625.9 72.6 445.5 72.6H423.4Z",
"width": 893
},
"search": [
"icon"
]
}
]
}

View File

@@ -87,6 +87,10 @@ class SFIcons {
static const IconData watch = IconData(0xe843, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData handshake = IconData(0xe844, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData listen = IconData(0xe850, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData screenTime = IconData(0xe851, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData friendsCircle = IconData(0xe852, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData temperature = IconData(0xe853, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData locationOutlined = IconData(0xe856, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData share = IconData(0xe858, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData favoriteOutlined = IconData(0xe859, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData renovationSelected = IconData(0xe862, fontFamily: _kFontFam, fontPackage: _kFontPkg);
@@ -102,7 +106,7 @@ class SFIcons {
static const IconData videoCallCircle = IconData(0xe884, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData fallCircle = IconData(0xe885, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData medicationCircle = IconData(0xe886, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData activityCircle = IconData(0xe887, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData healthCircle = IconData(0xe887, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData rewardsCircle = IconData(0xe888, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData locateSfCircle = IconData(0xe889, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData chat = IconData(0xe88a, fontFamily: _kFontFam, fontPackage: _kFontPkg);

View File

@@ -24,4 +24,5 @@ class AppRoutes {
static const contacts = '$dashboardFunctions/contacts';
static const remoteConnection = '$dashboardFunctions/remote_connection';
static const locateDevice = '$dashboardFunctions/locateDevice';
}