Merge pull request #84 from FRE-Informatica/debit/fd-1038

DEBIT/FD-1038 - Escritas de Testes para o App
This commit is contained in:
Ivan Antunes 2025-01-17 14:12:44 -03:00 committed by GitHub
commit 069b46e927
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
77 changed files with 17417 additions and 272 deletions

View File

@ -1,2 +1,2 @@
gradle 8.10.2 gradle 8.10.2
kotlin 2.0.20 kotlin 1.8.22

View File

@ -34,7 +34,7 @@ if (keystorePropertiesFile.exists()) {
android { android {
namespace 'com.freaccess.hub' namespace 'com.freaccess.hub'
compileSdkVersion 34 compileSdkVersion 34
compileSdk 34 compileSdk 35
sourceSets { sourceSets {
main.java.srcDirs += 'src/main/kotlin' main.java.srcDirs += 'src/main/kotlin'
@ -53,8 +53,16 @@ android {
versionName flutterVersionName versionName flutterVersionName
multiDexEnabled true multiDexEnabled true
consumerProguardFiles 'proguard-rules.pro' consumerProguardFiles 'proguard-rules.pro'
testInstrumentationRunner "pl.leancode.patrol.PatrolJUnitRunner"
testInstrumentationRunnerArguments clearPackageData: "true"
} }
testOptions {
execution "ANDROIDX_TEST_ORCHESTRATOR"
}
compileOptions { compileOptions {
coreLibraryDesugaringEnabled true coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_11 sourceCompatibility JavaVersion.VERSION_11
@ -92,6 +100,8 @@ android {
debug { debug {
signingConfig signingConfigs.debug signingConfig signingConfigs.debug
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
minifyEnabled false
shrinkResources false
} }
} }
} }
@ -106,11 +116,16 @@ dependencies {
implementation 'androidx.window:window:1.0.0' implementation 'androidx.window:window:1.0.0'
implementation 'androidx.window:window-java:1.0.0' implementation 'androidx.window:window-java:1.0.0'
implementation 'com.google.mlkit:face-detection:16.1.7' implementation 'com.google.mlkit:face-detection:16.1.7'
implementation ('com.google.firebase:firebase-messaging:24.0.0') { implementation('com.google.firebase:firebase-messaging:24.0.0') {
exclude group: 'com.google.firebase', module: 'firebase-iid' exclude group: 'com.google.firebase', module: 'firebase-iid'
} }
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3' coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3'
androidTestUtil "androidx.test:orchestrator:1.5.1"
// androidTestImplementation 'androidx.test:runner:1.4.0'
// androidTestImplementation 'androidx.test:rules:1.4.0'
} }
apply plugin: 'com.google.gms.google-services' apply plugin: 'com.google.gms.google-services'

View File

@ -0,0 +1,36 @@
package com.freaccess.hub;
import androidx.test.platform.app.InstrumentationRegistry;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import pl.leancode.patrol.PatrolJUnitRunner;
@RunWith(Parameterized.class)
public class MainActivityTest {
private final String dartTestName;
public MainActivityTest(String dartTestName) {
this.dartTestName = dartTestName;
}
@Parameters(name = "{0}")
public static Object[] testCases() {
PatrolJUnitRunner instrumentation = (PatrolJUnitRunner) InstrumentationRegistry.getInstrumentation();
// replace "MainActivity.class" with "io.flutter.embedding.android.FlutterActivity.class"
// if in AndroidManifest.xml in manifest/application/activity you have
// android:name="io.flutter.embedding.android.FlutterActivity"
instrumentation.setUp(MainActivity.class);
instrumentation.waitForPatrolAppService();
return instrumentation.listDartTests();
}
@Test
public void runDartTest() {
PatrolJUnitRunner instrumentation = (PatrolJUnitRunner) InstrumentationRegistry.getInstrumentation();
instrumentation.runDartTest(dartTestName);
}
}

View File

@ -1,6 +1,6 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript { buildscript {
ext.kotlin_version = '2.0.20' // Replace with the latest version ext.kotlin_version = '1.8.22'
ext.gradle_version = '8.6.0' // Replace with the latest version ext.gradle_version = '8.6.0' // Replace with the latest version
ext.google_services_version = '4.4.2' // Replace with the latest version ext.google_services_version = '4.4.2' // Replace with the latest version
repositories { repositories {
@ -8,10 +8,12 @@ buildscript {
mavenCentral() mavenCentral()
} }
dependencies { dependencies {
classpath "com.android.tools.build:gradle:$gradle_version" // Use a versão do Gradle que corresponde à sua configuração classpath "com.android.tools.build:gradle:$gradle_version"
// Use a versão do Gradle que corresponde à sua configuração
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "com.google.gms:google-services:$google_services_version" // Google Services plugin classpath "com.google.gms:google-services:$google_services_version"
} // Google Services plugin
}
} }
allprojects { allprojects {

View File

@ -20,7 +20,7 @@ plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0" id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id 'com.android.application' version '8.6.0' apply false id 'com.android.application' version '8.6.0' apply false
id 'com.android.library' version '8.6.0' apply false id 'com.android.library' version '8.6.0' apply false
id 'org.jetbrains.kotlin.android' version '2.0.20' apply false id 'org.jetbrains.kotlin.android' version '1.8.22' apply false
// START: FlutterFire Configuration // START: FlutterFire Configuration
@ -30,7 +30,6 @@ plugins {
// id "org.jetbrains.kotlin.android" version "1.8.10" apply false // id "org.jetbrains.kotlin.android" version "1.8.10" apply false
} }
include ":app" include ":app"

15496
coverage/lcov.info Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,64 @@
import 'dart:collection';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:go_router/go_router.dart';
import 'package:hub/components/molecular_components/throw_exception/throw_exception_widget.dart';
import 'package:hub/components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_widget.dart';
import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart';
import 'package:hub/features/backend/api_requests/index.dart';
import 'package:hub/features/local/index.dart';
import 'package:hub/features/menu/index.dart';
import 'package:hub/features/module/data/index.dart';
import 'package:hub/features/module/domain/index.dart';
import 'package:hub/features/storage/index.dart';
import 'package:hub/flutter_flow/index.dart' as ff;
import 'package:hub/initialization.dart';
import 'package:hub/main.dart';
import 'package:integration_test/integration_test.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:patrol_finders/patrol_finders.dart';
import 'fuzzer/fuzzer.dart';
part 'auth_test.dart';
part 'home_test.dart';
part 'locals_test.dart';
part 'menu_test.dart';
part 'module_test.dart';
part 'notify_test.dart';
part 'profile_test.dart';
part 'property_test.dart';
part 'setting_test.dart';
part 'storage_test.dart';
part 'utils_test.dart';
part 'welcome_test.dart';
late PatrolTester $;
void main() {
//init integration test
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
setUp(() async {});
tearDown(() async {});
// WelcomeTest.signInToSignUp();
// WelcomeTest.signUpToSignIn();
// AuthenticationTest.signIn();
AuthenticationTest.signUp();
// AuthenticationTest.signOut();
//
// ModularizationTest.switchLicense();
// ModularizationTest.containLicense();
//
// MenuTest.navToEntries();
// MenuTest.containEntries();
// MenuTest.labels2AppbarConsistency();
//
// LocalsTest.setLocal();
// LocalsTest.unlinkLocal();
}

View File

@ -0,0 +1,244 @@
part of 'app_test.dart';
class AuthenticationTest {
static Future<void> signIn() async {
patrolWidgetTest(
'Sign-In with fuzzed emails',
(PatrolTester tester) async {
$ = tester;
$.tester
.printToConsole('Authentication Test - Sign-In with fuzzed emails');
final PatrolFinder throwsException = $(Dialog).$(ThrowExceptionWidget);
final Fuzzer fuzzer = Fuzzer(
configs: [
FuzzConfig(
label: 'username',
type: AcceptedTypes.string,
minLength: 5,
maxLength: 10,
),
FuzzConfig(
label: 'domain',
type: AcceptedTypes.string,
minLength: 5,
maxLength: 10,
),
FuzzConfig(
label: 'password',
type: AcceptedTypes.string,
minLength: 5,
maxLength: 10,
),
],
iterations: 10,
);
Map<String, String> concat(
String username, String domain, String password) {
return {
'emailTextFormField': '${username}@${domain}.com',
'passwordTextFormField': password,
};
}
final credentials = fuzzer.fuzz(concat);
await _unlogged();
await $.pumpWidgetAndSettle(const App());
await _navigateToSignIn($);
for (var credential in credentials) {
print('Função: ${credential.functionName}');
print('Entradas: ${credential.inputs}');
print('Saída: ${credential.output}');
print('Mensagem: ${credential.message}');
print('---');
await _auth(credential.output, $, throwsException);
}
},
);
patrolWidgetTest(
'Sign-In with email_app@exemplo.com',
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole(
'Authentication Test - Sign-In with email_app@exemplo.com');
final PatrolFinder throwsException = $(Dialog).$(ThrowExceptionWidget);
final Map<String, String> credentials = {
'emailTextFormField': 'email_app@exemplo.com',
'passwordTextFormField': '12345678',
};
await _unlogged();
await $.pumpWidgetAndSettle(const App());
await _navigateToSignIn($);
await _auth(credentials, $, throwsException);
},
);
}
static Future<void> signUp() async {
patrolWidgetTest(
'Sign Up - credenciais já registradas',
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole(
'Authentication Test - Sign-Up: credenciais já registradas');
final PatrolFinder throwsException = $(Dialog).$(ThrowExceptionWidget);
final Map<String, String> credentials = {
'nameTextFormField': 'app',
'emailTextFormField': 'email_app@exemplo.com',
'passwordTextFormField': '12345678',
};
await _unlogged();
await $.pumpWidgetAndSettle(const App());
await _navigateToSignUp($);
await _auth(credentials, $, throwsException);
await Future.delayed(const Duration(milliseconds: 500));
},
);
patrolWidgetTest(
'Sign Up - credenciais novas',
(PatrolTester tester) async {
$ = tester;
$.tester
.printToConsole('Authentication Test - Sign-Up: credenciais novas');
final PatrolFinder throwsException = $(Dialog).$(ThrowExceptionWidget);
final Fuzzer fuzzer = Fuzzer(
configs: [
FuzzConfig(
label: 'name',
type: AcceptedTypes.string,
minLength: 5,
maxLength: 10,
),
FuzzConfig(
label: 'username',
type: AcceptedTypes.string,
minLength: 5,
maxLength: 10,
),
FuzzConfig(
label: 'domain',
type: AcceptedTypes.string,
minLength: 5,
maxLength: 10,
),
FuzzConfig(
label: 'password',
type: AcceptedTypes.string,
minLength: 8,
maxLength: 10,
),
],
iterations: 10,
);
Map<String, String> concat(
String name, String username, String domain, String password) {
return {
'nameTextFormField': name,
'emailTextFormField': '${username}@${domain}.test',
'passwordTextFormField': password,
};
}
final credentials = fuzzer.fuzz(concat);
await _unlogged();
await $.pumpWidgetAndSettle(const App());
for (var credential in credentials) {
print('Função: ${credential.functionName}');
print('Entradas: ${credential.inputs}');
print('Saída: ${credential.output}');
print('Mensagem: ${credential.message}');
print('---');
await _navigateToSignUp($);
await _auth(credential.output, $, throwsException);
}
},
);
}
static Future<void> signOut() async {
patrolWidgetTest(
'Deslogar da Conta',
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole(
'Authentication Test - Sign-Out: Deslogar da Conta');
await _logged();
await $.pumpWidget(const App());
await $.waitUntilVisible($(MenuStaggeredView));
await $(Icons.menu_rounded) //
.waitUntilVisible()
.tap();
await $.waitUntilVisible($(MenuListView));
await $(Icons.exit_to_app)
.waitUntilVisible()
.tap(settlePolicy: SettlePolicy.trySettle);
await Future.delayed(const Duration(milliseconds: 500));
},
);
}
static Future<void> recovery() async {}
}
Future<void> _auth(
Map<String, String> credentials,
PatrolTester $,
PatrolFinder throwsException,
) async {
await _enterCredentials(credentials, $);
await _submit('SubmitButtonWidget', $, throwsException);
}
Future<void> _enterCredentials(
Map<String, String> credentials,
PatrolTester $,
) async {
for (var entry in credentials.entries) {
await $(ValueKey(entry.key)) //
.waitUntilVisible()
.enterText(entry.value);
await $.pumpAndSettle();
}
}
Future<void> _submit(
String key, PatrolTester $, PatrolFinder throwsException) async {
await $(ValueKey(key)) //
.waitUntilVisible()
.tap();
if ($(ValueKey('ThrowExceptionWidget')).exists) {
// expect(throwsException, findsOneWidget);
await $(ValueKey('ThrowExceptionWidget')) //
.waitUntilVisible()
.tap();
} else {
_navigateBackUsingSystemGesture();
}
}
String _generateRandomString(int length) {
const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
final rand = Random();
return List.generate(length, (index) => chars[rand.nextInt(chars.length)])
.join();
}

View File

@ -0,0 +1,138 @@
import 'dart:math';
enum AcceptedTypes {
string,
integer,
float,
stringList,
integerList,
floatList,
}
class FuzzConfig {
final String label;
final AcceptedTypes type;
final int minLength;
final int maxLength;
final num minValue;
final num maxValue;
FuzzConfig({
required this.label,
required this.type,
this.minLength = 1,
this.maxLength = 10,
this.minValue = 0,
this.maxValue = 100,
});
}
class FuzzerResult {
final String functionName;
final List<dynamic> inputs;
final dynamic output;
final String message;
FuzzerResult({
required this.functionName,
required this.inputs,
this.output,
required this.message,
});
}
class Fuzzer {
final List<FuzzConfig> configs;
final int iterations;
final Random _random = Random();
Fuzzer({
required this.configs,
this.iterations = 100,
});
List<FuzzerResult> fuzz(Function fn) {
final results = <FuzzerResult>[];
final parameterCount = configs.length;
for (int i = 0; i < iterations; i++) {
final inputs = _generateInputs(parameterCount);
try {
final output = Function.apply(fn, inputs);
results.add(FuzzerResult(
functionName: fn.toString(),
inputs: inputs,
output: output,
message: 'Execução bem-sucedida.',
));
} catch (e) {
results.add(FuzzerResult(
functionName: fn.toString(),
inputs: inputs,
message: 'Erro: $e',
));
}
}
return results;
}
List<dynamic> _generateInputs(int count) {
return List.generate(count, (index) {
final config = configs[index];
return _generateValue(config);
});
}
dynamic _generateValue(FuzzConfig config) {
switch (config.type) {
case AcceptedTypes.string:
final length =
_random.nextInt(config.maxLength - config.minLength + 1) +
config.minLength;
return _generateRandomString(length);
case AcceptedTypes.integer:
return _random.nextInt(
config.maxValue.toInt() - config.minValue.toInt() + 1) +
config.minValue.toInt();
case AcceptedTypes.float:
return _random.nextDouble() * (config.maxValue - config.minValue) +
config.minValue;
case AcceptedTypes.stringList:
final length =
_random.nextInt(config.maxLength - config.minLength + 1) +
config.minLength;
return List.generate(
length, (_) => _generateRandomString(_random.nextInt(10) + 1));
case AcceptedTypes.integerList:
final length =
_random.nextInt(config.maxLength - config.minLength + 1) +
config.minLength;
return List.generate(
length,
(_) =>
_random.nextInt(
config.maxValue.toInt() - config.minValue.toInt() + 1) +
config.minValue.toInt());
case AcceptedTypes.floatList:
final length =
_random.nextInt(config.maxLength - config.minLength + 1) +
config.minLength;
return List.generate(
length,
(_) =>
_random.nextDouble() * (config.maxValue - config.minValue) +
config.minValue);
}
}
String _generateRandomString(int length) {
const chars =
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
return String.fromCharCodes(
Iterable.generate(
length,
(_) => chars.codeUnitAt(_random.nextInt(chars.length)),
),
);
}
}

View File

@ -0,0 +1,11 @@
part of 'app_test.dart';
class homeTest {
static Future drawer() async {}
static Future header() async {}
static Future feed() async {}
static Future isLogged() async {}
}

View File

@ -0,0 +1,204 @@
part of 'app_test.dart';
class LocalsTest {
static Future setLocal() async {
patrolWidgetTest(
'Selecionar um local disponível', //
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole('Locals Test - Selecionar um local disponível');
await _logged(false);
await $.pumpWidgetAndSettle(const App());
await $.waitUntilVisible($(MenuStaggeredView));
await $.waitUntilVisible($(LocalProfileComponentWidget));
final PatrolFinder profileFinder =
$(#AsyncLocalProfileComponentWidget_InkWell);
expect(profileFinder, findsOneWidget);
await $(profileFinder) //
.waitUntilVisible()
.tap();
final PatrolFinder bottomSheetFinder =
await $(BottomArrowLinkedLocalsComponentWidget) //
.waitUntilVisible();
expect(bottomSheetFinder, findsOneWidget);
final PatrolFinder listViewFinder = await $(bottomSheetFinder) //
.$(ListView)
.waitUntilVisible();
expect(listViewFinder, findsOneWidget);
await $.pump(const Duration(milliseconds: 500));
final PatrolFinder entriesFinder = await $(listViewFinder) //
.$(CardItemTemplateComponentWidget)
.waitUntilVisible();
expect(entriesFinder, findsWidgets);
if (entriesFinder.evaluate().isNotEmpty) {
await $(entriesFinder.first) //
.waitUntilVisible()
.tap();
await $.pumpAndSettle();
}
},
);
}
static Future unlinkLocal() async {
patrolWidgetTest('Desvincular do local selecionado', //
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole('Locals Test - Desvincular do local selecionado');
await _logged();
await $.pumpWidgetAndSettle(const App());
await $.waitUntilVisible($(MenuStaggeredView));
final PatrolFinder gridView = await $(GridView) //
.waitUntilVisible();
final PatrolFinder entries = await $(gridView)
.$(ButtonMenuItem) //
.waitUntilVisible();
await $.pumpAndSettle();
expect(entries, findsWidgets);
final PatrolFinder settings = await $(gridView) //
.$(Icons.settings)
.waitUntilVisible();
expect(settings, findsOneWidget);
await $(settings).tap();
final PatrolFinder unlinkButton = await $(Symbols.digital_out_of_home) //
.waitUntilVisible();
expect(unlinkButton, findsOneWidget);
await $(unlinkButton) //
.waitUntilVisible()
.tap();
final PatrolFinder alertDialog = await $(#AlertDialogKey) //
.waitUntilVisible();
await alertDialog
.$(#AcceptOptionKey) //
.waitUntilVisible()
.tap(settlePolicy: SettlePolicy.noSettle);
await $.pump();
await $.pump(const Duration(seconds: 1));
await $.pump();
final PatrolFinder bottomSheetFinder =
await $(BottomArrowLinkedLocalsComponentWidget) //
.waitUntilVisible();
expect(bottomSheetFinder, findsOneWidget);
final PatrolFinder listViewFinder = await $(bottomSheetFinder) //
.$(ListView)
.waitUntilVisible();
expect(listViewFinder, findsOneWidget);
final PatrolFinder entriesFinder = await $(listViewFinder)
.$(CardItemTemplateComponentWidget)
.waitUntilVisible();
expect(entriesFinder, findsWidgets);
});
patrolWidgetTest(
'Vincular um local desvinculado', //
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole('Locals Test - Vincular um local desvinculado');
await _logged(false);
await $.pumpWidget(const App());
final PatrolFinder bottomSheetFinder =
await $(BottomArrowLinkedLocalsComponentWidget) //
.waitUntilVisible();
expect(bottomSheetFinder, findsOneWidget);
await $.pump(const Duration(milliseconds: 500));
final PatrolFinder listViewFinder = $(bottomSheetFinder) //
.$(ListView);
expect(listViewFinder, findsOneWidget);
await $.pump(const Duration(milliseconds: 500));
final PatrolFinder entriesFinder = $(listViewFinder) //
.$(CardItemTemplateComponentWidget);
expect(entriesFinder, findsWidgets);
if (entriesFinder.evaluate().isNotEmpty) {
await $(entriesFinder.first).waitUntilVisible().tap();
final PatrolFinder alertDialog = await $(#AlertDialogKey) //
.waitUntilVisible();
await alertDialog
.$(#AcceptOptionKey) //
.waitUntilVisible()
.tap(settlePolicy: SettlePolicy.noSettle);
}
await Future.delayed(const Duration(milliseconds: 500));
// try {
// await $.pumpAndSettle(
// duration: const Duration(seconds: 2),
// phase: EnginePhase.sendSemanticsUpdate,
// timeout: const Duration(seconds: 2),
// );
// throw Exception('Local está vinculado');
// } catch (e) {
// await Future.delayed(const Duration(milliseconds: 500));
// return;
// }
},
);
}
static Future attachLocal() async {
patrolWidgetTest(
'Selecionar um local disponível', //
(PatrolTester tester) async {
$ = tester;
await _logged();
await $.pumpWidget(const App());
late Map<String, String> credentials;
final PatrolFinder throwsException = $('');
var name = ff.randomString(7, 7, true, true, true);
var email = '$name@example.com';
var password = '12345678';
credentials = {
'nameTextFormField': name,
'emailTextFormField': email,
'passwordTextFormField': password
};
await $.pumpWidget(const App());
await _navigateToSignUp($);
await _auth(credentials, $, throwsException);
credentials = {
'emailTextFormField': email,
'passwordTextFormField': password
};
await _auth(credentials, $, throwsException);
await $.pumpAndSettle();
await StorageHelper() //
.set(ProfileStorageKey.clientUUID.key, '7');
await $.pumpAndSettle();
await Future.delayed(const Duration(milliseconds: 500));
return;
},
);
}
}

View File

@ -0,0 +1,269 @@
part of 'app_test.dart';
class MenuTest {
static Future labels2AppbarConsistency() async {
patrolWidgetTest(
'As labels dos menuItems correspondem aos títulos das AppBars?', //
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole(
'Menu Test - As labels dos menuItems correspondem aos títulos das AppBars?');
await _logged();
await $.pumpWidgetAndSettle(const App());
await $.waitUntilVisible($(MenuStaggeredView));
await $.waitUntilVisible($(LocalProfileComponentWidget));
final PatrolFinder profileFinder =
await $(#AsyncLocalProfileComponentWidget_InkWell)
.waitUntilVisible();
expect(profileFinder, findsOneWidget);
await $(profileFinder) //
.waitUntilVisible()
.tap();
final PatrolFinder bottomSheetFinder =
await $(BottomArrowLinkedLocalsComponentWidget) //
.waitUntilVisible();
expect(bottomSheetFinder, findsOneWidget);
final PatrolFinder listViewFinder = await $(bottomSheetFinder) //
.$(ListView)
.waitUntilVisible();
expect(listViewFinder, findsOneWidget);
final PatrolFinder entriesFinder = await $(listViewFinder) //
.$(CardItemTemplateComponentWidget)
.waitUntilVisible();
expect(entriesFinder, findsWidgets);
if (entriesFinder.evaluate().isNotEmpty) {
await $(entriesFinder.first) //
.waitUntilVisible()
.tap(settlePolicy: SettlePolicy.noSettle);
}
await $.waitUntilVisible($(MenuStaggeredView));
await $.waitUntilVisible($(LocalProfileComponentWidget));
final List<String> routes = MenuEntry.entries
.where((entry) => entry.key != 'FRE-HUB-LOGOUT')
.map((entry) => entry.route)
.toList();
final List<String> titles = MenuEntry.entries
.where((entry) => entry.key != 'FRE-HUB-LOGOUT')
.map((entry) => entry.name)
.toList();
final LinkedHashMap<String, String> routesTitles = LinkedHashMap //
.fromIterables(routes, titles);
late String route;
late String title;
for (final entry in routesTitles.entries) {
route = entry.key;
title = entry.value;
print('route: $route');
print('title: $title');
if (route == '/petsPage') continue;
if (route == '/fastPassPage') continue;
if (route == '/reservation') continue;
if (route == '/petsOnThePropertyPage') continue;
if (route == '/registerVisitorPage') continue;
if (route == '/messageHistoryPage') continue;
if (route == '/packageOrder') continue;
if (route == '/provisionalHistoryPage') continue;
if (route == '/scheduleCompleteVisitPage') continue;
if (route == '/preferencesSettings') continue;
ff.navigatorKey.currentContext!.go(route);
final PatrolFinder appBar = await $(AppBar) //
.waitUntilExists();
final PatrolFinder titleAppBar = await appBar //
.$(title)
.waitUntilVisible();
expect(titleAppBar, findsOneWidget);
}
},
);
}
static Future containEntries() async {
patrolWidgetTest(
'HomeMenu contém seus itens?', //
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole('Menu Test - HomeMenu contém seus itens?');
await _logged();
await $.pumpWidgetAndSettle(const App());
await $.waitUntilVisible($(MenuStaggeredView));
await $.waitUntilVisible($(GridView));
final PatrolFinder gridEntries = await $(GridView) //
.$(ButtonMenuItem)
.waitUntilVisible();
expect(gridEntries, findsWidgets);
final List<String?> menuKeys = gridEntries
.evaluate()
.map((element) {
final key = element.widget.key;
if (key is ValueKey<String>) {
return key.value;
}
return null;
})
.where((key) => key != null)
.toList();
await $.pumpAndSettle();
final List<MenuEntry> entries = MenuEntry.entries;
await $.pumpAndSettle();
final List<String> entriesKey = entries
.where((entry) => entry.types.contains(MenuEntryType.Home))
.map((entry) => entry.key)
.toList();
await $.pumpAndSettle();
expect(entriesKey, containsAll(menuKeys));
},
);
patrolWidgetTest(
'DrawerMenu contém seus itens?', //
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole('Menu Test - DrawerMenu contém seus itens?');
await _logged();
await $.pumpWidgetAndSettle(const App());
await $.waitUntilVisible($(MenuStaggeredView));
await $.waitUntilVisible($(GridView));
final PatrolFinder gridEntries = await $(GridView) //
.$(ButtonMenuItem)
.waitUntilVisible();
expect(gridEntries, findsWidgets);
await $(Icons.menu_rounded).waitUntilVisible().tap();
await $.waitUntilVisible($(ListView));
final PatrolFinder listEntries = await $(ListView) //
.$(CardMenuItem)
.waitUntilVisible();
expect(listEntries, findsWidgets);
final List<String?> menuKeys = listEntries
.evaluate()
.map((element) {
final key = element.widget.key;
if (key is ValueKey<String>) {
return key.value;
}
return null;
})
.where((key) => key != null)
.toList();
await $.pumpAndSettle();
final List<MenuEntry> entries = MenuEntry.entries;
await $.pumpAndSettle();
final List<String> entriesKey = entries
.where((entry) => entry.types.contains(MenuEntryType.Drawer))
.map((entry) => entry.key)
.toList();
await $.pumpAndSettle();
expect(entriesKey, containsAll(menuKeys));
await Future.delayed(const Duration(milliseconds: 500));
},
);
}
static Future navToEntries() async {
patrolWidgetTest(
'Navegação entre items do Menu',
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole('Menu Test - Navegação entre items do Menu');
await _logged();
await $.pumpWidgetAndSettle(const App());
await $.waitUntilVisible($(MenuStaggeredView));
final PatrolFinder profile =
$(const Key('AsyncLocalProfileComponentWidget_InkWell'));
await $(profile)
.waitUntilVisible()
.tap(settlePolicy: SettlePolicy.noSettle);
await $.waitUntilVisible($(BottomArrowLinkedLocalsComponentWidget));
final PatrolFinder local = $('FRE ACCESS DEMO');
await $(local)
.waitUntilVisible()
.tap(settlePolicy: SettlePolicy.noSettle);
await $.waitUntilVisible($(MenuStaggeredView));
final Finder gridView = find.byType(GridView);
await $.waitUntilVisible(gridView);
final Finder gridEntries = find.descendant(
of: gridView,
matching: find.byType(ButtonMenuItem),
);
await $.pumpAndSettle();
expect(gridEntries, findsWidgets);
final int gridEntriesCount = gridEntries.evaluate().length;
await $.pumpAndSettle();
for (int i = 0; i < gridEntriesCount; i++) {
await $.waitUntilVisible(
$(MenuStaggeredView),
timeout: Duration(seconds: 1),
);
await $.waitUntilVisible(
gridView,
timeout: Duration(seconds: 1),
);
await $.waitUntilVisible(
gridEntries.at(i),
timeout: Duration(seconds: 1),
);
final ButtonMenuItem entry =
$.tester.widget<ButtonMenuItem>(gridEntries.at(i));
final Key? widgetKey = entry.key;
expect(widgetKey, isNotNull);
print('WIDGETKEY = $widgetKey');
if (widgetKey == ValueKey<String>('FRE-HUB-FASTPASS')) continue;
if (widgetKey == ValueKey<String>('FRE-HUB-QRCODE')) continue;
if (widgetKey == ValueKey<String>('FRE-HUB-RESERVATIONS')) continue;
if (widgetKey == ValueKey<String>('FRE-HUB-SETTINGS')) continue;
await $(gridEntries.at(i))
.waitUntilVisible(timeout: const Duration(seconds: 1))
.tap(
settleTimeout: const Duration(seconds: 1),
settlePolicy: SettlePolicy.noSettle,
);
await $.pumpAndSettle(duration: Duration(milliseconds: 500));
await $(Icons.keyboard_arrow_left)
.waitUntilVisible(timeout: const Duration(seconds: 1))
.tap(
settleTimeout: const Duration(seconds: 1),
settlePolicy: SettlePolicy.noSettle,
);
await $.pumpAndSettle(duration: Duration(milliseconds: 500));
}
},
);
}
}

View File

@ -0,0 +1,58 @@
part of 'app_test.dart';
class ModularizationTest {
static Future containLicense() async {
patrolWidgetTest('Os modulos de licença está sendo processados?',
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole(
'Modularization Test - Os modulos de licença está sendo processados?');
await _logged();
await $.pumpWidgetAndSettle(const App());
await $.waitUntilVisible($(MenuStaggeredView));
final LicenseRepository licenseRepository = LicenseRepositoryImpl();
final List<String> result = await licenseRepository.getLicense();
expect(result, isNotEmpty);
await $.pumpAndSettle();
final List<MenuEntry> entries = MenuEntry.entries;
final List<String> entriesKey = entries
.where((entry) => entry.types.contains(MenuEntryType.Home))
.map((entry) => '{key: ${entry.key}}')
.toList();
expect(result, containsAll(entriesKey));
return;
});
}
static Future switchLicense() async {
patrolWidgetTest(
'Licença está sendo atualizada?',
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole('Licença está sendo atualizada?');
await _logged();
await $.pumpWidgetAndSettle(const App());
await $.waitUntilVisible($(MenuStaggeredView));
final PatrolFinder profile =
$(const Key('AsyncLocalProfileComponentWidget_InkWell'));
await $(profile)
.waitUntilVisible()
.tap(settlePolicy: SettlePolicy.noSettle);
await $.waitUntilVisible($(BottomArrowLinkedLocalsComponentWidget));
final PatrolFinder local = $('FRE ACCESS DEMO');
await $(local)
.waitUntilVisible()
.tap(settlePolicy: SettlePolicy.trySettle);
},
);
}
}

View File

@ -0,0 +1,3 @@
part of 'app_test.dart';
class notifyTest {}

View File

@ -0,0 +1,27 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:patrol/patrol.dart';
void main() {
patrolTest(
'counter state is the same after going to home and switching apps',
($) async {
// Replace later with your app's main widget
await $.pumpWidgetAndSettle(
MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('app')),
backgroundColor: Colors.blue,
),
),
);
expect($('app'), findsOneWidget);
if (!Platform.isMacOS) {
await $.native.pressHome();
}
},
);
}

View File

@ -0,0 +1 @@
part of 'app_test.dart';

View File

@ -0,0 +1,3 @@
part of 'app_test.dart';
class propertyTest {}

View File

@ -0,0 +1,3 @@
part of 'app_test.dart';
class settingTest {}

View File

@ -0,0 +1,3 @@
part of 'app_test.dart';
class storageTest {}

View File

@ -0,0 +1,86 @@
// GENERATED CODE - DO NOT MODIFY BY HAND AND DO NOT COMMIT TO VERSION CONTROL
// ignore_for_file: type=lint, invalid_use_of_internal_member
import 'dart:async';
import 'package:flutter_test/flutter_test.dart';
import 'package:patrol/patrol.dart';
import 'package:patrol/src/native/contracts/contracts.dart';
import 'package:test_api/src/backend/invoker.dart';
// START: GENERATED TEST IMPORTS
import 'app_test.dart' as app_test;
// END: GENERATED TEST IMPORTS
Future<void> main() async {
// This is the entrypoint of the bundled Dart test.
//
// Its responsibilies are:
// * Running a special Dart test that runs before all the other tests and
// explores the hierarchy of groups and tests.
// * Hosting a PatrolAppService, which the native side of Patrol uses to get
// the Dart tests, and to request execution of a specific Dart test.
//
// When running on Android, the Android Test Orchestrator, before running the
// tests, makes an initial run to gather the tests that it will later run. The
// native side of Patrol (specifically: PatrolJUnitRunner class) is hooked
// into the Android Test Orchestrator lifecycle and knows when that initial
// run happens. When it does, PatrolJUnitRunner makes an RPC call to
// PatrolAppService and asks it for Dart tests.
//
// When running on iOS, the native side of Patrol (specifically: the
// PATROL_INTEGRATION_TEST_IOS_RUNNER macro) makes an initial run to gather
// the tests that it will later run (same as the Android). During that initial
// run, it makes an RPC call to PatrolAppSevice and asks it for Dart tests.
//
// Once the native runner has the list of Dart tests, it dynamically creates
// native test cases from them. On Android, this is done using the
// Parametrized JUnit runner. On iOS, new test case methods are swizzled into
// the RunnerUITests class, taking advantage of the very dynamic nature of
// Objective-C runtime.
//
// Execution of these dynamically created native test cases is then fully
// managed by the underlying native test framework (JUnit on Android, XCTest
// on iOS). The native test cases do only one thing - request execution of the
// Dart test (out of which they had been created) and wait for it to complete.
// The result of running the Dart test is the result of the native test case.
final nativeAutomator = NativeAutomator(config: NativeAutomatorConfig());
await nativeAutomator.initialize();
final binding = PatrolBinding.ensureInitialized(NativeAutomatorConfig());
final testExplorationCompleter = Completer<DartGroupEntry>();
// A special test to explore the hierarchy of groups and tests. This is a hack
// around https://github.com/dart-lang/test/issues/1998.
//
// This test must be the first to run. If not, the native side likely won't
// receive any tests, and everything will fall apart.
test('patrol_test_explorer', () {
// Maybe somewhat counterintuitively, this callback runs *after* the calls
// to group() below.
final topLevelGroup = Invoker.current!.liveTest.groups.first;
final dartTestGroup = createDartTestGroup(topLevelGroup,
tags: null,
excludeTags: null,
);
testExplorationCompleter.complete(dartTestGroup);
print('patrol_test_explorer: obtained Dart-side test hierarchy:');
reportGroupStructure(dartTestGroup);
});
// START: GENERATED TEST GROUPS
group('app_test', app_test.main);
// END: GENERATED TEST GROUPS
final dartTestGroup = await testExplorationCompleter.future;
final appService = PatrolAppService(topLevelDartTestGroup: dartTestGroup);
binding.patrolAppService = appService;
await runAppService(appService);
// Until now, the native test runner was waiting for us, the Dart side, to
// come alive. Now that we did, let's tell it that we're ready to be asked
// about Dart tests.
await nativeAutomator.markPatrolAppServiceReady();
await appService.testExecutionCompleted;
}

View File

@ -0,0 +1,63 @@
part of 'app_test.dart';
Future<void> _logged([bool forceLinkedLocal = true]) async {
await initializeApp();
await StorageHelper() //
.set(SecureStorageKey.isLogged.value, 'true');
await StorageHelper() //
.set(SecureStorageKey.haveLocal.value, 'true');
await StorageHelper() //
.set(ProfileStorageKey.devUUID.key, 'b5c3818753e76d85');
await StorageHelper() //
.set(ProfileStorageKey.userUUID.key, '649c45d7514a28.85876308');
await StorageHelper() //
.set(SecureStorageKey.email.value, 'email_app@exemplo.com');
await StorageHelper() //
.set(SecureStorageKey.password.value, '123456');
await StorageHelper() //
.set(LocalsStorageKey.isNewVersion.key, true);
if (forceLinkedLocal == true) {
await StorageHelper() //
.set(ProfileStorageKey.clientUUID.key, '7');
await PhpGroup //
.resopndeVinculo
.call(tarefa: 'A');
await LicenseRepositoryImpl() //
.resetLicense();
}
}
Future<void> _unlogged() async {
await initializeApp();
await StorageHelper() //
.set(SecureStorageKey.isLogged.value, 'false');
await StorageHelper() //
.set(SecureStorageKey.haveLocal.value, 'false');
await StorageHelper() //
.set(ProfileStorageKey.devUUID.key, '');
await StorageHelper() //
.set(ProfileStorageKey.userUUID.key, '');
await StorageHelper() //
.set(ProfileStorageKey.clientUUID.key, '');
await StorageHelper() //
.set(SecureStorageKey.email.value, '');
await StorageHelper() //
.set(SecureStorageKey.password.value, '');
await StorageHelper() //
.set(LocalsStorageKey.isNewVersion.key, true);
}
Future<void> _navigateToSignIn(PatrolTester $) async {
final signInButton = $(#toggleSignInPage).waitUntilVisible();
await signInButton.tap();
}
Future<void> _navigateToSignUp(PatrolTester $) async {
final signUpButton = $(#toggleSignUpPage).waitUntilVisible();
await signUpButton.tap();
}
Future<void> _navigateBackUsingSystemGesture() async =>
IntegrationTestWidgetsFlutterBinding.instance.keyboard
.isLogicalKeyPressed(LogicalKeyboardKey.escape);

View File

@ -0,0 +1,31 @@
part of 'app_test.dart';
class WelcomeTest {
static Future signInToSignUp() async {
patrolWidgetTest(
'Sign-In to Sign-Up',
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole('Welcome Test - Sign-In to Sign-Up');
await _unlogged();
await $.pumpWidgetAndSettle(const App());
await _navigateToSignIn($);
await _navigateToSignUp($);
},
);
}
static Future signUpToSignIn() async {
patrolWidgetTest(
'Sign-Up to Sign-In',
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole('Welcome Test - Sign-Up to Sign-In');
await _unlogged();
await $.pumpWidgetAndSettle(const App());
await _navigateToSignUp($);
await _navigateToSignIn($);
},
);
}
}

View File

@ -7,9 +7,11 @@ class AppBarUtil extends StatelessWidget implements PreferredSizeWidget {
final String title; final String title;
final VoidCallback? onBackButtonPressed; final VoidCallback? onBackButtonPressed;
final Widget? actionButton; final Widget? actionButton;
final Key appBarKey;
const AppBarUtil({ const AppBarUtil({
super.key, super.key,
required this.appBarKey,
required this.title, required this.title,
this.onBackButtonPressed, this.onBackButtonPressed,
this.actionButton, this.actionButton,
@ -18,6 +20,7 @@ class AppBarUtil extends StatelessWidget implements PreferredSizeWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AppBar( return AppBar(
key: appBarKey,
backgroundColor: FlutterFlowTheme.of(context).primaryBackground, backgroundColor: FlutterFlowTheme.of(context).primaryBackground,
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
forceMaterialTransparency: true, forceMaterialTransparency: true,

View File

@ -1,3 +1,5 @@
import 'dart:developer';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hub/components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_model.dart'; import 'package:hub/components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_model.dart';
import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart'; import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart';
@ -202,7 +204,9 @@ class _BottomArrowLinkedLocalsComponentWidgetState
} }
Widget _item(BuildContext context, dynamic local) { Widget _item(BuildContext context, dynamic local) {
log('local: ${local['CLI_NOME']}');
return CardItemTemplateComponentWidget( return CardItemTemplateComponentWidget(
key: ValueKey<String>(local['CLI_NOME']),
imagePath: _imagePath(local), imagePath: _imagePath(local),
labelsHashMap: _labelsHashMap(local), labelsHashMap: _labelsHashMap(local),
statusHashMap: [_statusHashMap(local)], statusHashMap: [_statusHashMap(local)],

View File

@ -218,6 +218,7 @@ class _CardItemTemplateComponentWidgetState
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return InkWell( return InkWell(
key: widget.key,
splashColor: Colors.transparent, splashColor: Colors.transparent,
focusColor: Colors.transparent, focusColor: Colors.transparent,
hoverColor: Colors.transparent, hoverColor: Colors.transparent,

View File

@ -1,14 +1,15 @@
import 'package:easy_debounce/easy_debounce.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:hub/flutter_flow/nav/nav.dart'; import 'package:hub/flutter_flow/nav/nav.dart';
import 'package:hub/shared/utils/limited_text_size.dart'; import 'package:hub/shared/utils/limited_text_size.dart';
import '/flutter_flow/flutter_flow_theme.dart'; import '/flutter_flow/flutter_flow_theme.dart';
import '/flutter_flow/flutter_flow_util.dart'; import '/flutter_flow/flutter_flow_util.dart';
import '/flutter_flow/flutter_flow_widgets.dart'; import '/flutter_flow/flutter_flow_widgets.dart';
import 'package:easy_debounce/easy_debounce.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_fonts/google_fonts.dart';
import 'qr_code_pass_key_template_component_model.dart'; import 'qr_code_pass_key_template_component_model.dart';
export 'qr_code_pass_key_template_component_model.dart'; export 'qr_code_pass_key_template_component_model.dart';
class QrCodePassKeyTemplateComponentWidget extends StatefulWidget { class QrCodePassKeyTemplateComponentWidget extends StatefulWidget {

View File

@ -7,11 +7,14 @@ import 'sign_in_template_component_widget.dart'
class SignInTemplateComponentModel class SignInTemplateComponentModel
extends FlutterFlowModel<SignInTemplateComponentWidget> { extends FlutterFlowModel<SignInTemplateComponentWidget> {
final formKey = GlobalKey<FormState>(); final formKey = GlobalKey<FormState>();
final unfocusNode = FocusNode(); final unfocusNode = FocusNode();
FocusNode? emailAddressFocusNode; FocusNode? emailAddressFocusNode;
TextEditingController? emailAddressTextController; TextEditingController? emailAddressTextController;
String? Function(BuildContext, String?)? emailAddressTextControllerValidator; String? Function(BuildContext, String?)? emailAddressTextControllerValidator;
SignInTemplateComponentModel(); SignInTemplateComponentModel();
String? _emailAddressTextControllerValidator( String? _emailAddressTextControllerValidator(
BuildContext context, String? val) { BuildContext context, String? val) {
if (val == null || val.isEmpty) { if (val == null || val.isEmpty) {
@ -32,6 +35,7 @@ class SignInTemplateComponentModel
TextEditingController? passwordTextController; TextEditingController? passwordTextController;
late bool passwordVisibility; late bool passwordVisibility;
String? Function(BuildContext, String?)? passwordTextControllerValidator; String? Function(BuildContext, String?)? passwordTextControllerValidator;
String? _passwordTextControllerValidator(BuildContext context, String? val) { String? _passwordTextControllerValidator(BuildContext context, String? val) {
if (val == null || val.isEmpty) { if (val == null || val.isEmpty) {
return FFLocalizations.of(context).getText( return FFLocalizations.of(context).getText(

View File

@ -148,6 +148,7 @@ class AuthenticationService {
await StorageHelper().clean(Storage.databaseStorage); await StorageHelper().clean(Storage.databaseStorage);
await StorageHelper().clean(Storage.secureStorage); await StorageHelper().clean(Storage.secureStorage);
DatabaseService.isInitialized = false; DatabaseService.isInitialized = false;
await DatabaseService.instance.init(); await DatabaseService.instance.init();

View File

@ -18,7 +18,11 @@ const _kPrivateApiFunctionName = 'ffPrivateApiCall';
/// Start PHP Group Code /// Start PHP Group Code
class PhpGroup { abstract class Api {
GetLicense getLicense = GetLicense();
}
class PhpGroup extends Api {
static String getBaseUrl() => 'https://freaccess.com.br/freaccess'; static String getBaseUrl() => 'https://freaccess.com.br/freaccess';
static Map<String, String> headers = {}; static Map<String, String> headers = {};
static LoginCall loginCall = LoginCall(); static LoginCall loginCall = LoginCall();
@ -62,7 +66,7 @@ class PhpGroup {
static GetResidentsByProperty getResidentsByProperty = static GetResidentsByProperty getResidentsByProperty =
GetResidentsByProperty(); GetResidentsByProperty();
static GetOpenedVisits getOpenedVisits = GetOpenedVisits(); static GetOpenedVisits getOpenedVisits = GetOpenedVisits();
static GetLicense getLicense = GetLicense(); GetLicense getLicense = GetLicense();
static GetProvSchedules getProvSchedules = GetProvSchedules(); static GetProvSchedules getProvSchedules = GetProvSchedules();
} }

View File

@ -12,7 +12,6 @@ import 'package:hub/flutter_flow/flutter_flow_util.dart';
import 'package:hub/shared/utils/dialog_util.dart'; import 'package:hub/shared/utils/dialog_util.dart';
import 'package:hub/shared/utils/log_util.dart'; import 'package:hub/shared/utils/log_util.dart';
import 'package:hub/shared/utils/snackbar_util.dart'; import 'package:hub/shared/utils/snackbar_util.dart';
import 'package:rxdart/rxdart.dart'; import 'package:rxdart/rxdart.dart';
@immutable @immutable
@ -92,6 +91,7 @@ class ProvisionalHistoryState extends State<ProvisionalHistoryPage> {
Widget _backButton(BuildContext context, FlutterFlowTheme theme) { Widget _backButton(BuildContext context, FlutterFlowTheme theme) {
return FlutterFlowIconButton( return FlutterFlowIconButton(
key: ValueKey<String>('BackNavigationAppBar'),
borderColor: Colors.transparent, borderColor: Colors.transparent,
borderRadius: 30.0, borderRadius: 30.0,
borderWidth: 1.0, borderWidth: 1.0,

View File

@ -11,11 +11,18 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
HomeBloc() : super(HomeState()) { HomeBloc() : super(HomeState()) {
on<HomeEvent>(_onHomeEvent); on<HomeEvent>(_onHomeEvent);
_completer = LocalsRepositoryImpl.license.stream.listen((v) { _completer = LocalsRepositoryImpl.license.stream.listen((v) {
add(HomeEvent()); add(HomeEvent());
}); });
} }
@override
Future<void> close() {
_completer.cancel();
return super.close();
}
Future<void> _onHomeEvent(HomeEvent event, Emitter<HomeState> emit) async { Future<void> _onHomeEvent(HomeEvent event, Emitter<HomeState> emit) async {
final devUUID = final devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';

View File

@ -2,12 +2,11 @@ import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'package:hub/features/home/presentation/widgets/drawer_widget.dart'; import 'package:hub/features/home/presentation/widgets/drawer_widget.dart';
import 'package:hub/features/local/index.dart';
import 'package:hub/features/menu/index.dart'; import 'package:hub/features/menu/index.dart';
import 'package:hub/flutter_flow/flutter_flow_icon_button.dart'; import 'package:hub/flutter_flow/flutter_flow_icon_button.dart';
import 'package:hub/flutter_flow/flutter_flow_theme.dart'; import 'package:hub/flutter_flow/flutter_flow_theme.dart';
import 'package:hub/flutter_flow/flutter_flow_util.dart'; import 'package:hub/flutter_flow/flutter_flow_util.dart';
import 'package:hub/features/local/index.dart';
class HomePageWidget extends StatefulWidget { class HomePageWidget extends StatefulWidget {
const HomePageWidget(this.update, {super.key}); const HomePageWidget(this.update, {super.key});

View File

@ -25,6 +25,9 @@ class LocalsLocalDataSourceImpl implements LocalsLocalDataSource {
Future<String?> get(String key) async { Future<String?> get(String key) async {
final String? local = final String? local =
await StorageHelper().get(ProfileStorageKey.clientUUID.key); await StorageHelper().get(ProfileStorageKey.clientUUID.key);
if (local == null) {
return null;
}
var response = await DatabaseService.database.query( var response = await DatabaseService.database.query(
LocalsConstants.tableLocalsKeychain, LocalsConstants.tableLocalsKeychain,
where: 'key = ? AND local = ?', where: 'key = ? AND local = ?',

View File

@ -38,6 +38,12 @@ class LocalProfileBloc extends Bloc<LocalProfileEvent, LocalProfileState> {
}); });
} }
@override
Future<void> close() {
_completer.cancel();
return super.close();
}
Future<void> _onLocalProfileEvent( Future<void> _onLocalProfileEvent(
LocalProfileEvent event, Emitter<LocalProfileState> emit) async { LocalProfileEvent event, Emitter<LocalProfileState> emit) async {
final cliName = final cliName =

View File

@ -87,6 +87,8 @@ class _LocalProfileComponentWidgetState
child: Padding( child: Padding(
padding: const EdgeInsets.all(2.0), padding: const EdgeInsets.all(2.0),
child: InkWell( child: InkWell(
key: const Key(
'DefaultLocalProfileComponentWidget_InkWell'),
splashColor: Colors.transparent, splashColor: Colors.transparent,
focusColor: Colors.transparent, focusColor: Colors.transparent,
hoverColor: Colors.transparent, hoverColor: Colors.transparent,
@ -180,6 +182,8 @@ class _LocalProfileComponentWidgetState
child: Padding( child: Padding(
padding: const EdgeInsets.all(2.0), padding: const EdgeInsets.all(2.0),
child: InkWell( child: InkWell(
key: const Key(
'AsyncLocalProfileComponentWidget_InkWell'),
splashColor: Colors.transparent, splashColor: Colors.transparent,
focusColor: Colors.transparent, focusColor: Colors.transparent,
hoverColor: Colors.transparent, hoverColor: Colors.transparent,

View File

@ -9,29 +9,41 @@ import 'package:hub/shared/extensions/dialog_extensions.dart';
import 'package:hub/shared/utils/path_util.dart'; import 'package:hub/shared/utils/path_util.dart';
abstract class MenuLocalDataSource { abstract class MenuLocalDataSource {
Future<MenuItem?> addMenuEntry(EnumMenuItem item, List<MenuItem?> entries, Future<MenuItem?> addMenuEntry(Key key, EnumMenuItem item,
IconData icon, String text, Function() action); List<MenuItem?> entries, IconData icon, String text, Function() action);
Future<bool> processDisplayDefault( Future<bool> processDisplayDefault(
EnumMenuItem item, MenuEntry opt, List<MenuItem?> entries); EnumMenuItem item, MenuEntry opt, List<MenuItem?> entries);
Future<void> handleMenu(EnumMenuItem item, EnumDisplay display, MenuEntry opt, Future<void> handleMenu(EnumMenuItem item, EnumDisplay display, MenuEntry opt,
List<MenuItem?> entries); List<MenuItem?> entries);
Future<bool> processStartDate(String startDate, MenuEntry entry); Future<bool> processStartDate(String startDate, MenuEntry entry);
Future<bool> processExpirationDate(String expirationDate, MenuEntry entry); Future<bool> processExpirationDate(String expirationDate, MenuEntry entry);
} }
class MenuLocalDataSourceImpl implements MenuLocalDataSource { class MenuLocalDataSourceImpl implements MenuLocalDataSource {
static final MenuLocalDataSourceImpl _instance = static final MenuLocalDataSourceImpl _instance =
MenuLocalDataSourceImpl._internal(); MenuLocalDataSourceImpl._internal();
factory MenuLocalDataSourceImpl() => _instance; factory MenuLocalDataSourceImpl() => _instance;
MenuLocalDataSourceImpl._internal(); MenuLocalDataSourceImpl._internal();
@override @override
Future<MenuItem?> addMenuEntry(EnumMenuItem item, List<MenuItem?> entries, Future<MenuItem?> addMenuEntry(
IconData icon, String text, Function() action) async { Key key,
EnumMenuItem item,
List<MenuItem?> entries,
IconData icon,
String text,
Function() action,
) async {
final menuItem = item == EnumMenuItem.button final menuItem = item == EnumMenuItem.button
? ButtonMenuItem(icon: icon, action: action, title: text) ? ButtonMenuItem(key: key, icon: icon, action: action, title: text)
: item == EnumMenuItem.card || item == EnumMenuItem.tile : item == EnumMenuItem.card || item == EnumMenuItem.tile
? CardMenuItem(icon: icon, action: action, title: text) ? CardMenuItem(key: key, icon: icon, action: action, title: text)
: null; : null;
if (menuItem != null) { if (menuItem != null) {
entries.add(menuItem); entries.add(menuItem);
@ -43,7 +55,9 @@ class MenuLocalDataSourceImpl implements MenuLocalDataSource {
Future<bool> processDisplayDefault( Future<bool> processDisplayDefault(
EnumMenuItem item, MenuEntry opt, List<MenuItem?> entries) async { EnumMenuItem item, MenuEntry opt, List<MenuItem?> entries) async {
if (opt.key == 'FRE-HUB-LOGOUT') { if (opt.key == 'FRE-HUB-LOGOUT') {
await addMenuEntry(item, entries, opt.icon, opt.name, () async { await addMenuEntry(
ValueKey<String>(opt.key), item, entries, opt.icon, opt.name,
() async {
await AuthenticationService.signOut(navigatorKey.currentContext!); await AuthenticationService.signOut(navigatorKey.currentContext!);
}); });
return true; return true;
@ -57,12 +71,16 @@ class MenuLocalDataSourceImpl implements MenuLocalDataSource {
try { try {
switch (display.value) { switch (display.value) {
case 'VISIVEL': case 'VISIVEL':
await addMenuEntry(item, entries, opt.icon, opt.name, () async { await addMenuEntry(
ValueKey<String>(opt.key), item, entries, opt.icon, opt.name,
() async {
await PathUtil.nav(opt.route); await PathUtil.nav(opt.route);
}); });
break; break;
case 'DESABILITADO': case 'DESABILITADO':
await addMenuEntry(item, entries, opt.icon, opt.name, () async { await addMenuEntry(
ValueKey<String>(opt.key), item, entries, opt.icon, opt.name,
() async {
await DialogUnavailable.unavailableFeature( await DialogUnavailable.unavailableFeature(
navigatorKey.currentContext!); navigatorKey.currentContext!);
}); });

View File

@ -2,24 +2,24 @@ import 'dart:developer';
import 'package:hub/features/menu/index.dart'; import 'package:hub/features/menu/index.dart';
import 'package:hub/features/module/index.dart'; import 'package:hub/features/module/index.dart';
import 'package:hub/features/storage/index.dart';
import 'package:hub/flutter_flow/custom_functions.dart'; import 'package:hub/flutter_flow/custom_functions.dart';
class MenuRepositoryImpl implements MenuRepository { class MenuRepositoryImpl implements MenuRepository {
final MenuLocalDataSource menuDataSource = MenuLocalDataSourceImpl(); final MenuLocalDataSource menuDataSource = MenuLocalDataSourceImpl();
@override @override
Future<List<MenuItem?>> generateMenuEntries( Future<List<MenuItem?>> entries2Items(
List<MenuEntry> menuEntries, EnumMenuItem item) async { List<MenuEntry> menuEntries, EnumMenuItem menuItem) async {
List<MenuItem?> entries = []; List<MenuItem?> entries = [];
// final bool isNewVersion = await StorageHelper().get(KeychainStorageKey.isNewVersion.value).then((v) => v.toBoolean()); // final bool isNewVersion = await StorageHelper().get(KeychainStorageKey.isNewVersion.value).then((v) => v.toBoolean());
try { try {
for (var entry in menuEntries) { for (var entry in menuEntries) {
final bool isDefault = final bool isDefault = await menuDataSource.processDisplayDefault(
await menuDataSource.processDisplayDefault(item, entry, entries); menuItem, entry, entries);
if (isDefault) continue; if (isDefault) continue;
final licenseValue = final licenseValue = await LicenseRepositoryImpl().getModule(entry.key);
await LicenseRepositoryImpl().getLicense(entry.key);
if (licenseValue != null) { if (licenseValue != null) {
final licenseMap = await stringToMap(licenseValue); final licenseMap = await stringToMap(licenseValue);
final display = EnumDisplay.fromString(licenseMap['display']); final display = EnumDisplay.fromString(licenseMap['display']);
@ -30,17 +30,17 @@ class MenuRepositoryImpl implements MenuRepository {
final isExpired = final isExpired =
await menuDataSource.processExpirationDate(expirationDate, entry); await menuDataSource.processExpirationDate(expirationDate, entry);
if (isStarted && !isExpired) { if (isStarted && !isExpired) {
await menuDataSource.handleMenu(item, display, entry, entries); await menuDataSource.handleMenu(menuItem, display, entry, entries);
} }
if (isExpired) { if (isExpired) {
log('Entry ${entry.key} is expired'); log('Entry ${entry.key} is expired');
await menuDataSource.handleMenu( await menuDataSource.handleMenu(
item, EnumDisplay.inactive, entry, entries); menuItem, EnumDisplay.inactive, entry, entries);
} }
if (!isStarted) { if (!isStarted) {
log('Entry ${entry.key} is not started'); log('Entry ${entry.key} is not started');
await menuDataSource.handleMenu( await menuDataSource.handleMenu(
item, EnumDisplay.inactive, entry, entries); menuItem, EnumDisplay.inactive, entry, entries);
} }
} }
} }
@ -55,7 +55,7 @@ class MenuRepositoryImpl implements MenuRepository {
if (await _shouldUpdateDisplay(module, isNewVersion)) { if (await _shouldUpdateDisplay(module, isNewVersion)) {
final displayValue = final displayValue =
module['display'] == EnumDisplay.active ? 'VISIVEL' : 'INVISIVEL'; module['display'] == EnumDisplay.active ? 'VISIVEL' : 'INVISIVEL';
await LicenseLocalDataSourceImpl() await LicenseLocalDataSourceImpl(DatabaseService.database)
.setDisplayByKey(['FRE-HUB-ABOUT-PROPERTY'], displayValue); .setDisplayByKey(['FRE-HUB-ABOUT-PROPERTY'], displayValue);
return EnumDisplay.fromString(displayValue); return EnumDisplay.fromString(displayValue);
} }

View File

@ -1,6 +1,6 @@
import 'package:hub/features/menu/index.dart'; import 'package:hub/features/menu/index.dart';
abstract class MenuRepository { abstract class MenuRepository {
Future<List<MenuItem?>> generateMenuEntries( Future<List<MenuItem?>> entries2Items(
List<MenuEntry> menuEntries, EnumMenuItem item); List<MenuEntry> menuEntries, EnumMenuItem item);
} }

View File

@ -1,9 +1,10 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:hub/features/backend/index.dart';
import 'package:hub/features/local/index.dart';
import 'package:hub/features/menu/index.dart'; import 'package:hub/features/menu/index.dart';
import 'package:hub/features/module/index.dart'; import 'package:hub/features/module/index.dart';
import 'package:hub/features/local/index.dart';
class MenuEvent {} class MenuEvent {}
@ -36,10 +37,10 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> {
} }
Future<void> _onMenuEvent(MenuEvent event, Emitter<MenuState> emit) async { Future<void> _onMenuEvent(MenuEvent event, Emitter<MenuState> emit) async {
await LicenseRemoteDataSourceImpl().waitForSaveCompletion(); await LicenseRemoteDataSourceImpl(PhpGroup()).waitForSaveCompletion();
final List<MenuItem?> newEntries = final List<MenuItem?> newEntries =
await MenuRepositoryImpl().generateMenuEntries(entries, item); await MenuRepositoryImpl().entries2Items(entries, item);
emit(state.copyWith(menuEntries: newEntries)); emit(state.copyWith(menuEntries: newEntries));
} }

View File

@ -37,7 +37,7 @@ class MenuEntry implements BaseModule {
icon: Icons.sports_motorsports_outlined, icon: Icons.sports_motorsports_outlined,
name: FFLocalizations.of(navigatorKey.currentContext!).getVariableText( name: FFLocalizations.of(navigatorKey.currentContext!).getVariableText(
ptText: 'Agendar Entregas', ptText: 'Agendar Entregas',
enText: 'Schedule Delivery', enText: 'Delivery Schedule',
), ),
route: '/deliverySchedule', route: '/deliverySchedule',
types: [MenuEntryType.Home, MenuEntryType.Drawer], types: [MenuEntryType.Home, MenuEntryType.Drawer],

View File

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'package:hub/features/menu/index.dart'; import 'package:hub/features/menu/index.dart';
import 'package:hub/flutter_flow/flutter_flow_theme.dart'; import 'package:hub/flutter_flow/flutter_flow_theme.dart';
import 'package:hub/flutter_flow/flutter_flow_util.dart';
class CardMenuItem extends MenuItem { class CardMenuItem extends MenuItem {
const CardMenuItem({ const CardMenuItem({
@ -35,11 +36,11 @@ class _MenuCardItemState extends State<CardMenuItem> {
onTap: _isProcessing onTap: _isProcessing
? null ? null
: () async { : () async {
setState(() { safeSetState(() {
_isProcessing = true; _isProcessing = true;
}); });
await widget.action.call(); await widget.action.call();
setState(() { safeSetState(() {
_isProcessing = false; _isProcessing = false;
}); });
}, },

View File

@ -1,21 +1,41 @@
import 'dart:developer';
import 'package:hub/features/module/index.dart'; import 'package:hub/features/module/index.dart';
import 'package:hub/features/storage/index.dart'; import 'package:hub/features/storage/index.dart';
import 'package:hub/shared/extensions/string_extensions.dart'; import 'package:hub/shared/extensions/string_extensions.dart';
import 'package:sqflite/sqflite.dart';
abstract class LicenseLocalDataSource { abstract class LicenseLocalDataSource {
Future<void> init(); Future<void> init();
Future<void> setDisplayByKey(final List<String> key, final String display); Future<void> setDisplayByKey(final List<String> key, final String display);
Future<bool> isNewVersion(); Future<bool> isNewVersion();
Future<String?> get(String key); Future<String?> get(String key);
Future<void> set<T>(String key, T value);
Future<bool> set<T>(String key, T value);
Future<void> del(String key); Future<void> del(String key);
Future<bool> setupLicense(bool isNewVersion);
Future<List<String>> getLicense();
Future<void> clear(); Future<void> clear();
} }
class LicenseLocalDataSourceImpl implements LicenseLocalDataSource { class LicenseLocalDataSourceImpl implements LicenseLocalDataSource {
Database? _database;
static final LicenseLocalDataSourceImpl _instance = static final LicenseLocalDataSourceImpl _instance =
LicenseLocalDataSourceImpl._internal(); LicenseLocalDataSourceImpl._internal();
factory LicenseLocalDataSourceImpl() => _instance;
factory LicenseLocalDataSourceImpl(Database database) {
_instance._database ??= database;
return _instance;
}
LicenseLocalDataSourceImpl._internal(); LicenseLocalDataSourceImpl._internal();
@override @override
@ -23,6 +43,38 @@ class LicenseLocalDataSourceImpl implements LicenseLocalDataSource {
await DatabaseService.instance.init(); await DatabaseService.instance.init();
} }
@override
Future<bool> setupLicense(bool isNewVersion) async {
log('Setting up license...');
try {
final License license = await License.getLicense(isNewVersion);
final List<String> inactiveModuleKey = license.modules
.where((module) => module.display == ModuleStatus.inactive.key)
.map((module) => module.key)
.toList();
final List<String> activeModuleKey = license.modules
.where((module) => module.display == ModuleStatus.active.key)
.map((module) => module.key)
.toList();
final List<String> disabledModuleKey = license.modules
.where((module) => module.display == ModuleStatus.disabled.key)
.map((module) => module.key)
.toList();
await setDisplayByKey(inactiveModuleKey, 'INVISIVEL');
await setDisplayByKey(activeModuleKey, 'VISIVEL');
await setDisplayByKey(disabledModuleKey, 'DESABILITADO');
return true;
} catch (e, s) {
log('Erro ao configurar licenças: $e', stackTrace: s);
return false;
}
}
@override @override
Future<void> setDisplayByKey( Future<void> setDisplayByKey(
final List<String> keys, final String display) async { final List<String> keys, final String display) async {
@ -48,9 +100,9 @@ class LicenseLocalDataSourceImpl implements LicenseLocalDataSource {
@override @override
Future<String?> get(String key) async { Future<String?> get(String key) async {
var response = await DatabaseService.database var response = await _instance._database
.query(tableLicense, where: 'key = ?', whereArgs: [key]); ?.query(tableLicense, where: 'key = ?', whereArgs: [key]);
if (response.isEmpty) { if (response!.isEmpty) {
return null; return null;
} }
@ -58,12 +110,12 @@ class LicenseLocalDataSourceImpl implements LicenseLocalDataSource {
} }
@override @override
Future<void> set<T>(String key, T value) async { Future<bool> set<T>(String key, T value) async {
value as Map<String, dynamic>; value as Map<String, dynamic>;
if (value.isEmpty) return; if (value.isEmpty) return false;
if (key == 'null') return; if (key == 'null') return false;
await DatabaseService.database.rawInsert( await _instance._database?.rawInsert(
'INSERT OR REPLACE INTO $tableLicense (key, display, expirationDate, startDate, quantity) VALUES (?, ?, ?, ?, ?)', 'INSERT OR REPLACE INTO $tableLicense (key, display, expirationDate, startDate, quantity) VALUES (?, ?, ?, ?, ?)',
[ [
key, key,
@ -73,17 +125,27 @@ class LicenseLocalDataSourceImpl implements LicenseLocalDataSource {
value['quantity'] value['quantity']
], ],
); );
return; return true;
} }
@override @override
Future<void> del(String key) async { Future<void> del(String key) async {
await DatabaseService.database await _instance._database
.delete(tableLicense, where: 'key = ?', whereArgs: [key]); ?.delete(tableLicense, where: 'key = ?', whereArgs: [key]);
} }
@override @override
Future<void> clear() async { Future<void> clear() async {
await DatabaseService.database.delete(tableLicense); await _instance._database?.delete(tableLicense);
}
@override
Future<List<String>> getLicense() async {
var response =
await _instance._database?.query(tableLicense, columns: ['key']);
if (response!.isEmpty) {
return [];
}
return response.map((e) => e.toString()).toList();
} }
} }

View File

@ -6,60 +6,36 @@ import 'dart:developer';
import 'package:hub/features/backend/index.dart'; import 'package:hub/features/backend/index.dart';
import 'package:hub/features/local/data/repositories/locals_repository_impl.dart'; import 'package:hub/features/local/data/repositories/locals_repository_impl.dart';
import 'package:hub/features/module/index.dart'; import 'package:hub/features/module/index.dart';
import 'package:sqflite/sqflite.dart';
abstract class LicenseRemoteDataSource { abstract class LicenseRemoteDataSource {
Future<bool> fetchLicenses(bool isNewVersion); Future<bool> fetchLicenses(bool isNewVersion);
Future<void> cleanLicense(); Future<bool> cleanLicense();
Future<void> processLicense(); Future<void> processLicense();
Future<bool> setupLicense(Database database, bool isNewVersion);
} }
class LicenseRemoteDataSourceImpl implements LicenseRemoteDataSource { class LicenseRemoteDataSourceImpl implements LicenseRemoteDataSource {
Api? _api;
static final LicenseRemoteDataSourceImpl _instance = static final LicenseRemoteDataSourceImpl _instance =
LicenseRemoteDataSourceImpl._internal(); LicenseRemoteDataSourceImpl._internal();
factory LicenseRemoteDataSourceImpl() => _instance;
factory LicenseRemoteDataSourceImpl(Api api) {
_instance._api ??= api;
return _instance;
}
LicenseRemoteDataSourceImpl._internal(); LicenseRemoteDataSourceImpl._internal();
@override @override
Future<void> processLicense() async {} Future<void> processLicense() async {}
@override @override
Future<void> cleanLicense() async { Future<bool> cleanLicense() async {
LocalsRepositoryImpl.license.add(false);
}
@override
Future<bool> setupLicense(Database database, bool isNewVersion) async {
log('Setting up license...');
try { try {
final License license = await License.getLicense(isNewVersion); LocalsRepositoryImpl.license.add(false);
final List<String> inactiveModuleKey = license.modules
.where((module) => module.display == ModuleStatus.inactive.key)
.map((module) => module.key)
.toList();
final List<String> activeModuleKey = license.modules
.where((module) => module.display == ModuleStatus.active.key)
.map((module) => module.key)
.toList();
final List<String> disabledModuleKey = license.modules
.where((module) => module.display == ModuleStatus.disabled.key)
.map((module) => module.key)
.toList();
await LicenseLocalDataSourceImpl()
.setDisplayByKey(inactiveModuleKey, 'INVISIVEL');
await LicenseLocalDataSourceImpl()
.setDisplayByKey(activeModuleKey, 'VISIVEL');
await LicenseLocalDataSourceImpl()
.setDisplayByKey(disabledModuleKey, 'DESABILITADO');
return true; return true;
} catch (e, s) { } catch (e, s) {
log('Erro ao configurar licenças: $e', stackTrace: s); log('Erro ao limpar licenças: $e', stackTrace: s);
return false; return false;
} }
} }
@ -68,8 +44,8 @@ class LicenseRemoteDataSourceImpl implements LicenseRemoteDataSource {
Future<bool> fetchLicenses(bool isNewVersion) async { Future<bool> fetchLicenses(bool isNewVersion) async {
log('Fetching licenses...'); log('Fetching licenses...');
try { try {
final response = await PhpGroup.getLicense(); final response = await _instance._api?.getLicense();
final dynamic responseBody = response.jsonBody; final dynamic responseBody = response!.jsonBody;
if (responseBody == []) { if (responseBody == []) {
return true; return true;
@ -108,6 +84,6 @@ class LicenseRemoteDataSourceImpl implements LicenseRemoteDataSource {
static Future<void> _saveModule(final dynamic body) async { static Future<void> _saveModule(final dynamic body) async {
if (body is! Map<String, dynamic>) return; if (body is! Map<String, dynamic>) return;
await LicenseRepositoryImpl().setLicense(body['key'], body); await LicenseRepositoryImpl().setModule(body['key'], body);
} }
} }

View File

@ -5,44 +5,65 @@ import 'package:hub/features/module/domain/index.dart';
import 'package:hub/features/storage/index.dart'; import 'package:hub/features/storage/index.dart';
import 'package:sqflite/sqflite.dart'; import 'package:sqflite/sqflite.dart';
import '../../../backend/index.dart';
typedef LicenseStatus = bool; typedef LicenseStatus = bool;
class LicenseRepositoryImpl implements LicenseRepository { class LicenseRepositoryImpl implements LicenseRepository {
final LicenseLocalDataSource localDataSource = LicenseLocalDataSourceImpl(); late final Database database;
final LicenseRemoteDataSource remoteDataSource = late final Api api;
LicenseRemoteDataSourceImpl(); late final LicenseLocalDataSource localDataSource;
final Database database = DatabaseService.database; late final LicenseRemoteDataSource remoteDataSource;
LicenseRepositoryImpl(); LicenseRepositoryImpl([Database? database, Api? api])
: database = database ?? DatabaseService.database,
api = api ?? PhpGroup() {
localDataSource = LicenseLocalDataSourceImpl(this.database);
remoteDataSource = LicenseRemoteDataSourceImpl(this.api);
}
@override @override
Future<bool> updateLicense() async { Future<bool> updateLicense() async {
log('updateLicense'); log('updateLicense');
bool result = false; bool result = false;
final bool isNewVersion = await localDataSource.isNewVersion(); final bool isNewVersion = await localDataSource.isNewVersion();
if (isNewVersion) { if (isNewVersion) {
await remoteDataSource.setupLicense(database, isNewVersion); await localDataSource.setupLicense(isNewVersion);
result = await remoteDataSource.fetchLicenses(isNewVersion); result = await remoteDataSource.fetchLicenses(isNewVersion);
} else { } else {
result = await remoteDataSource.setupLicense(database, isNewVersion); result = await localDataSource.setupLicense(isNewVersion);
} }
return result; return result;
} }
@override @override
Future<void> cleanLicense() async { Future<bool> cleanLicense() async {
return await remoteDataSource.cleanLicense(); return await remoteDataSource.cleanLicense();
} }
@override @override
Future<String?> getLicense(String key) async { Future<String?> getModule(String key) async {
final response = await localDataSource.get(key); final response = await localDataSource.get(key);
return response; return response;
} }
@override @override
Future<void> setLicense<T>(String key, T value) async { Future<bool> setModule<T>(String key, T value) async {
return await localDataSource.set(key, value); return await localDataSource.set(key, value);
} }
@override
Future<List<String>> getLicense() async {
return await localDataSource.getLicense();
}
@override
Future<bool> resetLicense() async {
bool result = false;
final bool isNewVersion = await localDataSource.isNewVersion();
result = await localDataSource.setupLicense(isNewVersion);
return result;
}
} }

View File

@ -1,7 +1,13 @@
abstract class LicenseRepository { abstract class LicenseRepository {
Future<bool> updateLicense(); Future<bool> updateLicense();
Future<void> cleanLicense();
Future<String?> getLicense(String key); Future<bool> cleanLicense();
Future<void> setLicense<T>(String key, T value);
Future<bool> resetLicense();
Future<String?> getModule(String key);
Future<bool> setModule<T>(String key, T value);
Future<List<String>> getLicense();
} }

View File

@ -2,7 +2,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hub/components/atomic_components/shared_components_atoms/appbar.dart'; import 'package:hub/components/atomic_components/shared_components_atoms/appbar.dart';
import 'package:hub/features/menu/index.dart'; import 'package:hub/features/menu/index.dart';
import 'package:hub/flutter_flow/flutter_flow_model.dart';
import 'package:hub/flutter_flow/flutter_flow_theme.dart'; import 'package:hub/flutter_flow/flutter_flow_theme.dart';
import 'package:hub/flutter_flow/flutter_flow_util.dart'; import 'package:hub/flutter_flow/flutter_flow_util.dart';
import 'package:hub/flutter_flow/nav/nav.dart'; import 'package:hub/flutter_flow/nav/nav.dart';
@ -71,6 +70,8 @@ class _AboutPropertyPageState extends State<AboutPropertyPage>
final String title = FFLocalizations.of(context).getVariableText( final String title = FFLocalizations.of(context).getVariableText(
ptText: "Sobre a Propriedade", enText: "About the Property"); ptText: "Sobre a Propriedade", enText: "About the Property");
return AppBarUtil( return AppBarUtil(
key: UniqueKey(),
appBarKey: ValueKey<String>('BackNavigationAppBar'),
title: title, title: title,
onBackButtonPressed: () => context.pop(), onBackButtonPressed: () => context.pop(),
); );

View File

@ -33,6 +33,7 @@ class DatabaseService {
onOpen: _onOpen, onOpen: _onOpen,
onConfigure: _onConfigure, onConfigure: _onConfigure,
); );
print('Database initialized');
await LicenseRepositoryImpl().updateLicense(); await LicenseRepositoryImpl().updateLicense();
isInitialized = true; isInitialized = true;
} }

View File

@ -390,6 +390,7 @@ String formatNumber(
} }
DateTime get getCurrentTimestamp => DateTime.now(); DateTime get getCurrentTimestamp => DateTime.now();
DateTime dateTimeFromSecondsSinceEpoch(int seconds) { DateTime dateTimeFromSecondsSinceEpoch(int seconds) {
return DateTime.fromMillisecondsSinceEpoch(seconds * 1000); return DateTime.fromMillisecondsSinceEpoch(seconds * 1000);
} }
@ -400,8 +401,11 @@ extension DateTimeConversionExtension on DateTime {
extension DateTimeComparisonOperators on DateTime { extension DateTimeComparisonOperators on DateTime {
bool operator <(DateTime other) => isBefore(other); bool operator <(DateTime other) => isBefore(other);
bool operator >(DateTime other) => isAfter(other); bool operator >(DateTime other) => isAfter(other);
bool operator <=(DateTime other) => this < other || isAtSameMomentAs(other); bool operator <=(DateTime other) => this < other || isAtSameMomentAs(other);
bool operator >=(DateTime other) => this > other || isAtSameMomentAs(other); bool operator >=(DateTime other) => this > other || isAtSameMomentAs(other);
} }
@ -457,14 +461,18 @@ Rect? getWidgetBoundingBox(BuildContext context) {
} }
bool get isAndroid => !kIsWeb && Platform.isAndroid; bool get isAndroid => !kIsWeb && Platform.isAndroid;
bool get isiOS => !kIsWeb && Platform.isIOS; bool get isiOS => !kIsWeb && Platform.isIOS;
bool get isWeb => kIsWeb; bool get isWeb => kIsWeb;
const kBreakpointSmall = 479.0; const kBreakpointSmall = 479.0;
const kBreakpointMedium = 767.0; const kBreakpointMedium = 767.0;
const kBreakpointLarge = 991.0; const kBreakpointLarge = 991.0;
bool isMobileWidth(BuildContext context) => bool isMobileWidth(BuildContext context) =>
MediaQuery.sizeOf(context).width < kBreakpointSmall; MediaQuery.sizeOf(context).width < kBreakpointSmall;
bool responsiveVisibility({ bool responsiveVisibility({
required BuildContext context, required BuildContext context,
bool phone = true, bool phone = true,
@ -493,6 +501,7 @@ const kTextValidatorWebsiteRegex =
extension FFTextEditingControllerExt on TextEditingController? { extension FFTextEditingControllerExt on TextEditingController? {
String get text => this == null ? '' : this!.text; String get text => this == null ? '' : this!.text;
set text(String newText) => this?.text = newText; set text(String newText) => this?.text = newText;
} }
@ -574,6 +583,7 @@ void showAlertDialog(BuildContext context, String title, String content,
context: context, context: context,
builder: (context) { builder: (context) {
return AlertDialog( return AlertDialog(
key: ValueKey<String>('AlertDialogKey'),
backgroundColor: FlutterFlowTheme.of(context).primaryBackground, backgroundColor: FlutterFlowTheme.of(context).primaryBackground,
title: Text(title, title: Text(title,
style: TextStyle( style: TextStyle(
@ -593,6 +603,7 @@ void showAlertDialog(BuildContext context, String title, String content,
mainAxisSize: MainAxisSize.max, mainAxisSize: MainAxisSize.max,
children: [ children: [
FFButtonWidget( FFButtonWidget(
key: ValueKey<String>('RejectOptionKey'),
onPressed: () => context.pop(), //Navigator.pop(context), onPressed: () => context.pop(), //Navigator.pop(context),
options: FFButtonOptions( options: FFButtonOptions(
width: MediaQuery.of(context).size.width * 0.3, width: MediaQuery.of(context).size.width * 0.3,
@ -615,6 +626,7 @@ void showAlertDialog(BuildContext context, String title, String content,
), ),
), ),
FFButtonWidget( FFButtonWidget(
key: ValueKey<String>('AcceptOptionKey'),
onPressed: () async { onPressed: () async {
action(); action();
}, },
@ -707,6 +719,7 @@ extension StatefulWidgetExtensions on State<StatefulWidget> {
// For iOS 16 and below, set the status bar color to match the app's theme. // For iOS 16 and below, set the status bar color to match the app's theme.
// https://github.com/flutter/flutter/issues/41067 // https://github.com/flutter/flutter/issues/41067
Brightness? _lastBrightness; Brightness? _lastBrightness;
void fixStatusBarOniOS16AndBelow(BuildContext context) { void fixStatusBarOniOS16AndBelow(BuildContext context) {
if (!isiOS) { if (!isiOS) {
return; return;

View File

@ -15,20 +15,25 @@ class FFLocalizations {
static List<String> languages() => ['pt', 'en']; static List<String> languages() => ['pt', 'en'];
static late SharedPreferences _prefs; static late SharedPreferences _prefs;
static Future initialize() async => static Future initialize() async =>
_prefs = await SharedPreferences.getInstance(); _prefs = await SharedPreferences.getInstance();
static Future storeLocale(String locale) => static Future storeLocale(String locale) =>
_prefs.setString(_kLocaleStorageKey, locale); _prefs.setString(_kLocaleStorageKey, locale);
static Locale? getStoredLocale() { static Locale? getStoredLocale() {
final locale = _prefs.getString(_kLocaleStorageKey); final locale = _prefs.getString(_kLocaleStorageKey);
return locale != null && locale.isNotEmpty ? createLocale(locale) : null; return locale != null && locale.isNotEmpty ? createLocale(locale) : null;
} }
String get languageCode => locale.toString(); String get languageCode => locale.toString();
String? get languageShortCode => String? get languageShortCode =>
_languagesWithShortCode.contains(locale.toString()) _languagesWithShortCode.contains(locale.toString())
? '${locale.toString()}_short' ? '${locale.toString()}_short'
: null; : null;
int get languageIndex => languages().contains(languageCode) int get languageIndex => languages().contains(languageCode)
? languages().indexOf(languageCode) ? languages().indexOf(languageCode)
: 0; : 0;
@ -443,7 +448,7 @@ final kTranslationsMap = <Map<String, Map<String, String>>>[
}, },
'784f83pc': { '784f83pc': {
'pt': 'Consultar Liberações', 'pt': 'Consultar Liberações',
'en': 'Liberation History', 'en': 'Liberations History',
}, },
'1skj43ye': { '1skj43ye': {
'pt': 'Home', 'pt': 'Home',

View File

@ -126,7 +126,7 @@ GoRouter createRouter(AppStateNotifier appStateNotifier) {
) )
: const ReceptionPageWidget(); : const ReceptionPageWidget();
} else { } else {
return const WelcomePageWidget(); return const WelcomePage();
} }
}(), }(),
builder: (context, snapshot) { builder: (context, snapshot) {
@ -134,7 +134,7 @@ GoRouter createRouter(AppStateNotifier appStateNotifier) {
return const Center(child: CircularProgressIndicator()); return const Center(child: CircularProgressIndicator());
} else if (snapshot.hasError) { } else if (snapshot.hasError) {
DialogUtil.error(context, snapshot.error.toString()); DialogUtil.error(context, snapshot.error.toString());
return const WelcomePageWidget(); return const WelcomePage();
} else { } else {
return snapshot.data!; return snapshot.data!;
} }
@ -273,7 +273,7 @@ GoRouter createRouter(AppStateNotifier appStateNotifier) {
FFRoute( FFRoute(
name: 'welcomePage', name: 'welcomePage',
path: '/welcomePage', path: '/welcomePage',
builder: (context, params) => const WelcomePageWidget()), builder: (context, params) => const WelcomePage()),
FFRoute( FFRoute(
name: 'qrCodePage', name: 'qrCodePage',
path: '/qrCodePage', path: '/qrCodePage',

View File

@ -23,39 +23,58 @@ Future<void> initializeApp() async {
_initializeUrlStrategy(); _initializeUrlStrategy();
_initializeSystemSettings(); _initializeSystemSettings();
await _initializeFlutterFlow(); await _initializeFlutterFlow();
await _initializeNav();
} }
Future<void> _initializeTracking() async { Future<void> _initializeTracking() async {
print('Requesting tracking authorization...');
await AppTrackingTransparency.requestTrackingAuthorization(); await AppTrackingTransparency.requestTrackingAuthorization();
print('Tracking authorization requested');
} }
Future<void> _initializeFirebase() async { Future<void> _initializeFirebase() async {
print('Initializing Firebase...');
await Firebase.initializeApp(); await Firebase.initializeApp();
print('Firebase initialized');
} }
Future<void> _initializeNotificationService() async { Future<void> _initializeNotificationService() async {
print('Initializing Notification Service...');
await NotificationService.initialize(); await NotificationService.initialize();
print('Notification Service initialized');
} }
void _initializeUrlStrategy() { void _initializeUrlStrategy() {
print('Initializing URL Strategy...');
setUrlStrategy(PathUrlStrategy()); setUrlStrategy(PathUrlStrategy());
print('URL Strategy initialized');
} }
void _initializeSystemSettings() { void _initializeSystemSettings() {
print('Initializing System Settings...');
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
if (kDebugMode) { if (kDebugMode) {
log("Aplicativo em Debug Mode, crashlytics desabilitado!"); print('Debug mode');
} else { } else {
final crashlyticsInstance = FirebaseCrashlytics.instance; final crashlyticsInstance = FirebaseCrashlytics.instance;
print('Release mode');
if (crashlyticsInstance.isCrashlyticsCollectionEnabled) { if (crashlyticsInstance.isCrashlyticsCollectionEnabled) {
FlutterError.onError = crashlyticsInstance.recordFlutterError; FlutterError.onError = crashlyticsInstance.recordFlutterError;
print('Crashlytics enabled');
} }
} }
} }
Future<void> _initializeFlutterFlow() async { Future<void> _initializeFlutterFlow() async {
print('Initializing FlutterFlow...');
await FlutterFlowTheme.initialize(); await FlutterFlowTheme.initialize();
await FFLocalizations.initialize(); await FFLocalizations.initialize();
print('FlutterFlow initialized');
}
Future<void> _initializeNav() async {
print('Initializing Nav...');
GoRouter.optionURLReflectsImperativeAPIs = true; GoRouter.optionURLReflectsImperativeAPIs = true;
usePathUrlStrategy(); usePathUrlStrategy();
print('Nav initialized');
} }

View File

@ -8,14 +8,14 @@ import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:hub/features/notification/index.dart'; import 'package:hub/features/notification/index.dart';
import 'package:hub/features/storage/index.dart'; import 'package:hub/features/storage/index.dart';
import 'package:hub/flutter_flow/flutter_flow_theme.dart'; import 'package:hub/flutter_flow/flutter_flow_theme.dart';
import 'package:hub/flutter_flow/internationalization.dart'; import 'package:hub/flutter_flow/internationalization.dart';
import 'package:hub/flutter_flow/nav/nav.dart'; import 'package:hub/flutter_flow/nav/nav.dart';
import 'package:hub/shared/utils/test_util.dart';
import 'package:responsive_framework/responsive_framework.dart'; import 'package:responsive_framework/responsive_framework.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'initialization.dart'; import 'initialization.dart';
@ -175,11 +175,13 @@ class _AppState extends State<App> {
_router = createRouter(_appStateNotifier); _router = createRouter(_appStateNotifier);
Future.delayed( Future.delayed(
const Duration(milliseconds: 1000), const Duration(milliseconds: 1000),
() => setState(() => _appStateNotifier.stopShowingSplashImage()), () => mounted
? setState(() => _appStateNotifier.stopShowingSplashImage())
: null,
); );
_setupFirebaseMessaging(); _setupFirebaseMessaging();
DeepLinkService().ensureInitialization(); if (TestUtil.isInTest) DeepLinkService().ensureInitialization();
} }
@override @override

View File

@ -36,6 +36,7 @@ class _DeliveryScheduleState extends State<DeliverySchedule> {
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
forceMaterialTransparency: true, forceMaterialTransparency: true,
leading: FlutterFlowIconButton( leading: FlutterFlowIconButton(
key: ValueKey<String>('BackNavigationAppBar'),
borderColor: Colors.transparent, borderColor: Colors.transparent,
borderRadius: 30.0, borderRadius: 30.0,
borderWidth: 1.0, borderWidth: 1.0,

View File

@ -13,7 +13,6 @@ import 'package:hub/shared/utils/dialog_util.dart';
import 'package:hub/shared/utils/limited_text_size.dart'; import 'package:hub/shared/utils/limited_text_size.dart';
import 'package:hub/shared/utils/log_util.dart'; import 'package:hub/shared/utils/log_util.dart';
import 'package:hub/shared/utils/snackbar_util.dart'; import 'package:hub/shared/utils/snackbar_util.dart';
import 'package:hub/shared/utils/validator_util.dart'; import 'package:hub/shared/utils/validator_util.dart';
class LiberationHistoryWidget extends StatefulWidget { class LiberationHistoryWidget extends StatefulWidget {
@ -104,6 +103,7 @@ class _LiberationHistoryWidgetState extends State<LiberationHistoryWidget> {
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
forceMaterialTransparency: true, forceMaterialTransparency: true,
leading: FlutterFlowIconButton( leading: FlutterFlowIconButton(
key: ValueKey<String>('BackNavigationAppBar'),
borderColor: Colors.transparent, borderColor: Colors.transparent,
borderRadius: 30.0, borderRadius: 30.0,
borderWidth: 1.0, borderWidth: 1.0,
@ -332,13 +332,13 @@ class _LiberationHistoryWidgetState extends State<LiberationHistoryWidget> {
Future<ApiCallResponse?> _fetchRequests() async { Future<ApiCallResponse?> _fetchRequests() async {
try { try {
setState(() => _loading = true); safeSetState(() => _loading = true);
var response = await PhpGroup.getLiberationsCall.call().first; var response = await PhpGroup.getLiberationsCall.call().first;
final List<dynamic> requests = response.jsonBody['solicitacoes'] ?? []; final List<dynamic> requests = response.jsonBody['solicitacoes'] ?? [];
if (requests.isNotEmpty) { if (requests.isNotEmpty) {
setState(() { safeSetState(() {
_requestWrap.addAll(requests); _requestWrap.addAll(requests);
_hasData = true; _hasData = true;
_loading = false; _loading = false;
@ -349,7 +349,7 @@ class _LiberationHistoryWidgetState extends State<LiberationHistoryWidget> {
_showNoMoreDataSnackBar(context); _showNoMoreDataSnackBar(context);
setState(() { safeSetState(() {
_hasData = false; _hasData = false;
_loading = false; _loading = false;
}); });
@ -359,7 +359,7 @@ class _LiberationHistoryWidgetState extends State<LiberationHistoryWidget> {
await DialogUtil.errorDefault(context); await DialogUtil.errorDefault(context);
LogUtil.requestAPIFailed( LogUtil.requestAPIFailed(
"proccessRequest.php", "", "Consulta de Solicitações", e, s); "proccessRequest.php", "", "Consulta de Solicitações", e, s);
setState(() { safeSetState(() {
_hasData = false; _hasData = false;
_loading = false; _loading = false;
}); });

View File

@ -146,6 +146,7 @@ class _MessageHistoryPageWidgetState extends State<MessageHistoryPageWidget>
backgroundColor: FlutterFlowTheme.of(context).primaryBackground, backgroundColor: FlutterFlowTheme.of(context).primaryBackground,
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
leading: FlutterFlowIconButton( leading: FlutterFlowIconButton(
key: ValueKey<String>('BackNavigationAppBar'),
borderColor: Colors.transparent, borderColor: Colors.transparent,
borderRadius: 30.0, borderRadius: 30.0,
borderWidth: 1.0, borderWidth: 1.0,

View File

@ -10,11 +10,9 @@ import 'package:hub/features/storage/index.dart';
import 'package:hub/flutter_flow/flutter_flow_icon_button.dart'; import 'package:hub/flutter_flow/flutter_flow_icon_button.dart';
import 'package:hub/flutter_flow/flutter_flow_theme.dart'; import 'package:hub/flutter_flow/flutter_flow_theme.dart';
import 'package:hub/flutter_flow/flutter_flow_util.dart'; import 'package:hub/flutter_flow/flutter_flow_util.dart';
import 'package:hub/shared/utils/dialog_util.dart'; import 'package:hub/shared/utils/dialog_util.dart';
import 'package:hub/shared/utils/limited_text_size.dart'; import 'package:hub/shared/utils/limited_text_size.dart';
import 'package:hub/shared/utils/log_util.dart'; import 'package:hub/shared/utils/log_util.dart';
import 'package:hub/shared/utils/validator_util.dart'; import 'package:hub/shared/utils/validator_util.dart';
import 'package:rxdart/rxdart.dart'; import 'package:rxdart/rxdart.dart';
@ -145,6 +143,7 @@ class _PackageOrderPage extends State<PackageOrderPage> {
Widget _backButton(BuildContext context, FlutterFlowTheme theme) { Widget _backButton(BuildContext context, FlutterFlowTheme theme) {
return FlutterFlowIconButton( return FlutterFlowIconButton(
key: ValueKey<String>('BackNavigationAppBar'),
borderColor: Colors.transparent, borderColor: Colors.transparent,
borderRadius: 30.0, borderRadius: 30.0,
borderWidth: 1.0, borderWidth: 1.0,

View File

@ -47,6 +47,7 @@ class _PeopleOnThePropertyPageState extends State<PeopleOnThePropertyPage> {
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
forceMaterialTransparency: true, forceMaterialTransparency: true,
leading: FlutterFlowIconButton( leading: FlutterFlowIconButton(
key: ValueKey<String>('BackNavigationAppBar'),
borderColor: Colors.transparent, borderColor: Colors.transparent,
borderRadius: 30.0, borderRadius: 30.0,
borderWidth: 1.0, borderWidth: 1.0,

View File

@ -1,15 +1,12 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart'; import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart';
import 'package:hub/features/backend/index.dart'; import 'package:hub/features/backend/index.dart';
import 'package:hub/features/storage/index.dart'; import 'package:hub/features/storage/index.dart';
import 'package:hub/flutter_flow/flutter_flow_icon_button.dart'; import 'package:hub/flutter_flow/flutter_flow_icon_button.dart';
import 'package:hub/flutter_flow/flutter_flow_theme.dart'; import 'package:hub/flutter_flow/flutter_flow_theme.dart';
import 'package:hub/flutter_flow/flutter_flow_util.dart'; import 'package:hub/flutter_flow/flutter_flow_util.dart';
import 'package:hub/pages/pets_page/pets_page_model.dart'; import 'package:hub/pages/pets_page/pets_page_model.dart';
import 'package:hub/shared/utils/dialog_util.dart'; import 'package:hub/shared/utils/dialog_util.dart';
import 'package:hub/shared/utils/limited_text_size.dart'; import 'package:hub/shared/utils/limited_text_size.dart';
import 'package:hub/shared/utils/log_util.dart'; import 'package:hub/shared/utils/log_util.dart';
@ -85,6 +82,7 @@ class _PetsHistoryScreenState extends State<PetsHistoryScreen>
Widget _backButton(BuildContext context, FlutterFlowTheme theme) { Widget _backButton(BuildContext context, FlutterFlowTheme theme) {
return FlutterFlowIconButton( return FlutterFlowIconButton(
key: ValueKey<String>('BackNavigationAppBar'),
borderColor: Colors.transparent, borderColor: Colors.transparent,
borderRadius: 30.0, borderRadius: 30.0,
borderWidth: 1.0, borderWidth: 1.0,

View File

@ -1,5 +1,4 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:developer';
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -13,7 +12,6 @@ import 'package:hub/flutter_flow/flutter_flow_widgets.dart';
import 'package:hub/flutter_flow/form_field_controller.dart'; import 'package:hub/flutter_flow/form_field_controller.dart';
import 'package:hub/flutter_flow/nav/nav.dart'; import 'package:hub/flutter_flow/nav/nav.dart';
import 'package:hub/pages/pets_page/pets_page_widget.dart'; import 'package:hub/pages/pets_page/pets_page_widget.dart';
import 'package:hub/shared/utils/dialog_util.dart'; import 'package:hub/shared/utils/dialog_util.dart';
import 'package:hub/shared/utils/image_util.dart'; import 'package:hub/shared/utils/image_util.dart';
import 'package:hub/shared/utils/limited_text_size.dart'; import 'package:hub/shared/utils/limited_text_size.dart';
@ -110,7 +108,8 @@ class PetsPageModel extends FlutterFlowModel<PetsPageWidget> {
String? Function(BuildContext, String?)? textControllerObservationValidator; String? Function(BuildContext, String?)? textControllerObservationValidator;
Future<void> initAsync() async { Future<void> initAsync() async {
defaultDropDownText = FFLocalizations.of(buildContext!).getVariableText( defaultDropDownText =
FFLocalizations.of(navigatorKey.currentContext!).getVariableText(
enText: 'Select an option', enText: 'Select an option',
ptText: 'Selecione uma opção', ptText: 'Selecione uma opção',
); );

View File

@ -76,6 +76,8 @@ class _PetsPageWidgetState extends State<PetsPageWidget>
PreferredSizeWidget _buildAppBar(BuildContext context) { PreferredSizeWidget _buildAppBar(BuildContext context) {
return AppBarUtil( return AppBarUtil(
key: UniqueKey(),
appBarKey: ValueKey<String>('BackNavigationAppBar'),
title: FFLocalizations.of(context).getVariableText( title: FFLocalizations.of(context).getVariableText(
ptText: 'Cadastrar Pets', ptText: 'Cadastrar Pets',
enText: 'Pets Register', enText: 'Pets Register',

View File

@ -1,15 +1,13 @@
import 'dart:async'; import 'dart:async';
import 'dart:isolate';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hub/components/templates_components/change_passs_qr_code_pass_key_template_component/change_pass_widget.dart'; import 'package:hub/components/templates_components/change_passs_qr_code_pass_key_template_component/change_pass_widget.dart';
import 'package:hub/features/auth/index.dart'; import 'package:hub/features/auth/index.dart';
import 'package:hub/features/backend/index.dart'; import 'package:hub/features/backend/index.dart';
import 'package:hub/features/local/index.dart';
import 'package:hub/features/storage/index.dart'; import 'package:hub/features/storage/index.dart';
import 'package:hub/flutter_flow/flutter_flow_util.dart'; import 'package:hub/flutter_flow/flutter_flow_util.dart';
import 'package:hub/flutter_flow/nav/nav.dart'; import 'package:hub/flutter_flow/nav/nav.dart';
import 'package:hub/features/local/index.dart';
import 'package:hub/shared/utils/path_util.dart'; import 'package:hub/shared/utils/path_util.dart';
import 'package:share_plus/share_plus.dart'; import 'package:share_plus/share_plus.dart';

View File

@ -1,15 +1,12 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'package:hub/features/local/data/index.dart';
import 'package:hub/flutter_flow/flutter_flow_icon_button.dart'; import 'package:hub/flutter_flow/flutter_flow_icon_button.dart';
import 'package:hub/flutter_flow/flutter_flow_theme.dart'; import 'package:hub/flutter_flow/flutter_flow_theme.dart';
import 'package:hub/flutter_flow/flutter_flow_util.dart'; import 'package:hub/flutter_flow/flutter_flow_util.dart';
import 'package:hub/flutter_flow/nav/nav.dart'; import 'package:hub/flutter_flow/nav/nav.dart';
import 'package:hub/pages/preferences_settings_page/preferences_settings_model.dart'; import 'package:hub/pages/preferences_settings_page/preferences_settings_model.dart';
import 'package:hub/shared/utils/limited_text_size.dart'; import 'package:hub/shared/utils/limited_text_size.dart';
import 'package:material_symbols_icons/symbols.dart'; import 'package:material_symbols_icons/symbols.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class PreferencesPageWidget extends StatefulWidget { class PreferencesPageWidget extends StatefulWidget {
@ -41,6 +38,7 @@ class _PreferencesPageWidgetState extends State<PreferencesPageWidget> {
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
forceMaterialTransparency: true, forceMaterialTransparency: true,
leading: FlutterFlowIconButton( leading: FlutterFlowIconButton(
key: ValueKey<String>('BackNavigationAppBar'),
borderColor: Colors.transparent, borderColor: Colors.transparent,
borderRadius: 30.0, borderRadius: 30.0,
borderWidth: 1.0, borderWidth: 1.0,

View File

@ -36,6 +36,7 @@ class _ProvisionalScheduleState extends State<ProvisionalSchedule> {
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
forceMaterialTransparency: true, forceMaterialTransparency: true,
leading: FlutterFlowIconButton( leading: FlutterFlowIconButton(
key: ValueKey<String>('BackNavigationAppBar'),
borderColor: Colors.transparent, borderColor: Colors.transparent,
borderRadius: 30.0, borderRadius: 30.0,
borderWidth: 1.0, borderWidth: 1.0,

View File

@ -18,12 +18,9 @@ import 'package:hub/flutter_flow/flutter_flow_util.dart';
import 'package:hub/flutter_flow/flutter_flow_widgets.dart'; import 'package:hub/flutter_flow/flutter_flow_widgets.dart';
import 'package:hub/flutter_flow/nav/nav.dart'; import 'package:hub/flutter_flow/nav/nav.dart';
import 'package:hub/pages/qr_code_page/qr_code_page_model.dart'; import 'package:hub/pages/qr_code_page/qr_code_page_model.dart';
import 'package:hub/shared/utils/biometric_util.dart'; import 'package:hub/shared/utils/biometric_util.dart';
import 'package:hub/shared/utils/limited_text_size.dart'; import 'package:hub/shared/utils/limited_text_size.dart';
import 'package:percent_indicator/circular_percent_indicator.dart'; import 'package:percent_indicator/circular_percent_indicator.dart';
import 'package:qr_flutter/qr_flutter.dart'; import 'package:qr_flutter/qr_flutter.dart';
class QrCodePageWidget extends StatefulWidget { class QrCodePageWidget extends StatefulWidget {
@ -475,6 +472,7 @@ class _QrCodePageWidgetState extends State<QrCodePageWidget>
AppBar buildAppBar(BuildContext context) { AppBar buildAppBar(BuildContext context) {
return AppBar( return AppBar(
key: ValueKey<String>('BackNavigationAppBar'),
backgroundColor: FlutterFlowTheme.of(context).primaryBackground, backgroundColor: FlutterFlowTheme.of(context).primaryBackground,
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
leading: FlutterFlowIconButton( leading: FlutterFlowIconButton(
@ -492,7 +490,10 @@ class _QrCodePageWidgetState extends State<QrCodePageWidget>
}, },
), ),
title: Text( title: Text(
FFLocalizations.of(context).getText('ku7jqe53'), FFLocalizations.of(context).getVariableText(
ptText: 'QRCode de Acesso',
enText: 'Access QRCode',
),
style: FlutterFlowTheme.of(context).headlineMedium.override( style: FlutterFlowTheme.of(context).headlineMedium.override(
fontFamily: FlutterFlowTheme.of(context).headlineMediumFamily, fontFamily: FlutterFlowTheme.of(context).headlineMediumFamily,
color: FlutterFlowTheme.of(context).primaryText, color: FlutterFlowTheme.of(context).primaryText,

View File

@ -43,6 +43,7 @@ class _RegisterVisitorPageWidgetState extends State<RegisterVisitorPageWidget> {
backgroundColor: FlutterFlowTheme.of(context).primaryBackground, backgroundColor: FlutterFlowTheme.of(context).primaryBackground,
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
leading: FlutterFlowIconButton( leading: FlutterFlowIconButton(
key: ValueKey<String>('BackNavigationAppBar'),
borderColor: Colors.transparent, borderColor: Colors.transparent,
borderRadius: 30.0, borderRadius: 30.0,
borderWidth: 1.0, borderWidth: 1.0,
@ -57,8 +58,9 @@ class _RegisterVisitorPageWidgetState extends State<RegisterVisitorPageWidget> {
}, },
), ),
title: Text( title: Text(
FFLocalizations.of(context).getText( FFLocalizations.of(context).getVariableText(
'megskb6s' /* Cadastrar Visitante */, ptText: 'Cadastrar Visitantes',
enText: 'Register Visitors',
), ),
style: FlutterFlowTheme.of(context).headlineMedium.override( style: FlutterFlowTheme.of(context).headlineMedium.override(
fontFamily: FlutterFlowTheme.of(context).headlineMediumFamily, fontFamily: FlutterFlowTheme.of(context).headlineMediumFamily,

View File

@ -157,6 +157,7 @@ class _ResidentsOnThePropertyState extends State<ResidentsOnTheProperty>
Widget _backButton(BuildContext context, FlutterFlowTheme theme) { Widget _backButton(BuildContext context, FlutterFlowTheme theme) {
return FlutterFlowIconButton( return FlutterFlowIconButton(
key: ValueKey<String>('BackNavigationAppBar'),
borderColor: Colors.transparent, borderColor: Colors.transparent,
borderRadius: 30.0, borderRadius: 30.0,
borderWidth: 1.0, borderWidth: 1.0,

View File

@ -126,6 +126,7 @@ class _ScheduleCompleteVisitPageWidgetState
forceMaterialTransparency: true, forceMaterialTransparency: true,
elevation: 0.0, elevation: 0.0,
leading: FlutterFlowIconButton( leading: FlutterFlowIconButton(
key: ValueKey<String>('BackNavigationAppBar'),
borderColor: Colors.transparent, borderColor: Colors.transparent,
borderRadius: 30.0, borderRadius: 30.0,
borderWidth: 1.0, borderWidth: 1.0,

View File

@ -152,6 +152,7 @@ class _VehicleOnThePropertyState extends State<VehicleOnTheProperty>
Widget _backButton(BuildContext context, FlutterFlowTheme theme) { Widget _backButton(BuildContext context, FlutterFlowTheme theme) {
return FlutterFlowIconButton( return FlutterFlowIconButton(
key: ValueKey<String>('BackNavigationAppBar'),
borderColor: Colors.transparent, borderColor: Colors.transparent,
borderRadius: 30.0, borderRadius: 30.0,
borderWidth: 1.0, borderWidth: 1.0,

View File

@ -7,8 +7,8 @@ import 'package:hub/flutter_flow/flutter_flow_theme.dart';
import 'package:hub/flutter_flow/flutter_flow_util.dart'; import 'package:hub/flutter_flow/flutter_flow_util.dart';
import 'package:hub/pages/visits_on_the_property/model.dart'; import 'package:hub/pages/visits_on_the_property/model.dart';
import 'package:hub/shared/utils/dialog_util.dart'; import 'package:hub/shared/utils/dialog_util.dart';
import 'package:hub/shared/utils/log_util.dart';
import 'package:hub/shared/utils/limited_text_size.dart'; import 'package:hub/shared/utils/limited_text_size.dart';
import 'package:hub/shared/utils/log_util.dart';
class VisitsOnTheProperty extends StatefulWidget { class VisitsOnTheProperty extends StatefulWidget {
const VisitsOnTheProperty({super.key}); const VisitsOnTheProperty({super.key});
@ -135,7 +135,9 @@ class _VisitsOnThePropertyState extends State<VisitsOnTheProperty>
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
title: Text( title: Text(
FFLocalizations.of(context).getVariableText( FFLocalizations.of(context).getVariableText(
ptText: 'Visitas em aberto', enText: 'Opened visits'), ptText: 'Visitas Abertas',
enText: 'Opened Visits',
),
style: FlutterFlowTheme.of(context).headlineMedium.override( style: FlutterFlowTheme.of(context).headlineMedium.override(
fontFamily: FlutterFlowTheme.of(context).headlineMediumFamily, fontFamily: FlutterFlowTheme.of(context).headlineMediumFamily,
color: FlutterFlowTheme.of(context).primaryText, color: FlutterFlowTheme.of(context).primaryText,
@ -155,6 +157,7 @@ class _VisitsOnThePropertyState extends State<VisitsOnTheProperty>
Widget _backButton(BuildContext context, FlutterFlowTheme theme) { Widget _backButton(BuildContext context, FlutterFlowTheme theme) {
return FlutterFlowIconButton( return FlutterFlowIconButton(
key: ValueKey<String>('BackNavigationAppBar'),
borderColor: Colors.transparent, borderColor: Colors.transparent,
borderRadius: 30.0, borderRadius: 30.0,
borderWidth: 1.0, borderWidth: 1.0,

View File

@ -1,9 +1,9 @@
import '/components/templates_components/welcome_template_component/welcome_template_component_widget.dart'; import '/components/templates_components/welcome_template_component/welcome_template_component_widget.dart';
import '/flutter_flow/flutter_flow_util.dart'; import '/flutter_flow/flutter_flow_util.dart';
import 'welcome_page_widget.dart' show WelcomePageWidget; import 'welcome_page_widget.dart' show WelcomePage;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class WelcomePageModel extends FlutterFlowModel<WelcomePageWidget> { class WelcomePageModel extends FlutterFlowModel<WelcomePage> {
/// Local state fields for this page. /// Local state fields for this page.
String toggleIdx = 'welcome'; String toggleIdx = 'welcome';

View File

@ -11,14 +11,14 @@ import 'welcome_page_model.dart';
export 'welcome_page_model.dart'; export 'welcome_page_model.dart';
class WelcomePageWidget extends StatefulWidget with Switcher { class WelcomePage extends StatefulWidget with Switcher {
const WelcomePageWidget({super.key}); const WelcomePage({super.key});
@override @override
State<WelcomePageWidget> createState() => _WelcomePageWidgetState(); State<WelcomePage> createState() => _WelcomePageState();
} }
class _WelcomePageWidgetState extends State<WelcomePageWidget> { class _WelcomePageState extends State<WelcomePage> {
late WelcomePageModel _model; late WelcomePageModel _model;
final scaffoldKey = GlobalKey<ScaffoldState>(); final scaffoldKey = GlobalKey<ScaffoldState>();

View File

@ -8,6 +8,7 @@ export 'log_util.dart';
export 'path_util.dart'; export 'path_util.dart';
export 'share_util.dart'; export 'share_util.dart';
export 'snackbar_util.dart'; export 'snackbar_util.dart';
export 'string_util.dart';
export 'text_util.dart'; export 'text_util.dart';
export 'validator_util.dart'; export 'validator_util.dart';
export 'webview_util.dart'; export 'webview_util.dart';

View File

@ -0,0 +1,7 @@
import 'dart:io';
class TestUtil {
static bool get isInTest {
return Platform.environment.containsKey('FLUTTER_TEST');
}
}

View File

@ -34,10 +34,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: app_links name: app_links
sha256: ad1a6d598e7e39b46a34f746f9a8b011ee147e4c275d407fa457e7a62f84dd99 sha256: "433df2e61b10519407475d7f69e470789d23d593f28224c38ba1068597be7950"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.3.2" version: "6.3.3"
app_links_linux: app_links_linux:
dependency: transitive dependency: transitive
description: description:
@ -66,18 +66,18 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: app_tracking_transparency name: app_tracking_transparency
sha256: "64d9745931e565790abdea91b518ac8dc3cebe6d0d0aaf7119343271b983259a" sha256: "1f71f4d8402552fbf8b191d4edab301f233c1af794878b7bc56c708470ffd74c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.6" version: "2.0.6+1"
archive: archive:
dependency: transitive dependency: transitive
description: description:
name: archive name: archive
sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d sha256: "6199c74e3db4fbfbd04f66d739e72fe11c8a8957d5f219f1f4482dbde6420b5a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.6.1" version: "4.0.2"
args: args:
dependency: transitive dependency: transitive
description: description:
@ -130,10 +130,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: bloc name: bloc
sha256: "106842ad6569f0b60297619e9e0b1885c2fb9bf84812935490e6c5275777804e" sha256: "52c10575f4445c61dd9e0cafcc6356fdd827c4c64dd7945ef3c4105f6b6ac189"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "8.1.4" version: "9.0.0"
boolean_selector: boolean_selector:
dependency: transitive dependency: transitive
description: description:
@ -146,50 +146,50 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: build name: build
sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" sha256: cef23f1eda9b57566c81e2133d196f8e3df48f244b317368d65c5943d91148f0
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.1" version: "2.4.2"
build_config: build_config:
dependency: transitive dependency: transitive
description: description:
name: build_config name: build_config
sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 sha256: "4ae2de3e1e67ea270081eaee972e1bd8f027d459f249e0f1186730784c2e7e33"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.1" version: "1.1.2"
build_daemon: build_daemon:
dependency: transitive dependency: transitive
description: description:
name: build_daemon name: build_daemon
sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9" sha256: "294a2edaf4814a378725bfe6358210196f5ea37af89ecd81bfa32960113d4948"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.0.2" version: "4.0.3"
build_resolvers: build_resolvers:
dependency: transitive dependency: transitive
description: description:
name: build_resolvers name: build_resolvers
sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" sha256: "99d3980049739a985cf9b21f30881f46db3ebc62c5b8d5e60e27440876b1ba1e"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.2" version: "2.4.3"
build_runner: build_runner:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: build_runner name: build_runner
sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d" sha256: "74691599a5bc750dc96a6b4bfd48f7d9d66453eab04c7f4063134800d6a5c573"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.13" version: "2.4.14"
build_runner_core: build_runner_core:
dependency: transitive dependency: transitive
description: description:
name: build_runner_core name: build_runner_core
sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0 sha256: "22e3aa1c80e0ada3722fe5b63fd43d9c8990759d0a2cf489c8c5d7b2bdebc021"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "7.3.2" version: "8.0.0"
built_collection: built_collection:
dependency: transitive dependency: transitive
description: description:
@ -202,10 +202,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: built_value name: built_value
sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb sha256: "28a712df2576b63c6c005c465989a348604960c0958d28be5303ba9baa841ac2"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "8.9.2" version: "8.9.3"
cached_network_image: cached_network_image:
dependency: "direct main" dependency: "direct main"
description: description:
@ -286,6 +286,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.2" version: "3.1.2"
coverage:
dependency: transitive
description:
name: coverage
sha256: e3493833ea012784c740e341952298f1cc77f1f01b1bbc3eb4eecf6984fb7f43
url: "https://pub.dev"
source: hosted
version: "1.11.1"
cross_file: cross_file:
dependency: transitive dependency: transitive
description: description:
@ -338,10 +346,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: device_info_plus_platform_interface name: device_info_plus_platform_interface
sha256: "282d3cf731045a2feb66abfe61bbc40870ae50a3ed10a4d3d217556c35c8c2ba" sha256: "0b04e02b30791224b31969eb1b50d723498f402971bff3630bca2ba839bd1ed2"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "7.0.1" version: "7.0.2"
dispose_scope:
dependency: transitive
description:
name: dispose_scope
sha256: "48ec38ca2631c53c4f8fa96b294c801e55c335db5e3fb9f82cede150cfe5a2af"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
dropdown_button2: dropdown_button2:
dependency: "direct main" dependency: "direct main"
description: description:
@ -466,10 +482,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: firebase_core_platform_interface name: firebase_core_platform_interface
sha256: b94b217e3ad745e784960603d33d99471621ecca151c99c670869b76e50ad2a6 sha256: d7253d255ff10f85cfd2adaba9ac17bae878fa3ba577462451163bd9f1d1f0bf
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.3.1" version: "5.4.0"
firebase_core_web: firebase_core_web:
dependency: transitive dependency: transitive
description: description:
@ -543,10 +559,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_bloc name: flutter_bloc
sha256: b594505eac31a0518bdcb4b5b79573b8d9117b193cc80cc12e17d639b10aa27a sha256: "153856bdaac302bbdc58a1d1403d50c40557254aa05eaeed40515d88a25a526b"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "8.1.6" version: "9.0.0"
flutter_cache_manager: flutter_cache_manager:
dependency: transitive dependency: transitive
description: description:
@ -641,10 +657,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: flutter_plugin_android_lifecycle name: flutter_plugin_android_lifecycle
sha256: "9b78450b89f059e96c9ebb355fa6b3df1d6b330436e0b885fb49594c41721398" sha256: "615a505aef59b151b46bbeef55b36ce2b6ed299d160c51d84281946f0aa0ce0e"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.23" version: "2.0.24"
flutter_riverpod: flutter_riverpod:
dependency: "direct main" dependency: "direct main"
description: description:
@ -657,50 +673,58 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_secure_storage name: flutter_secure_storage
sha256: "165164745e6afb5c0e3e3fcc72a012fb9e58496fb26ffb92cf22e16a821e85d0" sha256: f7eceb0bc6f4fd0441e29d43cab9ac2a1c5ffd7ea7b64075136b718c46954874
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "9.2.2" version: "10.0.0-beta.4"
flutter_secure_storage_darwin:
dependency: transitive
description:
name: flutter_secure_storage_darwin
sha256: f226f2a572bed96bc6542198ebaec227150786e34311d455a7e2d3d06d951845
url: "https://pub.dev"
source: hosted
version: "0.1.0"
flutter_secure_storage_linux: flutter_secure_storage_linux:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_secure_storage_linux name: flutter_secure_storage_linux
sha256: "4d91bfc23047422cbcd73ac684bc169859ee766482517c22172c86596bf1464b" sha256: "9b4b73127e857cd3117d43a70fa3dddadb6e0b253be62e6a6ab85caa0742182c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.1" version: "2.0.1"
flutter_secure_storage_macos: flutter_secure_storage_macos:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_secure_storage_macos name: flutter_secure_storage_macos
sha256: "1693ab11121a5f925bbea0be725abfcfbbcf36c1e29e571f84a0c0f436147a81" sha256: "75894eb6b402ac7f7f5ee5487d651b87855a338e26eb6993f4b2fce33013a615"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.2" version: "4.0.0"
flutter_secure_storage_platform_interface: flutter_secure_storage_platform_interface:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_secure_storage_platform_interface name: flutter_secure_storage_platform_interface
sha256: cf91ad32ce5adef6fba4d736a542baca9daf3beac4db2d04be350b87f69ac4a8 sha256: "8ceea1223bee3c6ac1a22dabd8feefc550e4729b3675de4b5900f55afcb435d6"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.2" version: "2.0.1"
flutter_secure_storage_web: flutter_secure_storage_web:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_secure_storage_web name: flutter_secure_storage_web
sha256: f4ebff989b4f07b2656fb16b47852c0aab9fed9b4ec1c70103368337bc1886a9 sha256: "4c3f233e739545c6cb09286eeec1cc4744138372b985113acc904f7263bef517"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.1" version: "2.0.0"
flutter_secure_storage_windows: flutter_secure_storage_windows:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_secure_storage_windows name: flutter_secure_storage_windows
sha256: b20b07cb5ed4ed74fc567b78a72936203f587eba460af1df11281c9326cd3709 sha256: ff32af20f70a8d0e59b2938fc92de35b54a74671041c814275afd80e27df9f21
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.2" version: "4.0.0"
flutter_shaders: flutter_shaders:
dependency: transitive dependency: transitive
description: description:
@ -729,10 +753,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_svg name: flutter_svg
sha256: "54900a1a1243f3c4a5506d853a2b5c2dbc38d5f27e52a52618a8054401431123" sha256: c200fd79c918a40c5cd50ea0877fa13f81bdaf6f0a5d3dbcc2a13e3285d6aa1b
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.16" version: "2.0.17"
flutter_test: flutter_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter
@ -808,10 +832,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: go_router name: go_router
sha256: "2fd11229f59e23e967b0775df8d5948a519cd7e1e8b6e849729e010587b46539" sha256: "7c2d40b59890a929824f30d442e810116caf5088482629c894b9e4478c67472d"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "14.6.2" version: "14.6.3"
google_fonts: google_fonts:
dependency: "direct main" dependency: "direct main"
description: description:
@ -864,26 +888,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: http_multi_server name: http_multi_server
sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.2.1" version: "3.2.2"
http_parser: http_parser:
dependency: transitive dependency: transitive
description: description:
name: http_parser name: http_parser
sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.0.2" version: "4.1.2"
image: image:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: image name: image
sha256: f31d52537dc417fdcde36088fdf11d191026fd5e4fae742491ebd40e5a8bea7d sha256: "8346ad4b5173924b5ddddab782fc7d8a6300178c8b1dc427775405a01701c4a6"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.3.0" version: "4.5.2"
image_picker: image_picker:
dependency: "direct main" dependency: "direct main"
description: description:
@ -896,10 +920,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: image_picker_android name: image_picker_android
sha256: fa8141602fde3f7e2f81dbf043613eb44dfa325fa0bcf93c0f142c9f7a2c193e sha256: b62d34a506e12bb965e824b6db4fbf709ee4589cf5d3e99b45ab2287b008ee0c
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.8.12+18" version: "0.8.12+20"
image_picker_for_web: image_picker_for_web:
dependency: "direct main" dependency: "direct main"
description: description:
@ -912,10 +936,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: image_picker_ios name: image_picker_ios
sha256: "4f0568120c6fcc0aaa04511cb9f9f4d29fc3d0139884b1d06be88dcec7641d6b" sha256: "05da758e67bc7839e886b3959848aa6b44ff123ab4b28f67891008afe8ef9100"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.8.12+1" version: "0.8.12+2"
image_picker_linux: image_picker_linux:
dependency: transitive dependency: transitive
description: description:
@ -936,10 +960,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: image_picker_platform_interface name: image_picker_platform_interface
sha256: "9ec26d410ff46f483c5519c29c02ef0e02e13a543f882b152d4bfd2f06802f80" sha256: "886d57f0be73c4b140004e78b9f28a8914a09e50c2d816bdd0520051a71236a0"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.10.0" version: "2.10.1"
image_picker_windows: image_picker_windows:
dependency: transitive dependency: transitive
description: description:
@ -1037,10 +1061,10 @@ packages:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: lints name: lints
sha256: "3315600f3fb3b135be672bf4a178c55f274bebe368325ae18462c89ac1e3b413" sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.0.0" version: "5.1.1"
local_auth: local_auth:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1061,10 +1085,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: local_auth_darwin name: local_auth_darwin
sha256: "6d2950da311d26d492a89aeb247c72b4653ddc93601ea36a84924a396806d49c" sha256: "5c5127061107278ab4cafa1ac51b3b6760282bf1a2abf011270908a429d1634b"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.4.1" version: "1.4.2"
local_auth_platform_interface: local_auth_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -1117,10 +1141,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: material_symbols_icons name: material_symbols_icons
sha256: "64404f47f8e0a9d20478468e5decef867a688660bad7173adcd20418d7f892c9" sha256: "89aac72d25dd49303f71b3b1e70f8374791846729365b25bebc2a2531e5b86cd"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.2801.0" version: "4.2801.1"
maybe_just_nothing: maybe_just_nothing:
dependency: transitive dependency: transitive
description: description:
@ -1157,10 +1181,10 @@ packages:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: mockito name: mockito
sha256: "6841eed20a7befac0ce07df8116c8b8233ed1f4486a7647c7fc5a02ae6163917" sha256: f99d8d072e249f719a5531735d146d8cf04c580d93920b04de75bef6dfb2daf6
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.4.4" version: "5.4.5"
nested: nested:
dependency: transitive dependency: transitive
description: description:
@ -1169,6 +1193,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.0" version: "1.0.0"
node_preamble:
dependency: transitive
description:
name: node_preamble
sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db"
url: "https://pub.dev"
source: hosted
version: "2.0.2"
octo_image: octo_image:
dependency: transitive dependency: transitive
description: description:
@ -1189,26 +1221,26 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: package_info_plus name: package_info_plus
sha256: da8d9ac8c4b1df253d1a328b7bf01ae77ef132833479ab40763334db13b91cce sha256: "739e0a5c3c4055152520fa321d0645ee98e932718b4c8efeeb51451968fe0790"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "8.1.1" version: "8.1.3"
package_info_plus_platform_interface: package_info_plus_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: package_info_plus_platform_interface name: package_info_plus_platform_interface
sha256: ac1f4a4847f1ade8e6a87d1f39f5d7c67490738642e2542f559ec38c37489a66 sha256: a5ef9986efc7bf772f2696183a3992615baa76c1ffb1189318dd8803778fb05b
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.1" version: "3.0.2"
page_transition: page_transition:
dependency: "direct main" dependency: "direct main"
description: description:
name: page_transition name: page_transition
sha256: dee976b1f23de9bbef5cd512fe567e9f6278caee11f5eaca9a2115c19dc49ef6 sha256: "9d2a780d7d68b53ae82fbcc43e06a16195e6775e9aae40e55dc0cbb593460f9d"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.0" version: "2.2.1"
path: path:
dependency: transitive dependency: transitive
description: description:
@ -1273,6 +1305,30 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.0" version: "2.3.0"
patrol:
dependency: "direct dev"
description:
name: patrol
sha256: f2b423122e63b1251fc31165ba1f7d85d60e22b4d20076ef39dcb47f83e35467
url: "https://pub.dev"
source: hosted
version: "3.13.2"
patrol_finders:
dependency: "direct dev"
description:
name: patrol_finders
sha256: "5a1e2b4c6636e89645fc596d68224cfe6cca28e11c855b98dd0df9bed0d80405"
url: "https://pub.dev"
source: hosted
version: "2.6.0"
patrol_log:
dependency: transitive
description:
name: patrol_log
sha256: ad5d7b759d16071ca16aa9b27eb4f106ce23079792d4312941874dbc33e795cb
url: "https://pub.dev"
source: hosted
version: "0.2.2"
percent_indicator: percent_indicator:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1369,6 +1425,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.5.1" version: "1.5.1"
posix:
dependency: transitive
description:
name: posix
sha256: a0117dc2167805aa9125b82eee515cc891819bac2f538c83646d355b16f58b9a
url: "https://pub.dev"
source: hosted
version: "6.0.1"
process: process:
dependency: transitive dependency: transitive
description: description:
@ -1397,10 +1461,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: pubspec_parse name: pubspec_parse
sha256: c799b721d79eb6ee6fa56f00c04b472dcd44a30d258fac2174a6ec57302678f8 sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.0" version: "1.5.0"
qr: qr:
dependency: transitive dependency: transitive
description: description:
@ -1461,34 +1525,34 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: share_plus_platform_interface name: share_plus_platform_interface
sha256: c57c0bbfec7142e3a0f55633be504b796af72e60e3c791b44d5a017b985f7a48 sha256: cc012a23fc2d479854e6c80150696c4a5f5bb62cb89af4de1c505cf78d0a5d0b
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.0.1" version: "5.0.2"
shared_preferences: shared_preferences:
dependency: "direct main" dependency: "direct main"
description: description:
name: shared_preferences name: shared_preferences
sha256: "95f9997ca1fb9799d494d0cb2a780fd7be075818d59f00c43832ed112b158a82" sha256: a752ce92ea7540fc35a0d19722816e04d0e72828a4200e83a98cf1a1eb524c9a
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.3" version: "2.3.5"
shared_preferences_android: shared_preferences_android:
dependency: "direct main" dependency: "direct main"
description: description:
name: shared_preferences_android name: shared_preferences_android
sha256: "7f172d1b06de5da47b6264c2692ee2ead20bbbc246690427cdb4fc301cd0c549" sha256: bf808be89fe9dc467475e982c1db6c2faf3d2acf54d526cd5ec37d86c99dbd84
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.4" version: "2.4.1"
shared_preferences_foundation: shared_preferences_foundation:
dependency: "direct main" dependency: "direct main"
description: description:
name: shared_preferences_foundation name: shared_preferences_foundation
sha256: "07e050c7cd39bad516f8d64c455f04508d09df104be326d8c02551590a0d513d" sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.5.3" version: "2.5.4"
shared_preferences_linux: shared_preferences_linux:
dependency: transitive dependency: transitive
description: description:
@ -1525,10 +1589,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: shelf name: shelf
sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.4.1" version: "1.4.2"
shelf_packages_handler:
dependency: transitive
description:
name: shelf_packages_handler
sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e"
url: "https://pub.dev"
source: hosted
version: "3.0.2"
shelf_static:
dependency: transitive
description:
name: shelf_static
sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3
url: "https://pub.dev"
source: hosted
version: "1.1.3"
shelf_web_socket: shelf_web_socket:
dependency: transitive dependency: transitive
description: description:
@ -1554,10 +1634,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: source_helper name: source_helper
sha256: "6adebc0006c37dd63fe05bca0a929b99f06402fc95aa35bf36d67f5c06de01fd" sha256: "86d247119aedce8e63f4751bd9626fc9613255935558447569ad42f9f5b48b3c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.4" version: "1.3.5"
source_map_stack_trace:
dependency: transitive
description:
name: source_map_stack_trace
sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b
url: "https://pub.dev"
source: hosted
version: "2.1.2"
source_maps:
dependency: transitive
description:
name: source_maps
sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812"
url: "https://pub.dev"
source: hosted
version: "0.10.13"
source_span: source_span:
dependency: transitive dependency: transitive
description: description:
@ -1602,10 +1698,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: sqflite_darwin name: sqflite_darwin
sha256: "96a698e2bc82bd770a4d6aab00b42396a7c63d9e33513a56945cbccb594c2474" sha256: "22adfd9a2c7d634041e96d6241e6e1c8138ca6817018afc5d443fef91dcefa9c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.1" version: "2.4.1+1"
sqflite_platform_interface: sqflite_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -1642,10 +1738,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: stream_transform name: stream_transform
sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.0" version: "2.1.1"
string_scanner: string_scanner:
dependency: transitive dependency: transitive
description: description:
@ -1678,6 +1774,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.1" version: "1.2.1"
test:
dependency: "direct dev"
description:
name: test
sha256: "713a8789d62f3233c46b4a90b174737b2c04cb6ae4500f2aa8b1be8f03f5e67f"
url: "https://pub.dev"
source: hosted
version: "1.25.8"
test_api: test_api:
dependency: transitive dependency: transitive
description: description:
@ -1686,6 +1790,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.3" version: "0.7.3"
test_core:
dependency: transitive
description:
name: test_core
sha256: "12391302411737c176b0b5d6491f466b0dd56d4763e347b6714efbaa74d7953d"
url: "https://pub.dev"
source: hosted
version: "0.6.5"
timeago: timeago:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1698,10 +1810,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: timing name: timing
sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.1" version: "1.0.2"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:
@ -1762,18 +1874,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_web name: url_launcher_web
sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e" sha256: "3ba963161bd0fe395917ba881d320b9c4f6dd3c4a233da62ab18a5025c85f1e9"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.3" version: "2.4.0"
url_launcher_windows: url_launcher_windows:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_windows name: url_launcher_windows
sha256: "44cf3aabcedde30f2dba119a9dea3b0f2672fbe6fa96e85536251d678216b3c4" sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.3" version: "3.1.4"
uuid: uuid:
dependency: "direct overridden" dependency: "direct overridden"
description: description:
@ -1794,10 +1906,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: vector_graphics_codec name: vector_graphics_codec
sha256: "2430b973a4ca3c4dbc9999b62b8c719a160100dcbae5c819bae0cacce32c9cdb" sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.12" version: "1.1.13"
vector_graphics_compiler: vector_graphics_compiler:
dependency: transitive dependency: transitive
description: description:
@ -1826,10 +1938,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: watcher name: watcher
sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" sha256: "69da27e49efa56a15f8afe8f4438c4ec02eff0a117df1b22ea4aad194fe1c104"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.0" version: "1.1.1"
web: web:
dependency: transitive dependency: transitive
description: description:
@ -1862,6 +1974,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.4" version: "3.0.4"
webkit_inspection_protocol:
dependency: transitive
description:
name: webkit_inspection_protocol
sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572"
url: "https://pub.dev"
source: hosted
version: "1.2.1"
webview_flutter: webview_flutter:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1874,10 +1994,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: webview_flutter_android name: webview_flutter_android
sha256: "285cedfd9441267f6cca8843458620b5fda1af75b04f5818d0441acda5d7df19" sha256: d1ee28f44894cbabb1d94cc42f9980297f689ff844d067ec50ff88d86e27d63f
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.1.0" version: "4.3.0"
webview_flutter_platform_interface: webview_flutter_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -1890,10 +2010,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: webview_flutter_wkwebview name: webview_flutter_wkwebview
sha256: b7e92f129482460951d96ef9a46b49db34bd2e1621685de26e9eaafd9674e7eb sha256: "4adc14ea9a770cc9e2c8f1ac734536bd40e82615bd0fa6b94be10982de656cc7"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.16.3" version: "3.17.0"
win32: win32:
dependency: "direct overridden" dependency: "direct overridden"
description: description:
@ -1930,10 +2050,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: yaml name: yaml
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.2" version: "3.1.3"
sdks: sdks:
dart: ">=3.5.0 <4.0.0" dart: ">=3.6.0 <4.0.0"
flutter: ">=3.24.0" flutter: ">=3.27.0"

View File

@ -37,12 +37,12 @@ dependencies:
# flutter_plugin_android_lifecycle: ^2.0.23 # flutter_plugin_android_lifecycle: ^2.0.23
share_plus: ^10.0.0 share_plus: ^10.0.0
# connectivity_plus: ^6.0.5 # connectivity_plus: ^6.0.5
flutter_secure_storage: 9.2.2 flutter_secure_storage: ^10.0.0-beta.2
flutter_secure_storage_linux: 1.2.1 flutter_secure_storage_linux: ^2.0.0
flutter_secure_storage_macos: 3.1.2 flutter_secure_storage_macos: ^4.0.0
flutter_secure_storage_platform_interface: 1.1.2 flutter_secure_storage_platform_interface: ^2.0.1
flutter_secure_storage_web: 1.2.1 flutter_secure_storage_web: ^2.0.0
flutter_secure_storage_windows: 3.1.2 flutter_secure_storage_windows: ^4.0.0
flutter_spinkit: 5.2.1 flutter_spinkit: 5.2.1
flutter_staggered_grid_view: 0.7.0 flutter_staggered_grid_view: 0.7.0
flutter_svg: ^2.0.15 flutter_svg: ^2.0.15
@ -56,13 +56,13 @@ dependencies:
image_picker_for_web: ^3.0.5 image_picker_for_web: ^3.0.5
persistent_bottom_nav_bar: ^6.2.1 persistent_bottom_nav_bar: ^6.2.1
image_picker_ios: ^0.8.12+1 image_picker_ios: ^0.8.12+1
image_picker_platform_interface: 2.10.0 image_picker_platform_interface: ^2.10.1
local_auth: ^2.2.0 local_auth: ^2.2.0
intl: ^0.19.0 intl: ^0.19.0
# camera: ^0.11.0+2 # camera: ^0.11.0+2
json_path: ^0.7.4 json_path: ^0.7.4
mime_type: ^1.0.1 mime_type: ^1.0.1
page_transition: 2.1.0 page_transition: ^2.2.1
path_provider: ^2.1.4 path_provider: ^2.1.4
path_provider_android: ^2.2.12 path_provider_android: ^2.2.12
google_mlkit_face_detection: ^0.12.0 google_mlkit_face_detection: ^0.12.0
@ -92,7 +92,7 @@ dependencies:
material_symbols_icons: ^4.2784.0 material_symbols_icons: ^4.2784.0
fluttertoast: ^8.2.8 fluttertoast: ^8.2.8
cupertino_icons: ^1.0.0 cupertino_icons: ^1.0.0
flutter_bloc: ^8.1.6 flutter_bloc: ^9.0.0
flutter_riverpod: ^2.5.1 flutter_riverpod: ^2.5.1
qr_flutter: ^4.1.0 qr_flutter: ^4.1.0
permission_handler: ^11.3.1 permission_handler: ^11.3.1
@ -124,6 +124,9 @@ dev_dependencies:
build_runner: ^2.4.13 build_runner: ^2.4.13
freezed: ^2.5.7 freezed: ^2.5.7
json_serializable: ^6.9.0 json_serializable: ^6.9.0
test: ^1.25.8
patrol: ^3.13.2
patrol_finders: ^2.6.0
flutter_launcher_icons: flutter_launcher_icons:
android: "launcher_icon" android: "launcher_icon"
@ -157,3 +160,10 @@ fonts:
- family: Menu - family: Menu
fonts: fonts:
- asset: assets/fonts/menu.ttf - asset: assets/fonts/menu.ttf
patrol:
app_name: FRE ACCESS HUB
android:
package_name: com.freaccess.hub
ios:
bundle_id: br.com.freaccess.hub

View File

@ -0,0 +1,11 @@
# Ativa o 'patrol_cli' globalmente
flutter pub global activate patrol_cli
# Limpa os builds anteriores do Flutter
flutter clean
# Obtém as dependências do Flutter
flutter pub get
# Verifica a configuração do Patrol
patrol doctor

View File

@ -0,0 +1,70 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:hub/features/backend/index.dart';
import 'package:hub/features/menu/index.dart';
import 'package:hub/features/module/index.dart';
import 'package:hub/features/storage/index.dart';
import 'package:hub/initialization.dart';
import 'package:integration_test/integration_test.dart';
class ApiImpl implements Api {
@override
var getLicense = LicenseApi() as GetLicense;
}
class LicenseApi extends GetLicense {
@override
Future<ApiCallResponse> call() async => ApiCallResponse(
{
'error_msg': 'error',
},
{
'Content-Type': 'application/x-www-form-urlencoded',
},
200,
);
}
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
setUpAll(() async {
await initializeApp();
});
group('Test', () {
late LicenseRepository repo = LicenseRepositoryImpl(
DatabaseService.database,
ApiImpl(),
);
List<MenuEntry> menuEntries = MenuEntry.entries;
test('update license', () async {
late bool result;
result = await repo.updateLicense();
expect(result, true);
});
test('get module', () async {
late String? result;
for (var entry in menuEntries) {
result = await repo.getModule(entry.key);
expect(result, isNotNull);
}
});
test('set module', () async {
late bool? result;
for (var entry in menuEntries) {
result = await repo.setModule(entry.key, '');
expect(result, true);
}
});
test('clean license', () async {
late bool result;
result = await repo.cleanLicense();
expect(result, true);
});
});
}