Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions backend/include/backend/rpc_system.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@ class RpcSystem : public RpcHelper::StrandRpc

private:
void registerGetUsername();
void registerGetHostname();

std::string username() const;
std::string hostname() const;

mutable std::string usernameMemo_;
mutable std::string hostnameMemo_;
};
30 changes: 30 additions & 0 deletions backend/source/backend/rpc_system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#include <log/log.hpp>
#include <paths/utf8.hpp>

#include <boost/asio/ip/host_name.hpp>

#ifdef _WIN32
# include <windows.h>
# include <Lmcons.h>
Expand All @@ -26,6 +28,7 @@ RpcSystem::RpcSystem(boost::asio::any_io_executor executor, Nui::Window& wnd, Nu
: RpcHelper::StrandRpc{executor, wnd, hub}
{
registerGetUsername();
registerGetHostname();
}

void RpcSystem::registerGetUsername()
Expand All @@ -39,6 +42,33 @@ void RpcSystem::registerGetUsername()
);
}

void RpcSystem::registerGetHostname()
{
on("RpcSystem::getHostname")
.perform(
[this](RpcHelper::RpcOnce&& reply)
{
reply({{"hostname", hostname()}, {"success", true}});
}
);
}

std::string RpcSystem::hostname() const
{
if (!hostnameMemo_.empty())
return hostnameMemo_;

boost::system::error_code error;
auto name = boost::asio::ip::host_name(error);
if (error)
{
Log::error("RpcSystem::hostname: {}", error.message());
return "unknown";
}
hostnameMemo_ = Paths::sanitizedUtf8(name);
return hostnameMemo_;
}

std::string RpcSystem::username() const
{
if (!usernameMemo_.empty())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@ class FileExplorerPanel
*/
void setup();

/**
* @brief Sets the user, host and port the remote side names as its origin. Syncing the change is left
* to the caller.
*/
void setRemoteOrigin(std::string userAndHost);

/**
* @brief Attaches the caller-provided synchronize callback to both sides
* of the grid. Used by Session::setupFileGrid to wire in the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ NuiFileExplorer::Texts fileExplorerTexts()
.synchronize = language->get("fileExplorer", "contextMenu", "synchronize"),
.synchronizeHint = language->get("fileExplorer", "contextMenu", "synchronizeHint"),
},
.origin =
{
.local = language->get("fileExplorer", "origin", "local"),
.remote = language->get("fileExplorer", "origin", "remote"),
},
};
}

Expand Down
32 changes: 20 additions & 12 deletions frontend/source/frontend/session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,20 @@ using namespace Nui;
using namespace Nui::Elements;
using namespace Nui::Attributes;

namespace
{
/**
* @brief Formats the address of an SSH session as user@host:port, with brackets around IPv6 hosts.
*/
std::string sshAddress(std::string const& user, Persistence::SshSessionOptions const& options)
{
auto host = options.host;
if (host.find(':') != std::string::npos)
host = "[" + host + "]";
return fmt::format("{}@{}:{}", user, host, options.port.value_or(22));
}
}

struct Session::Implementation
{
// Prop-drill
Expand Down Expand Up @@ -802,11 +816,9 @@ void Session::onOpenSession(bool success, std::string const& info)
{
const auto& snapshot = impl_->snapshotManager->pending();
const auto& user = snapshot.remoteUsername;
auto host = sshSessionOptions.host;
const auto port = sshSessionOptions.port.value_or(22);
if (host.find(":") != std::string::npos)
host = "[" + host + "]";
*impl_->tabTitle = impl_->disambiguateTitle(this, fmt::format("{}@{}:{}", user, host, port));
const auto address = sshAddress(user, sshSessionOptions);
*impl_->tabTitle = impl_->disambiguateTitle(this, address);
impl_->fileExplorerPanel.setRemoteOrigin(address);
impl_->snapshotManager->setRemoteUsername(user);
const bool sftpWasOpen = snapshot.sftpWasOpen;
if (sftpWasOpen)
Expand All @@ -832,13 +844,9 @@ void Session::onOpenSession(bool success, std::string const& info)
Log::info("Retrieved username: {}", username);

const auto user = sshSessionOptions.loginUser().name.value_or(username);
auto host = sshSessionOptions.host;
const auto port = sshSessionOptions.port.value_or(22);

// assume ipv6 when finding ':' in host
if (host.find(":") != std::string::npos)
host = "[" + host + "]";
*impl_->tabTitle = impl_->disambiguateTitle(this, fmt::format("{}@{}:{}", user, host, port));
const auto address = sshAddress(user, sshSessionOptions);
*impl_->tabTitle = impl_->disambiguateTitle(this, address);
impl_->fileExplorerPanel.setRemoteOrigin(address);
impl_->snapshotManager->setRemoteUsername(user);

openSftp(user);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <nui/event_system/observed_value_combinator.hpp>
#include <nui/frontend/elements.hpp>
#include <nui/frontend/attributes.hpp>
#include <nui/frontend/rpc_client.hpp>

#include <algorithm>
#include <iterator>
Expand All @@ -30,6 +31,40 @@ using namespace Nui::Attributes;

namespace
{
std::string stringProperty(Nui::val const& response, char const* name)
{
if (!response.hasOwnProperty(name))
return {};
return response[name].as<std::string>();
}

/**
* @brief Names the user and hostname of this machine as the origin of the local side.
*
* @param side The local side.
* @param alive Expires with the panel, so late replies are dropped.
*/
void requestLocalOrigin(NuiFileExplorer::Side* side, std::weak_ptr<bool> alive)
{
Nui::RpcClient::callWithBackChannel(
"RpcSystem::getUsername",
[side, alive](Nui::val usernameResponse)
{
Nui::RpcClient::callWithBackChannel(
"RpcSystem::getHostname",
[side, alive, username = stringProperty(usernameResponse, "username")](Nui::val hostnameResponse)
{
if (alive.expired())
return;
const auto hostname = stringProperty(hostnameResponse, "hostname");
side->originHost(username.empty() ? hostname : fmt::format("{}@{}", username, hostname));
Nui::globalEventContext.executeActiveEventsImmediately();
}
);
}
);
}

NuiFileExplorer::FileGrid
buildFileGrid(FileExplorerPanel::Params& params, Persistence::SessionOptions const& engineOptions)
{
Expand Down Expand Up @@ -58,6 +93,7 @@ namespace
},
.pageSize = uiOptions.fileGridPageSize,
.texts = fileExplorerTexts(),
.origin = NuiFileExplorer::SideOrigin::Local,
},
{
.pathBarOnTop = uiOptions.fileGridPathBarOnTop,
Expand All @@ -74,6 +110,7 @@ namespace
},
.pageSize = uiOptions.fileGridPageSize,
.texts = fileExplorerTexts(),
.origin = NuiFileExplorer::SideOrigin::Remote,
},
std::make_unique<LocalSideModel>(
uiOptions, confirmDialog, inputDialog, filePropertyDialog, archiveTransferDialog
Expand Down Expand Up @@ -106,6 +143,7 @@ namespace
},
.pageSize = uiOptions.fileGridPageSize,
.texts = fileExplorerTexts(),
.origin = NuiFileExplorer::SideOrigin::Local,
},
std::make_unique<LocalSideModel>(
uiOptions, confirmDialog, inputDialog, filePropertyDialog, archiveTransferDialog
Expand All @@ -130,6 +168,7 @@ struct FileExplorerPanel::Implementation
NuiFileExplorer::FileGrid fileGrid;
Nui::Observed<std::shared_ptr<Nui::Dom::Element>> fileExplorerElement{};
LanguageChangeListener languageListener{};
std::shared_ptr<bool> alive = std::make_shared<bool>(true);

explicit Implementation(Params&& params)
: stateHolder{params.stateHolder}
Expand Down Expand Up @@ -231,6 +270,14 @@ void FileExplorerPanel::setup()
{
localSideModel().setRemoteModel(nullptr);
}

requestLocalOrigin(&localFileGridSide(), impl_->alive);
}

void FileExplorerPanel::setRemoteOrigin(std::string userAndHost)
{
if (auto* remote = remoteFileGridSide(); remote)
remote->originHost(std::move(userAndHost));
}

void FileExplorerPanel::setOnSynchronize(std::function<void(std::filesystem::path, std::filesystem::path)> onSync)
Expand Down
9 changes: 9 additions & 0 deletions nui-file-explorer/include/nui-file-explorer/side.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,11 @@ namespace NuiFileExplorer
*/
Texts const& texts() const;

/**
* @brief Sets the user and host the origin card names. Syncing the change is left to the caller.
*/
void originHost(std::string value);

/**
* @brief Sets a callback invoked when both sides have exactly one directory-like item
* selected and the user triggers the "Synchronize..." context menu entry.
Expand Down Expand Up @@ -199,6 +204,10 @@ namespace NuiFileExplorer
Nui::ElementRenderer operator()();

private:
Nui::ElementRenderer originIconAndKind();
std::string originClass(std::string const& baseClass) const;
Nui::ElementRenderer originChip();
Nui::ElementRenderer originCard();
Nui::ElementRenderer headMenu();
Nui::ElementRenderer pathBar();
Nui::ElementRenderer filter();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ namespace NuiFileExplorer
Nui::Observed<std::pair<SortCriterion, bool>> sorting{{SortCriterion::Name, true}};
Nui::Observed<bool> showHiddenFiles{false};
Nui::Observed<Texts> texts{};
Nui::Observed<std::string> originHost{};

std::weak_ptr<Nui::Dom::BasicElement> sideElement{};
std::weak_ptr<Nui::Dom::BasicElement> scrollContainer{};
Expand Down
16 changes: 16 additions & 0 deletions nui-file-explorer/include/nui-file-explorer/side/side_settings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,19 @@
#include <nui-file-explorer/texts.hpp>

#include <functional>
#include <optional>

namespace NuiFileExplorer
{
/**
* @brief Which machine a side shows, labelled in the path bar and on top of Places.
*/
enum class SideOrigin
{
Local,
Remote
};

struct SideSettings
{
bool pathBarOnTop = false;
Expand All @@ -18,5 +28,11 @@ namespace NuiFileExplorer

// Texts the side renders, English unless translations are passed.
Texts texts{};

/**
* @brief Shows the origin chip and card when set. The user and host are set through
* Side::originHost.
*/
std::optional<SideOrigin> origin{std::nullopt};
};
}
7 changes: 7 additions & 0 deletions nui-file-explorer/include/nui-file-explorer/texts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,19 @@ namespace NuiFileExplorer
std::string synchronizeHint{"Select exactly one directory on each side to synchronize."};
};

struct Origin
{
std::string local{"Local"};
std::string remote{"Remote"};
};

Toolbar toolbar{};
NewMenu newMenu{};
SortMenu sortMenu{};
ViewMenu viewMenu{};
Columns columns{};
Places places{};
ContextMenu contextMenu{};
Origin origin{};
};
}
Loading
Loading