mirror of
https://github.com/docusealco/docuseal
synced 2026-11-04 14:42:32 -05:00
adjust native
This commit is contained in:
1 parent
6f31bd7af8
commit
66758d45bc
21 files changed
+379
-64
No files matched your search
@@ -1,4 +1,5 @@
|
||||
import '@hotwired/turbo-rails'
|
||||
import './elements/native_bridge'
|
||||
|
||||
import { createApp, reactive } from 'vue'
|
||||
import TemplateBuilder from './template_builder/builder'
|
||||
@@ -97,14 +98,31 @@ if (window.webkit?.messageHandlers?.native) {
|
||||
}
|
||||
})
|
||||
|
||||
document.addEventListener('turbo:before-fetch-request', (event) => {
|
||||
document.addEventListener('native:pull-to-refresh', (event) => {
|
||||
const { session } = window.Turbo
|
||||
const visit = session.navigator.currentVisit
|
||||
const limit = document.getElementById('infinite_scroll')?.dataset.limit
|
||||
const url = new URL(document.baseURI)
|
||||
|
||||
if (limit && window.scrollY > 0 && event.target === document.documentElement && visit?.location.href === session.view.lastRenderedLocation.href && session.view.isPageRefresh(visit)) {
|
||||
event.detail.url.searchParams.set('limit', limit)
|
||||
}
|
||||
url.searchParams.delete('limit')
|
||||
|
||||
session.history.replace(url, session.history.restorationIdentifier)
|
||||
session.view.lastRenderedLocation = url
|
||||
|
||||
event.detail.result = new Promise((resolve) => {
|
||||
document.addEventListener('turbo:render', () => resolve(true), { once: true })
|
||||
document.addEventListener('turbo:fetch-request-error', () => resolve(true), { once: true })
|
||||
|
||||
session.refresh(document.baseURI)
|
||||
})
|
||||
})
|
||||
|
||||
document.addEventListener('native:refresh', () => {
|
||||
window.Turbo.session.refresh(document.baseURI)
|
||||
})
|
||||
|
||||
document.addEventListener('native:turbo-stream', (e) => {
|
||||
if (!e.detail.body?.trimStart().startsWith('<turbo-stream')) return
|
||||
|
||||
window.Turbo.renderStreamMessage(e.detail.body)
|
||||
})
|
||||
|
||||
document.addEventListener('turbo:visit', (e) => {
|
||||
@@ -118,8 +136,10 @@ if (window.webkit?.messageHandlers?.native) {
|
||||
})
|
||||
}
|
||||
|
||||
document.addEventListener('turbo:before-fetch-request', (event) => {
|
||||
event.detail.fetchOptions.headers['X-Turbo'] = 'true'
|
||||
document.addEventListener('turbo:before-fetch-response', (event) => {
|
||||
if (event.detail.fetchResponse.header('content-disposition')?.includes('attachment')) {
|
||||
event.preventDefault()
|
||||
}
|
||||
})
|
||||
document.addEventListener('turbo:submit-end', async (event) => {
|
||||
const resp = event.detail?.formSubmission?.result?.fetchResponse?.response
|
||||
@@ -232,6 +252,7 @@ safeRegisterElement('template-builder', class extends HTMLElement {
|
||||
document.addEventListener('template-builder:select-submitter', this.onSelectSubmitter)
|
||||
document.addEventListener('template-builder:sync-custom-fields', this.onSyncCustomFields)
|
||||
document.addEventListener('template-builder:draw-field', this.onDrawField)
|
||||
document.addEventListener('native:builder-view', this.onBuilderView)
|
||||
document.addEventListener('turbo:before-cache', this.onBeforeCache)
|
||||
|
||||
this.appElem = document.createElement('div')
|
||||
@@ -395,6 +416,23 @@ safeRegisterElement('template-builder', class extends HTMLElement {
|
||||
}
|
||||
}
|
||||
|
||||
onBuilderView = (event) => {
|
||||
const root = document.documentElement.cloneNode(true)
|
||||
const builder = root.querySelector('template-builder')
|
||||
const style = document.createElement('style')
|
||||
|
||||
builder.innerHTML = ''
|
||||
builder.setAttribute('data-native-view', event.detail.view)
|
||||
|
||||
root.querySelector('meta[name="viewport"]')?.setAttribute('content', 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no')
|
||||
|
||||
style.textContent = 'html { overflow-x: hidden; overscroll-behavior-x: none; } html, body { max-width: 100%; }'
|
||||
|
||||
root.querySelector('head').appendChild(style)
|
||||
|
||||
event.detail.result = '<!DOCTYPE html>' + root.outerHTML
|
||||
}
|
||||
|
||||
onBeforeCache = () => {
|
||||
this.app?.unmount()
|
||||
this.appElem?.remove()
|
||||
@@ -409,6 +447,7 @@ safeRegisterElement('template-builder', class extends HTMLElement {
|
||||
document.removeEventListener('template-builder:select-submitter', this.onSelectSubmitter)
|
||||
document.removeEventListener('template-builder:sync-custom-fields', this.onSyncCustomFields)
|
||||
document.removeEventListener('template-builder:draw-field', this.onDrawField)
|
||||
document.removeEventListener('native:builder-view', this.onBuilderView)
|
||||
document.removeEventListener('turbo:before-cache', this.onBeforeCache)
|
||||
|
||||
this.app?.unmount()
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
import { renderStreamMessage } from '@hotwired/turbo'
|
||||
import { renderStreamMessage, session } from '@hotwired/turbo'
|
||||
|
||||
export default class extends HTMLElement {
|
||||
connectedCallback () {
|
||||
if (!this.dataset.src) return
|
||||
if (this.dataset.limit) this.replaceLimitParam()
|
||||
|
||||
if (!this.dataset.src) {
|
||||
this.remove()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
this.observer = new IntersectionObserver((entries) => {
|
||||
if (entries.some((entry) => entry.isIntersecting)) {
|
||||
@@ -17,6 +23,15 @@ export default class extends HTMLElement {
|
||||
this.observer?.disconnect()
|
||||
}
|
||||
|
||||
replaceLimitParam () {
|
||||
const url = new URL(window.location.href)
|
||||
|
||||
url.searchParams.set('limit', this.dataset.limit)
|
||||
|
||||
session.history.replace(url, session.history.restorationIdentifier)
|
||||
session.view.lastRenderedLocation = url
|
||||
}
|
||||
|
||||
load () {
|
||||
if (this.loading || !this.dataset.src) return
|
||||
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
const handlers = window.webkit?.messageHandlers
|
||||
|
||||
if (handlers?.native && window === window.top) {
|
||||
handlers.native.postMessage({ type: 'reset' })
|
||||
|
||||
const reportPathConfiguration = () => {
|
||||
const element = document.getElementById('native_path_configuration')
|
||||
|
||||
if (element) handlers.native.postMessage({ type: 'path-configuration', json: element.textContent })
|
||||
}
|
||||
|
||||
document.addEventListener('turbo:load', reportPathConfiguration)
|
||||
|
||||
reportPathConfiguration()
|
||||
|
||||
const reportFlash = (element) => {
|
||||
if (!element) return
|
||||
|
||||
if (element.dataset.notice) handlers.flash.postMessage({ style: 'notice', message: element.dataset.notice })
|
||||
if (element.dataset.alert) handlers.flash.postMessage({ style: 'alert', message: element.dataset.alert })
|
||||
|
||||
element.remove()
|
||||
}
|
||||
|
||||
const reportPageFlash = () => reportFlash(document.getElementById('native_flash'))
|
||||
|
||||
new MutationObserver(reportPageFlash).observe(document.documentElement, { childList: true, subtree: true })
|
||||
|
||||
document.addEventListener('turbo:load', reportPageFlash)
|
||||
|
||||
document.addEventListener('native:flash', (event) => {
|
||||
reportFlash(new DOMParser().parseFromString(event.detail.html, 'text/html').getElementById('native_flash'))
|
||||
})
|
||||
|
||||
reportPageFlash()
|
||||
|
||||
document.addEventListener('click', (event) => {
|
||||
if (document.querySelector('native-modal')) return
|
||||
|
||||
const link = event.target.closest?.('a[data-turbo-frame="modal"], a[data-turbo-frame="drawer"]')
|
||||
|
||||
if (!link?.href) return
|
||||
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
|
||||
handlers.modal.postMessage({ action: 'open', url: link.href, modal: link.closest('[data-native-modal]')?.dataset.nativeModal || '' })
|
||||
}, true)
|
||||
|
||||
document.addEventListener('click', (event) => {
|
||||
const link = event.target.closest?.('a[href]')
|
||||
|
||||
if (!link) return
|
||||
|
||||
const title = link.dataset.nativeTitle || link.closest('[data-native-title]')?.dataset.nativeTitle || link.innerText.trim()
|
||||
|
||||
if (!title) return
|
||||
|
||||
const actions = link.closest('[data-native-actions]')?.dataset.nativeActions
|
||||
|
||||
handlers.native.postMessage({ type: 'title', url: link.href, title, actions: actions ? actions.split(',') : null })
|
||||
}, true)
|
||||
|
||||
document.addEventListener('native:action', (event) => {
|
||||
document.querySelector(`[data-native-id="${event.detail.id}"]`)?.click()
|
||||
})
|
||||
|
||||
document.addEventListener('native:title-bottom', (event) => {
|
||||
const rect = document.querySelector('h1, h2')?.getBoundingClientRect()
|
||||
|
||||
event.detail.result = rect?.height ? rect.bottom - document.documentElement.getBoundingClientRect().top : null
|
||||
})
|
||||
}
|
||||
@@ -1,10 +1,36 @@
|
||||
export default class extends HTMLElement {
|
||||
connectedCallback () {
|
||||
document.addEventListener('native:search', this.onSearch)
|
||||
document.addEventListener('turbo:before-cache', this.onBeforeCache)
|
||||
this.addEventListener('touchstart', this.onTouchStart, { passive: true })
|
||||
this.addEventListener('scroll', this.onScroll, { capture: true, passive: true })
|
||||
|
||||
const scroller = this.querySelector('[data-scroll-top]')
|
||||
|
||||
if (scroller) scroller.scrollTop = scroller.dataset.scrollTop
|
||||
}
|
||||
|
||||
disconnectedCallback () {
|
||||
document.removeEventListener('native:search', this.onSearch)
|
||||
document.removeEventListener('turbo:before-cache', this.onBeforeCache)
|
||||
}
|
||||
|
||||
onBeforeCache = () => {
|
||||
if (this.scroller) this.scroller.dataset.scrollTop = this.scroller.scrollTop
|
||||
}
|
||||
|
||||
onTouchStart = () => {
|
||||
this.isTouching = true
|
||||
}
|
||||
|
||||
onScroll = (event) => {
|
||||
this.scroller = event.target
|
||||
|
||||
if (!this.isTouching) return
|
||||
|
||||
this.isTouching = false
|
||||
|
||||
window.webkit?.messageHandlers?.native?.postMessage({ type: 'dismiss-keyboard' })
|
||||
}
|
||||
|
||||
onSearch = (event) => {
|
||||
|
||||
@@ -5,20 +5,36 @@ export default class extends HTMLElement {
|
||||
this.files = []
|
||||
|
||||
document.addEventListener('turbo:submit-end', this.onSubmitEnd)
|
||||
document.addEventListener('native:upload-start', this.onUploadStart)
|
||||
document.addEventListener('native:upload-chunk', this.onUploadChunk)
|
||||
document.addEventListener('native:upload-submit', this.onUploadSubmit)
|
||||
}
|
||||
|
||||
disconnectedCallback () {
|
||||
document.removeEventListener('turbo:submit-end', this.onSubmitEnd)
|
||||
document.removeEventListener('native:upload-start', this.onUploadStart)
|
||||
document.removeEventListener('native:upload-chunk', this.onUploadChunk)
|
||||
document.removeEventListener('native:upload-submit', this.onUploadSubmit)
|
||||
}
|
||||
|
||||
get form () {
|
||||
return this.querySelector('form')
|
||||
}
|
||||
|
||||
append (index, name, type, base64) {
|
||||
onUploadStart = (event) => {
|
||||
this.files = []
|
||||
|
||||
event.detail.result = true
|
||||
}
|
||||
|
||||
onUploadChunk = ({ detail: { index, name, type, chunk } }) => {
|
||||
const file = this.files[index] ||= { name, type, chunks: [] }
|
||||
|
||||
file.chunks.push(Uint8Array.from(atob(base64), (char) => char.charCodeAt(0)))
|
||||
file.chunks.push(Uint8Array.from(atob(chunk), (char) => char.charCodeAt(0)))
|
||||
}
|
||||
|
||||
onUploadSubmit = (event) => {
|
||||
event.detail.result = this.submit(event.detail.url)
|
||||
}
|
||||
|
||||
async submit (url) {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import './elements/native_bridge'
|
||||
|
||||
import { createApp, reactive } from 'vue'
|
||||
|
||||
import Form from './submission_form/form'
|
||||
|
||||
@@ -16,13 +16,10 @@
|
||||
v-if="editable"
|
||||
class="flex justify-between w-full"
|
||||
>
|
||||
<div
|
||||
style="width: 26px"
|
||||
class="flex flex-col"
|
||||
>
|
||||
<div class="flex flex-col w-[26px] max-md:w-7">
|
||||
<button
|
||||
v-if="item.conditions?.length"
|
||||
class="btn border-gray-300 bg-white text-base-content btn-xs rounded hover:text-base-100 hover:bg-base-content hover:border-base-content w-full transition-colors p-0 document-control-button"
|
||||
class="btn border-gray-300 bg-white text-base-content btn-xs rounded hover:text-base-100 hover:bg-base-content hover:border-base-content w-full transition-colors p-0 document-control-button max-md:h-7 max-md:min-h-7"
|
||||
@click.stop="openConditionsModal"
|
||||
>
|
||||
<IconRouteAltLeft
|
||||
@@ -31,7 +28,7 @@
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<div class="">
|
||||
<div class="max-md:[&_.btn]:h-7 max-md:[&_.btn]:min-h-7 max-md:[&_.btn]:text-sm">
|
||||
<ReplaceButton
|
||||
v-if="withReplaceButton"
|
||||
:template-id="template.id"
|
||||
@@ -55,8 +52,7 @@
|
||||
>
|
||||
<label
|
||||
tabindex="0"
|
||||
class="btn border-gray-300 bg-white text-base-content btn-xs rounded hover:text-base-100 hover:bg-base-content hover:border-base-content w-full transition-colors document-control-button px-0"
|
||||
style="width: 24px; height: 24px"
|
||||
class="btn border-gray-300 bg-white text-base-content btn-xs rounded hover:text-base-100 hover:bg-base-content hover:border-base-content transition-colors document-control-button px-0 w-6 h-6 max-md:w-7 max-md:h-7 max-md:min-h-7"
|
||||
@click.stop
|
||||
>
|
||||
<IconDotsVertical
|
||||
@@ -141,15 +137,13 @@
|
||||
:class="{ 'opacity-0 group-hover:opacity-100': !withVisibleControls }"
|
||||
>
|
||||
<button
|
||||
class="btn border-gray-300 bg-white text-base-content btn-xs rounded hover:text-base-100 hover:bg-base-content hover:border-base-content w-full transition-colors document-control-button"
|
||||
style="width: 24px; height: 24px"
|
||||
class="btn border-gray-300 bg-white text-base-content btn-xs rounded hover:text-base-100 hover:bg-base-content hover:border-base-content transition-colors document-control-button w-6 h-6 max-md:w-7 max-md:h-7 max-md:min-h-7 max-md:text-sm"
|
||||
@click.stop="$emit('up', item)"
|
||||
>
|
||||
↑
|
||||
</button>
|
||||
<button
|
||||
class="btn border-gray-300 bg-white text-base-content btn-xs rounded hover:text-base-100 hover:bg-base-content hover:border-base-content w-full transition-colors document-control-button"
|
||||
style="width: 24px; height: 24px"
|
||||
class="btn border-gray-300 bg-white text-base-content btn-xs rounded hover:text-base-100 hover:bg-base-content hover:border-base-content transition-colors document-control-button w-6 h-6 max-md:w-7 max-md:h-7 max-md:min-h-7 max-md:text-sm"
|
||||
@click.stop="$emit('down', item)"
|
||||
>
|
||||
↓
|
||||
|
||||
Reference in new issue
Block a user