mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 14:46:12 -04:00
removed TUI and dbus service
This commit is contained in:
@@ -26,7 +26,6 @@ refresh_compile_commands(
|
||||
targets = {
|
||||
":fast_init": "",
|
||||
":nearby_sharing_cli": "",
|
||||
"//sharing/linux/tui:tui": "",
|
||||
},
|
||||
# No need to add flags already in .bazelrc. They're automatically picked up.
|
||||
# If you don't need flags, a list of targets is also okay, as is a single target string.
|
||||
|
||||
@@ -18,20 +18,12 @@ RowLayout {
|
||||
Connections {
|
||||
target: backend
|
||||
|
||||
function onStatusTextChanged() {
|
||||
console.log(backend.statusText);
|
||||
}
|
||||
function onIncomingTransfer(share_target_id, device_name, status) {
|
||||
function onIncomingTransfer(share_target_id) {
|
||||
console.log("Getting incoming share");
|
||||
console.log("selected transfer: " + share_target_id)
|
||||
selectedTransferId = share_target_id;
|
||||
currentIndex = 2;
|
||||
}
|
||||
function onTransferUpdate(share_target_id, device_name, status, progress) {
|
||||
if (selectedTransferId === share_target_id) {
|
||||
currentIndex = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
@@ -47,7 +39,6 @@ RowLayout {
|
||||
return;
|
||||
}
|
||||
topLayout.selectedTransferId = shareTargetId;
|
||||
backend.prepareOutgoingTransfer(shareTargetId, topLayout.pendingPath);
|
||||
backend.sendFile(shareTargetId, topLayout.pendingPath);
|
||||
topLayout.currentIndex = 2;
|
||||
}
|
||||
@@ -57,20 +48,14 @@ RowLayout {
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
backend.startReceive();
|
||||
}
|
||||
|
||||
function cancelPendingShare() {
|
||||
pendingPath = "";
|
||||
selectedTransferId = 0;
|
||||
currentIndex = 0;
|
||||
backend.stopDiscovery();
|
||||
backend.startReceive();
|
||||
}
|
||||
|
||||
function startSharing() {
|
||||
backend.stopReceive();
|
||||
backend.startDiscovery();
|
||||
currentIndex = 1;
|
||||
}
|
||||
|
||||
+11
-11
@@ -46,7 +46,17 @@ qt_cc_library(
|
||||
srcs = ["backend.cc"],
|
||||
hdrs = ["backend.h"],
|
||||
deps = [
|
||||
":nearby_sharing_dbus_client",
|
||||
"//connections/implementation/flags:connections_flags",
|
||||
"//internal/base:file_path",
|
||||
"//internal/flags:nearby_flags",
|
||||
"//sharing:attachments",
|
||||
"//sharing:nearby_sharing_service",
|
||||
"//sharing:transfer_metadata",
|
||||
"//sharing:types",
|
||||
"//sharing/flags/generated:generated_flags",
|
||||
"//sharing/linux:linux_sharing_platform",
|
||||
"//sharing/proto:enums_cc_proto",
|
||||
"@com_google_absl//absl/time",
|
||||
"@rules_qt//:qt_core",
|
||||
"@rules_qt//:qt_hdrs",
|
||||
"@rules_qt//:qt_qml",
|
||||
@@ -75,13 +85,3 @@ qt_cc_binary(
|
||||
"@rules_qt//:qt_widgets",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "nearby_sharing_dbus_client",
|
||||
srcs = ["nearby_sharing_dbus_client.cc"],
|
||||
hdrs = ["nearby_sharing_dbus_client.h"],
|
||||
deps = [
|
||||
"//sharing/linux/daemon:nearby_sharing_dbus_client_glue",
|
||||
"@sdbus_cpp",
|
||||
],
|
||||
)
|
||||
|
||||
+389
-269
@@ -1,48 +1,104 @@
|
||||
#include "sharing/linux/app/backend.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <condition_variable>
|
||||
#include <filesystem>
|
||||
#include <functional>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <utility>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QMetaObject>
|
||||
#include <QPointer>
|
||||
#include <QUrl>
|
||||
#include <sdbus-c++/sdbus-c++.h>
|
||||
|
||||
#include "absl/time/time.h"
|
||||
#include "connections/implementation/flags/nearby_connections_feature_flags.h"
|
||||
#include "internal/base/file_path.h"
|
||||
#include "internal/flags/nearby_flags.h"
|
||||
#include "sharing/advertisement.h"
|
||||
#include "sharing/file_attachment.h"
|
||||
#include "sharing/flags/generated/nearby_sharing_feature_flags.h"
|
||||
#include "sharing/nearby_sharing_service_factory.h"
|
||||
#include "sharing/nearby_sharing_settings.h"
|
||||
#include "sharing/proto/enums.pb.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using NearbySharingService = nearby::sharing::NearbySharingService;
|
||||
|
||||
constexpr std::chrono::seconds kShutdownTimeout(10);
|
||||
|
||||
QString ToQString(const std::string& value) {
|
||||
return QString::fromStdString(value);
|
||||
}
|
||||
|
||||
QString NormalizeLocalPath(const QString& path) {
|
||||
const QUrl url(path);
|
||||
if (url.isValid() && url.isLocalFile()) {
|
||||
return url.toLocalFile();
|
||||
}
|
||||
return path;
|
||||
return url.isValid() && url.isLocalFile() ? url.toLocalFile() : path;
|
||||
}
|
||||
|
||||
double ProgressFraction(const std::optional<nearby::sharing::linux::app::Transfer>& transfer) {
|
||||
if (!transfer.has_value()) {
|
||||
return 0;
|
||||
}
|
||||
return std::clamp(transfer->progress / 100.0, 0.0, 1.0);
|
||||
void ConfigureFlags() {
|
||||
nearby::NearbyFlags::GetInstance().OverrideBoolFlagValue(
|
||||
nearby::sharing::config_package_nearby::nearby_sharing_feature::
|
||||
kEnableBleForTransfer,
|
||||
true);
|
||||
nearby::NearbyFlags::GetInstance().OverrideBoolFlagValue(
|
||||
nearby::connections::config_package_nearby::nearby_connections_feature::
|
||||
kEnableBleL2cap,
|
||||
true);
|
||||
nearby::NearbyFlags::GetInstance().OverrideBoolFlagValue(
|
||||
nearby::connections::config_package_nearby::nearby_connections_feature::
|
||||
kRefactorBleL2cap,
|
||||
true);
|
||||
}
|
||||
|
||||
bool IsAwaitingLocalConfirmation(
|
||||
const std::optional<nearby::sharing::linux::app::Transfer>& transfer) {
|
||||
return transfer.has_value() &&
|
||||
transfer->status == "kAwaitingLocalConfirmation";
|
||||
std::unique_ptr<nearby::sharing::AttachmentContainer> CreateFileAttachments(
|
||||
const std::string& path) {
|
||||
nearby::sharing::AttachmentContainer::Builder builder;
|
||||
builder.AddFileAttachment(
|
||||
nearby::sharing::FileAttachment(nearby::FilePath(path)));
|
||||
return builder.Build();
|
||||
}
|
||||
|
||||
QString DeviceNameFor(
|
||||
const std::optional<nearby::sharing::linux::app::ShareTarget>& target) {
|
||||
if (!target.has_value() || target->device_name.empty()) {
|
||||
return QStringLiteral("Unknown device");
|
||||
NearbySharingService::StatusCodes ShutdownService(
|
||||
NearbySharingService& service) {
|
||||
struct State {
|
||||
std::mutex mutex;
|
||||
std::condition_variable cv;
|
||||
std::optional<NearbySharingService::StatusCodes> status;
|
||||
};
|
||||
auto state = std::make_shared<State>();
|
||||
service.Shutdown([state](NearbySharingService::StatusCodes status) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(state->mutex);
|
||||
state->status = status;
|
||||
}
|
||||
state->cv.notify_one();
|
||||
});
|
||||
|
||||
std::unique_lock<std::mutex> lock(state->mutex);
|
||||
if (!state->cv.wait_for(lock, kShutdownTimeout,
|
||||
[&] { return state->status.has_value(); })) {
|
||||
return NearbySharingService::StatusCodes::kError;
|
||||
}
|
||||
return ToQString(target->device_name);
|
||||
return *state->status;
|
||||
}
|
||||
|
||||
void PostStatus(Backend* backend, std::function<void()> callback) {
|
||||
QPointer<Backend> guarded_backend(backend);
|
||||
if (!guarded_backend) {
|
||||
return;
|
||||
}
|
||||
QMetaObject::invokeMethod(
|
||||
guarded_backend,
|
||||
[guarded_backend, callback = std::move(callback)]() mutable {
|
||||
if (guarded_backend) {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -51,10 +107,7 @@ ShareTargetModel::ShareTargetModel(QObject* parent)
|
||||
: QAbstractListModel(parent) {}
|
||||
|
||||
int ShareTargetModel::rowCount(const QModelIndex& parent) const {
|
||||
if (parent.isValid()) {
|
||||
return 0;
|
||||
}
|
||||
return static_cast<int>(targets_.size());
|
||||
return parent.isValid() ? 0 : static_cast<int>(targets_.size());
|
||||
}
|
||||
|
||||
QVariant ShareTargetModel::data(const QModelIndex& index, int role) const {
|
||||
@@ -70,19 +123,7 @@ QVariant ShareTargetModel::data(const QModelIndex& index, int role) const {
|
||||
case DeviceNameRole:
|
||||
return ToQString(target.device_name);
|
||||
case TypeRole:
|
||||
return target.type;
|
||||
case IsIncomingRole:
|
||||
return target.is_incoming;
|
||||
case IsKnownRole:
|
||||
return target.is_known;
|
||||
case DeviceIdRole:
|
||||
return ToQString(target.device_id);
|
||||
case ForSelfShareRole:
|
||||
return target.for_self_share;
|
||||
case VendorIdRole:
|
||||
return target.vendor_id;
|
||||
case ReceiveDisabledRole:
|
||||
return target.receive_disabled;
|
||||
return static_cast<int>(target.type);
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
@@ -93,12 +134,6 @@ QHash<int, QByteArray> ShareTargetModel::roleNames() const {
|
||||
{IdRole, "targetId"},
|
||||
{DeviceNameRole, "deviceName"},
|
||||
{TypeRole, "type"},
|
||||
{IsIncomingRole, "isIncoming"},
|
||||
{IsKnownRole, "isKnown"},
|
||||
{DeviceIdRole, "deviceId"},
|
||||
{ForSelfShareRole, "forSelfShare"},
|
||||
{VendorIdRole, "vendorId"},
|
||||
{ReceiveDisabledRole, "receiveDisabled"},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -113,11 +148,7 @@ void ShareTargetModel::ApplyTarget(const ShareTarget& target) {
|
||||
}
|
||||
|
||||
targets_[row] = target;
|
||||
const QModelIndex changed_index = index(row);
|
||||
emit dataChanged(changed_index, changed_index,
|
||||
{IdRole, DeviceNameRole, TypeRole, IsIncomingRole,
|
||||
IsKnownRole, DeviceIdRole, ForSelfShareRole, VendorIdRole,
|
||||
ReceiveDisabledRole});
|
||||
emit dataChanged(index(row), index(row), {IdRole, DeviceNameRole, TypeRole});
|
||||
}
|
||||
|
||||
void ShareTargetModel::RemoveTarget(int64_t target_id) {
|
||||
@@ -125,25 +156,24 @@ void ShareTargetModel::RemoveTarget(int64_t target_id) {
|
||||
if (row < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
beginRemoveRows(QModelIndex(), row, row);
|
||||
targets_.erase(targets_.begin() + row);
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
void ShareTargetModel::ResetTargets(const std::vector<ShareTarget>& targets) {
|
||||
void ShareTargetModel::Clear() {
|
||||
if (targets_.empty()) {
|
||||
return;
|
||||
}
|
||||
beginResetModel();
|
||||
targets_ = targets;
|
||||
targets_.clear();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
std::optional<ShareTargetModel::ShareTarget> ShareTargetModel::FindTarget(
|
||||
int64_t target_id) const {
|
||||
const int row = IndexOf(target_id);
|
||||
if (row < 0) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return targets_[row];
|
||||
return row < 0 ? std::nullopt : std::optional<ShareTarget>(targets_[row]);
|
||||
}
|
||||
|
||||
int ShareTargetModel::IndexOf(int64_t target_id) const {
|
||||
@@ -159,10 +189,7 @@ ShareTransferModel::ShareTransferModel(QObject* parent)
|
||||
: QAbstractListModel(parent) {}
|
||||
|
||||
int ShareTransferModel::rowCount(const QModelIndex& parent) const {
|
||||
if (parent.isValid()) {
|
||||
return 0;
|
||||
}
|
||||
return static_cast<int>(transfers_.size());
|
||||
return parent.isValid() ? 0 : static_cast<int>(transfers_.size());
|
||||
}
|
||||
|
||||
QVariant ShareTransferModel::data(const QModelIndex& index, int role) const {
|
||||
@@ -178,18 +205,13 @@ QHash<int, QByteArray> ShareTransferModel::roleNames() const {
|
||||
{IdRole, "transferId"},
|
||||
{DirectionRole, "direction"},
|
||||
{DeviceNameRole, "deviceName"},
|
||||
{TypeRole, "type"},
|
||||
{StatusRole, "status"},
|
||||
{ProgressRole, "progress"},
|
||||
{TransferredBytesRole, "transferredBytes"},
|
||||
{TotalBytesRole, "totalBytes"},
|
||||
{TransferSpeedRole, "transferSpeed"},
|
||||
{EstimatedTimeRemainingRole, "estimatedTimeRemaining"},
|
||||
{TotalAttachmentsCountRole, "totalAttachmentsCount"},
|
||||
{TransferredAttachmentsCountRole, "transferredAttachmentsCount"},
|
||||
{IsFinalStatusRole, "isFinalStatus"},
|
||||
{HasTargetRole, "hasTarget"},
|
||||
{HasTransferRole, "hasTransfer"},
|
||||
{AwaitingLocalConfirmationRole, "awaitingLocalConfirmation"},
|
||||
{LocalPathRole, "localPath"},
|
||||
};
|
||||
@@ -204,21 +226,24 @@ void ShareTransferModel::ApplyTarget(const ShareTarget& target) {
|
||||
EmitRowChanged(row);
|
||||
}
|
||||
|
||||
void ShareTransferModel::ApplyTransfer(const QString& direction,
|
||||
void ShareTransferModel::ApplyTransfer(bool receive_mode,
|
||||
const ShareTarget& target,
|
||||
const Transfer& transfer) {
|
||||
const TransferMetadata& transfer,
|
||||
int64_t total_bytes) {
|
||||
int row = IndexOf(target.id);
|
||||
if (row < 0) {
|
||||
row = static_cast<int>(transfers_.size());
|
||||
beginInsertRows(QModelIndex(), row, row);
|
||||
transfers_.push_back(Row{target.id, direction, target, transfer, {}});
|
||||
transfers_.push_back(
|
||||
Row{target.id, receive_mode, target, transfer, total_bytes, {}});
|
||||
endInsertRows();
|
||||
return;
|
||||
}
|
||||
|
||||
transfers_[row].direction = direction;
|
||||
transfers_[row].receive_mode = receive_mode;
|
||||
transfers_[row].target = target;
|
||||
transfers_[row].transfer = transfer;
|
||||
transfers_[row].total_bytes = total_bytes;
|
||||
EmitRowChanged(row);
|
||||
}
|
||||
|
||||
@@ -231,7 +256,6 @@ void ShareTransferModel::PrepareOutgoingTransfer(
|
||||
beginInsertRows(QModelIndex(), row, row);
|
||||
Row transfer;
|
||||
transfer.id = target_id;
|
||||
transfer.direction = QStringLiteral("send");
|
||||
transfer.target = target;
|
||||
transfer.local_path = local_path;
|
||||
transfers_.push_back(std::move(transfer));
|
||||
@@ -239,22 +263,12 @@ void ShareTransferModel::PrepareOutgoingTransfer(
|
||||
return;
|
||||
}
|
||||
|
||||
transfers_[row].direction = QStringLiteral("send");
|
||||
transfers_[row].receive_mode = false;
|
||||
transfers_[row].target = target;
|
||||
transfers_[row].local_path = local_path;
|
||||
EmitRowChanged(row);
|
||||
}
|
||||
|
||||
void ShareTransferModel::RemoveTransfer(int64_t target_id) {
|
||||
const int row = IndexOf(target_id);
|
||||
if (row < 0) {
|
||||
return;
|
||||
}
|
||||
beginRemoveRows(QModelIndex(), row, row);
|
||||
transfers_.erase(transfers_.begin() + row);
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
int ShareTransferModel::IndexOf(int64_t target_id) const {
|
||||
for (int i = 0; i < static_cast<int>(transfers_.size()); ++i) {
|
||||
if (transfers_[i].id == target_id) {
|
||||
@@ -265,47 +279,43 @@ int ShareTransferModel::IndexOf(int64_t target_id) const {
|
||||
}
|
||||
|
||||
QVariant ShareTransferModel::DataForRow(const Row& row, int role) const {
|
||||
const Transfer empty_transfer;
|
||||
const Transfer& transfer = row.transfer.value_or(empty_transfer);
|
||||
|
||||
const auto& target = row.target;
|
||||
const auto& transfer = row.transfer;
|
||||
switch (role) {
|
||||
case IdRole:
|
||||
return QVariant::fromValue<qint64>(row.id);
|
||||
case DirectionRole:
|
||||
return row.direction;
|
||||
return row.receive_mode ? QStringLiteral("receive")
|
||||
: QStringLiteral("send");
|
||||
case DeviceNameRole:
|
||||
return DeviceNameFor(row.target);
|
||||
case TypeRole:
|
||||
return row.target.has_value() ? row.target->type : 0;
|
||||
return target.has_value() && !target->device_name.empty()
|
||||
? ToQString(target->device_name)
|
||||
: QStringLiteral("Unknown device");
|
||||
case StatusRole:
|
||||
if (row.transfer.has_value()) {
|
||||
return ToQString(transfer.status);
|
||||
}
|
||||
return row.direction == QStringLiteral("send")
|
||||
? QStringLiteral("kConnecting")
|
||||
: QStringLiteral("kUnknown");
|
||||
return transfer.has_value() ? ToQString(TransferMetadata::StatusToString(
|
||||
transfer->status()))
|
||||
: QString();
|
||||
case ProgressRole:
|
||||
return ProgressFraction(row.transfer);
|
||||
return transfer.has_value()
|
||||
? std::clamp(static_cast<double>(transfer->progress()) / 100.0,
|
||||
0.0, 1.0)
|
||||
: 0.0;
|
||||
case TransferredBytesRole:
|
||||
return QVariant::fromValue<qint64>(transfer.transferred_bytes);
|
||||
return QVariant::fromValue<qulonglong>(
|
||||
transfer.has_value() ? transfer->transferred_bytes() : 0);
|
||||
case TotalBytesRole:
|
||||
return QVariant::fromValue<qint64>(transfer.total_bytes);
|
||||
case TransferSpeedRole:
|
||||
return QVariant::fromValue<qint64>(transfer.transfer_speed);
|
||||
case EstimatedTimeRemainingRole:
|
||||
return QVariant::fromValue<qint64>(transfer.estimated_time_remaining);
|
||||
return QVariant::fromValue<qint64>(row.total_bytes);
|
||||
case TotalAttachmentsCountRole:
|
||||
return transfer.total_attachments_count;
|
||||
return transfer.has_value() ? transfer->total_attachments_count() : 0;
|
||||
case TransferredAttachmentsCountRole:
|
||||
return transfer.transferred_attachments_count;
|
||||
return transfer.has_value() ? transfer->transferred_attachments_count()
|
||||
: 0;
|
||||
case IsFinalStatusRole:
|
||||
return transfer.is_final_status;
|
||||
case HasTargetRole:
|
||||
return row.target.has_value();
|
||||
case HasTransferRole:
|
||||
return row.transfer.has_value();
|
||||
return transfer.has_value() && transfer->is_final_status();
|
||||
case AwaitingLocalConfirmationRole:
|
||||
return IsAwaitingLocalConfirmation(row.transfer);
|
||||
return transfer.has_value() &&
|
||||
transfer->status() ==
|
||||
TransferMetadata::Status::kAwaitingLocalConfirmation;
|
||||
case LocalPathRole:
|
||||
return row.local_path;
|
||||
default:
|
||||
@@ -314,202 +324,312 @@ QVariant ShareTransferModel::DataForRow(const Row& row, int role) const {
|
||||
}
|
||||
|
||||
void ShareTransferModel::EmitRowChanged(int row) {
|
||||
const QModelIndex changed_index = index(row);
|
||||
emit dataChanged(changed_index, changed_index,
|
||||
{IdRole, DirectionRole, DeviceNameRole, TypeRole,
|
||||
StatusRole, ProgressRole, TransferredBytesRole,
|
||||
TotalBytesRole, TransferSpeedRole,
|
||||
EstimatedTimeRemainingRole, TotalAttachmentsCountRole,
|
||||
TransferredAttachmentsCountRole, IsFinalStatusRole,
|
||||
HasTargetRole, HasTransferRole,
|
||||
AwaitingLocalConfirmationRole, LocalPathRole});
|
||||
emit dataChanged(
|
||||
index(row), index(row),
|
||||
{IdRole, DirectionRole, DeviceNameRole, StatusRole, ProgressRole,
|
||||
TransferredBytesRole, TotalBytesRole, TotalAttachmentsCountRole,
|
||||
TransferredAttachmentsCountRole, IsFinalStatusRole,
|
||||
AwaitingLocalConfirmationRole, LocalPathRole});
|
||||
}
|
||||
|
||||
void Backend::TransferCallback::OnTransferUpdate(
|
||||
const ShareTarget& share_target,
|
||||
const nearby::sharing::AttachmentContainer& attachment_container,
|
||||
const TransferMetadata& transfer_metadata) {
|
||||
backend_.OnTransferUpdate(receive_mode_, share_target, attachment_container,
|
||||
transfer_metadata);
|
||||
}
|
||||
|
||||
Backend::Backend(QObject* parent)
|
||||
: QObject(parent), targets_(this), transfers_(this) {
|
||||
try {
|
||||
client_ = std::make_unique<Client>(this);
|
||||
SetStatusText(QStringLiteral("Connected to nearby sharing daemon"));
|
||||
} catch (const sdbus::Error& error) {
|
||||
SetStatusText(QStringLiteral("D-Bus connection failed: %1")
|
||||
.arg(QString::fromStdString(error.getMessage())));
|
||||
: QObject(parent),
|
||||
targets_(this),
|
||||
transfers_(this),
|
||||
send_transfer_callback_(*this, false),
|
||||
receive_transfer_callback_(*this, true) {
|
||||
ConfigureFlags();
|
||||
service_ = nearby::sharing::NearbySharingServiceFactory::GetInstance()
|
||||
->CreateSharingService(platform_, &analytics_recorder_,
|
||||
/*event_logger=*/nullptr,
|
||||
/*supports_file_sync=*/false);
|
||||
if (service_ == nullptr) {
|
||||
qCritical() << "Failed to create NearbySharingService";
|
||||
desired_mode_ = Mode::kNone;
|
||||
return;
|
||||
}
|
||||
|
||||
service_->GetSettings()->SetDataUsage(
|
||||
nearby::sharing::proto::WIFI_ONLY_DATA_USAGE);
|
||||
QPointer<Backend> backend(this);
|
||||
service_->SetVisibility(
|
||||
nearby::sharing::proto::DEVICE_VISIBILITY_EVERYONE, absl::ZeroDuration(),
|
||||
[backend](NearbySharingService::StatusCodes status) mutable {
|
||||
if (!backend) {
|
||||
return;
|
||||
}
|
||||
PostStatus(backend, [backend, status]() {
|
||||
if (!backend || backend->shutting_down_) {
|
||||
return;
|
||||
}
|
||||
backend->initialized_ =
|
||||
status == NearbySharingService::StatusCodes::kOk;
|
||||
backend->ReportStatus(QStringLiteral("Initialize"), status);
|
||||
if (backend->initialized_) {
|
||||
backend->DriveMode();
|
||||
} else {
|
||||
backend->desired_mode_ = Mode::kNone;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Backend::~Backend() = default;
|
||||
Backend::~Backend() {
|
||||
shutdown();
|
||||
}
|
||||
|
||||
void Backend::startReceive() {
|
||||
RunCommand(QStringLiteral("Start receive"),
|
||||
[this]() { return client_->StartReceive(); });
|
||||
}
|
||||
|
||||
void Backend::stopReceive() {
|
||||
RunCommand(QStringLiteral("Stop receive"),
|
||||
[this]() { return client_->StopReceive(); });
|
||||
SetDesiredMode(Mode::kReceive);
|
||||
}
|
||||
|
||||
void Backend::startDiscovery() {
|
||||
RunCommand(QStringLiteral("Start discovery"),
|
||||
[this]() { return client_->StartDiscovery(); });
|
||||
}
|
||||
|
||||
void Backend::stopDiscovery() {
|
||||
RunCommand(QStringLiteral("Stop discovery"),
|
||||
[this]() { return client_->StopDiscovery(); });
|
||||
SetDesiredMode(Mode::kDiscovery);
|
||||
}
|
||||
|
||||
void Backend::sendFile(qint64 share_target_id, const QString& path) {
|
||||
if (service_ == nullptr || shutting_down_) {
|
||||
return;
|
||||
}
|
||||
const QString local_path = NormalizeLocalPath(path);
|
||||
RunCommand(QStringLiteral("Send file"), [this, share_target_id, local_path]() {
|
||||
return client_->SendFile(share_target_id, local_path.toStdString());
|
||||
});
|
||||
}
|
||||
const std::string native_path = local_path.toStdString();
|
||||
std::error_code error;
|
||||
if (!std::filesystem::is_regular_file(native_path, error)) {
|
||||
qWarning() << "Send file failed: path is not a regular file" << local_path;
|
||||
return;
|
||||
}
|
||||
const auto target = targets_.FindTarget(share_target_id);
|
||||
if (!target.has_value()) {
|
||||
qWarning() << "Send file failed: unknown target" << share_target_id;
|
||||
return;
|
||||
}
|
||||
|
||||
void Backend::prepareOutgoingTransfer(qint64 share_target_id,
|
||||
const QString& path) {
|
||||
transfers_.PrepareOutgoingTransfer(share_target_id, NormalizeLocalPath(path),
|
||||
targets_.FindTarget(share_target_id));
|
||||
transfers_.PrepareOutgoingTransfer(share_target_id, local_path, target);
|
||||
service_->SendAttachments(share_target_id, CreateFileAttachments(native_path),
|
||||
StatusCallback(QStringLiteral("Send file")));
|
||||
}
|
||||
|
||||
void Backend::accept(qint64 share_target_id) {
|
||||
RunCommand(QStringLiteral("Accept transfer"), [this, share_target_id]() {
|
||||
return client_->Accept(share_target_id);
|
||||
});
|
||||
if (service_ != nullptr && !shutting_down_) {
|
||||
service_->Accept(share_target_id,
|
||||
StatusCallback(QStringLiteral("Accept transfer")));
|
||||
}
|
||||
}
|
||||
|
||||
void Backend::reject(qint64 share_target_id) {
|
||||
RunCommand(QStringLiteral("Reject transfer"), [this, share_target_id]() {
|
||||
return client_->Reject(share_target_id);
|
||||
});
|
||||
if (service_ != nullptr && !shutting_down_) {
|
||||
service_->Reject(share_target_id,
|
||||
StatusCallback(QStringLiteral("Reject transfer")));
|
||||
}
|
||||
}
|
||||
|
||||
void Backend::cancel(qint64 share_target_id) {
|
||||
RunCommand(QStringLiteral("Cancel transfer"), [this, share_target_id]() {
|
||||
return client_->Cancel(share_target_id);
|
||||
if (service_ != nullptr && !shutting_down_) {
|
||||
service_->Cancel(share_target_id,
|
||||
StatusCallback(QStringLiteral("Cancel transfer")));
|
||||
}
|
||||
}
|
||||
|
||||
void Backend::shutdown() {
|
||||
if (service_ == nullptr || shutting_down_) {
|
||||
return;
|
||||
}
|
||||
shutting_down_ = true;
|
||||
desired_mode_ = Mode::kNone;
|
||||
const auto status = ShutdownService(*service_);
|
||||
if (status != NearbySharingService::StatusCodes::kOk) {
|
||||
qWarning() << "Nearby Sharing shutdown failed:"
|
||||
<< NearbySharingService::StatusCodeToString(status);
|
||||
}
|
||||
service_ = nullptr;
|
||||
}
|
||||
|
||||
void Backend::OnShareTargetDiscovered(const ShareTarget& target) {
|
||||
QPointer<Backend> backend(this);
|
||||
PostStatus(this, [backend, target]() {
|
||||
if (!backend || backend->shutting_down_) {
|
||||
return;
|
||||
}
|
||||
backend->targets_.ApplyTarget(target);
|
||||
backend->transfers_.ApplyTarget(target);
|
||||
});
|
||||
}
|
||||
|
||||
void Backend::OnTargetDiscovered(const ShareTarget& target) {
|
||||
QMetaObject::invokeMethod(
|
||||
this, [this, target]() { ApplyTarget(target); }, Qt::QueuedConnection);
|
||||
void Backend::OnShareTargetUpdated(const ShareTarget& target) {
|
||||
OnShareTargetDiscovered(target);
|
||||
}
|
||||
|
||||
void Backend::OnTargetUpdated(const ShareTarget& target) {
|
||||
QMetaObject::invokeMethod(
|
||||
this, [this, target]() { ApplyTarget(target); }, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void Backend::OnTargetLost(const ShareTarget& target) {
|
||||
QMetaObject::invokeMethod(
|
||||
this, [this, target]() { RemoveTarget(target); }, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void Backend::OnIncomingTransfer(const std::string& direction,
|
||||
const ShareTarget& target,
|
||||
const Transfer& transfer) {
|
||||
QMetaObject::invokeMethod(
|
||||
this,
|
||||
[this, direction, target, transfer]() {
|
||||
ApplyTarget(target);
|
||||
transfers_.ApplyTransfer(ToQString(direction), target, transfer);
|
||||
emit incomingTransfer(target.id, ToQString(target.device_name),
|
||||
ToQString(transfer.status));
|
||||
},
|
||||
Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void Backend::OnTransferUpdate(const std::string& direction,
|
||||
const ShareTarget& target,
|
||||
const Transfer& transfer) {
|
||||
QMetaObject::invokeMethod(
|
||||
this,
|
||||
[this, direction, target, transfer]() {
|
||||
ApplyTarget(target);
|
||||
transfers_.ApplyTransfer(ToQString(direction), target, transfer);
|
||||
emit transferUpdate(target.id, ToQString(target.device_name),
|
||||
ToQString(transfer.status), transfer.progress);
|
||||
},
|
||||
Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void Backend::OnStatusChanged(const Status& status) {
|
||||
QMetaObject::invokeMethod(
|
||||
this, [this, status]() { ApplyStatus(status); }, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void Backend::ApplyTarget(const ShareTarget& target) {
|
||||
targets_.ApplyTarget(target);
|
||||
transfers_.ApplyTarget(target);
|
||||
}
|
||||
|
||||
void Backend::RemoveTarget(const ShareTarget& target) {
|
||||
targets_.RemoveTarget(target.id);
|
||||
}
|
||||
|
||||
void Backend::ApplyStatus(const Status& status) {
|
||||
status_ = status;
|
||||
targets_.ResetTargets(status.targets);
|
||||
emit statusChanged();
|
||||
}
|
||||
|
||||
void Backend::ApplyCommandResult(const QString& command,
|
||||
const std::tuple<bool, std::string>& result) {
|
||||
const auto& [ok, message] = result;
|
||||
const QString detail =
|
||||
message.empty() ? (ok ? QStringLiteral("ok") : QStringLiteral("failed"))
|
||||
: ToQString(message);
|
||||
SetStatusText(QStringLiteral("%1: %2").arg(command, detail));
|
||||
}
|
||||
|
||||
void Backend::RunCommand(
|
||||
const QString& command,
|
||||
const std::function<std::tuple<bool, std::string>()>& operation) {
|
||||
if (!client_) {
|
||||
SetStatusText(QStringLiteral("%1 failed: not connected").arg(command));
|
||||
return;
|
||||
}
|
||||
|
||||
void Backend::OnShareTargetLost(const ShareTarget& target) {
|
||||
QPointer<Backend> backend(this);
|
||||
std::thread([backend, command, operation]() {
|
||||
try {
|
||||
auto result = operation();
|
||||
if (!backend) {
|
||||
return;
|
||||
}
|
||||
QMetaObject::invokeMethod(
|
||||
backend,
|
||||
[backend, command, result = std::move(result)]() {
|
||||
if (!backend) {
|
||||
return;
|
||||
}
|
||||
backend->ApplyCommandResult(command, result);
|
||||
},
|
||||
Qt::QueuedConnection);
|
||||
} catch (const sdbus::Error& error) {
|
||||
const QString message = QStringLiteral("%1 failed: %2")
|
||||
.arg(command, QString::fromStdString(
|
||||
error.getMessage()));
|
||||
if (!backend) {
|
||||
return;
|
||||
}
|
||||
QMetaObject::invokeMethod(
|
||||
backend,
|
||||
[backend, message]() {
|
||||
if (!backend) {
|
||||
return;
|
||||
}
|
||||
backend->SetStatusText(message);
|
||||
},
|
||||
Qt::QueuedConnection);
|
||||
PostStatus(this, [backend, id = target.id]() {
|
||||
if (backend && !backend->shutting_down_) {
|
||||
backend->targets_.RemoveTarget(id);
|
||||
}
|
||||
}).detach();
|
||||
});
|
||||
}
|
||||
|
||||
void Backend::OnTransferUpdate(
|
||||
bool receive_mode, const ShareTarget& target,
|
||||
const nearby::sharing::AttachmentContainer& attachments,
|
||||
const TransferMetadata& transfer) {
|
||||
const int64_t total_bytes = attachments.GetTotalAttachmentsSize();
|
||||
QPointer<Backend> backend(this);
|
||||
PostStatus(this, [backend, receive_mode, target, transfer, total_bytes]() {
|
||||
if (!backend || backend->shutting_down_) {
|
||||
return;
|
||||
}
|
||||
backend->targets_.ApplyTarget(target);
|
||||
backend->transfers_.ApplyTransfer(receive_mode, target, transfer,
|
||||
total_bytes);
|
||||
if (receive_mode &&
|
||||
transfer.status() ==
|
||||
TransferMetadata::Status::kAwaitingLocalConfirmation) {
|
||||
emit backend->incomingTransfer(target.id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Backend::SetStatusText(const QString& text) {
|
||||
if (status_text_ == text) {
|
||||
void Backend::SetDesiredMode(Mode mode) {
|
||||
desired_mode_ = mode;
|
||||
DriveMode();
|
||||
}
|
||||
|
||||
void Backend::DriveMode() {
|
||||
if (!initialized_ || service_ == nullptr || shutting_down_ ||
|
||||
mode_operation_in_flight_ || active_mode_ == desired_mode_) {
|
||||
return;
|
||||
}
|
||||
status_text_ = text;
|
||||
emit statusTextChanged();
|
||||
|
||||
mode_operation_in_flight_ = true;
|
||||
QPointer<Backend> backend(this);
|
||||
if (active_mode_ == Mode::kReceive) {
|
||||
service_->UnregisterReceiveSurface(
|
||||
&receive_transfer_callback_,
|
||||
[backend](NearbySharingService::StatusCodes status) mutable {
|
||||
if (backend) {
|
||||
PostStatus(backend, [backend, status]() {
|
||||
if (backend) {
|
||||
backend->OnModeStopped(Mode::kReceive, status);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (active_mode_ == Mode::kDiscovery) {
|
||||
service_->UnregisterSendSurface(
|
||||
&send_transfer_callback_,
|
||||
[backend](NearbySharingService::StatusCodes status) mutable {
|
||||
if (backend) {
|
||||
PostStatus(backend, [backend, status]() {
|
||||
if (backend) {
|
||||
backend->OnModeStopped(Mode::kDiscovery, status);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const Mode mode = desired_mode_;
|
||||
if (mode == Mode::kReceive) {
|
||||
service_->RegisterReceiveSurface(
|
||||
&receive_transfer_callback_,
|
||||
NearbySharingService::ReceiveSurfaceState::kForeground,
|
||||
nearby::sharing::Advertisement::BlockedVendorId::kNone,
|
||||
[backend, mode](NearbySharingService::StatusCodes status) mutable {
|
||||
if (backend) {
|
||||
PostStatus(backend, [backend, mode, status]() {
|
||||
if (backend) {
|
||||
backend->OnModeStarted(mode, status);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (mode == Mode::kDiscovery) {
|
||||
service_->RegisterSendSurface(
|
||||
&send_transfer_callback_, this,
|
||||
NearbySharingService::SendSurfaceState::kForeground,
|
||||
nearby::sharing::Advertisement::BlockedVendorId::kNone,
|
||||
/*disable_wifi_hotspot=*/false,
|
||||
[backend, mode](NearbySharingService::StatusCodes status) mutable {
|
||||
if (backend) {
|
||||
PostStatus(backend, [backend, mode, status]() {
|
||||
if (backend) {
|
||||
backend->OnModeStarted(mode, status);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
mode_operation_in_flight_ = false;
|
||||
}
|
||||
|
||||
void Backend::OnModeStopped(Mode mode,
|
||||
NearbySharingService::StatusCodes status) {
|
||||
mode_operation_in_flight_ = false;
|
||||
if (shutting_down_) {
|
||||
return;
|
||||
}
|
||||
if (status == NearbySharingService::StatusCodes::kOk ||
|
||||
status == NearbySharingService::StatusCodes::kStatusAlreadyStopped) {
|
||||
active_mode_ = Mode::kNone;
|
||||
if (mode == Mode::kDiscovery) {
|
||||
targets_.Clear();
|
||||
}
|
||||
} else {
|
||||
desired_mode_ = active_mode_;
|
||||
ReportStatus(QStringLiteral("Stop sharing mode"), status);
|
||||
}
|
||||
DriveMode();
|
||||
}
|
||||
|
||||
void Backend::OnModeStarted(Mode mode,
|
||||
NearbySharingService::StatusCodes status) {
|
||||
mode_operation_in_flight_ = false;
|
||||
if (shutting_down_) {
|
||||
return;
|
||||
}
|
||||
if (status == NearbySharingService::StatusCodes::kOk) {
|
||||
active_mode_ = mode;
|
||||
} else {
|
||||
desired_mode_ = Mode::kNone;
|
||||
ReportStatus(QStringLiteral("Start sharing mode"), status);
|
||||
}
|
||||
DriveMode();
|
||||
}
|
||||
|
||||
std::function<void(NearbySharingService::StatusCodes)> Backend::StatusCallback(
|
||||
QString operation) {
|
||||
QPointer<Backend> backend(this);
|
||||
return [backend, operation = std::move(operation)](
|
||||
NearbySharingService::StatusCodes status) {
|
||||
if (backend) {
|
||||
PostStatus(backend, [backend, operation, status]() {
|
||||
if (backend && !backend->shutting_down_) {
|
||||
backend->ReportStatus(operation, status);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void Backend::ReportStatus(const QString& operation,
|
||||
NearbySharingService::StatusCodes status) {
|
||||
if (status != NearbySharingService::StatusCodes::kOk) {
|
||||
qWarning().noquote()
|
||||
<< operation + QStringLiteral(" failed: ") +
|
||||
ToQString(NearbySharingService::StatusCodeToString(status));
|
||||
}
|
||||
}
|
||||
|
||||
+70
-72
@@ -5,7 +5,6 @@
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include <QAbstractListModel>
|
||||
@@ -14,24 +13,25 @@
|
||||
|
||||
#include "QtQmlIntegration/qqmlintegration.h"
|
||||
#include "qtmetamacros.h"
|
||||
#include "sharing/linux/app/nearby_sharing_dbus_client.h"
|
||||
#include "sharing/attachment_container.h"
|
||||
#include "sharing/linux/nearby_noop_analytics_recorder.h"
|
||||
#include "sharing/linux/platform/linux_sharing_platform.h"
|
||||
#include "sharing/nearby_sharing_service.h"
|
||||
#include "sharing/share_target.h"
|
||||
#include "sharing/share_target_discovered_callback.h"
|
||||
#include "sharing/transfer_metadata.h"
|
||||
#include "sharing/transfer_update_callback.h"
|
||||
|
||||
class ShareTargetModel : public QAbstractListModel {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
using ShareTarget = nearby::sharing::linux::app::ShareTarget;
|
||||
using ShareTarget = nearby::sharing::ShareTarget;
|
||||
|
||||
enum Role {
|
||||
IdRole = Qt::UserRole + 1,
|
||||
DeviceNameRole,
|
||||
TypeRole,
|
||||
IsIncomingRole,
|
||||
IsKnownRole,
|
||||
DeviceIdRole,
|
||||
ForSelfShareRole,
|
||||
VendorIdRole,
|
||||
ReceiveDisabledRole,
|
||||
};
|
||||
|
||||
explicit ShareTargetModel(QObject* parent = nullptr);
|
||||
@@ -42,7 +42,7 @@ class ShareTargetModel : public QAbstractListModel {
|
||||
|
||||
void ApplyTarget(const ShareTarget& target);
|
||||
void RemoveTarget(int64_t target_id);
|
||||
void ResetTargets(const std::vector<ShareTarget>& targets);
|
||||
void Clear();
|
||||
std::optional<ShareTarget> FindTarget(int64_t target_id) const;
|
||||
|
||||
private:
|
||||
@@ -55,25 +55,20 @@ class ShareTransferModel : public QAbstractListModel {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
using ShareTarget = nearby::sharing::linux::app::ShareTarget;
|
||||
using Transfer = nearby::sharing::linux::app::Transfer;
|
||||
using ShareTarget = nearby::sharing::ShareTarget;
|
||||
using TransferMetadata = nearby::sharing::TransferMetadata;
|
||||
|
||||
enum Role {
|
||||
IdRole = Qt::UserRole + 1,
|
||||
DirectionRole,
|
||||
DeviceNameRole,
|
||||
TypeRole,
|
||||
StatusRole,
|
||||
ProgressRole,
|
||||
TransferredBytesRole,
|
||||
TotalBytesRole,
|
||||
TransferSpeedRole,
|
||||
EstimatedTimeRemainingRole,
|
||||
TotalAttachmentsCountRole,
|
||||
TransferredAttachmentsCountRole,
|
||||
IsFinalStatusRole,
|
||||
HasTargetRole,
|
||||
HasTransferRole,
|
||||
AwaitingLocalConfirmationRole,
|
||||
LocalPathRole,
|
||||
};
|
||||
@@ -85,18 +80,18 @@ class ShareTransferModel : public QAbstractListModel {
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
void ApplyTarget(const ShareTarget& target);
|
||||
void ApplyTransfer(const QString& direction, const ShareTarget& target,
|
||||
const Transfer& transfer);
|
||||
void ApplyTransfer(bool receive_mode, const ShareTarget& target,
|
||||
const TransferMetadata& transfer, int64_t total_bytes);
|
||||
void PrepareOutgoingTransfer(int64_t target_id, const QString& local_path,
|
||||
const std::optional<ShareTarget>& target);
|
||||
void RemoveTransfer(int64_t target_id);
|
||||
|
||||
private:
|
||||
struct Row {
|
||||
int64_t id = 0;
|
||||
QString direction;
|
||||
bool receive_mode = false;
|
||||
std::optional<ShareTarget> target;
|
||||
std::optional<Transfer> transfer;
|
||||
std::optional<TransferMetadata> transfer;
|
||||
int64_t total_bytes = 0;
|
||||
QString local_path;
|
||||
};
|
||||
|
||||
@@ -107,17 +102,10 @@ class ShareTransferModel : public QAbstractListModel {
|
||||
std::vector<Row> transfers_;
|
||||
};
|
||||
|
||||
class Backend
|
||||
: public QObject,
|
||||
public nearby::sharing::linux::app::NearbySharingDbusClient::Observer {
|
||||
class Backend : public QObject,
|
||||
public nearby::sharing::ShareTargetDiscoveredCallback {
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
Q_PROPERTY(QString statusText READ statusText NOTIFY statusTextChanged)
|
||||
Q_PROPERTY(bool receiveRegistered READ receiveRegistered NOTIFY statusChanged)
|
||||
Q_PROPERTY(
|
||||
bool discoveryRegistered READ discoveryRegistered NOTIFY statusChanged)
|
||||
Q_PROPERTY(bool scanning READ scanning NOTIFY statusChanged)
|
||||
Q_PROPERTY(bool transferring READ transferring NOTIFY statusChanged)
|
||||
Q_PROPERTY(QAbstractListModel* targets READ targets CONSTANT)
|
||||
Q_PROPERTY(QAbstractListModel* transfers READ transfers CONSTANT)
|
||||
|
||||
@@ -125,63 +113,73 @@ class Backend
|
||||
explicit Backend(QObject* parent = nullptr);
|
||||
~Backend() override;
|
||||
|
||||
QString statusText() const { return status_text_; }
|
||||
bool receiveRegistered() const { return status_.receive_registered; }
|
||||
bool discoveryRegistered() const { return status_.discovery_registered; }
|
||||
bool scanning() const { return status_.is_scanning; }
|
||||
bool transferring() const { return status_.is_transferring; }
|
||||
QAbstractListModel* targets() { return &targets_; }
|
||||
QAbstractListModel* transfers() { return &transfers_; }
|
||||
|
||||
Q_INVOKABLE void startReceive();
|
||||
Q_INVOKABLE void stopReceive();
|
||||
Q_INVOKABLE void startDiscovery();
|
||||
Q_INVOKABLE void stopDiscovery();
|
||||
Q_INVOKABLE void sendFile(qint64 share_target_id, const QString& path);
|
||||
Q_INVOKABLE void prepareOutgoingTransfer(qint64 share_target_id,
|
||||
const QString& path);
|
||||
Q_INVOKABLE void accept(qint64 share_target_id);
|
||||
Q_INVOKABLE void reject(qint64 share_target_id);
|
||||
Q_INVOKABLE void cancel(qint64 share_target_id);
|
||||
void shutdown();
|
||||
|
||||
signals:
|
||||
void statusTextChanged();
|
||||
void statusChanged();
|
||||
void incomingTransfer(qint64 share_target_id, QString device_name,
|
||||
QString status);
|
||||
void transferUpdate(qint64 share_target_id, QString device_name,
|
||||
QString status, double progress);
|
||||
void incomingTransfer(qint64 share_target_id);
|
||||
|
||||
private:
|
||||
using Client = nearby::sharing::linux::app::NearbySharingDbusClient;
|
||||
using ShareTarget = nearby::sharing::linux::app::ShareTarget;
|
||||
using Status = nearby::sharing::linux::app::Status;
|
||||
using Transfer = nearby::sharing::linux::app::Transfer;
|
||||
using NearbySharingService = nearby::sharing::NearbySharingService;
|
||||
using ShareTarget = nearby::sharing::ShareTarget;
|
||||
using TransferMetadata = nearby::sharing::TransferMetadata;
|
||||
|
||||
void OnTargetDiscovered(const ShareTarget& target) override;
|
||||
void OnTargetUpdated(const ShareTarget& target) override;
|
||||
void OnTargetLost(const ShareTarget& target) override;
|
||||
void OnIncomingTransfer(const std::string& direction,
|
||||
const ShareTarget& target,
|
||||
const Transfer& transfer) override;
|
||||
void OnTransferUpdate(const std::string& direction, const ShareTarget& target,
|
||||
const Transfer& transfer) override;
|
||||
void OnStatusChanged(const Status& status) override;
|
||||
class TransferCallback final
|
||||
: public nearby::sharing::TransferUpdateCallback {
|
||||
public:
|
||||
TransferCallback(Backend& backend, bool receive_mode)
|
||||
: backend_(backend), receive_mode_(receive_mode) {}
|
||||
|
||||
void ApplyTarget(const ShareTarget& target);
|
||||
void RemoveTarget(const ShareTarget& target);
|
||||
void ApplyStatus(const Status& status);
|
||||
void ApplyCommandResult(const QString& command,
|
||||
const std::tuple<bool, std::string>& result);
|
||||
void RunCommand(
|
||||
const QString& command,
|
||||
const std::function<std::tuple<bool, std::string>()>& operation);
|
||||
void SetStatusText(const QString& text);
|
||||
void OnTransferUpdate(
|
||||
const ShareTarget& share_target,
|
||||
const nearby::sharing::AttachmentContainer& attachment_container,
|
||||
const TransferMetadata& transfer_metadata) override;
|
||||
|
||||
private:
|
||||
Backend& backend_;
|
||||
bool receive_mode_;
|
||||
};
|
||||
|
||||
enum class Mode {
|
||||
kNone,
|
||||
kReceive,
|
||||
kDiscovery,
|
||||
};
|
||||
|
||||
void OnShareTargetDiscovered(const ShareTarget& target) override;
|
||||
void OnShareTargetUpdated(const ShareTarget& target) override;
|
||||
void OnShareTargetLost(const ShareTarget& target) override;
|
||||
void OnTransferUpdate(bool receive_mode, const ShareTarget& target,
|
||||
const nearby::sharing::AttachmentContainer& attachments,
|
||||
const TransferMetadata& transfer);
|
||||
|
||||
void SetDesiredMode(Mode mode);
|
||||
void DriveMode();
|
||||
void OnModeStopped(Mode mode, NearbySharingService::StatusCodes status);
|
||||
void OnModeStarted(Mode mode, NearbySharingService::StatusCodes status);
|
||||
std::function<void(NearbySharingService::StatusCodes)> StatusCallback(
|
||||
QString operation);
|
||||
void ReportStatus(const QString& operation,
|
||||
NearbySharingService::StatusCodes status);
|
||||
|
||||
QString status_text_;
|
||||
Status status_;
|
||||
ShareTargetModel targets_;
|
||||
ShareTransferModel transfers_;
|
||||
std::unique_ptr<Client> client_;
|
||||
bool is_incoming_transfer_ = false;
|
||||
nearby::sharing::linux::NoOpAnalyticsRecorder analytics_recorder_;
|
||||
nearby::sharing::linux::LinuxSharingPlatform platform_;
|
||||
NearbySharingService* service_ = nullptr;
|
||||
TransferCallback send_transfer_callback_;
|
||||
TransferCallback receive_transfer_callback_;
|
||||
Mode active_mode_ = Mode::kNone;
|
||||
Mode desired_mode_ = Mode::kReceive;
|
||||
bool initialized_ = false;
|
||||
bool mode_operation_in_flight_ = false;
|
||||
bool shutting_down_ = false;
|
||||
};
|
||||
|
||||
+10
-19
@@ -81,19 +81,7 @@ bool RequiresFullReload(const QFileInfo& changed_file) {
|
||||
return changed_file.fileName() == QStringLiteral("main.qml");
|
||||
}
|
||||
|
||||
void InstallTerminationCleanup(QApplication& app, Backend& backend) {
|
||||
auto cleanup_done = std::make_shared<bool>(false);
|
||||
const auto cleanup = [&backend, cleanup_done]() {
|
||||
if (*cleanup_done) {
|
||||
return;
|
||||
}
|
||||
*cleanup_done = true;
|
||||
backend.stopDiscovery();
|
||||
backend.stopReceive();
|
||||
};
|
||||
|
||||
QObject::connect(&app, &QCoreApplication::aboutToQuit, &app, cleanup);
|
||||
|
||||
void InstallTerminationCleanup(QApplication& app) {
|
||||
if (pipe(g_signal_pipe) != 0) {
|
||||
return;
|
||||
}
|
||||
@@ -105,12 +93,11 @@ void InstallTerminationCleanup(QApplication& app, Backend& backend) {
|
||||
auto* notifier = new QSocketNotifier(g_signal_pipe[0],
|
||||
QSocketNotifier::Read, &app);
|
||||
QObject::connect(notifier, &QSocketNotifier::activated, &app,
|
||||
[&app, notifier, cleanup](int socket) {
|
||||
[&app, notifier](int socket) {
|
||||
notifier->setEnabled(false);
|
||||
char buffer[32];
|
||||
while (read(socket, buffer, sizeof(buffer)) > 0) {
|
||||
}
|
||||
cleanup();
|
||||
app.quit();
|
||||
});
|
||||
|
||||
@@ -127,9 +114,9 @@ void InstallTerminationCleanup(QApplication& app, Backend& backend) {
|
||||
int main(int argc, char* argv[]) {
|
||||
QApplication app(argc, argv);
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
Backend backend;
|
||||
InstallTerminationCleanup(app, backend);
|
||||
QQmlApplicationEngine engine;
|
||||
InstallTerminationCleanup(app);
|
||||
|
||||
const int fontId = QFontDatabase::addApplicationFont(":/googlesans_var.ttf");
|
||||
|
||||
@@ -192,7 +179,9 @@ int main(int argc, char* argv[]) {
|
||||
watcher.addPath(qml_source_dir.absolutePath());
|
||||
fullReload();
|
||||
|
||||
return app.exec();
|
||||
const int result = app.exec();
|
||||
backend.shutdown();
|
||||
return result;
|
||||
}
|
||||
|
||||
engine.rootContext()->setContextProperty("backend", &backend);
|
||||
@@ -208,5 +197,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
engine.load(url);
|
||||
|
||||
return app.exec();
|
||||
const int result = app.exec();
|
||||
backend.shutdown();
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,214 +0,0 @@
|
||||
#include "sharing/linux/app/nearby_sharing_dbus_client.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace nearby::sharing::linux::app {
|
||||
namespace {
|
||||
|
||||
template <typename T>
|
||||
T GetField(const DbusDictionary& map, const std::string& key,
|
||||
T default_value = T{}) {
|
||||
auto it = map.find(key);
|
||||
if (it == map.end()) {
|
||||
return default_value;
|
||||
}
|
||||
|
||||
try {
|
||||
return it->second.get<T>();
|
||||
} catch (const sdbus::Error&) {
|
||||
return default_value;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::optional<T> GetOptionalField(const DbusDictionary& map,
|
||||
const std::string& key) {
|
||||
auto it = map.find(key);
|
||||
if (it == map.end()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
try {
|
||||
return it->second.get<T>();
|
||||
} catch (const sdbus::Error&) {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
double GetProgress(const DbusDictionary& map) {
|
||||
if (auto progress = GetOptionalField<double>(map, "progress")) {
|
||||
return *progress;
|
||||
}
|
||||
if (auto progress = GetOptionalField<int32_t>(map, "progress")) {
|
||||
return *progress;
|
||||
}
|
||||
if (auto progress = GetOptionalField<int64_t>(map, "progress")) {
|
||||
return *progress;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NearbySharingDbusClient::NearbySharingDbusClient(Observer* observer)
|
||||
: sdbus::ProxyInterfaces<com::google::nearby::sharing_proxy>(
|
||||
sdbus::ServiceName("com.google.nearby.sharing"),
|
||||
sdbus::ObjectPath("/com/google/nearby/sharing")),
|
||||
observer_(observer) {
|
||||
registerProxy();
|
||||
}
|
||||
|
||||
NearbySharingDbusClient::~NearbySharingDbusClient() {
|
||||
unregisterProxy();
|
||||
}
|
||||
|
||||
std::tuple<bool, std::string> NearbySharingDbusClient::StartReceive() {
|
||||
return com::google::nearby::sharing_proxy::StartReceive();
|
||||
}
|
||||
|
||||
std::tuple<bool, std::string> NearbySharingDbusClient::StopReceive() {
|
||||
return com::google::nearby::sharing_proxy::StopReceive();
|
||||
}
|
||||
|
||||
std::tuple<bool, std::string> NearbySharingDbusClient::StartDiscovery() {
|
||||
return com::google::nearby::sharing_proxy::StartDiscovery();
|
||||
}
|
||||
|
||||
std::tuple<bool, std::string> NearbySharingDbusClient::StopDiscovery() {
|
||||
return com::google::nearby::sharing_proxy::StopDiscovery();
|
||||
}
|
||||
|
||||
std::tuple<bool, std::string> NearbySharingDbusClient::SendFile(
|
||||
int64_t share_target_id, const std::string& path) {
|
||||
return com::google::nearby::sharing_proxy::SendFile(share_target_id, path);
|
||||
}
|
||||
|
||||
std::tuple<bool, std::string> NearbySharingDbusClient::Accept(
|
||||
int64_t share_target_id) {
|
||||
return com::google::nearby::sharing_proxy::Accept(share_target_id);
|
||||
}
|
||||
|
||||
std::tuple<bool, std::string> NearbySharingDbusClient::Reject(
|
||||
int64_t share_target_id) {
|
||||
return com::google::nearby::sharing_proxy::Reject(share_target_id);
|
||||
}
|
||||
|
||||
std::tuple<bool, std::string> NearbySharingDbusClient::Cancel(
|
||||
int64_t share_target_id) {
|
||||
return com::google::nearby::sharing_proxy::Cancel(share_target_id);
|
||||
}
|
||||
|
||||
ShareTarget NearbySharingDbusClient::ConvertToShareTarget(
|
||||
const DbusDictionary& map) {
|
||||
ShareTarget target;
|
||||
target.id = GetField<int64_t>(map, "id");
|
||||
target.device_name = GetField<std::string>(map, "device_name");
|
||||
target.type = GetField<int32_t>(map, "type");
|
||||
target.is_incoming = GetField<bool>(map, "is_incoming");
|
||||
target.is_known = GetField<bool>(map, "is_known");
|
||||
target.device_id = GetField<std::string>(map, "device_id");
|
||||
target.for_self_share = GetField<bool>(map, "for_self_share");
|
||||
target.vendor_id = GetField<int32_t>(map, "vendor_id");
|
||||
target.receive_disabled = GetField<bool>(map, "receive_disabled");
|
||||
return target;
|
||||
}
|
||||
|
||||
Transfer NearbySharingDbusClient::ConvertToTransfer(const DbusDictionary& map) {
|
||||
Transfer transfer;
|
||||
transfer.status = GetField<std::string>(map, "status");
|
||||
transfer.progress = GetProgress(map);
|
||||
transfer.transferred_bytes = GetField<int64_t>(map, "transferred_bytes");
|
||||
transfer.total_bytes = GetField<int64_t>(map, "total_bytes");
|
||||
transfer.transfer_speed = GetField<int64_t>(map, "transfer_speed");
|
||||
transfer.estimated_time_remaining =
|
||||
GetField<int64_t>(map, "estimated_time_remaining");
|
||||
transfer.total_attachments_count =
|
||||
GetField<int32_t>(map, "total_attachments_count");
|
||||
transfer.transferred_attachments_count =
|
||||
GetField<int32_t>(map, "transferred_attachments_count");
|
||||
transfer.is_final_status = GetField<bool>(map, "is_final_status");
|
||||
transfer.is_self_share = GetField<bool>(map, "is_self_share");
|
||||
transfer.binding_id = GetField<std::string>(map, "binding_id");
|
||||
transfer.token = GetOptionalField<std::string>(map, "token");
|
||||
transfer.in_progress_attachment_id =
|
||||
GetOptionalField<int64_t>(map, "in_progress_attachment_id");
|
||||
transfer.in_progress_attachment_transferred_bytes = GetOptionalField<int64_t>(
|
||||
map, "in_progress_attachment_transferred_bytes");
|
||||
transfer.in_progress_attachment_total_bytes =
|
||||
GetOptionalField<int64_t>(map, "in_progress_attachment_total_bytes");
|
||||
return transfer;
|
||||
}
|
||||
|
||||
Status NearbySharingDbusClient::ConvertToStatus(const DbusDictionary& map) {
|
||||
Status status;
|
||||
status.receive_registered = GetField<bool>(map, "receive_registered");
|
||||
status.discovery_registered = GetField<bool>(map, "discovery_registered");
|
||||
status.is_transferring = GetField<bool>(map, "is_transferring");
|
||||
status.is_scanning = GetField<bool>(map, "is_scanning");
|
||||
status.bluetooth_present = GetField<bool>(map, "bluetooth_present");
|
||||
status.bluetooth_powered = GetField<bool>(map, "bluetooth_powered");
|
||||
status.lan_connected = GetField<bool>(map, "lan_connected");
|
||||
|
||||
auto raw_targets =
|
||||
GetOptionalField<std::vector<DbusDictionary>>(map, "targets");
|
||||
if (raw_targets.has_value()) {
|
||||
status.targets.reserve(raw_targets->size());
|
||||
for (const auto& target : *raw_targets) {
|
||||
status.targets.push_back(ConvertToShareTarget(target));
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void NearbySharingDbusClient::onTargetDiscovered(
|
||||
const DbusDictionary& share_target) {
|
||||
if (observer_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
observer_->OnTargetDiscovered(ConvertToShareTarget(share_target));
|
||||
}
|
||||
|
||||
void NearbySharingDbusClient::onTargetUpdated(
|
||||
const DbusDictionary& share_target) {
|
||||
if (observer_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
observer_->OnTargetUpdated(ConvertToShareTarget(share_target));
|
||||
}
|
||||
|
||||
void NearbySharingDbusClient::onTargetLost(const DbusDictionary& share_target) {
|
||||
if (observer_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
observer_->OnTargetLost(ConvertToShareTarget(share_target));
|
||||
}
|
||||
|
||||
void NearbySharingDbusClient::onIncomingTransfer(
|
||||
const std::string& direction, const DbusDictionary& share_target,
|
||||
const DbusDictionary& transfer) {
|
||||
if (observer_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
observer_->OnIncomingTransfer(direction, ConvertToShareTarget(share_target),
|
||||
ConvertToTransfer(transfer));
|
||||
}
|
||||
|
||||
void NearbySharingDbusClient::onTransferUpdate(
|
||||
const std::string& direction, const DbusDictionary& share_target,
|
||||
const DbusDictionary& transfer) {
|
||||
if (observer_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
observer_->OnTransferUpdate(direction, ConvertToShareTarget(share_target),
|
||||
ConvertToTransfer(transfer));
|
||||
}
|
||||
|
||||
void NearbySharingDbusClient::onStatusChanged(const DbusDictionary& status) {
|
||||
if (observer_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
observer_->OnStatusChanged(ConvertToStatus(status));
|
||||
}
|
||||
|
||||
} // namespace nearby::sharing::linux::app
|
||||
@@ -1,111 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include <sdbus-c++/sdbus-c++.h>
|
||||
|
||||
#include "sharing/linux/daemon/nearby_sharing_client.h"
|
||||
|
||||
namespace nearby::sharing::linux::app {
|
||||
|
||||
using DbusDictionary = std::map<std::string, sdbus::Variant>;
|
||||
|
||||
struct ShareTarget {
|
||||
int64_t id = 0;
|
||||
std::string device_name;
|
||||
int32_t type = 0;
|
||||
bool is_incoming = false;
|
||||
bool is_known = false;
|
||||
std::string device_id;
|
||||
bool for_self_share = false;
|
||||
int32_t vendor_id = 0;
|
||||
bool receive_disabled = false;
|
||||
};
|
||||
|
||||
struct Transfer {
|
||||
std::string status;
|
||||
double progress = 0;
|
||||
int64_t transferred_bytes = 0;
|
||||
int64_t total_bytes = 0;
|
||||
int64_t transfer_speed = 0;
|
||||
int64_t estimated_time_remaining = 0;
|
||||
int32_t total_attachments_count = 0;
|
||||
int32_t transferred_attachments_count = 0;
|
||||
bool is_final_status = false;
|
||||
bool is_self_share = false;
|
||||
std::string binding_id;
|
||||
std::optional<std::string> token;
|
||||
std::optional<int64_t> in_progress_attachment_id;
|
||||
std::optional<int64_t> in_progress_attachment_transferred_bytes;
|
||||
std::optional<int64_t> in_progress_attachment_total_bytes;
|
||||
};
|
||||
|
||||
struct Status {
|
||||
bool receive_registered = false;
|
||||
bool discovery_registered = false;
|
||||
bool is_transferring = false;
|
||||
bool is_scanning = false;
|
||||
bool bluetooth_present = false;
|
||||
bool bluetooth_powered = false;
|
||||
bool lan_connected = false;
|
||||
std::vector<ShareTarget> targets;
|
||||
};
|
||||
|
||||
class NearbySharingDbusClient
|
||||
: public sdbus::ProxyInterfaces<com::google::nearby::sharing_proxy> {
|
||||
public:
|
||||
struct Observer {
|
||||
virtual ~Observer() = default;
|
||||
virtual void OnTargetDiscovered(const ShareTarget& target) {}
|
||||
virtual void OnTargetUpdated(const ShareTarget& target) {}
|
||||
virtual void OnTargetLost(const ShareTarget& target) {}
|
||||
virtual void OnIncomingTransfer(const std::string& direction,
|
||||
const ShareTarget& target,
|
||||
const Transfer& transfer) {}
|
||||
virtual void OnTransferUpdate(const std::string& direction,
|
||||
const ShareTarget& target,
|
||||
const Transfer& transfer) {}
|
||||
virtual void OnStatusChanged(const Status& status) {}
|
||||
};
|
||||
|
||||
explicit NearbySharingDbusClient(Observer* observer);
|
||||
~NearbySharingDbusClient();
|
||||
|
||||
NearbySharingDbusClient(const NearbySharingDbusClient&) = delete;
|
||||
NearbySharingDbusClient& operator=(const NearbySharingDbusClient&) = delete;
|
||||
|
||||
std::tuple<bool, std::string> StartReceive();
|
||||
std::tuple<bool, std::string> StopReceive();
|
||||
std::tuple<bool, std::string> StartDiscovery();
|
||||
std::tuple<bool, std::string> StopDiscovery();
|
||||
std::tuple<bool, std::string> SendFile(int64_t share_target_id,
|
||||
const std::string& path);
|
||||
std::tuple<bool, std::string> Accept(int64_t share_target_id);
|
||||
std::tuple<bool, std::string> Reject(int64_t share_target_id);
|
||||
std::tuple<bool, std::string> Cancel(int64_t share_target_id);
|
||||
|
||||
static ShareTarget ConvertToShareTarget(const DbusDictionary& map);
|
||||
static Transfer ConvertToTransfer(const DbusDictionary& map);
|
||||
static Status ConvertToStatus(const DbusDictionary& map);
|
||||
|
||||
private:
|
||||
void onTargetDiscovered(const DbusDictionary& share_target) override;
|
||||
void onTargetUpdated(const DbusDictionary& share_target) override;
|
||||
void onTargetLost(const DbusDictionary& share_target) override;
|
||||
void onIncomingTransfer(const std::string& direction,
|
||||
const DbusDictionary& share_target,
|
||||
const DbusDictionary& transfer) override;
|
||||
void onTransferUpdate(const std::string& direction,
|
||||
const DbusDictionary& share_target,
|
||||
const DbusDictionary& transfer) override;
|
||||
void onStatusChanged(const DbusDictionary& status) override;
|
||||
|
||||
Observer* observer_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace nearby::sharing::linux::app
|
||||
@@ -1,59 +0,0 @@
|
||||
load("@rules_cc//cc:cc_library.bzl", "cc_library")
|
||||
load("@rules_cc//cc:cc_binary.bzl", "cc_binary")
|
||||
load("@rules_cc//cc:cc_test.bzl", "cc_test")
|
||||
|
||||
cc_binary(
|
||||
name = "nearby_sharing_daemon",
|
||||
srcs = ["main.cc"],
|
||||
deps = [
|
||||
":nearby_sharing_dbus_service",
|
||||
"//connections/implementation/flags:connections_flags",
|
||||
"//internal/flags:nearby_flags",
|
||||
"//sharing:nearby_sharing_service",
|
||||
"//sharing/flags/generated:generated_flags",
|
||||
"//sharing/linux:linux_sharing_platform",
|
||||
"//sharing/proto:enums_cc_proto",
|
||||
"@com_google_absl//absl/time",
|
||||
"@sdbus_cpp",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "nearby_sharing_dbus_client_glue",
|
||||
hdrs = ["nearby_sharing_client.h"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["@sdbus_cpp"],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "nearby_sharing_dbus_service",
|
||||
srcs = ["nearby_sharing_dbus_service.cc"],
|
||||
hdrs = [
|
||||
"nearby_sharing_dbus_service.h",
|
||||
"nearby_sharing_server.h",
|
||||
"nearby_sharing_client.h",
|
||||
],
|
||||
deps = [
|
||||
"//internal/base:file_path",
|
||||
"//sharing:attachments",
|
||||
"//sharing:nearby_sharing_service",
|
||||
"//sharing:transfer_metadata",
|
||||
"//sharing:types",
|
||||
"@com_google_absl//absl/synchronization",
|
||||
"@sdbus_cpp",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "nearby_sharing_dbus_service_test",
|
||||
srcs = ["nearby_sharing_dbus_service_test.cc"],
|
||||
deps = [
|
||||
":nearby_sharing_dbus_service",
|
||||
"//internal/platform/implementation/linux:linux",
|
||||
"//sharing:attachments",
|
||||
"//sharing:transfer_metadata",
|
||||
"//sharing:types",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
"@sdbus_cpp",
|
||||
],
|
||||
)
|
||||
@@ -1,165 +0,0 @@
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include <sdbus-c++/sdbus-c++.h>
|
||||
|
||||
#include "absl/time/time.h"
|
||||
#include "connections/implementation/flags/nearby_connections_feature_flags.h"
|
||||
#include "internal/flags/nearby_flags.h"
|
||||
#include "sharing/flags/generated/nearby_sharing_feature_flags.h"
|
||||
#include "sharing/linux/daemon/nearby_sharing_dbus_service.h"
|
||||
#include "sharing/linux/nearby_noop_analytics_recorder.h"
|
||||
#include "sharing/linux/platform/linux_sharing_platform.h"
|
||||
#include "sharing/nearby_sharing_service.h"
|
||||
#include "sharing/nearby_sharing_service_factory.h"
|
||||
#include "sharing/nearby_sharing_settings.h"
|
||||
#include "sharing/proto/enums.pb.h"
|
||||
|
||||
namespace nearby::sharing::linux {
|
||||
namespace {
|
||||
|
||||
std::atomic<bool> g_interrupted = false;
|
||||
sdbus::IConnection* g_bus = nullptr;
|
||||
|
||||
void HandleSignal(int signal) {
|
||||
static_cast<void>(signal);
|
||||
g_interrupted = true;
|
||||
if (g_bus != nullptr) {
|
||||
g_bus->leaveEventLoop();
|
||||
}
|
||||
}
|
||||
|
||||
std::string GetHostname() {
|
||||
char hostname[256] = {};
|
||||
if (gethostname(hostname, sizeof(hostname)) == 0 && hostname[0] != '\0') {
|
||||
return std::string(hostname);
|
||||
}
|
||||
return "LinuxShare";
|
||||
}
|
||||
|
||||
std::string GetDeviceName(int argc, char** argv) {
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
std::string arg = argv[i];
|
||||
if (arg == "--name" && i + 1 < argc) {
|
||||
return argv[i + 1];
|
||||
}
|
||||
}
|
||||
const char* env_name = std::getenv("NEARBY_DEVICE_NAME");
|
||||
if (env_name != nullptr && *env_name != '\0') {
|
||||
return env_name;
|
||||
}
|
||||
return GetHostname();
|
||||
}
|
||||
|
||||
template <typename Invoker>
|
||||
NearbySharingService::StatusCodes WaitForStatus(Invoker invoker) {
|
||||
std::mutex mutex;
|
||||
std::condition_variable cv;
|
||||
std::optional<NearbySharingService::StatusCodes> status;
|
||||
invoker([&](NearbySharingService::StatusCodes callback_status) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
status = callback_status;
|
||||
}
|
||||
cv.notify_one();
|
||||
});
|
||||
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
cv.wait(lock, [&] { return status.has_value(); });
|
||||
return *status;
|
||||
}
|
||||
|
||||
void ConfigureFlags() {
|
||||
nearby::NearbyFlags::GetInstance().OverrideBoolFlagValue(
|
||||
nearby::sharing::config_package_nearby::nearby_sharing_feature::
|
||||
kEnableBleForTransfer,
|
||||
true);
|
||||
nearby::NearbyFlags::GetInstance().OverrideBoolFlagValue(
|
||||
nearby::connections::config_package_nearby::nearby_connections_feature::
|
||||
kEnableBleL2cap,
|
||||
true);
|
||||
nearby::NearbyFlags::GetInstance().OverrideBoolFlagValue(
|
||||
nearby::connections::config_package_nearby::nearby_connections_feature::
|
||||
kRefactorBleL2cap,
|
||||
true);
|
||||
}
|
||||
|
||||
bool ConfigureSharingService(NearbySharingService& service,
|
||||
const std::string& device_name) {
|
||||
service.GetSettings()->SetDataUsage(proto::WIFI_ONLY_DATA_USAGE);
|
||||
service.GetSettings()->SetDeviceName(
|
||||
device_name, [](DeviceNameValidationResult validation_result) {
|
||||
static_cast<void>(validation_result);
|
||||
});
|
||||
auto status = WaitForStatus([&](auto callback) {
|
||||
service.SetVisibility(proto::DEVICE_VISIBILITY_EVERYONE,
|
||||
absl::ZeroDuration(), std::move(callback));
|
||||
});
|
||||
if (status != NearbySharingService::StatusCodes::kOk) {
|
||||
std::cerr << "SetVisibility failed: "
|
||||
<< NearbySharingService::StatusCodeToString(status) << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace nearby::sharing::linux
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
signal(SIGINT, nearby::sharing::linux::HandleSignal);
|
||||
signal(SIGTERM, nearby::sharing::linux::HandleSignal);
|
||||
|
||||
nearby::sharing::linux::ConfigureFlags();
|
||||
|
||||
const std::string device_name =
|
||||
nearby::sharing::linux::GetDeviceName(argc, argv);
|
||||
auto analytics_recorder = nearby::sharing::linux::NoOpAnalyticsRecorder();
|
||||
auto linux_platform =
|
||||
nearby::sharing::linux::LinuxSharingPlatform(device_name);
|
||||
auto* service =
|
||||
nearby::sharing::NearbySharingServiceFactory::GetInstance()
|
||||
->CreateSharingService(linux_platform, &analytics_recorder,
|
||||
/*event_logger=*/nullptr,
|
||||
/*supports_file_sync=*/false);
|
||||
if (service == nullptr) {
|
||||
std::cerr << "failed to create NearbySharingService" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
if (!nearby::sharing::linux::ConfigureSharingService(*service, device_name)) {
|
||||
nearby::sharing::linux::WaitForStatus(
|
||||
[&](auto callback) { service->Shutdown(std::move(callback)); });
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto bus = sdbus::createSessionBusConnection(
|
||||
sdbus::ServiceName("com.google.nearby.sharing"));
|
||||
nearby::sharing::linux::g_bus = bus.get();
|
||||
auto object = sdbus::createObject(
|
||||
*bus, sdbus::ObjectPath("/com/google/nearby/sharing"));
|
||||
nearby::sharing::linux::NearbySharingDbusService dbus_service(
|
||||
*object, *service, [&bus]() { bus->leaveEventLoop(); });
|
||||
dbus_service.EmitStatusChanged();
|
||||
|
||||
try {
|
||||
bus->enterEventLoop();
|
||||
} catch (const sdbus::Error& error) {
|
||||
std::cerr << "D-Bus event loop failed: " << error.getName() << ": "
|
||||
<< error.getMessage() << std::endl;
|
||||
dbus_service.ShutdownService();
|
||||
nearby::sharing::linux::g_bus = nullptr;
|
||||
return 1;
|
||||
}
|
||||
|
||||
dbus_service.ShutdownService();
|
||||
nearby::sharing::linux::g_bus = nullptr;
|
||||
return nearby::sharing::linux::g_interrupted ? 130 : 0;
|
||||
}
|
||||
@@ -1,174 +0,0 @@
|
||||
|
||||
/*
|
||||
* This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
|
||||
*/
|
||||
|
||||
#ifndef __sdbuscpp__sharing_linux_daemon_nearby_sharing_client_h__proxy__H__
|
||||
#define __sdbuscpp__sharing_linux_daemon_nearby_sharing_client_h__proxy__H__
|
||||
|
||||
#include <sdbus-c++/sdbus-c++.h>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
namespace com {
|
||||
namespace google {
|
||||
namespace nearby {
|
||||
|
||||
class sharing_proxy {
|
||||
public:
|
||||
static constexpr const char* INTERFACE_NAME = "com.google.nearby.sharing";
|
||||
|
||||
protected:
|
||||
sharing_proxy(sdbus::IProxy& proxy) : m_proxy(proxy) {}
|
||||
|
||||
sharing_proxy(const sharing_proxy&) = delete;
|
||||
sharing_proxy& operator=(const sharing_proxy&) = delete;
|
||||
sharing_proxy(sharing_proxy&&) = delete;
|
||||
sharing_proxy& operator=(sharing_proxy&&) = delete;
|
||||
|
||||
~sharing_proxy() = default;
|
||||
|
||||
void registerProxy() {
|
||||
m_proxy.uponSignal("TargetDiscovered")
|
||||
.onInterface(INTERFACE_NAME)
|
||||
.call(
|
||||
[this](const std::map<std::string, sdbus::Variant>& share_target) {
|
||||
this->onTargetDiscovered(share_target);
|
||||
});
|
||||
m_proxy.uponSignal("TargetUpdated")
|
||||
.onInterface(INTERFACE_NAME)
|
||||
.call(
|
||||
[this](const std::map<std::string, sdbus::Variant>& share_target) {
|
||||
this->onTargetUpdated(share_target);
|
||||
});
|
||||
m_proxy.uponSignal("TargetLost")
|
||||
.onInterface(INTERFACE_NAME)
|
||||
.call(
|
||||
[this](const std::map<std::string, sdbus::Variant>& share_target) {
|
||||
this->onTargetLost(share_target);
|
||||
});
|
||||
m_proxy.uponSignal("IncomingTransfer")
|
||||
.onInterface(INTERFACE_NAME)
|
||||
.call([this](const std::string& direction,
|
||||
const std::map<std::string, sdbus::Variant>& share_target,
|
||||
const std::map<std::string, sdbus::Variant>& transfer) {
|
||||
this->onIncomingTransfer(direction, share_target, transfer);
|
||||
});
|
||||
m_proxy.uponSignal("TransferUpdate")
|
||||
.onInterface(INTERFACE_NAME)
|
||||
.call([this](const std::string& direction,
|
||||
const std::map<std::string, sdbus::Variant>& share_target,
|
||||
const std::map<std::string, sdbus::Variant>& transfer) {
|
||||
this->onTransferUpdate(direction, share_target, transfer);
|
||||
});
|
||||
m_proxy.uponSignal("StatusChanged")
|
||||
.onInterface(INTERFACE_NAME)
|
||||
.call([this](const std::map<std::string, sdbus::Variant>& status) {
|
||||
this->onStatusChanged(status);
|
||||
});
|
||||
}
|
||||
|
||||
virtual void onTargetDiscovered(
|
||||
const std::map<std::string, sdbus::Variant>& share_target) = 0;
|
||||
virtual void onTargetUpdated(
|
||||
const std::map<std::string, sdbus::Variant>& share_target) = 0;
|
||||
virtual void onTargetLost(
|
||||
const std::map<std::string, sdbus::Variant>& share_target) = 0;
|
||||
virtual void onIncomingTransfer(
|
||||
const std::string& direction,
|
||||
const std::map<std::string, sdbus::Variant>& share_target,
|
||||
const std::map<std::string, sdbus::Variant>& transfer) = 0;
|
||||
virtual void onTransferUpdate(
|
||||
const std::string& direction,
|
||||
const std::map<std::string, sdbus::Variant>& share_target,
|
||||
const std::map<std::string, sdbus::Variant>& transfer) = 0;
|
||||
virtual void onStatusChanged(
|
||||
const std::map<std::string, sdbus::Variant>& status) = 0;
|
||||
|
||||
public:
|
||||
std::tuple<bool, std::string> StartReceive() {
|
||||
std::tuple<bool, std::string> result;
|
||||
m_proxy.callMethod("StartReceive")
|
||||
.onInterface(INTERFACE_NAME)
|
||||
.storeResultsTo(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::tuple<bool, std::string> StopReceive() {
|
||||
std::tuple<bool, std::string> result;
|
||||
m_proxy.callMethod("StopReceive")
|
||||
.onInterface(INTERFACE_NAME)
|
||||
.storeResultsTo(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::tuple<bool, std::string> StartDiscovery() {
|
||||
std::tuple<bool, std::string> result;
|
||||
m_proxy.callMethod("StartDiscovery")
|
||||
.onInterface(INTERFACE_NAME)
|
||||
.storeResultsTo(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::tuple<bool, std::string> StopDiscovery() {
|
||||
std::tuple<bool, std::string> result;
|
||||
m_proxy.callMethod("StopDiscovery")
|
||||
.onInterface(INTERFACE_NAME)
|
||||
.storeResultsTo(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::tuple<bool, std::string> SendFile(const int64_t& share_target_id,
|
||||
const std::string& path) {
|
||||
std::tuple<bool, std::string> result;
|
||||
m_proxy.callMethod("SendFile")
|
||||
.onInterface(INTERFACE_NAME)
|
||||
.withArguments(share_target_id, path)
|
||||
.storeResultsTo(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::tuple<bool, std::string> Accept(const int64_t& share_target_id) {
|
||||
std::tuple<bool, std::string> result;
|
||||
m_proxy.callMethod("Accept")
|
||||
.onInterface(INTERFACE_NAME)
|
||||
.withArguments(share_target_id)
|
||||
.storeResultsTo(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::tuple<bool, std::string> Reject(const int64_t& share_target_id) {
|
||||
std::tuple<bool, std::string> result;
|
||||
m_proxy.callMethod("Reject")
|
||||
.onInterface(INTERFACE_NAME)
|
||||
.withArguments(share_target_id)
|
||||
.storeResultsTo(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::tuple<bool, std::string> Cancel(const int64_t& share_target_id) {
|
||||
std::tuple<bool, std::string> result;
|
||||
m_proxy.callMethod("Cancel")
|
||||
.onInterface(INTERFACE_NAME)
|
||||
.withArguments(share_target_id)
|
||||
.storeResultsTo(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::tuple<bool, std::string> Shutdown() {
|
||||
std::tuple<bool, std::string> result;
|
||||
m_proxy.callMethod("Shutdown")
|
||||
.onInterface(INTERFACE_NAME)
|
||||
.storeResultsTo(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
sdbus::IProxy& m_proxy;
|
||||
};
|
||||
|
||||
} // namespace nearby
|
||||
} // namespace google
|
||||
} // namespace com
|
||||
|
||||
#endif
|
||||
@@ -1,134 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<node name="/com/google/nearby/sharing">
|
||||
<!--
|
||||
D-Bus contract for the Linux Nearby Sharing daemon.
|
||||
|
||||
The daemon internally exposes a socket-based JSON IPC model with:
|
||||
- commands: start_receive, stop_receive, start_discovery,
|
||||
stop_discovery, send_file, accept, reject, cancel, shutdown
|
||||
- events: target_discovered, target_updated, target_lost,
|
||||
incoming_transfer, transfer_update, status_changed
|
||||
|
||||
This interface preserves that surface with typed D-Bus methods and
|
||||
signals. Flexible payloads that were JSON objects are represented as
|
||||
a{sv} dictionaries so the daemon can expose the same field set without
|
||||
forcing a brittle fixed struct encoding for optional values.
|
||||
|
||||
Common dictionary payloads:
|
||||
- share_target a{sv}
|
||||
id x
|
||||
device_name s
|
||||
type i
|
||||
is_incoming b
|
||||
is_known b
|
||||
device_id s
|
||||
for_self_share b
|
||||
vendor_id i
|
||||
receive_disabled b
|
||||
- transfer a{sv}
|
||||
status s
|
||||
progress i
|
||||
transferred_bytes x
|
||||
total_bytes x
|
||||
transfer_speed x
|
||||
estimated_time_remaining x
|
||||
total_attachments_count i
|
||||
transferred_attachments_count i
|
||||
is_final_status b
|
||||
is_self_share b
|
||||
binding_id s
|
||||
token s (optional)
|
||||
in_progress_attachment_id x (optional)
|
||||
in_progress_attachment_transferred_bytes x (optional)
|
||||
in_progress_attachment_total_bytes x (optional)
|
||||
- status a{sv}
|
||||
receive_registered b
|
||||
discovery_registered b
|
||||
is_transferring b
|
||||
is_scanning b
|
||||
bluetooth_present b
|
||||
bluetooth_powered b
|
||||
lan_connected b
|
||||
targets aa{sv}
|
||||
-->
|
||||
<interface name="com.google.nearby.sharing">
|
||||
<method name="StartReceive">
|
||||
<arg name="ok" type="b" direction="out"/>
|
||||
<arg name="message" type="s" direction="out"/>
|
||||
</method>
|
||||
|
||||
<method name="StopReceive">
|
||||
<arg name="ok" type="b" direction="out"/>
|
||||
<arg name="message" type="s" direction="out"/>
|
||||
</method>
|
||||
|
||||
<method name="StartDiscovery">
|
||||
<arg name="ok" type="b" direction="out"/>
|
||||
<arg name="message" type="s" direction="out"/>
|
||||
</method>
|
||||
|
||||
<method name="StopDiscovery">
|
||||
<arg name="ok" type="b" direction="out"/>
|
||||
<arg name="message" type="s" direction="out"/>
|
||||
</method>
|
||||
|
||||
<method name="SendFile">
|
||||
<arg name="share_target_id" type="x" direction="in"/>
|
||||
<arg name="path" type="s" direction="in"/>
|
||||
<arg name="ok" type="b" direction="out"/>
|
||||
<arg name="message" type="s" direction="out"/>
|
||||
</method>
|
||||
|
||||
<method name="Accept">
|
||||
<arg name="share_target_id" type="x" direction="in"/>
|
||||
<arg name="ok" type="b" direction="out"/>
|
||||
<arg name="message" type="s" direction="out"/>
|
||||
</method>
|
||||
|
||||
<method name="Reject">
|
||||
<arg name="share_target_id" type="x" direction="in"/>
|
||||
<arg name="ok" type="b" direction="out"/>
|
||||
<arg name="message" type="s" direction="out"/>
|
||||
</method>
|
||||
|
||||
<method name="Cancel">
|
||||
<arg name="share_target_id" type="x" direction="in"/>
|
||||
<arg name="ok" type="b" direction="out"/>
|
||||
<arg name="message" type="s" direction="out"/>
|
||||
</method>
|
||||
|
||||
<method name="Shutdown">
|
||||
<arg name="ok" type="b" direction="out"/>
|
||||
<arg name="message" type="s" direction="out"/>
|
||||
</method>
|
||||
|
||||
<signal name="TargetDiscovered">
|
||||
<arg name="share_target" type="a{sv}"/>
|
||||
</signal>
|
||||
|
||||
<signal name="TargetUpdated">
|
||||
<arg name="share_target" type="a{sv}"/>
|
||||
</signal>
|
||||
|
||||
<signal name="TargetLost">
|
||||
<arg name="share_target" type="a{sv}"/>
|
||||
</signal>
|
||||
|
||||
<signal name="IncomingTransfer">
|
||||
<arg name="direction" type="s"/>
|
||||
<arg name="share_target" type="a{sv}"/>
|
||||
<arg name="transfer" type="a{sv}"/>
|
||||
</signal>
|
||||
|
||||
<signal name="TransferUpdate">
|
||||
<arg name="direction" type="s"/>
|
||||
<arg name="share_target" type="a{sv}"/>
|
||||
<arg name="transfer" type="a{sv}"/>
|
||||
</signal>
|
||||
|
||||
<signal name="StatusChanged">
|
||||
<arg name="status" type="a{sv}"/>
|
||||
</signal>
|
||||
</interface>
|
||||
</node>
|
||||
@@ -1,441 +0,0 @@
|
||||
#include "sharing/linux/daemon/nearby_sharing_dbus_service.h"
|
||||
|
||||
#include <condition_variable>
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "internal/base/file_path.h"
|
||||
#include "sharing/advertisement.h"
|
||||
#include "sharing/file_attachment.h"
|
||||
|
||||
namespace nearby::sharing::linux {
|
||||
namespace {
|
||||
|
||||
std::string StatusCodeToString(NearbySharingService::StatusCodes status) {
|
||||
return NearbySharingService::StatusCodeToString(status);
|
||||
}
|
||||
|
||||
std::tuple<bool, std::string> StatusResult(
|
||||
NearbySharingService::StatusCodes status) {
|
||||
return {status == NearbySharingService::StatusCodes::kOk,
|
||||
StatusCodeToString(status)};
|
||||
}
|
||||
|
||||
std::unique_ptr<AttachmentContainer> CreateFileAttachments(
|
||||
const std::string& file_path) {
|
||||
AttachmentContainer::Builder builder;
|
||||
builder.AddFileAttachment(FileAttachment(FilePath(file_path)));
|
||||
return builder.Build();
|
||||
}
|
||||
|
||||
template <typename Invoker>
|
||||
NearbySharingService::StatusCodes WaitForStatus(Invoker invoker) {
|
||||
std::mutex mutex;
|
||||
std::condition_variable cv;
|
||||
std::optional<NearbySharingService::StatusCodes> status;
|
||||
invoker([&](NearbySharingService::StatusCodes callback_status) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
status = callback_status;
|
||||
}
|
||||
cv.notify_one();
|
||||
});
|
||||
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
cv.wait(lock, [&] { return status.has_value(); });
|
||||
return *status;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
DbusDictionary ShareTargetToDbus(const ShareTarget& share_target) {
|
||||
DbusDictionary result;
|
||||
result.emplace("id", sdbus::Variant(share_target.id));
|
||||
result.emplace("device_name", sdbus::Variant(share_target.device_name));
|
||||
result.emplace("type",
|
||||
sdbus::Variant(static_cast<int32_t>(share_target.type)));
|
||||
result.emplace("is_incoming", sdbus::Variant(share_target.is_incoming));
|
||||
result.emplace("is_known", sdbus::Variant(share_target.is_known));
|
||||
result.emplace("device_id", sdbus::Variant(share_target.device_id));
|
||||
result.emplace("for_self_share", sdbus::Variant(share_target.for_self_share));
|
||||
result.emplace("vendor_id",
|
||||
sdbus::Variant(static_cast<int32_t>(share_target.vendor_id)));
|
||||
result.emplace("receive_disabled",
|
||||
sdbus::Variant(share_target.receive_disabled));
|
||||
return result;
|
||||
}
|
||||
|
||||
DbusDictionary TransferMetadataToDbus(
|
||||
const TransferMetadata& transfer_metadata,
|
||||
const AttachmentContainer& attachment_container) {
|
||||
DbusDictionary result;
|
||||
result.emplace("status", sdbus::Variant(TransferMetadata::StatusToString(
|
||||
transfer_metadata.status())));
|
||||
result.emplace(
|
||||
"progress",
|
||||
sdbus::Variant(static_cast<double>(transfer_metadata.progress())));
|
||||
result.emplace("transferred_bytes",
|
||||
sdbus::Variant(static_cast<int64_t>(
|
||||
transfer_metadata.transferred_bytes())));
|
||||
result.emplace(
|
||||
"total_bytes",
|
||||
sdbus::Variant(attachment_container.GetTotalAttachmentsSize()));
|
||||
result.emplace(
|
||||
"transfer_speed",
|
||||
sdbus::Variant(static_cast<int64_t>(transfer_metadata.transfer_speed())));
|
||||
result.emplace("estimated_time_remaining",
|
||||
sdbus::Variant(static_cast<int64_t>(
|
||||
transfer_metadata.estimated_time_remaining())));
|
||||
result.emplace("total_attachments_count",
|
||||
sdbus::Variant(transfer_metadata.total_attachments_count()));
|
||||
result.emplace(
|
||||
"transferred_attachments_count",
|
||||
sdbus::Variant(transfer_metadata.transferred_attachments_count()));
|
||||
result.emplace("is_final_status",
|
||||
sdbus::Variant(transfer_metadata.is_final_status()));
|
||||
result.emplace("is_self_share",
|
||||
sdbus::Variant(transfer_metadata.is_self_share()));
|
||||
result.emplace("binding_id", sdbus::Variant(transfer_metadata.binding_id()));
|
||||
|
||||
if (transfer_metadata.token().has_value()) {
|
||||
result.emplace("token", sdbus::Variant(*transfer_metadata.token()));
|
||||
}
|
||||
if (transfer_metadata.in_progress_attachment_id().has_value()) {
|
||||
result.emplace(
|
||||
"in_progress_attachment_id",
|
||||
sdbus::Variant(*transfer_metadata.in_progress_attachment_id()));
|
||||
}
|
||||
if (transfer_metadata.in_progress_attachment_transferred_bytes()
|
||||
.has_value()) {
|
||||
result.emplace(
|
||||
"in_progress_attachment_transferred_bytes",
|
||||
sdbus::Variant(static_cast<int64_t>(
|
||||
*transfer_metadata.in_progress_attachment_transferred_bytes())));
|
||||
}
|
||||
if (transfer_metadata.in_progress_attachment_total_bytes().has_value()) {
|
||||
result.emplace(
|
||||
"in_progress_attachment_total_bytes",
|
||||
sdbus::Variant(static_cast<int64_t>(
|
||||
*transfer_metadata.in_progress_attachment_total_bytes())));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
NearbySharingDbusService::TransferCallback::TransferCallback(
|
||||
NearbySharingDbusService& service, bool receive_mode)
|
||||
: service_(service), receive_mode_(receive_mode) {}
|
||||
|
||||
void NearbySharingDbusService::TransferCallback::OnTransferUpdate(
|
||||
const ShareTarget& share_target,
|
||||
const AttachmentContainer& attachment_container,
|
||||
const TransferMetadata& transfer_metadata) {
|
||||
service_.OnTransferUpdate(receive_mode_, share_target, attachment_container,
|
||||
transfer_metadata);
|
||||
}
|
||||
|
||||
NearbySharingDbusService::NearbySharingDbusService(
|
||||
sdbus::IObject& object, NearbySharingService& service,
|
||||
QuitCallback quit_callback)
|
||||
: sharing_adaptor(object),
|
||||
service_(service),
|
||||
quit_callback_(std::move(quit_callback)),
|
||||
send_transfer_callback_(*this, /*receive_mode=*/false),
|
||||
receive_transfer_callback_(*this, /*receive_mode=*/true) {
|
||||
registerAdaptor();
|
||||
service_.AddObserver(this);
|
||||
}
|
||||
|
||||
NearbySharingDbusService::~NearbySharingDbusService() {
|
||||
service_.RemoveObserver(this);
|
||||
ShutdownService();
|
||||
}
|
||||
|
||||
void NearbySharingDbusService::EmitStatusChanged() {
|
||||
emitStatusChanged(StatusToDbus());
|
||||
}
|
||||
|
||||
void NearbySharingDbusService::ShutdownService() {
|
||||
bool stop_receive = false;
|
||||
bool stop_discovery = false;
|
||||
{
|
||||
absl::MutexLock lock(lock_);
|
||||
if (shutdown_) {
|
||||
return;
|
||||
}
|
||||
shutdown_ = true;
|
||||
stop_receive = receive_registered_;
|
||||
stop_discovery = discovery_registered_;
|
||||
receive_registered_ = false;
|
||||
discovery_registered_ = false;
|
||||
targets_.clear();
|
||||
}
|
||||
|
||||
if (stop_receive) {
|
||||
WaitForStatus([&](auto callback) {
|
||||
service_.UnregisterReceiveSurface(&receive_transfer_callback_,
|
||||
std::move(callback));
|
||||
});
|
||||
}
|
||||
if (stop_discovery) {
|
||||
WaitForStatus([&](auto callback) {
|
||||
service_.UnregisterSendSurface(&send_transfer_callback_,
|
||||
std::move(callback));
|
||||
});
|
||||
}
|
||||
WaitForStatus([&](auto callback) { service_.Shutdown(std::move(callback)); });
|
||||
EmitStatusChanged();
|
||||
}
|
||||
|
||||
std::tuple<bool, std::string> NearbySharingDbusService::StartReceive() {
|
||||
{
|
||||
absl::MutexLock lock(lock_);
|
||||
if (receive_registered_) {
|
||||
return {true, "receive already started"};
|
||||
}
|
||||
}
|
||||
|
||||
auto result = InvokeStatusCommand([&](auto callback) {
|
||||
service_.RegisterReceiveSurface(
|
||||
&receive_transfer_callback_,
|
||||
NearbySharingService::ReceiveSurfaceState::kForeground,
|
||||
Advertisement::BlockedVendorId::kNone, std::move(callback));
|
||||
});
|
||||
if (std::get<0>(result)) {
|
||||
{
|
||||
absl::MutexLock lock(lock_);
|
||||
receive_registered_ = true;
|
||||
}
|
||||
EmitStatusChanged();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::tuple<bool, std::string> NearbySharingDbusService::StopReceive() {
|
||||
{
|
||||
absl::MutexLock lock(lock_);
|
||||
if (!receive_registered_) {
|
||||
return {true, "receive already stopped"};
|
||||
}
|
||||
}
|
||||
|
||||
auto result = InvokeStatusCommand([&](auto callback) {
|
||||
service_.UnregisterReceiveSurface(&receive_transfer_callback_,
|
||||
std::move(callback));
|
||||
});
|
||||
if (std::get<0>(result)) {
|
||||
{
|
||||
absl::MutexLock lock(lock_);
|
||||
receive_registered_ = false;
|
||||
}
|
||||
EmitStatusChanged();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::tuple<bool, std::string> NearbySharingDbusService::StartDiscovery() {
|
||||
{
|
||||
absl::MutexLock lock(lock_);
|
||||
if (discovery_registered_) {
|
||||
return {true, "discovery already started"};
|
||||
}
|
||||
}
|
||||
|
||||
auto result = InvokeStatusCommand([&](auto callback) {
|
||||
service_.RegisterSendSurface(
|
||||
&send_transfer_callback_, this,
|
||||
NearbySharingService::SendSurfaceState::kForeground,
|
||||
Advertisement::BlockedVendorId::kNone,
|
||||
/*disable_wifi_hotspot=*/false, std::move(callback));
|
||||
});
|
||||
if (std::get<0>(result)) {
|
||||
{
|
||||
absl::MutexLock lock(lock_);
|
||||
discovery_registered_ = true;
|
||||
}
|
||||
EmitStatusChanged();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::tuple<bool, std::string> NearbySharingDbusService::StopDiscovery() {
|
||||
{
|
||||
absl::MutexLock lock(lock_);
|
||||
if (!discovery_registered_) {
|
||||
return {true, "discovery already stopped"};
|
||||
}
|
||||
}
|
||||
|
||||
auto result = InvokeStatusCommand([&](auto callback) {
|
||||
service_.UnregisterSendSurface(&send_transfer_callback_,
|
||||
std::move(callback));
|
||||
});
|
||||
if (std::get<0>(result)) {
|
||||
{
|
||||
absl::MutexLock lock(lock_);
|
||||
discovery_registered_ = false;
|
||||
targets_.clear();
|
||||
}
|
||||
EmitStatusChanged();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::tuple<bool, std::string> NearbySharingDbusService::SendFile(
|
||||
const int64_t& share_target_id, const std::string& path) {
|
||||
std::error_code file_error;
|
||||
if (!std::filesystem::is_regular_file(path, file_error)) {
|
||||
return {false, "path is not a regular file"};
|
||||
}
|
||||
|
||||
{
|
||||
absl::MutexLock lock(lock_);
|
||||
if (targets_.find(share_target_id) == targets_.end()) {
|
||||
return {false, "unknown share_target_id"};
|
||||
}
|
||||
}
|
||||
|
||||
auto attachments = CreateFileAttachments(path);
|
||||
return InvokeStatusCommand([&](auto callback) {
|
||||
service_.SendAttachments(share_target_id, std::move(attachments),
|
||||
std::move(callback));
|
||||
});
|
||||
}
|
||||
|
||||
std::tuple<bool, std::string> NearbySharingDbusService::Accept(
|
||||
const int64_t& share_target_id) {
|
||||
return InvokeStatusCommand([&](auto callback) {
|
||||
service_.Accept(share_target_id, std::move(callback));
|
||||
});
|
||||
}
|
||||
|
||||
std::tuple<bool, std::string> NearbySharingDbusService::Reject(
|
||||
const int64_t& share_target_id) {
|
||||
return InvokeStatusCommand([&](auto callback) {
|
||||
service_.Reject(share_target_id, std::move(callback));
|
||||
});
|
||||
}
|
||||
|
||||
std::tuple<bool, std::string> NearbySharingDbusService::Cancel(
|
||||
const int64_t& share_target_id) {
|
||||
return InvokeStatusCommand([&](auto callback) {
|
||||
service_.Cancel(share_target_id, std::move(callback));
|
||||
});
|
||||
}
|
||||
|
||||
std::tuple<bool, std::string> NearbySharingDbusService::Shutdown() {
|
||||
ShutdownService();
|
||||
if (quit_callback_) {
|
||||
quit_callback_();
|
||||
}
|
||||
return {true, "daemon service shut down"};
|
||||
}
|
||||
|
||||
std::tuple<bool, std::string> NearbySharingDbusService::InvokeStatusCommand(
|
||||
std::function<void(std::function<void(NearbySharingService::StatusCodes)>)>
|
||||
invoker) {
|
||||
return StatusResult(WaitForStatus(std::move(invoker)));
|
||||
}
|
||||
|
||||
DbusDictionary NearbySharingDbusService::StatusToDbus() const {
|
||||
std::vector<DbusDictionary> targets;
|
||||
bool receive_registered = false;
|
||||
bool discovery_registered = false;
|
||||
{
|
||||
absl::MutexLock lock(lock_);
|
||||
receive_registered = receive_registered_;
|
||||
discovery_registered = discovery_registered_;
|
||||
targets.reserve(targets_.size());
|
||||
for (const auto& [id, target] : targets_) {
|
||||
static_cast<void>(id);
|
||||
targets.push_back(ShareTargetToDbus(target));
|
||||
}
|
||||
}
|
||||
|
||||
DbusDictionary status;
|
||||
status.emplace("receive_registered", sdbus::Variant(receive_registered));
|
||||
status.emplace("discovery_registered", sdbus::Variant(discovery_registered));
|
||||
status.emplace("is_transferring", sdbus::Variant(service_.IsTransferring()));
|
||||
status.emplace("is_scanning", sdbus::Variant(service_.IsScanning()));
|
||||
status.emplace("bluetooth_present",
|
||||
sdbus::Variant(service_.IsBluetoothPresent()));
|
||||
status.emplace("bluetooth_powered",
|
||||
sdbus::Variant(service_.IsBluetoothPowered()));
|
||||
status.emplace("lan_connected", sdbus::Variant(service_.IsLanConnected()));
|
||||
status.emplace("targets", sdbus::Variant(targets));
|
||||
return status;
|
||||
}
|
||||
|
||||
void NearbySharingDbusService::OnTransferUpdate(
|
||||
bool receive_mode, const ShareTarget& share_target,
|
||||
const AttachmentContainer& attachment_container,
|
||||
const TransferMetadata& transfer_metadata) {
|
||||
const std::string direction = receive_mode ? "receive" : "send";
|
||||
const DbusDictionary target = ShareTargetToDbus(share_target);
|
||||
const DbusDictionary transfer =
|
||||
TransferMetadataToDbus(transfer_metadata, attachment_container);
|
||||
|
||||
if (receive_mode &&
|
||||
transfer_metadata.status() ==
|
||||
TransferMetadata::Status::kAwaitingLocalConfirmation) {
|
||||
emitIncomingTransfer(direction, target, transfer);
|
||||
} else {
|
||||
emitTransferUpdate(direction, target, transfer);
|
||||
}
|
||||
EmitStatusChanged();
|
||||
}
|
||||
|
||||
void NearbySharingDbusService::OnShareTargetDiscovered(
|
||||
const ShareTarget& share_target) {
|
||||
{
|
||||
absl::MutexLock lock(lock_);
|
||||
targets_[share_target.id] = share_target;
|
||||
}
|
||||
emitTargetDiscovered(ShareTargetToDbus(share_target));
|
||||
EmitStatusChanged();
|
||||
}
|
||||
|
||||
void NearbySharingDbusService::OnShareTargetLost(
|
||||
const ShareTarget& share_target) {
|
||||
{
|
||||
absl::MutexLock lock(lock_);
|
||||
targets_.erase(share_target.id);
|
||||
}
|
||||
emitTargetLost(ShareTargetToDbus(share_target));
|
||||
EmitStatusChanged();
|
||||
}
|
||||
|
||||
void NearbySharingDbusService::OnShareTargetUpdated(
|
||||
const ShareTarget& share_target) {
|
||||
{
|
||||
absl::MutexLock lock(lock_);
|
||||
targets_[share_target.id] = share_target;
|
||||
}
|
||||
emitTargetUpdated(ShareTargetToDbus(share_target));
|
||||
EmitStatusChanged();
|
||||
}
|
||||
|
||||
void NearbySharingDbusService::OnHighVisibilityChanged(
|
||||
bool in_high_visibility) {
|
||||
static_cast<void>(in_high_visibility);
|
||||
EmitStatusChanged();
|
||||
}
|
||||
|
||||
void NearbySharingDbusService::OnBluetoothStatusChanged(AdapterState state) {
|
||||
static_cast<void>(state);
|
||||
EmitStatusChanged();
|
||||
}
|
||||
|
||||
void NearbySharingDbusService::OnLanStatusChanged(AdapterState state) {
|
||||
static_cast<void>(state);
|
||||
EmitStatusChanged();
|
||||
}
|
||||
|
||||
void NearbySharingDbusService::OnIrrecoverableHardwareErrorReported() {
|
||||
EmitStatusChanged();
|
||||
}
|
||||
|
||||
} // namespace nearby::sharing::linux
|
||||
@@ -1,105 +0,0 @@
|
||||
#ifndef SHARING_LINUX_DAEMON_NEARBY_SHARING_DBUS_SERVICE_H_
|
||||
#define SHARING_LINUX_DAEMON_NEARBY_SHARING_DBUS_SERVICE_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <sdbus-c++/sdbus-c++.h>
|
||||
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "sharing/attachment_container.h"
|
||||
#include "sharing/linux/daemon/nearby_sharing_server.h"
|
||||
#include "sharing/nearby_sharing_service.h"
|
||||
#include "sharing/share_target.h"
|
||||
#include "sharing/share_target_discovered_callback.h"
|
||||
#include "sharing/transfer_metadata.h"
|
||||
#include "sharing/transfer_update_callback.h"
|
||||
|
||||
namespace nearby::sharing::linux {
|
||||
|
||||
using DbusDictionary = std::map<std::string, sdbus::Variant>;
|
||||
|
||||
DbusDictionary ShareTargetToDbus(const ShareTarget& share_target);
|
||||
DbusDictionary TransferMetadataToDbus(
|
||||
const TransferMetadata& transfer_metadata,
|
||||
const AttachmentContainer& attachment_container);
|
||||
|
||||
class NearbySharingDbusService final
|
||||
: public com::google::nearby::sharing_adaptor,
|
||||
public ShareTargetDiscoveredCallback,
|
||||
public NearbySharingService::Observer {
|
||||
public:
|
||||
using QuitCallback = std::function<void()>;
|
||||
|
||||
NearbySharingDbusService(sdbus::IObject& object,
|
||||
NearbySharingService& service,
|
||||
QuitCallback quit_callback);
|
||||
~NearbySharingDbusService() override;
|
||||
|
||||
NearbySharingDbusService(const NearbySharingDbusService&) = delete;
|
||||
NearbySharingDbusService& operator=(const NearbySharingDbusService&) = delete;
|
||||
|
||||
void EmitStatusChanged();
|
||||
void ShutdownService();
|
||||
|
||||
void OnShareTargetDiscovered(const ShareTarget& share_target) override;
|
||||
void OnShareTargetLost(const ShareTarget& share_target) override;
|
||||
void OnShareTargetUpdated(const ShareTarget& share_target) override;
|
||||
|
||||
void OnHighVisibilityChanged(bool in_high_visibility) override;
|
||||
void OnBluetoothStatusChanged(AdapterState state) override;
|
||||
void OnLanStatusChanged(AdapterState state) override;
|
||||
void OnIrrecoverableHardwareErrorReported() override;
|
||||
|
||||
private:
|
||||
class TransferCallback final : public TransferUpdateCallback {
|
||||
public:
|
||||
TransferCallback(NearbySharingDbusService& service, bool receive_mode);
|
||||
|
||||
void OnTransferUpdate(const ShareTarget& share_target,
|
||||
const AttachmentContainer& attachment_container,
|
||||
const TransferMetadata& transfer_metadata) override;
|
||||
|
||||
private:
|
||||
NearbySharingDbusService& service_;
|
||||
bool receive_mode_;
|
||||
};
|
||||
|
||||
std::tuple<bool, std::string> StartReceive() override;
|
||||
std::tuple<bool, std::string> StopReceive() override;
|
||||
std::tuple<bool, std::string> StartDiscovery() override;
|
||||
std::tuple<bool, std::string> StopDiscovery() override;
|
||||
std::tuple<bool, std::string> SendFile(const int64_t& share_target_id,
|
||||
const std::string& path) override;
|
||||
std::tuple<bool, std::string> Accept(const int64_t& share_target_id) override;
|
||||
std::tuple<bool, std::string> Reject(const int64_t& share_target_id) override;
|
||||
std::tuple<bool, std::string> Cancel(const int64_t& share_target_id) override;
|
||||
std::tuple<bool, std::string> Shutdown() override;
|
||||
|
||||
std::tuple<bool, std::string> InvokeStatusCommand(
|
||||
std::function<
|
||||
void(std::function<void(NearbySharingService::StatusCodes)>)>
|
||||
invoker);
|
||||
DbusDictionary StatusToDbus() const;
|
||||
void OnTransferUpdate(bool receive_mode, const ShareTarget& share_target,
|
||||
const AttachmentContainer& attachment_container,
|
||||
const TransferMetadata& transfer_metadata);
|
||||
|
||||
NearbySharingService& service_;
|
||||
QuitCallback quit_callback_;
|
||||
TransferCallback send_transfer_callback_;
|
||||
TransferCallback receive_transfer_callback_;
|
||||
mutable absl::Mutex lock_;
|
||||
std::unordered_map<int64_t, ShareTarget> targets_;
|
||||
bool receive_registered_ = false;
|
||||
bool discovery_registered_ = false;
|
||||
bool shutdown_ = false;
|
||||
};
|
||||
|
||||
} // namespace nearby::sharing::linux
|
||||
|
||||
#endif // SHARING_LINUX_DAEMON_NEARBY_SHARING_DBUS_SERVICE_H_
|
||||
@@ -1,89 +0,0 @@
|
||||
#include "sharing/linux/daemon/nearby_sharing_dbus_service.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "sharing/attachment_container.h"
|
||||
#include "sharing/common/nearby_share_enums.h"
|
||||
#include "sharing/share_target.h"
|
||||
#include "sharing/transfer_metadata.h"
|
||||
#include "sharing/transfer_metadata_builder.h"
|
||||
|
||||
namespace nearby::sharing::linux {
|
||||
namespace {
|
||||
|
||||
ShareTarget MakeShareTarget() {
|
||||
ShareTarget target;
|
||||
target.id = 42;
|
||||
target.device_name = "Pixel";
|
||||
target.type = ShareTargetType::kPhone;
|
||||
target.is_incoming = true;
|
||||
target.is_known = true;
|
||||
target.device_id = "device-id";
|
||||
target.for_self_share = true;
|
||||
target.vendor_id = 7;
|
||||
target.receive_disabled = true;
|
||||
return target;
|
||||
}
|
||||
|
||||
TEST(NearbySharingDbusServiceTest, ShareTargetToDbusMapsNearbyFields) {
|
||||
DbusDictionary result = ShareTargetToDbus(MakeShareTarget());
|
||||
|
||||
EXPECT_EQ(result.at("id").get<int64_t>(), 42);
|
||||
EXPECT_EQ(result.at("device_name").get<std::string>(), "Pixel");
|
||||
EXPECT_EQ(result.at("type").get<int32_t>(),
|
||||
static_cast<int32_t>(ShareTargetType::kPhone));
|
||||
EXPECT_TRUE(result.at("is_incoming").get<bool>());
|
||||
EXPECT_TRUE(result.at("is_known").get<bool>());
|
||||
EXPECT_EQ(result.at("device_id").get<std::string>(), "device-id");
|
||||
EXPECT_TRUE(result.at("for_self_share").get<bool>());
|
||||
EXPECT_EQ(result.at("vendor_id").get<int32_t>(), 7);
|
||||
EXPECT_TRUE(result.at("receive_disabled").get<bool>());
|
||||
}
|
||||
|
||||
TEST(NearbySharingDbusServiceTest, TransferMetadataToDbusMapsNearbyFields) {
|
||||
AttachmentContainer::Builder attachments_builder;
|
||||
auto attachments = attachments_builder.Build();
|
||||
TransferMetadata metadata =
|
||||
TransferMetadataBuilder()
|
||||
.set_status(TransferMetadata::Status::kInProgress)
|
||||
.set_progress(25)
|
||||
.set_token(std::string("1234"))
|
||||
.set_is_self_share(true)
|
||||
.set_transferred_bytes(1024)
|
||||
.set_transfer_speed(256)
|
||||
.set_estimated_time_remaining(4)
|
||||
.set_total_attachments_count(2)
|
||||
.set_transferred_attachments_count(1)
|
||||
.set_in_progress_attachment_id(99)
|
||||
.set_in_progress_attachment_transferred_bytes(512)
|
||||
.set_in_progress_attachment_total_bytes(2048)
|
||||
.set_binding_id("binding")
|
||||
.build();
|
||||
|
||||
DbusDictionary result = TransferMetadataToDbus(metadata, *attachments);
|
||||
|
||||
EXPECT_EQ(result.at("status").get<std::string>(), "kInProgress");
|
||||
EXPECT_EQ(result.at("progress").get<double>(), 25);
|
||||
EXPECT_EQ(result.at("transferred_bytes").get<int64_t>(), 1024);
|
||||
EXPECT_EQ(result.at("total_bytes").get<int64_t>(), 0);
|
||||
EXPECT_EQ(result.at("transfer_speed").get<int64_t>(), 256);
|
||||
EXPECT_EQ(result.at("estimated_time_remaining").get<int64_t>(), 4);
|
||||
EXPECT_EQ(result.at("total_attachments_count").get<int>(), 2);
|
||||
EXPECT_EQ(result.at("transferred_attachments_count").get<int>(), 1);
|
||||
EXPECT_FALSE(result.at("is_final_status").get<bool>());
|
||||
EXPECT_TRUE(result.at("is_self_share").get<bool>());
|
||||
EXPECT_EQ(result.at("binding_id").get<std::string>(), "binding");
|
||||
EXPECT_EQ(result.at("token").get<std::string>(), "1234");
|
||||
EXPECT_EQ(result.at("in_progress_attachment_id").get<int64_t>(), 99);
|
||||
EXPECT_EQ(
|
||||
result.at("in_progress_attachment_transferred_bytes").get<int64_t>(),
|
||||
512);
|
||||
EXPECT_EQ(result.at("in_progress_attachment_total_bytes").get<int64_t>(),
|
||||
2048);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace nearby::sharing::linux
|
||||
@@ -1,168 +0,0 @@
|
||||
|
||||
/*
|
||||
* This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
|
||||
*/
|
||||
|
||||
#ifndef __sdbuscpp__sharing_linux_daemon_nearby_sharing_server_h__adaptor__H__
|
||||
#define __sdbuscpp__sharing_linux_daemon_nearby_sharing_server_h__adaptor__H__
|
||||
|
||||
#include <sdbus-c++/sdbus-c++.h>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
namespace com {
|
||||
namespace google {
|
||||
namespace nearby {
|
||||
|
||||
class sharing_adaptor {
|
||||
public:
|
||||
static constexpr const char* INTERFACE_NAME = "com.google.nearby.sharing";
|
||||
|
||||
protected:
|
||||
sharing_adaptor(sdbus::IObject& object) : m_object(object) {}
|
||||
|
||||
sharing_adaptor(const sharing_adaptor&) = delete;
|
||||
sharing_adaptor& operator=(const sharing_adaptor&) = delete;
|
||||
sharing_adaptor(sharing_adaptor&&) = delete;
|
||||
sharing_adaptor& operator=(sharing_adaptor&&) = delete;
|
||||
|
||||
~sharing_adaptor() = default;
|
||||
|
||||
void registerAdaptor() {
|
||||
m_object
|
||||
.addVTable(
|
||||
sdbus::registerMethod("StartReceive")
|
||||
.withOutputParamNames("ok", "message")
|
||||
.implementedAs([this]() { return this->StartReceive(); }),
|
||||
sdbus::registerMethod("StopReceive")
|
||||
.withOutputParamNames("ok", "message")
|
||||
.implementedAs([this]() { return this->StopReceive(); }),
|
||||
sdbus::registerMethod("StartDiscovery")
|
||||
.withOutputParamNames("ok", "message")
|
||||
.implementedAs([this]() { return this->StartDiscovery(); }),
|
||||
sdbus::registerMethod("StopDiscovery")
|
||||
.withOutputParamNames("ok", "message")
|
||||
.implementedAs([this]() { return this->StopDiscovery(); }),
|
||||
sdbus::registerMethod("SendFile")
|
||||
.withInputParamNames("share_target_id", "path")
|
||||
.withOutputParamNames("ok", "message")
|
||||
.implementedAs([this](const int64_t& share_target_id,
|
||||
const std::string& path) {
|
||||
return this->SendFile(share_target_id, path);
|
||||
}),
|
||||
sdbus::registerMethod("Accept")
|
||||
.withInputParamNames("share_target_id")
|
||||
.withOutputParamNames("ok", "message")
|
||||
.implementedAs([this](const int64_t& share_target_id) {
|
||||
return this->Accept(share_target_id);
|
||||
}),
|
||||
sdbus::registerMethod("Reject")
|
||||
.withInputParamNames("share_target_id")
|
||||
.withOutputParamNames("ok", "message")
|
||||
.implementedAs([this](const int64_t& share_target_id) {
|
||||
return this->Reject(share_target_id);
|
||||
}),
|
||||
sdbus::registerMethod("Cancel")
|
||||
.withInputParamNames("share_target_id")
|
||||
.withOutputParamNames("ok", "message")
|
||||
.implementedAs([this](const int64_t& share_target_id) {
|
||||
return this->Cancel(share_target_id);
|
||||
}),
|
||||
sdbus::registerMethod("Shutdown")
|
||||
.withOutputParamNames("ok", "message")
|
||||
.implementedAs([this]() { return this->Shutdown(); }),
|
||||
sdbus::registerSignal("TargetDiscovered")
|
||||
.withParameters<std::map<std::string, sdbus::Variant>>(
|
||||
"share_target"),
|
||||
sdbus::registerSignal("TargetUpdated")
|
||||
.withParameters<std::map<std::string, sdbus::Variant>>(
|
||||
"share_target"),
|
||||
sdbus::registerSignal("TargetLost")
|
||||
.withParameters<std::map<std::string, sdbus::Variant>>(
|
||||
"share_target"),
|
||||
sdbus::registerSignal("IncomingTransfer")
|
||||
.withParameters<std::string,
|
||||
std::map<std::string, sdbus::Variant>,
|
||||
std::map<std::string, sdbus::Variant>>(
|
||||
"direction", "share_target", "transfer"),
|
||||
sdbus::registerSignal("TransferUpdate")
|
||||
.withParameters<std::string,
|
||||
std::map<std::string, sdbus::Variant>,
|
||||
std::map<std::string, sdbus::Variant>>(
|
||||
"direction", "share_target", "transfer"),
|
||||
sdbus::registerSignal("StatusChanged")
|
||||
.withParameters<std::map<std::string, sdbus::Variant>>(
|
||||
"status"))
|
||||
.forInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
public:
|
||||
void emitTargetDiscovered(
|
||||
const std::map<std::string, sdbus::Variant>& share_target) {
|
||||
m_object.emitSignal("TargetDiscovered")
|
||||
.onInterface(INTERFACE_NAME)
|
||||
.withArguments(share_target);
|
||||
}
|
||||
|
||||
void emitTargetUpdated(
|
||||
const std::map<std::string, sdbus::Variant>& share_target) {
|
||||
m_object.emitSignal("TargetUpdated")
|
||||
.onInterface(INTERFACE_NAME)
|
||||
.withArguments(share_target);
|
||||
}
|
||||
|
||||
void emitTargetLost(
|
||||
const std::map<std::string, sdbus::Variant>& share_target) {
|
||||
m_object.emitSignal("TargetLost")
|
||||
.onInterface(INTERFACE_NAME)
|
||||
.withArguments(share_target);
|
||||
}
|
||||
|
||||
void emitIncomingTransfer(
|
||||
const std::string& direction,
|
||||
const std::map<std::string, sdbus::Variant>& share_target,
|
||||
const std::map<std::string, sdbus::Variant>& transfer) {
|
||||
m_object.emitSignal("IncomingTransfer")
|
||||
.onInterface(INTERFACE_NAME)
|
||||
.withArguments(direction, share_target, transfer);
|
||||
}
|
||||
|
||||
void emitTransferUpdate(
|
||||
const std::string& direction,
|
||||
const std::map<std::string, sdbus::Variant>& share_target,
|
||||
const std::map<std::string, sdbus::Variant>& transfer) {
|
||||
m_object.emitSignal("TransferUpdate")
|
||||
.onInterface(INTERFACE_NAME)
|
||||
.withArguments(direction, share_target, transfer);
|
||||
}
|
||||
|
||||
void emitStatusChanged(const std::map<std::string, sdbus::Variant>& status) {
|
||||
m_object.emitSignal("StatusChanged")
|
||||
.onInterface(INTERFACE_NAME)
|
||||
.withArguments(status);
|
||||
}
|
||||
|
||||
private:
|
||||
virtual std::tuple<bool, std::string> StartReceive() = 0;
|
||||
virtual std::tuple<bool, std::string> StopReceive() = 0;
|
||||
virtual std::tuple<bool, std::string> StartDiscovery() = 0;
|
||||
virtual std::tuple<bool, std::string> StopDiscovery() = 0;
|
||||
virtual std::tuple<bool, std::string> SendFile(const int64_t& share_target_id,
|
||||
const std::string& path) = 0;
|
||||
virtual std::tuple<bool, std::string> Accept(
|
||||
const int64_t& share_target_id) = 0;
|
||||
virtual std::tuple<bool, std::string> Reject(
|
||||
const int64_t& share_target_id) = 0;
|
||||
virtual std::tuple<bool, std::string> Cancel(
|
||||
const int64_t& share_target_id) = 0;
|
||||
virtual std::tuple<bool, std::string> Shutdown() = 0;
|
||||
|
||||
private:
|
||||
sdbus::IObject& m_object;
|
||||
};
|
||||
|
||||
} // namespace nearby
|
||||
} // namespace google
|
||||
} // namespace com
|
||||
|
||||
#endif
|
||||
@@ -1,113 +0,0 @@
|
||||
load("@rules_cc//cc:cc_binary.bzl", "cc_binary")
|
||||
load("@rules_cc//cc:cc_library.bzl", "cc_library")
|
||||
load("@rules_cc//cc:cc_test.bzl", "cc_test")
|
||||
|
||||
load("@hedron_compile_commands//:refresh_compile_commands.bzl", "refresh_compile_commands")
|
||||
|
||||
refresh_compile_commands(
|
||||
name = "refresh_compile_commands",
|
||||
|
||||
# Specify the targets of interest.
|
||||
# For example, specify a dict of targets and any flags required to build.
|
||||
targets = {
|
||||
":tui" : "",
|
||||
},
|
||||
# No need to add flags already in .bazelrc. They're automatically picked up.
|
||||
# If you don't need flags, a list of targets is also okay, as is a single target string.
|
||||
# Wildcard patterns, like //... for everything, *are* allowed here, just like a build.
|
||||
# As are additional targets (+) and subtractions (-), like in bazel query https://docs.bazel.build/versions/main/query.html#expressions
|
||||
# And if you're working on a header-only library, specify a test or binary target that compiles it.
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "tui",
|
||||
srcs = [
|
||||
"main.cc",
|
||||
],
|
||||
deps = [
|
||||
#":app",
|
||||
"nearby_sharing_dbus_client"
|
||||
]
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name ="nearby_sharing_dbus_client",
|
||||
hdrs = [
|
||||
'nearby_sharing_dbus_client.h'
|
||||
],
|
||||
srcs = [
|
||||
'nearby_sharing_dbus_client.cc'
|
||||
],
|
||||
deps = [
|
||||
"//sharing/linux/daemon:nearby_sharing_daemon",
|
||||
"@sdbus_cpp",
|
||||
]
|
||||
)
|
||||
|
||||
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 = "ipc_client",
|
||||
srcs = [
|
||||
"ipc_client.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"ipc_client.h",
|
||||
],
|
||||
deps = [
|
||||
"@nlohmann_json//:json",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "ipc_client_test",
|
||||
srcs = [
|
||||
"ipc_client_test.cc",
|
||||
],
|
||||
deps = [
|
||||
":ipc_client",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
"@nlohmann_json//:json",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "file_picker",
|
||||
srcs = [
|
||||
"file_picker.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"file_picker.h",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "palette",
|
||||
hdrs = [
|
||||
"palette.h",
|
||||
],
|
||||
deps = [
|
||||
"@ftxui//:ftxui",
|
||||
]
|
||||
)
|
||||
@@ -1,74 +0,0 @@
|
||||
#include "sharing/linux/tui/app.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "ftxui/component/component.hpp"
|
||||
#include "sharing/linux/tui/ui/home_screen.h"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
using namespace ftxui;
|
||||
namespace {
|
||||
|
||||
std::string GetHostname() {
|
||||
char hostname[256] = {};
|
||||
gethostname(hostname, sizeof(hostname));
|
||||
return hostname;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TuiApp::TuiApp() : screen_(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;
|
||||
},
|
||||
.incoming_share_device_name = incoming_share_device_name_,
|
||||
.incoming_share_device_type = incoming_share_device_type_,
|
||||
.on_incoming_share_accept =
|
||||
[this]() { current_page_ = Page::FilePicker; },
|
||||
.on_incoming_share_decline =
|
||||
[this]() { current_page_ = Page::FilePicker; },
|
||||
});
|
||||
|
||||
auto app =
|
||||
CatchEvent(component, [this](Event event) { return HandleEvent(event); });
|
||||
|
||||
screen_.Loop(app);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool TuiApp::HandleEvent(Event event) {
|
||||
if (event == Event::Character('q') || event == Event::Escape) {
|
||||
screen_.ExitLoopClosure()();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (event == Event::Backspace) {
|
||||
if (current_page_ == Page::Sharing) {
|
||||
current_page_ = Page::FilePicker;
|
||||
selected_file_.clear();
|
||||
return true;
|
||||
}
|
||||
if (current_page_ == Page::IncomingShare) {
|
||||
current_page_ = Page::FilePicker;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -1,27 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "ftxui/component/screen_interactive.hpp"
|
||||
#include "sharing/linux/tui/components/share_target.h"
|
||||
#include "sharing/linux/tui/file_picker.h"
|
||||
#include "sharing/linux/tui/page.h"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
using namespace ftxui;
|
||||
|
||||
class TuiApp {
|
||||
public:
|
||||
TuiApp();
|
||||
|
||||
int Run();
|
||||
|
||||
private:
|
||||
|
||||
ScreenInteractive screen_;
|
||||
ZenityFilePicker file_picker_;
|
||||
std::string hostname_;
|
||||
std::string selected_file_;
|
||||
};
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -1,68 +0,0 @@
|
||||
load("@rules_cc//cc:cc_library.bzl", "cc_library")
|
||||
|
||||
cc_library(
|
||||
name = "icons",
|
||||
srcs = [
|
||||
"file_icon.cc",
|
||||
"brand.cc",
|
||||
"laptop_icon.cc",
|
||||
"phone_icon.cc",
|
||||
"tablet_icon.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"file_icon.h",
|
||||
"brand.h",
|
||||
"laptop_icon.h",
|
||||
"phone_icon.h",
|
||||
"tablet_icon.h",
|
||||
],
|
||||
deps = [
|
||||
"@ftxui//:ftxui",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "share_target",
|
||||
srcs = [
|
||||
"share_target.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"share_target.h",
|
||||
],
|
||||
deps = [
|
||||
"@ftxui//:ftxui",
|
||||
"//sharing/linux/tui:palette",
|
||||
":icons",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "incoming_share_card",
|
||||
srcs = [
|
||||
"incoming_share_card.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"incoming_share_card.h",
|
||||
],
|
||||
deps = [
|
||||
":share_target",
|
||||
"//sharing/linux/tui:palette",
|
||||
"@ftxui//:ftxui",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "file_picker_card",
|
||||
srcs = [
|
||||
"file_picker_card.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"file_picker_card.h",
|
||||
],
|
||||
deps = [
|
||||
":icons",
|
||||
"//sharing/linux/tui:file_picker",
|
||||
"//sharing/linux/tui:palette",
|
||||
"@ftxui//:ftxui",
|
||||
],
|
||||
)
|
||||
@@ -1,15 +0,0 @@
|
||||
#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
|
||||
@@ -1,10 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
using namespace ftxui;
|
||||
|
||||
Element Brand();
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -1,30 +0,0 @@
|
||||
#include "sharing/linux/tui/components/file_icon.h"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
using namespace ftxui;
|
||||
|
||||
Element FileIcon(FileIconSize size) {
|
||||
if (size == FileIconSize::Small) {
|
||||
return vbox({
|
||||
text(" ______ ") | center,
|
||||
text(" / | | ") | center,
|
||||
text(" /__| | ") | center,
|
||||
text(" | ----- | ") | center,
|
||||
text(" | ----- | ") | center,
|
||||
text(" |_______| ") | center,
|
||||
});
|
||||
}
|
||||
|
||||
return vbox({
|
||||
text(" __________ ") | center,
|
||||
text(" / | | ") | center,
|
||||
text(" /__| | ") | center,
|
||||
text(" | --------- | ") | center,
|
||||
text(" | --------- | ") | center,
|
||||
text(" | --------- | ") | center,
|
||||
text(" | --------- | ") | center,
|
||||
text(" |___________| ") | center,
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -1,15 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
using namespace ftxui;
|
||||
|
||||
enum class FileIconSize {
|
||||
Large,
|
||||
Small,
|
||||
};
|
||||
|
||||
Element FileIcon(FileIconSize size);
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -1,67 +0,0 @@
|
||||
#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 {
|
||||
using namespace ftxui;
|
||||
|
||||
Component FilePickerCard(FilePickerCardOptions options) {
|
||||
auto picker_box = std::make_shared<Box>();
|
||||
auto hovered = std::make_shared<bool>(false);
|
||||
|
||||
auto card = Renderer([picker_box, hovered] {
|
||||
auto picker_card =
|
||||
vbox({
|
||||
FileIcon(FileIconSize::Large) | color(Palette::secondary),
|
||||
separatorEmpty(),
|
||||
text("Select file to share") | bold | center,
|
||||
}) |
|
||||
borderStyled(*hovered ? Palette::primary : Palette::secondary) |
|
||||
size(WIDTH, GREATER_THAN, 33) | size(HEIGHT, EQUAL, 13) |
|
||||
reflect(*picker_box);
|
||||
|
||||
return vbox({
|
||||
filler(),
|
||||
hbox({
|
||||
filler(),
|
||||
picker_card,
|
||||
filler(),
|
||||
}),
|
||||
filler(),
|
||||
}) |
|
||||
flex;
|
||||
});
|
||||
|
||||
return CatchEvent(card, [picker_box, hovered, options](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 != Mouse::Left ||
|
||||
mouse.motion != 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
|
||||
@@ -1,19 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#include "ftxui/component/component.hpp"
|
||||
#include "sharing/linux/tui/file_picker.h"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
using namespace ftxui;
|
||||
|
||||
struct FilePickerCardOptions {
|
||||
FilePicker* file_picker = nullptr;
|
||||
std::function<void(std::string)> on_file_selected;
|
||||
};
|
||||
|
||||
Component FilePickerCard(FilePickerCardOptions options);
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -1,44 +0,0 @@
|
||||
#include "sharing/linux/tui/components/incoming_share_card.h"
|
||||
#include "ftxui/component/component.hpp"
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
#include "sharing/linux/tui/components/share_target.h"
|
||||
#include "sharing/linux/tui/palette.h"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
using namespace ftxui;
|
||||
|
||||
Component IncomingShareCard(IncomingShareCardOptions options) {
|
||||
auto accept_button = Button("Accept", [options] {
|
||||
if (options.on_accept) {
|
||||
options.on_accept();
|
||||
}
|
||||
});
|
||||
auto decline_button = Button("Decline", [options] {
|
||||
if (options.on_decline) {
|
||||
options.on_decline();
|
||||
}
|
||||
});
|
||||
auto controls = Container::Horizontal({accept_button, decline_button});
|
||||
|
||||
return Renderer(controls, [accept_button, decline_button, options] {
|
||||
return vbox({
|
||||
window(text(" Incoming share ") | center,
|
||||
vbox({
|
||||
paragraph("Do you want to accept this share?") |
|
||||
bold | center,
|
||||
separator(),
|
||||
ShareTarget(options.device_name, options.device_type),
|
||||
separator(),
|
||||
hbox({
|
||||
accept_button->Render() | flex,
|
||||
separator(),
|
||||
decline_button->Render() | flex,
|
||||
}),
|
||||
})),
|
||||
}) |
|
||||
borderStyled(Palette::border) | bgcolor(Palette::surface) |
|
||||
size(WIDTH, GREATER_THAN, 40);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -1,21 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#include "ftxui/component/component.hpp"
|
||||
#include "sharing/linux/tui/components/share_target.h"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
using namespace ftxui;
|
||||
|
||||
struct IncomingShareCardOptions {
|
||||
std::string device_name;
|
||||
ShareTargetType device_type = ShareTargetType::kUnknown;
|
||||
std::function<void()> on_accept;
|
||||
std::function<void()> on_decline;
|
||||
};
|
||||
|
||||
Component IncomingShareCard(IncomingShareCardOptions options);
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -1,15 +0,0 @@
|
||||
#include "sharing/linux/tui/components/laptop_icon.h"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
using namespace ftxui;
|
||||
|
||||
Element Laptop() {
|
||||
return vbox({
|
||||
text(" +========+ ") | center,
|
||||
text(" | | ") | center,
|
||||
text(" |________| ") | center,
|
||||
text(" /--------\\ ") | center,
|
||||
text("/__________\\") | center,
|
||||
});
|
||||
}
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -1,10 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
using namespace ftxui;
|
||||
|
||||
Element Laptop();
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -1,15 +0,0 @@
|
||||
#include "sharing/linux/tui/components/phone_icon.h"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
using namespace ftxui;
|
||||
|
||||
Element Phone() {
|
||||
return vbox({
|
||||
text("______") | center,
|
||||
text("| |") | center,
|
||||
text("| |") | center,
|
||||
text("| |") | center,
|
||||
text("|____|") | center,
|
||||
});
|
||||
}
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -1,10 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
using namespace ftxui;
|
||||
|
||||
Element Phone();
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -1,32 +0,0 @@
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
#include "sharing/linux/tui/components/share_target.h"
|
||||
#include "sharing/linux/tui/components/laptop_icon.h"
|
||||
#include "sharing/linux/tui/components/phone_icon.h"
|
||||
#include "sharing/linux/tui/components/tablet_icon.h"
|
||||
#include "sharing/linux/tui/palette.h"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
using namespace ftxui;
|
||||
|
||||
Element ShareTarget(std::string device_name, ShareTargetType device_type) {
|
||||
Element icon;
|
||||
switch (device_type) {
|
||||
case ShareTargetType::kPhone:
|
||||
icon = Phone();
|
||||
break;
|
||||
case ShareTargetType::kTablet:
|
||||
icon = Tablet();
|
||||
break;
|
||||
default:
|
||||
icon = Laptop();
|
||||
break;
|
||||
}
|
||||
return vbox(
|
||||
{icon, separatorLight() | dim,
|
||||
paragraph(device_name) | color(Palette::secondary) | bold | center
|
||||
|
||||
}) |bgcolor(Palette::surface)|
|
||||
size(WIDTH, EQUAL, 14) | borderStyled(Palette::border);
|
||||
};
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -1,30 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
using namespace ftxui;
|
||||
|
||||
enum class ShareTargetType {
|
||||
// Unknown device type.
|
||||
kUnknown = 0,
|
||||
// A phone.
|
||||
kPhone = 1,
|
||||
// A tablet.
|
||||
kTablet = 2,
|
||||
// A laptop.
|
||||
kLaptop = 3,
|
||||
// A car.
|
||||
kCar = 4,
|
||||
// A foldable.
|
||||
kFoldable = 5,
|
||||
// An XR device.
|
||||
kXR = 6,
|
||||
};
|
||||
|
||||
Element ShareTarget(
|
||||
std::string device_name,
|
||||
ShareTargetType device_type
|
||||
);
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -1,15 +0,0 @@
|
||||
#include "sharing/linux/tui/components/tablet_icon.h"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
using namespace ftxui;
|
||||
|
||||
Element Tablet() {
|
||||
return vbox({
|
||||
text("____________") | center,
|
||||
text("| |") | center,
|
||||
text("| |") | center,
|
||||
text("|__________|") | center,
|
||||
text(" ") | center,
|
||||
});
|
||||
}
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -1,10 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
using namespace ftxui;
|
||||
|
||||
Element Tablet();
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -1,30 +0,0 @@
|
||||
#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
|
||||
@@ -1,19 +0,0 @@
|
||||
#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
|
||||
@@ -1,15 +0,0 @@
|
||||
#include "nearby_sharing_dbus_client.h"
|
||||
#include <sdbus-c++/IConnection.h>
|
||||
|
||||
int main() {
|
||||
auto sharing =
|
||||
NearbySharingService(sdbus::ServiceName("com.google.nearby.sharing"),
|
||||
sdbus::ObjectPath("/com/google/nearby/sharing"));
|
||||
|
||||
sharing.StartReceive();
|
||||
sleep(10);
|
||||
sharing.StopReceive();
|
||||
// nearby::sharing::linux_tui::TuiApp app;
|
||||
// return app.Run();
|
||||
return 0;
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
#include "sharing/linux/tui/nearby_sharing_dbus_client.h"
|
||||
|
||||
// Helper to extract a value from the map with a fallback if missing or type
|
||||
// mismatches
|
||||
template <typename T>
|
||||
T get_field(const std::map<std::string, sdbus::Variant>& map,
|
||||
const std::string& key, T default_value = T{}) {
|
||||
auto it = map.find(key);
|
||||
if (it != map.end()) {
|
||||
try {
|
||||
return it->second.get<T>();
|
||||
} catch (const sdbus::Error& e) {
|
||||
// Log type mismatch error if necessary
|
||||
}
|
||||
}
|
||||
return default_value;
|
||||
}
|
||||
|
||||
// Helper for optional fields
|
||||
template <typename T>
|
||||
std::optional<T> get_optional_field(
|
||||
const std::map<std::string, sdbus::Variant>& map, const std::string& key) {
|
||||
auto it = map.find(key);
|
||||
if (it != map.end()) {
|
||||
try {
|
||||
return it->second.get<T>();
|
||||
} catch (const sdbus::Error& e) {
|
||||
// Log type mismatch error if necessary
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// Converter: Map -> ShareTarget
|
||||
ShareTarget convertToShareTarget(
|
||||
const std::map<std::string, sdbus::Variant>& map) {
|
||||
ShareTarget target;
|
||||
target.id = get_field<int64_t>(map, "id");
|
||||
target.device_name = get_field<std::string>(map, "device_name");
|
||||
target.type = get_field<int32_t>(map, "type");
|
||||
target.is_incoming = get_field<bool>(map, "is_incoming");
|
||||
target.is_known = get_field<bool>(map, "is_known");
|
||||
target.device_id = get_field<std::string>(map, "device_id");
|
||||
target.for_self_share = get_field<bool>(map, "for_self_share");
|
||||
target.vendor_id = get_field<int32_t>(map, "vendor_id");
|
||||
target.receive_disabled = get_field<bool>(map, "receive_disabled");
|
||||
return target;
|
||||
}
|
||||
|
||||
// Converter: Map -> Transfer
|
||||
Transfer convertToTransfer(const std::map<std::string, sdbus::Variant>& map) {
|
||||
Transfer transfer;
|
||||
transfer.status = get_field<std::string>(map, "status");
|
||||
transfer.progress = get_field<int32_t>(map, "progress");
|
||||
transfer.transferred_bytes = get_field<int64_t>(map, "transferred_bytes");
|
||||
transfer.total_bytes = get_field<int64_t>(map, "total_bytes");
|
||||
transfer.transfer_speed = get_field<int64_t>(map, "transfer_speed");
|
||||
transfer.estimated_time_remaining =
|
||||
get_field<int64_t>(map, "estimated_time_remaining");
|
||||
transfer.total_attachments_count =
|
||||
get_field<int32_t>(map, "total_attachments_count");
|
||||
transfer.transferred_attachments_count =
|
||||
get_field<int32_t>(map, "transferred_attachments_count");
|
||||
transfer.is_final_status = get_field<bool>(map, "is_final_status");
|
||||
transfer.is_self_share = get_field<bool>(map, "is_self_share");
|
||||
transfer.binding_id = get_field<std::string>(map, "binding_id");
|
||||
|
||||
// Optional fields
|
||||
transfer.token = get_optional_field<std::string>(map, "token");
|
||||
transfer.in_progress_attachment_id =
|
||||
get_optional_field<int64_t>(map, "in_progress_attachment_id");
|
||||
transfer.in_progress_attachment_transferred_bytes =
|
||||
get_optional_field<int64_t>(map,
|
||||
"in_progress_attachment_transferred_bytes");
|
||||
transfer.in_progress_attachment_total_bytes =
|
||||
get_optional_field<int64_t>(map, "in_progress_attachment_total_bytes");
|
||||
return transfer;
|
||||
}
|
||||
|
||||
// Converter: Map -> Status
|
||||
Status convertToStatus(const std::map<std::string, sdbus::Variant>& map) {
|
||||
Status status;
|
||||
status.receive_registered = get_field<bool>(map, "receive_registered");
|
||||
status.discovery_registered = get_field<bool>(map, "discovery_registered");
|
||||
status.is_transferring = get_field<bool>(map, "is_transferring");
|
||||
status.is_scanning = get_field<bool>(map, "is_scanning");
|
||||
status.bluetooth_present = get_field<bool>(map, "bluetooth_present");
|
||||
status.bluetooth_powered = get_field<bool>(map, "bluetooth_powered");
|
||||
status.lan_connected = get_field<bool>(map, "lan_connected");
|
||||
|
||||
// Unpack aa{sv} (vector of maps) into vector of ShareTarget structs
|
||||
auto it = map.find("targets");
|
||||
if (it != map.end()) {
|
||||
try {
|
||||
auto raw_targets =
|
||||
it->second.get<std::vector<std::map<std::string, sdbus::Variant>>>();
|
||||
for (const auto& target_map : raw_targets) {
|
||||
status.targets.push_back(convertToShareTarget(target_map));
|
||||
}
|
||||
} catch (const sdbus::Error& e) {
|
||||
// Handle type mismatch for targets array
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
void NearbySharingService::onTargetDiscovered(
|
||||
const std::map<std::string, sdbus::Variant>& share_target) {
|
||||
auto target = convertToShareTarget(share_target);
|
||||
targets_[target.id] = target;
|
||||
};
|
||||
|
||||
void NearbySharingService::onTargetUpdated(
|
||||
const std::map<std::string, sdbus::Variant>& share_target) {
|
||||
auto target = convertToShareTarget(share_target);
|
||||
targets_[target.id] = target;
|
||||
};
|
||||
|
||||
void NearbySharingService::onTargetLost(
|
||||
const std::map<std::string, sdbus::Variant>& share_target) {
|
||||
auto target = convertToShareTarget(share_target);
|
||||
if (targets_.find(target.id) != targets_.end()) {
|
||||
targets_.erase(target.id);
|
||||
}
|
||||
};
|
||||
|
||||
void NearbySharingService::onIncomingTransfer(
|
||||
const std::string& direction,
|
||||
const std::map<std::string, sdbus::Variant>& share_target,
|
||||
const std::map<std::string, sdbus::Variant>& transfer) {
|
||||
auto target = convertToShareTarget(share_target);
|
||||
auto incoming_transfer = convertToTransfer(transfer);
|
||||
|
||||
incoming_transfer_ = incoming_transfer;
|
||||
};
|
||||
|
||||
void NearbySharingService::onTransferUpdate(
|
||||
const std::string& direction,
|
||||
const std::map<std::string, sdbus::Variant>& share_target,
|
||||
const std::map<std::string, sdbus::Variant>& transfer) {};
|
||||
|
||||
void NearbySharingService::onStatusChanged(
|
||||
const std::map<std::string, sdbus::Variant>& share_target) {};
|
||||
@@ -1,78 +0,0 @@
|
||||
#include "sharing/linux/daemon/nearby_sharing_client.h"
|
||||
|
||||
struct ShareTarget {
|
||||
int64_t id;
|
||||
std::string device_name;
|
||||
int32_t type;
|
||||
bool is_incoming;
|
||||
bool is_known;
|
||||
std::string device_id;
|
||||
bool for_self_share;
|
||||
int32_t vendor_id;
|
||||
bool receive_disabled;
|
||||
};
|
||||
|
||||
struct Transfer {
|
||||
std::string status;
|
||||
int32_t progress;
|
||||
int64_t transferred_bytes;
|
||||
int64_t total_bytes;
|
||||
int64_t transfer_speed;
|
||||
int64_t estimated_time_remaining;
|
||||
int32_t total_attachments_count;
|
||||
int32_t transferred_attachments_count;
|
||||
bool is_final_status;
|
||||
bool is_self_share;
|
||||
std::string binding_id;
|
||||
std::optional<std::string> token;
|
||||
std::optional<int64_t> in_progress_attachment_id;
|
||||
std::optional<int64_t> in_progress_attachment_transferred_bytes;
|
||||
std::optional<int64_t> in_progress_attachment_total_bytes;
|
||||
};
|
||||
|
||||
struct Status {
|
||||
bool receive_registered;
|
||||
bool discovery_registered;
|
||||
bool is_transferring;
|
||||
bool is_scanning;
|
||||
bool bluetooth_present;
|
||||
bool bluetooth_powered;
|
||||
bool lan_connected;
|
||||
|
||||
// aa{sv} maps to a vector of ShareTarget structs
|
||||
std::vector<ShareTarget> targets;
|
||||
};
|
||||
|
||||
|
||||
class NearbySharingService
|
||||
: public sdbus::ProxyInterfaces<com::google::nearby::sharing_proxy> {
|
||||
public:
|
||||
NearbySharingService(sdbus::ServiceName dest, sdbus::ObjectPath objectPath)
|
||||
: ProxyInterfaces(std::move(dest), std::move(objectPath)) {
|
||||
registerProxy();
|
||||
}
|
||||
~NearbySharingService() { unregisterProxy(); }
|
||||
|
||||
void onTargetDiscovered(
|
||||
const std::map<std::string, sdbus::Variant>& share_target) override;
|
||||
void onTargetUpdated(
|
||||
const std::map<std::string, sdbus::Variant>& share_target) override;
|
||||
void onTargetLost(
|
||||
const std::map<std::string, sdbus::Variant>& share_target) override;
|
||||
void onIncomingTransfer(
|
||||
const std::string& direction,
|
||||
const std::map<std::string, sdbus::Variant>& share_target,
|
||||
const std::map<std::string, sdbus::Variant>& transfer) override;
|
||||
void onTransferUpdate(
|
||||
const std::string& direction,
|
||||
const std::map<std::string, sdbus::Variant>& share_target,
|
||||
const std::map<std::string, sdbus::Variant>& transfer) override;
|
||||
void onStatusChanged(
|
||||
const std::map<std::string, sdbus::Variant>& status) override;
|
||||
|
||||
private:
|
||||
Status status_;
|
||||
std::map<int, ShareTarget> targets_;
|
||||
Transfer outgoing_transfer_;
|
||||
Transfer incoming_transfer_;
|
||||
};
|
||||
@@ -1,11 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
|
||||
enum class Page {
|
||||
FilePicker,
|
||||
Sharing,
|
||||
IncomingShare,
|
||||
};
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -1,46 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "ftxui/screen/color.hpp"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
using namespace ftxui;
|
||||
|
||||
struct Palette {
|
||||
// === Core Typography & Brand ===
|
||||
// Primary light text for high-contrast readability against dark backgrounds
|
||||
inline static const Color primary = Color::RGB(0xF1, 0xF9, 0xF6); // Off-white mint tint
|
||||
|
||||
// Secondary text, inactive states, or subtle accents
|
||||
inline static const Color secondary = Color::RGB(0x8A, 0xAF, 0xA4); // Muted sage gray
|
||||
|
||||
// Main brand accent, focused element backgrounds, or prominent icons (Unchanged)
|
||||
inline static const Color accent = Color::RGB(0xA3, 0xD9, 0xC9); // Original Mint Leaf
|
||||
|
||||
// === Surface & Structure ===
|
||||
// Active menu item highlights, selection cards, or focused component backgrounds
|
||||
inline static const Color active = Color::RGB(0x23, 0x3D, 0x34); // Deep forest green tint
|
||||
|
||||
// Base application window background
|
||||
inline static const Color base = Color::RGB(0x12, 0x1D, 0x1A); // Near-black deep mint/charcoal
|
||||
|
||||
// Explicit component surface background (e.g., sidebars, modals, or inactive cards)
|
||||
inline static const Color surface = Color::RGB(0x19, 0x2A, 0x25); // Mid-tone dark green
|
||||
|
||||
// Standard UI borders, dividers, and subtle grid lines
|
||||
inline static const Color border = Color::RGB(0x32, 0x52, 0x47); // Defined slate green
|
||||
|
||||
// Extremely muted text, placeholders, or disabled options
|
||||
inline static const Color disabled = Color::RGB(0x56, 0x73, 0x6B); // Ghostly sage green
|
||||
|
||||
// === Functional / Status Elements ===
|
||||
// Critical errors, destructive actions, or alerts (toned down for dark mode)
|
||||
inline static const Color error = Color::RGB(0xE0, 0x7A, 0x7A); // Soft desaturated coral/red
|
||||
|
||||
// Warnings, pending indicators, or high-priority notifications
|
||||
inline static const Color warning = Color::RGB(0xE6, 0xC2, 0x80); // Soft amber gold
|
||||
|
||||
// Success messages, online badges, or completed operations
|
||||
inline static const Color success = Color::RGB(0x81, 0xC7, 0x9D); // Vibrant spring mint
|
||||
};
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -1,66 +0,0 @@
|
||||
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",
|
||||
"//sharing/linux/tui/components:icons"
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "sidebar",
|
||||
srcs = [
|
||||
"sidebar.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"sidebar.h",
|
||||
],
|
||||
deps = [
|
||||
"//sharing/linux/tui:palette",
|
||||
"//sharing/linux/tui/components:icons",
|
||||
"@ftxui//:ftxui",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "file_selected_screen",
|
||||
srcs = [
|
||||
"file_selected_screen.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"file_selected_screen.h",
|
||||
],
|
||||
deps = [
|
||||
"//sharing/linux/tui:palette",
|
||||
"//sharing/linux/tui/components:share_target",
|
||||
"@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/components:incoming_share_card",
|
||||
"//sharing/linux/tui:file_picker",
|
||||
"//sharing/linux/tui:page",
|
||||
"//sharing/linux/tui:palette",
|
||||
"//sharing/linux/tui/components:file_picker_card",
|
||||
"@ftxui//:ftxui",
|
||||
],
|
||||
)
|
||||
@@ -1,37 +0,0 @@
|
||||
#include "sharing/linux/tui/ui/file_selected_screen.h"
|
||||
|
||||
#include "sharing/linux/tui/components/share_target.h"
|
||||
#include "sharing/linux/tui/palette.h"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
using namespace ftxui;
|
||||
|
||||
Element FileSelectedScreen(const std::string& selected_file) {
|
||||
FlexboxConfig config;
|
||||
config.direction = FlexboxConfig::Direction::Row;
|
||||
config.wrap = FlexboxConfig::Wrap::Wrap;
|
||||
config.gap_x = 1;
|
||||
config.gap_y = 1;
|
||||
return vbox({
|
||||
hbox(
|
||||
{filler(),
|
||||
flexbox(
|
||||
{
|
||||
ShareTarget("Lasan's A55", ShareTargetType::kPhone),
|
||||
ShareTarget("lasan-laptop", ShareTargetType::kLaptop),
|
||||
ShareTarget("lasan-laptop", ShareTargetType::kLaptop),
|
||||
ShareTarget("lasan-laptop", ShareTargetType::kLaptop),
|
||||
ShareTarget("Lasan's S9+", ShareTargetType::kTablet),
|
||||
ShareTarget("Lasan's S9+", ShareTargetType::kTablet),
|
||||
|
||||
},
|
||||
config) |
|
||||
flex
|
||||
|
||||
}),
|
||||
filler(),
|
||||
}) |
|
||||
flex;
|
||||
}
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -1,12 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
using namespace ftxui;
|
||||
|
||||
Element FileSelectedScreen(const std::string& selected_file);
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -1,11 +0,0 @@
|
||||
#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
|
||||
@@ -1,10 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
using namespace ftxui;
|
||||
|
||||
Element HomeHeader();
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -1,60 +0,0 @@
|
||||
#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/components/incoming_share_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 {
|
||||
using namespace ftxui;
|
||||
|
||||
Component HomeScreen(HomeScreenOptions options) {
|
||||
auto file_picker_card =
|
||||
FilePickerCard({.file_picker = options.file_picker,
|
||||
.on_file_selected = options.on_file_selected});
|
||||
auto incoming_share_card =
|
||||
IncomingShareCard({.device_name = options.incoming_share_device_name,
|
||||
.device_type = options.incoming_share_device_type,
|
||||
.on_accept = options.on_incoming_share_accept,
|
||||
.on_decline = options.on_incoming_share_decline});
|
||||
auto content = Container::Vertical({file_picker_card, incoming_share_card});
|
||||
|
||||
return Renderer(content, [file_picker_card, incoming_share_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;
|
||||
|
||||
Element main_panel;
|
||||
switch (current_page) {
|
||||
case Page::FilePicker:
|
||||
main_panel = file_picker_card->Render();
|
||||
break;
|
||||
case Page::IncomingShare:
|
||||
main_panel = incoming_share_card->Render();
|
||||
break;
|
||||
case Page::Sharing:
|
||||
main_panel = FileSelectedScreen(selected_file);
|
||||
break;
|
||||
}
|
||||
|
||||
return vbox({
|
||||
HomeHeader() | color(Palette::accent),
|
||||
separator(),
|
||||
hbox({
|
||||
Sidebar({.hostname = options.hostname,
|
||||
.selected_file = selected_file}),
|
||||
separator() | color(Palette::border),
|
||||
main_panel | flex,
|
||||
}) | flex,
|
||||
}) |
|
||||
bgcolor(Palette::base) | size(WIDTH, GREATER_THAN, 80) |
|
||||
size(HEIGHT, GREATER_THAN, 24);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -1,28 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#include "ftxui/component/component.hpp"
|
||||
#include "sharing/linux/tui/components/share_target.h"
|
||||
#include "sharing/linux/tui/file_picker.h"
|
||||
#include "sharing/linux/tui/page.h"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
using namespace ftxui;
|
||||
|
||||
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;
|
||||
std::string incoming_share_device_name;
|
||||
ShareTargetType incoming_share_device_type = ShareTargetType::kUnknown;
|
||||
std::function<void()> on_incoming_share_accept;
|
||||
std::function<void()> on_incoming_share_decline;
|
||||
};
|
||||
|
||||
Component HomeScreen(HomeScreenOptions options);
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -1,38 +0,0 @@
|
||||
#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
|
||||
@@ -1,17 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
using namespace ftxui;
|
||||
|
||||
struct SidebarState {
|
||||
std::string hostname;
|
||||
std::string selected_file;
|
||||
};
|
||||
|
||||
Element Sidebar(const SidebarState& state);
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
Reference in New Issue
Block a user