diff --git a/app/controllers/templates_versions_controller.rb b/app/controllers/templates_versions_controller.rb index 0dbd20aaa..6cd75c618 100644 --- a/app/controllers/templates_versions_controller.rb +++ b/app/controllers/templates_versions_controller.rb @@ -4,9 +4,12 @@ class TemplatesVersionsController < ApplicationController load_and_authorize_resource :template def index - versions = @template.template_versions.order(id: :desc).preload(:author) + @versions = @template.template_versions.order(id: :desc).preload(:author) - render json: versions.as_json(TemplateVersions::SERIALIZE_PARAMS) + respond_to do |format| + format.json { render json: @versions.as_json(TemplateVersions::SERIALIZE_PARAMS) } + format.html + end end def show diff --git a/app/controllers/testing_accounts_controller.rb b/app/controllers/testing_accounts_controller.rb index a96f21e54..f40440149 100644 --- a/app/controllers/testing_accounts_controller.rb +++ b/app/controllers/testing_accounts_controller.rb @@ -10,12 +10,22 @@ class TestingAccountsController < ApplicationController impersonate_user(Accounts.find_or_create_testing_user(true_user.account)) - redirect_back(fallback_location: root_path) + redirect_after_toggle end def destroy stop_impersonating_user - redirect_back(fallback_location: root_path) + redirect_after_toggle + end + + private + + def redirect_after_toggle + if turbo_native_app? + redirect_to root_path + else + redirect_back(fallback_location: root_path) + end end end diff --git a/app/javascript/application.js b/app/javascript/application.js index 967416ef9..4e3b73e3f 100644 --- a/app/javascript/application.js +++ b/app/javascript/application.js @@ -12,6 +12,8 @@ import TurboModal from './elements/turbo_modal' import NativeAction from './elements/native_action' import NativeSearch from './elements/native_search' import NativeModal from './elements/native_modal' +import NativeEvent from './elements/native_event' +import ModalButton from './elements/modal_button' import FileDropzone from './elements/file_dropzone' import MenuActive from './elements/menu_active' import ClipboardCopy from './elements/clipboard_copy' @@ -89,11 +91,23 @@ document.addEventListener('turbo:submit-end', async (event) => { return } + const filename = decodeURIComponent(resp.headers.get('content-disposition').split('"')[1]) + const download = window.webkit?.messageHandlers?.download + + if (download) { + const reader = new FileReader() + + reader.onload = () => download.postMessage({ name: filename, data: reader.result.split(',')[1] }) + reader.readAsDataURL(await resp.blob()) + + return + } + const url = URL.createObjectURL(await resp.blob()) const link = document.createElement('a') link.href = url - link.setAttribute('download', decodeURIComponent(resp.headers.get('content-disposition').split('"')[1])) + link.setAttribute('download', filename) document.body.appendChild(link) @@ -112,6 +126,8 @@ safeRegisterElement('turbo-modal', TurboModal) safeRegisterElement('native-action', NativeAction) safeRegisterElement('native-search', NativeSearch) safeRegisterElement('native-modal', NativeModal) +safeRegisterElement('native-event', NativeEvent) +safeRegisterElement('modal-button', ModalButton) safeRegisterElement('file-dropzone', FileDropzone) safeRegisterElement('menu-active', MenuActive) safeRegisterElement('clipboard-copy', ClipboardCopy) diff --git a/app/javascript/elements/native_action.js b/app/javascript/elements/native_action.js index 3e491665a..2079cdea9 100644 --- a/app/javascript/elements/native_action.js +++ b/app/javascript/elements/native_action.js @@ -21,6 +21,7 @@ export default class extends HTMLElement { title: this.dataset.label || target?.textContent.trim(), icon: this.dataset.icon, placement: this.dataset.placement || 'menu', + section: this.dataset.section, native: this.dataset.native, url: this.dataset.url, accept: this.dataset.accept, diff --git a/app/javascript/elements/native_event.js b/app/javascript/elements/native_event.js new file mode 100644 index 000000000..34995670b --- /dev/null +++ b/app/javascript/elements/native_event.js @@ -0,0 +1,35 @@ +export default class extends HTMLElement { + connectedCallback () { + this.addEventListener('click', this.dispatch) + } + + disconnectedCallback () { + this.removeEventListener('click', this.dispatch) + } + + dispatch = async () => { + const bridge = window.webkit?.messageHandlers?.modal + + if (!bridge || this.dataset.loading) return + + let detail = this.dataset.detail || 'null' + + if (this.dataset.src) { + this.dataset.loading = 'true' + + try { + const response = await fetch(this.dataset.src, { headers: { Accept: 'application/json' } }) + + if (!response.ok) return + + detail = await response.text() + } catch { + return + } finally { + delete this.dataset.loading + } + } + + bridge.postMessage({ action: 'dispatch', name: this.dataset.name, detail }) + } +} diff --git a/app/javascript/template_builder/builder.vue b/app/javascript/template_builder/builder.vue index 1c7e02f74..b4dd0035b 100644 --- a/app/javascript/template_builder/builder.vue +++ b/app/javascript/template_builder/builder.vue @@ -55,10 +55,10 @@ v-if="beforeRevisionSnapshot" class="top-1.5 sticky h-0 z-20 max-w-2xl mx-auto" > -
+
{{ t('viewing_revision_from').replace('{date}', formatRevisionTime(beforeRevisionSnapshot.revision.created_at)) }} -
+