@netless/app-presentation 0.1.2 → 0.1.3

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/dist/index.d.ts CHANGED
@@ -195,17 +195,32 @@ interface ILazyLoadInstance {
195
195
  toLoadCount: number;
196
196
  }
197
197
 
198
+ declare enum ELoadState {
199
+ unloaded = 0,
200
+ loading = 1,
201
+ loaded = 2,
202
+ error = 3
203
+ }
204
+ interface IPreloadMapValue {
205
+ src: string;
206
+ state: ELoadState;
207
+ }
198
208
  declare class Preload implements IDisposable {
199
209
  readonly pages: PresentationPage[];
200
- readonly links: HTMLLinkElement[];
201
- head: number;
202
- tail: number;
203
- timer: number;
204
- count: number;
205
- get done(): boolean;
210
+ static maxLinks: number;
211
+ readonly loadingLinks: Map<number, HTMLLinkElement>;
212
+ readonly preloadMap: Map<number, IPreloadMapValue>;
213
+ readonly waitingLoadSet: Set<number>;
214
+ readonly waitinglinks: number[];
215
+ touchIndex: number;
216
+ preloadSize: number;
206
217
  constructor(pages: PresentationPage[]);
207
- touch(index: number): void;
208
- handler(): void;
218
+ touch(index: number): Promise<ELoadState>;
219
+ private autoTouch;
220
+ private createLink;
221
+ private handler;
222
+ private requestAsyncCallBack;
223
+ private destroyLink;
209
224
  dispose(): void;
210
225
  }
211
226
 
@@ -272,6 +287,7 @@ declare class Presentation implements IDisposable<void> {
272
287
  showPreview: boolean;
273
288
  pageIndex: number;
274
289
  previewLazyload: ILazyLoadInstance | null;
290
+ timer: number | null;
275
291
  constructor(config: PresentationConfig);
276
292
  initialize(): void;
277
293
  setDOM(dom: Element | DocumentFragment): void;
@@ -790,66 +790,161 @@ var NetlessAppPresentation = (function (exports) {
790
790
  }
791
791
 
792
792
  // src/preload.ts
793
- var Preload = class {
793
+ var _Preload = class _Preload {
794
794
  constructor(pages) {
795
795
  this.pages = pages;
796
- this.head = 0;
797
- this.tail = 0;
798
- this.timer = 0;
799
- this.count = 0;
800
- this.links = new Array(pages.length);
796
+ this.loadingLinks = /* @__PURE__ */ new Map();
797
+ this.preloadMap = /* @__PURE__ */ new Map();
798
+ this.waitingLoadSet = /* @__PURE__ */ new Set();
799
+ this.waitinglinks = [];
800
+ this.touchIndex = 0;
801
+ this.preloadSize = 0;
802
+ this.preloadMap = new Map(pages.map((e, index) => [index, {
803
+ src: e.src,
804
+ state: 0 /* unloaded */
805
+ }]));
806
+ this.waitingLoadSet = new Set(pages.map((e, index) => index));
807
+ this.preloadSize = this.preloadMap.size;
801
808
  this.touch(0);
802
809
  }
803
- get done() {
804
- return this.head == 0 && this.tail == this.pages.length;
810
+ async touch(index) {
811
+ this.touchIndex = index;
812
+ const value = this.preloadMap.get(index);
813
+ let state = 0 /* unloaded */;
814
+ if (value) {
815
+ state = value.state;
816
+ if (value.state === 0 /* unloaded */) {
817
+ if (this.loadingLinks.size) {
818
+ for (const [i, link] of this.loadingLinks) {
819
+ this.destroyLink(i, link);
820
+ this.waitingLoadSet.add(i);
821
+ const v = this.preloadMap.get(i);
822
+ if (v) {
823
+ v.state = 0 /* unloaded */;
824
+ this.preloadMap.set(i, v);
825
+ }
826
+ }
827
+ for (const i of this.waitinglinks) {
828
+ this.waitingLoadSet.add(i);
829
+ }
830
+ this.waitinglinks.length = 0;
831
+ }
832
+ if (this.waitinglinks.includes(index)) {
833
+ this.waitinglinks.splice(this.waitinglinks.indexOf(index), 1);
834
+ }
835
+ state = await new Promise((resolve) => {
836
+ this.waitingLoadSet.delete(index);
837
+ this.createLink(index, resolve);
838
+ });
839
+ }
840
+ }
841
+ if (this.waitingLoadSet.size) {
842
+ this.requestAsyncCallBack(() => {
843
+ this.autoTouch();
844
+ }, 1e3);
845
+ }
846
+ return state;
805
847
  }
806
- touch(index) {
807
- if (this.done)
848
+ autoTouch() {
849
+ this.handler();
850
+ if (this.waitingLoadSet.size === 0) {
808
851
  return;
809
- this.head = this.tail = index;
810
- this.timer || (this.timer = setTimeout(this.handler.bind(this)));
852
+ }
853
+ let nextTouchDelay = 1e3;
854
+ this.touchIndex = (this.touchIndex + 1) % this.preloadSize;
855
+ const value = this.preloadMap.get(this.touchIndex);
856
+ if (value) {
857
+ switch (value.state) {
858
+ case 0 /* unloaded */:
859
+ case 3 /* error */:
860
+ if (!this.waitinglinks.includes(this.touchIndex)) {
861
+ this.waitinglinks.push(this.touchIndex);
862
+ this.waitingLoadSet.delete(this.touchIndex);
863
+ }
864
+ nextTouchDelay = 0;
865
+ break;
866
+ }
867
+ }
868
+ this.requestAsyncCallBack(() => {
869
+ this.autoTouch();
870
+ }, nextTouchDelay);
811
871
  }
812
- handler() {
813
- const { links } = this;
814
- while (this.head > 0 && links[this.head])
815
- this.head--;
816
- if (!links[this.head]) {
872
+ createLink(index, resolve) {
873
+ const value = this.preloadMap.get(index);
874
+ if (value) {
817
875
  const link = document.createElement("link");
818
- links[this.head] = link;
819
876
  link.rel = "preload";
820
877
  link.as = "image";
821
- link.href = this.pages[this.head].src;
822
- link.dataset.order = this.count + "";
878
+ link.href = value.src;
879
+ link.dataset.order = index + "";
823
880
  document.head.appendChild(link);
824
- this.count++;
881
+ link.onload = () => {
882
+ value.state = 2 /* loaded */;
883
+ this.preloadMap.set(index, value);
884
+ document.head.contains(link) && document.head.removeChild(link);
885
+ this.loadingLinks.delete(index);
886
+ resolve && resolve(2 /* loaded */);
887
+ this.autoTouch();
888
+ };
889
+ link.onerror = () => {
890
+ value.state = 3 /* error */;
891
+ this.preloadMap.set(index, value);
892
+ if (!this.waitinglinks.includes(index)) {
893
+ this.waitinglinks.push(index);
894
+ this.waitingLoadSet.delete(this.touchIndex);
895
+ }
896
+ document.head.contains(link) && document.head.removeChild(link);
897
+ this.loadingLinks.delete(index);
898
+ resolve && resolve(3 /* error */);
899
+ this.autoTouch();
900
+ };
901
+ this.loadingLinks.set(index, link);
902
+ value.state = 1 /* loading */;
903
+ this.preloadMap.set(index, value);
825
904
  }
826
- while (links[this.tail])
827
- this.tail++;
828
- if (this.tail < this.pages.length && !links[this.tail]) {
829
- const link = document.createElement("link");
830
- links[this.tail] = link;
831
- link.rel = "preload";
832
- link.as = "image";
833
- link.href = this.pages[this.tail].src;
834
- link.dataset.order = this.count + "";
835
- document.head.appendChild(link);
836
- this.count++;
905
+ }
906
+ handler() {
907
+ if (!this.waitinglinks.length) {
908
+ return;
837
909
  }
838
- this.timer = setTimeout(this.handler.bind(this), 2e3);
839
- this.count++;
840
- if (this.count >= 10) {
841
- for (const link of this.links)
842
- if (link && link.dataset.order && +link.dataset.order < this.count - 10)
843
- document.head.contains(link) && document.head.removeChild(link);
910
+ let i = this.loadingLinks.size;
911
+ while (i < _Preload.maxLinks) {
912
+ const index = this.waitinglinks.shift();
913
+ if (index !== void 0) {
914
+ this.createLink(index);
915
+ }
916
+ i++;
844
917
  }
845
918
  }
919
+ async requestAsyncCallBack(callBack, timeout) {
920
+ await new Promise(function(resolve) {
921
+ if (window.requestIdleCallback) {
922
+ requestIdleCallback(() => {
923
+ resolve(1);
924
+ }, { timeout });
925
+ } else {
926
+ setTimeout(() => {
927
+ resolve(2);
928
+ }, timeout);
929
+ }
930
+ });
931
+ callBack();
932
+ }
933
+ destroyLink(index, link) {
934
+ document.head.contains(link) && document.head.removeChild(link);
935
+ this.loadingLinks.delete(index);
936
+ }
846
937
  dispose() {
847
- clearTimeout(this.timer);
848
- for (const link of this.links)
849
- link && document.head.contains(link) && document.head.removeChild(link);
850
- this.links.length = 0;
938
+ for (const [index, link] of this.loadingLinks) {
939
+ this.destroyLink(index, link);
940
+ }
941
+ this.preloadMap.clear();
942
+ this.waitingLoadSet.clear();
943
+ this.waitinglinks.length = 0;
851
944
  }
852
945
  };
946
+ _Preload.maxLinks = 5;
947
+ var Preload = _Preload;
853
948
 
854
949
  // src/presentation.ts
855
950
  var Presentation = class {
@@ -860,6 +955,7 @@ var NetlessAppPresentation = (function (exports) {
860
955
  this.showPreview = false;
861
956
  this.pageIndex = 0;
862
957
  this.previewLazyload = null;
958
+ this.timer = null;
863
959
  var _a;
864
960
  this.pages = config.pages;
865
961
  this.preload = new Preload(this.pages);
@@ -1062,15 +1158,22 @@ var NetlessAppPresentation = (function (exports) {
1062
1158
  return this.pages[this.pageIndex];
1063
1159
  }
1064
1160
  updateImage() {
1065
- const page = this.page();
1066
- if (!page) {
1067
- this.image.src = "";
1068
- return;
1161
+ if (this.timer) {
1162
+ clearTimeout(this.timer);
1069
1163
  }
1070
- this.image.width = page.width;
1071
- this.image.height = page.height;
1072
- this.image.src = page.src;
1073
- this.preload.touch(this.pageIndex);
1164
+ this.timer = setTimeout(() => {
1165
+ this.timer = null;
1166
+ this.preload.touch(this.pageIndex).then(() => {
1167
+ const page = this.page();
1168
+ if (!page) {
1169
+ this.image.src = "";
1170
+ return;
1171
+ }
1172
+ this.image.width = page.width;
1173
+ this.image.height = page.height;
1174
+ this.image.src = page.src;
1175
+ });
1176
+ }, 200);
1074
1177
  }
1075
1178
  /** Returns a modified URL that points to the thumbnail image. */
1076
1179
  thumbnail(src) {
package/dist/index.js CHANGED
@@ -791,66 +791,161 @@ function arrowRightSVG(namespace) {
791
791
  }
792
792
 
793
793
  // src/preload.ts
794
- var Preload = class {
794
+ var _Preload = class _Preload {
795
795
  constructor(pages) {
796
796
  this.pages = pages;
797
- this.head = 0;
798
- this.tail = 0;
799
- this.timer = 0;
800
- this.count = 0;
801
- this.links = new Array(pages.length);
797
+ this.loadingLinks = /* @__PURE__ */ new Map();
798
+ this.preloadMap = /* @__PURE__ */ new Map();
799
+ this.waitingLoadSet = /* @__PURE__ */ new Set();
800
+ this.waitinglinks = [];
801
+ this.touchIndex = 0;
802
+ this.preloadSize = 0;
803
+ this.preloadMap = new Map(pages.map((e, index) => [index, {
804
+ src: e.src,
805
+ state: 0 /* unloaded */
806
+ }]));
807
+ this.waitingLoadSet = new Set(pages.map((e, index) => index));
808
+ this.preloadSize = this.preloadMap.size;
802
809
  this.touch(0);
803
810
  }
804
- get done() {
805
- return this.head == 0 && this.tail == this.pages.length;
811
+ async touch(index) {
812
+ this.touchIndex = index;
813
+ const value = this.preloadMap.get(index);
814
+ let state = 0 /* unloaded */;
815
+ if (value) {
816
+ state = value.state;
817
+ if (value.state === 0 /* unloaded */) {
818
+ if (this.loadingLinks.size) {
819
+ for (const [i, link] of this.loadingLinks) {
820
+ this.destroyLink(i, link);
821
+ this.waitingLoadSet.add(i);
822
+ const v = this.preloadMap.get(i);
823
+ if (v) {
824
+ v.state = 0 /* unloaded */;
825
+ this.preloadMap.set(i, v);
826
+ }
827
+ }
828
+ for (const i of this.waitinglinks) {
829
+ this.waitingLoadSet.add(i);
830
+ }
831
+ this.waitinglinks.length = 0;
832
+ }
833
+ if (this.waitinglinks.includes(index)) {
834
+ this.waitinglinks.splice(this.waitinglinks.indexOf(index), 1);
835
+ }
836
+ state = await new Promise((resolve) => {
837
+ this.waitingLoadSet.delete(index);
838
+ this.createLink(index, resolve);
839
+ });
840
+ }
841
+ }
842
+ if (this.waitingLoadSet.size) {
843
+ this.requestAsyncCallBack(() => {
844
+ this.autoTouch();
845
+ }, 1e3);
846
+ }
847
+ return state;
806
848
  }
807
- touch(index) {
808
- if (this.done)
849
+ autoTouch() {
850
+ this.handler();
851
+ if (this.waitingLoadSet.size === 0) {
809
852
  return;
810
- this.head = this.tail = index;
811
- this.timer || (this.timer = setTimeout(this.handler.bind(this)));
853
+ }
854
+ let nextTouchDelay = 1e3;
855
+ this.touchIndex = (this.touchIndex + 1) % this.preloadSize;
856
+ const value = this.preloadMap.get(this.touchIndex);
857
+ if (value) {
858
+ switch (value.state) {
859
+ case 0 /* unloaded */:
860
+ case 3 /* error */:
861
+ if (!this.waitinglinks.includes(this.touchIndex)) {
862
+ this.waitinglinks.push(this.touchIndex);
863
+ this.waitingLoadSet.delete(this.touchIndex);
864
+ }
865
+ nextTouchDelay = 0;
866
+ break;
867
+ }
868
+ }
869
+ this.requestAsyncCallBack(() => {
870
+ this.autoTouch();
871
+ }, nextTouchDelay);
812
872
  }
813
- handler() {
814
- const { links } = this;
815
- while (this.head > 0 && links[this.head])
816
- this.head--;
817
- if (!links[this.head]) {
873
+ createLink(index, resolve) {
874
+ const value = this.preloadMap.get(index);
875
+ if (value) {
818
876
  const link = document.createElement("link");
819
- links[this.head] = link;
820
877
  link.rel = "preload";
821
878
  link.as = "image";
822
- link.href = this.pages[this.head].src;
823
- link.dataset.order = this.count + "";
879
+ link.href = value.src;
880
+ link.dataset.order = index + "";
824
881
  document.head.appendChild(link);
825
- this.count++;
882
+ link.onload = () => {
883
+ value.state = 2 /* loaded */;
884
+ this.preloadMap.set(index, value);
885
+ document.head.contains(link) && document.head.removeChild(link);
886
+ this.loadingLinks.delete(index);
887
+ resolve && resolve(2 /* loaded */);
888
+ this.autoTouch();
889
+ };
890
+ link.onerror = () => {
891
+ value.state = 3 /* error */;
892
+ this.preloadMap.set(index, value);
893
+ if (!this.waitinglinks.includes(index)) {
894
+ this.waitinglinks.push(index);
895
+ this.waitingLoadSet.delete(this.touchIndex);
896
+ }
897
+ document.head.contains(link) && document.head.removeChild(link);
898
+ this.loadingLinks.delete(index);
899
+ resolve && resolve(3 /* error */);
900
+ this.autoTouch();
901
+ };
902
+ this.loadingLinks.set(index, link);
903
+ value.state = 1 /* loading */;
904
+ this.preloadMap.set(index, value);
826
905
  }
827
- while (links[this.tail])
828
- this.tail++;
829
- if (this.tail < this.pages.length && !links[this.tail]) {
830
- const link = document.createElement("link");
831
- links[this.tail] = link;
832
- link.rel = "preload";
833
- link.as = "image";
834
- link.href = this.pages[this.tail].src;
835
- link.dataset.order = this.count + "";
836
- document.head.appendChild(link);
837
- this.count++;
906
+ }
907
+ handler() {
908
+ if (!this.waitinglinks.length) {
909
+ return;
838
910
  }
839
- this.timer = setTimeout(this.handler.bind(this), 2e3);
840
- this.count++;
841
- if (this.count >= 10) {
842
- for (const link of this.links)
843
- if (link && link.dataset.order && +link.dataset.order < this.count - 10)
844
- document.head.contains(link) && document.head.removeChild(link);
911
+ let i = this.loadingLinks.size;
912
+ while (i < _Preload.maxLinks) {
913
+ const index = this.waitinglinks.shift();
914
+ if (index !== void 0) {
915
+ this.createLink(index);
916
+ }
917
+ i++;
845
918
  }
846
919
  }
920
+ async requestAsyncCallBack(callBack, timeout) {
921
+ await new Promise(function(resolve) {
922
+ if (window.requestIdleCallback) {
923
+ requestIdleCallback(() => {
924
+ resolve(1);
925
+ }, { timeout });
926
+ } else {
927
+ setTimeout(() => {
928
+ resolve(2);
929
+ }, timeout);
930
+ }
931
+ });
932
+ callBack();
933
+ }
934
+ destroyLink(index, link) {
935
+ document.head.contains(link) && document.head.removeChild(link);
936
+ this.loadingLinks.delete(index);
937
+ }
847
938
  dispose() {
848
- clearTimeout(this.timer);
849
- for (const link of this.links)
850
- link && document.head.contains(link) && document.head.removeChild(link);
851
- this.links.length = 0;
939
+ for (const [index, link] of this.loadingLinks) {
940
+ this.destroyLink(index, link);
941
+ }
942
+ this.preloadMap.clear();
943
+ this.waitingLoadSet.clear();
944
+ this.waitinglinks.length = 0;
852
945
  }
853
946
  };
947
+ _Preload.maxLinks = 5;
948
+ var Preload = _Preload;
854
949
 
855
950
  // src/presentation.ts
856
951
  var Presentation = class {
@@ -861,6 +956,7 @@ var Presentation = class {
861
956
  this.showPreview = false;
862
957
  this.pageIndex = 0;
863
958
  this.previewLazyload = null;
959
+ this.timer = null;
864
960
  var _a;
865
961
  this.pages = config.pages;
866
962
  this.preload = new Preload(this.pages);
@@ -1063,15 +1159,22 @@ var Presentation = class {
1063
1159
  return this.pages[this.pageIndex];
1064
1160
  }
1065
1161
  updateImage() {
1066
- const page = this.page();
1067
- if (!page) {
1068
- this.image.src = "";
1069
- return;
1162
+ if (this.timer) {
1163
+ clearTimeout(this.timer);
1070
1164
  }
1071
- this.image.width = page.width;
1072
- this.image.height = page.height;
1073
- this.image.src = page.src;
1074
- this.preload.touch(this.pageIndex);
1165
+ this.timer = setTimeout(() => {
1166
+ this.timer = null;
1167
+ this.preload.touch(this.pageIndex).then(() => {
1168
+ const page = this.page();
1169
+ if (!page) {
1170
+ this.image.src = "";
1171
+ return;
1172
+ }
1173
+ this.image.width = page.width;
1174
+ this.image.height = page.height;
1175
+ this.image.src = page.src;
1176
+ });
1177
+ }, 200);
1075
1178
  }
1076
1179
  /** Returns a modified URL that points to the thumbnail image. */
1077
1180
  thumbnail(src) {