Avoid reloading bookmarks list after interacting with card actions

This removes the "turbo-reload" controller that listened to Turbo form submit
events and reloaded the current page after any bookmark card got modified.

Since bookmark card actions offer the user to favorite or archive a bookmark,
the reload was in place to subsequently remove the bookmark in case it no
longer satisfied the current view filter. For instance, un-favoriting a bookmark
would remove it from the "Favorites" list.

However, the reload was expensive. Not only does the whole page need to be
re-fetched after editing any bookmark, but the whole document body would have
to be replaced with the one from the fetch response. In Safari on macOS,
replacing the whole body typically takes 1-2s due to the number of DOM
mutations that all have to be reacted to by Stimulus in order to disconnect the
old controllers and reconnect the new ones. In a lot of cases, there isn't even
a need to re-fetch and replace the entire document body because the bookmark
being edited is still in the list, even after the edits.

Removing this controller reduces the laginess of Readeck in Safari, avoids
scroll position reset problems, and avoids making an extra request to Readeck
backend. The downside of this change is that a bookmark will never leave the
current view (for example, after being un-favorited) until the user manually
refreshes the page.
This commit is contained in:
Mislav Marohnić
2025-11-04 03:16:45 +01:00
parent 221e53ec65
commit 90446310e2
3 changed files with 3 additions and 41 deletions

View File

@@ -103,7 +103,7 @@ SPDX-License-Identifier: AGPL-3.0-only
{{- else -}}
<div class="bookmark-card--actions">
<form action="{{ _url }}" method="post"
data-controller="turbo-form turbo-reload"
data-controller="turbo-form"
data-turbo-form-action-value="{{ urlFor(`/api/bookmarks`, .ID) }}"
data-turbo-form-method-value="patch">
<input type="hidden" name="_to" value="{{ currentPath }}" />

View File

@@ -1,40 +0,0 @@
// SPDX-FileCopyrightText: © 2021 Olivier Meunier <olivier@neokraft.net>
//
// SPDX-License-Identifier: AGPL-3.0-only
import {Controller} from "@hotwired/stimulus"
import {visit} from "@hotwired/turbo"
// This controller listens for turbo:submit-end events
// and reload the frame with the ID given by data-turbo-reload-frame-id-value
// attribute by reloading the current page when the form is submited.
// It obviously applies only to form elements.
export default class extends Controller {
static values = {
frameId: String,
}
connect() {
document.addEventListener("turbo:submit-end", this.reloadFrame.bind(this))
}
disconnect() {
document.removeEventListener(
"turbo:submit-end",
this.reloadFrame.bind(this),
)
}
reloadFrame(evt) {
if (evt.target != this.element) {
return
}
const options = {action: "replace"}
if (this.hasFrameIdValue) {
options.frame = this.frameIdValue
}
visit(document.location.href, options)
}
}

View File

@@ -2,6 +2,8 @@
//
// SPDX-License-Identifier: AGPL-3.0-only
import "@hotwired/turbo"
const cspNonce = document.querySelector(
'html>head>meta[name="csp-nonce"]',
).content