Wiki
Clone wikikdrecall-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 petrefapp.com and storycore34.com).
- 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
2020‑05‑08
- [web] Initial commit for KD-reCall.
- [web] Incremental development update.
2020‑05‑14
- [web] Incremental development updates.
2020‑05‑16
- [web] Working on session handling.
- [web] Finished PHP session handling.
2020‑05‑21
- [web] Initial split between auth for both web and app.
2020‑05‑24
- [web] Worked on /auth. Renamed /app to /api.
- [web] Auth path still working. API: Login and Logout are done (w/ JWT).
2020‑05‑28
- [web] Progress: Auth flow, session control, and some security (removed JWT)
2020‑06‑01
- [web] Started userData object population from server for client on login.
- [web] Added pertinent user obj props. Setup whichApp and app_id usage.
2020‑06‑09
- [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.
2020‑06‑10
- [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.
2020‑06‑12
- [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.
2020‑06‑13
- [web] Auth: 2 DB updates. Implemented create_user_tables. Began allowing for multi-app registrations.
2020‑06‑15
- [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.
2020-06
- [browser extension] Took two weeks off to create a browser extension.
2020‑07‑03
- [mobile] Initial commit of mobile app source files.
2020‑07‑05
- [mobile] Structural refactor and UI completion of login screen.
2020‑07‑22
- [mobile] Login UI complete. Began testing.
2020‑07‑24
- [mobile] Got some testing to work using lists, maps, and loops.
2020‑07‑31
- [mobile] Getting caught up: Field-level testing is done. Login is done.
- [web] Getting caught up: Field-level testing done. Login done.
2020‑08‑03
- [mobile] Just preserving where I'm at: API token logins ~70-80%.
2020‑08‑05
- [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.
2020‑08‑07
- [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
div
s andspan
s toa
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
andtitle
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
toinput-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]
- Began getting
app_prefs.php
setup --- will be a composite of multiple other files. - Added countdown counter to Notes
textarea
. fieldNotesCounter.innerText = Math.max(0, 5000 - evt.target.value.length).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
- // ^^^ Math.max() | Thanks to: stackoverflow.com => character-counter-backspace-doesnt-reflect-on-characters-remaining
- // ^^^ Comma Regex | Thanks to: stackoverflow.com => how-to-print-a-number-with-commas-as-thousands-separators-in-javascript
- Prettied up the UI message response area.
- Took control over the
reset form
button to clear custom UI adjustments. - Got the base of the server-side validation structure outlined and coded.
- Working on validation; primarily email and password data.
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 fromrunp.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 programmaticaltextarea
to pass PHP-filterednotes
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 forON UPDATE CASCADE
. - Fixed
user_notes
table; madeuser_id
UNIQUE
and increasednotes
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
preferences-testing.md
andpreferences-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
orJSON
. - 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 andtargetSdkVersion
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.
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 kdcinfo.com
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 contentCard()
. - 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 onAuth()->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
andUserInfo
to gain insights on how Prefs() fits into it all
(i.e. provider-level data sharing and access, routes, and themes). - Created a draw.io 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) andprefs_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').
_formControllerEmail.addListener(_showChangeEmail);
- Started up app.
Error --> Changed out provider initialization call with a hard-codedtrue
inmain.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 theChangeNotifierProvider
in theproviders
List[]. -
Secondly, in all my learnings, I've not seen an example of where the
ChangeNotifierProvider
was used as achild:
of theMultiProvider
, even though it's also been configured in theproviders
List[]. This feels like an advanced approach for the Provider package perhaps? The Flutter documentation also only shows theChangeNotifierProvider
being configured in theproviders
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 kdcbase.com is a masked redirect to content provided from my personal portfolio domain on kdcinfo.com. I sat through chatting with half a dozen CS tech reps while setting up the kdcbase.com 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 adarkmode
, and atheme
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 theroutes
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 theChangeNotifierProvider
, andisDark
will default tofalse
, initially, in every case.tryAutoLogin()
will attempt to restore the properisDark
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:
[main.dart]
MultiProvider( providers: [ ChangeNotifierProvider.value( value: Auth() // Nothing fancy here. ... theme: _showTheme( themeModel, // 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.log
s. - 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.
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
FocusNode
s setup. - Have all the input field
Controller
s 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 toProvider.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 : TextInputAction.next,
- 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 aCard
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="false" autocomplete="new-password" // Spec: https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofill autocomplete="chrome-off" // This is not a team-conscientious move.
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:
`t_reset` 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
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
andObservable_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 throughDevHelpers.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/Diagrams.net).
- 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
andnotes
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 astatic const
in each base screen file).
1/10/2021 4:03:38 PM
- Added in preliminary code for
core_base
. Swapped outstatic 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
withSlivers
and a pinnedSliverAppBar
.
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
#1at fixing the Prefs().isDark change, which reroutes toCore()
instead of back toPrefs()
.
1/28/2021 1:06:41 PM
- Implemented column reordering by adding
Draggables
andDragTargets
.
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 aSliverAppBar
andSliverList
. - 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
andint
types. - Adjusted account removal process to accommodate removal of 'allCoreData' and 'allCorePrefs'.
- Expanded [DevHelpers] print to accommodate some non-string fields (
bool
andint
). - 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)
to4
and 'qty' fromtinyint(1)
to2
). - 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 onis_null
andis_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 toawait
on BottomSheet.
2/12/2021 7:49:15 PM
- Added
Dismissible
s 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
andcorePrefsToStorage
to beasync
andawait
ing their storage writes. - Also fixed multiple String parsing data locations that needed parsing to and from both
int
anddouble
. - Created an 'input-output' matrix and updated other notes.
- Added various sizes of KD-reCall->Hungry logos; one of which I used on kdcBase.com.
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
andLocal 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 ashowDialog()
to ashowGeneralDialog()
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 aBuilder
and giving it its owncontext
. - Also moved the
showMsgSnackBar()
andconfirmDialog()
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 toresetItems()
. - 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 withprintItK()
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 aSingleChildScrollView
. - 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 toRxValues
and am filtering thecolumnOrder
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".
3/9/2021 8:02:53 PM
There are too many updates to post them all, so they were categorized by their actions:
Summary:
- Added x3.
- Adjusted x1.
- Finalized x1.
- Fixed x6.
- Formatted x2.
- Gave x2.
- Reformatted x1.
- Relocated x3.
- Removed x3.
- Tweaked x1.
Highlights:
- 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
andshowPrice
frombool
s tochar(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)
andLost 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 acontroller
/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.
- Added a missing
- 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).
- Removed two superfluous
- 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 aBottomNavigationBar
with aPageView
and aPageController
. - The new Instructions'
BottomNavigationBar
andPageView
controller is complemented with anotherPageView
for Privacy, Assertions, Terms, and Support (a.k.a. "App Info"), all accessible via aTabBar
and their ownDefaultTabController
. - Both new
PageView
tab panels have their own customAppBar
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.
- Converted Instructions from a
- 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).
-
- Had to fix a few 'back button' issues.
-
- 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.
-
- 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).
- 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
-
- 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 allreturn
ed 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
, toupstreams
, topull requests
, topulls
andpushes
.- Any app can do a
Pull Request
to update the Common Shell, after which all the other apps can then do aPull
andPush
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."
- Any app can do a
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.
Updated