aqua 1.1.2+7 aqua: ^1.1.2+7 copied to clipboard
Utility classes/functions to help with UI development using the Flutter framework.
Aqua #
Utility classes/functions to help with UI development using the Flutter framework.
It is recommended to use the as
keyword with the import
statement when importing the package to prevent name conflicts, for example...
import 'package:aqua/aqua.dart' as aqua
To log output to file
await aqua.log('data to log', 'path/to/file', clear: true, time: true);
To save data to device
Future<void> save() async {
var id = 'id';
var _value = 1920;
await aqua.Pref.set(id, value);
var value = await aqua.Pref.get(id);
}
Show time in terms of hours and minutes and days ago
var time = aqua.readTimestamp(DateTime.now().millisecondsSinceEpoch / 1000);
To put a block of code in a try catch
// the argument for tryCatch could either be a callback to a function or a future
// as a function
Widget _buildWidget(){
// may fail to build for some reason
}
var child = await aqua.tryCatch(_buildWidget(), verbose: true);
// as a future
Future<Widget> _buildWidget() async {
// may fail to build for some reason
}
var future = _buildWidget();
var child = await aqua.tryCatch(future, verbose: true);
if(child != null){
// proceed
}
put your future in a callback and run it as many times as specified if you want it to run until their is a value other than null, set retries to 0
/// int retries = 0; allows it to run until value other than null is produced
int retries = 5;
callback() async => await yourFuture();
var result = await aqua.Timeout.until(retries, callback, verbose: true);
Interacting with APIs from remote locations
// posting to an endpoint
var fromServer = await aqua.Client(
'192.168.1.100', //ip
8080, // port
'/test', // endpoint
query: {
'id': 1,
}, // post parameters
verbose: true
).getResponse();
// or
var client = aqua.Client(
'192.168.1.100', //ip
8080, // port
'/test', // endpoint
query: {
'id': 1,
}, // post parameters
verbose: true
);
var fromServer = await client.getResponse(); // defaults to POST
if(client.statusCode == 200){
// some code
}
// a real end point would look like this
// the end point is free to use
// you can find the rest of the endpoints here: https://www.coingecko.com/en/api
var fromServer = await aqua.Client(
'api.coingecko.com',
443,
'/api/v3/coins/markets',
isSecured: true,
query: {
'vs_currency': 'usd',
'order': 'market_cap_desc',
'per_page': '20',
'page': '1',
'sparkline': 'true'
},
verbose: true
).getResponse(method: 'GET');
// other parameters include
var client = aqua.Client(
'192.168.1.2',
8080,
'/test',
headers: <String, String>{
'Authorization': 'Bearer $yourtoken'
},
query: {
'id': 1
}
isSecured: true,
verbose: constants.Api.verbose,
expectedStatusCodes: [201] // not a must, assumes you know your status codes for api
);
var fromServer = await client.getResponse(); //defaults to POST, others include GET, PUT, DELETE
if(client.statusCode == 201){
// some code
}
set timeouts when interacting with remote Apis, and onTimeout callbacks for when timeout is reached; timeout is in milliseconds
var fromServer = await aqua.Client(
'api.coingecko.com',
443,
'/api/v3/coins/markets',
isSecured: true,
query: {
'vs_currency': 'usd',
'order': 'market_cap_desc',
'per_page': '20',
'page': '1',
'sparkline': 'true'
},
verbose: true,
timeout: 300,
onTimeout: (){
// callback to handle this scenario
//eg inform widget of the timeout, and perharps retry
// how you retry this request is up to you
streamController.sink.add('/api/v3/coins/markets timeout out');
}
).getResponse(method: 'GET');
DESKTOP ONLY
To allow for mouse pointers to change to click icons on hovering on a clickable widget
@override
Widget build(BuildContext context){
// some code
// then
return aqua.MouseInteractivity(
child: child
);
}
To get a random index between a range of indexes
var index = aqua.getRandomNumber(min: 10, max: 10000);
To output info on screen with different colors
aqua.pretifyOutput('to print on screen'); // will print in green
aqua.pretifyOutput('to print on screen', color: 'red'); // white, red, magenta, yellow, cyan, blue, defaults to green
To obscure text
var obscured = aqua.obscureText('obscured');
show snackbar; must use a scaffold for this to work
aqua.showSnackbar(
'info',
context,
color: Colors.red,
bgColor: Colors.black,
mounted=mounted // flutter value,
seconds=1
);
Check for email syntax or digits without characters
var isEmail = aqua.Validators.isEmail('email');
var isNumber = aqua.Validartors.isNumber('1234132');
Disallow listview glow
@override
Widget build(BuildContext context){
return aqua.disallowGlow(ListView());
}
To add a shadowy effect on an image
@override
Widget build(BuildContext context){
return aqua.Shadow(
child: Image(image: AssetImage('/path/to/asset'))
);
}
A quick drop down widget
@override
Widget build(BuildContext context){
return aqua.DropDown(
initValue: 'one',
items: ['one', 'two', 'three', 'four', 'five', 'six']
);
}
A quick TabBar. Tabs without scaffold...
@override
Widget build(BuildContext context){
return Material(
child: DefaultTabController(
length: 3,
child: Column(
children: [
aqua.TabHeader(
tabListing: ['car', 'transit', 'bike'],
),
Expanded(
child: TabBarView(
children: [
Icon(Icons.directions_car),
Icon(Icons.directions_transit),
Icon(Icons.directions_bike),
],
),
)
],
),
)
);
}
To get screen dimensions in scale
@override
Widget build(BuildContext context){
aqua.Dimensions().init(context);
return Container(
width: aqua.Dimensions.width, // full width of screen
height: aqua.Dimensions.height, // full height of screen
color: Colors.red
);
}
To get height and width for an expanded widget
@override
Widget build(BuildContext context){
return Column(
children: [
Expanded(
child: aqua.DynamicDimensions(
renderWidget: (double width, double height){
return Container(
width: width,
height: height
color: Colors.red,
);
}
),
),
SizedBox(height: 10.0),
]
);
}
To captilaize a word
var capitalized = aqua.capitalize('alphabet');
print('capitalized: $capitalized);
To create a file quickly (will also create the recursive directories on the path)
await aqua.createFile('/path/to/file');
// to clear a file/truncate a file
await aqua.createFile('/path/to/file', clear: true);
To generate a random ID
var id = aqua.generateUUID(length: 30);
To navigate
// some code
// then
aqua.Dimensions().init(context);
Widget viewOne = Container(
width: aqua.Dimensions.width,
height: aqua.Dimensions.height
color: Colors.blue
);
Widget viewTwo = Container(
width: aqua.Dimensions.width,
height: aqua.Dimensions.height
color: Colors.red
);
// to navigate to the next view without erasing the previous view from state
aqua.CustomNavigator(
context: context,
buildScreen: () = > viewOne
).navigateToPage();
// to navigate to the next view and erase the previous view from state
aqua.CustomNavigator(
context: context,
replaceSingle: true,
buildScreen: () = > viewOne
).navigateToPage();
// to navigate to the next view and erase ALL the previous views from state
aqua.CustomNavigator(
context: context,
replaceAll: true,
buildScreen: () = > viewOne
).navigateToPage();
// to navigate to the next view using a named route
aqua.CustomNavigator(
context: context,
namedRoute: '/home',
buildScreen: () = > viewOne
).navigateToPage();
To display loader
Widget loader = aqua.Loader(
width: width,
height: height,
color: color
);
To request focus from another widget
@override
Widget build(BuildContext context){
// some code
// then
Widget withFocus = aqua.requestFocus(child, context);
// make sure to return a widget
}
To add commas to numbers
String number = aqua.pretifyNumber('1000000');
print('number: $number');
To clip images into a circular widget
@override
Widget build(BuildContext context){
// some code
// then
Widget clippedImage = aqua.ClippedCircle(
child: child // some widget, could be an image, wrapped in a container,
color: Colors.blue // border of the circle
);
// make sure to return a widget
}
Sometimes the clipped image might not expand into the container as expected, to force it do so:
@override
Widget build(BuildContext context){
// some code
// then
Widget clippedImage = aqua.ClippedCircle(
child: aqua.ImageFit(
child: child // Image.asset(path/to/file) or even a network image
) // some widget, could be an image, wrapped in a container,
color: Colors.blue // border of the circle
);
// make sure to return a widget
}
Custom Text Form Widget
class Play extends StatefulWidget {
@override
PlayState createState() => PlayState();
}
class PlayState extends State<Play>{
FocusNode focusNode;
TextEditingController textEditingController;
@override
void initState(){
super.initState();
focusNode = FocusNode();
textEditingController = TextEditingController();
}
@override
void dispose(){
focusNode?.dispose();
textEditingController?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context){
aqua.Dimensions().init(context);
return Column(
children: [
Row(
children: [
Expanded(
child: aqua.TextFormFieldCustom(
borderRadius: 20,
isOutlineBorder: true, //false
verticalPadding: 15.0,
horizontalPadding: 15.0,
keyboardType: TextInputType.text,
borderColor: Colors.grey.withOpacity(0.5),
focusedBorderColor: conf.Colors.orange1,
cursorColor: conf.Colors.orange1,
borderWidth: 2,
hintText: 'hint text',
hintTextstyle: const TextStyle(
color: Colors.black,
fontStyle: FontStyle.italic
),
labelTextStyle: const TextStyle(
color: Colors.black,
fontStyle: FontStyle.italic
),
labelText: 'label',
focusNode: FocusNode(),
controller: TextEditingController(),
prefixIconData: Icons.message,
prefixIconColor: Colors.grey,
focusedPrefixIconColor: Colors.green,
onChanged: (String value, TextEditingController controller){
},
isObscureText: true, //false
prefixIcon: Container() //widget,
maxLines: 2, // any int,
streamController: StreamController() // to send back changed values to listeners
)
)
]
),
]
);
}
}
Dotted Line; Separator
@override
Widget build(BuildContext context){
// some code
// then
Widget separator = Row(
children: [
Expanded(
child: aqua.DottedLine()
)
]
);
// make sure to return a widget
}
Stepped Progresser; To track progress of an ongoing step by step instructive activity;
It scales to any number of steps; Will render something like this:
@override
Widget build(BuildContext context){
// some code
// then
Widget progress = aqua.SteppedProgress(
steps: ['Step 1', 'Step 2', 'Step 3'],
thickness: 1.5,
dashWidth: 5,
currentStep: 2,
);
// make sure to return a widget
}
FLUTTER DEVICES
Window Navigator, a bit of boilerplate code is needed for this to work ...
To setup your environment for mobile, click here
To setup your environment for desktop, click here
Copy paste the code below to render a screen like this:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:aqua/aqua.dart' as aqua;
class Shell extends StatefulWidget {
@override
ShellState createState() => ShellState();
}
class ShellState extends State<Shell>{
Widget selectedWidget;
aqua.NavigationStreamer mainNavStreamer;
StreamSubscription mainNavStreamSubscription;
@override
void initState(){
super.initState();
mainNavStreamer = aqua.NavigationStreamer();
mainNavStreamSubscription = mainNavStreamer.listen((data){
aqua.pretifyOutput('[SHELL] data from nav stream: $data');
selectedWidget = data['window'];
setState((){});
});
}
@override
void dispose(){
mainNavStreamSubscription.cancel();
mainNavStreamer.close();
super.dispose();
}
Widget _buildShell(BuildContext context){
Map<String, Map<String, dynamic>> generatedRoutes = _buildGeneratedRoutes();
var textStyle = TextStyle(
fontSize: 30.0,
color: Colors.white,
fontWeight: FontWeight.bold
);
Widget firstWidget = Container(
color: Colors.purple,
child: Center(
child: Text(
'Home',
style: textStyle
)
),
);
return Scaffold(
appBar: null,
body: SingleChildScrollView(
child: Container(
child: Row(
children: [
Expanded(
child: aqua.Navigation(
header: Container(
width: navWidth,
height: 100.0,
color: Colors.red,
child: Center(
child: Text(
'Header',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold
),
),
),
),
routes: generatedRoutes,
bgColors: <Color>[
Colors.blue,
Colors.blueAccent
],
hoverColor: Colors.brown.withOpacity(0.5),
selectedColor: Colors.white.withOpacity(0.5),
navStreamer: mainNavStreamer,
),
),
Expanded(
flex: 6,
child: selectedWidget == null ? aqua.requestFocus(
firstWidget,
context
) : aqua.requestFocus(
selectedWidget,
context
)
),
]
)
),
),
);
}
@override
Widget build(BuildContext context) => _buildShell(context);
Map<String, Map<String, dynamic>> _buildGeneratedRoutes(){
var textStyle = TextStyle(
fontSize: 30.0,
color: Colors.white,
fontWeight: FontWeight.bold
);
Function _buildIconHelper = (IconData iconData){
return Icon(iconData, color: Colors.black, size: 15.0,);
};
return {
'Home': {
'window': aqua.DynammicDimensions(
renderWidget: (double width, double height){
return Container(
width: width,
height: height,
color: Colors.purple
);
}
),
'icon': _buildIconHelper(Icons.home)
},
'Search': {
'window': aqua.DynammicDimensions(
renderWidget: (double width, double height){
return Container(
width: width,
height: height,
color: Colors.red
);
}
),
'icon': _buildIconHelper(Icons.search)
},
'Settings': {
'window': aqua.DynammicDimensions(
renderWidget: (double width, double height){
return Container(
width: width,
height: height,
color: Colors.blue
);
}
),,
'icon': _buildIconHelper(Icons.settings)
}
};
}
}