[ui] Add auto-mount on first launch functionality #52
This commit is contained in:
@@ -426,6 +426,7 @@ inline constexpr auto JSON_MAX_CONNECTIONS{"MaxConnections"};
|
|||||||
inline constexpr auto JSON_MAX_UPLOAD_COUNT{"MaxUploadCount"};
|
inline constexpr auto JSON_MAX_UPLOAD_COUNT{"MaxUploadCount"};
|
||||||
inline constexpr auto JSON_MED_FREQ_INTERVAL_SECS{"MedFreqIntervalSeconds"};
|
inline constexpr auto JSON_MED_FREQ_INTERVAL_SECS{"MedFreqIntervalSeconds"};
|
||||||
inline constexpr auto JSON_META{"Meta"};
|
inline constexpr auto JSON_META{"Meta"};
|
||||||
|
inline constexpr auto JSON_MOUNT_AUTO_START{"MountAutoStart"};
|
||||||
inline constexpr auto JSON_MOUNT_LOCATIONS{"MountLocations"};
|
inline constexpr auto JSON_MOUNT_LOCATIONS{"MountLocations"};
|
||||||
inline constexpr auto JSON_ONLINE_CHECK_RETRY_SECS{"OnlineCheckRetrySeconds"};
|
inline constexpr auto JSON_ONLINE_CHECK_RETRY_SECS{"OnlineCheckRetrySeconds"};
|
||||||
inline constexpr auto JSON_PATH{"Path"};
|
inline constexpr auto JSON_PATH{"Path"};
|
||||||
|
@@ -104,6 +104,9 @@ private:
|
|||||||
|
|
||||||
void handle_post_mount(const httplib::Request &req, httplib::Response &res);
|
void handle_post_mount(const httplib::Request &req, httplib::Response &res);
|
||||||
|
|
||||||
|
void handle_put_mount_auto_start(const httplib::Request &req,
|
||||||
|
httplib::Response &res) const;
|
||||||
|
|
||||||
void handle_put_mount_location(const httplib::Request &req,
|
void handle_put_mount_location(const httplib::Request &req,
|
||||||
httplib::Response &res) const;
|
httplib::Response &res) const;
|
||||||
|
|
||||||
|
@@ -42,6 +42,8 @@ private:
|
|||||||
std::unordered_map<provider_type,
|
std::unordered_map<provider_type,
|
||||||
std::unordered_map<std::string, std::string>>
|
std::unordered_map<std::string, std::string>>
|
||||||
locations_;
|
locations_;
|
||||||
|
std::unordered_map<provider_type, std::unordered_map<std::string, bool>>
|
||||||
|
mount_auto_start_;
|
||||||
mutable std::recursive_mutex mtx_;
|
mutable std::recursive_mutex mtx_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -60,6 +62,9 @@ public:
|
|||||||
|
|
||||||
[[nodiscard]] auto get_auto_start() const -> bool { return auto_start_; }
|
[[nodiscard]] auto get_auto_start() const -> bool { return auto_start_; }
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_auto_start(provider_type prov,
|
||||||
|
std::string_view name) const -> bool;
|
||||||
|
|
||||||
[[nodiscard]] auto get_hidden() const -> bool { return hidden_; }
|
[[nodiscard]] auto get_hidden() const -> bool { return hidden_; }
|
||||||
|
|
||||||
[[nodiscard]] auto get_launch_only() const -> bool { return launch_only_; }
|
[[nodiscard]] auto get_launch_only() const -> bool { return launch_only_; }
|
||||||
@@ -76,6 +81,9 @@ public:
|
|||||||
|
|
||||||
void set_auto_start(bool auto_start);
|
void set_auto_start(bool auto_start);
|
||||||
|
|
||||||
|
void set_auto_start(provider_type prov, std::string_view name,
|
||||||
|
bool auto_start);
|
||||||
|
|
||||||
void set_hidden(bool hidden);
|
void set_hidden(bool hidden);
|
||||||
|
|
||||||
void set_launch_only(bool launch_only);
|
void set_launch_only(bool launch_only);
|
||||||
|
@@ -255,6 +255,10 @@ handlers::handlers(mgmt_app_config *config, httplib::Server *server)
|
|||||||
server->Post("/api/v1/mount",
|
server->Post("/api/v1/mount",
|
||||||
[this](auto &&req, auto &&res) { handle_post_mount(req, res); });
|
[this](auto &&req, auto &&res) { handle_post_mount(req, res); });
|
||||||
|
|
||||||
|
server->Put("/api/v1/mount_auto_start", [this](auto &&req, auto &&res) {
|
||||||
|
handle_put_mount_auto_start(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
server->Put("/api/v1/mount_location", [this](auto &&req, auto &&res) {
|
server->Put("/api/v1/mount_location", [this](auto &&req, auto &&res) {
|
||||||
handle_put_mount_location(req, res);
|
handle_put_mount_location(req, res);
|
||||||
});
|
});
|
||||||
@@ -382,6 +386,21 @@ void handlers::generate_config(provider_type prov, std::string_view name,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handlers::handle_put_mount_auto_start(const httplib::Request &req,
|
||||||
|
httplib::Response &res) const {
|
||||||
|
auto prov = provider_type_from_string(req.get_param_value("type"));
|
||||||
|
auto name = req.get_param_value("name");
|
||||||
|
|
||||||
|
if (not data_directory_exists(prov, name)) {
|
||||||
|
res.status = http_error_codes::not_found;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto auto_start = utils::string::to_bool(req.get_param_value("auto_start"));
|
||||||
|
config_->set_auto_start(prov, name, auto_start);
|
||||||
|
res.status = http_error_codes::ok;
|
||||||
|
}
|
||||||
|
|
||||||
void handlers::handle_put_mount_location(const httplib::Request &req,
|
void handlers::handle_put_mount_location(const httplib::Request &req,
|
||||||
httplib::Response &res) const {
|
httplib::Response &res) const {
|
||||||
auto prov = provider_type_from_string(req.get_param_value("type"));
|
auto prov = provider_type_from_string(req.get_param_value("type"));
|
||||||
@@ -523,6 +542,8 @@ void handlers::handle_get_mount_status(const httplib::Request &req,
|
|||||||
result.at("Location").get<std::string>());
|
result.at("Location").get<std::string>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result["AutoStart"] = config_->get_auto_start(prov, name);
|
||||||
|
|
||||||
res.set_content(result.dump(), "application/json");
|
res.set_content(result.dump(), "application/json");
|
||||||
res.status = http_error_codes::ok;
|
res.status = http_error_codes::ok;
|
||||||
}
|
}
|
||||||
|
@@ -29,11 +29,12 @@
|
|||||||
#include "utils/unix.hpp"
|
#include "utils/unix.hpp"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
template <typename data_t>
|
||||||
[[nodiscard]] auto from_json(const nlohmann::json &json)
|
[[nodiscard]] auto from_json(const nlohmann::json &json)
|
||||||
-> std::unordered_map<repertory::provider_type,
|
-> std::unordered_map<repertory::provider_type,
|
||||||
std::unordered_map<std::string, std::string>> {
|
std::unordered_map<std::string, data_t>> {
|
||||||
std::unordered_map<repertory::provider_type,
|
std::unordered_map<repertory::provider_type,
|
||||||
std::unordered_map<std::string, std::string>>
|
std::unordered_map<std::string, data_t>>
|
||||||
map_of_maps{
|
map_of_maps{
|
||||||
{repertory::provider_type::encrypt, nlohmann::json::object()},
|
{repertory::provider_type::encrypt, nlohmann::json::object()},
|
||||||
{repertory::provider_type::remote, nlohmann::json::object()},
|
{repertory::provider_type::remote, nlohmann::json::object()},
|
||||||
@@ -97,7 +98,8 @@ mgmt_app_config::mgmt_app_config(bool hidden, bool launch_only)
|
|||||||
auto_start_ = data.contains(JSON_AUTO_START)
|
auto_start_ = data.contains(JSON_AUTO_START)
|
||||||
? data.at(JSON_AUTO_START).get<bool>()
|
? data.at(JSON_AUTO_START).get<bool>()
|
||||||
: false;
|
: false;
|
||||||
locations_ = from_json(data.at(JSON_MOUNT_LOCATIONS));
|
mount_auto_start_ = from_json<bool>(data.at(JSON_MOUNT_AUTO_START));
|
||||||
|
locations_ = from_json<std::string>(data.at(JSON_MOUNT_LOCATIONS));
|
||||||
|
|
||||||
if (not data.contains(JSON_AUTO_START)) {
|
if (not data.contains(JSON_AUTO_START)) {
|
||||||
save();
|
save();
|
||||||
@@ -119,6 +121,17 @@ mgmt_app_config::mgmt_app_config(bool hidden, bool launch_only)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto mgmt_app_config::get_auto_start(provider_type prov,
|
||||||
|
std::string_view name) const -> bool {
|
||||||
|
recur_mutex_lock lock(mtx_);
|
||||||
|
if (mount_auto_start_.contains(prov) &&
|
||||||
|
mount_auto_start_.at(prov).contains(std::string{name})) {
|
||||||
|
return mount_auto_start_.at(prov).at(std::string{name});
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
auto mgmt_app_config::get_mount_location(provider_type prov,
|
auto mgmt_app_config::get_mount_location(provider_type prov,
|
||||||
std::string_view name) const
|
std::string_view name) const
|
||||||
-> std::string {
|
-> std::string {
|
||||||
@@ -294,6 +307,22 @@ void mgmt_app_config::set_auto_start(bool auto_start) {
|
|||||||
save();
|
save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mgmt_app_config::set_auto_start(provider_type prov, std::string_view name,
|
||||||
|
bool auto_start) {
|
||||||
|
if (name.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
recur_mutex_lock lock(mtx_);
|
||||||
|
if (mount_auto_start_[prov][std::string{name}] == auto_start) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mount_auto_start_[prov][std::string{name}] = auto_start;
|
||||||
|
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
|
||||||
auto mgmt_app_config::to_json() const -> nlohmann::json {
|
auto mgmt_app_config::to_json() const -> nlohmann::json {
|
||||||
nlohmann::json data;
|
nlohmann::json data;
|
||||||
data[JSON_AUTO_START] = auto_start_;
|
data[JSON_AUTO_START] = auto_start_;
|
||||||
@@ -301,6 +330,7 @@ auto mgmt_app_config::to_json() const -> nlohmann::json {
|
|||||||
data[JSON_API_PORT] = api_port_;
|
data[JSON_API_PORT] = api_port_;
|
||||||
data[JSON_API_USER] = api_user_;
|
data[JSON_API_USER] = api_user_;
|
||||||
data[JSON_MOUNT_LOCATIONS] = map_to_json(locations_);
|
data[JSON_MOUNT_LOCATIONS] = map_to_json(locations_);
|
||||||
|
data[JSON_MOUNT_AUTO_START] = map_to_json(mount_auto_start_);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
} // namespace repertory::ui
|
} // namespace repertory::ui
|
||||||
|
@@ -21,6 +21,7 @@ class Mount with ChangeNotifier {
|
|||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool get autoStart => mountConfig.autoStart;
|
||||||
String? get bucket => mountConfig.bucket;
|
String? get bucket => mountConfig.bucket;
|
||||||
String get id => '${type}_$name';
|
String get id => '${type}_$name';
|
||||||
bool? get mounted => mountConfig.mounted;
|
bool? get mounted => mountConfig.mounted;
|
||||||
@@ -101,6 +102,35 @@ class Mount with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> setMountAutoStart(bool autoStart) async {
|
||||||
|
try {
|
||||||
|
mountConfig.autoStart = autoStart;
|
||||||
|
|
||||||
|
final auth = await _auth.createAuth();
|
||||||
|
final response = await http.put(
|
||||||
|
Uri.parse(
|
||||||
|
Uri.encodeFull(
|
||||||
|
'${getBaseUri()}/api/v1/mount_location?auth=$auth&name=$name&type=$type&auto_start=$autoStart',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.statusCode == 401) {
|
||||||
|
_auth.logoff();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.statusCode == 404) {
|
||||||
|
_mountList?.reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return refresh();
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('$e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> setMountLocation(String location) async {
|
Future<void> setMountLocation(String location) async {
|
||||||
try {
|
try {
|
||||||
mountConfig.path = location;
|
mountConfig.path = location;
|
||||||
|
@@ -3,6 +3,7 @@ import 'package:repertory/helpers.dart' show initialCaps;
|
|||||||
|
|
||||||
class MountConfig {
|
class MountConfig {
|
||||||
bool? mounted;
|
bool? mounted;
|
||||||
|
bool autoStart = false;
|
||||||
final String _name;
|
final String _name;
|
||||||
String path = '';
|
String path = '';
|
||||||
Map<String, dynamic> _settings = {};
|
Map<String, dynamic> _settings = {};
|
||||||
@@ -30,6 +31,9 @@ class MountConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void updateStatus(Map<String, dynamic> status) {
|
void updateStatus(Map<String, dynamic> status) {
|
||||||
|
autoStart = status.containsKey('AutoStart')
|
||||||
|
? status['AutoStart'] as bool
|
||||||
|
: false;
|
||||||
path = status['Location'] as String;
|
path = status['Location'] as String;
|
||||||
mounted = status['Active'] as bool;
|
mounted = status['Active'] as bool;
|
||||||
}
|
}
|
||||||
|
@@ -35,6 +35,11 @@ class _MountWidgetState extends State<MountWidget>
|
|||||||
);
|
);
|
||||||
final subStyle = textTheme.bodyMedium?.copyWith(color: scheme.onSurface);
|
final subStyle = textTheme.bodyMedium?.copyWith(color: scheme.onSurface);
|
||||||
|
|
||||||
|
final visualDensity = VisualDensity(
|
||||||
|
horizontal: -VisualDensity.maximumDensity,
|
||||||
|
vertical: -(VisualDensity.maximumDensity * 2.0),
|
||||||
|
);
|
||||||
|
|
||||||
return ConstrainedBox(
|
return ConstrainedBox(
|
||||||
constraints: const BoxConstraints(minHeight: 120),
|
constraints: const BoxConstraints(minHeight: 120),
|
||||||
child: Card(
|
child: Card(
|
||||||
@@ -141,6 +146,43 @@ class _MountWidgetState extends State<MountWidget>
|
|||||||
style: subStyle,
|
style: subStyle,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
IntrinsicWidth(
|
||||||
|
child: Theme(
|
||||||
|
data: Theme.of(context).copyWith(
|
||||||
|
listTileTheme: const ListTileThemeData(
|
||||||
|
contentPadding: EdgeInsets.zero,
|
||||||
|
horizontalTitleGap: 0,
|
||||||
|
minLeadingWidth: 0,
|
||||||
|
minVerticalPadding: 0,
|
||||||
|
),
|
||||||
|
checkboxTheme: CheckboxThemeData(
|
||||||
|
materialTapTargetSize:
|
||||||
|
MaterialTapTargetSize.shrinkWrap,
|
||||||
|
visualDensity: visualDensity,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: CheckboxListTile(
|
||||||
|
contentPadding: EdgeInsets.zero,
|
||||||
|
materialTapTargetSize:
|
||||||
|
MaterialTapTargetSize.shrinkWrap,
|
||||||
|
onChanged: (_) {},
|
||||||
|
title: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: const [
|
||||||
|
Icon(
|
||||||
|
Icons.auto_mode,
|
||||||
|
size: constants.smallIconSize,
|
||||||
|
),
|
||||||
|
SizedBox(width: constants.paddingSmall),
|
||||||
|
Text('Auto-mount'),
|
||||||
|
SizedBox(width: constants.paddingSmall),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
value: mount.autoStart,
|
||||||
|
visualDensity: visualDensity,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
Reference in New Issue
Block a user