Add backup browser

This commit is contained in:
JannisX11 2023-06-17 23:41:07 +02:00
parent 398529400a
commit b754f66003
7 changed files with 194 additions and 12 deletions

View File

@ -1568,6 +1568,66 @@ dialog#edit_bedrock_binding > .dialog_wrapper > .dialog_content {
color: inherit;
}
/* View Backups */
ul#view_backups_list {
max-height: calc(95vh - 220px);
margin-top: 8px;
margin-bottom: 8px;
}
ul#view_backups_list > li {
padding: 2px 6px;
cursor: pointer;
border: 2px solid transparent;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
ul#view_backups_list > li.current {
border-color: var(--color-accent);
}
ul#view_backups_list > li:hover {
color: var(--color-light);
}
ul#view_backups_list > li.selected {
background-color: var(--color-accent);
color: var(--color-accent_text);
position: relative;
}
#view_backups_list span {
flex-grow: 1;
}
#view_backups_list .view_backups_info_field {
color: var(--color-subtle_text);
width: 90px;
white-space: nowrap;
overflow: hidden;
cursor: inherit;
text-align: right;
}
#view_backups_list .view_backups_info_field:last-child {
width: 82px;
}
ul#view_backups_list > li.selected .view_backups_info_field {
color: inherit;
}
ol.pagination_numbers {
display: flex;
gap: 3px;
justify-content: center;
}
ol.pagination_numbers > li {
border-radius: 3px;
cursor: pointer;
padding: 0px 7px;
min-width: 22px;
}
ol.pagination_numbers > li:hover, ol.pagination_numbers > li.selected {
background-color: var(--color-accent);
color: var(--color-accent_text);
}
/* Custom Brush Options */
dialog#brush_options:not(.preset_selected) div.form_bar,
dialog#brush_options:not(.preset_selected) hr {

View File

@ -450,6 +450,118 @@ function createBackup(init) {
}
})
}
BARS.defineActions(() => {
let selected_id; // Remember selected one after re-opening
new Action('view_backups', {
icon: 'fa-archive',
category: 'file',
condition: () => isApp,
click(e) {
let backup_directory = app.getPath('userData')+osfs+'backups';
let files = fs.readdirSync(backup_directory);
let entries = files.map((file, i) => {
let path = PathModule.join(backup_directory, file);
let stats = fs.statSync(path);
let size = `${separateThousands(Math.round(stats.size / 1024))} KB`;
let entry = {
id: file,
path,
name: file.replace(/backup_\d+\.\d+\.\d+_\d+\.\d+_?/, '').replace(/\.bbmodel$/, '').replace(/_/g, ' ') || 'no name',
date: stats.mtime.toLocaleDateString(),
time: stats.mtime.toLocaleTimeString().replace(/:\d+ /, ' '),
date_long: stats.mtime.toString(),
timestamp: stats.mtime.getTime(),
size,
}
return entry;
})
entries.sort((a, b) => b.timestamp - a.timestamp);
let selected;
const dialog = new Dialog({
id: 'view_backups',
title: 'action.view_backups',
width: 720,
buttons: ['dialog.confirm', 'dialog.view_backups.open_folder', 'dialog.cancel'],
component: {
data() {return {
backups: entries,
page: 0,
per_page: 80,
search_term: '',
selected: (selected_id ? entries.find(e => e.id == selected_id) : null)
}},
methods: {
select(backup) {
selected = this.selected = backup;
selected_id = backup.id;
},
open() {
dialog.confirm();
},
setPage(number) {
this.page = number;
}
},
computed: {
filtered_backups() {
let term = this.search_term.toLowerCase();
return this.backups.filter(backup => {
return backup.name.includes(term);
})
},
viewed_backups() {
return this.filtered_backups.slice(this.page * this.per_page, (this.page+1) * this.per_page);
},
pages() {
let pages = [];
let length = this.filtered_backups.length;
for (let i = 0; i * this.per_page < length; i++) {
pages.push(i);
}
return pages;
}
},
template: `
<div>
<div class="bar">
<search-bar v-model="search_term" @input="setPage(0)"></search-bar>
</div>
<ul id="view_backups_list" class="list">
<li v-for="backup in viewed_backups" :key="backup.id" :class="{selected: selected == backup}" @dblclick="open(backup)" @click="select(backup);">
<span :title="backup.id">{{ backup.name }}</span>
<div class="view_backups_info_field" :title="backup.date_long">{{ backup.date }}</div>
<div class="view_backups_info_field" :title="backup.date_long">{{ backup.time }}</div>
<div class="view_backups_info_field">{{ backup.size }}</div>
</li>
</ul>
<ol class="pagination_numbers" v-if="pages.length > 1">
<li v-for="number in pages" :class="{selected: page == number}" @click="setPage(number)">{{ number+1 }}</li>
</ol>
</div>
`
},
onButton(button) {
if (button == 1) {
shell.openPath(backup_directory);
}
},
onConfirm() {
Blockbench.read([selected.path], {}, (files) => {
loadModelFile(files[0]);
})
dialog.close();
}
}).show();
}
})
})
//Close
window.onbeforeunload = function (event) {
try {

View File

@ -1798,14 +1798,6 @@ const BARS = {
shell.showItemInFolder(Project.export_path || Project.save_path);
}
})
new Action('open_backup_folder', {
icon: 'fa-archive',
category: 'file',
condition: () => isApp,
click: function (e) {
shell.openPath(app.getPath('userData')+osfs+'backups')
}
})
new Action('reload', {
icon: 'refresh',
category: 'file',

View File

@ -422,7 +422,7 @@ function setupInterface() {
Interface.status_bar.menu = new Menu([
'project_window',
'open_model_folder',
'open_backup_folder',
'view_backups',
'save',
'timelapse',
'cancel_gif',

View File

@ -450,7 +450,7 @@ const MenuBar = {
Blockbench.openLink('https://github.com/JannisX11/blockbench/issues');
}},
'_',
'open_backup_folder',
'view_backups',
'_',
{name: 'menu.help.developer', id: 'developer', icon: 'fas.fa-wrench', children: [
'reload_plugins',

View File

@ -104,6 +104,22 @@ function trimFloatNumber(val, max_digits = 4) {
if (string == -0) return 0;
return string;
}
function separateThousands(number) {
let str = number.toString();
let length = str.indexOf('.');
if (length == -1) length = str.length;
if (length < 4) return str;
let modified;
for (let i = length; i > 0; i -= 3) {
if (i == length) {
modified = str.substring(i-3);
} else {
modified = str.substring(Math.max(0, i-3), i) + ',' + modified;
}
}
return modified;
}
function getAxisLetter(number) {
switch (number) {
case 0: return 'x'; break;

View File

@ -603,6 +603,8 @@
"dialog.input.title": "Input",
"dialog.view_backups.open_folder": "Open Folder",
"dialog.sketchfab_uploader.title": "Upload Sketchfab Model",
"dialog.sketchfab_uploader.token": "API Token",
"dialog.sketchfab_uploader.about_token": "The token is used to connect Blockbench to your Sketchfab account. You can find it on %0",
@ -1110,8 +1112,8 @@
"action.new_window.desc": "Opens a new Blockbench window",
"action.open_model_folder": "Open Model Folder",
"action.open_model_folder.desc": "Opens the folder that the model is contained in",
"action.open_backup_folder": "Open Backup Folder",
"action.open_backup_folder.desc": "Opens the Blockbench backup folder",
"action.view_backups": "View Backups",
"action.view_backups.desc": "Browse the list of auto-saved project backups",
"action.open_model": "Open Model",
"action.open_model.desc": "Open a model file from your computer",
"action.open_from_link": "Open Model from Link...",