Skip to content

[iOS] Keyboard refactor + rotation fix#1347

Merged
jahorton merged 29 commits intomasterfrom
ios-444-keyboard-refactor
Dec 5, 2018
Merged

[iOS] Keyboard refactor + rotation fix#1347
jahorton merged 29 commits intomasterfrom
ios-444-keyboard-refactor

Conversation

@jahorton
Copy link
Copy Markdown
Contributor

@jahorton jahorton commented Nov 27, 2018

Fixes #444.
Fixes #1045.

This PR will serve the following purposes:

  1. Refactors all keyboard management code into a more centralized and OO-based pattern
  2. Merges the code paths for the in-app and system keyboard, simplifying management of keyboard events and layout
  3. Implements constraint-based sizing and layout for the keyboard, allowing iOS to automatically handle keyboard rotation events as appropriate for a user's device with little issue.

As #683 already performs a number of tasks related to point 1 above, this PR will be based upon that PR's work until it is merged.


Due to the scale of the work involved, it may be wise to review by commit in some cases. (That said, the line changed count is surprisingly low for this refactor...)

Particularly interesting commits:

034680d

  • gets in-app keyboard rotation based upon constraints working about as well as master's current state. It kinda breaks it for the system keyboard, though, but will serve well for further work in constraint-based rotation.
    • Warning logs during debug sessions indicate the need for a merged, centralized keyboard container that can help mediate constraints between our keyboard and the system's expectations of a keyboard view.

9d7da15

  • removes Manager from the KeymanWebDelegate indirection control flow. KeymanWebViewController now directly makes calls to the 'first responder.'
    • This has the effect of partially centralizing and disentangling the in-app vs system control path code, preparing it for further refactoring.
    • More must be done to fully de-spaghettify KeymanWebDelegate and its usages, though.

3f2c59c - a massive refactor that transforms the old system keyboard's base into a unified in-app/system keyboard object.

  • Updates base iOS target version to 9.0.
    • according to https://everyi.com/by-capability/maximum-supported-ios-version-for-ipod-iphone-ipad.html, this shouldn't affect any properly updated iOS device; if it was supported before, it'll still be supported by Keyman.
    • this decision simplifies constraint-based coding dramatically; the whole 'anchor' constraint scheme used by this commit was introduced in this version of iOS.
    • adds a couple of new warnings about a method deprecated after iOS 8 but by iOS 9.
  • sets InputViewController as the owner and maintainer of the KeymanWebViewController.
    • That bit about a "merged, centralized keyboard container" before? InputViewController can fulfill that role!
  • is now also the only KeymanWebDelegate, directly processing all text commands rather than relying on extra supporting code for TextViews and TextFields.
    • If desired, we may be able to fully strip out the entire 'delegate' abstraction now.
    • Since InputViewController is more generally usable, it can now be used via the inputViewController property for TextView and TextField.
      • More research is required to see if it'll even work directly with the base UIKit versions.
  • fully implements constraint-based sizing and layout for the in-app keyboard without issue
    • basically, gets the work from 034680d working on the refactored core keyboard object, and even better than before.
    • this does break the system keyboard, and even more so than before. So, still WIP.

b9eeab6

  • Gets the system (app-extension) keyboard to display the actual keyboard again... for the first load only.
    • It's a very consistent pattern - apparently, the WebView needs to be reinitialized/reset each time the extension is reloaded, as it forgets the old page.
  • Continued debugging of system keyboard constraint effects... something's really weird with how (system) keyboard extension constraints are handled when compared to in-app.
    • The work done here to ensure a consistent keyboard instance should help with... interpreting... the constraint violation logs that iOS provides.

e4c6ec6

  • System keyboard is now operational!
    • Turns out that InputViewController wasn't actually making its 'base' view correctly, as it's supposed to set inputView rather than view and use a UIInputView.
    • With this change in place, smart placement of an additional constraint allows the resulting base-level system keyboard view did the rest.

@jahorton jahorton changed the base branch from ios-kmw-vc to master November 28, 2018 08:27
@mcdurdin mcdurdin modified the milestones: P4S11, P4S12 Nov 30, 2018
extension KeymanWebViewController {
func languageMenuPosition(_ completion: @escaping (CGRect) -> Void) {
webView.evaluateJavaScript("langMenuPos();") { result, _ in
webView!.evaluateJavaScript("langMenuPos();") { result, _ in
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sometimes you use webView! and others you use webView?. Is this intentional and if so it might be good to clarify why.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a Swift thing - webView! asserts that it's not nil, while webView? has a built-in nil check before continuing with the rest of the line.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep -- it's just not clear to me the reason why sometimes you assert and sometimes you go ahead with a nil check for each of those JS calls.

Copy link
Copy Markdown
Contributor Author

@jahorton jahorton Dec 5, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. There are two cases I see in that file, and they do have a particular reason - they're the setOskWidth/setOskHeight method calls, right? Those two lines actually can be reached before webView is initialized, so they need the nil check. It's also fine if the call doesn't go through, as a state variable is also set with the size information and can be passed along to the webView as part of its initialization, so it's not like the values are being lost.

Without other changes, setting those two checks to use ! instead of ? will actually crash the app.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha. Are you happy to add a comment in the source accordingly for the poor future maintenance person? :)

Copy link
Copy Markdown
Member

@mcdurdin mcdurdin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rotation looking good. The banner has the wrong aspect ratio on the system keyboard sometimes.

The in-app keyboard rotation is especially smooth. The system keyboard rotation has a little jump at the end to fix its vertical size.

@jahorton
Copy link
Copy Markdown
Contributor Author

jahorton commented Dec 5, 2018

Yeah, the system keyboard isn't as consistent about reporting its rotation messages, so I did what I could to smooth it out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants