@internetarchive/ia-book-actions 1.4.4-alpha16 → 1.4.4-alpha17
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/package.json
CHANGED
|
@@ -26,6 +26,11 @@ export class LoanTokenPoller {
|
|
|
26
26
|
* attempt_to_renew_loan() already minted a valid access token as part
|
|
27
27
|
* of the renew_loan response itself — an immediate confirming
|
|
28
28
|
* create_token call is redundant.
|
|
29
|
+
* @param {Function} [options.onTokenRefreshed] - called after EVERY
|
|
30
|
+
* successful create_token, initial or routine — unlike successCallback,
|
|
31
|
+
* which only fires for the initial one. Lets the consumer retry any
|
|
32
|
+
* page image that failed during a prior access gap, now that access is
|
|
33
|
+
* confirmed good again.
|
|
29
34
|
*/
|
|
30
35
|
constructor(options = {}) {
|
|
31
36
|
const {
|
|
@@ -35,6 +40,7 @@ export class LoanTokenPoller {
|
|
|
35
40
|
errorCallback,
|
|
36
41
|
pollerDelay,
|
|
37
42
|
skipInitialCall = false,
|
|
43
|
+
onTokenRefreshed,
|
|
38
44
|
} = options;
|
|
39
45
|
|
|
40
46
|
this.identifier = identifier;
|
|
@@ -43,6 +49,7 @@ export class LoanTokenPoller {
|
|
|
43
49
|
this.errorCallback = errorCallback; // callback function to be called after loan token is created
|
|
44
50
|
this.pollerDelay = pollerDelay; // value in seconds
|
|
45
51
|
this.skipInitialCall = skipInitialCall === true;
|
|
52
|
+
this.onTokenRefreshed = onTokenRefreshed;
|
|
46
53
|
|
|
47
54
|
this.loanTokenInterval = undefined;
|
|
48
55
|
|
|
@@ -111,6 +118,7 @@ export class LoanTokenPoller {
|
|
|
111
118
|
identifier: this.identifier,
|
|
112
119
|
isInitial,
|
|
113
120
|
});
|
|
121
|
+
this.onTokenRefreshed?.();
|
|
114
122
|
if (isInitial) this.successCallback();
|
|
115
123
|
},
|
|
116
124
|
});
|
package/src/ia-book-actions.js
CHANGED
|
@@ -55,6 +55,10 @@ export default class IABookActions extends LitElement {
|
|
|
55
55
|
type: Function,
|
|
56
56
|
attribute: false,
|
|
57
57
|
},
|
|
58
|
+
reloadPageImages: {
|
|
59
|
+
type: Function,
|
|
60
|
+
attribute: false,
|
|
61
|
+
},
|
|
58
62
|
barType: { type: String },
|
|
59
63
|
sharedObserver: { attribute: false },
|
|
60
64
|
disableActionGroup: { type: Boolean },
|
|
@@ -77,6 +81,7 @@ export default class IABookActions extends LitElement {
|
|
|
77
81
|
this.width = 0;
|
|
78
82
|
this.bwbPurchaseUrl = '';
|
|
79
83
|
this.lendingBarPostInit = () => {};
|
|
84
|
+
this.reloadPageImages = () => {};
|
|
80
85
|
this.barType = 'action'; // 'title'|'action'
|
|
81
86
|
this.sharedObserver = undefined;
|
|
82
87
|
this.disableActionGroup = false;
|
|
@@ -762,6 +767,12 @@ export default class IABookActions extends LitElement {
|
|
|
762
767
|
// triggered this renewal.
|
|
763
768
|
this.skipNextInitialTokenCall = true;
|
|
764
769
|
|
|
770
|
+
// Retry any page image that failed during the gap this renewal just
|
|
771
|
+
// closed, right away rather than waiting for the next routine
|
|
772
|
+
// create_token tick (up to tokenDelay seconds away, now that the
|
|
773
|
+
// initial one above is skipped).
|
|
774
|
+
this.reloadPageImages();
|
|
775
|
+
|
|
765
776
|
if (this.recoveringFromLoanExpiry) {
|
|
766
777
|
// Only now is it safe to re-initialize BookReader — not for a
|
|
767
778
|
// routine top-up, where that would be disruptive. Call it
|
|
@@ -935,6 +946,13 @@ export default class IABookActions extends LitElement {
|
|
|
935
946
|
const errorCallback = eventObj => {
|
|
936
947
|
this.handleLendingActionError(eventObj);
|
|
937
948
|
};
|
|
949
|
+
// BookReader has no self-healing for a page <img> that failed while
|
|
950
|
+
// access was briefly invalid — retry any of those now that this
|
|
951
|
+
// create_token confirms access is good again, on every success, not
|
|
952
|
+
// just the initial one.
|
|
953
|
+
const onTokenRefreshed = () => {
|
|
954
|
+
this.reloadPageImages();
|
|
955
|
+
};
|
|
938
956
|
|
|
939
957
|
// Tear down any previous poller first, so only one is ever controlling
|
|
940
958
|
// window.IALendingIntervals.tokenPoller at a time.
|
|
@@ -946,6 +964,7 @@ export default class IABookActions extends LitElement {
|
|
|
946
964
|
errorCallback,
|
|
947
965
|
pollerDelay: this.tokenDelay, // in seconds
|
|
948
966
|
skipInitialCall,
|
|
967
|
+
onTokenRefreshed,
|
|
949
968
|
});
|
|
950
969
|
}
|
|
951
970
|
|
|
@@ -1130,6 +1149,10 @@ export default class IABookActions extends LitElement {
|
|
|
1130
1149
|
justify-content: center;
|
|
1131
1150
|
flex-wrap: wrap;
|
|
1132
1151
|
}
|
|
1152
|
+
|
|
1153
|
+
#action-bar-modal {
|
|
1154
|
+
--modalWidth: 36rem;
|
|
1155
|
+
}
|
|
1133
1156
|
`;
|
|
1134
1157
|
}
|
|
1135
1158
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { expect } from '@open-wc/testing';
|
|
1
|
+
import { expect, aTimeout } from '@open-wc/testing';
|
|
2
2
|
import Sinon from 'sinon';
|
|
3
3
|
|
|
4
4
|
import { LoanTokenPoller } from '../../../src/core/services/loan-token-poller.js';
|
|
@@ -152,3 +152,45 @@ describe('skipInitialCall option', () => {
|
|
|
152
152
|
poller.disconnectedCallback();
|
|
153
153
|
});
|
|
154
154
|
});
|
|
155
|
+
|
|
156
|
+
describe('onTokenRefreshed option', () => {
|
|
157
|
+
// BookReader has no self-healing for a page <img> that failed while
|
|
158
|
+
// access was briefly invalid, so the consumer needs a signal on EVERY
|
|
159
|
+
// create_token success (not just the initial one) to know it's safe to
|
|
160
|
+
// retry those images.
|
|
161
|
+
it('fires on the initial create_token success', async () => {
|
|
162
|
+
const onTokenRefreshed = Sinon.spy();
|
|
163
|
+
const poller = new LoanTokenPoller({
|
|
164
|
+
identifier: 'foo',
|
|
165
|
+
borrowType: 'browsed',
|
|
166
|
+
successCallback: () => {},
|
|
167
|
+
errorCallback: () => {},
|
|
168
|
+
pollerDelay: 120,
|
|
169
|
+
onTokenRefreshed,
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
await aTimeout(50);
|
|
173
|
+
|
|
174
|
+
expect(onTokenRefreshed.called).to.be.true;
|
|
175
|
+
poller.disconnectedCallback();
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it('fires on a routine (non-initial) create_token success too', async () => {
|
|
179
|
+
const onTokenRefreshed = Sinon.spy();
|
|
180
|
+
const poller = new LoanTokenPoller({
|
|
181
|
+
identifier: 'foo',
|
|
182
|
+
borrowType: 'browsed',
|
|
183
|
+
successCallback: () => {},
|
|
184
|
+
errorCallback: () => {},
|
|
185
|
+
pollerDelay: 120,
|
|
186
|
+
onTokenRefreshed,
|
|
187
|
+
});
|
|
188
|
+
onTokenRefreshed.resetHistory();
|
|
189
|
+
|
|
190
|
+
await poller.handleLoanTokenPoller(false);
|
|
191
|
+
await aTimeout(50);
|
|
192
|
+
|
|
193
|
+
expect(onTokenRefreshed.called).to.be.true;
|
|
194
|
+
poller.disconnectedCallback();
|
|
195
|
+
});
|
|
196
|
+
});
|
|
@@ -958,6 +958,7 @@ describe('autoRenewExpiredLoan', () => {
|
|
|
958
958
|
);
|
|
959
959
|
await el.updateComplete;
|
|
960
960
|
el.postInitComplete = true;
|
|
961
|
+
el.reloadPageImages = Sinon.spy();
|
|
961
962
|
|
|
962
963
|
await el.localCache.set({
|
|
963
964
|
key: 'foobar-loanTime',
|
|
@@ -985,6 +986,9 @@ describe('autoRenewExpiredLoan', () => {
|
|
|
985
986
|
await el.updateComplete;
|
|
986
987
|
|
|
987
988
|
expect(startTokenPollerSpy.calledOnceWith(true)).to.be.true;
|
|
989
|
+
// Retried right away rather than waiting for the (now-skipped) initial
|
|
990
|
+
// create_token or the next routine tick.
|
|
991
|
+
expect(el.reloadPageImages.called).to.be.true;
|
|
988
992
|
});
|
|
989
993
|
|
|
990
994
|
it('calls lendingBarPostInit directly on a recovery renewal and skips the initial create_token', async () => {
|
|
@@ -1006,6 +1010,7 @@ describe('autoRenewExpiredLoan', () => {
|
|
|
1006
1010
|
);
|
|
1007
1011
|
await el.updateComplete;
|
|
1008
1012
|
el.lendingBarPostInit = Sinon.spy();
|
|
1013
|
+
el.reloadPageImages = Sinon.spy();
|
|
1009
1014
|
|
|
1010
1015
|
await el.localCache.set({
|
|
1011
1016
|
key: 'foobar-loanTime',
|
|
@@ -1030,6 +1035,7 @@ describe('autoRenewExpiredLoan', () => {
|
|
|
1030
1035
|
// create_token success callback.
|
|
1031
1036
|
expect(el.lendingBarPostInit.calledOnce).to.be.true;
|
|
1032
1037
|
expect(el.postInitComplete).to.be.true;
|
|
1038
|
+
expect(el.reloadPageImages.called).to.be.true;
|
|
1033
1039
|
|
|
1034
1040
|
await el.updateComplete;
|
|
1035
1041
|
await aTimeout(150); // let the 100ms token-poller-restart check run
|