This commit is contained in:
J. A. Messias 2024-12-03 17:47:03 -03:00
parent a4ee7331ab
commit cf8ce52fd7
27 changed files with 174 additions and 102 deletions

View File

@ -33,7 +33,10 @@ class _HomePageWidgetState extends State<HomePageWidget> {
create: (context) => LocalProfileBloc()..add(LocalProfileEvent()),
),
],
child: Scaffold(
child: Builder(
builder: (context) {
context.read<LocalProfileBloc>().updateProfile(context);
return Scaffold(
key: scaffoldKey,
backgroundColor: FlutterFlowTheme.of(context).primaryBackground,
drawerEnableOpenDragGesture: true,
@ -41,6 +44,8 @@ class _HomePageWidgetState extends State<HomePageWidget> {
drawer: CustomDrawer(),
appBar: buildAppBar(context),
body: buildPage(context),
);
},
),
);
}

View File

@ -78,7 +78,7 @@ class _AboutPropertyPageState extends State<AboutPropertyPage> with SingleTicker
child: Container(
color: FlutterFlowTheme.of(context).primaryBackground,
child: Menufactory(
entry: MenuEntry.getEntriesByType(MenuEntryType.Drawer),
entry: MenuEntry.getEntriesByType(MenuEntryType.Property),
item: EnumMenuItem.button,
view: MenuView.list_grid,
),

View File

@ -16,9 +16,11 @@ import 'package:hub/shared/helpers/storage/storage_helper.dart';
import 'package:hub/shared/services/deeplink/deep_link_service.dart';
import 'package:responsive_framework/responsive_framework.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:hub/shared/extensions/string_extensions.dart';
import 'backend/notifications/firebase_messaging_service.dart';
import 'initialization.dart';
import 'shared/components/molecules/modules/index.dart';
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

View File

@ -34,7 +34,7 @@ class _ResidentsOnThePropertyState extends State<ResidentsOnTheProperty> with Ti
void initState() {
super.initState();
model = createModel(context, () => ResidentsOnThePropertyModel(onRefresh: () => safeSetState(() {})));
_future = _fetchVisits();
_future = _fetch();
_scrollController = ScrollController()
..addListener(() {
@ -160,7 +160,7 @@ class _ResidentsOnThePropertyState extends State<ResidentsOnTheProperty> with Ti
);
}
Future<ApiCallResponse?> _fetchVisits() async {
Future<ApiCallResponse?> _fetch() async {
try {
setState(() => _loading = true);
@ -202,7 +202,7 @@ class _ResidentsOnThePropertyState extends State<ResidentsOnTheProperty> with Ti
if (_hasData == true) {
_pageNumber++;
_future = _fetchVisits();
_future = _fetch();
}
}

View File

@ -190,7 +190,7 @@ class CustomDrawer extends StatelessWidget {
Widget _buildDrawerBody(BuildContext context) {
return Menufactory(
entry: MenuEntry.getEntriesByType(MenuEntryType.Property),
entry: MenuEntry.getEntriesByType(MenuEntryType.Drawer),
item: EnumMenuItem.tile,
view: MenuView.list,
);

View File

@ -162,12 +162,12 @@ class LocalsRemoteDataSourceImpl implements LocalsRemoteDataSource {
if (isError == true) {
final GetLocalsCall callback = PhpGroup.getLocalsCall;
response = await callback.call();
final String errorMsg = response.jsonBody['error_msg'] ?? 'Unknown error';
final String errorMsg = response.jsonBody['error_msg'] ?? 'Local indisponível';
await DialogUtil.error(context, errorMsg).whenComplete(() => selectLocal(context, response));
return false;
} else {
final bool isNewVersion = await LocalUtil.updateStorageUtil(response.jsonBody);
return await LicenseRepositoryImpl().updateLicense(isNewVersion);
return await LicenseRepositoryImpl().updateLicense();
}
} catch (e, s) {
log('() => error processData: $e', stackTrace: s);

View File

@ -1,11 +1,14 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter/material.dart';
import 'package:hub/flutter_flow/flutter_flow_model.dart';
import 'package:hub/flutter_flow/nav/nav.dart';
import 'package:hub/shared/components/molecules/locals/index.dart';
import 'package:hub/shared/helpers/storage/base_storage.dart';
import 'package:hub/shared/helpers/storage/storage_helper.dart';
class LocalProfileEvent {}
class LocalProfileEvent {
}
class LocalProfileState {
final String cliName;
@ -14,6 +17,7 @@ class LocalProfileState {
LocalProfileState({this.cliName = '', this.cliUUID = ''});
LocalProfileState copyWith({String? cliName, String? cliUUID}) {
return LocalProfileState(
cliName: cliName ?? this.cliName,
cliUUID: cliUUID ?? this.cliUUID,
@ -23,11 +27,18 @@ class LocalProfileState {
class LocalProfileBloc extends Bloc<LocalProfileEvent, LocalProfileState> {
LocalProfileBloc() : super(LocalProfileState()) {
on<LocalProfileEvent>((event, emit) async {
on<LocalProfileEvent>(_onLocalProfileEvent);
}
Future<void> _onLocalProfileEvent(LocalProfileEvent event, Emitter<LocalProfileState> emit) async {
final cliName = (await StorageHelper().get(KeychainStorageKey.clientName.value)) ?? '';
final cliUUID = (await StorageHelper().get(KeychainStorageKey.clientUUID.value)) ?? '';
emit(state.copyWith(cliName: cliName, cliUUID: cliUUID));
});
}
void updateProfile(BuildContext context) {
add(LocalProfileEvent());
LocalsRepositoryImpl().update(context);
}
}

View File

@ -9,10 +9,12 @@ import 'package:hub/shared/extensions/dialog_extensions.dart';
import 'package:hub/shared/services/authentication/authentication_service.dart';
import 'package:hub/shared/utils/path_util.dart';
import '../../../modules/domain/entities/index.dart';
abstract class MenuLocalDataSource {
Future<MenuItem?> addMenuEntry(EnumMenuItem item, List<MenuItem?> entries, IconData icon, String text, Function() action);
Future<bool> processDisplayDefault(EnumMenuItem item, MenuEntry opt, List<MenuItem?> entries);
Future<void> processDisplay(EnumMenuItem item, String display, MenuEntry opt, List<MenuItem?> entries);
Future<void> processDisplay(EnumMenuItem item, EnumDisplay display, MenuEntry opt, List<MenuItem?> entries);
Future<bool> processStartDate(String startDate, MenuEntry opt);
Future<bool> processExpirationDate(String expirationDate, MenuEntry opt);
}
@ -48,9 +50,9 @@ class MenuLocalDataSourceImpl implements MenuLocalDataSource {
}
@override
Future<void> processDisplay(EnumMenuItem item, String display, MenuEntry opt, List<MenuItem?> entries) async {
Future<void> processDisplay(EnumMenuItem item, EnumDisplay display, MenuEntry opt, List<MenuItem?> entries) async {
try {
switch (display) {
switch (display.value) {
case 'VISIVEL':
await addMenuEntry(item, entries, opt.icon, opt.name, () async {
await PathUtil.nav(opt.route);

View File

@ -23,7 +23,7 @@ class MenuRepositoryImpl implements MenuRepository {
final licenseValue = await LicenseRepositoryImpl().getLicense(opt.value);
if (licenseValue != null) {
final licenseMap = await stringToMap(licenseValue);
final display = licenseMap['display'] ?? 'INVISIVEL';
final display = EnumDisplay.fromString(licenseMap['display']);
final startDate = licenseMap['startDate'] ?? '';
final expirationDate = licenseMap['expirationDate'] ?? '';
final isStarted = await menuDataSource.processStartDate(startDate, opt);

View File

@ -1 +1,3 @@
export 'menu_bloc.dart';
export 'menu_item_bloc.dart';
export 'menu_view_bloc.dart';

View File

@ -1,9 +1,55 @@
import 'dart:async';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:hub/shared/components/molecules/menu/data/repositories/menu_repository_impl.dart';
import 'package:hub/shared/components/molecules/menu/index.dart';
import 'package:hub/shared/components/molecules/modules/index.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class MenuEvent {}
class MenuState {}
class MenuState {
final List<MenuItem?> menuEntries;
final bool isGrid;
MenuState({this.menuEntries = const [], this.isGrid = false});
MenuState copyWith({List<MenuItem?>? menuEntries, bool? isGrid}) {
return MenuState(
menuEntries: menuEntries ?? this.menuEntries,
isGrid: isGrid ?? this.isGrid,
);
}
}
class MenuBloc extends Bloc<MenuEvent, MenuState> {
MenuBloc() : super(MenuState());
final MenuView style;
final EnumMenuItem item;
final List<MenuEntry> menuOptions;
late StreamSubscription<void> _completer;
MenuBloc({required this.style, required this.item, required this.menuOptions}) : super(MenuState()) {
on<MenuEvent>((event, emit) async {
await LicenseRemoteDataSourceImpl().waitForSaveCompletion();
final entries = await MenuRepositoryImpl().generateMenuEntries(menuOptions, item);
emit(state.copyWith(menuEntries: entries));
});
_completer = LicenseRemoteDataSourceImpl().streamCompleterController.listen((_) {
add(MenuEvent());
});
}
@override
Future<void> close() {
_completer.cancel();
return super.close();
}
}

View File

@ -1,52 +1,11 @@
import 'dart:async';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:hub/shared/components/molecules/menu/data/repositories/menu_repository_impl.dart';
import 'package:hub/shared/components/molecules/menu/index.dart';
import 'package:hub/shared/components/molecules/modules/index.dart';
class MenuViewEvent {}
class MenuViewState {
final List<MenuItem?> menuEntries;
final bool isGrid;
MenuViewState({this.menuEntries = const [], this.isGrid = false});
MenuViewState copyWith({List<MenuItem?>? menuEntries, bool? isGrid}) {
return MenuViewState(
menuEntries: menuEntries ?? this.menuEntries,
isGrid: isGrid ?? this.isGrid,
);
}
}
class MenuViewState {}
class MenuViewBloc extends Bloc<MenuViewEvent, MenuViewState> {
final MenuView style;
final EnumMenuItem item;
final List<MenuEntry> menuOptions;
late StreamSubscription<void> _completer;
MenuViewBloc({required this.style, required this.item, required this.menuOptions}) : super(MenuViewState()) {
on<MenuViewEvent>((event, emit) async {
await LicenseRemoteDataSourceImpl().waitForSaveCompletion();
final entries = await MenuRepositoryImpl().generateMenuEntries(menuOptions, item);
emit(state.copyWith(menuEntries: entries));
});
_completer = LicenseRemoteDataSourceImpl().streamCompleterController.listen((_) {
add(MenuViewEvent());
});
}
@override
Future<void> close() {
_completer.cancel();
return super.close();
}
MenuViewBloc() : super(MenuViewState());
}

View File

@ -214,6 +214,7 @@ class MenuEntry implements BaseModule {
static List<MenuEntry> getEntriesByType(MenuEntryType type) {
return entries.where((entry) => entry.types.contains(type)).toList();
}
}

View File

@ -44,12 +44,12 @@ class Menufactory extends StatelessWidget {
Widget _buildMenuBloc(BuildContext context) {
return BlocProvider(
create: (context) => MenuViewBloc(
create: (context) => MenuBloc(
style: view,
item: item,
menuOptions: entry,
)..add(MenuViewEvent()),
child: BlocBuilder<MenuViewBloc, MenuViewState>(
)..add(MenuEvent()),
child: BlocBuilder<MenuBloc, MenuState>(
builder: (context, state) {
if (view == MenuView.list_grid) {
return MenuStaggeredView(

View File

@ -44,7 +44,7 @@ class _MenuButtonWidgetState extends State<ButtonMenuItem> {
setState(() {
_isProcessing = true;
});
widget.action.call();
await widget.action.call();
setState(() {
_isProcessing = false;
});

View File

@ -39,7 +39,7 @@ class _MenuCardItemState extends State<CardMenuItem> {
setState(() {
_isProcessing = true;
});
widget.action.call();
await widget.action.call();
setState(() {
_isProcessing = false;
});

View File

@ -1,18 +1,19 @@
import 'dart:developer';
import 'package:hub/shared/components/molecules/modules/index.dart';
import 'package:hub/shared/helpers/database/database_helper.dart';
import 'package:hub/shared/helpers/storage/base_storage.dart';
import 'package:hub/shared/helpers/storage/storage_helper.dart';
import 'package:hub/shared/extensions/string_extensions.dart';
import 'package:sqflite/sqflite.dart';
abstract class LicenseLocalDataSource {
Future<void> init();
Future<void> setDisplayByKey(final List<String> key, final String display);
Future<bool> isNewVersion();
Future<String?> g(String key);
Future<void> s<T>(String key, T value);
Future<void> d(String key);
Future<void> c();
Future<String?> get(String key);
Future<void> set<T>(String key, T value);
Future<void> del(String key);
Future<void> clear();
}
class LicenseLocalDataSourceImpl implements LicenseLocalDataSource {
@ -21,15 +22,17 @@ class LicenseLocalDataSourceImpl implements LicenseLocalDataSource {
LicenseLocalDataSourceImpl._internal();
@override
Future<void> init() async {
await DatabaseStorage.instance.init();
}
@override
Future<void> setDisplayByKey(final List<String?> key, final String display) async {
if (key.isEmpty) return;
for (var element in key) {
if (element != null) {
await s(element, {
await set(element, {
'display': display,
'expirationDate': '',
'startDate': '',
@ -39,15 +42,15 @@ class LicenseLocalDataSourceImpl implements LicenseLocalDataSource {
}
}
@override
Future<bool> isNewVersion() async {
var response = await DatabaseStorage.database.query(tableLicense, where: 'key = ?', whereArgs: [KeychainStorageKey.isNewVersion.value], columns: ['display']);
if (response.isEmpty) {
return false;
}
return response.first['display'] == 'true';
final String? reponse = await StorageHelper().get(KeychainStorageKey.isNewVersion.value);
final bool isNewVersion = reponse.toBoolean();
return isNewVersion;
}
Future<String?> g(String key) async {
@override
Future<String?> get(String key) async {
var response = await DatabaseStorage.database.query(tableLicense, where: 'key = ?', whereArgs: [key]);
if (response.isEmpty) {
return null;
@ -55,7 +58,8 @@ class LicenseLocalDataSourceImpl implements LicenseLocalDataSource {
return response.first.toString();
}
Future<void> s<T>(String key, T value) async {
@override
Future<void> set<T>(String key, T value) async {
value as Map<String, dynamic>;
await DatabaseStorage.database.insert(
@ -71,11 +75,13 @@ class LicenseLocalDataSourceImpl implements LicenseLocalDataSource {
return;
}
Future<void> d(String key) async {
@override
Future<void> del(String key) async {
await DatabaseStorage.database.delete(tableLicense, where: 'key = ?', whereArgs: [key]);
}
Future<void> c() async {
@override
Future<void> clear() async {
await DatabaseStorage.database.delete(tableLicense);
}
}

View File

@ -7,7 +7,6 @@ import 'package:hub/backend/api_requests/api_calls.dart';
import 'package:hub/shared/components/molecules/modules/index.dart';
import 'package:hub/shared/helpers/database/database_helper.dart';
import 'package:rxdart/rxdart.dart';
import 'package:sqflite/sqflite.dart';
abstract class LicenseRemoteDataSource {
@ -118,6 +117,6 @@ class LicenseRemoteDataSourceImpl implements LicenseRemoteDataSource {
static Future<void> _saveModule(final dynamic body) async {
if (body is! Map<String, dynamic>) return;
await LicenseLocalDataSourceImpl().s(body['key'], body);
await LicenseLocalDataSourceImpl().set(body['key'], body);
}
}

View File

@ -17,7 +17,8 @@ class LicenseRepositoryImpl implements LicenseRepository {
static final license = BehaviorSubject<LicenseStatus>();
static get stream => license.stream;
Future<bool> updateLicense(bool isNewVersion) async {
Future<bool> updateLicense() async {
final bool isNewVersion = await localDataSource.isNewVersion();
await remoteDataSource.setupLicense(database, isNewVersion);
if (isNewVersion) {
return await remoteDataSource.fetchLicenses(isNewVersion);
@ -31,10 +32,10 @@ class LicenseRepositoryImpl implements LicenseRepository {
}
Future<String?> getLicense(String key) async {
return await localDataSource.g(key);
return await localDataSource.get(key);
}
Future<void> setLicense<T>(String key, T value) async {
return await localDataSource.s(key, value);
return await localDataSource.set(key, value);
}
}

View File

@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
import 'package:hub/flutter_flow/internationalization.dart';
import 'package:hub/flutter_flow/nav/nav.dart';
abstract class BaseModule {
String get value;
String get name;

View File

@ -6,8 +6,8 @@ import 'package:hub/shared/helpers/storage/storage_helper.dart';
import 'module.dart';
enum LicenseKeys {
enum LicenseKeys {
messages('FRE-HUB-MESSAGES'),
liberations('FRE-HUB-LIBERATIONS'),
reservations('FRE-HUB-RESERVATIONS'),

View File

@ -3,6 +3,30 @@ import 'package:hub/shared/components/molecules/modules/data/models/module_model
enum ModuleStatus { active, inactive, disabled }
enum EnumDisplay {
active('VISIVEL'),
inactive('INVISIVEL'),
expired('DESABILITADO');
final String value;
const EnumDisplay(this.value);
static EnumDisplay fromString(String? value) {
if (value == null) return EnumDisplay.inactive;
switch (value) {
case 'VISIVEL':
return EnumDisplay.active;
case 'INVISIVEL':
return EnumDisplay.inactive;
case 'DESABILITADO':
return EnumDisplay.expired;
default:
return EnumDisplay.inactive;
}
}
}
extension ModuleStatusExtension on ModuleStatus {
String get key {
switch (this) {

View File

@ -1,5 +1,5 @@
abstract class LicenseRepository {
Future<bool> updateLicense(bool isNewVersion);
Future<bool> updateLicense();
Future<void> cleanLicense();
Future<String?> getLicense(String key);

View File

@ -32,7 +32,7 @@ class DatabaseStorage {
onUpgrade: _onUpgrade,
onDowngrade: _onDowngrade,
);
await LicenseRepositoryImpl().updateLicense(false);
await LicenseRepositoryImpl().updateLicense();
isInitialized = true;
}

View File

@ -23,15 +23,18 @@ class KeychainHelper implements BaseStorage {
@override
Future<String?> get(String key) async {
var response = await DatabaseStorage.database.query(tableKeychain, where: 'key = ?', whereArgs: [key]);
if (response.isEmpty) {
return null;
}
log('() => get keychain: $key : ${response.first['value']}');
return response.first['value'].toString();
}
@override
Future<void> set<T>(String key, T value) async {
var date = DateTime.now().toIso8601String();
await DatabaseStorage.database.insert(
tableKeychain,
@ -44,6 +47,7 @@ class KeychainHelper implements BaseStorage {
'createdAt': date,
},
conflictAlgorithm: ConflictAlgorithm.replace);
log('() => set keychain: $key : $value');
}
@override
@ -53,7 +57,11 @@ class KeychainHelper implements BaseStorage {
@override
Future<void> clearAll() async {
try {
await DatabaseStorage.database.delete(tableKeychain);
} catch (e, s) {
log('() => clearAll keychain: $e', stackTrace: s);
}
}

View File

@ -1,3 +1,5 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:hub/flutter_flow/nav/nav.dart';
import 'package:hub/shared/helpers/storage/base_storage.dart';
@ -138,6 +140,8 @@ class AuthenticationService {
alignment: Alignment.bottomCenter,
),
};
await StorageHelper().clean(Storage.databaseStorage);
await StorageHelper().clean(Storage.secureStorage);
await StorageHelper().clean(Storage.databaseStorage);
context.go('/welcomePage', extra: extra);