 How is everybody doing you okay? That is much better. I'm Paul. I'm Surma and what we normally do is we do a show called supercharged Where we live code things for people and at Polymer last year the Polymer Summit We did live live live in front of people live and we thought let's do it again And so that's exactly what we're gonna do today But what we normally do is we normally have one of us code and one of us talk But today we thought we'd have both of us code so not not at the same time I mean we could probably shouldn't we shouldn't not be stupid. We shouldn't do that So so I'm gonna code first and do you want to tell them what you get what we're gonna do all right? So I had the idea that or actually I exported my Twitter archive because I wanted to have it and look through it and it turns out that The file that contains all my tweets. I've ever done is about 16 megabytes worth of Small which is a big file and I'm not gonna open it because VS code doesn't like big files apparently, but I have the First four tweets and an extra file So that's basically what we're looking at and you can see my first treat apparently was in 2008 where I say something fundamental As got an account on Twitter yay. That's like that's everybody's first. It's the universal first tweet I think it's either that or hello world like shouting into the empty echo chamber. Yeah, nobody cares No, and what we wanted to do is How would you? Use this file in a web app bring that file back because there's something I noticed here This isn't an array of objects. Oh exactly. It's not an array. It's literally just concatenated Jason objects So they end here the next one starts there is no commas. In fact, yeah, the Jason Parsons kind of if you get rid of the selection It's got a red could wiggly under there because it thinks well, it's not real Jason Yeah, it's not a Jason file because there's more than one Jason object in there. So there's gonna be some Difficulties, so I guess before we lose more time. We just yeah, go start it And the first thing we always have to do is Type really fast and suddenly we have copyright. Yeah, we like snippets, too So I'm gonna work with some script. So what we're gonna do is I'm gonna work with My part of the program and I'm gonna use the new stuff which sirma.js That's me brilliant. Okay, fine. It's fine. Fine. That's the game you want to play I should call it Dustin because that's my Twitter handle. Okay. Like it follow me. Yeah. Wow always branding I love it. So I'm gonna use a module which is a new thing Which a allows me to be defer by default Which is something you should always be doing but also we get to use the new fancy import which we're gonna use later so let's write a new file and Look at the tweet and fetch the tweets JSON file, so I'm not gonna put anything else in here. I'm just gonna put this here and call it does surma.js and Go in here go to the networks tab and if I load this you can see I just downloaded 16 megabytes of which is quite a bit This was really really fast because I'm like have a server running locally the second you actually are on the internet This is gonna take a while Yes, you would have to wait seconds if not minutes before you could do anything with the data And that's actually a really important point We the web is a streaming medium and we actually want to treat it like that rather than saying I'm gonna hold everything back and then So what you would usually do is the official sound the official I received a response sound Yeah, what you would usually want to do is you want to take Respond and then call.json which turns the response into jason this wouldn't work you because as we have established It's not actually a jason object. It's just it's a bunch of jason. This would fail with there's like trailing data Please take care of this so I can't use it the next option that most people probably are aware of is not that Text which would give you a 16 megabyte size JavaScript string and I'm telling you on mobile. You're not gonna have a good time So we're now gonna go into the new territory and use something that probably is not as well known because Namely that response dot body is a stream. Oh What kind of stream? Thank you. I was waiting for your line. Sorry. It's a readable stream meaning that is a stream that You can read okay? They came in for the education you get it I'm gonna I'm gonna explain it more. So a readable stream is an asynchronous data structure Some people gonna scope it's a little bit like a promise, but that can be recalled multiple times So every time you get a new result back. It's a pipe of data, right? Yeah, it's a type of data Seemed data off it right and every time you get the next chunk in a network delivered But because it is from the network or because it's a stream once you get that chunk. It's gone It's been consumed and therefore they can only be one reader at a time Okay, and so what we need to do is we need to get a lock for this reader which you get by get reader Which means you have now a reader object and you're the only person who can read from this stream And if you want to what do you do if you want to get rid of the lock? Is that like there get rid of reader? Really release lock. Okay. I knew that that seems really okay. Get ready. We don't need we don't need that though So we have a reader and as I said a reader is an asynchronous data structure And so I'm gonna make use of async functions because otherwise this is gonna get weird because with async functions We can write code in a linear imperative way, even though it is a synchronous So we can do stuff that is very old-school and usually very hated upon a geologist while true. Eww Really? Yes. Oh, this isn't production code by the way. Yeah, it's not production code It will work. Yeah, hopefully hopefully, but there's yeah So what you get so when you want to read from a stream you would call your reader and say read and Since it's asynchronous. We have to wait that it's basically a promise But with the weight it just inlines all the handling and it makes much nicer And what we get from there is a value and a done flag a little bit of destructuring going on there All the new features man all yeah, so the so if we are if the stream is done It's end of stream then the then it's done so done is true and we can just return which is well a while true Loop is okay because that is our cancel condition. This is how we break out of it I'm still really if he on it seriously anyway, what is value? Let's just try out what value actually is I'm I now console lock the value thing. I'm going back here gonna open the console And we can see we just get a whole bunch of you and eight arrays This is literally the raw data from the HTTP response packaged in nice typed arrays in JavaScript And you can see that they're all pretty much 32 kilobytes big But that is more for coincidence than anything else. So for example, the last one is smaller There's probably some smaller ones somewhere in the middle. I don't know But it's a number you cannot rely on this might be an implementation detail of Chrome or my ghost server It doesn't matter the number not really relevant Okay, so now we are receiving these chunks and they're 32 k big coincidentally But the problem is really that we have these whole series of JSON objects in my tweet file and Now a tweet could be They could be multiple tweets in one chunk or they could be one tweet spanning multiple chunks and That's not really helpful. What we're gonna do is we're gonna write it so called Transform stream which is gonna transform our stream in a way that the chunks and the JSON objects align So basically every chunk After the transform we can be sure it's exactly one JSON object got it So you can pass that to jason dot-pars and you would guess a JSON object in the end We should be able to do that instead of just arbitrary splits at 32k. We want it per object exactly So now we're gonna use we're gonna use the reference implementation for transform streams They're gonna be in the browser at some point so a transform stream to explain is a readable stream a stream that you can read a Rightable stream a stream that you can write put together into one object where you put things in at one end Do some transform and get it out at the other end. Cool But they have not landed yet. So I'm gonna have to rely on the reference implementation so I'm gonna import from Transform stream.js and now we have it and can use it and let's see how to actually use it So as I said response.body is a stream and if you have a transform stream, you can use pipe through which means Here's a transform stream pipe that data through the transform and give me the result. So here we would create a new transform stream and That transform stream takes a transformer not to be confused with the cars So what so what we have to write is a JSON? Transformer you sure you don't want another new inside there as well. Let's go three deep meet more I can I can give you a variable. So this is gonna give us the JSON stream So as a return we get the transform stream, which is now a stream of individual JSON objects Okay, so afterwards we're not gonna get the lock on our body button our JSON stream and that should work So let's take a look at the actual Juicy bit, which is the JSON transformer. So class JSON Transformer it has a constructor which we are gonna need but not right now and a transformer has to has have three methods It's a start Which is called at the start. We don't need that. There's flush Which is called at the end and there is attention transform Oh, that's what we need, right? That's what we need and the transform you get two parameters the chunk that you now Have to transform and the controller and the controller is something it allows you to control your stream that Let me explain with code. I think code is always better than trying to hand wave all the things It allows you to do stuff like to define. What is the output of this chunk? You can have set all kinds of different signals like back pressure and your cash is full and We don't need any of that We just want to see a feeling if you Google for Jake Archibald streams You're probably gonna get a really good art. I think it's gonna appear. It's just yeah Well, that's the worry if you say streams too many times. I'm gonna stop mentioning the word now But so we take the controller and with NQ we can put something on to the output queue So just to show it works. I'm just gonna not do any transform whatever comes in I'm gonna take it and put it into the output. It's like a null transform So do nothing ideally everything should work the same Yes, so it's still Doing nothing just downloading the file But now we have a point where we can inject our code to do all the transformation me bits so How do you do that and the thing that we have to do now is we have to kind of Write our own little Jason parser. Really? It's not as complicated as it sounds Okay, so what what we will do is we will collect all the chunks that belong to run one Jason object Sure, and once we have those we'll squash them together get a string. Oh And then you and Q the right fine, and then we start over. Okay, so in this chunks array We're gonna collect all the chunks that belong to one Jason object And now we have to figure out how do we know when we've reached the end of a Jason object? And we do that by counting curly braces. So what we're gonna do is whenever we get a chunk Bite of chunk. So we're gonna loop over all the bytes in our chunk. That could be const That could be const. Sorry. Sorry inadvertent ring from stop it review. Sorry carry on We're gonna convert it into a character because we know Jason is always asking so we don't have to worry about Oh, yeah, you need coach and anigans. Yeah, okay And and then we're gonna switch over whatever character is and we care about it's either an opening brace sure or Closing brace closing. Hey, well done. Wait off so And we're gonna start and we're gonna try to count how deeply nest we are so whenever we encounter an opening curly brace We increase it and whenever we encounter a Caps lock is in the way. I mean this does not feel brittle to me. It's stop it I Am cool with this So when we decrease the depth We will hopefully at some point reach zero, which means we have found the end of a Jason object So what we're gonna do here? We're gonna Inmit and we're gonna talk about this later if we have reached the end of the chunk without having reached zero You want to know that we have to continue into the next chunk and this act current chunk is you have to Yes, I do the that's dancing program Do the chunk? Okay, fine. Okay, it's gonna help people understand sure. No, I get it. It's great So when we've reached the end of a chunk but not emitted it then we need to chunks push Push this is like when I type I know it's not a good. I'm the one with the typos He's the one that's normally really good at typing and it's really annoying to me cuz he's right good So we are now in the middle of some chunk we have reached zero We know the start of the chunk as part of the Jason object the rest is part of the next Jason object So we're gonna split that apart. So we have the tail You and eight Array, so that's actually interesting thing because the all these typed arrays in JavaScript are Basically just a chunk of memory and you can have different views Yeah, so we can look at the same memory as a series of floats or a series of ins Yeah, but also you can have them in different positions So we're gonna split it apart by just creating new views onto the same memory So to be clear rather than say copying this array into two separate rays You're just creating two views onto the same memory underneath And that one becomes the end of the the object and the next one becomes the start of the next object Exactly. Okay, fine. What I just realized so that for this we need to know the position the index where we had so I'm gonna rewrite to do the old I was feeling really smooth Was nice, but you know length fine plus plus done All right So the tail goes till I plus one because at the eye we have the code closing brace So the next one is where we want to cut and we have the next object where we kind of do the same And We start after and if you emit the last parameter it means all the rest of it So I because I is the curly brace I plus one is the next character fine So and because we kind after this we want to continue working on the remainder I'm just gonna get a little bit tricky and just say we're just gonna overwrite our job That's the next thing we can work on. Oh, this kind of stuff really ruins my head. Well So tail is as I said part the last bits of our Jason object So it's part of the chunks array. So now at this point We know that the chunks array is our next Jason object But potentially split into multiple chunks. Yes, we need to convert this into a string So you got several potentially you in eight arrays that need flattening down to a string. Yes, got it And sadly like to convert a buffer or an array a typed array to a string We need to use a text decoder. Sure. We do sure. So it's it's a little bit Sometimes I wish this would be simpler, but it's just now it is now And what we can do is we can use this dot chunks Reduce we're gonna start with an empty string and we're gonna take the string and the chunk and we're gonna concatenate the string with a Decoded version of the chunk and that is gonna be our Jason string Sure, it's this correct. I think it is and now we have a Jason string which we can is there is there Is there a German word for the feeling of sadness you get when something is really convoluted? I Think you could say something like Simplicismus mangel verzweiflung Pardon Simplicismus mangel verzweiflung. I love it. That's all my favorite CSS. It's almost CSS is Wait, it was cascading the stylization for login. Yes. Most of should be German always has a word All right. All right, so we have Jason string which we can emit So we now have actually turned into a string We can push that out and now the only thing left to do is to reset our state So we have to say this chunks is now empty because we're done processing it That is true. You could also set dot length equals zero. Can you yes, you can as I can do this It's really yes, you can I did not know length of readable. I'm trusting you Awkward awkward and and now this is and and because on the next loop you want to start at zero But it's a for loop so I plus plus is going to happen. We have to set it to minus one. No That's gross All right. Oh, you're not chipping that are you? Yeah, I am okay. All right, so it's prototype I'm not gonna run this code on my big treat file. I'm gonna take it on for because otherwise it's gonna take too long It's it's it's just no, okay, so if this goes, right, we're gonna see four tweets. No, we're not Line 13. Oh people are paying attention like it. What is on line 13? Oh bite is not defined. Yes So bite sure our chunk I see it's judging you because you changed my four const To that it and I typo decode Yeah That's like it's a bit bigger So we can now can see that we have four individual console locks which contain exactly one jason object Which means the alignment works? But and there is always a but so let's show you why what if there's an opening brace in a C C I see That would I said if I do that you would see nothing because the parser would see oh opening curly brace an Object started, but it's in a string and we didn't know that so what we have to do is we it's actually not that hard to fix We just need to track if we are in a string. Are you kidding me? Oh, come on So whenever we find a double quote We're just gonna go in string. It's this sure in string. Yeah, and Whenever we are yeah in string. Yeah, you don't actually care Now I'm getting that that word that feeling the German one about it doesn't feel less brittle now. Isn't it nice? No, okay? Yeah, no, it feels perfect. Great. This should work now. Yeah But slash double quote backslash double quote. Oh, yeah, he's right got that So if I so I guess if I do this it wouldn't work. Yeah, let's fix that easy easy Good shout though. It's a great shout So if we find something that is escaped which we have to escape because it's the escape line We have to skip the next character sure Skip next that is fights Can I revoke your programming license? No And if we so if we have to skip the next one we have to set it to sure false. Yeah, go on then. Yeah Continue sure. Yeah And just just the the ultimate test is going back to the full file and make dev tools grind to a halt All right, but hey scroll because we are not blocking the main thread too badly because this is actually kind of okay Kind of important actually you've gone. I've got a 16 meg file. That's being handled on the flight It's being streamed and transformed on the fly and he got what's the most recent one there is that must be German in German. Yeah, I mean I was wondering how fast is it's actually I mean, yeah There is processing going on, but it works pretty well. Hi. I mean, yeah, all right And now might go on go on move it right because normal people I don't think would sit there going oh, yes, I am enjoying your Jason coming down and watching it arrive in the the console there Well, I certainly do I know right. I mean know your audience So we thought the the better thing to do might be to actually create some kind of progress style And that's my job as always you do the visual stuff So I'm gonna make a an SC dial cuz it's super charged I think I might just call it arrow twist dial. So my branding is okay I can't believe you did that. That is no. I wonder if you want to call it dial JS or Lewis JS I want to call it or arrow twist. Yes. I want to call it stick to the script Um, arrow twist.js fine. Yes, I approve. I know you do. It's not it's not what I expected from today Okay, so I've got an SC dial. I'm gonna make something called arrow twist.js and you know what I have a custom elements I don't like writing these out with with Type in by heart. I just choose not to uh-huh With all those lifecycle callbacks already filled out for the custom elements 1.0 What's the German for custom or lifecycle callback? Functions surma lame cyclos re-cru function. See yeah, that would be one. We have right normally normally we have I'm actually gonna call SC dial normally. I go with like an unnamed class, but today. I'm not going to That's gonna apply to SC dial And I see dial And I don't need attribute change callback just did that just so you have a name for the class because you want to refer To it later. I'm gonna. Yeah, I've got a fee Yeah, we're gonna need some constants in here and I refer to them as static members of the class so Let me see what I'm gonna do first of all is I'm actually gonna get rid of this here because I like my log I know well tough. I'm in control now. I'm the one doing Right now normally you could do something like this with SVG But today I'm gonna use a canvas because I feel like not a lot of people like the canvas you talk to people like you know I did it But I use the so you're not gonna use the canvas So you're not gonna bend over backwards and try to make a diff be around and no, I'm gonna use Canvas is blazingly fast, and I think it's heavily underutilized on the web And when you use a canvas you get the context from the canvas like this Well chill no Or just to do okay old so basically can think of the can of the context as your pen that you move around on the canvas Because you give commands like move to a line to and you draw on See see I told you I was gonna do some Constants get size that makes you a good citizen because you avoid magic numbers. I know right I feel really good this dot a pen child because it's a custom element I can just call a pen child against it rather than something else it's extending html element, but but what? Take like it's it's a bug that it works in chrome Which I always thought is hilarious you are perspec not allowed to manipulate the DOM in the constructor all the custom element You have to do it in the works. It's a bug works Move it move it to the connected callback because that's very supposed to do it because Technically you cannot rely on the fact that the DOM is already available in the constructor It could still like float in the ether of custom elements works And then I probably should remove it but whatever in all right Sure, so The other thing that we're probably gonna do is so what I want is an API where we can set a percentage value for the dial as the files Come down as we get our 16 megs down. We should set a value between I'm gonna say between zero and one I'm for some We kind of need a way to put that value in from the outside exactly right? Yeah, I'm gonna do set percentage I guess the reason we're not just using a straight-up property is because we want to tie logic to the fact when somebody changes the value Exactly, right? So if it was like number Dot is I can never get that right percentage. You could just be like, you know Whoa, you could be like that throw new era no See See people that people don't there you go validation and also helpful error messages. Well done. Hey, I am all over This don't worry. I'll tidy it up before it goes on to the github repo, which it will yes our github repo By the way, it is Google Chrome slash UI element samples all our previous code is on there This one will get up there at some point today when we're done right and feel free to use it Yeah, play around. Yep. So when you set the percentage value, so we're gonna get a reference to the dial from outside We're gonna say percentage equals 1 or 0.5. We don't want to draw which will draw with on the canvas I wonder what the draw function does. Oh, I don't know. Let's see. So what we'll do is we will begin So you always operate against the context or begin path and then I always say if you're gonna do something like begin pass or a path Always use or is it close path? Always put its corresponding because the opposite of begin is close. It's close That makes sense. Welcome to the web. I know right. So we want I'm gonna do like a circular dial, right? So I want an arc. So like a normal progress bar, but bend into a circle. Yeah all the way around So I love this and so I've got to do x y radius. Okay fine. So I'm gonna say mid mid and mid now I haven't defined mid yet. So that's fine zero. Let me guess. It's the middle. Oh, you're so good at this fine fine fine No point for I'm just mate. I'm guessing an angle which is in radians Just because I want to check that it draws something because when you're working with a canvas sometimes it draws nothing and That's fun to debug. Yeah, so const mid equals SC dial. So we're gonna go for the size I'm gonna hand-tune this. We're getting some good mileage out of the constant. Well, we're getting some good mileage out of the constant I know right all over the place. It's gonna be great this don't you also want to do like like a half shush shush See that didn't draw anything Do you know why because after you've closed the path you actually have to say to the context to fill the path Yeah, because path just defines the path and you have to say what do you can stroke it or you can fill it Or you can probably do both I think don't we need to do as well. You actually need to call draw Oh What a day? Oh, there we go. Hey, we got something drawing at least I mean You're easily excitable now Now the thing is that's not really what I wanted because I want to kind of pie kind of I mean It makes sense because you just say go here draw arc and then go back to your start Yeah, it's correct. And as always you did the mistake not the computer Thanks So the fix for this is to actually move your pen to the middle middle They're gonna let you say before it's like you think of it the context is like a pen So if you move the pen as it were and you say move to inside the begin path and you say mid mid It draws the kind of pie chart kind of that's good. Oh, which is good So now that's that's pretty good. So what else are we gonna do? Let's see. Let's call this The outer I mean I I find it a little weird that it kind of starts to the right because yeah We all learn to read the clock. So I feel like okay fine, you know, yeah, that's fair enough, right? So yeah, he's right You wouldn't normally go out to the side with you if you're gonna start progress you start at top middle now One option here would be to take this start angle as being zero and just do like minus 90 degrees But it in the interest of showing something else to do with the canvas. I thought I would do it like this We do a rotate we rotate the canvas which is gonna rotate the coordinate system And I'm gonna get the corner system basically gets turned minus SC dialed up. Let's see. I'm such a grown-up 90 degree Really 90 degrees. I was like a proper but half doesn't get it on constant. No, I mean no Return math dot pi times by naught point five Right, didn't we just say sometimes the canvas draws nothing? Yes, I know what this is because I've seen it before It's because we're actually rotating around the top left hand corner We're actually rotating around the origin top left. Oh, so we're kind of we have this thing here And because we're getting it out of the drawing up there. We're cool. It's just to help people So you're basically just gonna move the origin. Yes, and then go I'm gonna so yeah If you move the origin with a translate And we move it to the middle middle So we move it to the mid and then we rotate and then we move it back again It sounds odd, but it will work. It makes sense, but otherwise you would have to Yeah, I don't know. I'll see you do it It is it is right now. There you go. Yes. That's good Here's another thing. I think what we'll do is we'll do an inner arc while we're here And then we're gonna actually wire it up to your code, which is now legacy code. Ew We started out at bleeding edge and it's already obsolete. I've no kidding me That's yeah, right. So math dot pi times by two because we want a full I want a full sort of circle circle. Oh, oh, oh, oh, oh, this will be fun. This won't get anybody upset We'll call it tau you flame Bade Apparently this has support in this room. Hey, I'm not like yes, you should use tau which is the same as two times pie trolling right, so we'll do this dot ctx dot Fill fill style equals Let's do white. Let me go I'm gonna need a fill style here. So for now. I'll set that to back to the black All right. Now that doesn't look great because yeah, no same radio. No, but if I do mid times by naught point eight Look at that. I'm not nice. So we get like a little We're good. We're good. Now. Let's wire it up to your stuff In actual the loading percentage so do percentage which will be a value between zero and one times by s c dowel Okay Which will be disappeared because the value is zero, which is fine So actually this time it's working as intended even though we don't see anything absolutely so over here in your thing I'm gonna get reference dial equals document and this is where we can say this is a production code because now We're kind of mixing concerns. It's my module was supposed to take care of loading. Oh, and now we also kind of like patching UI stuff in there But you know for the sake of how to do this. It's valid. I think sure keep going keep typing Okay, so if it's done well, we know that dial dot percentage is one. That's fine That is correct and for everything else. We actually want to know how many bytes have come through the wire So we need the total bytes. So let's say bytes total HTTP protocol can help you with that. Yes, it can with the headers dot get and then we're gonna ask for the content length and Then I'm just gonna pause in on that. There we go back here Yeah, because it's a string and if you divide by string Yeah, it's not gonna be nice and javascript, right? So we know the total number of bytes if that header comes through which I'm relying on Let bytes counted be zero sure now if we get down here We're gonna have to say we're gonna add so we can just increase by the number by the string length because that's because it's Jason that is equal the number of bytes because there's no unicode things Yeah, right. It's counted over bytes total. Yeah, she got right between zero good Yeah, that's not I mean kinder just for that. Just we could just say this is intended and ship it Sure, you know what's going on here? The the canvas is it's a state machine Effectively so every time we call draw. It's trying. It's rotating the canvas by 90 degrees. Whoop Oh, so we keep just rotating and drawing. Yeah, that's obviously the drawing effect So what we can do here is we can actually ask before we do that The the rotation and so forth we can actually ask the canvas to save it's it's stuff It's state basically like what's the fill style everything like that We can save it and this is another one of those moments where if you call dot save you immediately figure out where you're gonna call This dot ctx dot restore where you're gonna bring it back because otherwise you're gonna push something onto a stack And you're never gonna pop it and that won't be fun for you Oh, so this will basically revert to the previous state except all the drawing has happened in the meantime will persist Yes, so here we should now go round. Ah That's definitely better, but it's actually you probably can't tell I'm gonna zoom in. There you go It is. Oh, that's very pixelated, isn't it? It is a bit. It's really jagged and the reason is because you also have to clear the canvas it is Oh by default draws actually smooth, which is why this is surprising But we keep drawing over and over the edges so it adds up to not smooth So we'll do the size and we'll do the size One of the most efficient constants ever created see right much smoother now while I'm here since it's not in the middle of the screen I'm gonna move it to the middle of the screen, and I do like doing this style Style there you go. Okay ML body Let's do with I do that all the time. Ah, you want to oh, are you gonna do the master discipline of CSS of vertical centering? Yeah That's good when people like you can't do vertical centering in CSS you can say sure you can display flex if you can line items center Justify content center smile a happy smile hooray, right? Next up I am gonna go back and I'm gonna change this color from black And I'm gonna say it looks a little bit. Yeah on a crook. All right. Rgb128. There we go. That's a blue color Well, let's make it nicer By let's see when let's do this is a template string. Oh I'll stop it Paul. There we are told you I made typos. Let's do so. We'll do what this stop percent whoa That would be interesting. Yeah, that would be weird times by 255 Oh, so we're gonna go from like blue and no red to blue and full red except we're going from black to pink Why ours Rgb values have to be rounded. Oh, so once you have decimal points CSS goes like no Okay, okay, so well we're doing all right here, aren't we make it? What else can we do? Oh, we could put an actual number in the middle to tell you how far we've actually got through the downloading Let's do that. Let's do that here. So put label label label label see how I'm actually doing I actually doing comments because I know when you come back to canvas Code in just like half an hour after this and we're gonna try to upload this we will have gotten what it is about Yeah, it's right after regular expressions. Were you like really? It's like just face on keyboard and it still kind of works brings out my prettiest faces that one Right, okay. We're gonna do fill text. So we know we want to do that Oh, we should set the color for that cdx dot fill style Yeah equals let's do it as a kind of gray color All right fill text Person you would prefer three three three honestly really okay fine fine You know normally that bothered by this kind of stuff fine three three three slightly darker great percentage times by a hundred And we'll do it at mid-mid in the middle of the dial. Sure. Sounds good. I mean I Would ship it sure Do you know what this is actually a great opportunity to talk about the restore because if we do the restore before the label It's still turned it still turned so we'll do that that'll put it back where it needs to go Hey, that's a start and then we can do let's see probably around this too mass dot round Yeah, I think you're right. I don't people don't care about like the 15th decimal place. I know right. It's tiny Tiny that is okay. Let's make it bigger. This yeah Ctx dot font equals. Let's have a look we would want to do let's make it a one of these and we'll say oh No, wait, let's see dial dot size see oh because you'll make it dependent on the that is good quarter the size Px aerial sure that's gonna be fine. Okay. Sounds good symmetry I mean And the thing is you don't handle negative feedback very well some The things I feel like the bottom left corner of the one is actually perfectly centered Yeah, it is actually it's because the the text baseline and the text alignment It will mean that it is for the bottom left hand corner which we can change by saying this dot I thought we'd have to like measure ourselves or something when you know doable. That would be awful. You imagine no We just do this text baseline Oh because I like how one in the middle of the other one center would be yeah would be too easy So flexbox is a center center SVG. Yeah, sure. Let's not talk about it. There you go But I think what we can do is it's not ourselves another label because we can On this one, I'm gonna do this one at seven seven seven. Is that okay? All right, I'll let you have it. I mean, okay. Let's do this at like. Oh, I don't know 0.06. I love just guessing numbers I don't think yeah, you can like number fishing is great fun. You're like 0.6. No Yeah, why did you stop using like constants now? Huh? Huh don't we mean All right percent. That's rubbish great stuff. Let's do minus 20 Plus 15 Sure, ooh close, but not quite minus 20 plus but no cigar. There we go that feels now I don't like that looking good minus 15 when it's 14 gone then plus 26 Sure, why not? Why not? I mean, it looks good. I feel pretty good about this Can can we do this with network throttling just to have like a little bit more time with what network throttling? Oh, sorry. I didn't more time. Yeah Yeah, because at the moment this is no throttling so imagine then we were to click on that and it was regular 4g Now this is actually really important because we're now not blocking as sermas code showed you We're not blocking on this stuff coming down before we show anything And we're actually able to give the user some kind of information And if you needed to do something with those tweets like Jason dot parsing them showing them in IDB something like that You could be doing that kind of work here, too We could already be rendering parts of the tweets because every chunk contains one tweet So we could start listing things while there's a progress bar in the top And yeah, the main thread is still available as you can see because it can draw Let's do that. In fact, let's we have just about enough time. I think to get away with this So on the connected callback we couldn't call draw I'm gonna do a request animation frame to call this dot draw and I'm not gonna call it anymore. So it's gonna go into this kind of busy It's just always gonna draw and it's gonna probably break I'm not gonna spend ages explaining why it's because the request animation frame the When it's called This stops referring to the class instance and starts referring to window. So the way to to fix that It's the Lewis bind as I call it. Yeah dot bind. It's weird But this we cover it every single super charge because I always Keep doing it right and since that's drawing every frame now We should be able to do a recording here And we should be able to see that so it is this is if it works It's comfortably at 60 FPS. We have loads of headspace headroom in our per-frame budget We're getting something to our users really fast and we are out of time But just a reminder we've covered streams transform streams. We've covered custom elements We've drawn canvas stuff. We've got you something which is taking 16 megs of Java Jason and I think we're in under 200 lines of code or something. Yeah, let me just check We are in not this is a reminder just how awesome the web platform can be because you've got what about 110 from me And you've got about 70 or so from you so that is about 180 lines of code And we've got something that I think is reusable and quite interesting. So there you go Thank you very much for joining us today. We've had a great time