@internetarchive/ia-book-actions 0.1.4 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/demo/index.html CHANGED
@@ -131,11 +131,11 @@
131
131
  iaBookActions.returnUrl = 'https://openlibrary.org';
132
132
  iaBookActions.localCache = localCache;
133
133
 
134
- let loanTotalTime2Min = { loanTotalTime: 20, loanRenewAtLast: 15, pageChangedInLast: 15 };
135
- let loanTotalTime5Min = { loanTotalTime: 300, loanRenewAtLast: 180, pageChangedInLast: 15 };
134
+ let loanTotalTime2Min = { loanTotalTime: 20, loanRenewAtLast: 15, pageChangedInLast: 5 };
135
+ let loanTotalTime5Min = { loanTotalTime: 300, loanRenewAtLast: 290, pageChangedInLast: 15 };
136
136
  let loanTotalTime1Hour = { loanTotalTime: 3600, loanRenewAtLast: 600, pageChangedInLast: 900 };
137
137
 
138
- iaBookActions.loanRenewTimeConfig = loanTotalTime1Hour;
138
+ iaBookActions.loanRenewTimeConfig = loanTotalTime5Min;
139
139
 
140
140
  let lendingStatus1 = iaBookActions.lendingStatus;
141
141
  let secondsLeftOnLoan = iaBookActions.loanRenewTimeConfig.loanTotalTime;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@internetarchive/ia-book-actions",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Bookreader actions for borrowable book",
5
5
  "author": "Internet Archive",
6
6
  "license": "AGPL-3.0-only",
@@ -31,6 +31,12 @@ export default class TimerCountdown extends LitElement {
31
31
  */
32
32
  this.loanRenewAtLast = 0;
33
33
 
34
+ /**
35
+ * store time when timer is started
36
+ * @type {string}
37
+ */
38
+ this.timeWhenTimerStart = '';
39
+
34
40
  /**
35
41
  * delay seconds in setInterval function
36
42
  * @type {number}
@@ -42,32 +48,36 @@ export default class TimerCountdown extends LitElement {
42
48
  window?.IALendingIntervals?.clearTimerCountdown();
43
49
  }
44
50
 
51
+ firstUpdated() {
52
+ this.timerCountdown();
53
+ }
54
+
45
55
  updated(changed) {
46
56
  if (changed.has('secondsLeftOnLoan') && this.secondsLeftOnLoan > 0) {
47
- this.disconnectedCallback();
48
-
49
57
  this.timerCountdown();
50
58
  }
51
59
  }
52
60
 
53
61
  timerCountdown() {
62
+ this.disconnectedCallback();
63
+
54
64
  // - let just execute setInterval in every 1 minute
55
65
  this.timerExecutionSeconds = 60;
66
+ let secondsLeft = this.secondsLeftOnLoan;
67
+
68
+ // store current time
69
+ this.timeWhenTimerStart = new Date();
56
70
 
57
71
  /**
58
72
  * set interval in window object
59
73
  * @see ia-lending-intervals.js
60
74
  */
61
- window.IALendingIntervals.timerCountdown = setInterval(() => {
62
- this.secondsLeftOnLoan -= this.timerExecutionSeconds;
63
- const secondsLeft = Math.round(this.secondsLeftOnLoan);
75
+ window.IALendingIntervals.timerCountdown = setInterval(async () => {
76
+ secondsLeft -= this.timerExecutionSeconds;
77
+ secondsLeft = Math.round(secondsLeft); // round number
64
78
 
65
- console.log(
66
- 'timeLeftInSec',
67
- secondsLeft,
68
- ' ||| timeLeftInMin',
69
- Math.ceil(secondsLeft / 60)
70
- );
79
+ // re-sync timer is gone off
80
+ await this.reSyncTimerIfGoneOff(secondsLeft);
71
81
 
72
82
  /**
73
83
  * execute from last 10th minute to 0th minute
@@ -76,26 +86,74 @@ export default class TimerCountdown extends LitElement {
76
86
  * @see IABookActions::bindLoanRenewEvents
77
87
  */
78
88
  if (secondsLeft <= this.loanRenewAtLast) {
79
- this.dispatchEvent(
80
- new CustomEvent('IABookActions:loanRenew', {
81
- detail: {
82
- hasPageChanged: false,
83
- secondsLeft,
84
- },
85
- bubbles: true,
86
- composed: true,
87
- })
88
- );
89
+ this.dispatchLoanRenewEvent(secondsLeft);
89
90
  }
90
91
 
91
- // clear interval
92
- if (secondsLeft <= 60) {
92
+ // clear interval in secondsLeft if less
93
+ if (secondsLeft <= this.timerExecutionSeconds) {
93
94
  this.disconnectedCallback();
94
95
  window?.Sentry?.captureMessage(sentryLogs.clearOneHourTimer);
95
96
  }
96
97
  }, this.timerExecutionSeconds * 1000);
97
98
  }
98
99
 
100
+ /**
101
+ * dispatch loan renew attempt event
102
+ *
103
+ * @param {number} secondsLeft
104
+ * @memberof TimerCountdown
105
+ */
106
+ dispatchLoanRenewEvent(secondsLeft) {
107
+ this.dispatchEvent(
108
+ new CustomEvent('IABookActions:loanRenew', {
109
+ detail: {
110
+ hasPageChanged: false,
111
+ secondsLeft,
112
+ },
113
+ bubbles: true,
114
+ composed: true,
115
+ })
116
+ );
117
+ }
118
+
119
+ /**
120
+ * helper function to determine if timer is not in sync properly
121
+ *
122
+ * @param {number} timerSecondsLeft - actual seconds left get from setInterval
123
+ *
124
+ * @memberof TimerCountdown
125
+ */
126
+ async reSyncTimerIfGoneOff(timerSecondsLeft) {
127
+ // debug info
128
+ console.log(
129
+ new Date().toLocaleTimeString(),
130
+ 'timeLeftInSec',
131
+ timerSecondsLeft,
132
+ ' ||| timeLeftInMin',
133
+ Math.ceil(timerSecondsLeft / 60)
134
+ );
135
+
136
+ const currentTime = new Date();
137
+
138
+ // current time - loan time
139
+ const diffInSeconds =
140
+ currentTime.getTime() / 1000 - this.timeWhenTimerStart.getTime() / 1000;
141
+
142
+ const secondsShouldLeft = this.secondsLeftOnLoan - diffInSeconds;
143
+
144
+ // convert in minutes
145
+ const whatIsleft = Math.round(timerSecondsLeft);
146
+ const whatShouldLeft = Math.round(secondsShouldLeft);
147
+
148
+ if (whatIsleft !== whatShouldLeft) {
149
+ // debug info
150
+ console.log(
151
+ `timer is gone off, let's re-sync, whatIsleft -> ${whatIsleft}, whatShouldLeft -> ${whatShouldLeft}`
152
+ );
153
+ this.secondsLeftOnLoan = secondsShouldLeft; // the seconds should left in timer again
154
+ }
155
+ }
156
+
99
157
  /**
100
158
  * get remaining time with timeunit
101
159
  *
@@ -240,7 +240,7 @@ export default class IABookActions extends LitElement {
240
240
  */
241
241
  setTimeout(
242
242
  () => {
243
- this.startLoanTokenPoller();
243
+ if (!hasExpired) this.startLoanTokenPoller();
244
244
  },
245
245
 
246
246
  // if book is renew while reading, let's wait to execute create-token api
@@ -260,12 +260,13 @@ export default class IABookActions extends LitElement {
260
260
  * dispatched this event from bookreader page changed
261
261
  */
262
262
  window.addEventListener('BookReader:userAction', () => {
263
+ console.log('user action');
264
+ this.suppressToast = true;
265
+ this.closeToastManager();
266
+
263
267
  if (this.borrowType === 'browsed') {
264
- this.suppressToast = false;
265
268
  this.autoLoanRenewChecker(true);
266
269
  }
267
-
268
- return nothing;
269
270
  });
270
271
 
271
272
  /**
@@ -320,6 +321,16 @@ export default class IABookActions extends LitElement {
320
321
  this.loanRenewResult = this.loanRenewHelper.result;
321
322
  }
322
323
 
324
+ /**
325
+ * close/hide toast message
326
+ */
327
+ async closeToastManager() {
328
+ const toastTemplate = this.shadowRoot.querySelector('toast-template');
329
+ if (toastTemplate) {
330
+ toastTemplate?.remove();
331
+ }
332
+ }
333
+
323
334
  /**
324
335
  * Show toast messages on some specific loan renew features. e.g.
325
336
  * - show message when book is auto renewed
@@ -329,14 +340,11 @@ export default class IABookActions extends LitElement {
329
340
  async showToastMessage() {
330
341
  if (this.suppressToast) return;
331
342
 
332
- const iaBookActions = document.querySelector('ia-book-actions')?.shadowRoot;
333
- if (!iaBookActions) return;
334
-
335
- let toastTemplate = iaBookActions.querySelector('toast-template');
343
+ let toastTemplate = this.shadowRoot.querySelector('toast-template');
336
344
  if (!toastTemplate) {
337
345
  toastTemplate = document.createElement('toast-template');
338
346
  }
339
- await iaBookActions.appendChild(toastTemplate);
347
+ await this.shadowRoot.appendChild(toastTemplate);
340
348
 
341
349
  // if secondsLeft < 60, consider it 1 minute
342
350
  let { secondsLeft } = this.loanRenewResult;
@@ -573,8 +581,7 @@ export default class IABookActions extends LitElement {
573
581
  * @param {string} event.detail.data.error - error message
574
582
  */
575
583
  handleLendingActionError(event) {
576
- // toggle activity loader
577
- this.handleToggleActionGroup();
584
+ this.disableActionGroup = false;
578
585
 
579
586
  // clear all intervals for lending system when error occured
580
587
  window?.IALendingIntervals?.clearAll();
@@ -582,7 +589,9 @@ export default class IABookActions extends LitElement {
582
589
  const action = event?.detail?.action;
583
590
  const errorMsg = event?.detail?.data?.error;
584
591
 
585
- if (errorMsg) this.showErrorModal(errorMsg, action);
592
+ // template not show create_token errors
593
+ if (errorMsg && action !== 'create_token')
594
+ this.showErrorModal(errorMsg, action);
586
595
 
587
596
  // if error related to loan token
588
597
  // - clear tokenPoller interval
@@ -616,8 +625,6 @@ export default class IABookActions extends LitElement {
616
625
 
617
626
  /* show error message if something went wrong */
618
627
  async showErrorModal(errorMsg, action) {
619
- this.disableActionGroup = false;
620
-
621
628
  // check if this.modal passed as prop
622
629
  if (!this.modal) {
623
630
  this.modal = document.querySelector('modal-manager');
@@ -1,146 +0,0 @@
1
- <!doctype html>
2
- <html lang="en-GB">
3
-
4
- <head>
5
- <meta charset="utf-8">
6
- <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
7
- <style>
8
- html {
9
- font-size: 10px;
10
- /* This is to match petabox's base font size */
11
- }
12
- body {
13
- margin: 0;
14
- text-align: center;
15
- font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
16
- }
17
- #demo {
18
- height: 50px;
19
- }
20
- ia-book-actions {
21
- --white: #fff;
22
- --black: #000;
23
- --primaryBGColor: var(--black);
24
- --secondaryBGColor: #222;
25
- --tertiaryBGColor: #333;
26
- --primaryTextColor: var(--white);
27
- --primaryCTAFill: #194880;
28
- --primaryCTABorder: #c5d1df;
29
- --secondaryCTAFill: #333;
30
- --secondaryCTABorder: #999;
31
- --secondaryCTAFillRGB: 51, 51, 51;
32
- --primaryErrorCTAFill: #e51c26;
33
- --primaryErrorCTABorder: #f8c6c8;
34
- --primaryCTAFillRGB: 25, 72, 128;
35
- --primaryErrorCTAFillRGB: 229, 28, 38;
36
- --primaryDisableCTAFill: #767676;
37
- }
38
-
39
- fieldset {
40
- width: fit-content;
41
- margin-top: 50px;
42
- }
43
- fieldset legend {
44
- text-align: left;
45
- font-size: 12px;
46
- }
47
- td {
48
- color: white;
49
- font-size: 14px;
50
- border-radius: 5%;
51
- display: table-cell;
52
- text-align: initial;
53
- margin: 5px 0;
54
- width: max-content;
55
- display: block;
56
- }
57
- label {
58
- padding: 10px;
59
- display: block;
60
- cursor: pointer;
61
- margin: 2px;
62
- background: #4e545a;
63
- border-radius: 10px;
64
- }
65
- input[type="radio"], input[type="checkbox"] {
66
- margin-top: 0;
67
- vertical-align: middle;
68
- }
69
-
70
- .initial td {
71
- float: left;
72
- margin: 2px;
73
- }
74
-
75
- body.modal-manager-open {
76
- overflow: hidden;
77
- }
78
-
79
- modal-manager[mode='closed'] {
80
- display: none;
81
- }
82
- </style>
83
- </head>
84
-
85
- <body>
86
- <ia-bookreader class="focus-on-child-only" signedin="" fullscreen="">
87
- <div slot="header">
88
- <ia-book-actions></ia-book-actions>
89
- </div>
90
- <div slot="main">
91
- <div id="BookReader"></div>
92
- </div>
93
- </ia-bookreader>
94
-
95
-
96
- <script type="module">
97
- /* eslint-disable */
98
- import '@internetarchive/bookreader';
99
- import '@internetarchive/bookreader/BookReader/jquery-1.10.1.js';
100
- import '@internetarchive/bookreader/BookReader/BookReader.js';
101
- import '../src/ia-book-actions.js';
102
- import {
103
- defaultLendingStatus,
104
- canBrowseAndBorrow,
105
- } from '../src/assets/data/lending-get-status-service.js';
106
- import { ModalConfig } from '@internetarchive/modal-manager';
107
-
108
- const userid = '@neeraj-archive';
109
- const identifier = 'naturalhistoryof00unse_4111';
110
- let bwbPurchaseUrl = 'https://www.betterworldbooks.com/product/detail/cambridge-ancient-hist-v04-0521044863';
111
-
112
- let iaBookActions = document.querySelector('ia-book-actions');
113
-
114
- // for debugging
115
- window.iaBookActions = iaBookActions;
116
-
117
- const modalConfig = new ModalConfig();
118
- modalConfig.headerColor = '#d9534f';
119
-
120
- let lendingBarPostInit = function lendingBarPostInit() {
121
- setTimeout(function() {
122
- console.log('executed', 'br.init()');
123
- }, 100);
124
- }
125
-
126
- // set defaultLendingStatus for unavailable (without borrowables) book
127
- iaBookActions.userid = userid;
128
- iaBookActions.identifier = identifier;
129
- iaBookActions.bookTitle = 'Contemporary Black biography. Volume 39 : profiles from the interContemporary Black biography. Volume 39';
130
- iaBookActions.lendingStatus = canBrowseAndBorrow;
131
- iaBookActions.bwbPurchaseUrl = '';
132
- iaBookActions.modalConfig = modalConfig;
133
- iaBookActions.lendingBarPostInit = lendingBarPostInit;
134
- iaBookActions.tokenDelay = 2000; // 2 seconds
135
- iaBookActions.returnUrl = 'https://openlibrary.org';
136
-
137
- let lendingStatus1 = iaBookActions.lendingStatus;
138
-
139
- const manifest = await fetch('https://ia801302.us.archive.org/BookReader/BookReaderJSIA.php?id=goody&itemPath=/29/items/goody&server=ia801302.us.archive.org&format=jsonp&subPrefix=goody&requestUri=/details/goody/mode/1up%3Fview%3Dtheater%26ui%3Dembed%26wrapper%3Dfalse');
140
-
141
- console.log('manifest ****', manifest).then(res => res.json());
142
- </script>
143
-
144
- </div>
145
- </body>
146
- </html>