TrashView.tsx

6.2 KB · raw

1import { createSignal, For, onMount, Show } from "solid-js";2import type { VaultEntry } from "../../shared/types";3import { sendMessage } from "../App";45interface TrashViewProps {6  onBack: () => void;7  onRestored: () => void;8}910export function TrashView(props: TrashViewProps) {11  const [deleted, setDeleted] = createSignal<VaultEntry[]>([]);12  const [loading, setLoading] = createSignal(true);13  const [confirmPurgeId, setConfirmPurgeId] = createSignal<string | null>(null);14  const [confirmPurgeAll, setConfirmPurgeAll] = createSignal(false);1516  onMount(async () => {17    await reload();18  });1920  async function reload() {21    setLoading(true);22    const res = await sendMessage({ type: "GET_DELETED_ENTRIES" });23    setDeleted((res as { ok: boolean; data?: VaultEntry[] }).data ?? []);24    setLoading(false);25  }2627  async function restore(id: string) {28    await sendMessage({ type: "RESTORE_ENTRY", payload: { id } });29    props.onRestored();30    await reload();31  }3233  async function purge(id: string) {34    await sendMessage({ type: "PURGE_ENTRY", payload: { id } });35    setConfirmPurgeId(null);36    await reload();37  }3839  async function purgeAll() {40    for (const entry of deleted()) {41      await sendMessage({ type: "PURGE_ENTRY", payload: { id: entry.id } });42    }43    setConfirmPurgeAll(false);44    await reload();45  }4647  function formatDate(ts?: number): string {48    if (!ts) return "";49    return new Date(ts).toLocaleDateString(undefined, { month: "short", day: "numeric" });50  }5152  return (53    <div class="peach-overlay-view ov-enter-right" style="display:flex">54      <div class="peach-overlay-header">55        <button56          class="peach-btn peach-btn--ghost peach-btn--sm peach-icon-btn"57          onClick={props.onBack}58          aria-label="Back"59        >60          <svg width="7" height="12" viewBox="0 0 7 12" fill="none" stroke="currentColor" stroke-width="1.1" stroke-linecap="round" stroke-linejoin="round">61            <path d="M6 1L1 6L6 11" />62          </svg>63        </button>64        <span class="peach-overlay-title">trash</span>65        <div class="peach-overlay-spacer" />66      </div>6768      <div class="peach-settings-body">69        <Show when={loading()}>70          <div class="peach-list-empty"><span>loading...</span></div>71        </Show>7273        <Show when={!loading() && deleted().length === 0}>74          <div class="peach-list-empty" style="padding:32px 20px;">75            <span style="font-size:13px;color:var(--t1);">trash is empty</span>76          </div>77        </Show>7879        <Show when={!loading() && deleted().length > 0}>80          <div class="peach-settings-group peach-trash-list">81            <p class="peach-settings-label">82              {deleted().length} deleted {deleted().length === 1 ? "entry" : "entries"}83            </p>8485            <For each={deleted()}>86              {(entry) => (87                <div class="peach-trash-entry-row">88                  <div class="peach-trash-entry-info">89                    <span class="peach-trash-entry-title">{entry.title}</span>90                    <span class="peach-trash-entry-meta">91                      deleted {formatDate(entry.deletedAt)}92                      {entry.url ? ` · ${entry.url.replace(/^https?:\/\//, "").split("/")[0]}` : ""}93                    </span>94                  </div>95                  <div class="peach-trash-entry-actions">96                    <button97                      class="peach-btn peach-btn--subtle peach-btn--sm"98                      style="font-size:10px"99                      onClick={() => void restore(entry.id)}100                    >101                      restore102                    </button>103                    <Show104                      when={confirmPurgeId() === entry.id}105                      fallback={106                        <button107                          class="peach-btn peach-btn--ghost peach-btn--sm"108                          style="font-size:10px;color:var(--peach-breach)"109                          onClick={() => setConfirmPurgeId(entry.id)}110                        >111                          delete112                        </button>113                      }114                    >115                      <button116                        class="peach-btn peach-btn--sm peach-btn--danger"117                        style="font-size:10px"118                        onClick={() => void purge(entry.id)}119                      >120                        confirm121                      </button>122                      <button123                        class="peach-btn peach-btn--ghost peach-btn--sm"124                        style="font-size:10px"125                        onClick={() => setConfirmPurgeId(null)}126                      >127                        ×128                      </button>129                    </Show>130                  </div>131                </div>132              )}133            </For>134          </div>135136          <div class="peach-settings-group">137            <div class="peach-settings-row peach-settings-row--meta">138              <Show139                when={confirmPurgeAll()}140                fallback={141                  <button142                    class="peach-btn peach-btn--ghost peach-btn--sm"143                    style="color:var(--peach-breach);font-size:11px"144                    onClick={() => setConfirmPurgeAll(true)}145                  >146                    permanently delete all147                  </button>148                }149              >150                <span style="font-size:11px;color:var(--t1)">delete all permanently?</span>151                <button152                  class="peach-btn peach-btn--sm peach-btn--danger"153                  style="font-size:10px"154                  onClick={() => void purgeAll()}155                >156                  yes, delete all157                </button>158                <button159                  class="peach-btn peach-btn--ghost peach-btn--sm"160                  style="font-size:10px"161                  onClick={() => setConfirmPurgeAll(false)}162                >163                  cancel164                </button>165              </Show>166            </div>167          </div>168169          <div class="peach-info-notice peach-trash-notice">170            Deleted entries are auto-removed based on your trash retention setting.171          </div>172        </Show>173      </div>174    </div>175  );176}