Nice little directory browser :D
at master 173 lines 4.6 kB view raw
1@* 2 This file is part of Utatane. 3 4 Utatane is free software: you can redistribute it and/or modify it under 5 the terms of the GNU Affero General Public License as published by the Free 6 Software Foundation, either version 3 of the License, or (at your option) 7 any later version. 8 9 Utatane is distributed in the hope that it will be useful, but WITHOUT ANY 10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 11 FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for 12 more details. 13 14 You should have received a copy of the GNU Affero General Public License 15 along with Utatane. If not, see <http://www.gnu.org/licenses/>. 16*@ 17 18@page "/{*Path:nonfile}" 19 20@* <PageTitle>Index</PageTitle> *@ 21<HeadContent> 22 <script src="/.nhnd/_hyperscript.js"></script> 23 <script src="/.nhnd/_hs_tailwind.js"></script> 24 25 <script type="text/hyperscript"> 26def get_dir(x) 27 if not x 28 return "descending" 29 otherwise 30 return "ascending" 31 end 32end 33 34behavior sort_table(property) 35 on click 36 -- wait 0.1s 37 remove @@aria-sort from <th/> 38 39 set target to the first <#prop-${property}/> 40 set dir_target to the first <input[name="sort-asc"]/> 41 42 if (target's checked is true) 43 set dir_target's checked to (not dir_target's checked) 44 otherwise 45 set <input[name=sort-by]/>'s checked to false 46 set dir_target's checked to true 47 set target's checked to true 48 end 49 50 set my @@aria-sort to get_dir((dir_target's checked)) 51 send nhnd:run to me 52 end 53end 54 </script> 55</HeadContent> 56 57<Header Path="@Path" /> 58 59@* redirect notice here... *@ 60 61<div class="n-box flex flex-row"> 62 <div id="main"> 63 <form id="sorting-on" class="hidden"> 64 <input autocomplete="off" type="text" name="path" value="@Path" id="prop-path" /> 65 66 <input autocomplete="off" type="radio" name="sort-by" value="name" id="prop-name" checked/> 67 <input autocomplete="off" type="radio" name="sort-by" value="size" id="prop-size"/> 68 <input autocomplete="off" type="radio" name="sort-by" value="time" id="prop-time"/> 69 70 <input autocomplete="off" type="checkbox" name="sort-asc" checked/> 71 </form> 72 73 <table 74 id="filetable" 75 hx-swap="innerHtml" 76 hx-target="#filetable tbody" 77 hx-include="#sorting-on input" 78 hx-select="table tbody tr" 79 _="on htmx:afterSettle send nhnd:update to #file-counter" 80 > 81 <thead> 82 <tr> 83 @{ String InstallSort(String x) => $"install sort_table(property: '{x}') end"; } 84 <th id="filetable-head-dl" class="pointer-events-none" tabindex="0"> 85 <span class="visually-hidden">Download link</span> 86 </th> 87 88 <th id="filetable-head-icon" class="pointer-events-none" tabindex="0"> 89 <span class="visually-hidden">File type icon</span> 90 </th> 91 92 <th id="filetable-head-name" 93 hx-get="/api/files" 94 hx-trigger="load from:document, nhnd:run" 95 hx-indicator="#filetable-body, #name-spinner, #filetable-head-name" 96 aria-sort="ascending" 97 _="@InstallSort("name")" 98 > 99 <div> 100 <span class="header-label"> 101 Name 102 <span id="name-spinner" class="spinner" /> 103 </span> 104 </div> 105 </th> 106 107 <th id="filetable-head-size" 108 hx-get="/api/files" 109 hx-trigger="nhnd:run" 110 hx-indicator="#filetable-body, #name-spinner, #filetable-head-size" 111 _="@InstallSort("size")" 112 > 113 <div> 114 <span class="header-label"> 115 Size 116 <span id="size-spinner" class="spinner" /> 117 </span> 118 </div> 119 </th> 120 121 <th id="filetable-head-time" 122 hx-get="/api/files" 123 hx-trigger="nhnd:run" 124 hx-indicator="#filetable-body, #name-spinner, #filetable-head-time" 125 _="@InstallSort("time")" 126 > 127 <div> 128 <span class="header-label"> 129 Time 130 <span id="time-spinner" class="spinner" /> 131 </span> 132 </div> 133 </th> 134 </tr> 135 </thead> 136 <tbody id="filetable-body" 137 class="htmx-indicator" 138 hx-swap="scroll:top" 139 _="on htmx:beforeRequest(target) set #prop-path's value to the target" 140 > 141 @* pregen rows to prevent massive layout shift *@ 142 @foreach (FileSystemInfo fsi in _joinedPath.EnumerateFileSystemInfos()) { 143 <tr> 144 <td /> 145 <td /> 146 <td>@( "\u00A0" )</td> 147 <td /> 148 <td /> 149 </tr> 150 } 151 </tbody> 152 </table> 153 </div> 154</div> 155 156 157@code { 158 [Parameter] 159 public required String Path { 160 get; 161 set => field = $"/{value}"; 162 } 163 164 private DirectoryInfo _joinedPath; 165 166 protected override Task OnInitializedAsync() { 167 // we checked in middleware dw 168 _joinedPath = Utils.VerifyPath(Path).Value.AsT1(); 169 170 return base.OnInitializedAsync(); 171 } 172 173}