-
Notifications
You must be signed in to change notification settings - Fork 415
/
navigator.ts
121 lines (95 loc) · 3.24 KB
/
navigator.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import { FetchMethod } from "../../http/fetch_request"
import { FetchResponse } from "../../http/fetch_response"
import { FormSubmission } from "./form_submission"
import { Locatable, Location } from "../location"
import { Visit, VisitDelegate, VisitOptions } from "./visit"
export type NavigatorDelegate = VisitDelegate & {
allowsVisitingLocation(location: Location): boolean
visitProposedToLocation(location: Location, options: Partial<VisitOptions>): void
}
export class Navigator {
readonly delegate: NavigatorDelegate
formSubmission?: FormSubmission
currentVisit?: Visit
constructor(delegate: NavigatorDelegate) {
this.delegate = delegate
}
proposeVisit(location: Location, options: Partial<VisitOptions> = {}) {
if (this.delegate.allowsVisitingLocation(location)) {
this.delegate.visitProposedToLocation(location, options)
}
}
startVisit(location: Locatable, restorationIdentifier: string, options: Partial<VisitOptions> = {}) {
this.stop()
this.currentVisit = new Visit(this, Location.wrap(location), restorationIdentifier, {
referrer: this.location,
...options
})
this.currentVisit.start()
}
submitForm(form: HTMLFormElement, submitter?: HTMLElement) {
this.stop()
this.formSubmission = new FormSubmission(this, form, submitter, true)
this.formSubmission.start()
}
stop() {
if (this.formSubmission) {
this.formSubmission.stop()
delete this.formSubmission
}
if (this.currentVisit) {
this.currentVisit.cancel()
delete this.currentVisit
}
}
get adapter() {
return this.delegate.adapter
}
get view() {
return this.delegate.view
}
get history() {
return this.delegate.history
}
// Form submission delegate
formSubmissionStarted(formSubmission: FormSubmission) {
}
async formSubmissionSucceededWithResponse(formSubmission: FormSubmission, fetchResponse: FetchResponse) {
console.log("Form submission succeeded", formSubmission)
if (formSubmission == this.formSubmission) {
const responseHTML = await fetchResponse.responseHTML
if (responseHTML) {
if (formSubmission.method != FetchMethod.get) {
console.log("Clearing snapshot cache after successful form submission")
this.view.clearSnapshotCache()
}
const { statusCode } = fetchResponse
const visitOptions = { response: { statusCode, responseHTML } }
console.log("Visiting", fetchResponse.location, visitOptions)
this.proposeVisit(fetchResponse.location, visitOptions)
}
}
}
formSubmissionFailedWithResponse(formSubmission: FormSubmission, fetchResponse: FetchResponse) {
console.error("Form submission failed", formSubmission, fetchResponse)
}
formSubmissionErrored(formSubmission: FormSubmission, error: Error) {
console.error("Form submission failed", formSubmission, error)
}
formSubmissionFinished(formSubmission: FormSubmission) {
}
// Visit delegate
visitStarted(visit: Visit) {
this.delegate.visitStarted(visit)
}
visitCompleted(visit: Visit) {
this.delegate.visitCompleted(visit)
}
// Visits
get location() {
return this.history.location
}
get restorationIdentifier() {
return this.history.restorationIdentifier
}
}