Tags et favoris, filtres dans l'explorateur
- DATA_DIR/.meta.json : tags et favoris par chemin, suivis aux renommages, déplacements, copies (tags seuls) et suppressions. - API : GET /api/tags, POST /api/meta/favorite, POST /api/meta/tags ; Entry porte tags et favorite ; /api/search accepte tag= et fav=true (q facultatif). - Tags comparés sans casse ni accents, écriture existante conservée ; ils participent à la recherche texte. - Explorateur : ligne de filtres (Favoris, tags avec leur nombre), étoile et tags sur les éléments, menu Favori / Tags…, actions sur la sélection, dialogue Tags (ajout, retrait, suggestions). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H6J7vKwXx7uopxKhWfFJpm
This commit is contained in:
1 parent
c78df092c1
commit
c1ea1e84a7
13 files changed
+880
-33
No files matched your search
@@ -47,6 +47,9 @@ type Entry struct {
|
||||
IsDir bool `json:"isDir"`
|
||||
Size int64 `json:"size"`
|
||||
ModTime time.Time `json:"modTime"`
|
||||
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
Favorite bool `json:"favorite,omitempty"`
|
||||
}
|
||||
|
||||
// Store est un dépôt de schémas enraciné dans un répertoire.
|
||||
@@ -58,6 +61,9 @@ type Store struct {
|
||||
|
||||
settingsMu sync.Mutex // sérialise les lectures-modifications de .settings.json
|
||||
index textIndex // texte des schémas pour la recherche (search.go)
|
||||
|
||||
metaMu sync.Mutex // tags et favoris (meta.go)
|
||||
meta map[string]itemMeta // nil : pas encore chargé
|
||||
}
|
||||
|
||||
// New crée le répertoire racine si besoin et renvoie un Store.
|
||||
@@ -165,6 +171,7 @@ func (s *Store) List(rel string) ([]Entry, error) {
|
||||
return nil, mapErr(err)
|
||||
}
|
||||
out := make([]Entry, 0, len(des))
|
||||
meta := s.metaSnapshot()
|
||||
for _, de := range des {
|
||||
if !visible(de.Name(), de.IsDir()) || de.Type()&fs.ModeSymlink != 0 {
|
||||
continue
|
||||
@@ -173,7 +180,9 @@ func (s *Store) List(rel string) ([]Entry, error) {
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
out = append(out, toEntry(path.Join(c, de.Name()), fi))
|
||||
e := toEntry(path.Join(c, de.Name()), fi)
|
||||
decorate(&e, meta)
|
||||
out = append(out, e)
|
||||
}
|
||||
sort.Slice(out, func(i, j int) bool {
|
||||
if out[i].IsDir != out[j].IsDir {
|
||||
@@ -335,6 +344,7 @@ func (s *Store) Move(from, to string) (Entry, error) {
|
||||
}
|
||||
s.moveThumb(cf, ct, fi.IsDir())
|
||||
s.moveHistory(cf, ct)
|
||||
s.moveMeta(cf, ct)
|
||||
fi, err = os.Stat(at)
|
||||
if err != nil {
|
||||
return Entry{}, err
|
||||
@@ -400,6 +410,9 @@ func (s *Store) Copy(from, to string) (Entry, error) {
|
||||
e, _, err := s.Write(to, data, "", true)
|
||||
if err == nil {
|
||||
s.copyThumb(from, e.Path)
|
||||
if cf, err := Clean(from); err == nil {
|
||||
s.copyMeta(cf, e.Path)
|
||||
}
|
||||
}
|
||||
return e, err
|
||||
}
|
||||
@@ -436,6 +449,7 @@ func (s *Store) Delete(rel string, recursive bool) error {
|
||||
}
|
||||
s.removeThumb(c, fi.IsDir())
|
||||
s.trashHistory(c, trash)
|
||||
s.removeMeta(c)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user