react-native-toast-hybrid
Version:
A toast that can be used for react-native, while available for native android, ios.
135 lines (134 loc) • 3.87 kB
JavaScript
import { useRef, useEffect } from 'react';
import { BackHandler } from 'react-native';
import ToastHybrid from './NativeToast';
let defaultDuration = 2000;
export default class Toast {
static instances = new Set();
static config(options = {}) {
defaultDuration = options.duration || defaultDuration;
ToastHybrid.config(options);
}
static text(text, duration = defaultDuration) {
new Toast().text(text, duration);
}
static info(text, duration = defaultDuration) {
new Toast().info(text, duration);
}
static done(text, duration = defaultDuration) {
new Toast().done(text, duration);
}
static error(text, duration = defaultDuration) {
new Toast().error(text, duration);
}
static loading(text) {
return new Toast().loading(text);
}
static hideAll() {
Array.from(Toast.instances).forEach(t => t.hide());
}
underlying = null;
constructor() {
Toast.instances.add(this);
}
ensure() {
if (this.underlying !== null) {
return this.underlying;
}
const underlying = ToastHybrid.createToast();
return underlying;
}
closed = false;
timer = null;
loading(text) {
if (!this.closed) {
this.clearTimeout();
this.underlying = this.ensure();
this.underlying.then(key => {
this.clearTimeout();
ToastHybrid.loading(key, text);
});
}
return this;
}
clearTimeout() {
if (this.timer !== null) {
clearTimeout(this.timer);
this.timer = null;
}
}
text(text, duration = defaultDuration) {
return this.show(ToastHybrid.text, text, duration);
}
show(fn, text, duration) {
if (duration === 0) {
if (this.underlying === null) {
return this;
}
this.hide();
return this;
}
if (!this.closed) {
this.clearTimeout();
this.underlying = this.ensure();
this.underlying.then(key => {
if (!this.closed) {
fn(key, text);
this.clearTimeout();
this.timer = setTimeout(() => this.hide(), duration);
}
else {
this.hide();
}
});
}
return this;
}
info(text, duration = defaultDuration) {
return this.show(ToastHybrid.info, text, duration);
}
done(text, duration = defaultDuration) {
return this.show(ToastHybrid.done, text, duration);
}
error(text, duration = defaultDuration) {
return this.show(ToastHybrid.error, text, duration);
}
hide() {
Toast.instances.delete(this);
this.clearTimeout();
if (this.underlying !== null) {
this.underlying.then(key => {
ToastHybrid.hide(key);
});
this.underlying = null;
}
}
shutdown() {
this.closed = true;
this.hide();
}
}
export function useToast() {
const toastRef = useRef(new Toast());
useEffect(() => {
const toast = toastRef.current;
toast.closed = false;
return () => {
toast.shutdown();
};
}, []);
useEffect(() => {
function handleHardwareBack() {
const toast = toastRef.current;
if (toast.underlying !== null) {
toast.hide();
return true;
}
return false;
}
const subscription = BackHandler.addEventListener('hardwareBackPress', handleHardwareBack);
return () => {
subscription.remove();
};
}, []);
return toastRef.current;
}