longform
longform copied to clipboard
Scenes disappear from list when reordering with drag/drop
I'm using 2.0.0.
Occasionally when I rearrange scenes in the scene list, scenes disappear. Reload app without saving causes Longform to find them again, but it loses their ordering / location in the index tree.
I'm attempting to reproduce this to gather more detail, but it's a bit of a Heisenbug for me. I can update the description or comment here if or when I encounter it next -- just wanted to flag it now in case it was introduced in a recent commit.
When did you install the beta? I recently fixed this exact behavior in #91. If you reinstall it, does this still occur?
Interesting! I installed last night, I'll check again. I'm using BRAT for the first time (and I'm not too sure what I'm doing), so that might be a factor.
Hmm, that should be recent enough...
What platform and Obsidian version number are you seeing this on? Is there any way you could make an anonymized version of the buggy project to share here?
I ran the update command on BRAT again after my last comment, and haven't seen the problem since. I guess that's good? Though it's mysterious. I'll keep using it and see if it comes up again. Happy to share an anonymized version if it does.
- Obsidian 0.15.9, macOS 11.6.8 (intel)
Strange. Let me know! Here's how the other bug looked, if it helps:
- Move a scene. Looks good.
- Move another scene. The previously-moved scene disappears.
- Repeat.
I thought I had guarded against this with the fix, but it's possible some other issue crept in. Keep me posted, and thanks for trying it!
Strange. Let me know! Here's how the other bug looked, if it helps:
- Move a scene. Looks good.
- Move another scene. The previously-moved scene disappears.
- Repeat.
I thought I had guarded against this with the fix, but it's possible some other issue crept in. Keep me posted, and thanks for trying it!
for me, scenes disappear immediately after being dragged on mobile, and will not reappear in the index until i reload the app. so basically,
- move scene
- scene disappears
- repeat until there's no scenes left
@GamerGirlandCo do you have the latest beta? You'll need to uninstall and reinstall in BRAT, as I'm not updating version numbers. If you haven't reinstalled in the past few days you're likely seeing the fixed issue I linked. If not let me know.
@GamerGirlandCo do you have the latest beta? You'll need to uninstall and reinstall in BRAT, as I'm not updating version numbers. If you haven't reinstalled in the past few days you're likely seeing the fixed issue I linked. If not let me know.
aha, that fixed it! :D thank you!!
Ok, I'm seeing the issue again. Often, scenes are disappearing from "folded" lists in the outline. In fact, I can pretty reliably disappear scenes using either of these methods:
- Nest some scenes under a parent, then "fold" the parent. Move an unrelated scene with drag and drop. This causes all the "nested" scenes to disappear.
- Nest at least one scene under a parent, then "fold" the parent. Move any scene under the parent, so that it would be "nested" if released. The held scene disappears. Now unfold the parent:
- If there was 1 scene nested before, it will remain, and the one you were moving has disappeared.
- If there were 2 or more nested before, they're gone and the one you were holding is there.
I found a fix for this! Edit: Wrote about it below.
Scenes under collapsed scenes get lost:
When Sortable.js serializes with toArray(), it does so by reading back the items from the DOM to determine order.
-
<SortableList>
calls toArray here, onMount().
Items that are hidden (because they're indented and their parent was collapsed) are being skipped for rendering entirely, so they don't show up in the DOM. The next time serialization happens, anything that's missing from the tree gets dropped from the store.
One way to solve it:
Keep hidden scene items in the DOM, but style them with "display: none". SortableList still sees them and can maintain a stable sort, even when things are collapsed.
Simplified diff:
diff --git a/src/view/explorer/SceneList.svelte b/src/view/explorer/SceneList.svelte
index 4000ef8..b54bda5 100644
--- a/src/view/explorer/SceneList.svelte
+++ b/src/view/explorer/SceneList.svelte
@@ -61,12 +61,15 @@
let ignoringUntilIndent = Infinity;
scenes.forEach(({ title, indent, numbering }, index) => {
- if (indent <= ignoringUntilIndent) {
- ignoringUntilIndent = Infinity;
+ if (true) {
+ let hidden = indent > ignoringUntilIndent;
+ if (!hidden) {
+ ignoringUntilIndent = Infinity;
+ }
const collapsed = _collapsedItems.contains(title);
if (collapsed) {
- ignoringUntilIndent = indent;
+ ignoringUntilIndent = Math.min(ignoringUntilIndent, indent);
}
const nextScene = index < scenes.length - 1 ? scenes[index + 1] : false;
@@ -76,6 +79,7 @@
indent: indent,
path: makeScenePath($selectedDraft as MultipleSceneDraft, title),
collapsible: nextScene && nextScene.indent > indent,
+ hidden: hidden,
numbering,
};
itemsToReturn.push(item);
@@ -315,7 +319,8 @@
>
<div
class="scene-container"
- style="margin-left: {item.indent * 32}px"
+ style="margin-left: {item.indent * 32}px; {item.hidden &&
+ 'display: none;'}"
class:selected={$activeFile && $activeFile.path === item.path}
on:click={(e) =>
typeof item.path === "string" ? onItemClick(item, e) : {}}
Notes:
- I left the
if (true) {}
in because it makes the diff more readable. - the
Math.min
part becomes necessary for nested collapsed scenes, since we're walking through all of them now, not just the first one we see.
Brilliant, thank you! I'll take a look at this this week, amazing work.
Funnily enough I saw the email subject this morning upon waking and realized immediately that I was relying on a DOM read... 😊
by "this week" I guess I meant "two months from now," but such is life :)