diff options
| author | Bobby <[email protected]> | 2025-12-24 12:44:33 +0530 |
|---|---|---|
| committer | Bobby <[email protected]> | 2025-12-24 12:44:33 +0530 |
| commit | 81ab367f440d6f85297b2013d0c1aa57fda7e9cd (patch) | |
| tree | 823a55ba7416d6df86e88bfdfad7925904c0c565 | |
| parent | 62cf64c4216a527334d4b9c312d144aaeec27ff9 (diff) | |
| download | lain-81ab367f440d6f85297b2013d0c1aa57fda7e9cd.tar.xz lain-81ab367f440d6f85297b2013d0c1aa57fda7e9cd.zip | |
refactor: Exclude virtual IMAP folders from processing and standardize template formatting.
| -rw-r--r-- | database/migrate.go | 1 | ||||
| -rw-r--r-- | repository/folders.go | 8 | ||||
| -rw-r--r-- | templates/auth/login.django | 38 | ||||
| -rw-r--r-- | templates/error.django | 12 | ||||
| -rw-r--r-- | templates/layouts/generic.django | 14 | ||||
| -rw-r--r-- | templates/layouts/mailbox.django | 16 | ||||
| -rw-r--r-- | templates/layouts/main.django | 100 | ||||
| -rw-r--r-- | templates/mail/folder.django | 2 | ||||
| -rw-r--r-- | templates/partials/filters.django | 53 | ||||
| -rw-r--r-- | templates/partials/footer.django | 4 | ||||
| -rw-r--r-- | templates/partials/navbar.django | 4 | ||||
| -rw-r--r-- | templates/partials/pane.django | 55 | ||||
| -rw-r--r-- | templates/partials/preview.django | 78 | ||||
| -rw-r--r-- | templates/partials/sidebar.django | 62 |
14 files changed, 209 insertions, 238 deletions
diff --git a/database/migrate.go b/database/migrate.go index 3ea96c1..0f1242f 100644 --- a/database/migrate.go +++ b/database/migrate.go @@ -7,6 +7,7 @@ func migrate() error { &models.Preferences{}, &models.Folder{}, &models.Email{}, + &models.Attachment{}, ) return err } diff --git a/repository/folders.go b/repository/folders.go index 0da58e0..20dcaa2 100644 --- a/repository/folders.go +++ b/repository/folders.go @@ -266,6 +266,10 @@ func syncFolders(userEmail string) error { foldersByName := make(map[string]uint) for i, imapFolder := range imapFolders { + if strings.HasPrefix(imapFolder.Name, "Virtual") || strings.Contains(imapFolder.Name, "/Virtual") { + continue + } + var folder models.Folder imapNameLower := strings.ToLower(imapFolder.Name) result := database.DB.Where("user_email = ? AND LOWER(imap_name) = ?", userEmail, imapNameLower).First(&folder) @@ -296,6 +300,10 @@ func syncFolders(userEmail string) error { } for _, imapFolder := range imapFolders { + if strings.HasPrefix(imapFolder.Name, "Virtual") || strings.Contains(imapFolder.Name, "/Virtual") { + continue + } + if strings.Contains(imapFolder.Name, "/") { parts := strings.Split(imapFolder.Name, "/") if len(parts) > 1 { diff --git a/templates/auth/login.django b/templates/auth/login.django index 1a75162..efb9505 100644 --- a/templates/auth/login.django +++ b/templates/auth/login.django @@ -1,26 +1,26 @@ {% extends 'layouts/generic.django' %} {% block content %} -<div class="login-page"> - <div class="login-container"> - <h1>{{ AppName }}</h1> - <p class="subtitle">{{ AppDescription }}</p> + <div class="login-page"> + <div class="login-container"> + <h1>{{ AppName }}</h1> + <p class="subtitle">{{ AppDescription }}</p> - {% if Error %} - <div class="error">{{ Error }}</div> - {% endif %} + {% if Error %} + <div class="error">{{ Error }}</div> + {% endif %} - <form method="POST" action="{% url 'auth.login' %}"> - <div class="field"> - <label>Email</label> - <input type="email" name="email" required autofocus /> - </div> + <form method="POST" action="{% url 'auth.login' %}"> + <div class="field"> + <label>Email</label> + <input type="email" name="email" required autofocus /> + </div> - <div class="field"> - <label>Password</label> - <input type="password" name="password" required /> - </div> + <div class="field"> + <label>Password</label> + <input type="password" name="password" required /> + </div> - <button type="submit">Login</button> - </form> + <button type="submit">Login</button> + </form> + </div> </div> -</div> {% endblock %} diff --git a/templates/error.django b/templates/error.django index 30700a4..b7473ae 100644 --- a/templates/error.django +++ b/templates/error.django @@ -1,9 +1,9 @@ {% extends 'layouts/generic.django' %} {% block content %} -<div class="error-page"> - <div class="error-container"> - <h1>{{ ErrorTitle }}</h1> - <p>{{ ErrorMessage }}</p> - <a href="{% url 'auth.login' %}">Go back home</a> + <div class="error-page"> + <div class="error-container"> + <h1>{{ ErrorTitle }}</h1> + <p>{{ ErrorMessage }}</p> + <a href="{% url 'auth.login' %}">Go back home</a> + </div> </div> -</div> {% endblock %} diff --git a/templates/layouts/generic.django b/templates/layouts/generic.django index 62f9091..2369e21 100644 --- a/templates/layouts/generic.django +++ b/templates/layouts/generic.django @@ -5,12 +5,20 @@ <title>{{ Title }}</title> <link rel="stylesheet" href="/static/css/main.css" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> - {% block head %} {% endblock %} + {% block head %} + + {% endblock %} </head> <body> {% block body %} - <main class="content">{% block content %} {% endblock %}</main> + <main class="content"> + {% block content %} + + {% endblock %} + </main> {% endblock %} {% include 'partials/footer.django' %} </body> - {% block scripts %} {% endblock %} + {% block scripts %} + + {% endblock %} </html> diff --git a/templates/layouts/mailbox.django b/templates/layouts/mailbox.django index f422c13..32a7c8f 100644 --- a/templates/layouts/mailbox.django +++ b/templates/layouts/mailbox.django @@ -1,9 +1,15 @@ {% extends 'layouts/main.django' %} {% block content %} -<div class="mailbox"> - <aside class="sidebar">{% include 'partials/sidebar.django' %}</aside> + <div class="mailbox"> + <aside class="sidebar"> + {% include 'partials/sidebar.django' %} + </aside> - <section class="pane">{% include 'partials/pane.django' %}</section> + <section class="pane"> + {% include 'partials/pane.django' %} + </section> - <section class="preview">{% include 'partials/preview.django' %}</section> -</div> + <section class="preview"> + {% include 'partials/preview.django' %} + </section> + </div> {% endblock %} diff --git a/templates/layouts/main.django b/templates/layouts/main.django index c3c45b9..2ca45fd 100644 --- a/templates/layouts/main.django +++ b/templates/layouts/main.django @@ -1,55 +1,55 @@ -{% extends 'layouts/generic.django' %} {% block body %} {% include -'partials/navbar.django' %} -<main>{% block content %} {% endblock %}</main> -{% endblock %} {% block scripts %} -<script> - document.addEventListener("DOMContentLoaded", function () { - // Handle dropdown clicks - document.querySelectorAll(".options-subitem > a").forEach(function (item) { - item.addEventListener("click", function (e) { - e.preventDefault(); - const parent = this.parentElement; - - if (parent.classList.contains("disabled")) { - return; - } +{% extends 'layouts/generic.django' %} {% block body %} + {% include 'partials/navbar.django' %} + <main> + {% block content %} - document - .querySelectorAll(".options-subitem.open") - .forEach(function (other) { + {% endblock %} + </main> +{% endblock %} {% block scripts %} + <script> + document.addEventListener('DOMContentLoaded', function () { + // Handle dropdown clicks + document.querySelectorAll('.options-subitem > a').forEach(function (item) { + item.addEventListener('click', function (e) { + e.preventDefault() + const parent = this.parentElement + + if (parent.classList.contains('disabled')) { + return + } + + document.querySelectorAll('.options-subitem.open').forEach(function (other) { if (other !== parent) { - other.classList.remove("open"); + other.classList.remove('open') } - }); - - parent.classList.toggle("open"); - }); - }); - - document.addEventListener("click", function (e) { - if (!e.target.closest(".options-subitem")) { - document - .querySelectorAll(".options-subitem.open") - .forEach(function (item) { - item.classList.remove("open"); - }); - } - }); - - // Toggle search filters - const toggleBtn = document.getElementById("toggle-filters"); - const filters = document.getElementById("search-filters"); - - if (toggleBtn && filters) { - toggleBtn.addEventListener("click", function (e) { - e.preventDefault(); - if (filters.style.display === "none") { - filters.style.display = "block"; - } else { - filters.style.display = "none"; + }) + + parent.classList.toggle('open') + }) + }) + + document.addEventListener('click', function (e) { + if (!e.target.closest('.options-subitem')) { + document.querySelectorAll('.options-subitem.open').forEach(function (item) { + item.classList.remove('open') + }) } - }); - } - }); -</script> + }) + + // Toggle search filters + const toggleBtn = document.getElementById('toggle-filters') + const filters = document.getElementById('search-filters') + + if (toggleBtn && filters) { + toggleBtn.addEventListener('click', function (e) { + e.preventDefault() + if (filters.style.display === 'none') { + filters.style.display = 'block' + } else { + filters.style.display = 'none' + } + }) + } + }) + </script> {% endblock %} diff --git a/templates/mail/folder.django b/templates/mail/folder.django index 4769203..91aa6f8 100644 --- a/templates/mail/folder.django +++ b/templates/mail/folder.django @@ -1,3 +1,3 @@ {% extends 'layouts/mailbox.django' %} {% block scripts %} -<script src="{% static 'js/filters.js' %}"></script> + <script src="{% static 'js/filters.js' %}"></script> {% endblock %} diff --git a/templates/partials/filters.django b/templates/partials/filters.django index 82e803b..148696e 100644 --- a/templates/partials/filters.django +++ b/templates/partials/filters.django @@ -15,13 +15,7 @@ </div> <div class="tag-input-container"> <div class="tags" id="from-tags"></div> - <input - type="text" - class="tag-input" - id="from-input" - placeholder="Add email..." - autocomplete="off" - /> + <input type="text" class="tag-input" id="from-input" placeholder="Add email..." autocomplete="off" /> <input type="hidden" name="from[]" id="from-hidden" /> </div> </div> @@ -37,13 +31,7 @@ </div> <div class="tag-input-container"> <div class="tags" id="to-tags"></div> - <input - type="text" - class="tag-input" - id="to-input" - placeholder="Add email..." - autocomplete="off" - /> + <input type="text" class="tag-input" id="to-input" placeholder="Add email..." autocomplete="off" /> <input type="hidden" name="to[]" id="to-hidden" /> </div> </div> @@ -59,12 +47,7 @@ <option value="endswith">ends</option> </select> </div> - <input - type="text" - name="subject" - class="filter-input" - placeholder="Search..." - /> + <input type="text" name="subject" class="filter-input" placeholder="Search..." /> </div> <div class="filter-section"> @@ -75,12 +58,7 @@ <option value="excludes">excludes</option> </select> </div> - <input - type="text" - name="body" - class="filter-input" - placeholder="Search..." - /> + <input type="text" name="body" class="filter-input" placeholder="Search..." /> </div> <div class="filter-section"> @@ -94,13 +72,7 @@ </div> <div class="tag-input-container"> <div class="tags" id="filename-tags"></div> - <input - type="text" - class="tag-input" - id="filename-input" - placeholder="Add filename..." - autocomplete="off" - /> + <input type="text" class="tag-input" id="filename-input" placeholder="Add filename..." autocomplete="off" /> <input type="hidden" name="filename[]" id="filename-hidden" /> </div> </div> @@ -157,14 +129,7 @@ <option value="all">All folders</option> <option value="custom">Custom folders</option> </select> - <input - type="text" - name="custom_folders" - class="filter-input" - placeholder="Folder1, Folder2..." - style="margin-top: 5px; display: none" - id="custom-folders-input" - /> + <input type="text" name="custom_folders" class="filter-input" placeholder="Folder1, Folder2..." style="margin-top: 5px; display: none" id="custom-folders-input" /> </div> <div class="filter-actions"> @@ -173,8 +138,4 @@ </div> </div> -<div - class="autocomplete-dropdown" - id="autocomplete-dropdown" - style="display: none" -></div> +<div class="autocomplete-dropdown" id="autocomplete-dropdown" style="display: none"></div> diff --git a/templates/partials/footer.django b/templates/partials/footer.django index 91c1a6f..ddb98fe 100644 --- a/templates/partials/footer.django +++ b/templates/partials/footer.django @@ -1,7 +1,5 @@ <footer> {{ AppName }} - Powered by {{ AppEngine }} - © - <a href="https://shi.foo" target="_blank" rel="noopener noreferrer"> - shi.foo - </a> + <a href="https://shi.foo" target="_blank" rel="noopener noreferrer">shi.foo</a> 2025 </footer> diff --git a/templates/partials/navbar.django b/templates/partials/navbar.django index 88097f7..7b18bc9 100644 --- a/templates/partials/navbar.django +++ b/templates/partials/navbar.django @@ -115,9 +115,7 @@ <div class="nav-search"> <form action="#" method="get"> <input type="text" name="q" placeholder="Search" class="search-input" /> - <button type="button" id="toggle-filters" class="btn-filters"> - Filters - </button> + <button type="button" id="toggle-filters" class="btn-filters">Filters</button> <button type="submit" class="btn-search">Search</button> {% include 'partials/filters.django' %} </form> diff --git a/templates/partials/pane.django b/templates/partials/pane.django index 8b231d9..20ddfcc 100644 --- a/templates/partials/pane.django +++ b/templates/partials/pane.django @@ -1,35 +1,34 @@ <div class="pane"> - {% if Emails %} {% for email in Emails %} - <div - class="email-row {% if not email.IsRead %}unread{% endif %} {% if email.Active %}active{% endif %}" - data-email-id="{{ email.ID }}" - > - <div class="email-checkbox"> - <input type="checkbox" /> - </div> + {% if Emails %} + {% for email in Emails %} + <div class="email-row {% if not email.IsRead %}unread{% endif %} {% if email.Active %}active{% endif %}" data-email-id="{{ email.ID }}"> + <div class="email-checkbox"> + <input type="checkbox" /> + </div> - <div class="email-flag {% if email.IsFlagged %}flagged{% endif %}"> - {% comment %} - <img src="{% static 'icons/flag.svg' %}" alt="Flag" /> - (We will write the static filter later){% endcomment %} - </div> + <div class="email-flag {% if email.IsFlagged %}flagged{% endif %}"> + {% comment %} + <img src="{% static 'icons/flag.svg' %}" alt="Flag" /> + (We will write the static filter later){% endcomment %} + </div> - <div class="email-info"> - <div class="email-from">{{ email.FromName }}</div> - <div class="email-subject">{{ email.Subject }}</div> - <div class="email-preview">{{ email.Preview }}</div> - </div> + <div class="email-info"> + <div class="email-from">{{ email.FromName }}</div> + <div class="email-subject">{{ email.Subject }}</div> + <div class="email-preview">{{ email.Preview }}</div> + </div> - <div class="email-meta"> - {% if email.HasAttachments %} - <span class="attachment-icon">📎</span> - {% endif %} - <span class="email-date">{{ email.Date }}</span> + <div class="email-meta"> + {% if email.HasAttachments %} + <span class="attachment-icon">📎</span> + {% endif %} + <span class="email-date">{{ email.Date }}</span> + </div> + </div> + {% endfor %} + {% else %} + <div class="empty-state"> + <p>No emails in this folder</p> </div> - </div> - {% endfor %} {% else %} - <div class="empty-state"> - <p>No emails in this folder</p> - </div> {% endif %} </div> diff --git a/templates/partials/preview.django b/templates/partials/preview.django index fbce3f2..d7aa00a 100644 --- a/templates/partials/preview.django +++ b/templates/partials/preview.django @@ -1,51 +1,49 @@ {% if Email %} -<div class="email-header"> - <h2 class="email-subject">{{ Email.Subject }}</h2> + <div class="email-header"> + <h2 class="email-subject">{{ Email.Subject }}</h2> - <div class="email-actions"> - <button class="btn-icon" title="Reply">↶</button> - <button class="btn-icon" title="Reply All">⇄</button> - <button class="btn-icon" title="Forward">→</button> - <button class="btn-icon" title="Archive">â–¼</button> - <button class="btn-icon" title="Delete">×</button> + <div class="email-actions"> + <button class="btn-icon" title="Reply">↶</button> + <button class="btn-icon" title="Reply All">⇄</button> + <button class="btn-icon" title="Forward">→</button> + <button class="btn-icon" title="Archive">â–¼</button> + <button class="btn-icon" title="Delete">×</button> + </div> </div> -</div> -<div class="email-sender"> - <div class="sender-info"> - <strong>{{ Email.FromName }}</strong> - <{{ Email.FromAddress }}> + <div class="email-sender"> + <div class="sender-info"> + <strong>{{ Email.FromName }}</strong> + <{{ Email.FromAddress }}> + </div> + <div class="email-date">{{ Email.Date }}</div> </div> - <div class="email-date">{{ Email.Date }}</div> -</div> -<div class="email-recipients"> - <div> - <strong>To:</strong> - {{ Email.To }} + <div class="email-recipients"> + <div> + <strong>To:</strong> + {{ Email.To }} + </div> + {% if Email.Cc %} + <div> + <strong>Cc:</strong> + {{ Email.Cc }} + </div> + {% endif %} </div> - {% if Email.Cc %} - <div> - <strong>Cc:</strong> - {{ Email.Cc }} - </div> - {% endif %} -</div> -{% if Email.Attachments %} -<div class="email-attachments"> - <strong>Attachments:</strong> - {% for attachment in Email.Attachments %} - <a href="#" class="attachment"> - {{ attachment.Filename }} ({{ attachment.Size }}) - </a> - {% endfor %} -</div> -{% endif %} + {% if Email.Attachments %} + <div class="email-attachments"> + <strong>Attachments:</strong> + {% for attachment in Email.Attachments %} + <a href="#" class="attachment">{{ attachment.Filename }} ({{ attachment.Size }})</a> + {% endfor %} + </div> + {% endif %} -<div class="email-body">{{ Email.Body|safe }}</div> + <div class="email-body">{{ Email.Body|safe }}</div> {% else %} -<div class="no-email-selected"> - <p>Select an email to view</p> -</div> + <div class="no-email-selected"> + <p>Select an email to view</p> + </div> {% endif %} diff --git a/templates/partials/sidebar.django b/templates/partials/sidebar.django index 4e829e5..12df271 100644 --- a/templates/partials/sidebar.django +++ b/templates/partials/sidebar.django @@ -1,46 +1,40 @@ <ul class="folder-list"> {% for folder in Folders %} - <li class="folder-item {% if folder.Active %}active{% endif %}"> - <a href="/mail/{{ folder.IMAPName|lower }}"> - <img - src="{% if folder.Active %} + <li class="folder-item {% if folder.Active %}active{% endif %}"> + <a href="/mail/{{ folder.IMAPName|lower }}"> + <img src="{% if folder.Active %} {{ folder.IconOpen }} {% else %} {{ folder.IconClose }} {% endif %}" - alt="{{ folder.Name }}" - class="folder-icon" - /> - <span class="folder-name">{{ folder.Name }}</span> - {% if folder.UnreadCount > 0 %} - <span class="folder-count">{{ folder.UnreadCount }}</span> - {% endif %} - </a> - {% if folder.Subfolders %} - <ul class="subfolder-list"> - {% for subfolder in folder.Subfolders %} - <li - class="folder-item subfolder {% if subfolder.Active %}active{% endif %}" - > - <a href="/mail/{{ subfolder.IMAPName|lower }}"> - <img - src="{% if subfolder.Active %} + alt="{{ folder.Name }}" + class="folder-icon" /> + <span class="folder-name">{{ folder.Name }}</span> + {% if folder.UnreadCount > 0 %} + <span class="folder-count">{{ folder.UnreadCount }}</span> + {% endif %} + </a> + {% if folder.Subfolders %} + <ul class="subfolder-list"> + {% for subfolder in folder.Subfolders %} + <li class="folder-item subfolder {% if subfolder.Active %}active{% endif %}"> + <a href="/mail/{{ subfolder.IMAPName|lower }}"> + <img src="{% if subfolder.Active %} {{ subfolder.IconOpen }} {% else %} {{ subfolder.IconClose }} {% endif %}" - alt="{{ subfolder.Name }}" - class="folder-icon" - /> - <span class="folder-name">{{ subfolder.Name }}</span> - {% if subfolder.UnreadCount > 0 %} - <span class="folder-count">{{ subfolder.UnreadCount }}</span> - {% endif %} - </a> - </li> - {% endfor %} - </ul> - {% endif %} - </li> + alt="{{ subfolder.Name }}" + class="folder-icon" /> + <span class="folder-name">{{ subfolder.Name }}</span> + {% if subfolder.UnreadCount > 0 %} + <span class="folder-count">{{ subfolder.UnreadCount }}</span> + {% endif %} + </a> + </li> + {% endfor %} + </ul> + {% endif %} + </li> {% endfor %} </ul> |
