Clone wiki

kdrecall-apps / History

KD-reCall: A mobile suite of simple reminder apps.

Tech Used

  • App Interface: Flutter, Dart, PHP, MySQL
  • Web Interface: HTML, CSS, JavaScript, PHP, MySQL

Revision Synopsis

The basic beginnings:

  • Database tables and relationships outlined, structured, and modeled.
  • Web-based authentication system setup (based primarily on my custom auth system from both and
  • Web-based authentication testing setup with Selenium IDE.
  • Mobile app structure created.
  • Mobile app authentication routing and page setup.
  • Mobile app auth testing setup with Flutter testing.
  • Web-based pages refactored to reflect mobile app theming.

Revision History


  • [web] Initial commit for KD-reCall.
  • [web] Incremental development update.


  • [web] Incremental development updates.


  • [web] Working on session handling.
  • [web] Finished PHP session handling.


  • [web] Initial split between auth for both web and app.


  • [web] Worked on /auth. Renamed /app to /api.
  • [web] Auth path still working. API: Login and Logout are done (w/ JWT).


  • [web] Progress: Auth flow, session control, and some security (removed JWT)


  • [web] Started userData object population from server for client on login.
  • [web] Added pertinent user obj props. Setup whichApp and app_id usage.


  • [web] Authentication implementation / merge / refactor.
  • [web] Authentication: Added app_id
  • [web] Authentication: Added removeAll(). 'app_id' adjustments.
  • [web] Authentication: Added [whichApp|whichForm]_array, api/[verify|reset|dnd], api/http_responses. Bug fixes.
  • [web] Authentication: Finished api/DND.
  • [web] Authentication: Finished auth/DND. Bug fixes and code tweaks.
  • [web] Authentication: E-mail adjustments. DND refactor. Finished auth/reset.


  • [web] Auth: Refactored auth/reset to require username if not logged in. Changed PASSWORD_BCRYPT to PASSWORD_DEFAULT.
  • [web] Auth: Completed final revision of flowchart diagram.


  • [web] Auth flow source asset file updates.
  • [web] Auth: Added login logic to reset ref. name. Added 'resend'.
  • [web] Added 'api/reset'. Added active user orphan token check. Fixed expiration check.


  • [web] Auth: 2 DB updates. Implemented create_user_tables. Began allowing for multi-app registrations.


  • [web] Auth: Working on allowing login to register a new app - having to do some refactoring.
  • [web] Auth: Cleaned up files and fixed some bugs. Adjusted tests.
  • [web] Auth: Got user preferences showing on preferences page.


  • [browser extension] Took two weeks off to create a browser extension.


  • [mobile] Initial commit of mobile app source files.


  • [mobile] Structural refactor and UI completion of login screen.


  • [mobile] Login UI complete. Began testing.


  • [mobile] Got some testing to work using lists, maps, and loops.


  • [mobile] Getting caught up: Field-level testing is done. Login is done.
  • [web] Getting caught up: Field-level testing done. Login done.


  • [mobile] Just preserving where I'm at: API token logins ~70-80%.


  • [mobile] Login and logout with token working through app via API.
  • [web] Added app_user_access table w token. Began login/logout auth flows.
  • [web] Progress on login/logout flow with token.
  • [web] Login and logout with token working through app via API.


  • [mobile] Auth page near complete. Starting on forgot password / password reset.
  • [web] Progress on logout.
  • [web] Progress on login, logout, and registration / verify.
  • [web] Updated 'reset' and 'dnd' verify API pages and their email verbiage.

2020‑08‑09 [mobile, web]

  • [mobile] Forgot/reset password complete. Authentication screen complete.
  • [mobile] Cleaned some code. Added printK(). Added _nameRef to logged in appbar title.
  • [web] Added verifyAndReset form.

2020‑08‑12 [web]

Current primary focus from here on out is on completing the web authentication pages 100%. This includes finalizing the FAQ/terms/privacy/about panels, then will finalize the preferences page. All the while fixing and tweaking things along the way.

  • Split out Hungry readme from kdrecall readme.
  • Added getUserFromUID() for logged users. Removed access_code. Added 'exit()' after all header('location').

2020‑08‑14 [web]

  • Finished with sessions. Another landing page iteration.
  • Got index, landing page, and preferences layout code ready for boilerplating.

2020‑08‑15 [web]

  • Moved images out of _img and into _assets_src

2020‑08‑16 [web]

  • Added boilerplate templates. Added side drawer. Reduced placeholder text.
  • Still working on preferences page.
  • Made landing page responsive. Added contact form. Moved kdrecall.js include into _bottom. Added placeholder for links to app store.

2020-08-17 [web]

  • Finished outline of structure for the primary files (index, login, logout, preference, meta, _bottom)
  • Finished extrapolation of asset usage for same files (CSS, JS, [meta: css], [_bottom: js])
  • Finished colorizing outlined usage in RightNote. This allowed me to spot who is including what and where, thus spotting and removing two double-calls to kdrecall.js.
  • Finished layout of preferences page in drawio. Created two views; wide and thin. Exported as PNG.
  • Worked a bit on preferences page. Now that I can see what I'm aiming for, got all the HTML elements lined up and ready for CSS formatting.
  • Started a bit on FAQ/terms/privacy wording (copied files from PetRefApp same as contact form).

2020-08-18 [web]

  • Fixed burger buttons on faux appBar.
  • Created _includes folder and shifted files.
  • Got FAQ and About panels laid out and formatted.
  • Converted <div>s to <a> tags for keyboard nav. Added keydowns and .focuses.

2020-08-19 [web]

  • Went through wording in privacy panel.
  • Began analyzing various modal entries and exits.

2020-08-20 [web]

  • Began checking through tabbing on page.
  • Added a closed tabbing loop on the contact form and the side drawer.
  • Added privacy, FAQ, and contact form to footer.
  • Created a 'modal endpoints' structural outline.
  • Prettied up footer links.
  • Added focus to hovers.
  • Converted clickable divs and spans to a tags.
  • Added keypresses to clicks.

2020-08-21 [web]

  • Fixed and finalized closed tabbing loop on side drawer and contact form.
  • Added and finalized tabbing loop on FAQ and Privacy modals.
  • Prettied up all the modals; made more consistent with each other and the site.
  • Think I'm done with the layout, formatting, and functionality of all the modals.
  • 4 modals
  • 8 entrances
  • All escape endpoints
  • All keyboard inputs for constrained keyboard navigation
  • Keyboard navigation of entire index page is complete.

2020-08-22 [web]

  • Shuttered the app detail blocks instead of expand-dropping them all in at once like a curtain call.
  • Brought all four shutters up from the bottom, and coupled them with fade transitions.
  • Made hero logo image clickable; added alt and title properties.
  • Fixed two text links in appBar.
  • Added some missing hrefs.

2020-08-22/23 [web]

  • Done with verbiage, layout, and formatting on the FAQ, About, Privacy, Disclaimers, etc.
  • Moved 'About' from Privacy to FAQ and updated references.
  • Updated individual page meta titles and descriptions.
  • Fixed error: When logging in, .toLowerCase() error on undefined.

2020-08-23 [web]

  • Done with preferences page general layout.
  • Applied a responsive breakpoint at 720px.
  • Changed 'login status' to checkbox icon.
  • Got all the form posting mechanics in place.

2020-08-24 [web]

  • Done with styling toggle buttons. Instead of a switch, using an input="range" and custom styled slider. Sliders can be 0-1, 0-1-2, 0-1-2-3, etc.
  • Slider styling thanks to: Daniel Stern
  • Browser compatibility cross-checked with: CSS Tricks
  • Added a 950px media query breakpoint. This widens the interface from 768px out to 900px --- helps a little on the preferences page; not so much on authentication pages, which have their own styling.
  • Began entering HTML code for pop-up tips.
  • Removed "themes" from preferences page (display: none). Will get to them later if there's even any interest. Dark mode (theme) will suffice for now.

2020-08-24 [web] (technically; 08-25 @1:52 AM)

  • Setup a preferences data object.
  • Sliders now update the data object, then provide feedback to the preferences panel. Data object will also populate on button save.

2020-08-24 [web] (technically; 08-25 @4:15 AM)

  • Finished with Preferences layout and formatting.
    • Moved 'Show Help' section to be alongside Global Dark Mode.
    • Added a question mark icon showing 'quick tip' pop-ups for 3 fields.
    • Added a checkbox for option to change password.
      • Will need to setup an intermediary screen for capturing current, and setting new password.
    • Ready for form validation and submission.

2020-08-25 [web]

  • Added quick tip pop-up cancel buttons.
  • Created a 'quick tip' pop-up for the various field-level validation requirements.
  • Fixed the Save and Reset buttons on narrow screens; made responsive.

2020-08-25 [web]

  • Began adding code for password fields.
  • Added 3-sec countdown on login.
  • Fixed reference name error.
  • Tweaked quick tip box.
  • Stopped sliders from updating prefsObj (original values); will be kept immutable.
  • Getting a handle on how the form submission is going to work;
  • Email change requires current password.
  • Password change requires current password, new password, and a confirm password.
  • None of these fields are present on the original preferences screen.

2020-08-26 [web]

  • Added visual feedback when individual preference settings are changed.
  • For the sliders, feedback is immediate as the sliders are moved.
  • For the text inputs and textarea, feedback is when the field loses focus (blur; not worth a keydown listener).
  • Added visual feedback when sliders are focused via keyboard.
  • Determined password fields should be directly under their respective form fields.
  • Finished the mechanics of adding dynamic password fields for both email or password changes.
  • Email changes require current password.
  • Password changes require current password, new password, and new password confirmation.
        - Chrome complained about having two password fields; suggested separating out forms.
        - These fields are a part of the overall form though; they're just dynamically toggled.
        - Thought about it, and my initial approach on how to do the two passwords seemed to work.
        - When hiding either of the relevant input fields, also set their attribute to `hidden`.
        - When displaying either of the relevant fields, set their attribute to `password`.
  • Enabled auto-focus on dynamic password fields (hopefully click-then-lose-focus won't be an issue---will play around with it some).
  • Moved form validation requirements quick tip button to bottom; is now a full-width button above submit/reset buttons.
  • Removed question mark icon from validation requirement button, and stopped the bubbling <b> tag.
  • Renamed input-text to input-tip-text for clarity.
  • Removed 'app description' (clutter).

2020-08-27 [web]

  • Disabled login button on click. Reenables on error.
  • Misc tweaks and fixes.
  • Password fields are expanding out nicely.
  • Fixed issue with sliders popping back to name field.
  • Apparently sliders don't get focus by default when changing them, so manually applied .focus().
  • Fixed password min length on login.
  • Consolidating validation constants in [page_overlay_js.php].
  • Technically there should be a more global version of 'runa.js'; one that 'runp.js', and potentially others, could leverage as a shared-scoped parent.
  • Began adding code for form post return messages.
  • Began pruning and adjusting client side validation code.

2020-08-28 [web]

2020-08-29 [web]

  • Set session to auto-timeout (will redirect to log in on any subsequent activity).
  • Added in requirement for whichApp on all preferences form submissions (not just user ID).
  • The API file app_prefs is a culmination of four other API files.
  • Initial gathering and go-through of all the major code pieces.
  • Aggregated and trimmed a lot of the code within.
  • Not posting to it from runp.js yet.

2020-08-30 [web]

  • Began posting to app_prefs. Although currently a complete Frankenstein, got the file to load without error (posting from runp.js).
  • Fixed session error. Moved the include call to _core to be above session activity checks.
  • A lot more code gathering and trimming inside app_prefs. Blocked out 3 major sections; top (initial sift), middle (in progress), bottom (TBD).

2020-08-31 [web]

  • Continued the overhaul on the still-Frankensteined app_prefs API file. Got the major field sections grouped (email and password, name, notes, and the 3 sliders), although still quite rough.
  • Began adding setter methods to the primary class object.

2020-09-01 [web]

  • Filtering user's notes. Using a programmatical textarea to pass PHP-filtered notes to JavaScript.
  • Fixed a double ternary (in PHP you gotta wrap that second ternary!)
  • Added function to clear changed fields.
  • Worked on reference name and slider validation.
  • Updating initial prefsObj with changed field data.
  • Additional class object updates.
  • Fixed user_reset table to allow for ON UPDATE CASCADE.
  • Fixed user_notes table; made user_id UNIQUE and increased notes to 5,000 characters.

2020-09-02 [web]

  • Cut session timeout from 5 hours to 1 hour.
  • Changed email field to trigger change event when user has stopped typing for half a second. Ergo, when the email field changes, it will no longer wait for the field to blur, but instead will show the 'current password' field near immediately after the field is changed.
  • Fixed 'error flow-through' issue --- when one field validation failed, subsequent field validations would continue.
  • Cleaned up session stats at bottom of preferences screen. It's now minimized by default, and only shows two stats (hid the two 'previous' session stats). Also added a small scrollIntoView on the footer (after the CSS animations are done; 1s).
  • All error handling now only posts log entries to server.
  • Added and preferences-testing.ods to source assets.
  • The web-based preferences interface is complete.

2020-09-03 [web]

  • Structured and formatted 2 of 4 ancillary pages; password reset and DND.
  • Started on 'user removal'.
  • Tried a handful of locations and layouts.
  • Ended up going next to 'Change Password'.
  • Initially going with confirm alert dialog.
  • No call to back end yet.
  • New rule: Loosening up on periods and commas being inside quotes, especially within all my 'programming endeavors'.

2020-09-04 [web]

  • Structured and formatted remaining ancillary pages; verify and logout.
  • Determined new user removal layout and process.
  • Moved to a modal for user removal functionality.
  • As with the footer link modals, made it keyboard friendly.
  • Providing a removal notice, input field for current password, and a submit button.
  • UI and UX feel good.

2020-09-05 [web]

  • Completed user removal process.
  • Added supporting method to class object.
  • @JavaScript Fetch Form Posts → know what you're sending; post data or JSON.
  • Added account removal success message to KD-reCall home (index) page.
  • Completed preferences page
  • 'Completeness' status was previously correct---for the time it was written; I did not account for user removal ... figured it was going to be in the side drawer panel menu, which is where I began with it.
  • Extracted out the embedded CSS into its own file.
  • Changed out all [http_status] to 200 and added a [xsfer_status] with their relevant http status codes. Change all: http_status = 200

2020-09-06 -- 2020-09-17 [mobile]

This last week and a half is mostly just a blurred mixture of learning, trying, fixing, and a little actual programming.

  • Added option to save email address on login form (after a successful login).
  • There was a three day delay in figuring out how to populate a form field after an async call.
  • I posted my findings on Stack Overflow.
  • Added option to reveal (unmask) password.
  • Added Tooltips to both the 'save email' and 'unmask password' icon buttons.
  • Also integrated a TooltipTheme into the app's custom theme configuration.
  • Added an 'i'nfo icon in the app bar that opens an 'about' dialog showing info about the app.
  • Added ability to 'swipe-down refresh' the authentication screen.
  • Eventually derived an approach for shared route authentication detection.
  • Was considering going with a splash screen, but came to the conclusion that an intermediary splash screen is unnecessary.
  • Instead, just added a transient "one moment..." wait screen for authentication detection, along with an instructive welcome message on the authentication screen. The pass-thru "one moment" message is about all you have time to read while waiting to know if you're already authenticated or not, which just does an async check into the device's secure storage.
  • Fixed issue with server side error messages not being delivered to the snackbar.
  • Near three days later, during my second step-by-step widget-debugging step-through, I realized at one point it was hitting the router.
  • That led to the discovery that I had a 'notifyListeners()' at the end of one of the final form submission function calls. Oops.
  • Filtering this notifier call out of the login form submission fixed the error.
  • Updated minSdkVersion to 21 and targetSdkVersion to 29 per Codenames, Tags, and Build Numbers.
  • Codenames, Tags, and Build Numbers
  • Target API level requirements for the Play Console
  • Build and release an Android app

Current App Status for 2020-09-17

Knowing I've still got a few more topics I will need to dive deeper into prior to completing the pilot app, I'm still pushing for the end of September (less than two weeks). However, realistically speaking, Hungry-on-Hand will likely run into early October. I still need to create the preferences screen, and then the actual app itself.

The goods news, however, is the remaining apps should require less than 5% of all this developmental 'overhead.' Ergo, I 'should' be able to eventually code one KD-reCall reminder app every 1 to 2 weeks, tops.

Below is a screenshot of what the completed login screen for mobile looks like. You'll find the theme reflects the web-based interface that was completed earlier. And of course, each mobile app will have its own hero-subtitled image.

KD-reCall Login Screen

2020-09-18 [web]

  • Moved 'account removal' code from API (mobile) to POST (web) and refactored.
  • Because remove account is now a part of the preferences page, both web and mobile will split to their mirrored functionality, as is consistent with the rest of the project.
  • I thought the two could share this functionality---it was a poor and short-sighted decision. On a split-interface project such as this, we need structural code consistency!
  • Yes, some of the back end code sections are duplicated, sometimes verbatim even, but merging code functionalities should be done as a whole, not piecemeal (and what's the ROI?)
  • A couple other refactors are in order as well (@TODO:). One in particular is moving the throttle logic from back end form handlers to back end classes, as is done already in a couple places (and it's awesome!)
  • Fixed issue with registration verification page found in error log.
  • Fixed issue with redirect not working after account removal.

2020-09-19 [mobile]

  • Added cancel button to forgot/reset password pop-up.
  • Made hero image clickable (shows 'about' dialog).
  • Refactored entire 'submit()' function to better flow through the API responses.
  • Outsourced 'showInfoDialog' code as a static method in its own auth_helpers class.
  • Lots more research and relearning on the overall Provider package concepts.
    I'm now branching past just the authentication screen, and need a better understanding of the multi-provider routes I have setup.
  • Began playing with dark mode theme. Lots to do, but going to solely focus instead on preferences screen.

2020-09-20 [mobile]

  • Began prepping for creating the Preferences screen.
    Gathered preference properties from web-based code.
  • Setup a data object that includes a few static const map properties (to emulate 'enums with values').
  • Outsourced those enum-with-value constants for comparison logic in other screens, and the main.
    Started with a skeleton screen file.
    Started with a skeleton provider file.
  • Will bring over coding structures from Auth() and some other classes.
  • Swapped out my test 'isFavorite' with the more proper 'isDark' (still hard coded).

An example of the static const maps now used as 'enums with values' thank to @Nae on Stack Overflow:

  class LocalDarkmode {
    static const kd_off = '0';
    static const kd_on = '1';
    static const kd_global = '2';

2020-09-21 [web - other]

Having been working with debugging my KD-reCall web-based preferences API, I got the idea to do a search on my entire domain for "error_log".

Sorting the results yielded some unexpected current findings. I then recalled that I did put up some temporary parking pages for quite a few of my utilities when I upgraded to PHP7. Those, coupled with a half dozen other findings, kept me busy for about 15 hours.

And yes, that was "results," as in plural. I have over a decade of projects created using a variety of technologies, but a LOT of those projects are 2002–2010 PHP files, which, after upgrading to MySQLi and PHP7, are still run wonderfully.

A quick list of the web apps I fixed are: - PHP/MySQL Form-a-Form - Guess-a-Number - TWG Hall o' Fame - My B to B Online Business Form - WoW Blog, journal, and character pages - My first photo album - Personal countdown calendar - Pick-a-Meal

2020-09-22 [mobile]

  • Extracted out the AppBar into its own widget class.
  • Extracted out the entire body's Stack(), which accepts a custom child widget as its innermost content Card().
  • Got Prefs screen started pretty good.
    I'd say I'm about 20% through the UI screen file initial setup.
  • Got Prefs provider data initially setup pretty good.
  • Created the isDark functional logic in the Prefs provider based on Auth()->UserInfo settings.

2020-09-23 [mobile]

  • Got all the critical errors cleared in both 'prefs_p.dart' and 'prefs_card.dart'.
  • No logic yet, and all the fields are complete Frankensteins, but the screen comes up.
  • Conglomerating data flow through AuthData and UserInfo to gain insights on how Prefs() fits into it all
    (i.e. provider-level data sharing and access, routes, and themes).
  • Created a code skeleton composite for a broader view of the data and interactions between the app's main, provider, models, and screen files.
    Creating and updating diagrams and flowcharts, although time consuming, can help immensely in walking back through the code in detail, oftentimes revealing flaws along the way.

2020-09-24 [mobile]

  • Finally got all the code, data, and flows lined up in both prefs_p (provider file) and prefs_card (functional inner-screen widget---each screen has its own).
    Getting a little better handle on data initialization at the 'forest level'.
  • Began adding a couple input listeners ('email' and 'nameRef').
  • Started up app.
    Error --> Changed out provider initialization call with a hard-coded true in main.dart.
    Error --> Something something on a null object --- But the screen came up!

2020-09-25 [mobile]

  • Fix for #2:
  • Removed _localPrefsData initialization from the Prefs() build, and now initializing when instantiating. PrefsData _localPrefsData = PrefsData();
  • Fix for #1: After further research I have determined I need to refactor my app's theme approach.
  • Search topics: "MultiProvider" "consumer" "themedata"

About to take a new trek on my app's theme setup. - My original themedata findings didn't account for the isDark: true being set dynamically. :(

Current Status: Two steps forward, one step back. Going to have to refactor the app's entire theme approach. It's a learning process. :)

2020-09-25 [mobile] - Part 2

As previously mentioned, couldn't get dark mode set dynamically via Provider within my current theme setup, so I researched and found a more comprehensive approach to theming.

New theming implementation: - A review of their code didn't look like it would work. - Installation of their demo files from GitHub produced at least a dozen errors. - But after fixing the criitical errors, the app came up and worked. - It was beautiful!

But what worked wasn't dark mode ... what worked was the ability to switch between custom preset themes. Wow!

To be honest, I'm still processing what this new theme approach just accomplished---my first, second, and third thoughts are that it's awesome! But, I'm still factoring its functional integrity, how it applies to dark mode, and how & IF it really applies to fully custom personalized themes---something I had set aside for the pilot app's development.

Having themes this easy feels too good to be true, but I saw it working before my very eyes, in both their app and my own, so I just need to let it sink in and process its flow and application. If this turns out to be a solid approach, as I will find while completing the integration, I will also need to reactivate preset themes on the web's preferences page, test the API endpoints, and still implement dark mode (but should now be able to do through this new theming mechanism).

The new theme approach was provided by FlutterDevs via their GitHub repo, and explained in their Medium walkthrough: Multi Theme Using Provider in Flutter.

  • Their approach was uniquely insightful in that it provided the missing details on how to use their theme's ChangeNotifier (in the provider file) with the ChangeNotifierProvider in the providers List[].

  • Secondly, in all my learnings, I've not seen an example of where the ChangeNotifierProvider was used as a child: of the MultiProvider, even though it's also been configured in the providers List[]. This feels like an advanced approach for the Provider package perhaps? The Flutter documentation also only shows the ChangeNotifierProvider being configured in the providers List[].

Their Medium article's walklthrough also references Panache: A Flutter Material Theme editor. As stated on the Panache website,

  • Panache helps you to create beautiful Material themes for your Flutter applications.
  • Customize widgets colors and shapes, and download your theme.dart file.

In summary, I swapped out the Theme class for a ThemeModel. And although I do find this theming approach is a significant bonus for the app as a whole, I will need to spend some time to complete the theme's integration, as well as developing out all the resulting action items.

2020-09-26 [_]

  • Day trip to Sacramento.

  • Still not yet processed the application and effects of the new theming system.

Between refactoring the app's entire theme, adding custom preset themes back into development, and today's day trip, the pilot app's delivery has shifted to mid-October.

2020-09-27 [_]

  • Another detour:

My project showcase domain at is a masked redirect to content provided from my personal portfolio domain on I sat through chatting with half a dozen CS tech reps while setting up the SSL, and, as usual, learned a few new things about my domains along the way.

  • Stuck again in some 'lack of knowledge' muck.

I spent some time trying to get button font sizes increased via the new theming system now in place, only to find that none of the ThemeData properties provided by the new system work. Well, they may be working, but nothing is set to take advantage of whatever is working ... perhaps? I certainly saw something working!

I do know the primary and secondary colors I have setup are working, because the app's colors look almost back to normal (excepting a few blue colors here and there).

Need to process.

2020-09-28 [mobile]

A new approach:

  • I brought back up the demo theme project and went through file by file.
  • I took a forest-level look at what it is I'm trying to accomplish, and what I currently have set in place to accommodate what needs to be done.

@5:02 PM I figured it out.

  • In the MaterialApp widget, there is both a darkmode, and a theme property. tl;dr, ne'er the twain shall meet.
  • The darkmode property will be used in certain cases, and the code for the new theme system I'm using had both set.

@11:40 PM

  • Added in two color themes from Panache ('paprika' and 'yellowish').
  • Refactored the code based on my new understandings and got it working. Some icons change, and the button font size changes. Lots of work ahead in tweaking it all.

@1:45 AM

  • Got it working even more ... scaffold and backgrounds all swap out. WOOT !!!

2020-09-29 [mobile]

Got login screen prettied back up.

  • Adjusted button fonts.
  • Added input padding (and letting other padding default back to EdgeInset defaults).
  • Themes are tedious.

Before logging off, noticed reference name wasn't showing up, although I know I'd seen it populated.

  • Determined the value was being cleared out by having an initializer at the top of the provider file.

2020-09-30 [mobile]

After working and thinking through my dilemma of the reference name being cleared out on the Preferences screen, it turns out I was only populating the _localUserInfo object with the nameRef setting on login. It wasn't being repopulated when its provider file was reinitialized, which I learned can occur quite often.

However, in the process of finding this oversight, I came across an even more perplexing issue. Just as the Prefs() provider class can be reinitialized at any time, as I found with the missing nameRef setting, as can the Auth() class, and its _localUserInfo object. This meant isDark was being cleared out with each reinitialization just like nameRef was.

But to avoid isDark from being cleared out, if we don't initialize the Auth() class until later (like in the _tryAutoLogin router call, which is where _localUserInfo is populated), that means that the initial isDark getter call for the app's theme has nothing to work with (i.e., the _localUserInfo object is null when called from the theme: property).

It was all quite perplexing, especially when trying to determine how, or even if, the ChangeNotifierProvider or ChangeNotiferProxyProvider components are involved, and if so, how?

@6:50 PM - Revelation: should isDark be just a "logged in" user setting? I hadn't thought about its actual usage, as I'm still figuring out and learning syntax and Flutter flows.

  • For starters, it's currently being set based on what's in Auth._localUserInfo.
  • Secondly, that information is populated during the tryAutoLogin() call in the routes property.

Thinking through this new perspective, I coded in what I figured to be the right setup, and everything seemed to work. As it sometimes happens, the result was fairly close to what I already had, but now armed with an understanding of why it wasn't working, I was able to make the one or two minor tweaks necessary to meet the new understanding of the expectations.

Business logic decision: The isDark logic is already in place for "logged in" users---ergo, logged in users will have the dark mode option.

  • Auth is initialized from the ChangeNotifierProvider, and isDark will default to false, initially, in every case.
  • tryAutoLogin() will attempt to restore the proper isDark based on _localUserInfo stored in the device's Shared Preferences.
  • The "One moment..." screen should be the only screen that has no dark mode, as that screen shows while the app asynchronously goes and grabs the isDark setting. That in mind, I may consider darkening the "One moment..." screen, as I believe, given the two scenarios, it is better to initially assume a dark mode.

Snippets of the resulting successful code with an understanding: isDark is a getter with Auth-based dependencies:


  MultiProvider( providers: [ ChangeNotifierProvider.value( value: Auth() // Nothing fancy here.
  theme: _showTheme(
    // authProvider.isDark,                            // Incorrect
    authProvider.isAuth ? authProvider.isDark : false, // FIXED !!!
  home: authProvider.isAuth
    ? PreferencesScreen()
    : buildFutureBuilder(context, authProvider),

2020-10-01, -02 [_]

Inadvertently spent two days on other life stuff ... with more life stuff coming up on Sun and Mon 10/04-05.

2020-__ [web]

Random updates to the KD-reCall web-based interface:

  • Added 'notes' field to getUserFromEmail query.
  • Fixed a null object error.
  • Removed console.logs.
  • Centered toggles on preferences screen.

2020-10-03 [mobile]

  • Success!

Got global dark mode to toggle on and off. And it remembers and sees it on the 'auth check' screen, and again on login.

Felt like at least a dozen tweaks, starting with my realizing the token was being sent back with the rest of the received preferences data. This is because it's required to be sent for user verification. So, I had to remove it out from the data object/array.

This led me to figuring out how to deal between PHP's JSON array objects and associative arrays. The problem was that I have a decoded JSON object, but then I add the received and decoded data into that JSON object, but that data is an associative array (or vice versa, depending on which "object" you're focusing on). So in coming to understand this, and accessing the array within the object, or the object within the array, it took a bit to wrap my head around to understand and figure out.

But in removing the token field, because PHP copies by reference, it also removed it from the JSON object itself, which is needed further down in the code. So that fix was to create a temporary token string prior to cutting it from the data object.

  $thisToken = $json_obj->userToken; //  // We're creating a copy of the token string, because, being a reference, removing 'userToken' from '$newObj'
  unset($newObj["userdata"]->userToken); // also removes it from '$json_obj->userToken', which is needed below.
Once that was done, I found each change of the dark mode setting triggered the 'auth check' screen. This was because I was also updating the userId, which triggers the auth route flow logic when set (apparently even if unchanged).

Once that was fixed, the 'check auth' screen kept getting hit on logout, and I was getting an error: 'Future' is not a subtype of type 'FutureOr'. This was due to my needing to change out all the pre-API method call parameters to accommodate the (new and) necessary dynamic list.

Future<Map<String, List<dynamic>>> logout() async { ... }

Side Note: I don't like using dynamic types, just as I didn't like using any(?) in TypeScript, but it was either that, or spend 2 to 3 days learning how to do PHP type casting gymnastics, as I did with my API responses in which everything that is sent back is an Array---even single response items; they're just a one-element array.

Summary: The happy path to updating all the preferences is open, and I believe I just now need to setup all the fields, add validation, add the overall submission, and preferences should be done. Guesstimation: 10/05 Monday evening, although preferrably tonight.

2020-10-04 [mobile]

In randomly chaecking through the app, I found the Forgot and Reset Password forms didn't work. They just hung. Hmmm...

@10/4/2020 7:05 PM

  • Got it solved.
    Holy holy wow wow!

I faced a DOS-level generic error with a stacktrace of little to no help. Stepping through the code, it just "jumped" from a simple call straight into the error -> catch block. The error was:

_TypeError (type '_TypeError' is not a subtype of type 'String')

Research might tell you this is a problem with not using toList() on a derived map. I must have tried at least two dozen different changes to my code, including adding potential toList() method calls in various locations that appeared could benefit from such a method. I changed code on both local and server-side, some of which were fortunately good and likely necessary changes. Other changes I'll need to revisit prior to commit.

It wasn't until I swapped out a .then() callback and assigned its await to a variable: This led me deeper into and closer to where my code was wrong.

I traced all the way back to the 'Forgot Password' button method, finding two more <String> types not yet changed to <dynamic>. This led to a search for <String>>. That search revealed another <String> type in the finishAPICall() method, and yet another in the receiveMsg() method.

Then I found one more in the reference to the showInfoDialog() method, found in the [auth_helpers.dart] file.

static void showInfoDialog(BuildContext sbctx, Map<String, List<dynamic>> statusObj) { ... }

2020-10-05 [mobile]

  • For help in keeping things visually structured, stripped out and created a code skeleton from the form fields in the [web] [preferences.php] file.

  • Moving along and getting things displaying on preferences page.

  • Have all the input field FocusNodes setup.
  • Have all the input field Controllers setup.
  • Started on slider toggles. Got the first one near complete (thanks to the head start by Stack Overflow). They'll need focus as well.

Need to start on functionality.

2020-10-06 [mobile]

  • Made a first test pass on the Prefs form.
  • More of the "jumping-to-the-catch-error-block" errors (String -> dynamic).
  • So many twists and turns:
  • By reading through one semi-lengthy error message in the debug console, among other potential/irrelevant issues and solutions, it informed me my Prefs provider might not be in the MultiProvider list.
  • Next error: Out of range. For testing, I was returning returnObj without populating a status (i.e. it was empty, but expected 1).
  • Next error: Had to add listen: false to 2 calls to Provider.of<ThemeModel> in the [auth_helpers] file.
  • And so many more...
  • Good progress. A lot to go.

2020-10-07 [mobile]

  • Toggling global dark mode now works, but... wondering if it's the right way.
  • Researching: if one flutter provider needs access to another provider (spoiler: changeNotifierProxyProvider, although I still don't grasp it fully).
  • Added slider toggle widget (with a little start from Stack Overflow) and got global dark mode to update via the Prefs provider.
  • Got all 3 sliders on happy paths.

Was working with trying to get the slider toggles to be round with a line between like the web interface: got close enough to see I'd rather have the buttons with my new labels ("Currently ON", "Turn OFF").

2020-10-06 -- 08 [web]

  • [PHP] Stripping returnObj (token, password, confirm, etc.)
  • [PHP] Fixed isWeb vs. isMobile logic, among many other fixes.
  • [JS] Now clearing password fields on success.

2020-10-08 [mobile]

  • Most of preferences screen is working.
  • Dark theme colors are much better.
  • Created a few custom text themes.
  • Toggle sliders look and work good.
  • Swapped colors between drawer and dark mode background.
    • Figured out and made adjustment to other colors.
  • Figured out how to get the multiline to add a new line.
        keyboardType: tfField == 'email'
            ? TextInputType.emailAddress
            : tfField == 'notes'
                ? TextInputType.multiline
                : TextInputType.text,
        textInputAction: (tfFocusNext == null)
            ? tfField == 'notes'
                ? TextInputAction.newline
                : TextInputAction.done
  • Fixed numerous bugs and logic issues (things change as the app grows and matures).
  • Change email works, but ... not thrilled it doesn't ask to revalidate.
  • I didn't set it up originally because I figured they're logged in, but this isn't a security issue, it's an owner/authenticity issue.
  • We need to know the email belongs to the user, else people can just use any "email address".
  • @TODO: It should set the account to a (new) verification status.

So, thus far about 85% of preferences is complete. - Just still need to go through 'Change Password' and 'Remove Account' functionality. - Then, will take the time to convert the 'change email' to require validation.

2020-10-09 [mobile]

  • Fixed numerous errors in my PHP coding logic wrt using in_array vs. array_key_exists vs. property_exists vs. isempty vs. isset.

  • Change password functionality is complete.

  • Had to fix the 'userInfo' not referencing the correct data.
  • Created a new method to retrieve the values direct from Shared Preferences and provide them back to the _initState call.

The issue is that I'm doing it mostly imperatively, because I don't have enough experience yet with the ChangeNotifierProvider and how they are all supposed to be magically connected. Need to study and analyze this more, but also need to finish this app. :)

Moving on to Remove Account, which needs its own screen widget.

  • Created the new Remove Account screen (quite crude). Tried running it and got a new error: no material widget found.
    > To introduce a Material widget, you can either directly include one, 
    > or use a widget that contains Material itself, such as a Card, Dialog, Drawer, or Scaffold.

I don't get it. I'm using the same structural setup from [auth_reset_form.dart] --- all the major Widgets are in place.

2020-10-10 [mobile]

  • Fixed previous issue temporarily by wrapping the Form inside of a Card widget.
  • Side note: This code was later (today) fully refactored based on my 'about' dialog.

  • Analyzing and working through the PHP 'remove account' and 'user token' control flows.

Found I've coded for two token comaprison approaches, but only using one of them --- for logout. - Research (minimal): hashed token comparison approach "hash_equals" vs. database lookup
#1: Get the hashed token and use hash_equals() with a newly created hash.
#2: Create a new hash and use it in a database where clause.

Of the two, I'm going to switch 'logout' to use #1, because that's its entire purpose, and I just don't think a database lookup is the best approach (could be wrong!). This approach is also suggested on Stack Overflow.

An example of my most common Flutter errors---that yield little to no stack trace help, and stepping through just jumps directly to the catch block:

'Future' is not a subtype of type 'FutureOr'
_TypeError (type '_TypeError' is not a subtype of type 'String')
flutter type 'NoSuchMethodError' is not a subtype of type 'String'

  • Finished fixing Remove Account.

Was putting too much logic in the modal. Just needed to run the removeAccount, then pop it off and return the result. Then on the fallback screen we can run the success/error modal and subsequent logout.

  • Remove Account functionality is complete.
  • Added verbiage and theming.

Moving on to requiring email validation for changing email address. - This will need to be thought through. - This is the last item left on the preferences screen.

2020-10-11 -- 12 [web]

This was a lot of work, and I feel the need to justify it (to myself)---if only to help isolate and adapt for future LOEs. - Project hindsight analogy: If I were to consider drawing a hand, I would visualize it as a fully detailed 'outline' in my head, but I tend to end up with a micro-detailed, pore-level hand rendering. Once you start drilling down into a project, then you can begin to see all the underlying factors involved. I try to factor as much as I can before starting a project, but I seem to find more nuances when I'm working in and through the code.

Began logic:

    // Email exists in [USER TABLE]                    *** Caution: Email exists ***
        // Need status from [RESET TABLE]              *** Check created_at date
            // created_at > 5
            // created_at < 5
    // Email doesn't exist in [USER TABLE]             *** Need to also check [RESET_CHANGE TABLE]
        // Email exists in [RESET_CHANGE TABLE]        *** Check created_at date
            // created_at > 5
            // created_at < 5
        // Email doesn't exist in [RESET_CHANGE TABLE] *** Clear: Add row and Send email with access code ***

Added: - Table [_RESET_CHANGE] - email_change to [web] API objects and flows. - Rudimentary UI elements with some CSS to get the ball rolling. - Went with the one new input field, and a checkbox to help control state. - Integrated email change field into JavaScript flow (prep for API call).

Removed: - updateMailAndPassFromUID() -> Will no longer process email and password together.

Created: - emailExists() - runChecks() - getUserStatusByNewEmail() - clearResetChangeEmail() - getEmailChangeCreatedByNewEmail()

Changes to: - updateEmailFromUID() - removeUser()

Modularized: - checkDateDf($checkDate = '')

2020-10-13 [web]

I tried everything to get Chrome to not autofill the password fields. Nothing works.

  autocomplete="off" // Set on both `input` and `form` tags.
  autocomplete="new-password" // Spec:
  autocomplete="chrome-off" // This is not a team-conscientious move.
Chrome has a "use case" page that apparently is just for people to vent all the reasons why autocomplete should not be forced into every-single-field-no-matter-what-despite-what-the-creators-have-in-mind. Personally I think if you're on a "change email" or "change password" that having the 'current password' is there for an additional secruity element, and having it autofill defeats that entire purpose. This also reminds me of Chrome now hiding extension icons by default, no-matter-what. Developers were allowed to voice their say... but turns out that was just a vent box too.

Per MDN: - autocomplete="new-password" - I submitted a 2-step report to MDN that apparently Chrome doesn't honor this anymore.

In the end, I'm going with:

  <form autocomplete="off">
    <input type="email" autocomplete="off">
    <input type="password" autocomplete="new-password"><!-- Per the spec -->

More work on API logic. - Got PHP syntax errors ironed out. - Uncommented out API call and began initial testing. - Got email sending and database updating. - Coding for updating new email in [reset_change] table is complete. - Also ran a few tests; same submitter (must wait), token expired (transparent), email is already active.

2020-10-14 [web]

Core PHP coding for email verification is complete, however, I actually completed the [mobile] version of the API code. - Because preferences uses the [api/app_prefs.php] API file, I had copied over the [api/app_verify.php] API file as my starter, instead of [auth/verify.php].

Ergo, - Completed change email API for [mobile] (untested---still need to work on mobile). - Now will convert to API for [web] so I can test the preferences [web] page.

Created: - [auth/changeemail.php]

Email change is done for [web]. - Now clearing change email address on preferences page load if expired. - Now differentiating between emailExists and emailChangeExists. - Needs more testing. - Needs <a> links.

Resulting functions: Note: All the names have been somewhat randomly modified. - function accessCodeChangeMailExists() {...} - function shouldChangeMail() {...} - function updateUserPassFromUID() {...} - function MailChangeExists() {...} - function getMailChangeStatus() {...} - function runMailChecks() { - return 'error'; - return 'error'; - return false; - return false; - return "error"; - return "same"; - return "verify"; - return 'verify'; - return 'dnd'; - return 'active'; } - function getUserStatusByNewMail() { - return false; - return 'error'; - return 'verify'; - return 'error'; - return 'error'; - return 'dnd'; - return 'active'; - return false; - return 'error'; } - function issetMailChangeByMail() {...} - function getMailChangeCreatedByNewMail() {...} - function removeResetChangeMail($thisMail = '') {...} - function removeResetChangeMailByID() {...} - function updateResetChangeMail() {...}

Final database changes:

        Added 'email' index
        email -> t_user -> cascade|cascade
        app_id -> t_app -> cascade|restrict

    `t_reset_change` [new]
        Added 'user_id' index | unique
        Added 'email' index
        Added 'reset_token'
        Added 'created_at'
        user_id -> t_user -> cascade|no action

I really did not see all the interactions and implications across the board that this was going to impact. This was primarily due to project fatigue. I don't encounter it often, but I'm not usually on the same project for 6+ months. The only reason I am in this case is because I'm laying the groundwork twofold: 1) I'm about to create 5-10 mobile apps all based on the same coding framework and authentication structure. 2) The authentication framework I've come up with attempts to cover all the authentication bases, and I'm doing it for both web (session auth) and mobile (token auth).

When registering, need to check [t_reset_change] to see if email is waiting to be 'changed to'. If yes, but >5 min, it's clear. - Email check for registration is complete.

2020-10-15 [web] [mobile]

DND: - Completed: when adding DND, also remove email from [t_reset_change] if exists (if email/DND link sent via a change email request).

This was slightly more involved than originally thought.

1) Need to check if email exists in [t_reset_change]. 2) Need to check if change email was set < 5 min. 3) Need to create a faux user and set status to DND. 4) Need to then remove email from [t_reset_change] --- On error, remove newly created user from #3.[1]

[1] Doing what I can to not have the same email in both [t_user] and [t_reset_change] tables, although an expired email in [t_reset_change] should eventually be removed programmatically if it's going to be in use [i.e. not DND]---hopefully I've got all my removeChangeEmail() methods in all the right places.

  • Added links to error messages.
    <a href='{$pathToLoginPage}'>log in</a>
  • Went through all @TODO: tags in code.
  • Began some testing.
  • Registration, verification, login, and changing password all seem to work as expected.
  • A couple errors were thrown, but could have been from one of my two DND attempts.

My little half dozen testing paths are a start, but will need to approach this much more systematically. There can be no doubts with these email changes and DND faux account creations.

2020-10-16 [web]

  • Sick day

  • Got testing worked out. Ended up with 39 paths; later expanded to 43 paths adding four log outs.

    Action ---->  As  Try to ---->  For Expiry
    ------ -----  --- ------------  --- -----
    Register -->  KD1 Register -->  KD1 < 5
    Register -->  KD1 Register -->  KD1 > 5
    Register -->  KD1 Verify ---->  KD1 > 5
    Register -->  KD1 Verify ---->  KD1 < 5
    Register -->  KD2 Verify ---->  KD2 < 5
    ----------->  KD2 Change email  KD1
    ----------->  KD2 Change email  KD2
    Change email  KD2 Verify ---->  KD3 > 5
    Change email  KD2 Verify ---->  KD3 < 5
    Change email  KD3 Verify ---->  KD2 < 5
    Log out
    Register -->  KD3
    ----------->  KD2 Change email  KD3 < 5
    ----------->  KD2 Change email  KD3 > 5
    ----------->  --> Verify ---->  KD3 < 5
    Remove  KD3
    Register -->  KD2 Verify ---->  KD2 < 5
    Register -->  KD3
    ----------->  KD2 Change email  KD3 < 5
    ----------->  KD2 Change email  KD3 > 5
    Log out
    Register -->  KD3 Register -->  KD3 < 5
    ----------->  --> Register -->  KD3 > 5
    ----------->  --> Verify ---->  KD3 < 5
    Register -->  KD4
    ----------->  KD2 Change email  KD4 < 5
    ----------->  KD2 Change email  KD4 > 5
    ----------->  KD2 Change email  KD2
    ----------->  KD2 Change email  KD4 < 5
    ----------->  KD2 Change email  KD4 > 5
    ----------->  --> Verify ---->  KD4 < 5
    Log out
    Register -->  KD5
    ----------->  --> DND ------->  KD5 > 5
    Register -->  KD5
    ----------->  --> DND ------->  KD5 < 5
    ----------->  --> Register -->  KD5
    ----------->  KD3 Change email  KD5
    Log out
    Register -->  KD6 Verify ---->  KD6 < 5
    ----------->  KD6 Change email  KD7
    ----------->  --> DND ------->  KD7 > 5
    ----------->  --> DND ------->  KD7 < 5
Now just need to implement.

2020-10-17 [web]

Created a (secure) PHP page to keep an eye on my 3 primary database tables during testing: [t_user], [t_reset], [t_reset_change]

In preparation for testing, I set out to delete the accounts I created from yesterday. I then spent half the day researching what broke the 'remove account' functionality.

  • Turns out, "I" had (who else?) added a logic check within the body of removeUser().
            function removeUser() {
                if ($this->clientHashCompare()) { ... }
  • ...making it consistent with [mobile], but!, only [mobile] does a token hash check, not [web].

==> [ 1.50 ] hours of straight testing. There are quite a few 'wait >5 min' steps, which gives you time to make notes and do a little analysis.

  • Went through all 39 testing scenarios---added four log out actions.
  • Fixed one error while it was still in an 'access code wait' mode.
  • The very last test broke. Could not completely add the faux account; created the [t_user], but failed on [t_reset] with app_id = 0.
  • Saved all test results from 3-sql page I created earlier.

Next step: apply same email change verification functionality to [mobile] and run through all the same tests.

Architectural Considerations

2020-12-23 [mobile]

I got to a point with my app where I just couldn't get the code to do what I needed it to do. Basically, I need to update various components from three different 'reactive' sources. Scouring the web, I tried dozens of variations with every aspect of the Provider package I could find data on. I got really close a couple times, but always, always hit a solid road block. Additionally, in the end, my entire code base felt really ... procedural (read, cluttered). I felt claustrophobic in my own code, and could not make heads or tails of all the different flows (and I've got plenty of DrawIO diagrams to show for it).

Pressing pause on development, I put myself through a Coursera series on Computer and Object Oriented Systems Design.

With a newfound deeper understanding of OOD, and after several failed attempts to outline CRC (Class-Responsibility Collaborator) cards due to my app's current convoluted spaghetti code, I ventured to learn the "Filled Stacks" architecture. That went really well, and I loved the Clean Architecture approach, but he lost me on TDD. After additional consideration, I resolved that I didn't want to become reliant on a 3rd party package. Especially with my still being relatively new, if something breaks in their architectural package, I wouldn't know that it wasn't me doing something wrong. A package such as that is highly beneficial to developers who have the years of experience and can simply know when something isn't working "as expected."

I had one architectural tutorial left to put to the test---Ray Wenderlich. To my delight, it was based on the Filled Stacks architecture, but didn't rely on the Stacked package itself. Unfortunately, although it gave me the insight of the architecture outside of the Stacked package, it didn't detail any reactiveness. But another huge plus was it showed me how to implement an abstract class with Dart, providing a crystal clear outline for switching between Dev and Prod data (e.g. for Web API and Storage data/access).

So, I then had two paths to my goal of a cleaner architecture---both with their own limitations.

Knowing these were still my best potentials for success, I took a(nother) chance. After double checking licensing on the code for both architectures, I extrapolated the reactive sections of the Stacked package, and merged in the essence of Ray's architecture, creating my own little architectural Frankenstein, which, when done, did not work.

Slightly baffled, I created a simple pared down skeleton version of the code I had just compounded into my own app, and lo and behold, it worked! That was 2020-12-19. After months of failure in finding a good architectural approach that solved my app's needs, I was too tired to be excited. Using the observable_ish documentation, I then expanded my pared coding test to also react to compound objects, which after some trial and error, also worked.

The next day I applied the compound object setup to my own app, making all the pertinent adjustments, and when done, it also worked. Woot!

Since that breakthrough, I've been working on continuing the refactor of the rest of my app to leverage the new reactive architectural design. It is tedious, but only because I still need practice in shifting my code around. At least now I can diagram my app without it becoming a game of Twister.

References: Coursera Object Oriented Design Filled Stacks Ray Wenderlich

New projected estimate for app completion: I have no idea but am hopeful for early 2021.

Getting Back on Track

Commit History

There have been so many ups and downs and ins and outs over the last two months, from this point on will simply be the commits that have been made during development.

12/20/2020 7:05:51 PM

  • Finally got multiple shared states across multiple components working---via Clean(ish) Architecture using Get_It and Observable_ish.
  • Slider toggles are working; now working on the Prefs form not saving the values somewhere (exposed on a swipe refresh, which reloads the route).

12/30/2020 11:53:45 AM

  • Got the login and logout flows working.
  • Got themes going again.
  • Got screens fading in (mostly).
  • Currently debugging a double build call on Prefs after login. Researching better debugging methods.

12/31/2020 4:05:04 PM

  • Wow. It works. Got a nice little fade/slide animation on screen loads (that only trigger once).
  • Added an [app_service].
  • Fixed both 'new user' and 'empty' form submit errors.
  • And the 'change email' checkbox now works again.

1/2/2021 2:36:05 AM

  • Found and fixed all icon colors between light and dark modes.
  • Set all print() to go through DevHelpers.printK().
  • Enabled screen transition for screen refreshes.

1/2/2021 9:01:50 PM

  • Fixed slider toggles submitting current values.
  • Could not reliably recreate drawer/keyboard issue.
  • Researched and prepped Drawer code for responding to opening and closing of drawer.
  • Removed superfluous code and made other coding adjustments based on flowcharts I created (using Drawio/
  • Made all [serviceLocator] calls final.
  • Added 4-point 2020 timeline to readme.
  • Fixed issue with logging out when only partially logged out.
  • Fixed issue with email_change and notes being passed back as null (added null coalescing).

1/9/2021 8:45:45 PM

  • Added SplashScreen.
  • Added Shared Preferences initializer to ServiceLocator: set main to async.
  • Moved all Shared Prefs and Secure Storage to their own StorageService.
  • Set up and began using an _appPages Map for routes (instead of a static const in each base screen file).

1/10/2021 4:03:38 PM

  • Added in preliminary code for core_base. Swapped out static const routeName routes.

1/10/2021 4:03:38 PM

  • Various updates to ancillary back-end files for structure and flows.
  • Began working on Core.
  • Added price to Hungry base SQL table.

1/23/2021 1:57:35 AM

  • Interim commit. Settled on using a CustomScrollView with Slivers and a pinned SliverAppBar.

1/26/2021 1:08:20 AM

  • Got all the columns laid out programmatically, and the order of columns able to be swapped (ready for Draggable).
  • Renamed unused files to 'z_' (treating as deprecated).
  • Renamed a couple methods to be more germane.
  • Attempt #1 at fixing the Prefs().isDark change, which reroutes to Core() instead of back to Prefs().

1/28/2021 1:06:41 PM

  • Implemented column reordering by adding Draggables and DragTargets.

1/29/2021 5:16:21 PM

  • Refactored data and methods from CoreList (CoreTable) Widget into ViewModel and CoreService.
  • Layout is laid out.

2/9/2021 11:30:02 AM

  • Created the actual Core Item Listing screen using a CustomScrollView with a SliverAppBar and SliverList.
  • The Core Item Listing screen takes an offline-first approach (PWA-style).
  • Added 'allCoreData' as a Core Item container List.
  • Added Core Item list settings as 'allCorePrefs' to track column order, sort column, sort direction, and price & volume visibility.
  • Added drag-n-drop to column headers to change column order.
  • Added new 'add' and 'edit' Core Item form and validation.
  • Fixed infinite loop bug in which [core_service] triggered its own recurring build.
  • Removed testing data and replaced with endpoints and processes to handle 'allCoreData' and 'allCorePrefs' via local variables, device storage, and custom database API.
  • Expanded device storage (Shared Preferences) to allow for storing and retrieving bool and int types.
  • Adjusted account removal process to accommodate removal of 'allCoreData' and 'allCorePrefs'.
  • Expanded [DevHelpers] print to accommodate some non-string fields (bool and int).
  • Fixed [AuthHelpers] feedback message bug.
  • Fixed ambiguous variable in tryAutoLogin().
  • Cleaned out a couple unused/orphaned dart files.

2/9/2021 12:00:47 PM

  • Created new API to accommodate Core Item Listing and Preferences.
  • Added new database table and back-end code to hold Core Item Listing preferences.
  • Adjusted other database tables to accommodate new Core Item Listing screen (increased 'volume' from varchar(3) to 4 and 'qty' from tinyint(1) to 2).
  • Created various DrawIO diagrams and flowcharts.

2/9/2021 12:13:09 PM

  • Additional updates for Core Item Listing and Core Item Preferences.
  • Added back-end form validation.
  • Registration verification will now create the necessary Core Item Preference table entries.

2/9/2021 12:21:20 PM

  • Synced up [web] API with new [mobile] updates.

2/9/2021 12:28:13 PM

  • Adjusted for allowing reusable volume names and removing orphans.

2/9/2021 12:35:58 PM

  • Added 'getCoreItems()' and sending Core Items back with returned payload.

2/9/2021 12:39:58 PM

  • Added 'getAllCorePrefs()'.
  • Prepped for individual updates of Core Preferences with 'setIsAscending()', 'setSortColumn()', 'setColumnOrder()', 'setShowPrice()', and 'setShowVolume()'.

2/9/2021 12:43:26 PM

  • Additional updates for Core Item Listing and Core Item Preferences.
  • Added 'getCoreItems' for initial and refreshed Core Item List dependency injection.

2/10/2021 1:01:31 AM

  • Changed out [core_base] 'FutureBuilder()' with a 'didChangeDependency -> isFirstPass' approach.
  • FutureBuilders should not be used for data injection at a screen level, because every change triggers them to rebuild the entire screen.
  • Formatting of the Core Item 'add and ddit form' BottomSheet is looking much better.
  • On both the add/edit form and the main Core List, changed out 3 columns to have static Container maxWidths, instead of using Expanded widgets with flex factors; Item Name is now the only flex.
  • Fixed numerous form validation bugs.
  • Changed deprecated 'accentIconTheme' color to use 'floatingActionButtonTheme' foregroundColor.

2/10/2021 9:02:27 PM

  • Fixed newly retrieved data from database to work with the local vars and Core List in a few spots (mostly just parsing strings, but also hit a couple challenging 'Type mismatch' errors).
  • Began adding [filenames] to print() statements.
  • Fixed instance method toString() inside the 'CoreInfoItem' data model.

2/10/2021 9:14:38 PM

  • Fixed PHP treating "0" as being empty. :o :| ... Now relying more on is_null and is_numeric.
  • Fixed some form validation wording.
  • Fixed usage of mysqli_insert_id() to instead use PDO $this->conn->lastInsertId();

2/11/2021 2:46:45 AM

  • Converted CoreBase to Stateful so it can do a setState() after the 'FloatingActionButton' onPressed. Also set to await on BottomSheet.

2/12/2021 7:49:15 PM

  • Added Dismissibles to delete Core List rows from local, storage, and the database. Got the functionality part done; now just needs all the accessories.
  • Bug Fix: Made both coreDataToStorage and corePrefsToStorage to be async and awaiting their storage writes.
  • Also fixed multiple String parsing data locations that needed parsing to and from both int and double.
  • Created an 'input-output' matrix and updated other notes.
  • Added various sizes of KD-reCall->Hungry logos; one of which I used on

2/12/2021 8:06:02 PM

  • Added 'itemDelete' functionality in [app_core].
  • Added 'getCoreItems' and 'itemDelete' to whichForm_array in [_core] settings file.

2/13/2021 12:38:52 PM

  • Added an autoFocus to Item Name field. Fixed dynamic add/update button text.
  • Got Core List to reflect Core Item update by adding a testing counter on the page.

2/14/2021 1:15:28 PM

  • Added quantity adjustment [+/-] functionality for Core Items.
  • Added ability to delete a Core Item if the 'decrease' button is tapped when quantity is 0 (will confirm prior).
  • Added validation check that requires Core Item Names to be unique.
  • Locked down Dismissible row swipes to 'end_to_start', and added a garbage can (delete) icon to the Dismissible swiped background.
  • Added and formatted a general-use 'appSnackBar' in Dev Testing Helpers and implemented throughout [core_card].
  • Created a confirmation dialog function to use in a couple locations, but primarily for prior to removing an item via the 'Qty < 0' method.
  • Split out 'fetchSetCore()' to run 'retrieveSetCore()' first, and show snackbar messages for each.
  • Removed 'item counter update' testing code in [core_card], but am using its 'RxValue' as the 'Consumer' trigger in [core_service] via [core_card_viewmodel]. Although nothing is dependent on the counter value itself, apparently just changing its RxValue is enough to warrant a rebuild on the Consumer listening to the viewmodel.
  • Tightened the top corner radius on all the heading tabs.
  • Fixed draggable heading tab colors.
  • Fixed type casting errors in corePrefsToVars.
  • Added 'CorePref' to 'SubmitPage` enum.
  • Tried preventing the 'empty space animation' from the top of the screen when refreshing the screen (the overflow 'pull drag'). Couldn't find a straightforward reliable method to prevent this (although I may be looking at it wrong, or need to refactor).

2/22/2021 2:00:04 PM

  • Added sorting functionality.
  • Added 'sorting direction' icon for active sort column.
  • Changed sorting to be case-insensitive.
  • Added new simplified snackbar for Core List connectivity feedback.
  • Added database and storage functionality for Core List preference settings.
  • Fixed price formatting in Core List (toStringFixed(2)).
  • Added throttling on quantity adjustments. Each "+" or "-" onTap will visually disable for each individually tapped icon.
  • Without throttling, triggering the async calls consecutively, without an action queue, led to broken socket connections and missed taps.
  • With the throttling, you can't rapid-adjust quantities, but the visual feedback is helpful to see the successfully registered taps.
  • Adjusted formatting for all header tiles, especially when dragging to change column order.
  • Adjusted formatting for all cells, rows, and columns with alignment, font sizes, padding, and margin.
  • Added an onLongPress to the "-" icon as a shortcut to delete the Core Item via an affirmation dialog.
  • Added a TextInputFormatter for each field for live-validation input.
  • Decreased the character input limit from 50 to 40 for the Core Item Name field (this allowed for a font size increase).
  • Changed keyboard type for Quantity and Price.
  • Added auto-selection of Quantity and Price fields if they're at 0, and only for the first three taps (if the keyboard changes, it loses the selection on the first tap).
  • Fixed error when changing column order (was basing on column index instead of column value ... this was a huge misnomer).
  • Now hiding a couple preferences: Show Help and Local Dark Mode (based on a quick impromptu 'live user test').
  • To aid in development, created new categorized print calls between 'build' prints [printItB], shared prefs [printItSP], secure storage [printItSS], and the remaining [printItK]s.

2/22/2021 2:12:49 PM

  • Fixed and streamlined back-end handling of Core Item Volume names; also handles removing orphans and increased length to 5.
  • Added database updating of Core List Prefs.

2/24/2021 2:23:04 AM

  • Got live validation in place. Added a TextInputFormatter for each field to only allow validation-level input in each text form field. This was a lot of learning/work.

2/24/2021 2:46:00 AM

  • Changed About() from a showDialog() to a showGeneralDialog() and shared it via a static method in [auth_helpers]. The dialog smoothly fades and scales in and out.
  • Applied the new dialog to the appBar icon, the hero logo, and added to the Auth page, which will show only the first time you arrive, but can still access it via the 'i' appBar icon.
  • Fixed showing snackbar after the Add/Edit Item BottomSheet is dismissed by wrapping the FloatingActionButton in a Builder and giving it its own context.
  • Also moved the showMsgSnackBar() and confirmDialog() methods into a new shared file.
  • Adjusted the wording and formatting on the About() dialog.
  • Fixed Secure Storage printing method.

2/24/2021 8:55:15 PM

  • Fixed Shared Prefs not printing.
  • Converted robust getter to function (basically a getter that got out of hand).
  • Fixed 'columnOrder' storage issue.
  • Added comments for manually and deliberately breaking [main_base] FutureBuilder, and changed its formatting.
  • Fixed 'preference setting success' falling into error/else clause (rather, it just shouldn't show the snackbar).

2/26/2021 1:29:06 AM

  • Refactored and streamlined the 'Add' and 'Edit' approaches for adding or updating the Core Item List via [core_add].
  • Both action-initiator files [core_base] and [core_card] now use a shared [core_card_viewmodel] method.
  • Fixed item name validation where it would allow an empty name because it's tied to the new input formatter, who's regex doesn't allow 0 characters.
  • Added a cloning method to the CoreInfoItem class object, so a [core_add] change doesn't reflect in the [core_card}'s Core List.
  • Added faux updateItemCount() for when adding Core Items to the Core List (same as when updating the list).
  • Fixed [core_add] form field values being cleared, by moving and populating the controller values inside didChangeDependencies, after a call to resetItems().
  • Added 'onChange' in [core_add] form fields to save each field's value as the user types. Otherwise, the field wasn't being saved unless the button was pressed.
  • Added more printB()s.
  • Swapped out more print()s with printItK()s.
  • Changed more 'columnIdx' to 'columnVal'---that distinction is night and day.
  • Deleted older 'z_' files.

2/26/2021 1:53:26 PM

  • Cleaned out unused imports.
  • Started on AppBar action: pulldown.
  • Fixed drawer navigation to Core List screen.
  • Fixed both Auth Card and Preference screens giving render flex overflows when switching between them via the Drawer by wrapping their top Column with a SingleChildScrollView.
  • Fixed Core List screen by giving its root Column a Container with deviceSize height and width (it has its own scroll inside).
  • Fixed Prefs page switching back to Core List after dark mode is toggled---it now stays on the Prefs screen.

2/26/2021 2:19:35 PM

  • Expanded 'ColumnOrder' validation to allow for lists of 6, 5, and 4 elements (for when not showing Price or Volume columns).
  • Added notes and files on my troubleshooting rebuilds and disposes, all of which were perfectly normal and expected---my issue was with how to navigate those rebuilds and disposals when showing SnackBars.

2/27/2021 11:15:51 PM

  • Completed show and hide for Price and Volume columns.
  • Changed both 'showPrice' and 'showVolume' primitive bool values to RxValues and am filtering the columnOrder mapping with a .where clause.
  • Completed AppBar actions dropdown menu; added dividers and formatted it up pretty.
  • Got three of the AppBar action items working, with two of the three having dynamic labels; toggle dark mode, show/hide Price column, and show/hide Volume column (the last two having the dynamic [show|hide] labels).
  • Created some generic KD-reCall icons (128, 64, 48, 32, and 24).

2/28/2021 2:01:58 AM

  • Completed formatting Core List and Add/Edit panel for dark mode. 97% happy with it---vertical alignment on +/- header tiles are slightly offset from their columns.
  • Adjusted app's primary yellow background card... added 40 more blue to help subdue a faint lime green tint.
  • Prettied up deletion alert dialog a bit.

2/28/2021 3:02:55 PM

  • Finished all AppBar action items except Help().
  • Initial-cased the Name and Volume text form input fields.
  • Initial-cased the Reference Name field (for both login and preferences screen).
  • Changed action menu to go back to Core List screen when on Prefs screen.
  • Changed Drawer to swap between Account Settings and Core List screens, instead of always showing both.
  • Added a "Step 1" and "Step 2" to Forgot Password panel toggle buttons.

3/3/2021 8:38:46 PM

  • Completed 'App Instructions'.
  • Added Instructions button on Core List screen when list is empty.
  • Completed 'About' (took a lot of work; also added links to the project's Atlassian/BitBucket pages).
  • Finalized AppBar actions drop-down menu.
  • Began migration to Flutter 2.0.0.

3/4/2021 7:38:27 PM

  • Code complete on Flutter 2.0.0 migration.
  • Created new Button style themes for all the deprecated Flat and Raised Buttons.

3/5/2021 9:12:02 PM

  • Finalized formatting for Instructions panel (on empty Core List screen) and About panel (with Licenses).
  • Fixed status bar icon colors being intermittently set to black (such as when going to the License panel). Also fixed AppBar icon buttons doing the same thing.
  • Fixed one incorrectly themed button (found so far).
  • Prepping for adaptive icon implementation, and...
  • Redesigning the app's icon based on Material and Android specs and guides.

3/6/2021 11:32:04 PM

  • Created an app launcher icon, along with its adaptive icon formats for back- and foregrounds as well.
  • Removed a legacy logo.

3/7/2021 8:28:33 PM

  • Designed and added launcher icons and a splash screen.
    • For clarity, this is the App-level splash screen, which is shown when the app is loading, which will show the "KD-reCall: Simple Reminders" logo on a solid paprika background.
    • It is not the splash screen that is shown while waiting on the authentication status check, which now simply shows the relevant app's title, in this case, "Hungry on Hand".

KD-reCall App Splash Screen with Simple Reminders subtitle

3/9/2021 8:02:53 PM

There are too many updates to post them all, so they were categorized by their actions:


  • Added x3.
  • Adjusted x1.
  • Finalized x1.
  • Fixed x6.
  • Formatted x2.
  • Gave x2.
  • Reformatted x1.
  • Relocated x3.
  • Removed x3.
  • Tweaked x1.


  • Finalized all Core Item row colors for both light and dark modes.
  • Adjusted dark mode colors on Dismissible Core Item rows.
  • Fixed and tweaked numerous flows and functions.
  • Fixed and tweaked formatting and layout of numerous elements and areas.
  • Formatted confirmation dialog and removed extra top padding (for when title isn't used).
  • Added 'Item Name' to delete confirmation message.
  • Gave minWidths to slider toggle buttons on Prefs screen when Advanced Preferences are turned off.
  • Gave Prefs screen its own heading title, and adjusted for both light and dark modes.
  • Reformatted top of Prefs screen for when Advanced Preferences are turned on.
  • Removed logo from Prefs screen.
  • Adjusted numerous 'behind the scenes' code and flows (detailed in internal coding notes).

3/12/2021 1:19:01 AM

  • Changed out approach for hiding Volume and Price columns.
    • The new approach now actually removes the columns from the column order array, which not only allows for column reordering when columns are hidden [bug fix], but will also remember where the hidden columns were when they are restored.
    • This was done by converting both showVolume and showPrice from bools to char(2)s, which allows for a bit to be set for both 'visibility' [1|2] and 'index' [0-5].
  • Also fixed a major null dereference bug that was crashing the app intermittently.
  • Then found and fixed another issue where, although the new indexes were getting updated in storage, the revised column order list was not.
  • In light of the above fix, also added a backup that will update the column order array string in storage if it doesn't match the visibility or index bits.

3/12/2021 2:33:42 AM

  • Fixed a newfound issue where the visibility column indexes weren't being updated after either of the indexes were inserted or removed. The fix was to add a call to update the indexes whenever an adjustment is made to the column order array.
    • And although the solution was solid, I had to then fix my fix for it to work, as I was executing the follow-up indexing update method too soon. Once that fix was made, the show/hide column functions will now shift the other's index accordingly, and only if necessary (that is, if the other column is currently visible).

3/12/2021 6:05:44 PM

  • Added a [kd_icon] image widget for About() panel.
  • Added Terms and Conditions to About panel, and fixed dark mode buttons and bullet colors.
  • Fixed 'Add/Edit Item' form button in dark mode (again?).
  • Tried changing button colors in light mode on About panel, but:
    • In light mode, the About() button background colors have a direct effect on the 'text selection toolbar' (copy/paste/selectAll) color.
    • And because the 'text selection toolbar' text color is directly based on the brightness scheme, when in light mode, it has black text, which cannot be seen on a dark (paprika) button.
    • And because neither property can be overridden individually, although not ideal, I have to go with the 'best case' color scenarios for both (light buttons in light mode on About panel---although it looks so much better with paprika :().
    • Would also love a border on the 'text selection toolbar', but that does not appear to be exposed anywhere (although there are multiple properties that 'appear' to provide a border styling property, as with the toolbar's text color styling, none of them yielded any effect). Perhaps there is a package that helps achieve this, but even if so, it isn't worth the cost of a dependency. Both buttons are ... satisfactory.

3/13/2021 12:48:30 AM

  • Added icons to the AppBar's (three-dot) "Settings Menu" dropdown.
  • Applied logic to show relevant icons based on app environment in the AppBar menu and the Drawer (this is what the Dec 19th architectural discovery was all about, which I documented on Dec 23rd (above)).
  • Added a 'Tip' to the 'empty list' screen, and changed the 'Add' button text to 'Add an Item' (but will still show 'Add' when the list is non-empty).
  • Created a tiny KD-reCall icon for the last commit entry in the wiki (but instead went with a cropped screen capture).

3/13/2021 12:27:33 PM

  • Added a "Reset 'List Display Settings' Back to Default" button on Prefs screen (needs environmental formatting).
  • Added a light border around snackbar for noticeability.

3/13/2021 7:19:51 PM

  • Fixed formatting in Drawer for light and dark mode, and removed a superfluous column.
  • Tweaked the formatting of the 'empty message panel'.

3/14/2021 12:59:03 AM

  • Added "List Reset" functionality to the AppBar settings menu.
  • Fixed AppBar's 'Reset Columns' action reflecting updates in the List screen.
  • Fixed snackbar border radius color in dark mode, and gave the contents some room to breathe.
  • Playing peek-a-boo with Flutter, Dart, or Android's Exited (sigterm) and Lost connection to device messages.

3/14/2021 3:47:01 AM

  • Fixed Add/Edit form's Item Name validation so it's case insensitive.
  • Removed 'Reset Columns' button from Prefs screen (was confusing by itself)---although you can still do all three List actions from the Settings Menu when still on the Prefs screen.
  • Added onTap to AppBar title text that shows the App Intro dialog (removed from AppBar Settings Menu earlier).
  • Fixed '+' and '-' icon 'tapped/busy' colors in dark mode.
  • Fixed a typo.

3/16/2021 10:39:53 PM

  • Finished email formatting.
    • Researched proper font sizing, and applied to both [web] and [app] email templates.
    • Also added <hr> (alongside <br>) when replacing with \n for text-based emails.
  • Changed 'forgot/reset password' form to remember 'username' field.
    • Email is handled selectively (see updates below).
    • So only password and token need to be reentered if an error is encountered.
    • This flow can be revisited in the future to allow for error reporting to be done before the dialog is dismissed (as it's done in the Add/Edit Item BottomSheet form).
  • Other coding tweaks:
    • Added a missing dispose for a controller/listener.
    • Removed a couple superfluous references.
    • Refactored a null check into a parameter default, which was the start of refactoring the email flow between the login and forgot/reset forms.
  • Fixed email flow between the 'login' and 'forgot/reset' forms (see 'refactor'---the line above).
    • 'Login form' email field will not save until after a successful login with the 'save email' checkbox checked.
    • 'Reset form' email field will save its own value, but will be overridden if the 'Login form' email field is populated.
    • This appears to only be confusing if you've saved one email, and are trying to reset a different email, and you're canceling instead of submitting, or the 'save email' checkbox is checked (which is an opt-in value).
  • In doing all that:
    • Removed two superfluous authService update calls on save. // They are already saved in '.save()'.
    • Testing out removing a setState. Works without it. Yay.
    • Fixed a couple other things and tested through.
    • Then fixed something else. How does this app even function... :/
    • Also, the 'Save Email' is working again (was being overridden by the value from the reset form's email field).
  • Fixed both [web] and [app] forgot/reset password validation flows, which will now first test for token authenticity, then username (if not logged in), then its orphan status.
  • Fixed username not being validated on Reset Password form (fell back to server side validation).
  • Added 'loading' indicator on forgot/reset submit button actions.
  • UI cleanup: not showing price if price is 0.00.

3/21/2021 11:45:24 PM

  • Now using a bottom TabBar to switch between 'App Instructions' and a new 'App Info' panel. The (new) 'App Info' panel uses a top TabBar with 4 panels.
    • Converted Instructions from a showDialog to a BottomNavigationBar with a PageView and a PageController.
    • The new Instructions' BottomNavigationBar and PageView controller is complemented with another PageView for Privacy, Assertions, Terms, and Support (a.k.a. "App Info"), all accessible via a TabBar and their own DefaultTabController.
    • Both new PageView tab panels have their own custom AppBar title.
    • Both the 'Drawer Menu' and the 'Settings Menu' will show appropriate and relative links to the various screens. For instance, when on the 'Account Settings' screen, the 'Account Settings' link will not be available from either menu.
  • Added Attributions to About panel, along with links to the 'App Instructions' and 'App Info' panels.
  • Reformatted empty Core List screen (e.g. moved 'Tip' to below the placard).
  • Added 'Overview', 'Authentication System', and 'Logging Out' to Instructions.
  • Tweaked formatting on all the worked-on screens and panels.

3/23/2021 2:49:44 AM

  • Went back through all the Selenium IDE tests. Updated a lot of them, and made some coding adjustments for some others. Was time-consuming, but glad I did it.
  • Fixed app from completely dropping when the back button is pressed when on the bottommost Navigation route.
    • Still allows for internal popping (like the Drawer), and
    • will redirect all other screens to the Core List when the back button is pressed.
  • Added a new top section in Instructions: 'One Suite Account.' Explains how one account works between all the apps in the suite.
  • Changed Instructions title from "App: Instructions" to "Hungry on Hand: Instructions".
  • Adjusted instructions 'light mode' tile colors (to be a tad offset in contrast like dark mode).
  • Made both of the App Info screen titles, and the Preferences screen title, 'tap to navigate' back to the Core List screen (had to pass through a callback).
  • Removed the two App Info links from the About panel (it would crash when accessing About from the Drawer, and then trying to tap through to either App Info screen). The framework's About() dialog box does not allow for a lot of programmatic interaction (figuring out custom styling alone took a week).
  • Added a shared error handling function for the web API call, and all of the Storage calls, and is prepped for any and all other try-catch blocks.
  • Turned off client-side validation and tested the app through the back end as well (as I do with the web interface). Found and fixed some DND bugs.
  • Continued swapping out every 'e-mail' with 'email' that I could find (PHP and JavaScript).
  • Added attributions.

3/26/2021 2:00:34 AM

  • Added 'App Info: Privacy' to the Settings Menu.
  • Then, made the App Info link unavailable when on the App Info screen (this took a couple small doses---and one large dose---of a little magic coding).
      1. Had to fix a few 'back button' issues.
      1. Had to solve a navigation issue for when the 'toggle dark mode' setting was selected from the Settings Menu when not on the Core List screen.
      1. Challenged myself to convert the AppBar Settings Menu to be dynamic (to show/hide the App Info link), then went the extra mile and made it reactive while I was at it (so it'll show/hide based on which screen you're on, but it's not 'telling' the menu to change---the menu is listening to changes from an 'exemptions' list).
  • In the beginning of the process, migrated the Settings Menu data (text and icons) from the [app_bar] file to the [app_service] file, which, since it's now stateful data, and not static, is where it belongs (although static data can live there too).

The first app in the KD-reCall suite is functionally complete and fully operational.

There is still some cleanup work to be done before embarking on the second app in the suite, like adding more try/catch blocks, going through @TODO:s in the code, and maybe adding a donations option (or, maybe later along with social signins), but it appears to be fully operational.

The hope is for two weeks on the 2nd app, but reality has shown it'll more likely be a month, or two. The second app to be done will be "B4-I-Go"; small lists of common reminders to check off before going various places.

3/27/2021 10:54:02 PM

  • Went through every catch in the codebase --- ensured they all returned or otherwise exited properly.
  • Went through every @TODO: in the codebase (thanks to the VS Code 'Todo Tree' extension by Gruntfuggly) --- updated, fixed, or set to Long Term [LT].
  • Went through and converted all remaining native print()s to go through the (custom) [DevHelpers] print method (which takes two parameters, the first being the file that's calling the print function).
  • Provided relevant and sometimes quite detailed development notes about the code, flows, and some of the decisions, while going through all of the above.
  • Fixed: Will now hide snackbar when refreshing the Prefs screen (trying to 'close' it after a refresh makes it an orphan, with a 'disposed of' ancestor or parent).
  • Turned back on Web API call on Core List (it is (now) a constant, which I leave off during development, so the Host and Database aren't being hit after every file save (hot reload) and screen refresh).

3/29/2021 2:33:42 PM

  • Added two 'direct access' web pages: 'assertions' and 'support'.
  • Fixed formatting of web interface registration verification 'success' message.
  • On the app's Login screen, changed out the app's title to be 'Simple Reminders' (the app's name is already in the logo).
  • Added 'Close Window' text next to the button on the App Intro's welcome pop-up.
  • Created new graphics for Google Console Play settings.

App Suite: Project Setup

3/29/2021 9:41:57 PM

In getting multiple apps in a suite to follow a consistent pattern throughout every app, and to reduce code duplication and minimize future maintenance efforts, each KD-reCall app will share a 'Common Shell,' while each app will have its own Core section within its own codebase.

  • This process was confirmed as I just did my first round trip from Git forks, to upstreams, to pull requests, to pulls and pushes.
    • Any app can do a Pull Request to update the Common Shell, after which all the other apps can then do a Pull and Push to update the Common Shell code in their own codebases.
    • This pattern follows the Git: Forking Workflow closely, which, "is most often seen in public open source projects."

Pilot App Update

The pilot app, Hungry on Hand, is currently in Google Review, awaiting release to 'Closed Testing.' However, the app will not be published directly after testing. It will instead await the second app to be completed, and possibly the 3rd, so at least the first two or three can be released as a suite.

It will, however, be available to anyone wanting to test it---for personal use, or to see how a budding Flutter developer's first app works.

Simply contact Keith, me, the developer, with your email address, and a simple 'Request to test [Hungry]' (or something of the sort). Additionally, as mentioned in a few places throughout the app, feedback is most welcome.

Pilot App Testing

As of Apr 2, 2021, the KD-reCall pilot app, Hungry on Hand, has entered the Closed Testing phase. The app will be published live after the second (or third) app is joined in completion, so at least the first two or three apps can be released as a suite.

Early Access Request

The Hungry on Hand reminder app is available to anyone with an Android wanting to test, or even just use the app. Simply use the KD-reCall Contact Form, providing your email address and a simple 'Request to test [Hungry]' (or something of the sort). Feedback is welcome via that same contact form, or the Bug and Feature Tracker.