summaryrefslogtreecommitdiffhomepage
path: root/gui/src/renderer
diff options
context:
space:
mode:
authorOskar Nyberg <oskar@mullvad.net>2021-06-29 14:49:13 +0200
committerOskar Nyberg <oskar@mullvad.net>2021-07-01 11:37:48 +0200
commite6d83cc9fe4b8e951403bc3ee6d0744934b041ee (patch)
tree29a4738c20ce56e2f29855111a235a251807e96c /gui/src/renderer
parentd962e59af7ebe3980686324d430ff1854a832445 (diff)
downloadmullvadvpn-e6d83cc9fe4b8e951403bc3ee6d0744934b041ee.tar.xz
mullvadvpn-e6d83cc9fe4b8e951403bc3ee6d0744934b041ee.zip
Replace history methods with new ones more aligned with our needs
Diffstat (limited to 'gui/src/renderer')
-rw-r--r--gui/src/renderer/lib/history.ts147
1 files changed, 96 insertions, 51 deletions
diff --git a/gui/src/renderer/lib/history.ts b/gui/src/renderer/lib/history.ts
index 3f98508ce1..c3a06b98e3 100644
--- a/gui/src/renderer/lib/history.ts
+++ b/gui/src/renderer/lib/history.ts
@@ -1,9 +1,44 @@
import { Location, Action, LocationDescriptor } from 'history';
+export interface ITransitionSpecification {
+ name: string;
+ duration: number;
+}
+
+interface ITransitionMap {
+ [name: string]: ITransitionSpecification;
+}
+
+/**
+ * Transition descriptors
+ */
+export const transitions: ITransitionMap = {
+ show: {
+ name: 'slide-up',
+ duration: 450,
+ },
+ dismiss: {
+ name: 'slide-down',
+ duration: 450,
+ },
+ push: {
+ name: 'push',
+ duration: 450,
+ },
+ pop: {
+ name: 'pop',
+ duration: 450,
+ },
+ none: {
+ name: '',
+ duration: 0,
+ },
+};
+
type LocationListener<S = unknown> = (
location: Location<S>,
action: Action,
- entries: Location<S>[],
+ transition: ITransitionSpecification,
) => void;
// It currently isn't possible to implement this correctly with support for a generic state. State
@@ -33,80 +68,90 @@ export default class History {
}
public push = (nextLocation: LocationDescriptor<S>, nextState?: S) => {
- const affectedEntries = [this.entries[this.index]];
- const location = this.createLocation(nextLocation, nextState);
- this.lastAction = 'PUSH';
- this.index += 1;
- this.entries.splice(this.index, this.entries.length - this.index, location);
- this.notify(affectedEntries);
- };
-
- public replace = (nextLocation: LocationDescriptor<S>, nextState?: S) => {
- const affectedEntries = [this.entries[this.index]];
- this.entries[this.index] = this.createLocation(nextLocation, nextState);
- this.lastAction = 'REPLACE';
- this.notify(affectedEntries);
+ this.pushImpl(nextLocation, nextState);
+ this.notify(transitions.push);
};
- public go = (n: number) => {
- if (this.canGo(n)) {
- const nextIndex = this.index + n;
- const affectedEntries =
- this.index < nextIndex
- ? this.entries.slice(this.index, nextIndex)
- : this.entries.slice(nextIndex + 1, this.index + 1);
-
- this.index = nextIndex;
- this.lastAction = 'POP';
- this.notify(affectedEntries);
+ public pop = () => {
+ if (this.popImpl()) {
+ this.notify(transitions.pop);
}
};
- public goBack = () => this.go(-1);
- public goForward = () => this.go(1);
+ public show = (nextLocation: LocationDescriptor<S>, nextState?: S) => {
+ this.pushImpl(nextLocation, nextState);
+ this.notify(transitions.show);
+ };
- public reset = () => {
- const affectedEntries = this.entries.slice(1);
- this.lastAction = 'POP';
- this.index = 0;
- this.notify(affectedEntries);
+ public dismiss = (all?: boolean) => {
+ if (this.popImpl(all ? this.index : 1)) {
+ this.notify(transitions.dismiss);
+ }
};
- public resetWith = (nextLocation: LocationDescriptor<S>, nextState?: S) => {
- const affectedEntries = [...this.entries];
- this.entries = [this.createLocation(nextLocation, nextState)];
+ public reset = (
+ nextLocation: LocationDescriptor<S>,
+ transition?: ITransitionSpecification,
+ nextState?: S,
+ ) => {
+ const location = this.createLocation(nextLocation, nextState);
this.lastAction = 'REPLACE';
this.index = 0;
- this.notify(affectedEntries);
- };
+ this.entries = [location];
- public resetWithIfDifferent = (nextLocation: LocationDescriptor<S>, nextState?: S) => {
- const location = this.createLocation(nextLocation, nextState);
- if (this.entries[0].pathname !== location.pathname) {
- this.resetWith(nextLocation, nextState);
- }
+ this.notify(transition ?? transitions.none);
};
+ public listen(callback: LocationListener<S>) {
+ this.listeners.push(callback);
+ return () => (this.listeners = this.listeners.filter((listener) => listener !== callback));
+ }
+
public canGo(n: number) {
const nextIndex = this.index + n;
return nextIndex >= 0 && nextIndex < this.entries.length;
}
- public listen(callback: LocationListener<S>) {
- this.listeners.push(callback);
- return () => (this.listeners = this.listeners.filter((listener) => listener !== callback));
+ public block(): never {
+ throw Error('Not implemented');
}
-
- public block(): () => void {
+ public replace(): never {
throw Error('Not implemented');
}
-
- public createHref(): string {
+ public go(): never {
+ throw Error('Not implemented');
+ }
+ public goBack(): never {
+ throw Error('Not implemented');
+ }
+ public goForward(): never {
+ throw Error('Not implemented');
+ }
+ public createHref(): never {
throw Error('Not implemented');
}
- private notify(affectedEntries: Location<S>[]) {
- this.listeners.forEach((listener) => listener(this.location, this.action, affectedEntries));
+ private pushImpl(nextLocation: LocationDescriptor<S>, nextState?: S) {
+ const location = this.createLocation(nextLocation, nextState);
+ this.lastAction = 'PUSH';
+ this.index += 1;
+ this.entries.splice(this.index, this.entries.length - this.index, location);
+ }
+
+ private popImpl(n = 1): boolean {
+ if (this.canGo(-n)) {
+ this.lastAction = 'POP';
+ this.index -= n;
+ this.entries = this.entries.slice(0, this.index + 1);
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private notify(transition: ITransitionSpecification) {
+ this.listeners.forEach((listener) => listener(this.location, this.action, transition));
}
private createLocation(location: LocationDescriptor<S>, state?: S): Location<S> {