diff --git a/LICENSE b/LICENSE
index 81a03efb..354acafe 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
BSD 3-Clause License
-Copyright (c) 2020-2022, The @ Foundation
+Copyright (c) 2022-2022, The Atsign Foundation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/README.md b/README.md
index 10f5b17b..57a4f8af 100644
--- a/README.md
+++ b/README.md
@@ -14,12 +14,12 @@ confidential information without worrying about your data being stored on
a server in the cloud.
This repo holds the open source code for the @mosphere PRO app, to serve as
-an example of apps that can be build on the @ Platform.
+an example of apps that can be build on the atPlatform.
## Developer
The purpose of this repo is primarily to be an example of what can be done
-with the @ Platform. So if you're a developer take a look at the code here.
+with the atPlatform. So if you're a developer take a look at the code here.
### Contributor
diff --git a/code_of_conduct.md b/code_of_conduct.md
index 82431d4e..b6d43a95 100644
--- a/code_of_conduct.md
+++ b/code_of_conduct.md
@@ -1,6 +1,6 @@
-# The @ Foundation Code of Conduct
+# The Atsign Foundation Code of Conduct
Based on
[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.0-4baaaa.svg)](code_of_conduct.md)
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index 1dcff344..1f7c878e 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -415,7 +415,7 @@
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = "Share Extension/Share Extension.entitlements";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 43;
+ CURRENT_PROJECT_VERSION = 44;
DEVELOPMENT_TEAM = 5XUSS6C2DF;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = "Share Extension/Info.plist";
@@ -448,7 +448,7 @@
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = "Share Extension/Share Extension.entitlements";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 43;
+ CURRENT_PROJECT_VERSION = 44;
DEVELOPMENT_TEAM = 5XUSS6C2DF;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = "Share Extension/Info.plist";
@@ -478,7 +478,7 @@
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = "Share Extension/Share Extension.entitlements";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 43;
+ CURRENT_PROJECT_VERSION = 44;
DEVELOPMENT_TEAM = 5XUSS6C2DF;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = "Share Extension/Info.plist";
@@ -560,7 +560,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 43;
+ CURRENT_PROJECT_VERSION = 44;
DEVELOPMENT_TEAM = 5XUSS6C2DF;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@@ -708,7 +708,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 43;
+ CURRENT_PROJECT_VERSION = 44;
DEVELOPMENT_TEAM = 5XUSS6C2DF;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@@ -747,7 +747,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 43;
+ CURRENT_PROJECT_VERSION = 44;
DEVELOPMENT_TEAM = 5XUSS6C2DF;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
diff --git a/lib/desktop_screens/desktop_common_widgets/dektop_custom_person_tile.dart b/lib/desktop_screens/desktop_common_widgets/dektop_custom_person_tile.dart
index 0a8abb27..7a3eb714 100644
--- a/lib/desktop_screens/desktop_common_widgets/dektop_custom_person_tile.dart
+++ b/lib/desktop_screens/desktop_common_widgets/dektop_custom_person_tile.dart
@@ -44,7 +44,7 @@ class DesktopCustomPersonVerticalTile extends StatelessWidget {
)
: ContactInitial(
initials: title ?? ' ',
- size: 30,
+ size: 50,
maxSize: (80.0 - 30.0),
minSize: 50,
),
diff --git a/lib/desktop_screens/desktop_welcome_screen/desktop_welcome_screen.dart b/lib/desktop_screens/desktop_welcome_screen/desktop_welcome_screen.dart
index 369437c4..8fb3d2fd 100644
--- a/lib/desktop_screens/desktop_welcome_screen/desktop_welcome_screen.dart
+++ b/lib/desktop_screens/desktop_welcome_screen/desktop_welcome_screen.dart
@@ -623,13 +623,14 @@ class SideBarIcon extends StatelessWidget {
}
Future _launchInBrowser(String url) async {
- if (await canLaunchUrl(Uri(path: url))) {
+ try {
await launchUrl(
- Uri(path: url),
- // forceSafariVC: false,
- // forceWebView: false,
+ Uri(
+ scheme: 'https',
+ path: url,
+ ),
);
- } else {
+ } catch (e) {
throw 'Could not launch $url';
}
}
diff --git a/lib/desktop_screens/trusted_sender/desktop_empty_trusted_sender.dart b/lib/desktop_screens/trusted_sender/desktop_empty_trusted_sender.dart
index 43ae95fa..2e145bba 100644
--- a/lib/desktop_screens/trusted_sender/desktop_empty_trusted_sender.dart
+++ b/lib/desktop_screens/trusted_sender/desktop_empty_trusted_sender.dart
@@ -129,7 +129,7 @@ class _DesktopEmptySenderState extends State {
_list.forEach((element) async {
if (element!.contact != null) {
await provider
- .addTrustedContacts(element.contact);
+ .addTrustedContacts(element.contact!);
}
});
await provider.setTrustedContact();
diff --git a/lib/desktop_screens/trusted_sender/desktop_trusted_sender.dart b/lib/desktop_screens/trusted_sender/desktop_trusted_sender.dart
index 6962c08c..090dad37 100644
--- a/lib/desktop_screens/trusted_sender/desktop_trusted_sender.dart
+++ b/lib/desktop_screens/trusted_sender/desktop_trusted_sender.dart
@@ -1,6 +1,7 @@
+import 'dart:typed_data';
+
+import 'package:at_contacts_group_flutter/at_contacts_group_flutter.dart';
import 'package:at_contacts_group_flutter/screens/group_contact_view/group_contact_view.dart';
-import 'package:atsign_atmosphere_pro/desktop_routes/desktop_route_names.dart';
-import 'package:atsign_atmosphere_pro/desktop_routes/desktop_routes.dart';
import 'package:atsign_atmosphere_pro/desktop_screens/desktop_common_widgets/dektop_custom_person_tile.dart';
import 'package:atsign_atmosphere_pro/desktop_screens/desktop_common_widgets/desktop_custom_input_field.dart';
import 'package:atsign_atmosphere_pro/desktop_screens/desktop_common_widgets/desktop_header.dart';
@@ -9,6 +10,7 @@ import 'package:atsign_atmosphere_pro/screens/common_widgets/provider_callback.d
import 'package:atsign_atmosphere_pro/screens/common_widgets/provider_handler.dart';
import 'package:atsign_atmosphere_pro/screens/trusted_contacts/widgets/remove_trusted_contact_dialog.dart';
import 'package:at_common_flutter/services/size_config.dart';
+import 'package:atsign_atmosphere_pro/services/common_utility_functions.dart';
import 'package:atsign_atmosphere_pro/utils/colors.dart';
import 'package:atsign_atmosphere_pro/utils/text_strings.dart';
import 'package:atsign_atmosphere_pro/view_models/trusted_sender_view_model.dart';
@@ -122,7 +124,16 @@ class _DesktopTrustedSenderState extends State {
spacing: 30.0,
children: List.generate(
provider.trustedContacts.length, (index) {
- if (provider.trustedContacts[index]!.atSign!
+ Uint8List? byteImage;
+
+ if (provider.trustedContacts[index].atSign !=
+ null) {
+ byteImage = CommonUtilityFunctions()
+ .getCachedContactImage(provider
+ .trustedContacts[index].atSign!);
+ }
+
+ if (provider.trustedContacts[index].atSign!
.contains(searchText)) {
return InkWell(
onTap: () {
@@ -134,17 +145,21 @@ class _DesktopTrustedSenderState extends State {
TextStrings().removeTrustedSender,
contact: AtContact(
atSign: provider
- .trustedContacts[index]!
+ .trustedContacts[index]
.atSign),
),
);
},
child: DesktopCustomPersonVerticalTile(
- title: provider
- .trustedContacts[index]!.atSign,
- subTitle: provider
- .trustedContacts[index]!.atSign,
- showCancelIcon: false),
+ title: provider
+ .trustedContacts[index].atSign,
+ subTitle: provider
+ .trustedContacts[index].atSign,
+ showCancelIcon: false,
+ showImage:
+ byteImage != null ? true : false,
+ image: byteImage,
+ ),
);
} else {
return SizedBox();
@@ -163,6 +178,9 @@ class _DesktopTrustedSenderState extends State {
showGroups: false,
showContacts: true,
isDesktop: true,
+ contactSelectedHistory: provider.trustedContacts
+ .map((e) => GroupContactsModel(contact: e))
+ .toList(),
selectedList: (_list) {
providerCallback(
context,
@@ -170,7 +188,7 @@ class _DesktopTrustedSenderState extends State {
_list.forEach((element) async {
if (element!.contact != null) {
await provider.addTrustedContacts(
- element.contact);
+ element.contact!);
}
});
diff --git a/lib/screens/common_widgets/app_bar.dart b/lib/screens/common_widgets/app_bar.dart
index 5ff1f394..05234e20 100644
--- a/lib/screens/common_widgets/app_bar.dart
+++ b/lib/screens/common_widgets/app_bar.dart
@@ -164,19 +164,24 @@ class _CustomAppBarState extends State {
}
}
} else if (widget.isTrustedContactScreen) {
+ var trustedContacts =
+ Provider.of(
+ NavService.navKey.currentContext!,
+ listen: false)
+ .trustedContacts;
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ContactsScreen(
asSelectionScreen: true,
- context: NavService.navKey.currentContext,
+ selectedContactsHistory: trustedContacts,
selectedList: (s) async {
s.forEach((element) async {
await Provider.of<
TrustedContactProvider>(
context,
listen: false)
- .addTrustedContacts(element);
+ .addTrustedContacts(element!);
});
await Provider.of(
context,
diff --git a/lib/screens/common_widgets/website_webview.dart b/lib/screens/common_widgets/website_webview.dart
index 479b128a..ace2617c 100644
--- a/lib/screens/common_widgets/website_webview.dart
+++ b/lib/screens/common_widgets/website_webview.dart
@@ -4,6 +4,8 @@ import 'package:atsign_atmosphere_pro/services/snackbar_service.dart';
import 'package:atsign_atmosphere_pro/utils/colors.dart';
import 'package:atsign_atmosphere_pro/utils/text_strings.dart';
import 'package:atsign_atmosphere_pro/utils/text_styles.dart';
+import 'package:flutter/foundation.dart';
+import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:webview_flutter/webview_flutter.dart';
@@ -72,6 +74,11 @@ class _WebsiteScreenState extends State {
WebView(
initialUrl: widget.url,
javascriptMode: JavascriptMode.unrestricted,
+ gestureRecognizers: {
+ Factory(
+ () => VerticalDragGestureRecognizer()..onUpdate = (_) {},
+ )
+ },
onPageFinished: (test1) {
this.setState(() {
loading = false;
diff --git a/lib/screens/trusted_contacts/trusted_contacts.dart b/lib/screens/trusted_contacts/trusted_contacts.dart
index 0cc99ab3..28bf1c57 100644
--- a/lib/screens/trusted_contacts/trusted_contacts.dart
+++ b/lib/screens/trusted_contacts/trusted_contacts.dart
@@ -2,7 +2,6 @@ import 'dart:typed_data';
import 'package:at_contacts_flutter/screens/contacts_screen.dart';
import 'package:atsign_atmosphere_pro/services/common_utility_functions.dart';
-import 'package:atsign_atmosphere_pro/services/navigation_service.dart';
import 'package:atsign_atmosphere_pro/utils/text_strings.dart'
as pro_text_strings;
import 'package:atsign_atmosphere_pro/utils/colors.dart' as pro_color_constants;
@@ -78,6 +77,7 @@ class _TrustedContactsState extends State {
pro_text_strings.TextStrings()
.addTrustedSender,
style: CustomTextStyles.secondaryRegular16,
+ textAlign: TextAlign.center,
),
SizedBox(
height: 25.toHeight,
@@ -95,13 +95,13 @@ class _TrustedContactsState extends State {
builder: (context) =>
ContactsScreen(
asSelectionScreen: true,
- context: NavService
- .navKey.currentContext,
+ selectedContactsHistory:
+ provider.trustedContacts,
selectedList: (s) async {
s.forEach((element) async {
await provider
.addTrustedContacts(
- element);
+ element!);
});
await provider
.setTrustedContact();
@@ -117,12 +117,11 @@ class _TrustedContactsState extends State {
itemBuilder: (context, index) {
Uint8List? byteImage;
- if (provider.trustedContacts[index]!
- .tags!['image'] !=
+ if (provider.trustedContacts[index].atSign !=
null) {
byteImage = CommonUtilityFunctions()
- .getContactImage(
- provider.trustedContacts[index]!);
+ .getCachedContactImage(provider
+ .trustedContacts[index].atSign!);
}
return ContactListTile(
@@ -145,18 +144,18 @@ class _TrustedContactsState extends State {
onAdd: () {},
onRemove: () {},
name:
- provider.trustedContacts[index]!.tags !=
+ provider.trustedContacts[index].tags !=
null &&
- provider.trustedContacts[index]!
+ provider.trustedContacts[index]
.tags!['name'] !=
null
- ? provider.trustedContacts[index]!
+ ? provider.trustedContacts[index]
.tags!['name']
: provider
- .trustedContacts[index]!.atSign!
+ .trustedContacts[index].atSign!
.substring(1),
atSign:
- provider.trustedContacts[index]!.atSign,
+ provider.trustedContacts[index].atSign,
image: byteImage != null
? CustomCircleAvatar(
byteImage: byteImage,
@@ -164,7 +163,7 @@ class _TrustedContactsState extends State {
)
: ContactInitial(
initials: provider
- .trustedContacts[index]!.atSign,
+ .trustedContacts[index].atSign,
),
);
},
diff --git a/lib/services/backend_service.dart b/lib/services/backend_service.dart
index 9822fb65..13e1071c 100644
--- a/lib/services/backend_service.dart
+++ b/lib/services/backend_service.dart
@@ -217,7 +217,7 @@ class BackendService {
Provider.of(context, listen: false);
trustedContactProvider.trustedContacts.forEach((element) {
- if (element!.atSign == fromAtSign) {
+ if (element.atSign == fromAtSign) {
trustedSender = true;
}
});
diff --git a/lib/services/overlay_service.dart b/lib/services/overlay_service.dart
index 3f7a078b..453f9292 100644
--- a/lib/services/overlay_service.dart
+++ b/lib/services/overlay_service.dart
@@ -87,13 +87,14 @@ class OverlayService {
fontWeight: FontWeight.normal,
),
),
- SizedBox(height: 5),
- Text(
- getFileUploadMessage(
- provider.sentFileTransferProgress,
- ),
- style: TextStyle(fontSize: 12.toFont),
- ),
+ //// Not showing estimated file upload time.
+ // SizedBox(height: 5),
+ // Text(
+ // getFileUploadMessage(
+ // provider.sentFileTransferProgress,
+ // ),
+ // style: TextStyle(fontSize: 12.toFont),
+ // ),
],
),
),
diff --git a/lib/utils/constants.dart b/lib/utils/constants.dart
index f2f88260..775cb475 100644
--- a/lib/utils/constants.dart
+++ b/lib/utils/constants.dart
@@ -15,13 +15,13 @@ class MixedConstants {
static const int ROOT_PORT = 64;
- static const String TERMS_CONDITIONS = 'https://atsign.com/terms-conditions/';
+ static const String TERMS_CONDITIONS = 'atsign.com/terms-conditions/';
static const String FILEBIN_URL = 'https://ck6agzxiog6kmb.atsign.com/';
// static const String PRIVACY_POLICY = 'https://atsign.com/privacy-policy/';
static const String PRIVACY_POLICY =
"https://atsign.com/apps/atmosphere/atmosphere-privacy/";
- static const String FAQ = "https://atsign.com/faqs/";
+ static const String FAQ = "atsign.com/faqs/";
static const MACOS_STORE_LINK = 'https://apps.apple.com/app/id1550936444';
diff --git a/lib/view_models/trusted_sender_view_model.dart b/lib/view_models/trusted_sender_view_model.dart
index 2565327c..0c679177 100644
--- a/lib/view_models/trusted_sender_view_model.dart
+++ b/lib/view_models/trusted_sender_view_model.dart
@@ -1,7 +1,6 @@
import 'dart:convert';
import 'package:at_client_mobile/at_client_mobile.dart';
-import 'package:at_commons/at_commons.dart';
import 'package:at_contact/at_contact.dart';
import 'package:atsign_atmosphere_pro/services/backend_service.dart';
import 'package:atsign_atmosphere_pro/view_models/base_model.dart';
@@ -11,14 +10,17 @@ class TrustedContactProvider extends BaseModel {
static TrustedContactProvider _instance = TrustedContactProvider._();
factory TrustedContactProvider() => _instance;
String AddTrustedContacts = 'add_trusted_contacts';
- List trustedContacts = [];
+ List trustedContacts = [];
bool trustedContactOperation = false;
List trustedNames = [];
String GetTrustedContacts = 'get_trusted_contacts';
- List fetchedTrustedContact = [];
+ List fetchedTrustedContact = [];
BackendService backendService = BackendService.getInstance();
- addTrustedContacts(AtContact? trustedContact) async {
+ addTrustedContacts(AtContact trustedContact) async {
+ if (trustedContact.tags != null && trustedContact.tags!['image'] != null) {
+ trustedContact.tags!['image'] = null;
+ }
setStatus(AddTrustedContacts, Status.Loading);
try {
diff --git a/pubspec.lock b/pubspec.lock
index 3aa942fc..f41a191b 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -63,14 +63,14 @@ packages:
name: at_client
url: "https://pub.dartlang.org"
source: hosted
- version: "3.0.26"
+ version: "3.0.28"
at_client_mobile:
dependency: "direct main"
description:
name: at_client_mobile
url: "https://pub.dartlang.org"
source: hosted
- version: "3.1.17"
+ version: "3.1.18"
at_common_flutter:
dependency: "direct main"
description:
@@ -84,14 +84,14 @@ packages:
name: at_commons
url: "https://pub.dartlang.org"
source: hosted
- version: "3.0.17"
+ version: "3.0.18"
at_contact:
dependency: "direct main"
description:
name: at_contact
url: "https://pub.dartlang.org"
source: hosted
- version: "3.0.6"
+ version: "3.0.7"
at_contacts_flutter:
dependency: "direct main"
description:
@@ -105,14 +105,14 @@ packages:
name: at_contacts_group_flutter
url: "https://pub.dartlang.org"
source: hosted
- version: "4.0.6"
+ version: "4.0.7"
at_lookup:
dependency: transitive
description:
name: at_lookup
url: "https://pub.dartlang.org"
source: hosted
- version: "3.0.25"
+ version: "3.0.26"
at_onboarding_flutter:
dependency: "direct main"
description:
@@ -126,14 +126,14 @@ packages:
name: at_persistence_secondary_server
url: "https://pub.dartlang.org"
source: hosted
- version: "3.0.27"
+ version: "3.0.29"
at_persistence_spec:
dependency: transitive
description:
name: at_persistence_spec
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.5"
+ version: "2.0.6"
at_server_status:
dependency: transitive
description:
@@ -648,6 +648,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "3.2.0"
+ image_compression:
+ dependency: transitive
+ description:
+ name: image_compression
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.0.3"
internet_connection_checker:
dependency: transitive
description:
@@ -850,7 +857,7 @@ packages:
name: path_provider_android
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.14"
+ version: "2.0.16"
path_provider_ios:
dependency: transitive
description:
@@ -1032,7 +1039,7 @@ packages:
name: share_plus
url: "https://pub.dartlang.org"
source: hosted
- version: "4.0.8"
+ version: "4.0.10"
share_plus_linux:
dependency: transitive
description:
@@ -1137,7 +1144,7 @@ packages:
name: shelf_packages_handler
url: "https://pub.dartlang.org"
source: hosted
- version: "3.0.0"
+ version: "3.0.1"
shelf_static:
dependency: transitive
description:
@@ -1261,7 +1268,7 @@ packages:
name: url_launcher
url: "https://pub.dartlang.org"
source: hosted
- version: "6.1.3"
+ version: "6.1.4"
url_launcher_android:
dependency: transitive
description:
@@ -1296,7 +1303,7 @@ packages:
name: url_launcher_platform_interface
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.5"
+ version: "2.1.0"
url_launcher_web:
dependency: transitive
description:
@@ -1331,7 +1338,7 @@ packages:
name: video_compress
url: "https://pub.dartlang.org"
source: hosted
- version: "3.1.0"
+ version: "3.1.1"
video_thumbnail:
dependency: "direct main"
description:
@@ -1380,7 +1387,7 @@ packages:
name: webview_flutter_android
url: "https://pub.dartlang.org"
source: hosted
- version: "2.8.11"
+ version: "2.8.14"
webview_flutter_platform_interface:
dependency: transitive
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 2842716f..9f95c888 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -17,7 +17,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# Mobile version
-version: 1.0.7+43
+version: 1.0.7+44
# Desktop version macos
# version: 1.0.1+19
@@ -52,7 +52,7 @@ dependencies:
share_plus: ^4.0.1
url_launcher: ^6.0.20
video_thumbnail: ^0.4.6
- webview_flutter: ^3.0.1
+ webview_flutter: ^3.0.4
http: ^0.13.4
package_info_plus: ^1.4.2
fluttertoast: ^8.0.9
@@ -71,7 +71,7 @@ dependencies:
at_onboarding_flutter: ^4.0.3
at_backupkey_flutter: ^4.0.1
at_contacts_flutter: ^4.0.5
- at_contacts_group_flutter: ^4.0.6
+ at_contacts_group_flutter: ^4.0.7
local_notifier: ^0.1.1
at_sync_ui_flutter: ^1.0.3