Utopian Rocks Mobile - Update 0.1.0

in utopian-io •  6 years ago  (edited)

Repository

https://github.com/tensor-programming/utopian-rocks-mobile

New Features

From prerelease version 0.0.1 to prerelease version 0.1.0; the main new features in this application are the Timer, the Vote Power Indicator, the Information drawer, the "check for update" Button, a Filter Menu and a few structural changes. This also includes minor UI improvements to make the application a bit smoother and more intuitive as well as some minor bug fixes.

The Timer and Vote Power Indicators

First let's talk about the Timer and Vote Power Indicators. The utopian.rocks website addresses these two elements by calculating the rough score of each contribution and simulating the voting system. It also uses the Beem library to further correct the vote power calculations to make them more accurate. In the mobile application, rather then manually calculating these two values in the same way that the website does, the application just grabs the html document. The application is then able to use css selectors to grab the values at the time of the document request and use them as initial values for both fields. The getHtml() function is responsible for grabbing the html document string and adding a static singleton version of it to the ParseWebsite object.

The getVotePower() and getTimer() functions call the getHtml() function and grab the appropriate values from the html document string. In the case of getTimer(), the application needs to reformat the Timer string into a number of seconds. The application then counts down from this value by making use of the Observable.periodic() method from the RxDart library. This code emmits data to the getTimer() function every second and then passes the return data to the user interface. By doing this, the application is able to decrement the starting amount of seconds in real-time.

On the frontend, the application uses the intl library to format the seconds into something that is more readable. Here the seconds are passed into a DateTime object and then formatted using the DateFormat.Hms() function. This Timer is embedded on a BottomAppBar along with the Vote Power indicator.

bottomBar.png

Information Drawer and Package Info

I wanted to add some instructions and application information to the user interface. I decided to add a drawer to the application which would be able to serve this information. This drawer makes use of the Package_Info library. This library makes it easy to gain access to various pieces of information about the application including version, application name, and the application icon. An entirely new BLoC was created to serve this information to the UI widgets.

The BLoC contains an observable which serves the package information. In Flutter, drawers are created and destroyed every time you open and close them. Because of this, I needed to make the observable reusable and I was able to do this using the Observable.defer() method. This method creates a new Observable from another Observable only once the observer subscribes to it. Since the Package_Info library serves its data through a Future value, I was able to create a one event Observable from the Future and wrap it in the Observable.defer() call.

This information is then passed up to the InformationDrawer widget through the InformationBloc and it is used to programmatically generate the information for the drawer. This same stream is also re-used for the Update Button widget which is on the drawer.

drawer.png

Release Update Button

Originally, I wanted to make it so that the application would automatically check for updates when the user opened it. I was able to achieve this in some of the early versions but I found that an unauthenticated github API request had a request limit. For a period, I then made it so that the Update Check only happened a single time or happened over a larger period of time, but I found both of these solutions to be unintuitive and intrusive. My final solution was to add a Button to the Information Drawer which the user could press to check for updates. What makes this solution more elegant is that the user can initiate the process and if there is no update available, a notification can be deployed.

For this to work properly, I needed access to the github API so that the application could look at the releases on the utopian-rocks-mobile repository. This was done by creating a GithubApi repository object. As with the contributions results, the GithubApi calls to a REST api endpoint and grabs JSON. The JSON is then serialized through a small model which was added to the model file. This data is then passed to the UI from the InformationBloc in a way that is similar to the Package Information. Since this event is tied to a button and a DialogWindow; it needs to use the Observable.defer() method so that it can be reusable. Every time a user pushes the button, it creates a new observable which then checks the application's version number with the latest version number from the Github API. If there is a new release or the release number does not match the one inside of the application, then a DialogWindow is deployed telling the user that they can update the application. Otherwise, a second DialogWindow is deployed telling the user that there is no new release. The first DialogWindow contains a button which calls to the Url_Launcher library and it sends an intent to the application with the release url attached to it.


notification-download.png notification.png

Building the Filter Menu

The utopian.rocks website recently added the ability to filter through the contributions by category and I wanted to add this feature to my application as well. I did this by adding a popup menu to the bottom application bar next to the Timer and Vote Power Indicators. The PopupMenu is programmatically generated by mapping over a list of all of the categories as well as an "all" filter. Each Category Icon, Name and Color is bound to a ListTile inside of a PopupMenuItem widget. For the "all" filter, the generic Utopian Icon was used along with the Utopian Purple Blue Color. When the user selects a filter from the PopupMenu the category string is added to a Sink in the ContributionBloc object.

Creating this functionality was a little more tricky then I originally had anticipated because applying a filter to the list of contributions does not emit a new event through the results stream. This means that the StreamBuilder widgets will not rebuild the UI to account for this change. Originally, I was manually invoking an emission event by re-applying the tabName string to the tabName Sink. This made the application think that it was changing from one page to the next which would force a rebuild. This way of doing things was flawed however, because it caused the page to build twice when the user changed from one tab to the next. Sometimes, contributions from one page would bleed over to the next page as a result.

To correct this, I used of a new filteredResults Observable and the Observable.combineLatest2() method. The Observable.combineLatest2() method takes two streams and then passes them through a function to create a new stream. In this case, the two streams are the original results stream and the filter sink. These two streams are then passed into a applyFilter utility function which checks to see whether or not the filter equals the "all" string. If it doesn't the application iterates through all of the contributions and checks the filter against the contribution's category field. The function then returns a new list of contributions which are only in that specific category.


filter-menu.png

More information

If you want to learn more about the changes made between the different releases, make sure to take a look at the changelog document in the repository. If you'd like to get this application, you may do so by accessing the releases inside of the repository; this will change when the application is deployed to the Google Play and iOS App stores. Also, as of right now, there is no iOS build for this application so if you want to use it on iOS you must build it yourself.

If you'd like to contribute to this project, feel free to make you way over to the repository and open a issue or pull request. Bug reports and suggestions are more than welcome.

GitHub Account

https://github.com/tensor-programming

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!
Sort Order:  

Hi there,

Great to see the mobile version is having progress.

The utopian.rocks website addresses these two elements by calculating the rough score of each contribution and simulating the voting system. It also uses the Beem library to further correct the vote power calculations to make them more accurate. In the mobile application, rather than manually calculating these two values in the same way that the website does, the application just grabs the HTML document.

I personally don't like this idea. If the utopian.rocks API doesn't have it, it's possible to do the same calculations.

  • Make a request to https://steemit.com/@emrebeyler.json
  • Calculate the current vp from the last_vote_time and voting_power properties.
  • Calculate the recharge with the same information.

This would reduce the HTTP requests from two to one.


Your contribution has been evaluated according to Utopian policies and guidelines, as well as a predefined set of questions pertaining to the category.

To view those questions and the relevant answers related to your post, click here.


Need help? Write a ticket on https://support.utopian.io/.
Chat with us on Discord.
[utopian-moderator]

  ·  6 years ago (edited)

Well normally I would agree with you. Pulling in an entire HTML document and making a bunch of requests is a fairly bad practice for any application and even worse on a mobile application. That being said, the Idea is to eventually make it so that the application pulls in the HTML a single time on starting up and then it makes its own calculations from there. I am going to add caching next and this will be a big part of it. I looked into doing the calculations manually before and doing them from scratch was fairly performance heavy. The other way to do it would be to make an API request to the steem API for the Utopian vote and recharge information which you suggested, but I really would rather avoid using the steem API if possible. (A utopian API on the other hand would be an entirely different matter wink wink).

Thank you for moderating my contribution @emrebeyler

Thank you for your review, @emrebeyler!

So far this week you've reviewed 9 contributions. Keep up the good work!

@tensor, have you solve the problem on how to use SVG in Flutter?

SVG is not currently supported in flutter. There are some libraries but it involves much more pain then its worth. In my case, the utopian Icons were in Font format so it was very easy to use just code points and IconData objects to create Icons which I could scale and color etc.

Hi @tensor!

Your post was upvoted by @steem-ua, new Steem dApp, using UserAuthority for algorithmic post curation!
Your post is eligible for our upvote, thanks to our collaboration with @utopian-io!
Feel free to join our @steem-ua Discord server

Hey, @tensor!

Thanks for contributing on Utopian.
We’re already looking forward to your next contribution!

Get higher incentives and support Utopian.io!
Simply set @utopian.pay as a 5% (or higher) payout beneficiary on your contribution post (via SteemPlus or Steeditor).

Want to chat? Join us on Discord https://discord.gg/h52nFrV.

Vote for Utopian Witness!