fix(ux): optimize event lists and fix editor line wrapping
- Implemented 'Details' toggle in Session lists to defer expensive presenter/file sub-component renders, improving initial hydration speed. - Fixed line-wrapping for long lines in Journals Editor (both plain textarea and CodeMirror). - Updated TODO.md and GEMINI.md to reflect Journals standardization and performance optimizations.
This commit is contained in:
@@ -75,12 +75,16 @@ This project is the frontend UI/UX for the Aether (AE) system, built with Svelte
|
|||||||
---
|
---
|
||||||
|
|
||||||
## 🧠 Session Context (2026-01-26)
|
## 🧠 Session Context (2026-01-26)
|
||||||
- **Status:** Performance Sprint Complete. Moving to IDAA Module Audit.
|
- **Status:** Performance Sprint & Journals Standardization Complete.
|
||||||
- **Recent Actions:**
|
- **Recent Actions:**
|
||||||
- Eliminated page load delays via SWR and non-blocking background refreshes.
|
- Eliminated page load delays via SWR and non-blocking background refreshes.
|
||||||
|
- Standardized Journals module: renamed all components to `ae_comp__*`, normalized props to snake_case, and unified icons under `lucide-svelte`.
|
||||||
|
- Fixed line-wrapping issues in both plain and CodeMirror editors.
|
||||||
|
- Optimized Event Session list rendering with a "Details" toggle to defer expensive sub-components.
|
||||||
- Hardened Service Worker and suppressed aborted fetch logs.
|
- Hardened Service Worker and suppressed aborted fetch logs.
|
||||||
- Finalized Native Launcher Phase 5 automation and Telemetry UI.
|
- Finalized Native Launcher Phase 5 automation and Telemetry UI.
|
||||||
- **Pending Tasks:**
|
- **Pending Tasks:**
|
||||||
|
- [ ] Refactor `get_device_config` to be non-blocking in root layout.
|
||||||
- [ ] Audit IDAA pages for reported issues.
|
- [ ] Audit IDAA pages for reported issues.
|
||||||
- [ ] Restore Exhibit Search functionality.
|
- [ ] Restore Exhibit Search functionality.
|
||||||
- [ ] Build standalone Payload Validation tool.
|
- [ ] Build standalone Payload Validation tool.
|
||||||
|
|||||||
3
TODO.md
3
TODO.md
@@ -47,6 +47,9 @@ This is a list of tasks to be completed before the next event/show/conference.
|
|||||||
|
|
||||||
## Recent Accomplishments (Jan 26, 2026)
|
## Recent Accomplishments (Jan 26, 2026)
|
||||||
- [x] **Performance:** Eliminated "white page" delay on refresh across all major modules.
|
- [x] **Performance:** Eliminated "white page" delay on refresh across all major modules.
|
||||||
|
- [x] **Journals Standardization:** Renamed all components to `ae_comp__*`, normalized props to snake_case, and migrated to `lucide-svelte`.
|
||||||
|
- [x] **Editor UX:** Fixed line-wrapping for long lines in both plain textarea and CodeMirror editors.
|
||||||
|
- [x] **Event Optimization:** Implemented "Details" toggle in Session lists to defer expensive presenter/file renders.
|
||||||
- [x] **Native Bridge:** Completed specialized macOS handlers for remote presentation control.
|
- [x] **Native Bridge:** Completed specialized macOS handlers for remote presentation control.
|
||||||
- [x] **Stability:** Resolved duplicate export errors and script evaluation failures in Service Worker.
|
- [x] **Stability:** Resolved duplicate export errors and script evaluation failures in Service Worker.
|
||||||
|
|
||||||
|
|||||||
@@ -173,17 +173,13 @@
|
|||||||
/* overflow: auto; */
|
/* overflow: auto; */
|
||||||
/* background-color: var(--cm-background); */
|
/* background-color: var(--cm-background); */
|
||||||
|
|
||||||
/* text-wrap: normal; */
|
text-wrap: wrap;
|
||||||
/* text-wrap: balance; */
|
overflow-wrap: break-word;
|
||||||
/* text-wrap: wrap; */
|
|
||||||
/* text-wrap: break-word; */
|
|
||||||
}
|
}
|
||||||
.codemirror-wrapper :global(.cm-editor) {
|
.codemirror-wrapper :global(.cm-editor) {
|
||||||
/* font-size: .8rem; */
|
/* font-size: .8rem; */
|
||||||
/* text-wrap: normal; */
|
text-wrap: wrap;
|
||||||
/* text-wrap: balance; */
|
overflow-wrap: break-word;
|
||||||
/* text-wrap: wrap; */
|
|
||||||
/* text-wrap: break-word; */
|
|
||||||
|
|
||||||
/* max-width: 100%; */
|
/* max-width: 100%; */
|
||||||
/* max-height: 100%; */
|
/* max-height: 100%; */
|
||||||
|
|||||||
@@ -77,8 +77,12 @@
|
|||||||
let ae_tmp: key_val = $state({});
|
let ae_tmp: key_val = $state({});
|
||||||
let ae_triggers: key_val = $state({});
|
let ae_triggers: key_val = $state({});
|
||||||
let trigger_reload_session_id: string = $state('');
|
let trigger_reload_session_id: string = $state('');
|
||||||
|
let show_details_kv: Record<string, boolean> = $state({});
|
||||||
|
|
||||||
// *** Functions and Logic
|
// *** Functions and Logic
|
||||||
|
function toggle_details(id: string) {
|
||||||
|
show_details_kv[id] = !show_details_kv[id];
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- xs:max-w-sm lg:max-w-100 -->
|
<!-- xs:max-w-sm lg:max-w-100 -->
|
||||||
@@ -143,74 +147,91 @@
|
|||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<a
|
<div class="flex flex-col gap-1">
|
||||||
href="/events/{session_obj?.event_id}/session/{session_obj?.event_session_id}"
|
<div class="flex items-center gap-1">
|
||||||
class="
|
<a
|
||||||
btn
|
href="/events/{session_obj?.event_id}/session/{session_obj?.event_session_id}"
|
||||||
ae_btn_secondary_filled
|
class="
|
||||||
min-w-full max-w-md
|
btn
|
||||||
sm:w-80
|
ae_btn_secondary_filled
|
||||||
text-xs/3 sm:text-xs/4 md:text-xs/4 lg:text-sm/4 xl:text-base/5
|
grow max-w-md
|
||||||
md:max-w-xs
|
text-xs/3 sm:text-xs/4 md:text-xs/4 lg:text-sm/4 xl:text-base/5
|
||||||
sm:btn-sm
|
md:max-w-xs
|
||||||
md:btn-md
|
sm:btn-sm
|
||||||
"
|
md:btn-md
|
||||||
title={`Code = ${session_obj?.code}\n${session_obj?.name}\nID = ${session_obj?.event_session_id}\nDay = ${ae_util.iso_datetime_formatter(session_obj?.start_datetime, 'dddd')}\nStart = ${ae_util.iso_datetime_formatter(session_obj?.start_datetime, 'time_12_short')}\nEnd = ${ae_util.iso_datetime_formatter(session_obj?.end_datetime, 'time_12_short')}\nLocation = ${session_obj?.event_location_name}`}
|
"
|
||||||
>
|
title={`Code = ${session_obj?.code}\n${session_obj?.name}\nID = ${session_obj?.event_session_id}\nDay = ${ae_util.iso_datetime_formatter(session_obj?.start_datetime, 'dddd')}\nStart = ${ae_util.iso_datetime_formatter(session_obj?.start_datetime, 'time_12_short')}\nEnd = ${ae_util.iso_datetime_formatter(session_obj?.end_datetime, 'time_12_short')}\nLocation = ${session_obj?.event_location_name}`}
|
||||||
<!-- <span class="fas fa-eye m-0.25 text-xs text-surface-800-200"></span> -->
|
|
||||||
<span
|
|
||||||
class="fas fa-chalkboard-teacher m-0.25 text-xs text-neutral-800/50"
|
|
||||||
></span>
|
|
||||||
<!-- overflow-x-scroll -->
|
|
||||||
<span
|
|
||||||
class="
|
|
||||||
grow overflow-hidden text-wrap text-left
|
|
||||||
max-h-12 sm:max-h-12 md:max-h-9 lg:max-h-12 xl:max-h-16
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<!-- <div> -->
|
|
||||||
<strong>{session_obj?.name}</strong>
|
|
||||||
<!-- </div> -->
|
|
||||||
</span>
|
|
||||||
{#if session_obj?.file_count_all}
|
|
||||||
<span
|
|
||||||
class="badge preset-tonal-success hover:preset-filled-success-500"
|
|
||||||
title="{session_obj?.file_count_all}× files under session"
|
|
||||||
>
|
>
|
||||||
<span class="fas fa-file-alt mx-1"></span>
|
<!-- <span class="fas fa-eye m-0.25 text-xs text-surface-800-200"></span> -->
|
||||||
{session_obj?.file_count_all}×
|
<span
|
||||||
</span>
|
class="fas fa-chalkboard-teacher m-0.25 text-xs text-neutral-800/50"
|
||||||
{:else}
|
></span>
|
||||||
<!-- Nothing -->
|
<!-- overflow-x-scroll -->
|
||||||
|
<span
|
||||||
|
class="
|
||||||
|
grow overflow-hidden text-wrap text-left
|
||||||
|
max-h-12 sm:max-h-12 md:max-h-9 lg:max-h-12 xl:max-h-16
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<!-- <div> -->
|
||||||
|
<strong>{session_obj?.name}</strong>
|
||||||
|
<!-- </div> -->
|
||||||
|
</span>
|
||||||
|
{#if session_obj?.file_count_all}
|
||||||
|
<span
|
||||||
|
class="badge preset-tonal-success hover:preset-filled-success-500"
|
||||||
|
title="{session_obj?.file_count_all}× files under session"
|
||||||
|
>
|
||||||
|
<span class="fas fa-file-alt mx-1"></span>
|
||||||
|
{session_obj?.file_count_all}×
|
||||||
|
</span>
|
||||||
|
{:else}
|
||||||
|
<!-- Nothing -->
|
||||||
|
{/if}
|
||||||
|
</a>
|
||||||
|
|
||||||
|
{#if (show__session_presentations || show__session_files) && $ae_loc.manager_access}
|
||||||
|
<button
|
||||||
|
class="btn btn-icon btn-sm variant-soft-surface"
|
||||||
|
onclick={() => toggle_details(session_obj.event_session_id)}
|
||||||
|
title="Toggle Presenters & Files"
|
||||||
|
>
|
||||||
|
<span class="fas fa-chevron-{show_details_kv[session_obj.event_session_id] ? 'up' : 'down'}"></span>
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if show_details_kv[session_obj.event_session_id]}
|
||||||
|
<div class="p-2 bg-surface-500/5 rounded-lg border border-surface-500/10 mt-1 animate-fade-in">
|
||||||
|
{#if show__session_presentations && $ae_loc.manager_access}
|
||||||
|
<Comp_event_presenter_obj_li
|
||||||
|
link_to_type={'event_session'}
|
||||||
|
link_to_id={session_obj?.event_session_id}
|
||||||
|
display_mode={'minimal'}
|
||||||
|
{log_lvl}
|
||||||
|
></Comp_event_presenter_obj_li>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if show__session_files && $ae_loc.manager_access}
|
||||||
|
<Element_manage_event_file_li
|
||||||
|
link_to_type={'event_session'}
|
||||||
|
link_to_id={session_obj?.event_session_id}
|
||||||
|
allow_basic={$events_loc.auth__kv.session[
|
||||||
|
$events_slct.event_session_id
|
||||||
|
] ||
|
||||||
|
$events_loc.auth__kv.presenter[
|
||||||
|
$events_slct.event_presenter_id
|
||||||
|
]}
|
||||||
|
allow_moderator={$events_loc.auth__kv.session[
|
||||||
|
$events_slct.event_session_id
|
||||||
|
]}
|
||||||
|
container_class_li={''}
|
||||||
|
display_mode={'minimal'}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</a>
|
</div>
|
||||||
|
|
||||||
{#if show__session_presentations && $ae_loc.manager_access}
|
|
||||||
<Comp_event_presenter_obj_li
|
|
||||||
link_to_type={'event_session'}
|
|
||||||
link_to_id={session_obj?.event_session_id}
|
|
||||||
display_mode={'minimal'}
|
|
||||||
{log_lvl}
|
|
||||||
></Comp_event_presenter_obj_li>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if show__session_files && $ae_loc.manager_access}
|
|
||||||
<Element_manage_event_file_li
|
|
||||||
link_to_type={'event_session'}
|
|
||||||
link_to_id={session_obj?.event_session_id}
|
|
||||||
allow_basic={$events_loc.auth__kv.session[
|
|
||||||
$events_slct.event_session_id
|
|
||||||
] ||
|
|
||||||
$events_loc.auth__kv.presenter[
|
|
||||||
$events_slct.event_presenter_id
|
|
||||||
]}
|
|
||||||
allow_moderator={$events_loc.auth__kv.session[
|
|
||||||
$events_slct.event_session_id
|
|
||||||
]}
|
|
||||||
container_class_li={''}
|
|
||||||
display_mode={'minimal'}
|
|
||||||
/>
|
|
||||||
{/if}
|
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="flex flex-col text-xs lg:text-sm">
|
<span class="flex flex-col text-xs lg:text-sm">
|
||||||
|
|||||||
@@ -84,7 +84,7 @@
|
|||||||
{:else}
|
{:else}
|
||||||
<textarea
|
<textarea
|
||||||
bind:value={tmp_entry_obj.content}
|
bind:value={tmp_entry_obj.content}
|
||||||
class="textarea grow w-full max-w-6xl p-4 font-mono shadow-lg rounded-lg border-orange-500/30 h-[500px]"
|
class="textarea grow w-full max-w-6xl p-4 font-mono shadow-lg rounded-lg border-orange-500/30 h-[500px] whitespace-pre-wrap break-words"
|
||||||
placeholder="Edit content..."
|
placeholder="Edit content..."
|
||||||
></textarea>
|
></textarea>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
Reference in New Issue
Block a user