Why use RepositoryProvider over BlocProvider - bloc

Reading the doc for BloC why use RepositoryProvider over BlocProvider.
Yes, you could call a service etc. on a Repository, but do you know what are the toughts of having a RepositoryProvide - when you could react to events in a BloC and call the Repository accordingly?
RepositoryProvider:
RepositoryProvider(
create: (context) => RepositoryA(),
child: ChildA(),
);
...
context.read<RepositoryA>().CallServivceSomething()
...
BlocProvidere:
BlocProvider(
create: (BuildContext context) => BlocA(),
child: ChildA(),
);
...
context.read<BlocA>().add(NewEvent(SomeStateToCallService()));
...
Thanks

Related

Is there a way to stop CustomScrollView from automatically scrolling down when Keyboard is activated?

It seems that whenever I focus on a TextField (that sits inside a SliverPersistentHeader) SliverList+SliverPersistentHeader scrolls down. I have created some mockups of what I mean below:
So in this mockup, the user starts off at the first layout, scrolls up to continue viewing the lsit and then when they click on the TextField, the whole thing shifts down. Any way to stop that?
I have also attached my basic Scaffold code for your perusal:
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Consts.coMainBackground,
resizeToAvoidBottomInset: false,
body: CustomScrollView(
slivers: <Widget>[
_sliverAppBar(),
_makeHeader(),
BlocBuilder<AllPersonsBloc, AllPersonsState>(
builder: (context, state) {
if (state is AllPersonsLoading) {
return _buildLoading();
} else if (state is AllPersonsLoaded) {
return _sliverList(context, state.persons);
} else if (state is AllPersonsError) {
return _buildErrorMessage(state.message);
} else {
return _buildErrorMessage('Unknown error!');
}
},
),
],
),
);
}
the _makeHeader creates the SliverPersistentHeader and the rest I think should make sense based on names.
Your help would greatly appreciated :)
Thanks!
Got it...
return SliverAppBar(
automaticallyImplyLeading: false,
backgroundColor: Consts.coForestGreenBackground,
expandedHeight: 207,
titleSpacing: 0,
elevation: 0,
floating: false,
pinned: false,
snap: false,
flexibleSpace: FlexibleSpaceBar(
Note that the item is not pinned/floated/snapped. Then its important that the input (TextField in this case) has a scrollPadding (top) of 0.
Your scaffold will ALSO need an appbar. So technically you have an appbar and a SliverAppBar but the SliverAppBar is just to wrap the flexibleSpace.
Or rather, zero after any padding on the element it self. In my case its 40 since the TextField has a top padding of 30 and another 10 from the element that contains it etc.

Dart / Flutter - Validating a string for URL

I'm trying to create a system in which I can validate a string to check if it's a url or not. (https://www.google.com/)
I found the flutter package validator but this isn't dart 2 compatible, so won't be compatible with my code.
Similarly named, I also found the validators package but I can't seem to get it working correctly with my code, as it throws the following error; (hope you like my project name ;)
Because every version of flutter_test from sdk depends on test 1.3.0
and every version of validators depends on test ^1.3.3, flutter_test from sdk is incompatible with validators.
So, because gucci depends on both validators ^1.0.0+1 and flutter_test any from sdk, version solving failed.
Unable to reload your application because "flutter packages get" failed to update package dependencies.
Exception: pub get failed (1)
If you could either find a fix for validators so that it doesn't throw this error and thus works correctly with my code, or suggest another method of validating a string to be URL compliant that would be great.
Thanks
Edit - My pubspec.yaml file
name: gucci
description: A new Flutter project.
dependencies:
flutter:
sdk: flutter
cupertino_icons:
barcode_scan:
gradient_app_bar:
url_launcher:
validate: ^1.7.0
dev_dependencies:
flutter_test:
sdk: flutter
fonts:
- family: PlayfairDisplay
fonts:
- asset: fonts/PlayfairDisplay-BoldItalic.ttf
- family: Kanit
fonts:
- asset: fonts/Kanit-ExtraBoldItalic.ttf
- family: Poppins
fonts:
- asset: fonts/Poppins-BoldItalic.ttf
- family: PoppinsLightItalic
fonts:
- asset: fonts/Poppins-LightItalic.ttf
- family: PoppinsMediumItalic
fonts:
- asset: fonts/Poppins-MediumItalic.ttf
To check Valid URL string you just have to use Uri.parse() like below.
bool _validURL = Uri.parse(_adVertData.webLink).isAbsolute;
Just check value of _validURL
Uri.tryParse(mystring)?.hasAbsolutePath ?? false;
Some example results:
url
result
'https://stackoverflow.com/questions/52975739/dart-flutter-validating-a-string-for-url'
true
asd
false
asd:asd
false
%EMPTY_STRING%
false
google.nl
false
https:
false
https://
false
https://a
false
https://a/
true
var urlPattern = r"(https?|http)://([-A-Z0-9.]+)(/[-A-Z0-9+&##/%=~_|!:,.;]*)?(\?[A-Z0-9+&##/%=~_|!:‌​,.;]*)?";
var match = new RegExp(urlPattern, caseSensitive: false).firstMatch('https://www.google.com');
You can use RegExp too.
I used the following method below. Depending on your rec, all valid URLs need to have a host (ex, google.com). If a URL does not have a host it returns an empty string (not undefined or null).
bool isURLValid = Uri.parse('https://google.com/').host.isNotEmpty;
Using .isAbsolute, as some have already reported, marks URLs such as 'http:' to be valid URLs which not.
For some reason, the validators package is requiring a pretty recent version of flutter's testing library rather than leaving it up to the application. Maybe there's a good reason for that (i.e. they're using a new feature).
The flutter engine internally requires a particular version of the flutter_test library (which is why it's generally a bad idea to specify a version of it). So to fix this you'll have to upgrade your flutter by running flutter upgrade. If you're already at the most recent version of the channel you're in, you may have to run flutter channel dev or flutter channel master to switch to a channel (branch really) that's updated more often.
I run on the dev branch/channel for the most part and while it very occasionally has problems, it doesn't happen a lot. I'd advise against using the master branch if possible though.
Validation using RegEx
String hasValidUrl(String value) {
String pattern = r'(http|https)://[\w-]+(\.[\w-]+)+([\w.,#?^=%&:/~+#-]*[\w#?^=%&/~+#-])?';
RegExp regExp = new RegExp(pattern);
if (value.length == 0) {
return 'Please enter url';
}
else if (!regExp.hasMatch(value)) {
return 'Please enter valid url';
}
return null;
}
Validation using in-built package
final Uri uri = Uri.tryParse(value);
if (!uri.hasAbsolutePath) {
return 'Please enter valid url';
}
If you want some special case like you have to validate deepLink then RegEx practice is best.
For RegExp, if you are going to find URL in a string, you can use this one.
r'^((?:.|\n)*?)((http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)([-A-Z0-9.]+)(/[-A-Z0-9+&##/%=~_|!:,.;]*)?(\?[A-Z0-9+&##/%=~_|!:‌​,.;]*)?)'
It can be used when you are highlighting URL in a string. For example in a chat app, you can highlight URL in a sent chat message.
This validates google.com, https://google.com, http://google.com all.
I'm using this way to validate Urls. In your TextFormField's use this validator. here your url should be start from www.
validator: (website) {
String pattern =
r'^((?:.|\n)*?)((http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)([-A-Z0-9.]+)(/[-A-Z0-9+&##/%=~_|!:,.;]*)?(\?[A-Z0-9+&##/%=~_|!:‌​,.;]*)?)';
RegExp regExp = RegExp(pattern);
if (website.isEmpty) {
return "Please enter your website";
} else if (!(regExp.hasMatch(website))) {
return "Website Url must be started from www";
} else {
return null;
}
},
TextEditingController urlController = TextEditingController();
String urlData = '';
static final GlobalKey<FormFieldState<String>> _orderFromkey =
GlobalKey<FormFieldState<String>>();
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
resizeToAvoidBottomInset: false,
body: Column(
children: [
appBar(label: appName),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
key: _orderFromkey,
controller: urlController,
validator: (value) {
String patttern = r"((https?:www\.)|(https?:\/\/)|(www\.))[-a-zA-Z0-9#:%._\+~#=]{1,256}\.[a-zA-Z0-9]{1,6}(\/[-a-zA-Z0-9()#:%_\+.~#?&\/=]*)?";
RegExp regExp = new RegExp(patttern);
if (!regExp.hasMatch(value!)) {
return 'Please enter valid URL';
}
},
decoration: InputDecoration(
fillColor: appColor,
labelText: "url",
labelStyle: new TextStyle(color: appColor),
contentPadding: EdgeInsets.only(left: 10, right: 10),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: appColor),
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: black),
),
hintText: 'Enter Your URL'),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: InkWell(
onTap: () {
print('_orderFromkey: ${_orderFromkey}');
final FormFieldState<String>? form =
_orderFromkey.currentState;
if (form!.validate()) {
urlData = urlController.text;
Get.toNamed('/showQr', arguments: urlData);
print('text : ${urlData}');
} else {
// _autoValidation = true;
}
},
child: Container(
width: ScreenSize.size.width * 0.6,
height: ScreenSize.size.height * 0.1,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: appColor,
),
child: const Align(
alignment: Alignment.center,
child: Text(
'Submit',
style: TextStyle(
fontSize: 20,
color: white,
fontWeight: FontWeight.w700),
textAlign: TextAlign.center,
)),
),
),
),
],
)),
);
}
You can use the url_launcher package for this.
Future<bool> checkIfUrlIsValid({required String url}) async {
if (await canLaunchUrl(Uri.parse(url))) {
return true;
}
return false;}
checkIfUrlIsValid(url: 'https://google.com'); // true;
checkIfUrlIsValid(url: 'google com'); // false;
Use this simple function then you can identify string is valid URL or not
bool isURl(String url){
return RegExp(r'^((?:.|\n)*?)((http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)([-A-Z0-9.]+)(/[-A-Z0-9+&##/%=~_|!:,.;]*)?(\?[A-Z0-9+&##/%=~_|!:‌​,.;]*)?)')
.hasMatch(url); }

adding listview.builder inside row giving an exceptions

when I try to add an listview.builder inside a row an exception appears
my code:
return new Scaffold(
appBar: new AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: new Text(widget.title),
),
body: Row(children: <Widget>[
ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.vertical,
itemCount: 3,
itemBuilder: (BuildContext context, int index) {
return Text('data');
},
)
// This trailing comma makes auto-formatting nicer for build methods.
],)
);
the exception:
══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
I/flutter ( 5949): The following assertion was thrown during performLayout():
I/flutter ( 5949): 'package:flutter/src/rendering/viewport.dart': Failed assertion: line 1597 pos 16:
I/flutter ( 5949): 'constraints.hasBoundedWidth': is not true.
I/flutter ( 5949): Either the assertion indicates an error in the framework itself, or we should provide substantially
I/flutter ( 5949): more information in this error message to help you determine and fix the underlying cause.
Wrap Expanded and then add to list.builder > physics:
const NeverScrollableScrollPhysics(),

How to write condition statements in flutter?

I wanted to learn how can I apply "if" condition in my flutter code? As I am new to dart language coding.
Suppose in a code like below, i want to add condition that if the counter's value is 1 then "You have pushed the button $_counter time" else "You have pushed the button $_counter times"
children: <Widget>[
new Text(
'You have pushed the button $_counter times:',
)/*,
new Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),*/
]
P.S. its just a simple example for me to understand how to use if condition in flutter.
For such simple cases you can use the ternary if ?: inside string interpolation:
new Text(
'You have pushed the button $_counter time${_counter != 1 ? 's' : ''}:',
)
for the case of the conditions you have just a single condition then you can use the basic ternary operators,
child: Text(
'{fee=="FREE"?"Free":fee}',
),
But if you have multiple conditions or value that need to compare from the index position(i.e. you have to fetch value and then need to put in condition) in listview then you can add method as your text value in your Widget as follows:
child: Text(
'${checkForPrice(index)}',
),
),
checkForPrice(int index) {
String strFee = data['payload']['webinar'][index]['fee'];
String finalFee = "";
if (strFee == "FREE") {
finalFee = 'FREE';
} else {
finalFee = '\$ ${data['payload']['webinar'][index]['fee']}';
}
return finalFee;}
This will definitely help you in showing data with multiple conditions.
at the first time i tried flutter i have no idea what dart language is but after some browsing i found this useful documentation. You can find anything you looking for right there including if statement that you are asking about. But i can tell you the if statement works the same as any other language such as JavaScript, Java, etc.
Edit: here i give you some example how to use it in flutter
Future<Null> toTheHomeScreen() async {
await _signInWithGoogle();
SharedPreferences sprefs = await SharedPreferences.getInstance();
if (sprefs.getString('idToken').isNotEmpty) {
new Future.delayed(new Duration(seconds: 3), () {
new CircularProgressIndicator();
Navigator.of(context).push(
new MaterialPageRoute(
builder: (BuildContext context) {
return new HomeScreen();
}
)
);
});
} else {
Navigator.of(context).pop();
}
}
the if statement check if there is any key named 'idToken' stored in sharedpref, if it not empty user will redirect to home page.
I hope this will help you.

Buddypress new profile tabs and sub tabs: How to set up url slug properly?

First of all, I’ve seen alot of people trying to do a similar task, which is simply to create a new tab, with sub tabs in the user profile menu. I’ve managed to do this, but I can’t seem to get the url slug to work properly. When I click on the first sub tab, it simply takes me back to the main page for the user profile, and when I click on any additional sub tabs I get 404 errors. I have a feeling I’m missing something pretty simple, and I’ve been trying to learn over the last couple weeks how to make this work without any luck. If someone could help guide me on how to get this working properly, I would very grateful, and I imagine many others would find this post useful in the future.
For the record the main profile tab works properly, but the sub-tabs do not.
Here is the code I currently have in my bp-custom.php file
// My Membership Profile Tab
function profile_new_nav_item() {
global $bp;
bp_core_new_nav_item(
array(
'name' => 'My Membership',
'slug' => 'my-membership',
'default_subnav_slug' => 'extra_sub_tab', // We add this submenu item below
'screen_function' => 'view_manage_tab_main'
)
);
}
add_action( 'bp_setup_nav', 'profile_new_nav_item', 10 );
function view_manage_tab_main() {
add_action( 'bp_template_content', 'bp_template_content_main_function' );
bp_core_load_template( 'template_content' );
}
function bp_template_content_main_function() {
if ( ! is_user_logged_in() ) {
wp_login_form( array( 'echo' => true ) );
}
}
function profile_new_subnav_item() {
global $bp;
bp_core_new_subnav_item( array(
'name' => 'Membership Level',
'slug' => 'extra_sub_tab',
'parent_url' => $bp->loggedin_user->domain . $bp->bp_nav[ 'extra_tab' ][ 'slug' ] . '/',
'parent_slug' => $bp->bp_nav[ 'my-membership' ][ 'slug' ],
'position' => 10,
'screen_function' => 'view_manage_sub_tab_main'
) );
}
add_action( 'bp_setup_nav', 'profile_new_subnav_item', 10 );
function view_manage_sub_tab_main() {
add_action( 'bp_template_content', 'bp_template_content_sub_function' );
bp_core_load_template( 'template_content' );
}
function bp_template_content_sub_function() {
if ( is_user_logged_in() ) {
//Add shortcode to display content in sub tab
echo do_shortcode( '[membership]' );
} else {
wp_login_form( array( 'echo' => true ) );
}
}
// My Billing Profile Tab
function profile_new_subnav_item_billing() {
global $bp;
bp_core_new_subnav_item( array(
'name' => 'Billing',
'slug' => 'extra_sub_tab_billing',
'parent_url' => $bp->loggedin_user->domain . $bp->bp_nav[ 'extra_tab' ][ 'slug' ] . '/',
'parent_slug' => $bp->bp_nav[ 'my-membership' ][ 'slug' ],
'position' => 20,
'screen_function' => 'view_manage_sub_tab_billing'
) );
}
add_action( 'bp_setup_nav', 'profile_new_subnav_item_billing', 20 );
function view_manage_sub_tab_billing() {
add_action( 'bp_template_content', 'bp_template_content_sub_function_billing' );
bp_core_load_template( 'template_content' );
}
function bp_template_content_sub_function_billing() {
if ( is_user_logged_in() ) {
//Add shortcode to display content in sub tab
echo do_shortcode( '[billing]' );
} else {
wp_login_form( array( 'echo' => true ) );
}
}
You may use this:
// define your parent slug
$parent_slug = 'activity';
bp_core_new_subnav_item( array( .........
'parent_url' => $bp->loggedin_user->domain . $parent_slug.'/',
'parent_slug' => $parent_slug,
It works for me.

Resources