FCSC Feedback bug fix
This commit is contained in:
parent
4da8888796
commit
10f8ab2db0
@ -20,12 +20,12 @@ if (project.hasProperty('google-services.json')) {
|
|||||||
|
|
||||||
def flutterVersionCode = localProperties.getProperty("flutter.versionCode")
|
def flutterVersionCode = localProperties.getProperty("flutter.versionCode")
|
||||||
if (flutterVersionCode == null) {
|
if (flutterVersionCode == null) {
|
||||||
flutterVersionCode = "25"
|
flutterVersionCode = "26"
|
||||||
}
|
}
|
||||||
|
|
||||||
def flutterVersionName = localProperties.getProperty("flutter.versionName")
|
def flutterVersionName = localProperties.getProperty("flutter.versionName")
|
||||||
if (flutterVersionName == null) {
|
if (flutterVersionName == null) {
|
||||||
flutterVersionName = "1.2.17"
|
flutterVersionName = "1.2.18"
|
||||||
}
|
}
|
||||||
|
|
||||||
def keystorePropertiesFile = rootProject.file("key.properties")
|
def keystorePropertiesFile = rootProject.file("key.properties")
|
||||||
|
|||||||
@ -513,7 +513,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.2.15;
|
MARKETING_VERSION = 1.2.16;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = ae.gov.fcsc.frontend.ios;
|
PRODUCT_BUNDLE_IDENTIFIER = ae.gov.fcsc.frontend.ios;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||||
@ -707,7 +707,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.2.15;
|
MARKETING_VERSION = 1.2.16;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = ae.gov.fcsc.frontend.ios;
|
PRODUCT_BUNDLE_IDENTIFIER = ae.gov.fcsc.frontend.ios;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||||
@ -737,7 +737,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.2.15;
|
MARKETING_VERSION = 1.2.16;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = ae.gov.fcsc.frontend.ios;
|
PRODUCT_BUNDLE_IDENTIFIER = ae.gov.fcsc.frontend.ios;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
// api_config.dart
|
// api_config.dart
|
||||||
// const String apiUrl = 'http://127.0.0.1:8090';
|
// const String apiUrl = 'http://127.0.0.1:8090';
|
||||||
// const String apiUrl = 'https://pbdev.venbait.in/';
|
// const String apiUrl = 'https://pbdev.venbait.in/';
|
||||||
// const String apiUrl = 'https://pb.venbait.in/';
|
const String apiUrl = 'https://pb.venbait.in/';
|
||||||
const String apiUrl = 'https://pocket.fcsc.gov.ae/';
|
// const String apiUrl = 'https://pocket.fcsc.gov.ae/';
|
||||||
|
|||||||
@ -11,7 +11,7 @@ class AuthRepository {
|
|||||||
Future<String?> fetchLocallyStored() async {
|
Future<String?> fetchLocallyStored() async {
|
||||||
return await _secureStorage.read(key: "FlutterSecureStorage.session");
|
return await _secureStorage.read(key: "FlutterSecureStorage.session");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SessionCheckScreen extends StatefulWidget {
|
class SessionCheckScreen extends StatefulWidget {
|
||||||
const SessionCheckScreen({Key? key}) : super(key: key);
|
const SessionCheckScreen({Key? key}) : super(key: key);
|
||||||
@ -25,6 +25,14 @@ class _SessionCheckScreenState extends State<SessionCheckScreen> {
|
|||||||
final String playStoreUrl = "https://play.google.com/store/apps/details?id=ae.gov.fcsc.stats";
|
final String playStoreUrl = "https://play.google.com/store/apps/details?id=ae.gov.fcsc.stats";
|
||||||
bool _isLoading = true;
|
bool _isLoading = true;
|
||||||
|
|
||||||
|
bool _isLoginPath(String path) {
|
||||||
|
return path == '/login' || path.startsWith('/login?');
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _isForgotPasswordPath(String path) {
|
||||||
|
return path.startsWith('/forgot-password/');
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@ -43,20 +51,34 @@ class _SessionCheckScreenState extends State<SessionCheckScreen> {
|
|||||||
.uri;
|
.uri;
|
||||||
|
|
||||||
final intendedPath = uri.queryParameters['intendedPath'];
|
final intendedPath = uri.queryParameters['intendedPath'];
|
||||||
|
final normalizedIntendedPath =
|
||||||
|
(intendedPath != null && intendedPath.isNotEmpty)
|
||||||
|
? Uri.decodeComponent(intendedPath)
|
||||||
|
: null;
|
||||||
|
|
||||||
if (session != null &&
|
if (session != null &&
|
||||||
session.freshness != SessionFreshness.expired) {
|
session.freshness != SessionFreshness.expired) {
|
||||||
|
|
||||||
if (intendedPath != null && intendedPath.isNotEmpty) {
|
if (normalizedIntendedPath != null && normalizedIntendedPath.isNotEmpty) {
|
||||||
context.go(intendedPath);
|
// Deep link to /login should open home when session is already valid.
|
||||||
|
if (_isLoginPath(normalizedIntendedPath)) {
|
||||||
|
context.go('/myhomepage');
|
||||||
|
} else {
|
||||||
|
context.go(normalizedIntendedPath);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
context.go('/myhomepage');
|
context.go('/myhomepage');
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (intendedPath != null && intendedPath.isNotEmpty) {
|
if (normalizedIntendedPath != null && normalizedIntendedPath.isNotEmpty) {
|
||||||
context.go('/login?intendedPath=${Uri.encodeComponent(intendedPath)}');
|
// Forgot password links are public and should open directly.
|
||||||
|
if (_isForgotPasswordPath(normalizedIntendedPath)) {
|
||||||
|
context.go(normalizedIntendedPath);
|
||||||
|
} else {
|
||||||
|
context.go('/login?intendedPath=${Uri.encodeComponent(normalizedIntendedPath)}');
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
context.go('/login');
|
context.go('/login');
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,34 +50,95 @@ class _ThemeSelectorDialogState extends State<ThemeSelectorDialog> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final isDarkTheme = Theme.of(context).brightness == Brightness.dark;
|
||||||
|
const accentColor = Color(0xFFB68A34);
|
||||||
|
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
|
backgroundColor: isDarkTheme ? Colors.black : Colors.white,
|
||||||
title: Text(
|
title: Text(
|
||||||
_tr(en: 'Choose Theme', ar: 'اختر المظهر'),
|
_tr(en: 'Choose Theme', ar: 'اختر المظهر'),
|
||||||
|
style: TextStyle(
|
||||||
|
color: isDarkTheme ? Colors.white : Colors.black,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
content: Column(
|
content: SizedBox(
|
||||||
mainAxisSize: MainAxisSize.min,
|
width: double.maxFinite,
|
||||||
children: AppTheme.values.map((theme) {
|
child: Column(
|
||||||
return RadioListTile<AppTheme>(
|
mainAxisSize: MainAxisSize.min,
|
||||||
title: Text(_themeLabel(theme)),
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
value: theme,
|
children: AppTheme.values.map((theme) {
|
||||||
groupValue: _selectedTheme,
|
return RadioListTile<AppTheme>(
|
||||||
onChanged: (value) async {
|
contentPadding: EdgeInsets.zero,
|
||||||
final prefs = await SharedPreferences.getInstance();
|
controlAffinity: ListTileControlAffinity.leading,
|
||||||
await prefs.setString(
|
activeColor: accentColor,
|
||||||
'ThemeType', value.toString().split('.').last);
|
fillColor: WidgetStateProperty.all(accentColor),
|
||||||
|
title: Text(
|
||||||
|
_themeLabel(theme),
|
||||||
|
style: TextStyle(
|
||||||
|
color: isDarkTheme ? Colors.white : Colors.black,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
value: theme,
|
||||||
|
groupValue: _selectedTheme,
|
||||||
|
onChanged: (value) async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
await prefs.setString(
|
||||||
|
'ThemeType', value.toString().split('.').last);
|
||||||
|
|
||||||
setState(() => _selectedTheme = value!);
|
setState(() => _selectedTheme = value!);
|
||||||
});
|
});
|
||||||
}).toList(),
|
}).toList(),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
Row(
|
||||||
onPressed: () => Navigator.of(context).pop(null),
|
children: [
|
||||||
child: Text(_tr(en: 'Cancel', ar: 'إلغاء')),
|
Expanded(
|
||||||
),
|
child: TextButton(
|
||||||
ElevatedButton(
|
onPressed: () => Navigator.of(context).pop(null),
|
||||||
onPressed: () => Navigator.of(context).pop(_selectedTheme),
|
style: TextButton.styleFrom(
|
||||||
child: Text(_tr(en: 'OK', ar: 'حسناً')),
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(10.0),
|
||||||
|
),
|
||||||
|
side: const BorderSide(
|
||||||
|
color: accentColor,
|
||||||
|
width: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
_tr(en: 'Cancel', ar: 'إلغاء'),
|
||||||
|
style: const TextStyle(
|
||||||
|
color: accentColor,
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
Expanded(
|
||||||
|
child: TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(_selectedTheme),
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
backgroundColor: accentColor,
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(10.0),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: FittedBox(
|
||||||
|
fit: BoxFit.scaleDown,
|
||||||
|
child: Text(
|
||||||
|
_tr(en: 'OK', ar: 'حسناً'),
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@ -92,6 +92,7 @@ class _MainAppState extends ConsumerState<MainApp> {
|
|||||||
String? pendingDeepLink;
|
String? pendingDeepLink;
|
||||||
Map<String, dynamic>? pendingDeepLinkData;
|
Map<String, dynamic>? pendingDeepLinkData;
|
||||||
StreamSubscription<Uri>? _appLinkSubscription;
|
StreamSubscription<Uri>? _appLinkSubscription;
|
||||||
|
Timer? _oneLinkFallbackTimer;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -104,6 +105,7 @@ class _MainAppState extends ConsumerState<MainApp> {
|
|||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_appLinkSubscription?.cancel();
|
_appLinkSubscription?.cancel();
|
||||||
|
_oneLinkFallbackTimer?.cancel();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,8 +125,15 @@ class _MainAppState extends ConsumerState<MainApp> {
|
|||||||
if (uri.scheme == 'fcscappstates') {
|
if (uri.scheme == 'fcscappstates') {
|
||||||
final deepLinkValue = uri.queryParameters['deep_link_value'];
|
final deepLinkValue = uri.queryParameters['deep_link_value'];
|
||||||
if (deepLinkValue != null && deepLinkValue.isNotEmpty) {
|
if (deepLinkValue != null && deepLinkValue.isNotEmpty) {
|
||||||
|
_oneLinkFallbackTimer?.cancel();
|
||||||
final path = deepLinkValue.startsWith('/') ? deepLinkValue : '/$deepLinkValue';
|
final path = deepLinkValue.startsWith('/') ? deepLinkValue : '/$deepLinkValue';
|
||||||
router.go('/?intendedPath=${Uri.encodeComponent(path)}');
|
router.go('/?intendedPath=${Uri.encodeComponent(path)}');
|
||||||
|
} else {
|
||||||
|
// Wait briefly for AppsFlyer SDK callback, then fallback to app root.
|
||||||
|
_oneLinkFallbackTimer?.cancel();
|
||||||
|
_oneLinkFallbackTimer = Timer(const Duration(milliseconds: 1500), () {
|
||||||
|
if (mounted) router.go('/');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -133,8 +142,17 @@ class _MainAppState extends ConsumerState<MainApp> {
|
|||||||
if (uri.scheme == 'https' && uri.host == 'fcscstats.onelink.me') {
|
if (uri.scheme == 'https' && uri.host == 'fcscstats.onelink.me') {
|
||||||
final deepLinkValue = uri.queryParameters['deep_link_value'];
|
final deepLinkValue = uri.queryParameters['deep_link_value'];
|
||||||
if (deepLinkValue != null && deepLinkValue.isNotEmpty) {
|
if (deepLinkValue != null && deepLinkValue.isNotEmpty) {
|
||||||
|
_oneLinkFallbackTimer?.cancel();
|
||||||
final path = deepLinkValue.startsWith('/') ? deepLinkValue : '/$deepLinkValue';
|
final path = deepLinkValue.startsWith('/') ? deepLinkValue : '/$deepLinkValue';
|
||||||
router.go('/?intendedPath=${Uri.encodeComponent(path)}');
|
router.go('/?intendedPath=${Uri.encodeComponent(path)}');
|
||||||
|
} else {
|
||||||
|
// Some OneLink opens arrive without query params; AppsFlyer SDK usually
|
||||||
|
// delivers deep_link_value shortly after. Delay root fallback to avoid
|
||||||
|
// overriding the real deep-link route.
|
||||||
|
_oneLinkFallbackTimer?.cancel();
|
||||||
|
_oneLinkFallbackTimer = Timer(const Duration(milliseconds: 1500), () {
|
||||||
|
if (mounted) router.go('/');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -204,13 +222,37 @@ class _MainAppState extends ConsumerState<MainApp> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _handleDeepLink(String? deepLinkValue, Map<String, dynamic> data) {
|
void _handleDeepLink(String? deepLinkValue, Map<String, dynamic> data) {
|
||||||
if (deepLinkValue == null || deepLinkValue.isEmpty) return;
|
_oneLinkFallbackTimer?.cancel();
|
||||||
|
|
||||||
|
String? resolved = deepLinkValue;
|
||||||
|
|
||||||
|
// AppsFlyer may not always populate deepLinkValue for complex links.
|
||||||
|
// Fallback to clickEvent payload keys.
|
||||||
|
resolved ??= data['deep_link_value']?.toString();
|
||||||
|
resolved ??= data['af_dp']?.toString();
|
||||||
|
resolved = resolved?.trim();
|
||||||
|
|
||||||
|
if (resolved == null || resolved.isEmpty) return;
|
||||||
|
|
||||||
|
// If AppsFlyer gives a full URL, preserve path+query only.
|
||||||
|
if (resolved.startsWith('http://') || resolved.startsWith('https://')) {
|
||||||
|
final parsed = Uri.tryParse(resolved);
|
||||||
|
if (parsed != null) {
|
||||||
|
resolved = parsed.path + (parsed.hasQuery ? '?${parsed.query}' : '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode once so encoded query paths like
|
||||||
|
// %2FchartScreen%2Fgdp%3FbgColor%3D... become route-friendly.
|
||||||
|
try {
|
||||||
|
resolved = Uri.decodeComponent(resolved);
|
||||||
|
} catch (_) {}
|
||||||
|
|
||||||
// Use full path as intendedPath so shared links (e.g. /uaenumbers/123) open the right screen.
|
// Use full path as intendedPath so shared links (e.g. /uaenumbers/123) open the right screen.
|
||||||
// SessionCheckScreen: if logged in -> go to intendedPath; if not -> login then redirect.
|
// SessionCheckScreen: if logged in -> go to intendedPath; if not -> login then redirect.
|
||||||
final String intendedPath = deepLinkValue.startsWith('/')
|
final String intendedPath = resolved!.startsWith('/')
|
||||||
? deepLinkValue
|
? resolved
|
||||||
: '/$deepLinkValue';
|
: '/$resolved';
|
||||||
|
|
||||||
context.go('/?intendedPath=${Uri.encodeComponent(intendedPath)}');
|
context.go('/?intendedPath=${Uri.encodeComponent(intendedPath)}');
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2370,7 +2370,9 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
// OneLink template V6mR; configure in AppsFlyer dashboard: app package/bundle ID + store fallback URLs
|
// OneLink template V6mR; configure in AppsFlyer dashboard: app package/bundle ID + store fallback URLs
|
||||||
const String baseAppLink = 'https://fcscstats.onelink.me/V6mR/t40b32al';
|
const String baseAppLink = 'https://fcscstats.onelink.me/V6mR/t40b32al';
|
||||||
final String path = currentRoute.startsWith('/') ? currentRoute : '/$currentRoute';
|
final String path = currentRoute.startsWith('/') ? currentRoute : '/$currentRoute';
|
||||||
final String shareLink = path == '/' ? baseAppLink : '$baseAppLink$path';
|
final String shareLink = path == '/'
|
||||||
|
? baseAppLink
|
||||||
|
: '$baseAppLink?deep_link_value=${Uri.encodeComponent(path)}';
|
||||||
final String shareText = 'Check this out!\n\n$shareLink';
|
final String shareText = 'Check this out!\n\n$shareLink';
|
||||||
print('Generated Share Link: $shareLink');
|
print('Generated Share Link: $shareLink');
|
||||||
|
|
||||||
|
|||||||
@ -229,29 +229,29 @@ class LoginRoute extends HookConsumerWidget with WidgetsBindingObserver{
|
|||||||
backgroundColor: isDark ? const Color(0xFF1F1F1F) : Colors.white,
|
backgroundColor: isDark ? const Color(0xFF1F1F1F) : Colors.white,
|
||||||
title: showErrorTitle
|
title: showErrorTitle
|
||||||
? Column(
|
? Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
const CircleAvatar(
|
const CircleAvatar(
|
||||||
radius: 18,
|
radius: 18,
|
||||||
backgroundColor: Color(0xFFFFE9E9),
|
backgroundColor: Color(0xFFFFE9E9),
|
||||||
child: Icon(
|
child: Icon(
|
||||||
Icons.priority_high_rounded,
|
Icons.priority_high_rounded,
|
||||||
color: Color(0xFFD83731),
|
color: Color(0xFFD83731),
|
||||||
size: 22,
|
size: 22,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Text(
|
Text(
|
||||||
context.translate('Error!', 'خطأ!'),
|
context.translate('Error!', 'خطأ!'),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: context.translate('Roboto', 'NotoKufi'),
|
fontFamily: context.translate('Roboto', 'NotoKufi'),
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
color: isDark ? Colors.white : const Color(0xFF1A1A1A),
|
color: isDark ? Colors.white : const Color(0xFF1A1A1A),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
content: Text(
|
content: Text(
|
||||||
message,
|
message,
|
||||||
@ -674,11 +674,11 @@ class LoginRoute extends HookConsumerWidget with WidgetsBindingObserver{
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> oAuthGoogleAndAppleLogin(
|
Future<void> oAuthGoogleAndAppleLogin(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
WidgetRef ref,
|
WidgetRef ref,
|
||||||
platform, {
|
platform, {
|
||||||
bool linkToExistingAccount = false,
|
bool linkToExistingAccount = false,
|
||||||
}) async {
|
}) async {
|
||||||
print('platform $platform');
|
print('platform $platform');
|
||||||
try {
|
try {
|
||||||
final authData;
|
final authData;
|
||||||
@ -696,8 +696,9 @@ class LoginRoute extends HookConsumerWidget with WidgetsBindingObserver{
|
|||||||
queryParameters: {
|
queryParameters: {
|
||||||
...url.queryParameters,
|
...url.queryParameters,
|
||||||
'acr_values':
|
'acr_values':
|
||||||
'urn:safelayer:tws:policies:authentication:level:low',
|
'urn:safelayer:tws:policies:authentication:level:low',
|
||||||
'ui_locales': uiLocales,
|
'ui_locales': uiLocales,
|
||||||
|
// 'redirect_url': 'ae.gov.fcsc.stats://auth-callback',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
print(mobileUri);
|
print(mobileUri);
|
||||||
@ -727,7 +728,7 @@ class LoginRoute extends HookConsumerWidget with WidgetsBindingObserver{
|
|||||||
// Google must use external browser. Apple uses OAuthWebView on mobile per app flow.
|
// Google must use external browser. Apple uses OAuthWebView on mobile per app flow.
|
||||||
authData = await pb.collection('users').authWithOAuth2(
|
authData = await pb.collection('users').authWithOAuth2(
|
||||||
platform,
|
platform,
|
||||||
(url) async {
|
(url) async {
|
||||||
if (platform == 'apple' && !kIsWeb) {
|
if (platform == 'apple' && !kIsWeb) {
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
await Navigator.of(context).push(
|
await Navigator.of(context).push(
|
||||||
@ -2629,17 +2630,17 @@ class LoginRoute extends HookConsumerWidget with WidgetsBindingObserver{
|
|||||||
dontHaveAnAccountRegisterBtn,
|
dontHaveAnAccountRegisterBtn,
|
||||||
// continueAsGuestBtn,
|
// continueAsGuestBtn,
|
||||||
15.verticalSpace,
|
15.verticalSpace,
|
||||||
// orText,
|
orText,
|
||||||
// 15.verticalSpace,
|
15.verticalSpace,
|
||||||
// signInWithUAEPassBtn,
|
signInWithUAEPassBtn,
|
||||||
// 15.verticalSpace,
|
15.verticalSpace,
|
||||||
// orText,
|
orText,
|
||||||
15.verticalSpace,
|
15.verticalSpace,
|
||||||
signInWithGoogleBtn,
|
signInWithGoogleBtn,
|
||||||
15.verticalSpace,
|
15.verticalSpace,
|
||||||
signInWithAppleBtn,
|
signInWithAppleBtn,
|
||||||
15.verticalSpace,
|
// 15.verticalSpace,
|
||||||
signInWithUAEPassBtn,
|
// signInWithUAEPassBtn,
|
||||||
30.verticalSpace,
|
30.verticalSpace,
|
||||||
// 120.verticalSpace,
|
// 120.verticalSpace,
|
||||||
],
|
],
|
||||||
@ -2791,29 +2792,48 @@ class OAuthWebView extends StatelessWidget {
|
|||||||
static const _resumePath = 'resume_authn';
|
static const _resumePath = 'resume_authn';
|
||||||
|
|
||||||
Future<void> _closeIfOAuthCompleted(
|
Future<void> _closeIfOAuthCompleted(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
InAppWebViewController controller,
|
InAppWebViewController controller,
|
||||||
WebUri? url,
|
WebUri? url,
|
||||||
) async {
|
) async {
|
||||||
if (useUaePassDeepLink || !context.mounted) return;
|
if (!context.mounted) return;
|
||||||
|
|
||||||
final s = (url?.toString() ?? '').toLowerCase();
|
final s = (url?.toString() ?? '').toLowerCase();
|
||||||
if (s.contains('/api/oauth2-redirect')) {
|
final authIsReady = PocketBaseService.authStore.isValid;
|
||||||
Navigator.of(context).pop();
|
|
||||||
|
if (s.contains('/api/oauth2-redirect') && s.contains('code=')) {
|
||||||
|
await Navigator.of(context).maybePop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// PocketBase sometimes renders a static completion page.
|
if (s.contains('oauth2-redirect-success') ||
|
||||||
|
s.contains('oauth2_redirect_success')) {
|
||||||
|
if (!useUaePassDeepLink && !authIsReady) return;
|
||||||
|
await Navigator.of(context).maybePop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PocketBase/hosted success pages (old + new titles).
|
||||||
final title = ((await controller.getTitle()) ?? '').toLowerCase();
|
final title = ((await controller.getTitle()) ?? '').toLowerCase();
|
||||||
if (title.contains('auth completed')) {
|
if (title.contains('auth success') ||
|
||||||
Navigator.of(context).pop();
|
title.contains('auth completed') ||
|
||||||
|
title.contains('authentication successful')) {
|
||||||
|
if (!useUaePassDeepLink && !authIsReady) return;
|
||||||
|
await Navigator.of(context).maybePop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final html = ((await controller.getHtml()) ?? '').toLowerCase();
|
final html = ((await controller.getHtml()) ?? '').toLowerCase();
|
||||||
if (html.contains('auth completed') &&
|
final legacySuccess = html.contains('auth completed') &&
|
||||||
html.contains('you can close this window')) {
|
(html.contains('you can close this window') ||
|
||||||
Navigator.of(context).pop();
|
html.contains('close this window'));
|
||||||
|
final newSuccess = html.contains('authentication successful') &&
|
||||||
|
(html.contains('proceed') ||
|
||||||
|
html.contains('return to uae stats app'));
|
||||||
|
|
||||||
|
if (legacySuccess || newSuccess) {
|
||||||
|
if (!useUaePassDeepLink && !authIsReady) return;
|
||||||
|
await Navigator.of(context).maybePop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2828,13 +2848,29 @@ class OAuthWebView extends StatelessWidget {
|
|||||||
initialSettings: InAppWebViewSettings(
|
initialSettings: InAppWebViewSettings(
|
||||||
javaScriptEnabled: true,
|
javaScriptEnabled: true,
|
||||||
domStorageEnabled: true,
|
domStorageEnabled: true,
|
||||||
useShouldOverrideUrlLoading: useUaePassDeepLink,
|
useShouldOverrideUrlLoading: true,
|
||||||
),
|
),
|
||||||
shouldOverrideUrlLoading: useUaePassDeepLink
|
shouldOverrideUrlLoading: (controller, navigationAction) async {
|
||||||
? (controller, navigationAction) async {
|
|
||||||
final uri = navigationAction.request.url;
|
final uri = navigationAction.request.url;
|
||||||
if (uri == null) return NavigationActionPolicy.ALLOW;
|
if (uri == null) return NavigationActionPolicy.ALLOW;
|
||||||
final full = uri.toString();
|
final full = uri.toString();
|
||||||
|
|
||||||
|
// If callback deep link is about to open, forward to OS and close WebView.
|
||||||
|
if (full.toLowerCase().startsWith('$_appCallbackScheme://$_resumePath')) {
|
||||||
|
final callbackUri = Uri.tryParse(full);
|
||||||
|
if (callbackUri != null) {
|
||||||
|
await launchUrl(callbackUri, mode: LaunchMode.externalApplication);
|
||||||
|
}
|
||||||
|
if (context.mounted) {
|
||||||
|
await Navigator.of(context).maybePop();
|
||||||
|
}
|
||||||
|
return NavigationActionPolicy.CANCEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!useUaePassDeepLink) {
|
||||||
|
return NavigationActionPolicy.ALLOW;
|
||||||
|
}
|
||||||
|
|
||||||
// Match uaepass:// or uaepassstg:// (scheme can be missing on some platforms)
|
// Match uaepass:// or uaepassstg:// (scheme can be missing on some platforms)
|
||||||
if (!full.toLowerCase().startsWith('$_uaepassProdScheme://') &&
|
if (!full.toLowerCase().startsWith('$_uaepassProdScheme://') &&
|
||||||
!full.toLowerCase().startsWith('$_uaepassStagingScheme://')) {
|
!full.toLowerCase().startsWith('$_uaepassStagingScheme://')) {
|
||||||
@ -2875,12 +2911,11 @@ class OAuthWebView extends StatelessWidget {
|
|||||||
mode: LaunchMode.externalApplication,
|
mode: LaunchMode.externalApplication,
|
||||||
).then((launched) {
|
).then((launched) {
|
||||||
if (launched && context.mounted) {
|
if (launched && context.mounted) {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).maybePop();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return NavigationActionPolicy.CANCEL;
|
return NavigationActionPolicy.CANCEL;
|
||||||
}
|
},
|
||||||
: null,
|
|
||||||
onLoadStart: (controller, url) async =>
|
onLoadStart: (controller, url) async =>
|
||||||
_closeIfOAuthCompleted(context, controller, url),
|
_closeIfOAuthCompleted(context, controller, url),
|
||||||
onLoadStop: (controller, url) async =>
|
onLoadStop: (controller, url) async =>
|
||||||
@ -2891,7 +2926,7 @@ class OAuthWebView extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// abstract class _LocalAuthRepo {
|
// abstract class _LocalAuthRepo {
|
||||||
// static const _key = 'session';
|
// static const _key = 'session';
|
||||||
|
|||||||
@ -185,8 +185,8 @@ class _ReportDetailPageState extends ConsumerState<ReportDetailPage> {
|
|||||||
),
|
),
|
||||||
child: BaseScaffold(
|
child: BaseScaffold(
|
||||||
showBackButton: true,
|
showBackButton: true,
|
||||||
backgroundColor: isDarkTheme ? Color(0xFF111111) : Colors.white,
|
backgroundColor: isDarkTheme ? Colors.black : Colors.white,
|
||||||
appbarColor: isDarkTheme ? Color(0xFF111111) : Colors.white,
|
appbarColor: isDarkTheme ? Colors.black : Colors.white,
|
||||||
title: Text(
|
title: Text(
|
||||||
AppLocalizations.of(context)!.nav_competitiveness,
|
AppLocalizations.of(context)!.nav_competitiveness,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
@ -199,7 +199,8 @@ class _ReportDetailPageState extends ConsumerState<ReportDetailPage> {
|
|||||||
),
|
),
|
||||||
body: isLoading || selectedReport.isEmpty
|
body: isLoading || selectedReport.isEmpty
|
||||||
? const Center(child: CircularProgressIndicator())
|
? const Center(child: CircularProgressIndicator())
|
||||||
: Column(
|
: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
/// 🔹 Top Section With Padding
|
/// 🔹 Top Section With Padding
|
||||||
Padding(
|
Padding(
|
||||||
@ -255,7 +256,7 @@ class _ReportDetailPageState extends ConsumerState<ReportDetailPage> {
|
|||||||
|
|
||||||
/// 🔹 DESCRIPTION
|
/// 🔹 DESCRIPTION
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 72,
|
height: 150,
|
||||||
child: ScrollConfiguration(
|
child: ScrollConfiguration(
|
||||||
behavior: const ScrollBehavior().copyWith(scrollbars: false),
|
behavior: const ScrollBehavior().copyWith(scrollbars: false),
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
@ -367,7 +368,9 @@ class _ReportDetailPageState extends ConsumerState<ReportDetailPage> {
|
|||||||
),
|
),
|
||||||
|
|
||||||
/// 🔹 COUNTRY SECTION
|
/// 🔹 COUNTRY SECTION
|
||||||
Container(
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: isDarkTheme ? Color(0xFF222222) : Color(0xFFF5F5F5),
|
color: isDarkTheme ? Color(0xFF222222) : Color(0xFFF5F5F5),
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
@ -391,8 +394,11 @@ class _ReportDetailPageState extends ConsumerState<ReportDetailPage> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
)),
|
)),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|||||||
@ -155,8 +155,8 @@ class _CompetitivenessState extends ConsumerState<Competitiveness> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: BaseScaffold(
|
child: BaseScaffold(
|
||||||
backgroundColor: isDarkTheme ? Color(0xFF111111) : Colors.white,
|
backgroundColor: isDarkTheme ? Colors.black : Colors.white,
|
||||||
appbarColor: isDarkTheme ? Color(0xFF111111) : Colors.white,
|
appbarColor: isDarkTheme ? Colors.black : Colors.white,
|
||||||
title: Text(
|
title: Text(
|
||||||
AppLocalizations.of(context)!.nav_competitiveness,
|
AppLocalizations.of(context)!.nav_competitiveness,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
|
|||||||
@ -199,8 +199,8 @@ class _DetailedCountryProfilePageState
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: BaseScaffold(
|
child: BaseScaffold(
|
||||||
backgroundColor: isDarkTheme ? Color(0xFF111111) : Colors.white,
|
backgroundColor: isDarkTheme ? Colors.black : Colors.white,
|
||||||
appbarColor: isDarkTheme ? Color(0xFF111111) : Colors.white,
|
appbarColor: isDarkTheme ? Colors.black : Colors.white,
|
||||||
title: Text(
|
title: Text(
|
||||||
AppLocalizations.of(context)!.country_profile,
|
AppLocalizations.of(context)!.country_profile,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
@ -1069,7 +1069,7 @@ class _CategoryPopupContentState extends ConsumerState<CategoryPopupContent> {
|
|||||||
Text(
|
Text(
|
||||||
tab['label'] as String,
|
tab['label'] as String,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 13,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
color: isDarkTheme
|
color: isDarkTheme
|
||||||
? (isSelected
|
? (isSelected
|
||||||
@ -1084,7 +1084,7 @@ class _CategoryPopupContentState extends ConsumerState<CategoryPopupContent> {
|
|||||||
formatTradeValue(tab['total'] as double),
|
formatTradeValue(tab['total'] as double),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.w900,
|
fontWeight: FontWeight.w900,
|
||||||
fontSize: 22,
|
fontSize: 16,
|
||||||
color: _getTradeColor(typeKey),
|
color: _getTradeColor(typeKey),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -159,8 +159,8 @@ class _ListCountriesRouteState extends ConsumerState<ListCountriesRoute> {
|
|||||||
MediaQuery.of(context).platformBrightness == Brightness.dark);
|
MediaQuery.of(context).platformBrightness == Brightness.dark);
|
||||||
|
|
||||||
final body = BaseScaffold(
|
final body = BaseScaffold(
|
||||||
backgroundColor: isDarkTheme ? Color(0xFF111111) : Colors.white,
|
backgroundColor: isDarkTheme ? Colors.black : Colors.white,
|
||||||
appbarColor: isDarkTheme ? Color(0xFF111111) : Colors.white,
|
appbarColor: isDarkTheme ? Colors.black : Colors.white,
|
||||||
title: Text(
|
title: Text(
|
||||||
AppLocalizations.of(context)!.country_profile,
|
AppLocalizations.of(context)!.country_profile,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
@ -186,7 +186,7 @@ class _ListCountriesRouteState extends ConsumerState<ListCountriesRoute> {
|
|||||||
maxHeight: 50,
|
maxHeight: 50,
|
||||||
),
|
),
|
||||||
elevation: WidgetStatePropertyAll(0),
|
elevation: WidgetStatePropertyAll(0),
|
||||||
backgroundColor: WidgetStatePropertyAll(isDarkTheme ? Color(0xFF111111) : Colors.white),
|
backgroundColor: WidgetStatePropertyAll(isDarkTheme ? Colors.black : Colors.white),
|
||||||
controller: _searchController,
|
controller: _searchController,
|
||||||
hintText: AppLocalizations.of(context)!.searchCountry,
|
hintText: AppLocalizations.of(context)!.searchCountry,
|
||||||
hintStyle: WidgetStateProperty.all(
|
hintStyle: WidgetStateProperty.all(
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
@ -47,7 +48,7 @@ class UaeNumbers extends ConsumerWidget {
|
|||||||
context.go('/myhomepage'); // Show exit confirmation dialog
|
context.go('/myhomepage'); // Show exit confirmation dialog
|
||||||
},
|
},
|
||||||
child: BaseScaffold(
|
child: BaseScaffold(
|
||||||
backgroundColor: isDarkTheme ? Color(0xFF333333) : Color(0xFF414042),
|
backgroundColor: isDarkTheme ? Color(0xFF000000) : Color(0xFFFFFFFF),
|
||||||
title: Text(
|
title: Text(
|
||||||
context.translate(
|
context.translate(
|
||||||
'UAE Numbers',
|
'UAE Numbers',
|
||||||
@ -63,6 +64,7 @@ class UaeNumbers extends ConsumerWidget {
|
|||||||
),
|
),
|
||||||
body: uaenumberWidget(),
|
body: uaenumberWidget(),
|
||||||
),
|
),
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:pocketbase/pocketbase.dart';
|
import 'package:pocketbase/pocketbase.dart';
|
||||||
@ -60,7 +61,7 @@ class _MyHomePageState extends ConsumerState<MyHomePage> {
|
|||||||
'NotoKufi',
|
'NotoKufi',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
content: Padding(
|
content: Padding(
|
||||||
padding: const EdgeInsets.all(20.0),
|
padding: const EdgeInsets.all(20.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
@ -156,7 +157,7 @@ class _MyHomePageState extends ConsumerState<MyHomePage> {
|
|||||||
(ref.watch(themeProvider) == ThemeMode.system &&
|
(ref.watch(themeProvider) == ThemeMode.system &&
|
||||||
MediaQuery.of(context).platformBrightness == Brightness.dark);
|
MediaQuery.of(context).platformBrightness == Brightness.dark);
|
||||||
|
|
||||||
return PopScope(
|
return PopScope(
|
||||||
canPop: false, // Allow back navigation only if not login screen
|
canPop: false, // Allow back navigation only if not login screen
|
||||||
onPopInvokedWithResult: (didPop, result) {
|
onPopInvokedWithResult: (didPop, result) {
|
||||||
if (didPop) return;
|
if (didPop) return;
|
||||||
@ -164,6 +165,7 @@ class _MyHomePageState extends ConsumerState<MyHomePage> {
|
|||||||
context, isDarkTheme); // Show exit confirmation dialog
|
context, isDarkTheme); // Show exit confirmation dialog
|
||||||
},
|
},
|
||||||
child: BaseScaffold(
|
child: BaseScaffold(
|
||||||
|
backgroundColor: isDarkTheme ? Color(0xFF000000) : Color(0xFFFFFFFF),
|
||||||
title: Center(
|
title: Center(
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: myheight / 5,
|
height: myheight / 5,
|
||||||
@ -174,6 +176,7 @@ class _MyHomePageState extends ConsumerState<MyHomePage> {
|
|||||||
: LogoAssetPath.uaeStatLight)))),
|
: LogoAssetPath.uaeStatLight)))),
|
||||||
body: EconomyStatsWidget(),
|
body: EconomyStatsWidget(),
|
||||||
),
|
),
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1078,8 +1081,9 @@ class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
|
|||||||
return Center(child: Text("No data available"));
|
return Center(child: Text("No data available"));
|
||||||
}
|
}
|
||||||
String firstMainTopic = data.first['main_topic'] ?? '';
|
String firstMainTopic = data.first['main_topic'] ?? '';
|
||||||
return Container(
|
return SingleChildScrollView(
|
||||||
color: isDarkTheme ? Color(0xFF000000) : Color(0xFFFFFFFF),
|
child: Container(
|
||||||
|
color: isDarkTheme ? Color(0xFF000000) : Color(0xFFFFFFFF),
|
||||||
// decoration: isDarkTheme
|
// decoration: isDarkTheme
|
||||||
// ? BoxDecoration(
|
// ? BoxDecoration(
|
||||||
// image: DecorationImage(
|
// image: DecorationImage(
|
||||||
@ -1088,12 +1092,12 @@ class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
|
|||||||
// ),
|
// ),
|
||||||
// )
|
// )
|
||||||
// : null,
|
// : null,
|
||||||
height: myheight,
|
width: double.infinity,
|
||||||
// color: Colors.cyan,
|
// color: Colors.cyan,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.only(left: 10, right: 10),
|
padding: EdgeInsets.only(left: 10, right: 10),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: data.map((mainTopic) {
|
children: data.map((mainTopic) {
|
||||||
String colorPattern = mainTopic['color_pattern'];
|
String colorPattern = mainTopic['color_pattern'];
|
||||||
// Color backgroundColor = Color(int.parse(colorPattern));
|
// Color backgroundColor = Color(int.parse(colorPattern));
|
||||||
|
|
||||||
@ -1121,11 +1125,9 @@ class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
|
|||||||
final crossAxisCount =
|
final crossAxisCount =
|
||||||
totalTiles > 0 ? (totalTiles / 2).ceil().clamp(1, 2) : 1;
|
totalTiles > 0 ? (totalTiles / 2).ceil().clamp(1, 2) : 1;
|
||||||
|
|
||||||
return Expanded(
|
return Container(
|
||||||
child: Container(
|
|
||||||
// color: Colors.cyan,
|
// color: Colors.cyan,
|
||||||
height:
|
// Set the background color for the entire Column
|
||||||
myheight, // Set the background color for the entire Column
|
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
@ -1205,9 +1207,9 @@ class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
}).toList(),
|
||||||
}).toList(),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@ -519,8 +519,8 @@ class _BookMarkState extends ConsumerState<BookMark> {
|
|||||||
context.go('/myhomepage');
|
context.go('/myhomepage');
|
||||||
},
|
},
|
||||||
child: BaseScaffold(
|
child: BaseScaffold(
|
||||||
backgroundColor: isDarkTheme ? Color(0xFF111111) : Colors.white,
|
backgroundColor: isDarkTheme ? Colors.black : Colors.white,
|
||||||
appbarColor: isDarkTheme ? Color(0xFF111111) : Colors.white,
|
appbarColor: isDarkTheme ? Colors.black : Colors.white,
|
||||||
title: Text(
|
title: Text(
|
||||||
AppLocalizations.of(context)!.bookmarks,
|
AppLocalizations.of(context)!.bookmarks,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
@ -532,7 +532,7 @@ class _BookMarkState extends ConsumerState<BookMark> {
|
|||||||
),
|
),
|
||||||
body: isLoading
|
body: isLoading
|
||||||
? Container(
|
? Container(
|
||||||
color: isDarkTheme ? Color(0xFF111111) : Colors.white,
|
color: isDarkTheme ? Colors.black : Colors.white,
|
||||||
// color: Color(0x98FFFCE5), // Semi-transparent background
|
// color: Color(0x98FFFCE5), // Semi-transparent background
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
@ -591,7 +591,7 @@ class _BookMarkState extends ConsumerState<BookMark> {
|
|||||||
childWidget: Container(
|
childWidget: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: isDarkTheme
|
color: isDarkTheme
|
||||||
? Color(0xFF111111)
|
? Colors.black
|
||||||
: Colors.white,
|
: Colors.white,
|
||||||
// borderRadius: BorderRadius.all(Radius.circular(20))
|
// borderRadius: BorderRadius.all(Radius.circular(20))
|
||||||
),
|
),
|
||||||
@ -768,7 +768,7 @@ class _BookMarkState extends ConsumerState<BookMark> {
|
|||||||
height: 100,
|
height: 100,
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: isDarkTheme ? Color(0xFF111111) : Colors.white,
|
color: isDarkTheme ? Colors.black : Colors.white,
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
border: Border.all(color: data['valueColor']),
|
border: Border.all(color: data['valueColor']),
|
||||||
),
|
),
|
||||||
@ -892,7 +892,7 @@ class _BookMarkState extends ConsumerState<BookMark> {
|
|||||||
height: 100,
|
height: 100,
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: isDarkTheme ? Color(0xFF111111) : Colors.white,
|
color: isDarkTheme ? Colors.black : Colors.white,
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
border: Border.all(color: styleColor),
|
border: Border.all(color: styleColor),
|
||||||
),
|
),
|
||||||
@ -985,7 +985,7 @@ class TabBarHeader extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
color: isDarkTheme ? Color(0xFF111111) : Colors.white,
|
color: isDarkTheme ? Colors.black : Colors.white,
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
@ -1081,7 +1081,7 @@ class _CustomExpandableTileState extends State<CustomExpandableTile> {
|
|||||||
child: Container(
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: widget.isDarkTheme
|
color: widget.isDarkTheme
|
||||||
? Color(0xFF111111)
|
? Colors.black
|
||||||
: Colors
|
: Colors
|
||||||
.white, // Ensuring the background outside the rounded container is white
|
.white, // Ensuring the background outside the rounded container is white
|
||||||
),
|
),
|
||||||
|
|||||||
@ -143,13 +143,13 @@ class _ContactState extends ConsumerState<Contact> {
|
|||||||
context.go('/myhomepage');
|
context.go('/myhomepage');
|
||||||
},
|
},
|
||||||
child: BaseScaffold(
|
child: BaseScaffold(
|
||||||
backgroundColor: isDarkTheme ? Color(0xFF333333) : Colors.white,
|
backgroundColor: isDarkTheme ? Colors.black : Colors.white,
|
||||||
appbarColor: isDarkTheme ? Color(0xFF333333) : Colors.white,
|
appbarColor: isDarkTheme ? Colors.black : Colors.white,
|
||||||
body: isLoading
|
body: isLoading
|
||||||
? Container(
|
? Container(
|
||||||
// color: Color(0x98FFFCE5), // Semi-transparent background
|
// color: Color(0x98FFFCE5), // Semi-transparent background
|
||||||
color: isDarkTheme
|
color: isDarkTheme
|
||||||
? Color(0xFF333333)
|
? Colors.black
|
||||||
: Color(0x98FFFCE5), // Semi-transparent background
|
: Color(0x98FFFCE5), // Semi-transparent background
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
@ -171,7 +171,7 @@ class _ContactState extends ConsumerState<Contact> {
|
|||||||
: Container(
|
: Container(
|
||||||
// color: Colors.grey[200],
|
// color: Colors.grey[200],
|
||||||
// color: isDarkTheme ? Color(0xFF3B3C3F) : Colors.grey[200],
|
// color: isDarkTheme ? Color(0xFF3B3C3F) : Colors.grey[200],
|
||||||
color: isDarkTheme ? Color(0xFF333333) : Colors.grey[200],
|
color: isDarkTheme ? Colors.black : Colors.grey[200],
|
||||||
width: screenWidth,
|
width: screenWidth,
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
|
|||||||
@ -338,8 +338,8 @@ class _FeedbackFormState extends ConsumerState<FeedbackForm>
|
|||||||
context.go('/myhomepage'); // Show exit confirmation dialog
|
context.go('/myhomepage'); // Show exit confirmation dialog
|
||||||
},
|
},
|
||||||
child: BaseScaffold(
|
child: BaseScaffold(
|
||||||
backgroundColor: isDarkTheme ? Color(0xFF111111) : Colors.white,
|
backgroundColor: isDarkTheme ? Colors.black : Colors.white,
|
||||||
appbarColor: isDarkTheme ? Color(0xFF111111) : Colors.white,
|
appbarColor: isDarkTheme ? Colors.black : Colors.white,
|
||||||
// backgroundColor: isDarkTheme ? Color(0xFF333333) : Color(0xFF414042),
|
// backgroundColor: isDarkTheme ? Color(0xFF333333) : Color(0xFF414042),
|
||||||
// appbarColor: isDarkTheme ? Color(0xFF333333) : Color(0xFF414042),
|
// appbarColor: isDarkTheme ? Color(0xFF333333) : Color(0xFF414042),
|
||||||
|
|
||||||
|
|||||||
@ -313,8 +313,8 @@ class _NotificationPageState extends ConsumerState<NotificationPage> {
|
|||||||
context.go('/myhomepage');
|
context.go('/myhomepage');
|
||||||
},
|
},
|
||||||
child: BaseScaffold(
|
child: BaseScaffold(
|
||||||
backgroundColor: isDarkTheme ? Color(0xFF111111) : Colors.white,
|
backgroundColor: isDarkTheme ? Colors.black : Colors.white,
|
||||||
appbarColor: isDarkTheme ? Color(0xFF111111) : Colors.white,
|
appbarColor: isDarkTheme ? Colors.black : Colors.white,
|
||||||
title: Text(
|
title: Text(
|
||||||
context.translate(
|
context.translate(
|
||||||
'Notification $notificationCount',
|
'Notification $notificationCount',
|
||||||
@ -330,7 +330,7 @@ class _NotificationPageState extends ConsumerState<NotificationPage> {
|
|||||||
? Container(
|
? Container(
|
||||||
// color: Color(0x98FFFCE5), // Semi-transparent background
|
// color: Color(0x98FFFCE5), // Semi-transparent background
|
||||||
color: isDarkTheme
|
color: isDarkTheme
|
||||||
? Color(0xFF111111)
|
? Colors.black
|
||||||
: Color(0x98FFFCE5), // Semi-transparent background
|
: Color(0x98FFFCE5), // Semi-transparent background
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
@ -435,7 +435,7 @@ class TabBarHeader extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
color: isDarkTheme ? Color(0xFF111111) : Colors.white,
|
color: isDarkTheme ? Colors.black : Colors.white,
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
|
|||||||
@ -211,8 +211,8 @@ class _NotificationDetailsState extends ConsumerState<NotificationDetails> {
|
|||||||
context.go('/notification');
|
context.go('/notification');
|
||||||
},
|
},
|
||||||
child: BaseScaffold(
|
child: BaseScaffold(
|
||||||
backgroundColor: isDarkTheme ? Color(0xFF111111) : Colors.white,
|
backgroundColor: isDarkTheme ? Colors.black : Colors.white,
|
||||||
appbarColor: isDarkTheme ? Color(0xFF111111) : Colors.white,
|
appbarColor: isDarkTheme ? Colors.black : Colors.white,
|
||||||
title: Text(
|
title: Text(
|
||||||
context.translate(
|
context.translate(
|
||||||
'Notification',
|
'Notification',
|
||||||
|
|||||||
@ -99,15 +99,15 @@ class _UserguideState extends ConsumerState<Userguide> {
|
|||||||
},
|
},
|
||||||
child: BaseScaffold(
|
child: BaseScaffold(
|
||||||
showDivider: true,
|
showDivider: true,
|
||||||
bottomColor: isDarkTheme ? Color(0xFF111111) : Colors.white,
|
bottomColor: isDarkTheme ? Colors.black : Colors.white,
|
||||||
// dividerColor: isDarkTheme ? Color(0xFF111111) : Colors.grey[300],
|
// dividerColor: isDarkTheme ? Color(0xFF111111) : Colors.grey[300],
|
||||||
dividerColor: isDarkTheme ? Colors.grey : Colors.grey[300],
|
dividerColor: isDarkTheme ? Colors.grey : Colors.grey[300],
|
||||||
appbarColor: isDarkTheme ? Color(0xFF111111) : Colors.white,
|
appbarColor: isDarkTheme ? Colors.black: Colors.white,
|
||||||
title: Text(AppLocalizations.of(context)!.guide_title,
|
title: Text(AppLocalizations.of(context)!.guide_title,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: isDarkTheme ? Colors.white : Color(0xFF414042))),
|
color: isDarkTheme ? Colors.white : Color(0xFF414042))),
|
||||||
body: Container(
|
body: Container(
|
||||||
color: isDarkTheme ? Color(0xFF111111) : Colors.white,
|
color: isDarkTheme ? Colors.black : Colors.white,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20),
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20),
|
||||||
child: GridView.builder(
|
child: GridView.builder(
|
||||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||||
@ -172,7 +172,7 @@ class _HoverContainerState extends ConsumerState<HoverContainer> {
|
|||||||
width: screenWidth * 0.30,
|
width: screenWidth * 0.30,
|
||||||
margin: EdgeInsets.all(1),
|
margin: EdgeInsets.all(1),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: isDarkTheme ? Color(0xFF111111) : Colors.white,
|
color: isDarkTheme ? Colors.black : Colors.white,
|
||||||
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
boxShadow: isHovered
|
boxShadow: isHovered
|
||||||
|
|||||||
@ -1112,7 +1112,7 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
drawer: Drawer(
|
drawer: Drawer(
|
||||||
backgroundColor: isDarkTheme ? Color(0xFF111111) : Colors.white,
|
backgroundColor: isDarkTheme ? Colors.black : Colors.white,
|
||||||
child: Column(children: [
|
child: Column(children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: ListView(
|
child: ListView(
|
||||||
@ -1550,41 +1550,46 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
])),
|
])),
|
||||||
bottomNavigationBar: Stack(
|
bottomNavigationBar: Container(
|
||||||
children: [
|
decoration: BoxDecoration(
|
||||||
// if (isDarkTheme)
|
borderRadius: const BorderRadius.only(
|
||||||
// Positioned(
|
topLeft: Radius.circular(20),
|
||||||
// bottom: 0,
|
topRight: Radius.circular(20),
|
||||||
// left: 0,
|
),
|
||||||
// right: 0,
|
boxShadow: [
|
||||||
// child: Container(
|
BoxShadow(
|
||||||
// height: kBottomNavigationBarHeight + 0, // Adjust as needed
|
color: Colors.black.withValues(alpha: 0.10),
|
||||||
// decoration: BoxDecoration(
|
blurRadius: 16,
|
||||||
// image: DecorationImage(
|
spreadRadius: 1,
|
||||||
// image: AssetImage(
|
offset: const Offset(0, -2),
|
||||||
// 'assets/dark_bg.png'), // your dark mode image
|
),
|
||||||
// fit: BoxFit.cover,
|
],
|
||||||
// ),
|
),
|
||||||
// ),
|
child: ClipRRect(
|
||||||
// ),
|
borderRadius: const BorderRadius.only(
|
||||||
// ),
|
topLeft: Radius.circular(20),
|
||||||
BottomNavigationBar(
|
topRight: Radius.circular(20),
|
||||||
|
),
|
||||||
|
child: BottomNavigationBar(
|
||||||
backgroundColor: isDarkTheme ? Color(0xFF000000) : Colors.white,
|
backgroundColor: isDarkTheme ? Color(0xFF000000) : Colors.white,
|
||||||
currentIndex: _getSelectedIndex(currentRoute),
|
currentIndex: _getSelectedIndex(currentRoute),
|
||||||
onTap: (index) => _onItemTapped(context, index),
|
onTap: (index) => _onItemTapped(context, index),
|
||||||
type: BottomNavigationBarType.fixed,
|
type: BottomNavigationBarType.fixed,
|
||||||
|
elevation: 0,
|
||||||
items: [
|
items: [
|
||||||
BottomNavigationBarItem(
|
BottomNavigationBarItem(
|
||||||
icon: Padding(
|
icon: Padding(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(bottom: 4),
|
||||||
bottom: 4), // Adjust this for spacing
|
child: SizedBox(
|
||||||
child: Image.asset(
|
width: 24,
|
||||||
BottomBarAssetIconPath.home,
|
height: 24,
|
||||||
color: _getSelectedIndex(currentRoute) == 0
|
child: Image.asset(
|
||||||
? (isDarkTheme ? Color(0xFFFFFFFF) : Colors.black)
|
BottomBarAssetIconPath.home,
|
||||||
: Color(0xFF989898),
|
fit: BoxFit.contain,
|
||||||
width: 23.98,
|
color: _getSelectedIndex(currentRoute) == 0
|
||||||
height: 25,
|
? Color(0xFFAA8E83)
|
||||||
|
: Color(0xFF989898),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// label: 'Home',
|
// label: 'Home',
|
||||||
@ -1593,15 +1598,17 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
|
|||||||
BottomNavigationBarItem(
|
BottomNavigationBarItem(
|
||||||
// icon: Icon(Icons.map),
|
// icon: Icon(Icons.map),
|
||||||
icon: Padding(
|
icon: Padding(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(bottom: 4),
|
||||||
bottom: 4), // Adjust this for spacing
|
child: SizedBox(
|
||||||
child: Image.asset(
|
width: 24,
|
||||||
BottomBarAssetIconPath.uaeMap,
|
height: 24,
|
||||||
color: _getSelectedIndex(currentRoute) == 1
|
child: Image.asset(
|
||||||
? (isDarkTheme ? Color(0xFFFFFFFF) : Colors.black)
|
BottomBarAssetIconPath.uaeMap,
|
||||||
: Color(0xFF989898),
|
fit: BoxFit.contain,
|
||||||
width: 23.98,
|
color: _getSelectedIndex(currentRoute) == 1
|
||||||
height: 25,
|
? Color(0xFFAA8E83)
|
||||||
|
: Color(0xFF989898),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// label: 'UAE Numbers'
|
// label: 'UAE Numbers'
|
||||||
@ -1609,15 +1616,17 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
|
|||||||
),
|
),
|
||||||
BottomNavigationBarItem(
|
BottomNavigationBarItem(
|
||||||
icon: Padding(
|
icon: Padding(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(bottom: 4),
|
||||||
bottom: 4), // Adjust this for spacing
|
child: SizedBox(
|
||||||
child: Image.asset(
|
width: 24,
|
||||||
BottomBarAssetIconPath.ranking,
|
height: 24,
|
||||||
color: _getSelectedIndex(currentRoute) == 2
|
child: Image.asset(
|
||||||
? (isDarkTheme ? Color(0xFFFFFFFF) : Colors.black)
|
BottomBarAssetIconPath.ranking,
|
||||||
: Color(0xFF989898),
|
fit: BoxFit.contain,
|
||||||
width: 23.98,
|
color: _getSelectedIndex(currentRoute) == 2
|
||||||
height: 25,
|
? Color(0xFFAA8E83)
|
||||||
|
: Color(0xFF989898),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// label: 'Competitiveness',
|
// label: 'Competitiveness',
|
||||||
@ -1625,15 +1634,17 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
|
|||||||
),
|
),
|
||||||
BottomNavigationBarItem(
|
BottomNavigationBarItem(
|
||||||
icon: Padding(
|
icon: Padding(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(bottom: 4),
|
||||||
bottom: 4), // Adjust this for spacing
|
child: SizedBox(
|
||||||
child: Image.asset(
|
width: 24,
|
||||||
BottomBarAssetIconPath.globe,
|
height: 24,
|
||||||
color: _getSelectedIndex(currentRoute) == 3
|
child: Image.asset(
|
||||||
? (isDarkTheme ? Color(0xFFFFFFFF) : Colors.black)
|
BottomBarAssetIconPath.globe,
|
||||||
: Color(0xFF989898),
|
fit: BoxFit.contain,
|
||||||
width: 23.98,
|
color: _getSelectedIndex(currentRoute) == 3
|
||||||
height: 25,
|
? Color(0xFFAA8E83)
|
||||||
|
: Color(0xFF989898),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// label: 'Country Profile',
|
// label: 'Country Profile',
|
||||||
@ -1641,7 +1652,7 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
key: bottomNavKey,
|
key: bottomNavKey,
|
||||||
selectedItemColor: isDarkTheme ? Color(0xFFFFFFFF) : Colors.black,
|
selectedItemColor: Color(0xFFAA8E83),
|
||||||
unselectedItemColor: Color(0xFF989898),
|
unselectedItemColor: Color(0xFF989898),
|
||||||
selectedLabelStyle: TextStyle(
|
selectedLabelStyle: TextStyle(
|
||||||
fontFamily: context.translate(
|
fontFamily: context.translate(
|
||||||
@ -1649,6 +1660,7 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
|
|||||||
'NotoKufi',
|
'NotoKufi',
|
||||||
),
|
),
|
||||||
fontSize: 10, // Font size for unselected label
|
fontSize: 10, // Font size for unselected label
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
),
|
),
|
||||||
unselectedLabelStyle: TextStyle(
|
unselectedLabelStyle: TextStyle(
|
||||||
fontFamily: context.translate(
|
fontFamily: context.translate(
|
||||||
@ -1659,7 +1671,7 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
|
|||||||
),
|
),
|
||||||
showUnselectedLabels: true,
|
showUnselectedLabels: true,
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
// BottomNavigationBar(
|
// BottomNavigationBar(
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
name: uae_stat
|
name: uae_stat
|
||||||
description: "View statistics about the UAE from the Federal Center for Statistics and Competitiveness."
|
description: "View statistics about the UAE from the Federal Center for Statistics and Competitiveness."
|
||||||
publish_to: "none"
|
publish_to: "none"
|
||||||
#version: 1.2.17+25
|
#version: 1.2.18+26
|
||||||
version: 1.2.15+23
|
version: 1.2.16+24
|
||||||
#version: 1.0.16+17
|
#version: 1.0.16+17
|
||||||
#version: 1.0.6+6
|
#version: 1.0.6+6
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user