feat(ui): browse and recover by folder
A Folders mode next to grid and list shows one level at a time: subfolders first with their file count and size, then the files, under a clickable breadcrumb. Folders and files are marked with tri-state boxes that persist while navigating; the bar shows the exact total from the core, and the selection is recovered relative to each marked folder. The sidebar folder tree navigates in this mode. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ca677a8bc1
commit
00aceecf70
7 files changed
+317
-15
No files matched your search
+9
-3
@@ -687,19 +687,25 @@ async function onProgressClick(e) {
|
||||
}
|
||||
|
||||
async function recover(sel) {
|
||||
// From folder browsing: each marked folder is recreated from itself down
|
||||
// (a/b/Projeto -> Projeto/...), so there is no layout to choose.
|
||||
const bySelection = !!sel.selection;
|
||||
const f = await askForm({
|
||||
title: 'Recuperar para…',
|
||||
text: 'Escolha uma pasta em <b>outro disco</b>. O Guará nunca grava no disco de origem, para não sobrescrever o que ainda dá para salvar. <span class="sub">Se a recuperação for interrompida, escolha a mesma pasta de novo: o Guará pula o que já foi conferido.</span>',
|
||||
text: 'Escolha uma pasta em <b>outro disco</b>. O Guará nunca grava no disco de origem, para não sobrescrever o que ainda dá para salvar. <span class="sub">Se a recuperação for interrompida, escolha a mesma pasta de novo: o Guará pula o que já foi conferido.</span>'
|
||||
+ (bySelection ? ' <span class="sub">Cada pasta marcada é recriada no destino a partir dela mesma, com todas as subpastas. Arquivos marcados soltos vão para a raiz do destino.</span>' : '')
|
||||
+ (bySelection && sel.filtered ? ' <span class="sub"><b>Atenção:</b> pastas marcadas são recuperadas inteiras; os filtros ativos não se aplicam a elas.</span>' : ''),
|
||||
ok: 'Recuperar',
|
||||
fields: [
|
||||
{ name: 'dest', label: 'Pasta de destino', value: (S.defaults.home || '') + (S.defaults.sep || '/') + 'Guara-Recuperados', pick: { directory: true, multiple: false } },
|
||||
{ name: 'layout', label: 'Organizar os arquivos', value: 'folders', options: [['folders', 'Pastas originais (e por tipo quando não há pasta)'], ['type', 'Por tipo (Fotos, Documentos, Vídeos...)'], ['date', 'Por data (ano e mês)'], ['flat', 'Tudo na mesma pasta']] },
|
||||
...(bySelection ? [] : [{ name: 'layout', label: 'Organizar os arquivos', value: 'folders', options: [['folders', 'Pastas originais (e por tipo quando não há pasta)'], ['type', 'Por tipo (Fotos, Documentos, Vídeos...)'], ['date', 'Por data (ano e mês)'], ['flat', 'Tudo na mesma pasta']] }]),
|
||||
],
|
||||
});
|
||||
if (!f || !f.dest) return;
|
||||
const dest = f.dest;
|
||||
const { filtered, ...target } = sel;
|
||||
try {
|
||||
const { job } = await rpc('recover_start', { job: S.job, dest, layout: f.layout, ...sel });
|
||||
const { job } = await rpc('recover_start', { job: S.job, dest, layout: f.layout || 'folders', ...target });
|
||||
watchAux(job, 'Recuperando arquivos', (st) => {
|
||||
const r = st.report || {};
|
||||
const ok = (r.recovered || []).length, bad = (r.failed || []).length;
|
||||
|
||||
Reference in new issue
Block a user