Skip to content
This repository has been archived by the owner on Jul 19, 2023. It is now read-only.

Offline improvements #64

Merged
merged 9 commits into from
Apr 28, 2017
2 changes: 1 addition & 1 deletion examples/twenty/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
var bookCacheUrl = new URL("appcache.html", window.location.href);

var store = new LocalStorageStore.default(webpubManifestUrl.href);
var cacher = new ServiceWorkerCacher.default(store, webpubManifestUrl, "../../sw.js", bookCacheUrl);
var cacher = new ServiceWorkerCacher.default(store, webpubManifestUrl, "../sw.js", bookCacheUrl);

var paginator = new ColumnsPaginatedBookView.default();
var scroller = new ScrollingBookView.default();
Expand Down
27 changes: 19 additions & 8 deletions src/ApplicationCacheCacher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export default class ApplicationCacheCacher implements Cacher {
private readonly bookCacheUrl: URL;
protected bookCacheElement: HTMLIFrameElement;
private statusUpdateCallback: (status: CacheStatus) => void = () => {};
private status: CacheStatus = CacheStatus.Uncached;

public constructor(bookCacheUrl: URL) {
this.bookCacheUrl = bookCacheUrl;
Expand All @@ -32,16 +33,20 @@ export default class ApplicationCacheCacher implements Cacher {
this.updateStatus();

this.bookCacheElement.addEventListener("load", () => {
this.updateStatus();
try {
this.updateStatus();

const bookCache = this.bookCacheElement.contentWindow.applicationCache;
const bookCache = this.bookCacheElement.contentWindow.applicationCache;

bookCache.oncached = this.updateStatus.bind(this);
bookCache.onchecking = this.updateStatus.bind(this);
bookCache.ondownloading = this.updateStatus.bind(this);
bookCache.onerror = this.handleError.bind(this);
bookCache.onnoupdate = this.updateStatus.bind(this);
bookCache.onupdateready = this.updateStatus.bind(this);
bookCache.oncached = this.updateStatus.bind(this);
bookCache.onchecking = this.updateStatus.bind(this);
bookCache.ondownloading = this.updateStatus.bind(this);
bookCache.onerror = this.handleError.bind(this);
bookCache.onnoupdate = this.updateStatus.bind(this);
bookCache.onupdateready = this.updateStatus.bind(this);
} catch (err) {
this.handleError();
}
});

return new Promise<void>(resolve => resolve());
Expand All @@ -52,6 +57,10 @@ export default class ApplicationCacheCacher implements Cacher {
this.updateStatus();
}

public getStatus(): CacheStatus {
return this.status;
}

protected updateStatus() {
let status: CacheStatus;
let appCacheStatus = window.applicationCache.UNCACHED;
Expand All @@ -77,10 +86,12 @@ export default class ApplicationCacheCacher implements Cacher {
status = CacheStatus.Downloaded;
}

this.status = status;
this.statusUpdateCallback(status);
}

protected handleError() {
this.status = CacheStatus.Error;
this.statusUpdateCallback(CacheStatus.Error);
}
}
60 changes: 0 additions & 60 deletions src/BookSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ const optionTemplate = (liClassName: string, buttonClassName: string, label: str
const offlineTemplate = `
<li>
<div class='offline-status'></div>
<button class='enable-offline' href='#'>Read offline</button>
</li>
`;

Expand All @@ -37,33 +36,23 @@ const increaseSvg = `<svg xmlns="http://www.w3.org/2000/svg" width="60" height="
</svg>
`;

export enum OfflineStatus {
Enabled,
Disabled,
NoSelection
};

export default class BookSettings {
private readonly store: Store;
private readonly bookViews: BookView[];
private viewButtons: { [key: string]: HTMLButtonElement };
private readonly fontSizes: string[];
private fontSizeButtons: { [key: string]: HTMLButtonElement };
private fontSizeLabel: HTMLLIElement;
private offlineButton: HTMLButtonElement;
private offlineStatusElement: HTMLElement;

private viewChangeCallback: () => void = () => {};
private fontSizeChangeCallback: () => void = () => {};
private offlineEnabledCallback: () => void = () => {};

private selectedView: BookView;
private selectedFontSize: string;
private offlineStatus: OfflineStatus = OfflineStatus.NoSelection;

private static readonly SELECTED_VIEW_KEY = "settings-selected-view";
private static readonly SELECTED_FONT_SIZE_KEY = "settings-selected-font-size";
private static readonly OFFLINE_ENABLED_KEY = "settings-offline-enabled";

/** @param store Store to save the user's selections in. */
/** @param bookViews Array of BookView options. */
Expand Down Expand Up @@ -113,13 +102,6 @@ export default class BookSettings {
}
this.selectedFontSize = selectedFontSize;
}

const offlineEnabled = await this.store.get(BookSettings.OFFLINE_ENABLED_KEY);
if (offlineEnabled === "true") {
this.offlineStatus = OfflineStatus.Enabled;
} else if (offlineEnabled === "false") {
this.offlineStatus = OfflineStatus.Disabled;
}
}

public renderControls(element: HTMLElement): void {
Expand Down Expand Up @@ -156,9 +138,7 @@ export default class BookSettings {
this.updateFontSizeButtons();
}

this.offlineButton = HTMLUtilities.findRequiredElement(element, 'button[class="enable-offline"]') as HTMLButtonElement;
this.offlineStatusElement = HTMLUtilities.findRequiredElement(element, 'div[class="offline-status"]') as HTMLElement;
this.updateOfflineButton();

this.setupEvents();

Expand All @@ -176,10 +156,6 @@ export default class BookSettings {
this.fontSizeChangeCallback = callback;
}

public onOfflineEnabled(callback: () => void) {
this.offlineEnabledCallback = callback;
}

private setupEvents(): void {
for (const view of this.bookViews) {
const button = this.viewButtons[view.name];
Expand Down Expand Up @@ -222,14 +198,6 @@ export default class BookSettings {
event.preventDefault();
});
}

this.offlineButton.addEventListener("click", (event: MouseEvent) => {
this.offlineStatus = OfflineStatus.Enabled;
this.offlineEnabledCallback();
this.updateOfflineButton();
this.storeOfflineEnabled(true);
event.preventDefault();
});
}

private updateViewButtons(): void {
Expand Down Expand Up @@ -260,14 +228,6 @@ export default class BookSettings {
this.fontSizeLabel.style.fontSize = this.selectedFontSize;
}

private updateOfflineButton(): void {
if (this.getOfflineStatus() === OfflineStatus.Enabled) {
this.offlineButton.style.display = "none";
} else {
this.offlineButton.style.display = "block";
}
}

public getSelectedView(): BookView {
return this.selectedView;
}
Expand All @@ -276,22 +236,6 @@ export default class BookSettings {
return this.selectedFontSize;
}

public getOfflineStatus(): OfflineStatus {
return this.offlineStatus;
}

public async askUserToEnableOfflineUse(): Promise<void> {
const enable = window.confirm("Would you like to download this book to read offline?");
if (enable) {
this.offlineStatus = OfflineStatus.Enabled;
this.offlineEnabledCallback();
} else {
this.offlineStatus = OfflineStatus.Disabled;
}
this.updateOfflineButton();
await this.storeOfflineEnabled(enable);
}

public getOfflineStatusElement(): HTMLElement {
return this.offlineStatusElement;
}
Expand All @@ -303,8 +247,4 @@ export default class BookSettings {
private async storeSelectedFontSize(fontSize: string): Promise<void> {
return this.store.set(BookSettings.SELECTED_FONT_SIZE_KEY, fontSize);
}

private async storeOfflineEnabled(offlineEnabled: boolean): Promise<void> {
return this.store.set(BookSettings.OFFLINE_ENABLED_KEY, offlineEnabled ? "true" : "false");
}
};
3 changes: 3 additions & 0 deletions src/Cacher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ interface Cacher {

// Register a function to call when the cache status changes.
onStatusUpdate(callback: (status: CacheStatus) => void): void;

// Return the current CacheStatus.
getStatus(): CacheStatus;
}

export default Cacher;
Loading