Public Access
Merge main (file sharing, v0.18.0) into the VPN branch
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
This commit is contained in:
@@ -48,6 +48,7 @@ void StorageApp::onEnter() {
|
||||
}
|
||||
|
||||
void StorageApp::onExit() {
|
||||
share_.stop(); // sharing lasts as long as its screen
|
||||
if (wait_ != Wait::None && wait_ != Wait::Work) {
|
||||
ops_.cancel();
|
||||
wait_ = Wait::None;
|
||||
@@ -97,6 +98,13 @@ bool StorageApp::work(const std::string& why, const std::string& selectAfter) {
|
||||
|
||||
void StorageApp::update(uint32_t nowMs) {
|
||||
bool present = storage_.state().present;
|
||||
if (view_ == View::Share) {
|
||||
if (!present || !share_.running()) {
|
||||
share_.stop();
|
||||
view_ = View::Browse;
|
||||
}
|
||||
if (nowMs - lastDrawMs_ >= 500) requestRedraw(); // what the browser is doing
|
||||
}
|
||||
if (present != cardPresent_) { // taken out, put in, or erased: back to the top
|
||||
cardPresent_ = present;
|
||||
cwd_ = want_ = "/";
|
||||
@@ -281,6 +289,7 @@ void StorageApp::help(std::vector<KeyHelp>& out) const {
|
||||
case View::Editor: return noteEditor_.help(out);
|
||||
case View::Viewer: return viewer_.help(out);
|
||||
case View::Details: return keys::add(out, keys::kStorageDetails);
|
||||
case View::Share: return keys::add(out, keys::kStorageShare);
|
||||
default: break;
|
||||
}
|
||||
if (dialog_) return keys::add(out, keys::kDialog);
|
||||
@@ -295,6 +304,7 @@ const char* StorageApp::helpTitle() const {
|
||||
case View::Editor: return "Storage: the editor";
|
||||
case View::Viewer: return "Storage: a file";
|
||||
case View::Details: return "Storage: details";
|
||||
case View::Share: return "Storage: sharing";
|
||||
case View::Name: return "Storage: a name";
|
||||
default: return nullptr;
|
||||
}
|
||||
@@ -303,6 +313,14 @@ const char* StorageApp::helpTitle() const {
|
||||
bool StorageApp::onKey(const KeyEvent& e) {
|
||||
requestRedraw();
|
||||
if (view_ == View::NoMemory) return false;
|
||||
if (view_ == View::Share) {
|
||||
if (e.key == Key::Back) {
|
||||
share_.stop();
|
||||
view_ = View::Browse;
|
||||
open(cwd_); // what was uploaded or deleted meanwhile
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (view_ == View::Maintenance) {
|
||||
if (!maintenance_.onKey(e)) {
|
||||
view_ = View::Browse;
|
||||
@@ -413,6 +431,12 @@ bool StorageApp::onBrowseKey(const KeyEvent& e) {
|
||||
}
|
||||
uint32_t ch = e.key == Key::Char ? (e.ch >= 'A' && e.ch <= 'Z' ? e.ch + 32 : e.ch) : 0;
|
||||
if (ch == 'm') askMaintenance();
|
||||
if (ch == 'w') {
|
||||
std::string why = share_.start();
|
||||
if (why.empty()) view_ = View::Share;
|
||||
else say(why);
|
||||
return true;
|
||||
}
|
||||
if (!cardPresent_ || !loaded_) return true;
|
||||
|
||||
Item item = selected();
|
||||
@@ -507,6 +531,7 @@ void StorageApp::draw(Canvas& c) {
|
||||
c.drawString("in Gemini) and open Storage again.", 4, area.y + 22 + theme::kLineHeight);
|
||||
return;
|
||||
case View::Maintenance: maintenance_.draw(c); return;
|
||||
case View::Share: drawShare(c); return;
|
||||
case View::Viewer: viewer_.draw(c); return;
|
||||
case View::Editor: noteEditor_.draw(c); return;
|
||||
case View::Details: {
|
||||
@@ -539,6 +564,37 @@ void StorageApp::draw(Canvas& c) {
|
||||
}
|
||||
}
|
||||
|
||||
// The address as a QR code and in letters, the code to type, and what the browser has done.
|
||||
void StorageApp::drawShare(Canvas& c) {
|
||||
const auto& area = theme::kContent;
|
||||
std::string url = share_.url(), code = share_.code();
|
||||
const int qr = 104;
|
||||
c.fillRect(2, area.y + 3, qr + 6, qr + 6, 0xFFFF); // a QR code wants a quiet border
|
||||
c.qrcode((url + "#" + code).c_str(), 5, area.y + 6, qr);
|
||||
int x = qr + 14, y = area.y + 4;
|
||||
c.setFont(&fonts::small);
|
||||
c.setTextColor(theme::kMuted);
|
||||
c.drawString("In a browser, on", x, y);
|
||||
c.drawString("this network:", x, y + 10);
|
||||
c.setTextColor(theme::kText);
|
||||
c.drawString(url.size() > 7 ? url.substr(7).c_str() : url.c_str(), x, y + 24); // without http://
|
||||
c.setTextColor(theme::kMuted);
|
||||
c.drawString("Code", x, y + 40);
|
||||
c.setFont(&fonts::bold);
|
||||
c.setTextColor(theme::kAccent);
|
||||
std::string grouped = code.size() == 6 ? code.substr(0, 3) + " " + code.substr(3) : code;
|
||||
c.drawString(grouped.c_str(), x, y + 50);
|
||||
c.setFont(&fonts::small);
|
||||
c.setTextColor(theme::kMuted);
|
||||
std::string moved = formatBytes(share_.bytesIn()) + " in, " + formatBytes(share_.bytesOut()) + " out";
|
||||
c.drawString(share_.requests() ? moved.c_str() : "Nothing asked yet", x, y + 72);
|
||||
c.drawString("Not encrypted.", x, y + 84);
|
||||
c.drawString("` stops sharing", x, y + 96);
|
||||
c.setTextColor(theme::kText);
|
||||
std::string last = share_.last();
|
||||
if (!last.empty()) c.drawString(last.c_str(), 4, area.y + area.h - 9);
|
||||
}
|
||||
|
||||
void StorageApp::drawBrowse(Canvas& c) {
|
||||
const auto& area = theme::kContent;
|
||||
StorageState card = storage_.state();
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "services/clock_service.h"
|
||||
#include "services/file_ops.h"
|
||||
#include "services/storage_service.h"
|
||||
#include "services/web_share.h"
|
||||
#include "ui/theme.h"
|
||||
|
||||
namespace roro {
|
||||
@@ -26,8 +27,8 @@ namespace roro {
|
||||
// usage, Storage Clean-up and erasing the card, behind a warning (Q128).
|
||||
class StorageApp : public App {
|
||||
public:
|
||||
StorageApp(FileOps& ops, StorageService& storage, ClockService& clock, UpdateService& update, PowerService& power, EventBus& bus)
|
||||
: ops_(ops), storage_(storage), bus_(bus), maintenance_(storage, clock, bus), viewer_(storage, update), noteEditor_(storage, clock, power) {}
|
||||
StorageApp(FileOps& ops, StorageService& storage, ClockService& clock, UpdateService& update, PowerService& power, EventBus& bus, WebShare& share)
|
||||
: ops_(ops), storage_(storage), bus_(bus), share_(share), maintenance_(storage, clock, bus), viewer_(storage, update), noteEditor_(storage, clock, power) {}
|
||||
void onEnter() override;
|
||||
void onExit() override;
|
||||
bool onKey(const KeyEvent& e) override;
|
||||
@@ -40,7 +41,7 @@ class StorageApp : public App {
|
||||
const char* helpTitle() const override;
|
||||
|
||||
private:
|
||||
enum class View { Browse, Details, Name, Viewer, Editor, Maintenance, NoMemory };
|
||||
enum class View { Browse, Details, Name, Viewer, Editor, Maintenance, NoMemory, Share };
|
||||
enum class Ask { None, Delete, Replace, Maintenance };
|
||||
enum class Wait { None, List, CountToDelete, CountForDetails, Work }; // what the running operation is for
|
||||
static constexpr int kRows = 8;
|
||||
@@ -66,10 +67,12 @@ class StorageApp : public App {
|
||||
void say(const std::string& text);
|
||||
void drawBrowse(Canvas& c);
|
||||
void drawProgress(Canvas& c);
|
||||
void drawShare(Canvas& c); // `w`: the card in a browser on the same network (issue #88)
|
||||
|
||||
FileOps& ops_;
|
||||
StorageService& storage_;
|
||||
EventBus& bus_;
|
||||
WebShare& share_;
|
||||
MaintenancePage maintenance_;
|
||||
FileViewer viewer_;
|
||||
NoteEditor noteEditor_; // `e` in the text viewer (Q146)
|
||||
|
||||
Reference in New Issue
Block a user