Skip to content

Instantly share code, notes, and snippets.

@NathanWalker
Last active February 23, 2021 18:43
Show Gist options
  • Save NathanWalker/0ecbe1158058c48cf96dcfe2fa7e4520 to your computer and use it in GitHub Desktop.
Save NathanWalker/0ecbe1158058c48cf96dcfe2fa7e4520 to your computer and use it in GitHub Desktop.
Simple offline handling with NativeScript using Angular as example
// pseudo code using angular flavor as example
@Injectable({ providedIn: 'root' })
export class SomeHttpInterceptor implements HttpInterceptor {
_mobileOffline = new MobileOffline();
constructor(private mobileStorage: MobileAPIStorageService) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (!this._mobileOffline.isOnline) {
// Offline
// cached responses only
return this.mobileStorage
.getItem(cacheKey)
.pipe(
take(1),
map((res) => {
return new HttpResponse({
body: res,
status: 200,
url: req.url,
});
})
);
} else {
return next.handle(req).pipe(
tap((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
if (req.method && req.method.toLowerCase() === 'get') {
// cache all get requests for right now
// NOTE: you can provide your own configurations around this
this.mobileStorage.setItem(this._getRequestCacheKey(req), event.body);
}
}
}),
catchError((err: any) => {
console.log('catch http error:', err);
return throwError(err);
})
);
}
}
private _getRequestCacheKey(req: HttpRequest<any>) {
return `${req.method}-${req.urlWithParams}`;
}
}
import { Injectable } from '@angular/core';
import { ApplicationSettings } from '@nativescript/core';
@Injectable({ providedIn: 'root' })
export class MobileAPIStorageService {
public setItem(key: string, data: any): void {
if (typeof data === 'undefined') {
data = null;
} else {
data = JSON.stringify(data);
}
ApplicationSettings.setString(key, data);
}
public getItem(key: string, _default = null): Observable<any> {
const item = ApplicationSettings.getString(key);
if (!item || item === 'null') {
return from(Promise.resolve(_default));
}
try {
return from(Promise.resolve(JSON.parse(item)));
} catch (e) {
return from(Promise.resolve(_default));
}
}
public removeItem(key: string): void {
ApplicationSettings.remove(key);
}
public clearAll(): void {
ApplicationSettings.clear();
}
}
import { Connectivity } from '@nativescript/core';
export class MobileOffline {
isOnline = true;
constructor() {
this._init();
}
private _init() {
// IMPORTANT: This works inconsistently between Simulator and real device
// * Simulator: will fire when going Offline, but never again when user comes back online
// * real device: will fire properly in both cases so don't worry about the simulator case
Connectivity.startMonitoring((networkType) => {
let isOnline = false;
switch (networkType) {
case Connectivity.connectionType.none:
// no connection
isOnline = false;
break;
case Connectivity.connectionType.wifi:
case Connectivity.connectionType.mobile:
// wifi or cellular data
isOnline = true;
break;
default:
// assume offline in unknown cases
isOnline = false;
break;
}
console.log(`monitoring connectivity, connectionType: ${networkType}, isOnline: ${isOnline}`);
// if first time going offline, show notice
if (this.isOnline && !isOnline) {
// show offline notice here only once, the first time user goes from online > offline
// toast message or whatever
}
this.isOnline = isOnline;
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment