mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 14:46:12 -04:00
updated tui architecture
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
load("@rules_cc//cc:cc_binary.bzl", "cc_binary")
|
||||
load("@rules_cc//cc:cc_library.bzl", "cc_library")
|
||||
|
||||
load("@hedron_compile_commands//:refresh_compile_commands.bzl", "refresh_compile_commands")
|
||||
|
||||
@@ -22,6 +23,49 @@ cc_binary(
|
||||
srcs = [
|
||||
"main.cc",
|
||||
],
|
||||
deps = [
|
||||
":app",
|
||||
]
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "app",
|
||||
srcs = [
|
||||
"app.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"app.h",
|
||||
],
|
||||
deps = [
|
||||
":file_picker",
|
||||
":page",
|
||||
"//sharing/linux/tui/ui:home_screen",
|
||||
"@ftxui//:ftxui",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "page",
|
||||
hdrs = [
|
||||
"page.h",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "file_picker",
|
||||
srcs = [
|
||||
"file_picker.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"file_picker.h",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "palette",
|
||||
hdrs = [
|
||||
"palette.h",
|
||||
],
|
||||
deps = [
|
||||
"@ftxui//:ftxui",
|
||||
]
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
#include "sharing/linux/tui/app.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include "ftxui/component/component.hpp"
|
||||
#include "sharing/linux/tui/ui/home_screen.h"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
namespace {
|
||||
|
||||
std::string GetHostname() {
|
||||
char hostname[256] = {};
|
||||
gethostname(hostname, sizeof(hostname));
|
||||
return hostname;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TuiApp::TuiApp() : screen_(ftxui::ScreenInteractive::Fullscreen()) {
|
||||
hostname_ = GetHostname();
|
||||
screen_.TrackMouse(true);
|
||||
}
|
||||
|
||||
int TuiApp::Run() {
|
||||
auto component = HomeScreen({
|
||||
.hostname = hostname_,
|
||||
.current_page = ¤t_page_,
|
||||
.selected_file = &selected_file_,
|
||||
.file_picker = &file_picker_,
|
||||
.on_file_selected =
|
||||
[this](std::string path) {
|
||||
selected_file_ = path;
|
||||
current_page_ = Page::Sharing;
|
||||
},
|
||||
});
|
||||
|
||||
auto app = ftxui::CatchEvent(
|
||||
component, [this](ftxui::Event event) { return HandleEvent(event); });
|
||||
|
||||
screen_.Loop(app);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool TuiApp::HandleEvent(ftxui::Event event) {
|
||||
if (event == ftxui::Event::Character('q') || event == ftxui::Event::Escape) {
|
||||
screen_.ExitLoopClosure()();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (event == ftxui::Event::Backspace && current_page_ == Page::Sharing) {
|
||||
current_page_ = Page::FilePicker;
|
||||
selected_file_.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include "ftxui/component/screen_interactive.hpp"
|
||||
#include "sharing/linux/tui/file_picker.h"
|
||||
#include "sharing/linux/tui/page.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
|
||||
class TuiApp {
|
||||
public:
|
||||
TuiApp();
|
||||
|
||||
int Run();
|
||||
|
||||
private:
|
||||
bool HandleEvent(ftxui::Event event);
|
||||
|
||||
ftxui::ScreenInteractive screen_;
|
||||
ZenityFilePicker file_picker_;
|
||||
Page current_page_ = Page::FilePicker;
|
||||
std::string hostname_;
|
||||
std::string selected_file_;
|
||||
};
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -0,0 +1,30 @@
|
||||
load("@rules_cc//cc:cc_library.bzl", "cc_library")
|
||||
|
||||
cc_library(
|
||||
name = "file_icon",
|
||||
srcs = [
|
||||
"file_icon.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"file_icon.h",
|
||||
],
|
||||
deps = [
|
||||
"@ftxui//:ftxui",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "file_picker_card",
|
||||
srcs = [
|
||||
"file_picker_card.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"file_picker_card.h",
|
||||
],
|
||||
deps = [
|
||||
":file_icon",
|
||||
"//sharing/linux/tui:file_picker",
|
||||
"//sharing/linux/tui:palette",
|
||||
"@ftxui//:ftxui",
|
||||
],
|
||||
)
|
||||
@@ -0,0 +1,15 @@
|
||||
#include "sharing/linux/tui/components/brand.h"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
using namespace ftxui;
|
||||
|
||||
Element Brand() {
|
||||
return vbox({
|
||||
text(" ___ _ _ ___ _ "),
|
||||
text(" / _ \\ _ _(_)__| |__ / __| |_ __ _ _ _ ___ "),
|
||||
text(" | (_) | || | / _| / / \\__ \\ ' \\/ _` | '_/ -_)"),
|
||||
text(" \\__\\_\\\\_,_|_\\__|_\\_\\ |___/_||_\\__,_|_| \\___|"),
|
||||
text(" "),
|
||||
});
|
||||
}
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
|
||||
ftxui::Element Brand();
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -0,0 +1,29 @@
|
||||
#include "sharing/linux/tui/components/file_icon.h"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
|
||||
ftxui::Element FileIcon(FileIconSize size) {
|
||||
if (size == FileIconSize::Small) {
|
||||
return ftxui::vbox({
|
||||
ftxui::text(" ______ ") | ftxui::center,
|
||||
ftxui::text(" / | | ") | ftxui::center,
|
||||
ftxui::text(" /__| | ") | ftxui::center,
|
||||
ftxui::text(" | ----- | ") | ftxui::center,
|
||||
ftxui::text(" | ----- | ") | ftxui::center,
|
||||
ftxui::text(" |_______| ") | ftxui::center,
|
||||
});
|
||||
}
|
||||
|
||||
return ftxui::vbox({
|
||||
ftxui::text(" __________ ") | ftxui::center,
|
||||
ftxui::text(" / | | ") | ftxui::center,
|
||||
ftxui::text(" /__| | ") | ftxui::center,
|
||||
ftxui::text(" | --------- | ") | ftxui::center,
|
||||
ftxui::text(" | --------- | ") | ftxui::center,
|
||||
ftxui::text(" | --------- | ") | ftxui::center,
|
||||
ftxui::text(" | --------- | ") | ftxui::center,
|
||||
ftxui::text(" |___________| ") | ftxui::center,
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
|
||||
enum class FileIconSize {
|
||||
Large,
|
||||
Small,
|
||||
};
|
||||
|
||||
ftxui::Element FileIcon(FileIconSize size);
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -0,0 +1,69 @@
|
||||
#include "sharing/linux/tui/components/file_picker_card.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
#include "ftxui/component/event.hpp"
|
||||
#include "ftxui/screen/box.hpp"
|
||||
#include "sharing/linux/tui/components/file_icon.h"
|
||||
#include "sharing/linux/tui/palette.h"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
|
||||
ftxui::Component FilePickerCard(FilePickerCardOptions options) {
|
||||
auto picker_box = std::make_shared<ftxui::Box>();
|
||||
auto hovered = std::make_shared<bool>(false);
|
||||
|
||||
auto card = ftxui::Renderer([picker_box, hovered] {
|
||||
auto picker_card =
|
||||
ftxui::vbox({
|
||||
FileIcon(FileIconSize::Large) | ftxui::color(Palette::secondary),
|
||||
ftxui::separatorEmpty(),
|
||||
ftxui::text("Select file to share") | ftxui::bold | ftxui::center,
|
||||
}) |
|
||||
ftxui::borderStyled(*hovered ? Palette::primary : Palette::secondary) |
|
||||
ftxui::size(ftxui::WIDTH, ftxui::GREATER_THAN, 33) |
|
||||
ftxui::size(ftxui::HEIGHT, ftxui::EQUAL, 13) |
|
||||
ftxui::reflect(*picker_box);
|
||||
|
||||
return ftxui::vbox({
|
||||
ftxui::filler(),
|
||||
ftxui::hbox({
|
||||
ftxui::filler(),
|
||||
picker_card,
|
||||
ftxui::filler(),
|
||||
}),
|
||||
ftxui::filler(),
|
||||
}) |
|
||||
ftxui::flex;
|
||||
});
|
||||
|
||||
return ftxui::CatchEvent(
|
||||
card, [picker_box, hovered, options](ftxui::Event event) {
|
||||
if (!event.is_mouse()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto mouse = event.mouse();
|
||||
bool inside_picker =
|
||||
mouse.x >= picker_box->x_min && mouse.x <= picker_box->x_max &&
|
||||
mouse.y >= picker_box->y_min && mouse.y <= picker_box->y_max;
|
||||
|
||||
*hovered = inside_picker;
|
||||
|
||||
if (!inside_picker || mouse.button != ftxui::Mouse::Left ||
|
||||
mouse.motion != ftxui::Mouse::Pressed ||
|
||||
options.file_picker == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string path = options.file_picker->PickFile();
|
||||
if (!path.empty() && options.on_file_selected) {
|
||||
options.on_file_selected(path);
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#include "ftxui/component/component.hpp"
|
||||
#include "sharing/linux/tui/file_picker.h"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
|
||||
struct FilePickerCardOptions {
|
||||
FilePicker* file_picker = nullptr;
|
||||
std::function<void(std::string)> on_file_selected;
|
||||
};
|
||||
|
||||
ftxui::Component FilePickerCard(FilePickerCardOptions options);
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "sharing/linux/tui/file_picker.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
|
||||
std::string ZenityFilePicker::PickFile() {
|
||||
FILE* pipe = popen("zenity --file-selection 2>/dev/null", "r");
|
||||
if (pipe == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
char buffer[4096];
|
||||
std::string result;
|
||||
|
||||
if (fgets(buffer, sizeof(buffer), pipe) != nullptr) {
|
||||
result = buffer;
|
||||
}
|
||||
|
||||
pclose(pipe);
|
||||
|
||||
if (!result.empty() && result.back() == '\n') {
|
||||
result.pop_back();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
|
||||
class FilePicker {
|
||||
public:
|
||||
virtual ~FilePicker() = default;
|
||||
|
||||
virtual std::string PickFile() = 0;
|
||||
};
|
||||
|
||||
class ZenityFilePicker final : public FilePicker {
|
||||
public:
|
||||
std::string PickFile() override;
|
||||
};
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
+3
-182
@@ -1,185 +1,6 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include <ftxui/component/component.hpp>
|
||||
#include <ftxui/component/screen_interactive.hpp>
|
||||
#include <ftxui/dom/elements.hpp>
|
||||
#include <ftxui/screen/box.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
using namespace ftxui;
|
||||
|
||||
std::string OpenZenityFilePicker() {
|
||||
FILE* pipe = popen("zenity --file-selection 2>/dev/null", "r");
|
||||
if (!pipe) {
|
||||
return {};
|
||||
}
|
||||
|
||||
char buffer[4096];
|
||||
std::string result;
|
||||
|
||||
if (fgets(buffer, sizeof(buffer), pipe) != nullptr) {
|
||||
result = buffer;
|
||||
}
|
||||
|
||||
pclose(pipe);
|
||||
|
||||
// Remove trailing newline.
|
||||
if (!result.empty() && result.back() == '\n') {
|
||||
result.pop_back();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
enum class Page {
|
||||
FilePicker,
|
||||
FileSelected,
|
||||
};
|
||||
#include "sharing/linux/tui/app.h"
|
||||
|
||||
int main() {
|
||||
auto screen = ScreenInteractive::Fullscreen();
|
||||
screen.TrackMouse(true);
|
||||
|
||||
Page current_screen = Page::FilePicker;
|
||||
auto title_color = Color::RGB(0xab, 0xda, 0xc4);
|
||||
|
||||
// clang-format off
|
||||
auto title = vbox({
|
||||
text("┏━┓╻ ╻╻┏━╸╻┏ ┏━┓╻ ╻┏━┓┏━┓┏━╸") | color(title_color),
|
||||
text("┃┓┃┃ ┃┃┃ ┣┻┓ ┗━┓┣━┫┣━┫┣┳┛┣╸ ") | color(title_color),
|
||||
text("┗┻┛┗━┛╹┗━╸╹ ╹ ┗━┛╹ ╹╹ ╹╹┗╸┗━╸") | color(title_color),
|
||||
});
|
||||
|
||||
auto file_icon = vbox({
|
||||
text(" __________ ") | center | color(title_color),
|
||||
text(" / | | ") | center | color(title_color),
|
||||
text(" /__| | ") | center | color(title_color),
|
||||
text(" | --------- | ") | center | color(title_color),
|
||||
text(" | --------- | ") | center | color(title_color),
|
||||
text(" | --------- | ") | center | color(title_color),
|
||||
text(" | --------- | ") | center | color(title_color),
|
||||
text(" |___________| ") | center | color(title_color),
|
||||
});
|
||||
// clang-format on
|
||||
|
||||
char hostname[256] = {};
|
||||
gethostname(hostname, sizeof(hostname));
|
||||
|
||||
bool picker_hovered = false;
|
||||
std::string selected_file;
|
||||
|
||||
Box picker_box;
|
||||
auto RenderFilePickerScreen = [&] {
|
||||
auto picker_card =
|
||||
vbox({
|
||||
file_icon,
|
||||
separatorEmpty(),
|
||||
text("Click to open file picker") | bold | center,
|
||||
separatorEmpty(),
|
||||
text("No file selected") | dim | center,
|
||||
}) |
|
||||
borderStyled(picker_hovered ? Color::White : title_color) |
|
||||
size(WIDTH, GREATER_THAN, 38) | size(HEIGHT, EQUAL, 15) |
|
||||
reflect(picker_box);
|
||||
|
||||
return vbox({
|
||||
filler(),
|
||||
hbox({
|
||||
filler(),
|
||||
picker_card,
|
||||
filler(),
|
||||
}),
|
||||
filler(),
|
||||
}) |
|
||||
flex;
|
||||
};
|
||||
|
||||
auto RenderFileSelectedScreen = [&] {
|
||||
return vbox({
|
||||
text("File selected") | bold | center | color(title_color),
|
||||
separator(),
|
||||
paragraph(selected_file) | center,
|
||||
separatorEmpty(),
|
||||
text("Press Backspace to choose another file") | dim | center,
|
||||
}) |
|
||||
borderStyled(title_color) | flex;
|
||||
};
|
||||
|
||||
auto component = Renderer([&] {
|
||||
auto visible_as_box =
|
||||
window(text(" Visible as "),
|
||||
vbox({
|
||||
text(""),
|
||||
text(std::string(hostname)) | bold | center,
|
||||
text(""),
|
||||
})) |
|
||||
size(WIDTH, GREATER_THAN, 24) | size(HEIGHT, EQUAL, 5);
|
||||
auto main_panel = current_screen == Page::FilePicker
|
||||
? RenderFilePickerScreen()
|
||||
: RenderFileSelectedScreen();
|
||||
auto picker_card =
|
||||
vbox({
|
||||
file_icon,
|
||||
separatorEmpty(),
|
||||
text("Click to open file picker") | bold | center,
|
||||
separatorEmpty(),
|
||||
paragraph(selected_file.empty() ? "No file selected"
|
||||
: selected_file) |
|
||||
dim | center,
|
||||
}) |
|
||||
borderStyled(picker_hovered ? Color::White : title_color) |
|
||||
size(WIDTH, GREATER_THAN, 38) | size(HEIGHT, EQUAL, 15) |
|
||||
reflect(picker_box);
|
||||
|
||||
return vbox({
|
||||
title,
|
||||
separator(),
|
||||
hbox({
|
||||
vbox({
|
||||
visible_as_box,
|
||||
}),
|
||||
|
||||
main_panel | flex,
|
||||
}) | flex,
|
||||
}) |
|
||||
size(WIDTH, GREATER_THAN, 80) | size(HEIGHT, GREATER_THAN, 24);
|
||||
});
|
||||
|
||||
auto app = CatchEvent(component, [&](Event event) {
|
||||
if (event == Event::Character('q') || event == Event::Escape) {
|
||||
screen.ExitLoopClosure()();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!event.is_mouse()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto mouse = event.mouse();
|
||||
|
||||
bool inside_picker =
|
||||
mouse.x >= picker_box.x_min && mouse.x <= picker_box.x_max &&
|
||||
mouse.y >= picker_box.y_min && mouse.y <= picker_box.y_max;
|
||||
|
||||
picker_hovered = inside_picker;
|
||||
|
||||
if (inside_picker && mouse.button == Mouse::Left &&
|
||||
mouse.motion == Mouse::Pressed) {
|
||||
std::string path = OpenZenityFilePicker();
|
||||
|
||||
if (!path.empty()) {
|
||||
selected_file = path;
|
||||
current_screen = Page::FileSelected;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
screen.Loop(app);
|
||||
|
||||
return 0;
|
||||
nearby::sharing::linux_tui::TuiApp app;
|
||||
return app.Run();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
|
||||
enum class Page {
|
||||
FilePicker,
|
||||
Sharing,
|
||||
};
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "ftxui/screen/color.hpp"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
|
||||
struct Palette {
|
||||
inline static const ftxui::Color primary =
|
||||
ftxui::Color::RGB(0xF1, 0xF9, 0xF6); // Off-white mint tint
|
||||
|
||||
inline static const ftxui::Color secondary =
|
||||
ftxui::Color::RGB(0x8A, 0xAF, 0xA4); // Muted sage gray
|
||||
|
||||
inline static const ftxui::Color accent =
|
||||
ftxui::Color::RGB(0xA3, 0xD9, 0xC9); // Original Mint Leaf
|
||||
|
||||
inline static const ftxui::Color active =
|
||||
ftxui::Color::RGB(0x23, 0x3D, 0x34); // Deep forest green tint
|
||||
|
||||
inline static const ftxui::Color base =
|
||||
ftxui::Color::RGB(0x12, 0x1D, 0x1A); // Near-black deep mint/charcoal
|
||||
};
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -0,0 +1,63 @@
|
||||
load("@rules_cc//cc:cc_library.bzl", "cc_library")
|
||||
|
||||
cc_library(
|
||||
name = "home_header",
|
||||
srcs = [
|
||||
"home_header.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"home_header.h",
|
||||
],
|
||||
deps = [
|
||||
"@ftxui//:ftxui",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "sidebar",
|
||||
srcs = [
|
||||
"sidebar.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"sidebar.h",
|
||||
],
|
||||
deps = [
|
||||
"//sharing/linux/tui:palette",
|
||||
"//sharing/linux/tui/components:file_icon",
|
||||
"@ftxui//:ftxui",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "file_selected_screen",
|
||||
srcs = [
|
||||
"file_selected_screen.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"file_selected_screen.h",
|
||||
],
|
||||
deps = [
|
||||
"//sharing/linux/tui:palette",
|
||||
"@ftxui//:ftxui",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "home_screen",
|
||||
srcs = [
|
||||
"home_screen.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"home_screen.h",
|
||||
],
|
||||
deps = [
|
||||
":file_selected_screen",
|
||||
":home_header",
|
||||
":sidebar",
|
||||
"//sharing/linux/tui:file_picker",
|
||||
"//sharing/linux/tui:page",
|
||||
"//sharing/linux/tui:palette",
|
||||
"//sharing/linux/tui/components:file_picker_card",
|
||||
"@ftxui//:ftxui",
|
||||
],
|
||||
)
|
||||
@@ -0,0 +1,20 @@
|
||||
#include "sharing/linux/tui/ui/file_selected_screen.h"
|
||||
|
||||
#include "sharing/linux/tui/palette.h"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
|
||||
ftxui::Element FileSelectedScreen(const std::string& selected_file) {
|
||||
return ftxui::vbox({
|
||||
ftxui::text("File selected") | ftxui::bold | ftxui::center |
|
||||
ftxui::color(Palette::primary),
|
||||
ftxui::separator(),
|
||||
ftxui::paragraph(selected_file) | ftxui::center,
|
||||
ftxui::separatorEmpty(),
|
||||
ftxui::text("Press Backspace to choose another file") |
|
||||
ftxui::dim | ftxui::center,
|
||||
}) |
|
||||
ftxui::borderStyled(Palette::primary) | ftxui::flex;
|
||||
}
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
|
||||
ftxui::Element FileSelectedScreen(const std::string& selected_file);
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -0,0 +1,11 @@
|
||||
#include "sharing/linux/tui/ui/home_header.h"
|
||||
#include "sharing/linux/tui/components/brand.h"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
using namespace ftxui;
|
||||
|
||||
Element HomeHeader() {
|
||||
return Brand();
|
||||
}
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
|
||||
ftxui::Element HomeHeader();
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -0,0 +1,43 @@
|
||||
#include "sharing/linux/tui/ui/home_screen.h"
|
||||
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
#include "sharing/linux/tui/components/file_picker_card.h"
|
||||
#include "sharing/linux/tui/palette.h"
|
||||
#include "sharing/linux/tui/ui/file_selected_screen.h"
|
||||
#include "sharing/linux/tui/ui/home_header.h"
|
||||
#include "sharing/linux/tui/ui/sidebar.h"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
|
||||
ftxui::Component HomeScreen(HomeScreenOptions options) {
|
||||
auto file_picker_card =
|
||||
FilePickerCard({.file_picker = options.file_picker,
|
||||
.on_file_selected = options.on_file_selected});
|
||||
|
||||
return ftxui::Renderer(file_picker_card, [file_picker_card, options] {
|
||||
const std::string selected_file =
|
||||
options.selected_file == nullptr ? "" : *options.selected_file;
|
||||
const Page current_page = options.current_page == nullptr
|
||||
? Page::FilePicker
|
||||
: *options.current_page;
|
||||
|
||||
auto main_panel = current_page == Page::FilePicker
|
||||
? file_picker_card->Render()
|
||||
: FileSelectedScreen(selected_file);
|
||||
|
||||
return ftxui::vbox({
|
||||
HomeHeader() | ftxui::color(Palette::accent),
|
||||
ftxui::separator(),
|
||||
ftxui::hbox({
|
||||
Sidebar({.hostname = options.hostname,
|
||||
.selected_file = selected_file}),
|
||||
main_panel | ftxui::flex,
|
||||
}) | ftxui::flex,
|
||||
}) |
|
||||
ftxui::bgcolor(Palette::base) |
|
||||
ftxui::size(ftxui::WIDTH, ftxui::GREATER_THAN, 80) |
|
||||
ftxui::size(ftxui::HEIGHT, ftxui::GREATER_THAN, 24);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#include "ftxui/component/component.hpp"
|
||||
#include "sharing/linux/tui/file_picker.h"
|
||||
#include "sharing/linux/tui/page.h"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
|
||||
struct HomeScreenOptions {
|
||||
std::string hostname;
|
||||
const Page* current_page = nullptr;
|
||||
const std::string* selected_file = nullptr;
|
||||
FilePicker* file_picker = nullptr;
|
||||
std::function<void(std::string)> on_file_selected;
|
||||
};
|
||||
|
||||
ftxui::Component HomeScreen(HomeScreenOptions options);
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -0,0 +1,42 @@
|
||||
#include "sharing/linux/tui/ui/sidebar.h"
|
||||
|
||||
#include "sharing/linux/tui/components/file_icon.h"
|
||||
#include "sharing/linux/tui/palette.h"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
using namespace ftxui;
|
||||
|
||||
Element Sidebar(const SidebarState& state) {
|
||||
auto visible_as_box =
|
||||
window(
|
||||
text(" Visible as "),
|
||||
vbox({
|
||||
text(""),
|
||||
text(state.hostname) | bold | center,
|
||||
text(""),
|
||||
})) |
|
||||
size(WIDTH, GREATER_THAN, 24) |
|
||||
size(HEIGHT, EQUAL, 5);
|
||||
|
||||
if (state.selected_file.empty()) {
|
||||
return vbox({
|
||||
visible_as_box,
|
||||
filler(),
|
||||
});
|
||||
}
|
||||
|
||||
return vbox({
|
||||
visible_as_box,
|
||||
filler(),
|
||||
window(
|
||||
text(" Selected to share ") | center,
|
||||
vbox({
|
||||
FileIcon(FileIconSize::Small) | color(Palette::accent),
|
||||
text(""),
|
||||
paragraph(state.selected_file) | dim,
|
||||
})) |
|
||||
size(WIDTH, EQUAL, 24),
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
|
||||
struct SidebarState {
|
||||
std::string hostname;
|
||||
std::string selected_file;
|
||||
};
|
||||
|
||||
ftxui::Element Sidebar(const SidebarState& state);
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
Reference in New Issue
Block a user