Remix.run Logo
▲ chrismorgan a day ago

This is a good demonstration of why you really shouldn’t do this. Bluntly: this is completely unusable for many people, barely usable for a lot more, and on desktop and mobile both I would absolutely hate to use this, and a lot of the problems in it fundamentally cannot be fixed.

> But it also means the editor looks and behaves the same in every browser, on desktop and on phone, because nobody else is in charge of the pixels.

You say this as though it were a good thing. It’s very much not; they’re not supposed to be the same, they have slightly different expected renderings, and significantly different interactions.

And you can’t inspect or emulate them.

—⁂—

First of all, Firefox under Linux. I see it renders with my chosen fonts, indicating (since you’ve said you’re using 2D canvas) that you’re using fillText. Good; I would complain more about the alternative. But it does kinda go against a lot of what you said about who was in charge of the pixels.

I use my Compose key. Underlined · placeholders, proper replacement, &c. Huh, you’ve surprised me by actually handling that correctly. Well done.

Though I do note that when I type U+1F928 FACE WITH ONE EYEBROW RAISED in a title, in the app’s sidebar and top-of-page title it becomes U+1F929 GRINNING FACE WITH STAR EYES. That’s… not encouraging, but ultimately presumably Just a Bug.

I switch to Telugu and type “telugu”, తెలుగు. Uh oh… with each new consonant it drops the completed syllable, and when I press Escape at any point it deletes the composition. Utterly debilitating bug for IME usage, but ultimately fixable.

I enter some text, find that for the most part it works significantly better than I expected, even handling things like clipboards pretty well.

Then I turn to what I know it will fail, because it’s not possible to get correct universally (different platforms have different behaviours and you can’t probe it; user-agent/platform sniffing would get the best results): keyboard navigation. Ugh, Ctrl+{Left,Right} is utterly wrong. I expected it to have implemented perhaps Windows’ behaviour and I’d complain about that, but no, it’s stopping at both the end of one word and the start of the next, which no platform has ever done. Ctrl+{Up,Down} doesn’t work by paragraphs but still by line. PageUp/PageDown kinda work but the amounts they move by are just wrong, very wrong. And so on. Cursors are frustratingly non-native the while (becomes move when hovering over selected text).

I check whether Backspace seems sane on Telugu text. Seems to be, to my satisfaction. Ctrl+Backspace, of course, is utterly wrong like Ctrl+Left was.

I decide to skip testing any BiDi. But I do run through some of https://lord.io/text-editing-hates-you-too/, and watch it fail vertical cursor movement, affinity, emoji modifiers… meh, BiDi is here, so I decide to test it once and oh dear while it supports the general concepts properly (including selection) it seems to think that if you give it a little bit of RtL in an LtR paragraph it should turn the paragraph RtL which is badly wrong, and then it handles other aspects of selection and keyboard interaction badly wrongly. And it already failed composition. So yeah… it failed them all, where Firefox handles them all correctly.

I try zooming with my touchpad. Nothing happens if the cursor is over the canvas. Grr. Works but leaves the canvas blurry if the cursor is outside it. (Fixable.)

I paste the full text of Winnie-the-Pooh <https://www.gutenberg.org/cache/epub/67098/pg67098-images.ht...>. It locks up the browser tab for several seconds. (Not fundamental, but not surprising either. The browser can handle pasting a mere 26,000 words with light markup in an instant.) And takes perhaps minutes more in the background to decide it is failing to upload all the images (and regularly goes and tries to load them again later). It also inserts blank paragraphs between every paragraph and turns italics into underscore wrapping for no apparent reason. And mangles “*** START OF THE PROJECT GUTENBERG EBOOK WINNIE-THE-POOH ***” into italic “\\\\\\ START OF … \\\\\*”. Not encouraging, though once again not particularly about canvas text editing.

Now the document is long enough, I try scrolling. Oh no.* Scrolljacking!? That was completely unforced error! You must use a real scrolling area. Scrolling is now utterly tedious for me, because it’s not possible to implement scrolling yourself from the events exposed to you, and whatever monstrosity it’s doing instead gets the scroll rate wildly wrong and lacks inertia, so a full swipe on the touchpad gets almost a pageful instead of several plus a hundred more if done fast. Combined with it hiding its fake scrollbar until you scroll, large documents are nigh unusable. Now once again, this is not fundamental to canvas text editing, so long as you’re willing to put the thing in a proper scroll area that you maintain.

I switch to Firefox for Android with the FUTO keyboard. Initially things seem to be working well, better than I expected, particularly given how I’ve observed the backing text input is generally only being given a word at a time—I think FUTO must be remembering words itself for its suggestions, working around how badly broken what it’s being given is. But then I try to shift the cursor by sliding my finger along the Space key, and it doesn’t work. I switch to something else and come back, and selection is shot, it’s lost the caret and I don’t know what happened to it, and various keyboard interactions are broken. I press and hold on a word to select it as always works, and… it doesn’t: no, it seems like they’ve implemented something a little more like my vague memories of iOS from when I’ve seen that; and badly at that. Correct selection is rendered tedious, unreliable, and sometimes impossible. And as for doing anything with that selection… it offers Copy, Cut, Paste. Utterly inadequate, stopping the browser from doing stuff with the text (e.g. share to another app), but unavoidable in the canvas approach.

At this point I give up; it’s completely unusable for anything but the basics. A lot of what I complained about is just that this is buggy and incomplete, but a lot of it is also fundamentally unfixable.

Even the buggy and incomplete parts indicate why the approach is, to put it gently, risky. But the unfixable parts—

This is why you should only use contenteditable.

And I didn’t even get to throttling my CPU to 400MHz to test performance. But it’s after half past midnight and I should be asleep already.

▲chrismorgan 3 hours ago | parent | next [-]

> Though I do note that when I type U+1F928 FACE WITH ONE EYEBROW RAISED in a title, in the app’s sidebar and top-of-page title it becomes U+1F929 GRINNING FACE WITH STAR EYES. That’s… not encouraging, but ultimately presumably Just a Bug.

Fun discovery: this is a Firefox bug. Address bar, text areas, &c. and it’s consistently rendering the wrong character, but somehow your canvas got it mysteriously right. Wild! I should update my Nightly (couple of weeks out of date) and see if it’s still happening, and file a bug report if it is.

▲hamza512b 18 hours ago | parent | prev | next [-]

This is really valuable! Just to add a bit of context: I'm not the only one using canvas for rendering. Google Docs did it years before me. Think of it this way: I've built this almost entirely alone and still get most of the basics working.

Let's start with your test. I think the reason it struggled with the Gutenberg text is that it had a lot of images. Either way, that's a bug and it should be fixed (it shouldn't load all the images at once, and there's probably too much work happening on the main thread). I really appreciate the effort you put in.

I could also use a WebGPU or WebGL context, which would certainly be faster. I think I had a working version last year, but it had problems with blurry rendering (font hinting). I don't remember the exact details now.

Overall, I'm really thankful that you pointed these out. I'll try to work through them over the next few days. I do disagree with the premise, though: canvas is more than capable of achieving this. Performance shouldn't be an issue. That said, I agree with your points about integration with context menus and other tooling.

▲chrismorgan 11 hours ago | parent [-]

I have pointed out various fixable bugs, but I also pointed out some critical things that are fundamentally unfixable, and make the entire approach unbearable. You cannot make it acceptable on a pretty large fraction of mobile devices, and even where it’s not horribly broken, it’s still radically different from every single other thing on the device in extraordinarily frustrating ways.

As for Google Docs, well, I’ll just link to what I’ve written about it before: https://news.ycombinator.com/item?id=42253177. I honestly believe they lied in their justification, because the resulting experience is genuinely worse in every way. I can’t comment on how it is on mobile, because I’m too lazy to log in, and they probably do something different on mobile anyway.

▲hamza512b 8 hours ago | parent [-]

What choice do we have? We have to find a solution to the problem. ContentEditable is much harder to work with. This is a solution, and I hope we will at some point work out a new web API that makes these tasks easier.

Your reasoning is that I am missing out on a large percentage of users. I understand where this is coming from. I am working on mobile apps as well, as I did with iOS. I can try to close that gap even more, but I can't just switch to ContentEditable. I don't have the time, and there are already tons of projects that do that.

But if Google did it at their scale, then I think the tradeoff is reasonable, don't you think? You said in another HN post that they don't really use pure canvas. What do you mean? ContentEditable for capturing input?

▲chrismorgan 8 hours ago | parent [-]

By the time you’ve fixed as much as you can, you will certainly have more code, more complex code and more fragile code than you would have had from massaging contenteditable into your desired shape, and your result won’t even be better than it in any indisputable way.

“Pure canvas” means when the entire app runs inside a canvas to the maximum extent possible, such as with https://www.egui.rs/. Google Docs isn’t pure canvas because it uses regular DOM for the chrome, leaves text rendering to the browser (fillText or whatever) and uses real scrolling area (multiple canvases, tiling). Yours is similarly not pure canvas, though it’s a little closer in the obviously-bad way of how you implement scrolling yourself.

“Google did it” is not an endorsement for others doing it. They have often quite bizarre rationales that truly don’t apply to smaller organisations. As I have written, I’ve thought it through carefully multiple times in multiple ways, and I honestly believe they were lying about their motives through and through, because they just don’t make any sense. Google Docs was unambiguously better before they migrated to canvas, and most of their claims about what it got them were demonstrably false.

▲zenincognito a day ago | parent | prev [-]

[dead]