{% from "_macros.html" import icon, section_toggle %}
{#
A folder and everything under it. Recursive: a folder includes this same
template for each of its children, so nesting has no fixed depth limit.
Open/closed state is kept on the folder (`folder.collapsed`), written
by app.js as the toggle is pressed (`POST /api/preferences/section`, key
`folder:`) -- the same mechanism every other section heading uses. Kept
only in the browser (Alpine), a folder somebody shut would open again on the
next page, and on every out-of-band swap of the tree. The press is applied at once in the
browser; the post costs nothing anybody waits for.
Two shapes. A root folder (`nested` false, from `_sidebar_tree.html`)
is a section of the sidebar like `[ CHATS ]` and each device: its name in
brackets as the heading, which is what folds it, and its actions beside it in
the heading's own icon-button boxes. A child folder (`nested` true) is an
indented row under its parent. There is no `[ FOLDERS ]`
label above them all: a heading that names the kind of the headings
below it is a row that says nothing.
The + is always shown, as every section's is -- it is the one thing done
here most. Rename, settings and delete come up on hover or focus, the way a
chat row's actions do, so four boxes do not crowd the name out of a 17.5rem
sidebar; on a touchscreen they always show (`hover: none`, app.css).
#}
{% macro folder_actions(folder, box) -%}
{# Start a chat already filed here, and already carrying whatever the
folder seeds. Without this the only way into a folder is to make the
chat somewhere else and move it. #}
{{ icon("plus", "icon--sm") }}
{%- endmacro %}
{% macro folder_tools(folder, box) -%}
{{ icon("sliders", "icon--sm") }}
{%- endmacro %}
{% set body_id = "section-folder-" ~ folder.id %}
{% set is_open = not folder.collapsed %}
{#- The whole folder is a drop target for a chat (js/dnd.js): the nearest
one to the pointer wins, so a child folder inside it takes its own. -#}
{% if nested %}
{#- The chevron is inside this button, and the button uses the shared
section mechanism rather than a local flag. -#}
{{ folder_actions(folder, "") }}
{{ folder_tools(folder, "") }}
{% else %}
{#- `[ NAME ] ⌄` is one button, chevron included. A chevron beside the
button would leave pressing the arrow -- the part that says "this
folds" -- landing on a span with no handler. -#}
{{ section_toggle("folder:" ~ folder.id, folder.name, is_open, body_id, cls="folder__heading", title=folder.name) }}
{{ folder_tools(folder, "nav-group__add") }}
{#- On a phone (48rem and below) the three tools above are hidden
and this one box stands for them -- a menu of the same three actions,
carrying the same attributes, on the model picker's machinery
(`data-picker`, ui.js) as a device section's filter is. Three boxes
always drawn beside the + left a root folder's name one letter wide in
the drawer, and a phone has no hover to keep them out of the way. -#}
{% set more_label = t("More for the folder %(name)s", name=folder.name) %}
{# Bound once: the loop and the "Empty" check must be looking at the same
list, or a folder holding only archived chats claims to be empty while
showing them. Narrowed by the sidebar's switch, so a folder shows the
Chats side's kind only -- a folder is free to hold both, and its
agent chats are listed under their devices.
Every child folder, not only those holding this side's kind: on the
Chats side a child holding only agent chats is still a folder somebody
made, and with the Agents side showing no folders it would otherwise
be nowhere at all.
Without the switch (`sidebar_kind` "") every child showed already. #}
{% set listed = folder.visible_chats(sidebar_kind | default("")) %}
{% set shown = folder.children %}
{% for child in shown %}
{% with folder = child, nested = true %}
{% include "partials/_folder.html" %}
{% endwith %}
{% endfor %}
{% for chat_item in listed %}
{% include "partials/_chat_link.html" %}
{% endfor %}
{% if not shown and not listed %}