Progress bar for Notepad IO (#1322)

This commit is contained in:
Kyle Reed 2023-07-30 00:36:57 -07:00 committed by GitHub
parent 0a3aa706ef
commit 411f6c0a34
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 73 additions and 3 deletions

View File

@ -474,7 +474,13 @@ void TextEditorView::open_file(const fs::path& path) {
path_ = {}; path_ = {};
file_dirty_ = false; file_dirty_ = false;
has_temp_file_ = false; has_temp_file_ = false;
auto result = FileWrapper::open(path); auto result = FileWrapper::open(
path, false, [](uint32_t value, uint32_t total) {
Painter p;
auto percent = (value * 100) / total;
auto width = (percent * screen_width) / 100;
p.draw_hline({0, 16}, width, Color::yellow());
});
if (!result) { if (!result) {
nav_.display_modal("Read Error", "Cannot open file:\n" + result.error().what()); nav_.display_modal("Read Error", "Cannot open file:\n" + result.error().what());
@ -582,6 +588,10 @@ void TextEditorView::prepare_for_write() {
if (has_temp_file_) if (has_temp_file_)
return; return;
// TODO: This would be nice to have but it causes a stack overflow in an ISR?
// Painter p;
// p.draw_string({2, 48}, Styles::yellow, "Creating temporary file...");
// Copy to temp file on write. // Copy to temp file on write.
has_temp_file_ = true; has_temp_file_ = true;
delete_temp_file(path_); delete_temp_file(path_);

View File

@ -26,6 +26,7 @@
#include "file.hpp" #include "file.hpp"
#include "optional.hpp" #include "optional.hpp"
#include <functional>
#include <memory> #include <memory>
#include <string_view> #include <string_view>
@ -75,6 +76,8 @@ class BufferWrapper {
} }
virtual ~BufferWrapper() {} virtual ~BufferWrapper() {}
std::function<void(Size, Size)> on_read_progress{};
/* Prevent copies */ /* Prevent copies */
BufferWrapper(const BufferWrapper&) = delete; BufferWrapper(const BufferWrapper&) = delete;
BufferWrapper& operator=(const BufferWrapper&) = delete; BufferWrapper& operator=(const BufferWrapper&) = delete;
@ -234,13 +237,23 @@ class BufferWrapper {
line_count_ = start_line_; line_count_ = start_line_;
Offset offset = start_offset_; Offset offset = start_offset_;
// Report progress every N lines.
constexpr auto report_interval = 100u;
auto result = next_newline(offset); auto result = next_newline(offset);
auto next_report = report_interval;
while (result) { while (result) {
++line_count_; ++line_count_;
if (newlines_.size() < max_newlines) if (newlines_.size() < max_newlines)
newlines_.push_back(*result); newlines_.push_back(*result);
offset = *result + 1; offset = *result + 1;
if (on_read_progress && line_count_ > next_report) {
on_read_progress(offset, size());
next_report = line_count_ + report_interval;
}
result = next_newline(offset); result = next_newline(offset);
} }
} }
@ -397,6 +410,9 @@ class BufferWrapper {
// Number of bytes left to shift. // Number of bytes left to shift.
Offset remaining = size() - src; Offset remaining = size() - src;
Offset offset = size(); Offset offset = size();
Size report_total = remaining;
Size report_interval = report_total / 8;
Size next_report = remaining - report_interval;
while (remaining > 0) { while (remaining > 0) {
offset -= std::min(remaining, buffer_size); offset -= std::min(remaining, buffer_size);
@ -413,6 +429,11 @@ class BufferWrapper {
break; break;
remaining -= *result; remaining -= *result;
if (on_read_progress && remaining <= next_report) {
on_read_progress(report_total - remaining, report_total);
next_report = remaining > report_interval ? remaining - report_interval : 0;
}
} }
} }
@ -424,6 +445,9 @@ class BufferWrapper {
char buffer[buffer_size]; char buffer[buffer_size];
auto offset = src; auto offset = src;
Size report_total = size();
Size report_interval = report_total / 8;
Size next_report = offset + report_interval;
while (true) { while (true) {
wrapped_->seek(offset); wrapped_->seek(offset);
@ -438,6 +462,11 @@ class BufferWrapper {
break; break;
offset += *result; offset += *result;
if (on_read_progress && offset >= next_report) {
on_read_progress(offset, report_total);
next_report = offset + report_interval;
}
} }
// Delete the extra bytes at the end of the file. // Delete the extra bytes at the end of the file.
@ -463,13 +492,19 @@ class FileWrapper : public BufferWrapper<File, 64> {
template <typename T> template <typename T>
using Result = File::Result<T>; using Result = File::Result<T>;
using Error = File::Error; using Error = File::Error;
static Result<std::unique_ptr<FileWrapper>> open(const std::filesystem::path& path, bool create = false) { static Result<std::unique_ptr<FileWrapper>> open(
const std::filesystem::path& path,
bool create = false,
std::function<void(Size, Size)> on_read_progress = nullptr) {
auto fw = std::unique_ptr<FileWrapper>(new FileWrapper()); auto fw = std::unique_ptr<FileWrapper>(new FileWrapper());
auto error = fw->file_.open(path, /*read_only*/ false, create); auto error = fw->file_.open(path, /*read_only*/ false, create);
if (error) if (error)
return *error; return *error;
if (on_read_progress)
fw->on_read_progress = on_read_progress;
fw->initialize(); fw->initialize();
return fw; return fw;
} }

View File

@ -435,4 +435,29 @@ SCENARIO("Delete line.") {
} }
} }
SCENARIO("It calls on_read_progress while reading.") {
GIVEN("A file larger than internal buffer_size (512)") {
std::string content = std::string(599, 'a');
content.push_back('x');
MockFile f{content};
auto w = wrap_buffer(f);
auto init_line_count = w.line_count();
auto init_size = w.size();
auto called = false;
w.on_read_progress = [&called](auto, auto) {
called = true;
};
WHEN("Replacing range with larger size") {
w.replace_range({0, 2}, "bbb");
THEN("callback should be called.") {
CHECK(called);
}
}
}
}
TEST_SUITE_END(); TEST_SUITE_END();