From 31c16ef0224aed8d8630e0827fded4dfdd4f2168 Mon Sep 17 00:00:00 2001 From: Kevin Boos Date: Thu, 2 Jul 2026 19:35:00 -0400 Subject: [PATCH] Implement collapsible/expandable reply previews Previously reply previews shown in both the timeline and above the message text input bar were shown in full. Now, if the reply is too long, it'll be collapsed and shown only partially with a fade-out effect (fade to transparent on the bottom) with a "show more" button on bottom, which expands the preview on click. --- Cargo.lock | 170 ++++++++++---------- Cargo.toml | 4 +- src/home/room_screen.rs | 123 +++++++++++---- src/room/reply_preview.rs | 309 +++++++++++++++++++++++++++++++------ src/room/room_input_bar.rs | 20 ++- 5 files changed, 461 insertions(+), 165 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0191aa269..beb752165 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,7 +5,7 @@ version = 4 [[package]] name = "ab_glyph_rasterizer" version = "0.1.8" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" [[package]] name = "accessory" @@ -604,7 +604,7 @@ dependencies = [ [[package]] name = "bitflags" version = "2.10.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" [[package]] name = "bitmaps" @@ -722,7 +722,7 @@ checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "bytemuck" version = "1.25.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" [[package]] name = "byteorder" @@ -733,7 +733,7 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "byteorder" version = "1.5.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" [[package]] name = "bytes" @@ -1948,9 +1948,9 @@ dependencies = [ [[package]] name = "fxhash" version = "0.2.1" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ - "byteorder 1.5.0 (git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position)", + "byteorder 1.5.0 (git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures)", ] [[package]] @@ -2941,7 +2941,7 @@ dependencies = [ [[package]] name = "makepad-apple-sys" version = "1.0.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "makepad-objc-sys", ] @@ -2949,12 +2949,12 @@ dependencies = [ [[package]] name = "makepad-byteorder-lite" version = "0.1.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" [[package]] name = "makepad-code-editor" version = "2.0.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "makepad-widgets", ] @@ -2962,7 +2962,7 @@ dependencies = [ [[package]] name = "makepad-derive-wasm-bridge" version = "1.0.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "makepad-micro-proc-macro", ] @@ -2970,7 +2970,7 @@ dependencies = [ [[package]] name = "makepad-derive-widget" version = "2.0.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "makepad-live-id", "makepad-micro-proc-macro", @@ -2979,7 +2979,7 @@ dependencies = [ [[package]] name = "makepad-draw" version = "2.0.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "ab_glyph_rasterizer", "fxhash", @@ -2996,15 +2996,15 @@ dependencies = [ "rustybuzz", "sdfer", "serde", - "unicode-bidi 0.3.18 (git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position)", + "unicode-bidi 0.3.18 (git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures)", "unicode-linebreak", - "unicode-segmentation 1.12.0 (git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position)", + "unicode-segmentation 1.12.0 (git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures)", ] [[package]] name = "makepad-error-log" version = "1.0.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "makepad-micro-serde", ] @@ -3012,22 +3012,22 @@ dependencies = [ [[package]] name = "makepad-filesystem-watcher" version = "0.1.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" [[package]] name = "makepad-futures" version = "1.0.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" [[package]] name = "makepad-futures-legacy" version = "1.0.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" [[package]] name = "makepad-gif" version = "0.1.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "weezl", ] @@ -3035,7 +3035,7 @@ dependencies = [ [[package]] name = "makepad-html" version = "1.0.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "makepad-live-id", ] @@ -3049,7 +3049,7 @@ checksum = "9775cbec5fa0647500c3e5de7c850280a88335d1d2d770e5aa2332b801ba7064" [[package]] name = "makepad-latex-math" version = "0.1.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "ttf-parser", ] @@ -3057,7 +3057,7 @@ dependencies = [ [[package]] name = "makepad-live-id" version = "1.0.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "makepad-live-id-macros", "serde", @@ -3066,7 +3066,7 @@ dependencies = [ [[package]] name = "makepad-live-id-macros" version = "1.0.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "makepad-micro-proc-macro", ] @@ -3074,7 +3074,7 @@ dependencies = [ [[package]] name = "makepad-live-reload-core" version = "0.1.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "makepad-filesystem-watcher", ] @@ -3082,7 +3082,7 @@ dependencies = [ [[package]] name = "makepad-math" version = "1.0.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "makepad-micro-serde", ] @@ -3090,12 +3090,12 @@ dependencies = [ [[package]] name = "makepad-micro-proc-macro" version = "1.0.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" [[package]] name = "makepad-micro-serde" version = "1.0.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "makepad-live-id", "makepad-micro-serde-derive", @@ -3104,7 +3104,7 @@ dependencies = [ [[package]] name = "makepad-micro-serde-derive" version = "1.0.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "makepad-micro-proc-macro", ] @@ -3112,7 +3112,7 @@ dependencies = [ [[package]] name = "makepad-network" version = "1.0.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "makepad-apple-sys", "makepad-error-log", @@ -3126,15 +3126,15 @@ dependencies = [ [[package]] name = "makepad-objc-sys" version = "1.0.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" [[package]] name = "makepad-platform" version = "2.0.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "ash", - "bitflags 2.10.0 (git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position)", + "bitflags 2.10.0 (git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures)", "ctrlc", "hilog-sys", "makepad-android-state", @@ -3156,7 +3156,7 @@ dependencies = [ "napi-derive-ohos", "napi-ohos", "ohos-sys", - "smallvec 1.15.1 (git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position)", + "smallvec 1.15.1 (git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures)", "wayland-client", "wayland-egl", "wayland-protocols", @@ -3168,12 +3168,12 @@ dependencies = [ [[package]] name = "makepad-regex" version = "0.1.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" [[package]] name = "makepad-script" version = "1.0.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "makepad-error-log", "makepad-html", @@ -3181,13 +3181,13 @@ dependencies = [ "makepad-math", "makepad-regex", "makepad-script-derive", - "smallvec 1.15.1 (git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position)", + "smallvec 1.15.1 (git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures)", ] [[package]] name = "makepad-script-derive" version = "1.0.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "makepad-micro-proc-macro", ] @@ -3195,7 +3195,7 @@ dependencies = [ [[package]] name = "makepad-script-std" version = "1.0.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "makepad-network", "makepad-script", @@ -3204,14 +3204,14 @@ dependencies = [ [[package]] name = "makepad-shared-bytes" version = "1.0.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" [[package]] name = "makepad-studio-protocol" version = "0.1.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ - "bitflags 2.10.0 (git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position)", + "bitflags 2.10.0 (git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures)", "makepad-error-log", "makepad-live-id", "makepad-micro-serde", @@ -3221,7 +3221,7 @@ dependencies = [ [[package]] name = "makepad-svg" version = "1.0.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "makepad-html", "makepad-live-id", @@ -3230,7 +3230,7 @@ dependencies = [ [[package]] name = "makepad-tsdf" version = "0.1.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "makepad-math", "makepad-micro-serde", @@ -3239,7 +3239,7 @@ dependencies = [ [[package]] name = "makepad-wasm-bridge" version = "1.0.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "makepad-derive-wasm-bridge", "makepad-live-id", @@ -3248,7 +3248,7 @@ dependencies = [ [[package]] name = "makepad-webp" version = "0.2.4" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "makepad-byteorder-lite", ] @@ -3256,7 +3256,7 @@ dependencies = [ [[package]] name = "makepad-widgets" version = "2.0.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "makepad-derive-widget", "makepad-draw", @@ -3265,13 +3265,13 @@ dependencies = [ "pulldown-cmark 0.12.2", "serde", "ttf-parser", - "unicode-segmentation 1.12.0 (git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position)", + "unicode-segmentation 1.12.0 (git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures)", ] [[package]] name = "makepad-zune-bmp" version = "0.5.2" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "log", "makepad-zune-core", @@ -3280,7 +3280,7 @@ dependencies = [ [[package]] name = "makepad-zune-core" version = "0.5.1" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "log", ] @@ -3288,7 +3288,7 @@ dependencies = [ [[package]] name = "makepad-zune-inflate" version = "0.2.54" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "simd-adler32", ] @@ -3296,7 +3296,7 @@ dependencies = [ [[package]] name = "makepad-zune-jpeg" version = "0.5.15" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "makepad-zune-core", ] @@ -3304,7 +3304,7 @@ dependencies = [ [[package]] name = "makepad-zune-png" version = "0.5.2" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "makepad-zune-core", "makepad-zune-inflate", @@ -3313,7 +3313,7 @@ dependencies = [ [[package]] name = "makepad-zune-qoi" version = "0.5.2" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "makepad-zune-core", ] @@ -3695,7 +3695,7 @@ checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "memchr" version = "2.7.6" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" [[package]] name = "mime" @@ -4526,10 +4526,10 @@ dependencies = [ [[package]] name = "pulldown-cmark" version = "0.12.2" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ - "bitflags 2.10.0 (git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position)", - "memchr 2.7.6 (git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position)", + "bitflags 2.10.0 (git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures)", + "memchr 2.7.6 (git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures)", "unicase 2.9.0", ] @@ -5414,12 +5414,12 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "rustybuzz" version = "0.18.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ - "bitflags 2.10.0 (git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position)", + "bitflags 2.10.0 (git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures)", "bytemuck", "makepad-error-log", - "smallvec 1.15.1 (git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position)", + "smallvec 1.15.1 (git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures)", "ttf-parser", "unicode-bidi-mirroring", "unicode-ccc", @@ -5514,7 +5514,7 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sdfer" version = "0.2.1" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" [[package]] name = "sealed" @@ -5813,7 +5813,7 @@ dependencies = [ [[package]] name = "simd-adler32" version = "0.3.9" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" [[package]] name = "siphasher" @@ -5839,7 +5839,7 @@ dependencies = [ [[package]] name = "smallvec" version = "1.15.1" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" [[package]] name = "socket2" @@ -6620,7 +6620,7 @@ dependencies = [ [[package]] name = "ttf-parser" version = "0.24.1" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" [[package]] name = "tungstenite" @@ -6672,7 +6672,7 @@ checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" [[package]] name = "unicase" version = "2.9.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" [[package]] name = "unicode-bidi" @@ -6683,17 +6683,17 @@ checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-bidi" version = "0.3.18" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" [[package]] name = "unicode-bidi-mirroring" version = "0.3.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" [[package]] name = "unicode-ccc" version = "0.3.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" [[package]] name = "unicode-ident" @@ -6704,7 +6704,7 @@ checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" [[package]] name = "unicode-linebreak" version = "0.1.5" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" [[package]] name = "unicode-normalization" @@ -6724,12 +6724,12 @@ checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" [[package]] name = "unicode-properties" version = "0.1.4" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" [[package]] name = "unicode-script" version = "0.5.8" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" [[package]] name = "unicode-segmentation" @@ -6740,7 +6740,7 @@ checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-segmentation" version = "1.12.0" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" [[package]] name = "unicode-width" @@ -7072,7 +7072,7 @@ dependencies = [ [[package]] name = "wayland-backend" version = "0.3.12" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "downcast-rs", "libc", @@ -7084,7 +7084,7 @@ dependencies = [ [[package]] name = "wayland-client" version = "0.31.12" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "bitflags 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc", @@ -7094,7 +7094,7 @@ dependencies = [ [[package]] name = "wayland-egl" version = "0.32.9" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "wayland-backend", "wayland-sys", @@ -7103,7 +7103,7 @@ dependencies = [ [[package]] name = "wayland-protocols" version = "0.32.10" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "bitflags 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "wayland-backend", @@ -7113,7 +7113,7 @@ dependencies = [ [[package]] name = "wayland-sys" version = "0.31.8" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "log", "pkg-config", @@ -7164,7 +7164,7 @@ dependencies = [ [[package]] name = "weezl" version = "0.1.12" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" [[package]] name = "whoami" @@ -7217,7 +7217,7 @@ dependencies = [ [[package]] name = "windows" version = "0.62.2" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "windows-collections 0.3.2", "windows-core 0.62.2", @@ -7236,7 +7236,7 @@ dependencies = [ [[package]] name = "windows-collections" version = "0.3.2" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "windows-core 0.62.2", ] @@ -7269,7 +7269,7 @@ dependencies = [ [[package]] name = "windows-core" version = "0.62.2" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "windows-link 0.2.1", "windows-result 0.4.1", @@ -7290,7 +7290,7 @@ dependencies = [ [[package]] name = "windows-future" version = "0.3.2" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "windows-core 0.62.2", ] @@ -7354,7 +7354,7 @@ checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" [[package]] name = "windows-link" version = "0.2.1" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" [[package]] name = "windows-numerics" @@ -7398,7 +7398,7 @@ dependencies = [ [[package]] name = "windows-result" version = "0.4.1" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "windows-link 0.2.1", ] @@ -7415,7 +7415,7 @@ dependencies = [ [[package]] name = "windows-strings" version = "0.5.1" -source = "git+https://github.com/kevinaboos/makepad?branch=text_input_expose_caret_cursor_position#f633e2a6b358e29ac602fdfda8da5a248044608c" +source = "git+https://github.com/kevinaboos/makepad?branch=view_optimize_dont_redraw_cached_textures#19ff922e6f4a5d9f9ec974fb43683250049135fb" dependencies = [ "windows-link 0.2.1", ] diff --git a/Cargo.toml b/Cargo.toml index a2c1920fd..f09326f6f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,8 +17,8 @@ metadata.makepad-auto-version = "zqpv-Yj-K7WNVK2I8h5Okhho46Q=" # makepad-widgets = { git = "https://github.com/makepad/makepad", branch = "dev", features = ["serde"] } # makepad-code-editor = { git = "https://github.com/makepad/makepad", branch = "dev" } -makepad-widgets = { git = "https://github.com/kevinaboos/makepad", branch = "text_input_expose_caret_cursor_position", features = ["serde"] } -makepad-code-editor = { git = "https://github.com/kevinaboos/makepad", branch = "text_input_expose_caret_cursor_position" } +makepad-widgets = { git = "https://github.com/kevinaboos/makepad", branch = "view_optimize_dont_redraw_cached_textures", features = ["serde"] } +makepad-code-editor = { git = "https://github.com/kevinaboos/makepad", branch = "view_optimize_dont_redraw_cached_textures" } ## Including this crate automatically configures all `robius-*` crates to work with Makepad. diff --git a/src/home/room_screen.rs b/src/home/room_screen.rs index d79c96c0e..ba6bfdc73 100644 --- a/src/home/room_screen.rs +++ b/src/home/room_screen.rs @@ -30,7 +30,7 @@ use crate::{ user_profile::{ShowUserProfileAction, UserProfile, UserProfileAndRoomId, UserProfilePaneInfo, UserProfileSlidingPaneRef, UserProfileSlidingPaneWidgetExt}, user_profile_cache, }, - room::{BasicRoomDetails, room_input_bar::{RoomInputBarState, RoomInputBarWidgetRefExt}, typing_notice::TypingNoticeWidgetExt}, + room::{BasicRoomDetails, reply_preview::CollapsiblePreviewWidgetRefExt, room_input_bar::{RoomInputBarState, RoomInputBarWidgetRefExt}, typing_notice::TypingNoticeWidgetExt}, shared::{ attachment_download::{enqueue_already_downloading_notification, DownloadDisplayState, DownloadKind, DownloadableAttachment, PendingDownload, PendingDownloadState, media_source_mxc, start_attachment_download}, avatar::{AvatarState, AvatarWidgetRefExt}, confirmation_modal::ConfirmationModalContent, file_upload_modal::FileUploadAttemptId, html_or_plaintext::{HtmlOrPlaintextRef, HtmlOrPlaintextWidgetRefExt, RobrixHtmlLinkAction}, image_viewer::{ImageViewerAction, ImageViewerMetaData, LoadState}, jump_to_bottom_button::{JumpToBottomButtonWidgetExt, UnreadMessageCount}, popup_list::{PopupKind, enqueue_popup_notification}, restore_status_view::RestoreStatusViewWidgetExt, room_input_popup_menu::{RoomInputPopupMenuAction, RoomInputPopupMenuWidgetExt}, styles::*, text_or_image::{TextOrImageAction, TextOrImageRef, TextOrImageStatus, TextOrImageWidgetRefExt}, timestamp::TimestampWidgetRefExt }, @@ -280,9 +280,9 @@ script_mod! { // A preview of the earlier message that this message was in reply to. replied_to_message := mod.widgets.RepliedToMessage { - flow: Right + flow: Down margin: Inset{ bottom: 3, top: 10 } - replied_to_message_content +: { + preview_content +: { margin +: { left: 29 } padding +: { bottom: 10 } } @@ -356,7 +356,7 @@ script_mod! { mod.widgets.CondensedMessage = mod.widgets.Message { padding: Inset{ top: 2.0, bottom: 2.0 } replied_to_message +: { - replied_to_message_content +: { + preview_content +: { margin: Inset{ left: 74, bottom: 5.0 } } } @@ -746,6 +746,10 @@ pub struct RoomScreen { #[rust] all_rooms_loaded: bool, /// A flag to set key focus for the text input after it has been drawn. #[rust] focus_input_bar_on_show: bool, + /// After a reply preview collapses, redraw until the list is fills the viewport. + #[rust] relayout_redraws_left: u8, + #[rust] relayout_last_first_id: usize, + #[rust] relayout_last_scroll: f64, } impl Drop for RoomScreen { @@ -1255,6 +1259,7 @@ impl Widget for RoomScreen { &tl_state.user_power, &self.pinned_events, &tl_state.pending_downloads, + &tl_state.expanded_reply_previews, item_drawn_status, room_screen_widget_uid, ) @@ -1382,6 +1387,25 @@ impl Widget for RoomScreen { self.view.room_input_bar(cx, ids!(room_input_bar)).set_key_focus(cx); } + // After a reply preview is collapsed, the timeline portallist will have empty space at the top. + // We need to keep drawing it until it's filled. + if self.relayout_redraws_left > 0 { + self.relayout_redraws_left -= 1; + let (first_id, scroll) = { + let list = self.view.portal_list(cx, ids!(timeline.list)); + (list.first_id(), list.scroll_position()) + }; + if first_id != self.relayout_last_first_id + || (scroll - self.relayout_last_scroll).abs() > 0.5 + { + self.relayout_last_first_id = first_id; + self.relayout_last_scroll = scroll; + self.redraw(cx); + } else { + self.relayout_redraws_left = 0; + } + } + DrawStep::done() } } @@ -2301,6 +2325,17 @@ impl RoomScreen { loading_pane ); } + MessageAction::ToggleReplyPreviewExpanded(message_id) => { + if let Some(tl) = self.tl_state.as_mut() { + if !tl.expanded_reply_previews.remove(message_id) { + tl.expanded_reply_previews.insert(message_id.clone()); + } + } + // If we collapsed the preview, redraw until the list fills the viewport again. + self.relayout_redraws_left = 12; // but not more than 12 times + self.relayout_last_first_id = usize::MAX; + self.redraw(cx); + } MessageAction::JumpToEvent(event_id) => { self.jump_to_event( cx, @@ -2555,6 +2590,7 @@ impl RoomScreen { latest_own_user_receipt: None, tombstone_info, pending_downloads: SmallVec::new(), + expanded_reply_previews: HashSet::new(), }; timeline_state_store::mark_taken(cx, &tl_state.kind, owner); (tl_state, true) @@ -3342,6 +3378,10 @@ struct TimelineUiState { /// Media/file attachments in this timeline currently being downloaded. /// the inline button's spinner state. pending_downloads: SmallVec<[PendingDownload; 1]>, + + /// Reply previews the user has eaxpanded that should be shown in full. + /// Collapsed reply previews (their default state) are absent from this set. + expanded_reply_previews: HashSet, } #[derive(Default, Debug)] @@ -3473,6 +3513,7 @@ fn populate_message_view( user_power_levels: &UserPowerLevels, pinned_events: &[OwnedEventId], pending_downloads: &[PendingDownload], + expanded_reply_previews: &HashSet, item_drawn_status: ItemDrawnStatus, room_screen_widget_uid: WidgetUid, ) -> (WidgetRef, ItemDrawnStatus) { @@ -4004,7 +4045,7 @@ fn populate_message_view( populate_read_receipts(&item, cx, timeline_kind, event_tl_item); let is_reply_fully_drawn = draw_replied_to_message( cx, - &item.view(cx, ids!(replied_to_message)), + &item.widget(cx, ids!(replied_to_message)), timeline_kind, msg_like_content.in_reply_to.as_ref(), event_tl_item.event_id(), @@ -4057,7 +4098,8 @@ fn populate_message_view( .map(|p| p.state.display()) }) .unwrap_or_default(); - item.as_message().set_data(cx, message_details, download_info, download_state); + let is_reply_expanded = expanded_reply_previews.contains(&message_details.timeline_event_id); + item.as_message().set_data(cx, message_details, download_info, download_state, is_reply_expanded); // If `used_cached_item` is false, we should always redraw the profile, even if profile_drawn is true. @@ -4660,7 +4702,7 @@ fn populate_redacted_message_content( /// i.e., whether it can be considered cached and not needing to be redrawn later. fn draw_replied_to_message( cx: &mut Cx2d, - replied_to_message_view: &ViewRef, + replied_to_message_view: &WidgetRef, timeline_kind: &TimelineKind, in_reply_to: Option<&InReplyToDetails>, message_event_id: Option<&EventId>, @@ -4674,7 +4716,7 @@ fn draw_replied_to_message( TimelineDetails::Ready(replied_to_event) => { let (in_reply_to_username, is_avatar_fully_drawn) = replied_to_message_view - .avatar(cx, ids!(replied_to_message_content.reply_preview_avatar)) + .avatar(cx, ids!(preview_content.reply_preview_avatar)) .set_avatar_and_get_username( cx, timeline_kind, @@ -4687,7 +4729,7 @@ fn draw_replied_to_message( fully_drawn = is_avatar_fully_drawn; replied_to_message_view - .label(cx, ids!(replied_to_message_content.reply_preview_username)) + .label(cx, ids!(preview_content.reply_preview_username)) .set_text(cx, in_reply_to_username.as_str()); let msg_body = replied_to_message_view.html_or_plaintext(cx, ids!(reply_preview_body)); populate_preview_of_timeline_item( @@ -4701,26 +4743,26 @@ fn draw_replied_to_message( TimelineDetails::Error(_e) => { fully_drawn = true; replied_to_message_view - .label(cx, ids!(replied_to_message_content.reply_preview_username)) + .label(cx, ids!(preview_content.reply_preview_username)) .set_text(cx, "[Error fetching username]"); replied_to_message_view - .avatar(cx, ids!(replied_to_message_content.reply_preview_avatar)) + .avatar(cx, ids!(preview_content.reply_preview_avatar)) .show_text(cx, None, None, "?"); replied_to_message_view - .html_or_plaintext(cx, ids!(replied_to_message_content.reply_preview_body)) + .html_or_plaintext(cx, ids!(preview_content.reply_preview_body)) .show_plaintext(cx, "[Error fetching replied-to event]"); } td @ TimelineDetails::Pending | td @ TimelineDetails::Unavailable => { // We don't have the replied-to message yet, so we can't fully draw the preview. fully_drawn = false; replied_to_message_view - .label(cx, ids!(replied_to_message_content.reply_preview_username)) + .label(cx, ids!(preview_content.reply_preview_username)) .set_text(cx, "[Loading username...]"); replied_to_message_view - .avatar(cx, ids!(replied_to_message_content.reply_preview_avatar)) + .avatar(cx, ids!(preview_content.reply_preview_avatar)) .show_text(cx, None, None, "?"); replied_to_message_view - .html_or_plaintext(cx, ids!(replied_to_message_content.reply_preview_body)) + .html_or_plaintext(cx, ids!(preview_content.reply_preview_body)) .show_plaintext(cx, "[Loading replied-to message...]"); // Confusingly, we need to fetch the details of the `message` (the event that is the reply), @@ -4742,6 +4784,9 @@ fn draw_replied_to_message( } replied_to_message_view.set_visible(cx, show_reply); + // After we changed a reply preview's content, we need to clear its cached view and measured height. + replied_to_message_view.view(cx, ids!(preview_content)).redraw_texture_cache(); + replied_to_message_view.as_collapsible_preview().reset_measured_height(); fully_drawn } @@ -5215,6 +5260,8 @@ pub enum MessageAction { /// indicating that they want to auto-scroll back to the related message, /// e.g., a replied-to message. JumpToRelated(MessageDetails), + /// The user clicked the "Show more" or "Show less" button on a tall reply preview. + ToggleReplyPreviewExpanded(TimelineEventItemId), /// The user clicked the thread summary on a thread-root message. OpenThread(OwnedEventId), /// The user requested to jump to a specific event in this room. @@ -5294,10 +5341,15 @@ impl Widget for Message { let Some(details) = self.details.clone() else { return }; - // We first handle a click on the replied-to message preview, if present, - // because we don't want any widgets within the replied-to message to be - // clickable or otherwise interactive. - match event.hits(cx, self.view(cx, ids!(replied_to_message)).area()) { + let reply = self.view.widget(cx, ids!(replied_to_message)).as_collapsible_preview(); + let reply_content_area = reply.content_area(cx); + match event.hits(cx, reply_content_area) { + Hit::FingerHoverIn(..) => { + self.animator_play(cx, ids!(hover.on)); + } + Hit::FingerHoverOut(_fho) => { + self.animator_play(cx, ids!(hover.off)); + } Hit::FingerDown(fe) if fe.device.mouse_button().is_some_and(|b| b.is_secondary()) => { cx.widget_action( details.room_screen_widget_uid, @@ -5309,19 +5361,22 @@ impl Widget for Message { } Hit::FingerLongPress(lp) => { cx.widget_action( - details.room_screen_widget_uid, + details.room_screen_widget_uid, MessageAction::OpenMessageContextMenu { details: details.clone(), abs_pos: lp.abs, } ); } - // If the hit occurred on the replied-to message preview, jump to it. Hit::FingerUp(fe) if fe.is_over && fe.is_primary_hit() && fe.was_tap() => { - cx.widget_action( - details.room_screen_widget_uid, - MessageAction::JumpToRelated(details.clone()), - ); + // Tapping on a collapsed reply preview expands it. + // Tapping on an expanded reply preview jumps to the replied-to message. + let action = if reply.is_collapsed() { + MessageAction::ToggleReplyPreviewExpanded(details.timeline_event_id.clone()) + } else { + MessageAction::JumpToRelated(details.clone()) + }; + cx.widget_action(details.room_screen_widget_uid, action); } _ => { } } @@ -5430,6 +5485,17 @@ impl Widget for Message { } } + // Handle clicks on the reply preview's "show more" or "show less" buttons. + let reply = self.view.widget(cx, ids!(replied_to_message)); + if reply.button(cx, ids!(reply_expand_button)).clicked(actions) + || reply.button(cx, ids!(reply_collapse_button)).clicked(actions) + { + cx.widget_action( + details.room_screen_widget_uid, + MessageAction::ToggleReplyPreviewExpanded(details.timeline_event_id.clone()), + ); + } + // Handle clicks on the "Download" button shown beneath media messages. if let Some(info) = self.download_info.as_ref() && self.view.button(cx, ids!(content.download_section.download_button)).clicked(actions) @@ -5474,6 +5540,7 @@ impl Message { details: MessageDetails, download_info: Option, download_state: DownloadDisplayState, + is_reply_expanded: bool, ) { let prev_section_visible = self.download_info.is_some(); let prev_state = self.download_state; @@ -5481,6 +5548,9 @@ impl Message { self.details = Some(details); self.download_info = download_info; + // Re-apply this every time to ensure a re-used portallist item is still correctly expanded. + self.view.widget(cx, ids!(replied_to_message)).as_collapsible_preview().set_expanded(is_reply_expanded); + let section_visible = self.download_info.is_some(); self.view.view(cx, ids!(content.download_section)).set_visible(cx, section_visible); if let Some(info) = self.download_info.as_ref() { @@ -5516,9 +5586,10 @@ impl MessageRef { details: MessageDetails, download_info: Option, download_state: DownloadDisplayState, + is_reply_expanded: bool, ) { let Some(mut inner) = self.borrow_mut() else { return }; - inner.set_data(cx, details, download_info, download_state); + inner.set_data(cx, details, download_info, download_state, is_reply_expanded); } } diff --git a/src/room/reply_preview.rs b/src/room/reply_preview.rs index c1f4b319d..1437a3852 100644 --- a/src/room/reply_preview.rs +++ b/src/room/reply_preview.rs @@ -1,7 +1,10 @@ //! Widgets that represent a preview of a message that was (or is being) replied to. //! -//! The core view is private, `ReplyPreviewContent`, which is used by both of the public views -//! exported by this module: `RepliedToMessage` and `ReplyingPreview`. +//! * `ReplyPreviewContent` is the main reply content: the avatar, username, and message body. +//! * `CollapsiblePreview` is a wrapper around that to limits tall reply previews +//! to a fixed height with a fade-out effect at the bottom. +//! * `RepliedToMessage` are collapsible reply previews in the timeline. +//! * `ReplyingPreview` is a non-collapsible reply preview in the RoomInputBar. use makepad_widgets::*; @@ -10,12 +13,25 @@ script_mod! { use mod.widgets.* - mod.widgets.ReplyPreviewContent = View { + // We render the reply preview content into a CachedView (an off-screen texture) + // so that we can apply a fade-to-transparent effect towards the bottom. + mod.widgets.ReplyPreviewContent = CachedView { width: Fill height: Fit flow: Down padding: Inset{left: 16.0, bottom: 5.0, top: 2.0, right: 11.0} cursor: MouseCursor.Hand, + draw_bg +: { + fade_start: uniform(1.0) + fade_end: uniform(1.0) + fade_enabled: uniform(0.0) + pixel: fn() { + let c = self.image.sample(self.pos * self.scale + self.shift) + let t = clamp((self.pos.y - self.fade_start) / max(self.fade_end - self.fade_start, 0.0001), 0.0, 1.0) + let f = 1.0 - t * t * (3.0 - 2.0 * t) + return c * mix(1.0, f, self.fade_enabled) + } + } View { width: Fill @@ -96,8 +112,73 @@ script_mod! { } } - // A view that shows a preview of the message that the user is currently drafting a reply to, - // along with a "Replying to" label and a cancel button. + // The show more button (to expand) and show less button (to collapse) a tall reply preview. + mod.widgets.ReplyToggleButton = RobrixIconButton { + visible: false + width: Fit, height: Fit + spacing: 4 + padding: Inset{ top: 4, bottom: 4, left: 8, right: 8 } + draw_icon +: { color: #666666 } + icon_walk: Walk{ width: 10, height: 10 } + draw_text +: { + text_style: theme.font_regular { font_size: 10.0, line_spacing: 1.2 } + color: #666666 + color_hover: #666666 + color_down: #666666 + } + draw_bg +: { + color: (COLOR_BG_PREVIEW) + color_hover: (COLOR_BG_PREVIEW_HOVER) + color_down: #A8DBBF + border_size: 1.0 + border_color: #CCCCCC + border_color_hover: #CCCCCC + border_color_down: #CCCCCC + border_radius: 4.0 + } + } + + // Wraps a reply preview in a collapsible view. + mod.widgets.CollapsiblePreview = set_type_default() do #(CollapsiblePreview::register_widget(vm)) { + visible: false + width: Fill + height: Fit + flow: Down + + preview_content := mod.widgets.ReplyPreviewContent { } + + // A vertical bar drawn along the left of a reply preview. + reply_left_bar := View { + visible: false + show_bg: true + draw_bg +: { + bar_color: instance((USERNAME_TEXT_COLOR)) + pixel: fn() { + return Pal.premul(self.bar_color) + } + } + } + + reply_expand_button := mod.widgets.ReplyToggleButton { + draw_icon +: { svg: (ICON_TRIANGLE_DOWN) } + text: "Show more…" + } + + reply_collapse_button := mod.widgets.ReplyToggleButton { + draw_icon +: { svg: (ICON_TRIANGLE_UP) } + text: "Show less" + } + } + + // A reply preview shown in the timeline/RoomScreen. + mod.widgets.RepliedToMessage = mod.widgets.CollapsiblePreview { + expandable: true + show_left_bar: true + padding: Inset{top: 0, right: 12, bottom: 0, left: 12} + } + + // A reply preview shown in the RoomInputBar above the message text input, + // which is only collapsed and cannot be expanded. mod.widgets.ReplyingPreview = View { visible: false width: Fill @@ -139,57 +220,191 @@ script_mod! { } } - reply_preview_content := mod.widgets.ReplyPreviewContent { } + reply_preview_content := mod.widgets.CollapsiblePreview { + visible: true + expandable: false + } LineH { - margin: Inset{top: 4.0, left: 5, right: 5} //, bottom: 10} + margin: Inset{top: 4, left: 5, right: 5} } } +} - // A small inline preview of a message that was replied to by another message - // within a room timeline. - // That is, this view contains a preview of the earlier message - // that is shown above the "in-reply-to" message. - mod.widgets.RepliedToMessage = View { - visible: false - width: Fill - height: Fit - flow: Down +/// If a reply preview exceeds this height, it will be dranw in a collapsed wrapper. +const REPLY_PREVIEW_FULL_SHOW_THRESHOLD: f64 = 150.0; - padding: Inset{top: 0.0, right: 12.0, bottom: 0.0, left: 12.0} +/// The height of a collapsed reply preview. +const REPLY_PREVIEW_COLLAPSED_HEIGHT: f64 = 100.0; - // A reply preview with a vertical bar drawn in the background. - replied_to_message_content := mod.widgets.ReplyPreviewContent { - show_bg: true - draw_bg +: { - color: instance(COLOR_TRANSPARENT) - vertical_bar_color: instance(USERNAME_TEXT_COLOR) - vertical_bar_width: instance(2.0) - border_radius: instance(0.0) +/// The height of the fade effect at the bottom of a collapsed preview. +const REPLY_PREVIEW_FADE_HEIGHT: f64 = 50.0; - pixel: fn() { - let sdf = Sdf2d.viewport(self.pos * self.rect_size); - - sdf.box( - 0.0, - 0.0, - self.rect_size.x, - self.rect_size.y, - max(1.0, self.border_radius) - ); - sdf.fill(self.color); - - sdf.rect( - 0.0, - 0.0, - self.vertical_bar_width, - self.rect_size.y - ); - sdf.fill(self.vertical_bar_color); - - return sdf.result; - } +/// Max height of a reply preview's cachedview texture. +const REPLY_PREVIEW_TEXTURE_MAX_HEIGHT: f64 = 160.0; + +/// Padding beneath the bottom of the reply preview's body. +const REPLY_PREVIEW_BODY_BOTTOM_PADDING: f64 = 10.0; + +/// The width of the left bar alongside a reply preview. +const REPLY_PREVIEW_BAR_WIDTH: f64 = 2.0; + +#[derive(Script, ScriptHook, Widget)] +pub struct CollapsiblePreview { + #[deref] view: View, + #[walk] walk: Walk, + #[redraw] #[area] #[rust] area: Area, + #[layout] layout: Layout, + /// Whether this collapsed preview can be expanded. + #[live] expandable: bool, + /// Whether to draw the vertical bar to the left of this in-timeline reply preview. + #[live] show_left_bar: bool, + #[rust] is_expanded: bool, + #[rust] collapsible: bool, + #[rust] last_drawn_height: f64, + #[rust] toggle_button_rect: Rect, +} + +impl Widget for CollapsiblePreview { + fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) { + self.view.handle_event(cx, event, scope); + } + + fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep { + let preview_content = self.view.view(cx, ids!(preview_content)); + let left_bar = self.view.widget(cx, ids!(reply_left_bar)); + + // We only use the off-screen cachedview for too-tall reply previews that should be collapsed, + // as they need the fade effect. Normal small reply previews just draw directly. + let predict_collapsed = self.last_drawn_height > REPLY_PREVIEW_FULL_SHOW_THRESHOLD + && !(self.expandable && self.is_expanded); + if let Some(mut inner) = preview_content.borrow_mut() { + let optimize = if predict_collapsed { ViewOptimize::Texture } else { ViewOptimize::None }; + inner.set_optimize(cx, optimize); + inner.set_texture_max_height(Some(REPLY_PREVIEW_TEXTURE_MAX_HEIGHT)); + } + + cx.begin_turtle( + walk, + Layout { flow: Flow::Down, clip_x: false, clip_y: false, ..self.layout }, + ); + cx.begin_turtle( + Walk { width: Size::fill(), height: Size::fit(), ..Walk::default() }, + Layout { flow: Flow::Down, clip_y: true, ..Layout::default() }, + ); + preview_content.draw_all(cx, scope); + let content_rect = preview_content.area().rect(cx); + let body_rect = self.view.widget(cx, ids!(preview_content.reply_preview_body)).area().rect(cx); + let used = cx.turtle().used(); + // Obtain the true height of the reply body to determine if it needs to be collapsed. + if body_rect.pos.y > content_rect.pos.y { + self.last_drawn_height = body_rect.pos.y + body_rect.size.y + + REPLY_PREVIEW_BODY_BOTTOM_PADDING - content_rect.pos.y; + } + self.collapsible = self.last_drawn_height > REPLY_PREVIEW_FULL_SHOW_THRESHOLD; + let collapsed = self.collapsible && !(self.expandable && self.is_expanded); + + // Only apply the fade effect if it was collapsed. + if predict_collapsed { + let (fade_start, fade_end, enabled) = if collapsed { + // Bottom fade band of the collapsed window, as fractions of the texture height. + ( + ((REPLY_PREVIEW_COLLAPSED_HEIGHT - REPLY_PREVIEW_FADE_HEIGHT) / used.y) as f32, + (REPLY_PREVIEW_COLLAPSED_HEIGHT / used.y) as f32, + 1.0, + ) + } else { + (1.0, 1.0, 0.0) + }; + if let Some(mut inner) = preview_content.borrow_mut() { + inner.draw_bg.set_uniform_on_area(cx, live_id!(fade_start), &[fade_start]); + inner.draw_bg.set_uniform_on_area(cx, live_id!(fade_end), &[fade_end]); + inner.draw_bg.set_uniform_on_area(cx, live_id!(fade_enabled), &[enabled]); } } + if collapsed { + cx.turtle_mut().set_used(used.x, REPLY_PREVIEW_COLLAPSED_HEIGHT); + } + let inner_rect = cx.end_turtle(); + if collapsed != predict_collapsed { + self.redraw(cx); + } + + // The "Show more"/"Show less" button is drawn below the content, + // with a left indent indented to align with the text. + self.toggle_button_rect = Rect::default(); + let expand_button = self.view.widget(cx, ids!(reply_expand_button)); + let collapse_button = self.view.widget(cx, ids!(reply_collapse_button)); + if self.collapsible && self.expandable { + let (shown, hidden) = if self.is_expanded { + (&collapse_button, &expand_button) + } else { + (&expand_button, &collapse_button) + }; + hidden.set_visible(cx, false); + shown.set_visible(cx, true); + let button_walk = Walk { + width: Size::fit(), + height: Size::fit(), + margin: Inset { left: body_rect.pos.x - inner_rect.pos.x, top: 4.0, ..Inset::default() }, + ..Walk::default() + }; + let _ = shown.draw_walk(cx, scope, button_walk); + self.toggle_button_rect = shown.area().rect(cx); + } else { + expand_button.set_visible(cx, false); + collapse_button.set_visible(cx, false); + } + + // Draw the left bar from the top of the reply content to the bottom of the show more button. + if self.show_left_bar { + left_bar.set_visible(cx, true); + let bar_bottom = if self.collapsible && self.expandable { + self.toggle_button_rect.pos.y + self.toggle_button_rect.size.y + } else { + content_rect.pos.y + content_rect.size.y + }; + let bar_walk = Walk { + abs_pos: Some(dvec2(content_rect.pos.x, content_rect.pos.y)), + width: Size::Fixed(REPLY_PREVIEW_BAR_WIDTH), + height: Size::Fixed((bar_bottom - content_rect.pos.y).max(0.0)), + ..Walk::default() + }; + let _ = left_bar.draw_walk(cx, scope, bar_walk); + } else { + left_bar.set_visible(cx, false); + } + + cx.end_turtle_with_area(&mut self.area); + DrawStep::done() + } +} + +impl CollapsiblePreviewRef { + /// Sets whether this preview should be expanded, but doesn't redraw anything. + pub fn set_expanded(&self, is_expanded: bool) { + if let Some(mut inner) = self.borrow_mut() { + inner.is_expanded = is_expanded; + } + } + + /// Clears the previously-calculated height of the reply preview. + pub fn reset_measured_height(&self) { + if let Some(mut inner) = self.borrow_mut() { + inner.last_drawn_height = 0.0; + } + } + + /// Whether the preview is currently collapsed. + pub fn is_collapsed(&self) -> bool { + self.borrow() + .map(|inner| inner.collapsible && inner.expandable && !inner.is_expanded) + .unwrap_or(false) + } + + /// Area of the inner reply preview content: avatar, username, and body. + pub fn content_area(&self, cx: &mut Cx) -> Area { + let Some(inner) = self.borrow() else { return Area::Empty }; + inner.view.widget(cx, ids!(preview_content)).area() } } diff --git a/src/room/room_input_bar.rs b/src/room/room_input_bar.rs index 7570ce33a..3277ec030 100644 --- a/src/room/room_input_bar.rs +++ b/src/room/room_input_bar.rs @@ -25,6 +25,7 @@ use ruma::events::room::message::AddMentions; use matrix_sdk_ui::timeline::{EmbeddedEvent, EventTimelineItem, TimelineEventItemId}; use ruma::{events::room::message::{LocationMessageEventContent, MessageType, ReplyWithinThread, RoomMessageEventContent}, OwnedEventId, OwnedRoomId}; use crate::{home::{editing_pane::{EditingPaneState, EditingPaneWidgetExt, EditingPaneWidgetRefExt}, location_preview::{LocationPreviewWidgetExt, LocationPreviewWidgetRefExt}, room_screen::{MessageAction, populate_preview_of_timeline_item}, tombstone_footer::{SuccessorRoomDetails, TombstoneFooterWidgetExt}, upload_progress::UploadProgressViewWidgetRefExt}, location::init_location_subscriber, settings::app_preferences::{AppPreferencesAction, AppPreferencesGlobal}, shared::{avatar::AvatarWidgetRefExt, file_upload_modal::{AttachmentUpload, FileUploadModalAction, FileUploadAttemptId, PreviewPayload, load_file_metadata}, html_or_plaintext::HtmlOrPlaintextWidgetRefExt, mentionable_text_input::{MentionableTextInputWidgetExt, MentionableTextInputWidgetRefExt, MentionableTextInputState}, popup_list::{PopupKind, enqueue_popup_notification}, room_input_popup_menu::RoomInputPopupMenuAction, styles::*}, sliding_sync::{MatrixRequest, TimelineKind, UserPowerLevels, submit_async_request}, utils}; +use crate::room::reply_preview::CollapsiblePreviewWidgetRefExt; script_mod! { use mod.prelude.widgets.* @@ -195,7 +196,7 @@ impl ScriptHook for RoomInputBar { impl Widget for RoomInputBar { fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) { - match event.hits(cx, self.view.view(cx, ids!(replying_preview.reply_preview_content)).area()) { + match event.hits(cx, self.view.widget(cx, ids!(replying_preview.reply_preview_content)).area()) { // If the hit occurred on the replying message preview, jump to it. Hit::FingerUp(fe) if fe.is_over && fe.is_primary_hit() && fe.was_tap() => { if let Some(event_id) = self.replying_to.as_ref() @@ -254,6 +255,10 @@ impl Widget for RoomInputBar { } } + self.view.view(cx, ids!(replying_preview)) + .widget(cx, ids!(reply_preview_content)) + .set_visible(cx, true); + self.view.draw_walk(cx, scope, walk) } @@ -466,7 +471,7 @@ impl RoomInputBar { // 1. Populate and show the ReplyingPreview, of course. let replying_preview = self.view(cx, ids!(replying_preview)); let (replying_preview_username, _) = replying_preview - .avatar(cx, ids!(reply_preview_content.reply_preview_avatar)) + .avatar(cx, ids!(reply_preview_content.preview_content.reply_preview_avatar)) .set_avatar_and_get_username( cx, timeline_kind, @@ -477,18 +482,22 @@ impl RoomInputBar { ); replying_preview - .label(cx, ids!(reply_preview_content.reply_preview_username)) + .label(cx, ids!(reply_preview_content.preview_content.reply_preview_username)) .set_text(cx, replying_preview_username.as_str()); populate_preview_of_timeline_item( cx, - &replying_preview.html_or_plaintext(cx, ids!(reply_preview_content.reply_preview_body)), + &replying_preview.html_or_plaintext(cx, ids!(reply_preview_content.preview_content.reply_preview_body)), replying_to.0.content(), replying_to.0.sender(), &replying_preview_username, ); replying_preview.set_visible(cx, true); + let reply_preview_content = replying_preview.widget(cx, ids!(reply_preview_content)); + reply_preview_content.set_visible(cx, true); + reply_preview_content.as_collapsible_preview().reset_measured_height(); + reply_preview_content.view(cx, ids!(preview_content)).redraw_texture_cache(); self.replying_to = Some(replying_to); // 2. Hide other views that are irrelevant to a reply, e.g., @@ -548,9 +557,10 @@ impl RoomInputBar { /// This should be invoked after the EditingPane has been fully hidden. fn on_editing_pane_hidden(&mut self, cx: &mut Cx) { - // Restore the replying_preview. + // Restore the replying_preview (which would've been hidden when the editing pane was shown). if self.was_replying_preview_visible && self.replying_to.is_some() { self.view.view(cx, ids!(replying_preview)).set_visible(cx, true); + self.view.widget(cx, ids!(replying_preview.reply_preview_content)).set_visible(cx, true); } self.redraw(cx); // We don't need to do anything with the editing pane itself here,