jcubic / jquery.terminal

jQuery Terminal Emulator - JavaScript library for creating web-based terminals with custom commands
https://terminal.jcubic.pl
MIT License
3.12k stars 569 forks source link

iOS mobile: keyboard up/down and scrolling behaviour not working #914

Open giancarloerra opened 9 months ago

giancarloerra commented 9 months ago

Issue summary

Exploring all the possible examples, even the last one https://terminal.jcubic.pl/android.php, the behaviour on iOS mobile is not working: virtual keyboard going on and off doesn't get the last line (the prompt) scrolling up and down so that's never covered when keyboard is up.

Expected behavior

The bottom of the terminal, where terminal is, should always be automatically attached to the bottom of the visible view, without or without keyboard.

Actual behavior

Keyboard going up (once the screen is full of lines and after has been up and down once), covers the terminal. The terminal should always automatically scroll to the bottom, be attached to the keyboard popping up/down, and keep like that while typing a command (or prompt in focus) or when executing a command.

Steps to reproduce

Simply loading the latest demo https://terminal.jcubic.pl/android.php on iOS, making the screen full of commands so it scrolls down, keyboard up and down and then up again, it covers the bottom of the terminal/view.

Browser and OS

Latest iOS, Safari or Firefox (both using WebKit anyway).

Additional notes

giancarloerra commented 9 months ago

For now my nearest solution is:

const scrollToCmd = () => {
    let element = document.querySelector(".cmd");
    element.scrollIntoView();
}

and this listener

$(document).ready(function () {
    visualViewport.addEventListener("resize", () => {
        scrollToCmd();
    });
});

And in theory it seems to work. Problem is that when typing a command it scrolls up automatically as there seems to be something else bringing up the scroll to a point where is not aware of the virtual keyboard.

I tried this to mitigate:

        onCommandChange : function () {
            scrollToCmd();
        },

And it shows clearly that is fighting something else that brings the scroll up to to where it would be without the virtual keyboard: typing letters slowly, the focus/scroll goes briefly up and is then dragged down again to the correct position by the scrollToCmd().

If we could get rid of whatever is fighting this scrollToCmd(), this solution I believe could work.

giancarloerra commented 9 months ago

There's an additional bug happening once you have a long terminal and keyboard up/down a few times and scrolling etc.

A part of the body background colour is showing "behind" (or at the bottom) of the terminal.

Images of keyboard covering the content: IMG_4502 IMG_4503

And the black terminal showing the body behind (white):

Screenshot 2024-02-05 at 18 04 53
jcubic commented 9 months ago

Yes, this is a known issue see #707.

The problem is that on iOS the keyboard doesn't affect the layout size inside CSS. In the recent version of Chrome, they duplicated the "broken" behavior of Safari. So now for every mobile browser you need to use JavaScript to detect the virtual keyboard and it's not easy. See #859.

There is also a long-standing bug in mobile Safari with white space below the HTML, and I don't see a way to fix this. I think that the new Chrome added that bug to their implementation.

See this question on StackOverflow: White space outside HTML on mobile Safari when the keyboard is open

So the problem are bugs in the browsers that now become the standard.

I will try to attempt to fix this issue again. I need to find the code I was using to hack the new Chrome behavior, maybe it will work for iOS.

On Chrome you only need to add a special viewport meta tag. But on Safari I'm afraid this is default behavior and I don't think they will ever fix this.

If you know how to fix broken mobile browsers I'm all ears.

jcubic commented 9 months ago

I will check how your Scrolling into view behaves.

giancarloerra commented 9 months ago

Thank you. I confirm that the white space (in my case the background colour of body in place of background image) happens only in Safari, not Chrome (or it's hidden more quickly).

Thanks for checking those code snippets...they solve the problem of the keyboard up/down and bottom of the terminal (cmd) following it, so the keyboard does not cover anymore. It works on Chrome and Safari.

But the up/down remains, so there's something somewhere else that tries to scroll: if you can find where that is and try to disable it and see it that fixes it, maybe that could be a solution if it doesn't break anything else.

Thanks, much appreciated.

jcubic commented 9 months ago

The problem with scrolling up the content is that the page height is the full height of the phone and if you open the keyboard, the thing that makes the keyboard open is at the bottom of the page. Even if the height is 100% the page is bigger than the size of the available area. This is a broken behavior of Safari that is now duplicated by Chrome, which is really bad.

I've reported this two times to the Chrome team they said this is how it should work. Because they do the same what Safari is doing. This is really stupid but I nothing I can do.

I can only do hacks in JavaScript to fix broken behavior.

The reason why they think it's okay is because no one needs a full-height mobile app like the one I need for jQuery Terminal. They only care about normal websites where this works fine.

giancarloerra commented 9 months ago

It sounds like it's not going to be fixed (by them) anytime soon, not surprised, but if Chrome is following then maybe JS hacks is the way?

The one I did is a hack but it 'works' solving half of the problem, I wonder if you have a way to make it work also when typing letters in the terminal, because that's the only problem left.

With my hacks when you get focus on the terminal and the keyboard slides up, the terminal is nicely pushed up, and down, it all works nicely...but when typing, the up/down happens.

Just wondering if worth going down the hack route if it works most of the times.

jcubic commented 9 months ago

It seems that my old demo works for Chrome on iOS (that it's Safari with different branding), but not for Real Safari. iOS is a real mess. And there no dev tools of any kind on BrowserStack to debug Safari on iOS.

jcubic commented 9 months ago

Ok, I was able to run the Dev Tools on the browser Stack. And I think I have a working PoC of the code:

https://terminal.jcubic.pl/android.php

Can anyone check (on a physical iPhone) if it works? The code is not yet in the repository.

bsidhom commented 8 months ago

I can confirm that this works as expected on a physical iPhone.

bsidhom commented 8 months ago

Do you have link to the code so we can experiment with it? Did this require internal changes to the terminal itself or did you just use the public API/CSS? I can read the source on the page, but it's not clear what the significant changes are to get this working.

jcubic commented 8 months ago

The code is on top of the library inside the HTML file. I don't remember if I changed something in the source files but I don't see any uncommitted code and there is nothing in the git stash. So everything has to be inside the HTML.

This is everything:

body.full-screen-terminal {
    height: 100%;
    height: 100dvh;
    height: calc(var(--terminal-force-height) * 1px);
}
 function on_height_change(callback) {
     let { height } = window.visualViewport;
     callback(height);
     window.visualViewport.addEventListener('resize', function(event) {
         const { height: newHeight } = window.visualViewport;
         if (height !== newHeight) {
             height = newHeight;
             callback(height);
         }
     });
 }
 if ('visualViewport' in window) {
     on_height_change(function(height) {
         document.documentElement.style.setProperty('--terminal-force-height', height);
     });
 }

I don't see any other code besides this resize/force height. I need to incorporate this code into the library. And do more tests.

bsidhom commented 8 months ago

I may have spoken too soon. It works at first, but seems to get into a weird state if I click away the keyboard and then refocus it. And randomly on some page loads, I can’t focus the text area at all to bring up the virtual keyboard.

The blur-refocus issue also isn’t deterministic, so I’m not sure what’s causing it. It actually seems to work most of the time for me.

jcubic commented 8 months ago

That's what I was afraid of, that it doesn't work all the time. Will keep iterating over this idea and try to fix the issue. It may take time and may never get fixed. iOS is difficult to work with.

oxygen79 commented 8 months ago

A fix to this bug would be very welcome here too :)

jcubic commented 8 months ago

So for me the code works fine (in BrowserStack), the only problem is when you blur and focus again the cursor line is not visible.

I'm going to push this code, after adding the fix to the focus. And close this issue. Any bugs in iOS would have to be added separately with clear reproduction.

jcubic commented 8 months ago

I was too fast, my solution doesn't work 100% correctly.

jcubic commented 8 months ago

Can anybody check on a real iOS?

Same link https://terminal.jcubic.pl/android.php

I've made few changes, I hope it will work now.

jcubic commented 8 months ago

The fix solve the problem with jumping, but you can't scroll anymore.

jcubic commented 8 months ago

Ok, I think I got this. You should be able to test now:

Same link https://terminal.jcubic.pl/android.php

Shev3k commented 7 months ago

I tested on an iPhone 13, the initial first command works perfectly and then I cannot enter any more because the keyboard will glitch out whenever I try to target the command line. It has also caused the Desktop browser version to have the bottom white part for me, and so far I haven't figured out how to target it to keep it in line with the terminal background again (in my case, the usual black).

Edit: Got it to work by <body class="full-screen-terminal" style="height: 100%;">. This also alleviated the keyboard issue for more than the first command on mobile.

jcubic commented 7 months ago

@Shev3k thanks for testing, I need to revisit this. I also merged the changed, and they got released with 2.29.1 by accident. I should create a separated branch with the changes to mobile.

jcubic commented 7 months ago

Just fixed the height issue, I didn't realize that missing CSS variable don't cancel the CSS property. Now it should work again on Desktop.