{"id":137,"date":"2018-05-19T16:54:39","date_gmt":"2018-05-19T16:54:39","guid":{"rendered":"http:\/\/www.bullcrane.com\/angular\/?p=137"},"modified":"2018-05-20T22:46:05","modified_gmt":"2018-05-20T22:46:05","slug":"session-timer-problem","status":"publish","type":"post","link":"http:\/\/www.bullcrane.com\/angular\/2018\/05\/19\/session-timer-problem\/","title":{"rendered":"Session timer problem"},"content":{"rendered":"<p>Spotify&#8217;s web API uses OAuth for user authentication.\u00a0 I am using the option that produces an access token that works for sixty minutes and then expires.\u00a0 I want the user to know about this, so that it is clear what has happened if the session expires.\u00a0 Ordinary use of Shufflizer should not take more than a minute or two, but, of course, users can behave differently from what we expect, including simply leaving the app sitting open for a while and then returning.<\/p>\n<h6>My initial solution<\/h6>\n<p>I have created an <em>Observable.timer<\/em> that counts down minutes.\u00a0 I render this in a box.\u00a0 I turn the background red when we are down to five minutes.\u00a0 When we are down to zero then I also disable the <em>upload to spotify<\/em> button.\u00a0 It isn&#8217;t going to work any more.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-138\" src=\"http:\/\/www.bullcrane.com\/angular\/wp-content\/uploads\/2018\/05\/shufflizer_expire.png\" alt=\"\" width=\"399\" height=\"292\" srcset=\"http:\/\/www.bullcrane.com\/angular\/wp-content\/uploads\/2018\/05\/shufflizer_expire.png 399w, http:\/\/www.bullcrane.com\/angular\/wp-content\/uploads\/2018\/05\/shufflizer_expire-300x220.png 300w\" sizes=\"(max-width: 399px) 100vw, 399px\" \/><\/p>\n<h6>Problem:\u00a0 Observable.timer is cold<\/h6>\n<p>This has been working, but not exactly right.\u00a0 After a bit of testing I have concluded that <em>timer<\/em> is a cold observable, rather than hot.\u00a0 I am starting two sixty minutes timers, not one.\u00a0 The first timer starts when the page loads.\u00a0 It is reported in the box.\u00a0 This is good.\u00a0 The second timer starts when the user makes an edit to the playlist.\u00a0 It controls the disable of the button.\u00a0 This is bad.\u00a0 Waiting until the user makes an edit is not what I intended and is not accurate.<\/p>\n<p>Here is my observable.\u00a0 This counts down minutes from 60:<\/p>\n<pre>this.sessionCountdown = Observable.timer(0, 60000)\r\n  .map(mins =&gt; 60 - mins)\r\n  .takeWhile(minsRemaining =&gt; minsRemaining &gt;= 0);<\/pre>\n<p>My problem is in my HTML template, in my TypeScript expression for the <em>disable.<\/em>\u00a0 TypeScript&#8217;s <em>or <\/em>operator (the double-bar ||) does not execute its second part unless its first part is false.\u00a0 I coded an async pipe subscribe for the second part, not realizing that this subscribe creates its own instance of the timer.\u00a0 The user finally makes an edit to the playlist.\u00a0 Only then does TypeScript flop over to the other side of the double-bar, therefore starting the timer:<\/p>\n<pre>&lt;button (click)=\"uploadToSpotify()\"\r\n  mat-raised-button\r\n  [disabled]=\"!playlistIsEdited()<span style=\"color: #ff0000;\">||(sessionCountdown | async)&lt;=0<\/span>\"&gt;\r\n  &lt;i class=\"material-icons\"&gt;file_upload&lt;\/i&gt;\r\n  Upload to Spotify\r\n&lt;\/button&gt;<\/pre>\n<p>I am going to work on making the timer a singleton, so that I get something more like a hot observable.<\/p>\n<p>While I am working on this, I also need to deal with page reloads.\u00a0 I think I will do that with <em>session storage<\/em>.\u00a0 The timer should not start over if the page reloads.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Spotify&#8217;s web API uses OAuth for user authentication.\u00a0 I am using the option that produces an access token that works for sixty minutes and then expires.\u00a0 I want the user to know about this, so that it is clear what has happened if the session expires.\u00a0 Ordinary use of Shufflizer should not take more than &hellip; <\/p>\n<p class=\"link-more\"><a href=\"http:\/\/www.bullcrane.com\/angular\/2018\/05\/19\/session-timer-problem\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Session timer problem&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[7],"tags":[],"_links":{"self":[{"href":"http:\/\/www.bullcrane.com\/angular\/wp-json\/wp\/v2\/posts\/137"}],"collection":[{"href":"http:\/\/www.bullcrane.com\/angular\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.bullcrane.com\/angular\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.bullcrane.com\/angular\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.bullcrane.com\/angular\/wp-json\/wp\/v2\/comments?post=137"}],"version-history":[{"count":14,"href":"http:\/\/www.bullcrane.com\/angular\/wp-json\/wp\/v2\/posts\/137\/revisions"}],"predecessor-version":[{"id":157,"href":"http:\/\/www.bullcrane.com\/angular\/wp-json\/wp\/v2\/posts\/137\/revisions\/157"}],"wp:attachment":[{"href":"http:\/\/www.bullcrane.com\/angular\/wp-json\/wp\/v2\/media?parent=137"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.bullcrane.com\/angular\/wp-json\/wp\/v2\/categories?post=137"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.bullcrane.com\/angular\/wp-json\/wp\/v2\/tags?post=137"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}