Add bridge page controller and helpers.
This commit is contained in:
@@ -2,7 +2,6 @@
|
||||
import "@hotwired/turbo-rails"
|
||||
import "@hotwired/hotwire-native-bridge"
|
||||
import "initializers"
|
||||
import "bridge/initializers"
|
||||
import "controllers"
|
||||
|
||||
import "lexxy"
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
import { BridgeComponent } from "@hotwired/hotwire-native-bridge"
|
||||
import { BridgeElement } from "@hotwired/hotwire-native-bridge"
|
||||
import { viewport } from "bridge/helpers/viewport"
|
||||
import { nextFrame } from "helpers/timing_helpers"
|
||||
|
||||
export default class extends BridgeComponent {
|
||||
static component = "page"
|
||||
static targets = [ "header" ]
|
||||
static values = { title: String }
|
||||
|
||||
async connect() {
|
||||
super.connect()
|
||||
this.notifyBridgeOfPageChange()
|
||||
await nextFrame()
|
||||
this.startObserver()
|
||||
window.addEventListener("resize", this.windowResized)
|
||||
window.addEventListener("turbo:submit-start", this.submitStart)
|
||||
window.addEventListener("turbo:submit-end", this.submitEnd)
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
super.disconnect()
|
||||
this.stopObserver()
|
||||
window.removeEventListener("resize", this.windowResized)
|
||||
window.removeEventListener("turbo:submit-start", this.submitStart)
|
||||
window.removeEventListener("turbo:submit-end", this.submitEnd)
|
||||
}
|
||||
|
||||
receive(message) {
|
||||
switch (message.event) {
|
||||
case "change":
|
||||
this.updateHeaderVisibility(message.data)
|
||||
break
|
||||
case "set-text-size":
|
||||
this.setTextSize(message.data)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
setTextSize(data) {
|
||||
document.documentElement.dataset.textSize = data.textSize
|
||||
}
|
||||
|
||||
updateHeaderVisibility(data) {
|
||||
if (!this.hasHeaderTarget) return
|
||||
|
||||
const headerElement = new BridgeElement(this.headerTarget)
|
||||
|
||||
if (data.displayOnPlatform) {
|
||||
headerElement?.showOnPlatform()
|
||||
} else {
|
||||
headerElement?.hideOnPlatform()
|
||||
}
|
||||
}
|
||||
|
||||
// Bridge
|
||||
|
||||
notifyBridgeOfPageChange() {
|
||||
let headerElement = null
|
||||
const data = {
|
||||
title: this.title,
|
||||
url: window.location.href
|
||||
}
|
||||
|
||||
if (this.hasHeaderTarget) {
|
||||
// Assume header visible by default until we get IntersectionObserver update
|
||||
headerElement = new BridgeElement(this.headerTarget)
|
||||
data.elementVisible = true
|
||||
data.displayOnPlatform = headerElement.isDisplayedOnPlatform()
|
||||
}
|
||||
|
||||
this.send("change", data, message => this.receive(message))
|
||||
}
|
||||
|
||||
notifyBridgeOfVisibilityChange(visible) {
|
||||
this.send("visibility", { title: this.title, elementVisible: visible })
|
||||
}
|
||||
|
||||
notifyBridgeOfSubmitStart() {
|
||||
this.send("submitStart")
|
||||
}
|
||||
|
||||
notifyBridgeOfSubmitEnd() {
|
||||
this.send("submitEnd")
|
||||
}
|
||||
|
||||
// Intersection Observer
|
||||
|
||||
startObserver() {
|
||||
if (!this.hasHeaderTarget) return
|
||||
|
||||
this.observer = new IntersectionObserver(([ entry ]) =>
|
||||
this.notifyBridgeOfVisibilityChange(entry.isIntersecting),
|
||||
{ rootMargin: `-${this.topOffset}px 0px 0px 0px` }
|
||||
)
|
||||
|
||||
this.observer.observe(this.headerTarget)
|
||||
this.previousTopOffset = this.topOffset
|
||||
}
|
||||
|
||||
stopObserver() {
|
||||
this.observer?.disconnect()
|
||||
}
|
||||
|
||||
updateObserverIfNeeded() {
|
||||
if (this.topOffset === this.previousTopOffset) return
|
||||
|
||||
this.stopObserver()
|
||||
this.startObserver()
|
||||
}
|
||||
|
||||
windowResized = () => {
|
||||
this.updateObserverIfNeeded()
|
||||
}
|
||||
|
||||
submitStart = () => {
|
||||
this.notifyBridgeOfSubmitStart()
|
||||
}
|
||||
|
||||
submitEnd = () => {
|
||||
this.notifyBridgeOfSubmitEnd()
|
||||
}
|
||||
|
||||
get title() {
|
||||
return this.titleValue ? this.titleValue : document.title
|
||||
}
|
||||
|
||||
get topOffset() {
|
||||
return viewport.top
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
let top = 0
|
||||
|
||||
export const viewport = {
|
||||
get top() {
|
||||
return top
|
||||
},
|
||||
get height() {
|
||||
return visualViewport.height
|
||||
}
|
||||
}
|
||||
|
||||
function update() {
|
||||
requestAnimationFrame(() => {
|
||||
top = parseInt(getComputedStyle(document.documentElement).getPropertyValue("--safe-area-inset-top"))
|
||||
})
|
||||
}
|
||||
|
||||
visualViewport.addEventListener("resize", update)
|
||||
update()
|
||||
@@ -0,0 +1,13 @@
|
||||
import { BridgeElement } from "@hotwired/hotwire-native-bridge"
|
||||
|
||||
BridgeElement.prototype.isDisplayedOnPlatform = function() {
|
||||
return !this.hasClass("hide-on-native")
|
||||
}
|
||||
|
||||
BridgeElement.prototype.showOnPlatform = function() {
|
||||
this.element.classList.remove("hide-on-native")
|
||||
}
|
||||
|
||||
BridgeElement.prototype.hideOnPlatform = function() {
|
||||
this.element.classList.add("hide-on-native")
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
// Bridge initializers live here.
|
||||
import "bridge/initializers/bridge_element"
|
||||
|
||||
Reference in New Issue
Block a user