Skip to content

Commit 96e15b5

Browse files
error311nikp123
andauthored
release(v3.1.2): configurable ignore rules for indexing/tree + admin UX polish (fixes #91, refs #92)
- add ignoreRegex setting (admin config) with env override FR_IGNORE_REGEX to hide folders from tree/counts/indexing - add snapshot preset helper for common NAS snapshot paths (fixes #91) - unify ignore logic via FS::shouldIgnoreEntry across folder counts, tree listing, and disk usage scans - admin: improve settings search UX (clear button) + smoother section header styling - UI: polish header dock collapse/expand icon animations (landing/lift + reduced-motion support) Fixes #91 Refs #92 Co-authored-by: nikp123 <nikp123@e.email>
1 parent daa8815 commit 96e15b5

10 files changed

Lines changed: 660 additions & 65 deletions

File tree

CHANGELOG.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,61 @@
11
# Changelog
22

3+
## Changes 01/20/2026 (v3.1.2)
4+
5+
`release(v3.1.2): configurable ignore rules for indexing/tree + admin UX polish (fixes #91, refs #92)`
6+
7+
**Commit message**
8+
9+
```text
10+
release(v3.1.2): configurable ignore rules for indexing/tree + admin UX polish (fixes #91, refs #92)
11+
12+
- add ignoreRegex setting (admin config) with env override FR_IGNORE_REGEX to hide folders from tree/counts/indexing
13+
- add snapshot preset helper for common NAS snapshot paths (fixes #91)
14+
- unify ignore logic via FS::shouldIgnoreEntry across folder counts, tree listing, and disk usage scans
15+
- admin: improve settings search UX (clear button) + smoother section header styling
16+
- UI: polish header dock collapse/expand icon animations (landing/lift + reduced-motion support)
17+
18+
Fixes #91
19+
Refs #92
20+
21+
Co-authored-by: nikp123 <nikp123@e.email>
22+
```
23+
24+
**Added**
25+
26+
- **Indexing ignore rules (regex)**:
27+
- Admin setting: **Ignore paths (regex)** (`ignoreRegex`) — one pattern per line.
28+
- Env override: `FR_IGNORE_REGEX` (locks the field when set).
29+
- Built-in “quick add” button for a common snapshot preset: `(^|/)(@?snapshots?)(/|$)` (helps with NAS snapshot dirs).
30+
- **Centralized ignore helper**:
31+
- `FS::shouldIgnoreEntry($name, $parentRel)` applies built-in ignores plus optional regex patterns.
32+
33+
**Changed**
34+
35+
- **Folder tree / listing / counts now share ignore logic**:
36+
- Replaced scattered ignore arrays with `FS::shouldIgnoreEntry(...)` in folder enumeration paths.
37+
- **Disk usage scan now filters earlier**:
38+
- Uses a `RecursiveCallbackFilterIterator` so ignored entries are skipped before deeper traversal.
39+
- **Admin Panel UX**:
40+
- Settings search now includes a dedicated clear (X) button that appears only when a query exists.
41+
- Section headers now render via a `.section-header-inner` wrapper for cleaner layout/hover/active styles.
42+
- Audit table area now caps height and scrolls to avoid huge modal growth.
43+
- **Header dock polish**:
44+
- Adds “lift” and “land” animations for header dock icon buttons during card collapse/expand.
45+
- Respects `prefers-reduced-motion`.
46+
47+
**Fixed**
48+
49+
- **#91:** Snapshot folders (e.g., `snapshot`, `@snapshots`) can now be excluded cleanly from the tree, counts, indexing, and disk usage views via ignore rules.
50+
- Prevents “stuck landing” icon states by cleaning up animation classes/inline vars on `animationend`.
51+
52+
**Notes**
53+
54+
- Ignore rules are applied frequently during tree/list/count operations. Keep patterns simple to avoid expensive regexes.
55+
- Invalid regex lines are ignored safely (and won’t crash listing/indexing).
56+
57+
---
58+
359
## Changes 01/17/2026 (v3.1.1)
460

561
`release(v3.1.1): OIDC env overrides + configurable resumable chunk size + clearer startup logs (closes #86, closes #87, closes #90)`

config/config.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,31 @@ function decryptData($encryptedData, $encryptionKey)
185185
$encryptionKey = $envKey;
186186
}
187187

188+
// Optional: ignore regex for indexing/listing (env wins; admin config as fallback)
189+
if (!defined('FR_IGNORE_REGEX')) {
190+
$envIgnore = getenv('FR_IGNORE_REGEX');
191+
if ($envIgnore !== false && trim((string)$envIgnore) !== '') {
192+
define('FR_IGNORE_REGEX', (string)$envIgnore);
193+
} else {
194+
$cfgPath = USERS_DIR . 'adminConfig.json';
195+
if (is_file($cfgPath)) {
196+
$enc = @file_get_contents($cfgPath);
197+
if ($enc !== false && $enc !== '') {
198+
$dec = decryptData($enc, $encryptionKey);
199+
if ($dec !== false) {
200+
$cfg = json_decode($dec, true);
201+
if (is_array($cfg) && isset($cfg['ignoreRegex']) && is_string($cfg['ignoreRegex'])) {
202+
$val = trim($cfg['ignoreRegex']);
203+
if ($val !== '') {
204+
define('FR_IGNORE_REGEX', $val);
205+
}
206+
}
207+
}
208+
}
209+
}
210+
}
211+
}
212+
188213
// Helper to load JSON permissions (with optional decryption)
189214
function loadUserPermissions($username)
190215
{

public/css/styles.css

Lines changed: 144 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2909,10 +2909,78 @@ body.dark-mode #decreaseFont:not(:disabled):hover,body.dark-mode #increaseFont:n
29092909
display: inline-flex;
29102910
align-items: center;
29112911
justify-content: center;
2912+
--header-icon-delay: 0ms;
2913+
--header-icon-land-ms: 120ms;
2914+
--header-icon-lift-ms: 90ms;
29122915
}
29132916

29142917
.header-card-icon .material-icons {
29152918
font-size: 22px;
2919+
transform-origin: center center;
2920+
filter: none;
2921+
}
2922+
2923+
.header-card-icon.is-landing .material-icons {
2924+
animation: headerIconLand var(--header-icon-land-ms) cubic-bezier(.22,.61,.36,1) var(--header-icon-delay) backwards;
2925+
will-change: transform, opacity;
2926+
}
2927+
2928+
.header-card-icon.is-launching {
2929+
pointer-events: none;
2930+
}
2931+
2932+
.header-card-icon.is-launching .material-icons {
2933+
animation: headerIconLift var(--header-icon-lift-ms) ease-in forwards;
2934+
will-change: transform, opacity;
2935+
}
2936+
2937+
@keyframes headerIconLand {
2938+
0% {
2939+
opacity: 0;
2940+
transform: translateY(4px) rotateZ(-2deg);
2941+
filter: none;
2942+
}
2943+
35% {
2944+
opacity: 1;
2945+
transform: translateY(-1px) rotateZ(1.5deg);
2946+
filter: drop-shadow(0 6px 10px rgba(0,0,0,0.28));
2947+
}
2948+
65% {
2949+
transform: translateY(0) rotateZ(-1deg);
2950+
filter: drop-shadow(0 3px 6px rgba(0,0,0,0.18));
2951+
}
2952+
100% {
2953+
opacity: 1;
2954+
transform: translateY(0) rotateZ(0);
2955+
filter: none;
2956+
}
2957+
}
2958+
2959+
@keyframes headerIconLift {
2960+
0% {
2961+
opacity: 1;
2962+
transform: translateY(0) rotateZ(0);
2963+
filter: none;
2964+
}
2965+
35% {
2966+
transform: translateY(-2px) rotateZ(1.5deg);
2967+
filter: drop-shadow(0 6px 10px rgba(0,0,0,0.26));
2968+
}
2969+
100% {
2970+
opacity: 0;
2971+
transform: translateY(-4px) rotateZ(-1deg);
2972+
filter: none;
2973+
}
2974+
}
2975+
2976+
@media (prefers-reduced-motion: reduce) {
2977+
.header-card-icon.is-landing .material-icons,
2978+
.header-card-icon.is-launching .material-icons {
2979+
animation: none !important;
2980+
opacity: 1 !important;
2981+
transform: none !important;
2982+
filter: none !important;
2983+
}
29162984
}
29172985

29182986
.header-drop-zone.drag-active {
@@ -2954,29 +3022,43 @@ body.dark-mode #decreaseFont:not(:disabled):hover,body.dark-mode #increaseFont:n
29543022
.section-content { display:none; margin-left:20px; margin-top:8px; margin-bottom:8px; }
29553023

29563024
#adminPanelModal .section-header {
2957-
background: linear-gradient(180deg, rgba(15, 23, 42, 0.05), rgba(15, 23, 42, 0.02));
2958-
border: 1px solid rgba(15, 23, 42, 0.08);
2959-
padding: 8px 12px 8px 22px;
3025+
background: none;
3026+
border: 0;
3027+
padding: 0;
3028+
border-radius: 0;
3029+
display: block;
29603030
font-weight: 600;
29613031
text-transform: uppercase;
29623032
letter-spacing: 0.08em;
29633033
font-size: 0.85rem;
29643034
position: relative;
29653035
margin-top: 12px;
29663036
color: #111827;
2967-
transition: background 140ms ease, border-color 140ms ease, box-shadow 140ms ease, transform 140ms ease;
29683037
}
2969-
#adminPanelModal .section-header:hover {
3038+
#adminPanelModal .section-header-inner {
3039+
background: linear-gradient(180deg, rgba(15, 23, 42, 0.05), rgba(15, 23, 42, 0.02));
3040+
border: 1px solid rgba(15, 23, 42, 0.08);
3041+
padding: 8px 12px;
3042+
border-radius: 12px;
3043+
display: flex;
3044+
align-items: center;
3045+
justify-content: space-between;
3046+
position: relative;
3047+
transition: background 140ms ease, border-color 140ms ease, box-shadow 140ms ease, transform 140ms ease, padding-left 140ms ease;
3048+
}
3049+
#adminPanelModal .section-header:hover .section-header-inner {
29703050
background: rgba(15, 23, 42, 0.04);
29713051
border-color: rgba(15, 23, 42, 0.16);
3052+
box-shadow: 0 6px 14px rgba(15, 23, 42, 0.08);
29723053
transform: translateY(-1px);
29733054
}
2974-
#adminPanelModal .section-header:not(.collapsed) {
3055+
#adminPanelModal .section-header:not(.collapsed) .section-header-inner {
3056+
padding-left: 22px;
29753057
background: rgba(59, 130, 246, 0.06);
29763058
border-color: rgba(59, 130, 246, 0.35);
29773059
box-shadow: 0 6px 14px rgba(15, 23, 42, 0.08);
29783060
}
2979-
#adminPanelModal .section-header:not(.collapsed)::before {
3061+
#adminPanelModal .section-header:not(.collapsed) .section-header-inner::before {
29803062
content: "";
29813063
position: absolute;
29823064
left: 8px;
@@ -2987,20 +3069,22 @@ body.dark-mode #decreaseFont:not(:disabled):hover,body.dark-mode #increaseFont:n
29873069
background: linear-gradient(180deg, rgba(37, 99, 235, 0.9), rgba(96, 165, 250, 0.9));
29883070
}
29893071
#adminPanelModal .section-header .material-icons { color: #475569; }
2990-
body.dark-mode #adminPanelModal .section-header {
3072+
body.dark-mode #adminPanelModal .section-header { color: #f1f5f9; }
3073+
body.dark-mode #adminPanelModal .section-header .section-header-inner {
29913074
background: rgba(255, 255, 255, 0.05);
29923075
border-color: rgba(255, 255, 255, 0.08);
2993-
color: #f1f5f9;
29943076
}
2995-
body.dark-mode #adminPanelModal .section-header:hover {
3077+
body.dark-mode #adminPanelModal .section-header:hover .section-header-inner {
29963078
background: rgba(255, 255, 255, 0.08);
3079+
box-shadow: 0 6px 14px rgba(0, 0, 0, 0.45);
3080+
transform: translateY(-1px);
29973081
}
2998-
body.dark-mode #adminPanelModal .section-header:not(.collapsed) {
3082+
body.dark-mode #adminPanelModal .section-header:not(.collapsed) .section-header-inner {
29993083
background: rgba(96, 165, 250, 0.18);
30003084
border-color: rgba(96, 165, 250, 0.35);
30013085
box-shadow: 0 8px 18px rgba(0, 0, 0, 0.45);
30023086
}
3003-
body.dark-mode #adminPanelModal .section-header:not(.collapsed)::before {
3087+
body.dark-mode #adminPanelModal .section-header:not(.collapsed) .section-header-inner::before {
30043088
background: linear-gradient(180deg, rgba(148, 197, 255, 0.95), rgba(96, 165, 250, 0.95));
30053089
}
30063090
body.dark-mode #adminPanelModal .section-header .material-icons { color: #cbd5f5; }
@@ -3031,6 +3115,11 @@ body.dark-mode #adminPanelModal .section-content {
30313115
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.45);
30323116
}
30333117

3118+
#adminPanelModal .audit-table-wrap {
3119+
max-height: 260px;
3120+
overflow: auto;
3121+
}
3122+
30343123
#adminPanelModal .admin-panel-header {
30353124
display: flex;
30363125
align-items: center;
@@ -3087,6 +3176,39 @@ body.dark-mode #adminPanelModal .section-content {
30873176
max-height: 180px;
30883177
transition: max-height 200ms ease, opacity 200ms ease, transform 200ms ease, margin 200ms ease, padding 200ms ease, border-color 200ms ease;
30893178
}
3179+
#adminPanelModal .admin-search-input {
3180+
position: relative;
3181+
}
3182+
#adminPanelModal .admin-search-input .form-control {
3183+
padding-right: 38px;
3184+
}
3185+
#adminPanelModal .admin-search-clear {
3186+
position: absolute;
3187+
top: 50%;
3188+
right: 8px;
3189+
transform: translateY(-50%);
3190+
border: none;
3191+
background: transparent;
3192+
color: #6b7280;
3193+
width: 28px;
3194+
height: 28px;
3195+
padding: 0;
3196+
border-radius: 999px;
3197+
display: inline-flex;
3198+
align-items: center;
3199+
justify-content: center;
3200+
}
3201+
#adminPanelModal .admin-search-clear:hover {
3202+
background: rgba(15, 23, 42, 0.08);
3203+
color: #111;
3204+
}
3205+
#adminPanelModal .admin-search-clear:focus {
3206+
outline: none;
3207+
box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.2);
3208+
}
3209+
#adminPanelModal .admin-search-clear .material-icons {
3210+
font-size: 18px;
3211+
}
30903212
#adminPanelModal .admin-search-wrap.is-collapsed {
30913213
max-height: 0;
30923214
opacity: 0;
@@ -3113,6 +3235,16 @@ body.dark-mode #adminPanelModal .admin-search-wrap {
31133235
background: rgba(255, 255, 255, 0.04);
31143236
border-color: rgba(255, 255, 255, 0.08);
31153237
}
3238+
body.dark-mode #adminPanelModal .admin-search-clear {
3239+
color: #9ca3af;
3240+
}
3241+
body.dark-mode #adminPanelModal .admin-search-clear:hover {
3242+
background: rgba(255, 255, 255, 0.08);
3243+
color: #e5e7eb;
3244+
}
3245+
body.dark-mode #adminPanelModal .admin-search-clear:focus {
3246+
box-shadow: 0 0 0 2px rgba(147, 197, 253, 0.25);
3247+
}
31163248
@media (max-width: 720px) {
31173249
#adminPanelModal .admin-search-toggle-label { display: none; }
31183250
#adminPanelModal .admin-panel-header { gap: 8px; }

0 commit comments

Comments
 (0)