Friday, December 25, 2020

update-hosts version 3

A major version update has been released for update-hosts bringing it to version 3.

Version 3 is largely compatible with the older version 2, except that the script now requires you to select what is outputted from the tool, instead of outputting a hosts file by default. The tool can output hosts, dnsmasq, and ipset formatted files. Support for changing file names, output IP addresses, and adding additional sources on the fly is still present, but the unbreak list has been dropped as it was too far out of date to maintain accurately.

The script has been largely simplified and much of the output noise has been removed. Instead of logging each individual step, the script only outputs errors and success points. The average user doesn't care that the script is currently stripping line endings or parsing IP addresses, so that logging information has been removed.

Find the latest version here.

Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

Thursday, December 24, 2020

git-ssh version 3

git-ssh has seen a major version refresh with version 3.0.0

Version 3 drops the python language as well as support for config file version 1 and instead moves to POSIX shell script with support for only config version 2.

For anyone using git-ssh 2 this change means very little as it is still config compatible, but for users using v1 you would honestly be better off just starting from scratch, it's quick I promise.

Some major behavior changes in this version though.

Gone are any of the --long-option flags, operation is strictly through commands now.

Use git-ssh create and pass it a name and an ssh keyfile path to create a config. Similarly use git-ssh delete and give it a name to remove configs. Use git-ssh list to show all your possible configs.

git-ssh in version 1 and 2 operated as a git subtool, meaning you woul call it along with other arguments to git itself. In version 3 it fills a role more like an outside manager, it's default and only mode of operation is now the equivalent of version 2 --ssh-alias mode

Calling git-ssh export with a config name will export a special environment variable that git will read when handling ssh commands. You can eval the result of this export command to set up your keyed environment. You can then call git as normal, so stuff like shell completion and git performance will remain as normal.

The choice was made to move away from python for performance reasons. Python took a couple hundred milliseconds to start up, which would slow down basically all git operations when git-ssh was used. Moving to shell script allows faster startup performance, and since the requirement to support old configs is gone, the tool is greatly simplified as well.

Find the new git-ssh here

Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub 
=========================

Tuesday, December 22, 2020

Flashing Lights

Not gonna make the joke.

ZapTorch has received some updates today which simplify the code base and bring support for 2 new supported sequences!

Double tapping the Volume Down button will still turn the flashlight on, as it always has.

Double tapping the Volume Up button will turn the flashlight on and pulse it at a slow speed of about half a second. The light will flicker on and off every half-second or so, until you stop it by entering the sequence again. Cool!

Tapping Volume Down once and Volume Up once afterwards will put the light on in a strobe effect, flickering on and off quickly about once every 50 milliseconds or so. Seizure inducing!

This will be released in a future update.

Stay tuned!


========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

Managing Multiple Heroku Accounts

Let's say you have multiple accounts on Heroku for whatever reason, maybe some personal, some business.

When using heroku-cli, it expects you to basically always be signed in to only one account, meaning you have to keep logging in and jumping back and forth between different accounts via heroku login. It's kind of annoying.

I took ten minutes today to write a shell script called herotate which manages your heroku-cli active login file, a hidden file called .netrc in your home directory.

The script will move this file into a configuration directory and create a symlink to it, so all your heroku stuff will work as it normally does. When you want to add a different account, simply herotate unlink, and sign into a new account. 

 To make things even faster, you can manage multiple configurations inside of herotate as long as they all have different file names and live in the same configuration directory, which the script will echo out to you if you run it. By default, your config is named main but you can rename it and the tool will automatically continue to populate the directory with any new .netrc files.

You can symlink a config of your choosing at any time using >herotate link <config> and list all of your configs using herotate list.

Hopefully this simple script helps you manage multiple heroku-cli logins just like it helped me!

Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

Saturday, December 19, 2020

More Flexible PYDroid

PYDroid 22.2.8 was recently released which allows you to create a component which is composed of multiple UiViews which all handle different subsets of a UiViewEvent instead of handling the same UiViewEvent. This allows you to separate UiViewEvent models up into things like just events for list loading, versus just events for error message displays, and the like.

Imagine the following:


sealed class MyViewEvent : UiViewEvent {

  object ButtonEvent : MyViewEvent()
  object ListEvent : MyViewEvent()

}

class MyViewModel : UiViewModel<MyState, MyViewEvent, MyControllerEvent> {

  handleViewEvent(event: MyViewEvent) {
    return when (event) {
      -> ListEvent -> listWork()
      -> ButtonEvent -> buttonWork()
    }
  }
}

class MyButton : BaseUiView<MyState, MyViewEvent, MyControllerEvent> {

  // Because it implements MyViewEvent, which was 
  // a requirement to be in a Component,
  // it is aware of, and can wrongly use MyViewEvent.ListEvent

}

class MyList : BaseUiView<MyState, MyViewEvent, MyControllerEvent> {

  // Because it implements MyViewEvent, which was 
  // a requirement to be in a Component,
  // it is aware of, and can wrongly use MyViewEvent.ButtonEvent

}


you can now separate the view concerns like so


sealed class MyViewEvent: UiViewEvent {

  sealed class ButtonEvents : MyViewEvent() {

    object Clicked : ButtonEvents()

  }
  
  sealed class ListEvents : MyViewEvent() {

    object Loaded: ListEvents()
  }

}

class MyViewModel : UiViewModel<MyState, MyViewEvent, MyControllerEvent> {

  handleViewEvent(event: MyViewEvent) {
    return when (event) {
      -> ListEvents.Loaded -> listWork()
      -> ButtonEvents.Clicked -> buttonWork()
    }
  }
}

class MyButton : BaseUiView<MyState, MyViewEvent.ButtonEvents, MyControllerEvent> {

  // Because it implements MyViewEvent.ButtonEvents, 
  // it can only use the Clicked action
  // and it can still be created into a component
  // with MyViewModel, so no code changes in the
  // createComponent callsite.

}

class MyList : BaseUiView<MyState, MyViewEvent.ListEvents, MyControllerEvent> {

  // Because it implements MyViewEvent.ListEvents,
  // it can only use the Loaded action
  // and it can still be created into a component
  // with MyViewModel, so no code changes in the
  // createComponent callsite.

}


More changes will be coming soon to PYDroid to help you better share your component views between different ViewModels and UiControllers.

Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

Thursday, December 17, 2020

A Weekend with Animal Crossing

I was asked by my girlfriend to create a tool for her and her other Animal Crossing playing friends where she could keep track of a "wishlist" of items in the game that she wanted and her other friends would be able to check off items that they were planning on gifting to her, like an Elfster
for Animal Crossing.

Using simple Firebase tools and some React I built a simple frontend for the ACNH Api which I could use to display all of the items in the game. I used Firebase's realtime database to power a collaborative editing experience which handled the requesting and gifting flows of the items. It uses Firebase Auth to handle a email link based sign in, and uses Firebase hosting to power the web page. Neat!

It's called Celeste, named after the cute friend who comes to visit islands on a starry night. Since you wish upon a star, and this is a wishlist for you and your friends, I found it appropriate to name it after Celeste.

Since this was just a simple weekend project I won't be continuing it much further for the time being. My girlfriend found a fully running replacement site which I highly recommend you look at if something like Celeste has interested you. All in all, a fun weekend project and a nice look at how simple some of the hosting and platform services have become.

Find Celeste here

Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

Saturday, December 12, 2020

Some updates

PYDroid has been updated a bunch over the past couple of days to test the new in-app rating and update systems. I believe it finally to be stable, so the PYDroid version you should upgrade to from 22.0.4 is actually 22.2.7

Yeah, it took that many different build-test-deploy cycles until I finally ironed out all (most (some)) of the bugs.

FridgeFriend has been published with a new version bringing support for multiple Groups of Items, and all other apps are going through the internal and public beta channels. They will be published most likely later in the week.

I strongly recommend you update to these latest versions as they contain a bunch of fixes and improvements and better prepare you for any future updates as well.

Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

Tuesday, December 8, 2020

PYDroid Autopsy

PYDroid Autopsy is a new library which helps during development by showing a crash report page on the device when an application exits due to an uncaught exception.

PYDroid Autopsy is a debug only library which requires 0 code changes to use as it self-installs via a debug only ContentProvider. It overrides the UncaughtExceptionHandler, and does not call through to any other handlers, so be warned if you are using other tools during development that Autopsy is currently not compatible with other tools which override the handler.

PYDroid Autopsy shows a red crash screen as well as the stack trace whenever a crash occurs and the device is able to capture the crash before exiting. While this is not a 100% solution, it more often than not will help catch crashes in development. It will also fire the stacktrace to logcat for those connected to the Android debug tools.

Try it out today! Find it here.

Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

Faster Apps Better Libraries

It

Has

Been

A

While

First, the nerd stuff

PYDroid

Remember in your past life, PYDroid took this sort of stance

"When PYDroid triggers your view on a render event, it does not take the care to avoid duplicate re-renders when no data has actually changed. We believe it is best to handle re-renders in the UiView layer itself."

Ya so, times have changed thanks to StateFlow and its amazing ability to only fire events when attributes of a state have changed. Yay!

The old onRender(state: S) has changed to an onRender(state: UiRender<S>). The UiRender<S> is an interface which can allows the calling view to subscribe to changes and either emit the full state object, or only emit when a particular attribute on a state changes.

interface UiRender<S> {

  fun render(scope: CoroutineScope, onRender: (S) -> Unit): Unit

  fun <T> distinctBy(distinct: (S) -> T): UiRender<T>

}

This can improve performance dramatically in apps because now only certain relevant parts need to render when their relevant state piece changes. You still have all of the strengths of knowing that your state object is a single source of truth, but also gain the performance benefits of only drawing when you need to.

The distinctBy() function is useful for cases like, you want to show or hide a view based on a loading boolean, but the boolean does not control what data is present in the view. Before you would have:

fun onRender(state: S) {

  handleComplexChange(state)

  handleLoadingChanged(state.isLoading)

  handleDataChanged(state.data)

}

and both of these methods would get called even when just the loading state changed, or just the data state changed. Now you can be more specific:

fun onRender(state: UiRender<S>) {

  state.render { full -> handleComplexChange(full)

  state.distinctBy { it.isLoading }.render { loading -> handleLoadingChanged(loading) }

  state.distinctBy { it.data }.render { data -> handleDataChanged(data) }

}

For views that are more complex or derive their state from multiple attributes, the old expensive way can still be had by simply calling state.render() without any distinct filtering.

Migration should be made less painful by the fact that existing onRender(state: S) functions will continue to work, but are deprecated. Note that if you use your own custom class extending UiView instead of BaseUiView or PrefUiView, you will have to make a small API change to respect the new API. To keep existing behavior, call a plain render similar to the example above's handleComplexChange function call.

For UiViewModels, the state handling has been separated out to make the ViewModel less complex. UiStateViewModel<S> is a ViewModel which only handles accessing and mutating view state, it does not have bind hooks or clear hooks, and does not publish events to a controller. UiStateViewModel is powered by a UiStateModel<S> which is the class that actually handles a view state with accessors and mutators. This can allow you to use the PYDroid state model without needing to extend the full-fat UiViewModel, or even re-use a UiViewState modeled via a UiStateModel but have it interact with completely different UiViewEvents and UiControllerEvents in multiple UiViewModels.

The UiStateModel withState() function has been deprecated. To get the current state from within a state model, simply access it via the state variable. The setState function has also received an extra optional parameter, called andThen: (S) -> Unit, which is called only if the setState call results in a state change. In a future major version these deprecated functions will be removed.

PYDroid has also removed its custom update checking code and review prompting code in favor of Google's Play Store solutions for in-app updates and in-app reviews. This is done to make it easier to maintain these features, as before we were using a home-grown solution and Google's is much more battle tested, despite it resulting in a reliance on the Play Store. But, pyamsoft applications have only ever been published on the Play Store, so I do not see this lock in as a huge issue.

All pyamsoft applications have received support for the full-bleed window style when using gesture navigation. Gone are the days of a colored sliver of navbar where the gesture bar sits on the bottom of the device. Now the gesture bar will be transparent and will give a more modern Android look and feel.

FridgeFriend has gained support for multiple Groups of items instead of just one large Group of items. The multiple groups can be broken up into anything you find logical, like locations, or different fridges, or even by meal or food group. There is no strict system around what you can, and cannot do.

With recent Google restrictions to accessing location, FridgeFriend has made some changes about when it suggests you stores that are nearby. We already did not use Geofencing because of these restrictions, and do not request BACKGROUND_LOCATION, but Google has decreed that even a foreground permission level request, but made by something like WorkManager counts as background work. As such, you will only be able to receive nearby notifications from now on when you open the application.

Plenty more is soon to come and I hope to have a release out soon, but for now enjoy the holidays and stay safe.

Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================