20 Oct

I made DEV.to widget for websites/blogs

Hey Everyone! So I made an (Unofficial) DEV.to widget / profile-card which you can use in your websites and blogs (You just have to copy-paste 2 lines of code :D).

Here's how it looks like

Usage ( JUST 2 LINES OF CODE ๐Ÿ˜€ )

...

20 Oct

Message Encryption in JavaScript and PHP

Just for fun, let's encrypt some stuff in client-side JavaScript and have a PHP server decrypt it. Note that this will never replace TLS (HTTPS).

JavaScript Encryption with Sodium-Plus

You'll want the latest release of sodium-plus for this....

20 Oct

Building a Responsive UI Architecture in Flutter

Flutter Responsive UI

This tutorial is a follow up on Part 1 where we build a base widget that provides us with the appropriate information to build a responsive UI. Here you can find the starting code for this tutorial to which I have made a few adjustments compared to the part 1 video.

Changed the name of the BaseWidget to ResponsiveBuilderRemoved the Orientation from the SizingInformationUpdated the getDeviceType function to use the shortestSize property on the Size object instead of swapping width and height based on orientation.

In this tutorial I wanted to show off the ability to build UI for any combination of ScreenType X Orientation. What that means is that I want to be able to define, per widget, its layout for MobileDevice in Portrait, MobileDevice in Landscape, TabletDevice in Portrait, TabletDevice in Landscape etc. I want to make it clear that I also don't want to HAVE to define those layouts but I want to have the option. To illustrate this point I designed a simple layout where we'll modify the drawer based on those axis defined above. Below you can see the layouts for each screen + orientation. I wanted the differences to be visible but also still make sense. We're not going to discuss the UX, just the implementation of something like this.

In terms of the code organisation I have been going back and forth between the idea of storing multiple classes in one file. What I’ve ended up with is a file dedicated to the ScreenType the UI will display on. The file will contain both the Portrait and the Landscape layout if it has those. If you don’t understand 100% that’s fine, continue with the tutorial and you’ll see in a few minutes what I mean.

I highly recommend following along with the video since there’s lots of code in here.

Building a Widget per Screen Type

To get started I want to define another base level widget that will make use of the ResponsiveBuilder to provide us with a handy widget. This widget is specifically made to make the code more readable making it easier to maintain in the long run. We'll define a widget that will take in a widget for the mobile view as well as the tablet view. We'll place it in the responsive folder in a file called screen_type_layout.dart.

class ScreenTypeLayout extends StatelessWidget {  // Mobile will be returned by default  final Widget mobile;  final Widget tablet;  final Widget desktop;
  const ScreenTypeLayout(      {Key key, @required this.mobile, this.tablet, this.desktop})      : super(key: key);
  @override  Widget build(BuildContext context) {    return ResponsiveBuilder(builder: (context, sizingInformation) {      // If sizing indicates Tablet and we have a tablet widget then return      if (sizingInformation.deviceScreenType == DeviceScreenType.Tablet) {        if (tablet != null) {          return tablet;        }      }
      // If sizing indicates desktop and we have a desktop widget then return      if (sizingInformation.deviceScreenType == DeviceScreenType.Desktop) {        if (desktop != null) {          return desktop;        }      }
      // Return mobile layout if nothing else is supplied      return mobile;    });  }}

This widget will take in a Widget for each screen type. If one is not defined it will return the Mobile layout since we're starting there. This will give us a nice an easily readable top level widget. Next

Building a Widget per Orientation

Next up we want to establish the second axis that we want to build our widgets for. This will be the orientation. Orientation is easily fetched through the MediaQuery but using that directly will force conditionals in every view that needs to build using it. I’m not a fan of code duplication. To achieve a neater approach we’ll create a new widget orientation_layout.dart. This will provide us with two properties where we can provide the portrait and landscape widgets that we’d like to show.

class OrientationLayout extends StatelessWidget {  final Widget landscape;  final Widget portrait;  OrientationLayout({    Key key,    this.landscape,    @required this.portrait,  }) : super(key: key);
  @override  Widget build(BuildContext context) {    var orientation = MediaQuery.of(context).orientation;    if (orientation == Orientation.landscape) {      return landscape ?? portrait;    }
    return portrait;  }}

The portrait widget is required and will be the default if no landscape widget is supplied. If I were to put this in a package I would make both required and add an assert that says “If you don’t supply both there’s not point in using this widget”. That’s it for the Architectural setup, now lets write the code for the first UI.

Mobile Screen — Portrait

Below you can see how we want the mobile view to look in portrait mode. We want a hamburger icon in the top left corner, when tapped we want to show our AppDrawer.

Lets use our new widgets to get that setup. We’ll start off by building our HomeView, we'll use the ScreenTypeLayout. For the mobile widget we'll use the OrientationLayout and define the portrait widget for starters. Head over to the HomeView and modify the build method to look like this.

class HomeView extends StatelessWidget {  HomeView({Key key}) : super(key: key);
  @override  Widget build(BuildContext context) {    return ScreenTypeLayout(      mobile: OrientationLayout(        portrait: HomeMobilePortrait(),      ),    );  }}

Create a new file under home called home_view_mobile.dart and define the class HomeMobilePortrait which will display the mobile UI in portrait mode. Nothing special here, just a Scaffold with a key to open the scaffold from the icon press and an AppDrawer.

class HomeMobilePortrait extends StatelessWidget {  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
  @override  Widget build(BuildContext context) {    return Scaffold(      key: _scaffoldKey,      drawer: AppDrawer(),      body: Column(        children: <Widget>[          Padding(            padding: const EdgeInsets.all(16.0),            child: IconButton(              icon: Icon(                Icons.menu,                size: 30,              ),              onPressed: () {                _scaffoldKey.currentState.openDrawer();              },            ),          )        ],      ),    );  }}

Then we’ll define the AppDrawer. We know that the AppDrawer will change appearance for every combination of ScreenType and Orientation so it will require it's own widget. Create a new folder under the lib folder called widgets and in it create a folder called app_drawer and inside a file, app_drawer.dart.

class AppDrawer extends StatelessWidget {  const AppDrawer({Key key}) : super(key: key);
  @override  Widget build(BuildContext context) {    return Container(      width: 250,      decoration: BoxDecoration(        color: Colors.white,        boxShadow: [          BoxShadow(            blurRadius: 16,            color: Colors.black12,          )        ],      ),    );  }}

We’ll define a container for now with the width set to 250.

Mobile Screen — Landscape

Now lets move onto the Mobile Landscape view. As you see below, when the mobile app is in Landscape we want to show a smaller AppDrawer with a minimised version of the drawer items (implementation will come last).

We’ll start at the top then build the smaller widgets on the way down. Go to the home_view_mobile file, in the same file create a new stateless widget called HomeMobileLandscape and pass it to the landscape property of the OrientationLayout.

class HomeView extends StatelessWidget {  HomeView({Key key}) : super(key: key);
  @override  Widget build(BuildContext context) {    return ScreenTypeLayout(      mobile: OrientationLayout(        portrait: HomeMobilePortrait(),        landscape: HomeMobileLandscape(),      ),    );  }}

The Landscape Layout is pretty simple. It’s a scaffold with a Row as the body and the AppDrawer as the first child.

class HomeMobileLandscape extends StatelessWidget {  const HomeMobileLandscape({Key key}) : super(key: key);
  @override  Widget build(BuildContext context) {    return Scaffold(      body: Row(        children: <Widget>[AppDrawer()],      ),    );  }}

If you’re using the start project I gave you you’ll be using the device_preview package so you can quickly switch between orientations and device sizes. If you run the code now you should see the landscape layout looking like this.

Now as you see the drawer is a bit too wide for the design. We’ll use the Orientation inline to fix this since all we want to do is change the width of the drawer based on the orientation. Update the AppDrawer body to make use of the orientation and swap the width of the drawer Container.

class AppDrawer extends StatelessWidget {  const AppDrawer({Key key}) : super(key: key);
  @override  Widget build(BuildContext context) {    var orientation = MediaQuery.of(context).orientation;    return Container(        width: orientation == Orientation.portrait ? 250 : 100,        decoration: BoxDecoration(          color: Colors.white,          boxShadow: [            BoxShadow(              blurRadius: 16,              color: Colors.black12,            )          ],        ),    );  }}

That’s it for the Mobile Home Layout. Everything is separated and has no affect on each other. If the Drawer was more complicated than a simple check for width I would have used the OrientationLayout to supply two completely separate layouts. Just to keep things easier to modify in either state.

Now that you know how the Mobile is setup, the Tablet, and every other screen type will work exactly the same. In the solution here you can see how this implementation will look if you keep all the layouts in the same main file. Each responsive widget will have only one file with all it’s Orientation/ScreenType specific files in the same file, as Private widgets. I don’t know if I like the approach in the tutorial more than the single file one, but I’ve tried both. Given UI’s can get quite big I’m leaning towards a file for each display axis we want to cover.

Tablet Screen — Portrait

For the tablet Screen in portrait mode we want the AppDrawer to take up the full width, like a tab bar, and sit at the bottom of the screen for easy access in that mode.

We’ll start off by getting the HomeView tablet layout defined and then move down the tree for the smaller widgets. We’ll use one widget for the Tablet since we’re using the same children in both instances. We can update the HomeView to look like this.

class HomeView extends StatelessWidget {  HomeView({Key key}) : super(key: key);
  @override  Widget build(BuildContext context) {    return ScreenTypeLayout(      mobile: OrientationLayout(        portrait: HomeMobilePortrait(),        landscape: const HomeMobileLandscape(),      ),      tablet: const HomeTablet(),    );  }}

The HomeTablet widget will either be a Column in portrait or Row in landscape mode. The children will stay the same. The only difference being that the children are reversed when in Landscape. This is just to show that you can still combine the code for orientations if they have minimal differences. In the home folder create a new file called home_view_tablet.dart

class HomeTablet extends StatelessWidget {  const HomeTablet({    Key key,  }) : super(key: key);
  @override  Widget build(BuildContext context) {    var children = [      Expanded(        child: Container(),      ),      AppDrawer()    ];    var orientation = MediaQuery.of(context).orientation;    return Scaffold(      body: orientation == Orientation.portrait          ? Column(              children: children,            )          : Row(              children: children.reversed.toList(),            ),    );  }}

At this point we can go ahead and make the root of the AppDrawer a ScreenTypeLayout.

class AppDrawer extends StatelessWidget {  const AppDrawer({Key key}) : super(key: key);
  @override  Widget build(BuildContext context) {    return ScreenTypeLayout(      mobile: const AppDrawerMobileLayout(),      tablet: const OrientationLayout(        portrait: AppDrawerTabletPortrait(),      ),    );  }}

Create a new file under the app_drawer folder called app_drawer_mobile.dart.

class AppDrawerMobileLayout extends StatelessWidget {  const AppDrawerMobileLayout({Key key}) : super(key: key);
  @override  Widget build(BuildContext context) {    return OrientationBuilder(      builder: (context, orientation) => Container(        width: orientation == Orientation.portrait ? 250 : 100,        decoration: BoxDecoration(          color: Colors.white,          boxShadow: [            BoxShadow(              blurRadius: 16,              color: Colors.black12,            )          ],        ),      ),    );  }}

Create another file, app_drawer_tablet.dart and create a new widget AppDrawerTabletPortrait that defines the Portrait UI.

class AppDrawerTabletPortrait extends StatelessWidget {  const AppDrawerTabletPortrait({Key key}) : super(key: key);
  @override  Widget build(BuildContext context) {    return Container(      height: 130,      decoration: BoxDecoration(        color: Colors.white,        boxShadow: [          BoxShadow(blurRadius: 16, color: Colors.black12),        ],      ),    );  }}

If you save and run now your drawer should appear at the bottom of the screen when in portrait mode for the tablet.

Tablet Screen — Landscape

The last screen to implement for the design is the Landscape Tablet view for the AppDrawer. Open up the AppDrawer and set the landscape value for the tablet orientation to AppDrawerTabletLandscape.

class AppDrawer extends StatelessWidget {  const AppDrawer({Key key}) : super(key: key);
  @override  Widget build(BuildContext context) {    return ScreenTypeLayout(      mobile: const AppDrawerMobileLayout(),      tablet: const OrientationLayout(        portrait: const AppDrawerTabletPortrait(),        landscape: const AppDrawerTabletLandscape(),      ),    );  }}

Then we can create the Landscape widget in the app_drawer_tablet file and set the width to 250.

class AppDrawerTabletLandscape extends StatelessWidget {  const AppDrawerTabletLandscape({Key key}) : super(key: key);
  @override  Widget build(BuildContext context) {    return Container(      width: 250,      decoration: BoxDecoration(        color: Colors.white,        boxShadow: [          BoxShadow(blurRadius: 16, color: Colors.black12),        ],      ),    );  }}

The reason I didn’t use the OrientationLayout directly this time, was to show how much better it reads in code using the Layout. Just think about how many screens you'll have, having something that reads like this over time will help those future unintentional bugs that might come up when your web tester is resizing the view over and over to find the flaws.

🎉 Responsive View Layout Complete 🎉

That’s how I will be handling responsive projects going forward in production. Instead of using the MediaQuery directly I wanted something more readable and this is a step in that direction. Now lets build the Responsive Drawer Items. We know exactly how they should look in all 4 of the combinations we have. We can start off the widgets code with both Layout widgets and get all the boilerplate out of the way. Under the widgets folder create a new folder called drawer_option. In there Create a new file called drawer_option.dart, drawer_option_mobile.dart and drawer_option_tablet.dart.

In the drawer_option.dart file create a new stateless widget called DrawerOption.

class DrawerOption extends StatelessWidget {  final String title;  final IconData iconData;  const DrawerOption({    Key key,    this.title,    this.iconData,  }) : super(key: key);
  @override  Widget build(BuildContext context) {    return ScreenTypeLayout(      mobile: OrientationLayout(        portrait: DrawerOptionMobilePortrait(),        landscape: DrawerOptionMobileLandscape(),      ),      tablet: OrientationLayout(        portrait: DrawerOptionTabletPortrait(),        landscape: DrawerOptionTabletLandscape(),      ),    );  }}

In the drawer_option_mobile file we’ll create DrawerOptionMobilePortrait. It's a Container with height 80 and a row with an icon and text inside. It takes in a title and icon data.

class DrawerOptionMobilePortrait extends StatelessWidget {  final String title;  final IconData iconData;  const DrawerOptionMobilePortrait({    Key key,    this.title,    this.iconData,  }) : super(key: key);
  @override  Widget build(BuildContext context) {    return Container(      padding: const EdgeInsets.only(left: 25),      height: 80,      child: Row(        children: <Widget>[          Icon(            iconData,            size: 25,          ),          SizedBox(            width: 25,          ),          Text(            title,            style: TextStyle(fontSize: 21),          )        ],      ),    );  }}

In the same drawer_option_mobile file create the DrawerOptionMobileLandscape. It's a container (height 70) with an icon inside aligned to the centre.

class DrawerOptionMobileLandscape extends StatelessWidget {  final IconData iconData;  const DrawerOptionMobileLandscape({Key key, this.iconData}) : super(key: key);
  @override  Widget build(BuildContext context) {    return Container(      height: 70,      alignment: Alignment.center,      child: Icon(iconData, size: 30,),    );  }}

Then we can move onto the Tablet version. in the drawer_option_tablet file create a new widget.

class DrawerOptionTabletPortrait extends StatelessWidget {  final String title;  final IconData iconData;  const DrawerOptionTabletPortrait({    Key key,    this.title,    this.iconData,  }) : super(key: key);
  @override  Widget build(BuildContext context) {    return Container(      width: 152,      alignment: Alignment.center,      child: Column(        mainAxisSize: MainAxisSize.min,        children: <Widget>[          Icon(            iconData,            size: 45,          ),          Text(title, style: TextStyle(fontSize: 20)),        ],      ),    );  }}

And for the Tablet Landscape widget we’ll supply the DrawerOptionMobilePortrait widget since it's the same. Your DrawerOption class should now look like this.

class DrawerOption extends StatelessWidget {  final String title;  final IconData iconData;  const DrawerOption({    Key key,    this.title,    this.iconData,  }) : super(key: key);
  @override  Widget build(BuildContext context) {    return ScreenTypeLayout(      mobile: OrientationLayout(        portrait: DrawerOptionMobilePortrait(          title: title,          iconData: iconData,        ),        landscape: DrawerOptionMobileLandscape(          iconData: iconData,        ),      ),      tablet: OrientationLayout(        portrait: DrawerOptionTabletPortrait(          title: title,          iconData: iconData,        ),        landscape: DrawerOptionMobilePortrait(          title: title,          iconData: iconData,        ),      ),    );  }}

Then to wrap up we can go over to the AppDrawer create a static function getDrawerOptions that returns all our options.

class AppDrawer extends StatelessWidget {  ...
  static List<Widget> getDrawerOptions() {    return [      DrawerOption(        title: 'Images',        iconData: Icons.image,      ),      DrawerOption(        title: 'Reports',        iconData: Icons.photo_filter,      ),      DrawerOption(        title: 'Incidents',        iconData: Icons.message,      ),      DrawerOption(        title: 'Settings',        iconData: Icons.settings,      ),    ];  }}

For the AppDrawer mobile layout in app_drawer_mobile we can now set the child as a column with the drawer options as children.

class AppDrawerMobileLayout extends StatelessWidget {  @override  Widget build(BuildContext context) {    var orientation = MediaQuery.of(context).orientation;    return Container(      ...      child: Column(        children: AppDrawer.getDrawerOptions(),      ),    );  }}

for the Tablet Portrait widget of the AppDrawer we can do the same but we'll use a Row instead.

class AppDrawerTabletPortrait extends StatelessWidget {  @override  Widget build(BuildContext context) {    return Container(      ...      child: Row(        children: AppDrawer.getDrawerOptions(),      ),    );  }}

And for Tablet Landscape widget of the AppDrawer we'll use a column along with the children.

class AppDrawerTabletLandscape extends StatelessWidget {  @override  Widget build(BuildContext context) {    return Container(      ...      child: Column(        children: AppDrawer.getDrawerOptions(),      ),    );  }}

That’s it. You should be able to swap between all the orientations now for Mobile and Tablet and see a different UI. I’m leaving out the DrawerProfileItem so that you can do that as practice. The goal was to make responsive UI building more readable, check. Separate the layouts from each other to avoid massive conditional ridden UI files, check. Allow for a long term maintainable codebase, maybe check? We'll see in the next few months during production development.

Please let me know what you think. Come over to the Slack, Subscribe on YouTube. I build these architectures for clients and I like sharing them ๐Ÿ™‚

Until next week.

Flutter Community

Building a Responsive UI Architecture in Flutter was originally published in Flutter Community on Medium, where people are continuing the conversation by highlighting and responding to this story.

20 Oct

Reusing i18n strings for IT testing in Flutter

Reusing i18n strings for IT testing in

It is not uncommon to check the text of some widgets when doing integration testing. It is usually done so, in order to be assured that the user will receive the appropriate feedback before and/or after certain actions.

TL;DR

Check out the full example here, but I would suggest you keep reading, it will not take that long 🙂

The use case

Let’s take the default counter application you get whenever you generate a new flutter application.

There is a text (‘You have pushed the button this many times:’) that we really want to make sure it stays there cause it gives valuable feedback to the user. We want to make sure that this text is always visible and we could achieve that with the following integration test.

Provisioning for i18n

That would be sufficient for a small app such as this, but what in reality apps are way bigger and more complex than this. For those apps, it is common to provision for i18n, because it will widen the app’s audience.

The most common implementation you will find in an i18n flutter app is the one the documentation is actually suggesting. In our case for the counter app, it would look like the following listing.

Try to use AppLocalization in Integration Test

Now that we have created our AppLocalization we could, in theory, use this component in our integration tests in order to have a more static reference to a text, through the counterText getter.

So, we look at our integration test and we think that this is it! We feel confident and proud that we are going to test the text in using a static reference and not the literal string.

Well … think again! Lo and behold we have the following error!

test_driver/counter_it_test.dart:1:8: Error: Not found: 'dart:ui'
What is this error all about?

So apparently we should not import dart:ui directly or indirectly to the test_driver integration test. For more information on this issue check out this.

We can get away with the direct importing, but it is not that simple for the indirect one, as the import could lie several layers under our direct import.

How to fix it

Alright, so in theory, we could get away with using AppLocalization in integration tests, if we could abstract all the static references and translations into a module that has no dependencies.

One solution I managed to come up with is to use a mixin to keep the _localizedValues and getter methods. But this would not work by itself as we need a locale in order to resolve the correct i18n value for the getter.

String get counterText => _localizedValues[locale.toString()]['counter_text'];

This locale variable should be final and accessed by the mixi. So, we could introduce an abstract class to hold the final locale and bind it to the mixin by using the on notation in the mixin declaration. Confused? Let's look at some code to make it clearer.

Using the LocalizationsProvider

So, now all we have to do is to make AppLocalization inherit this functionality we have abstracted to LocalizationsProvider. It is as simple as this:

As for the integration tests, we can just have a test concrete class extending LocalizationsProvider ...

class TestLocalization extends LocaleCodeAware with LocalizationsProvider { TestLocalization(String localeCode) : super(localeCode); }

… and use that one in our tests

What we have achieved is that we are now able to use our i18n texts in a statically referenced way, in our integration tests. Furthermore, if a text change is needed it will only happen in LocalizationsProvider and it will be depicted both in the application and in tests without any other work needed.

You can find the complete example in this repo.

Originally published at https://efthymis.com on June 12, 2019.

Flutter Community

Reusing i18n strings for IT testing in Flutter was originally published in Flutter Community on Medium, where people are continuing the conversation by highlighting and responding to this story.

20 Oct

How to Process Passwords as a Software Developer

Passwords are still the primary method of authentication today, in a form of something you know. Humans are lazy, often resulting in low entropy and reused passwords.

Magnitudes of research and thought have been put into protecting passwords. They are...

19 Oct

How to spot a false teacher

Throughout your life, you will encounter various mentors, people who catch your attention and who you want to learn from. Some of this will be voluntary and some of it won't be.

We don't quite choose what information comes into our lives. We end up w...

18 Oct

An Adequate Introduction to Functional Programming

This article is part of a series where we explore functional and reactive programming both in general terms and applied to JavaScript.

In this first post, we discuss several functional core concepts with a practical approach, dwelling on the theoreti...