refactor(arcanegram): settings submenus + input polish
This commit is contained in:
parent
db1bf8b947
commit
0620ee457b
6 changed files with 243 additions and 62 deletions
|
|
@ -19,4 +19,16 @@
|
|||
"ag_fast_messages_title" = "Fast messages";
|
||||
"ag_fast_messages_info" = "Type a message per slot. Bind keys in Settings → Chat Settings → Keyboard Shortcuts.";
|
||||
"ag_fast_messages_slot" = "Slot {index}";
|
||||
"ag_fast_messages_placeholder" = "Message text (e.g. /dban begging)";
|
||||
"ag_fast_messages_placeholder" = "Message text";
|
||||
"ag_settings_appearance" = "Chat appearance";
|
||||
"ag_settings_sync_title" = "Cloud sync";
|
||||
"ag_sync_enabled_setting" = "Enable cloud sync";
|
||||
"ag_sync_enabled_info" = "Sync arcanegram-only settings between your devices via the arcanesync backend.";
|
||||
"ag_sync_endpoint_placeholder" = "Endpoint URL";
|
||||
"ag_sync_status_disabled" = "Disabled";
|
||||
"ag_sync_status_ready" = "Ready";
|
||||
"ag_sync_status_synced" = "Synced";
|
||||
"ag_sync_status_syncing" = "Syncing…";
|
||||
"ag_sync_status_offline" = "Offline";
|
||||
"ag_sync_status_offline_pending" = "Offline · {n} pending";
|
||||
"ag_sync_status_conflict" = "Resolving conflict…";
|
||||
|
|
|
|||
|
|
@ -1,3 +1,22 @@
|
|||
using "ui/widgets/widgets.style";
|
||||
|
||||
menuIconArcanegramSettings: icon {{ "arcanegram/settings/arcanegram_settings", menuIconColor }};
|
||||
|
||||
agFastMessageField: InputField(defaultInputField) {
|
||||
textBg: transparent;
|
||||
textMargins: margins(2px, 8px, 2px, 12px);
|
||||
|
||||
placeholderFg: placeholderFg;
|
||||
placeholderFgActive: placeholderFgActive;
|
||||
placeholderFgError: placeholderFgActive;
|
||||
placeholderMargins: margins(0px, 0px, 0px, 0px);
|
||||
placeholderScale: 0.;
|
||||
placeholderFont: normalFont;
|
||||
|
||||
border: 0px;
|
||||
borderActive: 0px;
|
||||
|
||||
heightMin: 40px;
|
||||
|
||||
style: defaultTextStyle;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include "main/main_session.h"
|
||||
#include "settings/settings_builder.h"
|
||||
#include "settings/settings_common_session.h"
|
||||
#include "styles/style_arcanegram.h"
|
||||
#include "styles/style_menu_icons.h"
|
||||
#include "styles/style_settings.h"
|
||||
#include "ui/vertical_list.h"
|
||||
|
|
@ -35,7 +36,7 @@ void AddSlotField(
|
|||
const auto field = container->add(
|
||||
object_ptr<Ui::InputField>(
|
||||
container,
|
||||
st::settingsBio,
|
||||
st::agFastMessageField,
|
||||
tr::ag_fast_messages_placeholder(),
|
||||
item.value()),
|
||||
st::settingsBioMargins);
|
||||
|
|
|
|||
|
|
@ -2,53 +2,72 @@
|
|||
|
||||
#include "arcanegram/ag_config.h"
|
||||
#include "arcanegram/sync/ag_sync_engine.h"
|
||||
#include "arcanegram/ui/ag_settings_main.h"
|
||||
#include "arcanegram/ui/ag_settings_widgets.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "settings/settings_builder.h"
|
||||
#include "settings/settings_common_session.h"
|
||||
#include "styles/style_menu_icons.h"
|
||||
#include "ui/wrap/vertical_layout.h"
|
||||
#include "window/window_session_controller.h"
|
||||
|
||||
#include <rpl/map.h>
|
||||
#include <rpl/producer.h>
|
||||
|
||||
// todo: replace hardcoded strings with tr::ag_sync_* once the misc__lang-keys
|
||||
// stgit patch is updated to declare them.
|
||||
|
||||
namespace Arcanegram::CloudSync {
|
||||
namespace {
|
||||
|
||||
using namespace ::Settings;
|
||||
using namespace ::Settings::Builder;
|
||||
|
||||
QString FormatStatus(const Sync::StatusInfo &info) {
|
||||
switch (info.status) {
|
||||
case Sync::Status::Disabled:
|
||||
return u"disabled"_q;
|
||||
return tr::ag_sync_status_disabled(tr::now);
|
||||
case Sync::Status::Idle:
|
||||
return info.lastSyncedAt
|
||||
? u"synced"_q
|
||||
: u"ready"_q;
|
||||
? tr::ag_sync_status_synced(tr::now)
|
||||
: tr::ag_sync_status_ready(tr::now);
|
||||
case Sync::Status::Syncing:
|
||||
return u"syncing…"_q;
|
||||
return tr::ag_sync_status_syncing(tr::now);
|
||||
case Sync::Status::Offline: {
|
||||
const auto base = info.pendingCount
|
||||
? u"offline · %1 pending"_q.arg(info.pendingCount)
|
||||
: u"offline"_q;
|
||||
? tr::ag_sync_status_offline_pending(
|
||||
tr::now,
|
||||
lt_n,
|
||||
QString::number(info.pendingCount))
|
||||
: tr::ag_sync_status_offline(tr::now);
|
||||
return info.message.isEmpty() ? base : (base + u" · "_q + info.message);
|
||||
}
|
||||
case Sync::Status::Conflict:
|
||||
return u"resolving conflict…"_q;
|
||||
return tr::ag_sync_status_conflict(tr::now);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
class Page : public Section<Page> {
|
||||
public:
|
||||
Page(QWidget *parent, not_null<Window::SessionController*> controller);
|
||||
|
||||
void Setup(::Settings::Builder::SectionBuilder &builder) {
|
||||
[[nodiscard]] rpl::producer<QString> title() override {
|
||||
return tr::ag_settings_sync_title();
|
||||
}
|
||||
|
||||
private:
|
||||
void setupContent();
|
||||
};
|
||||
|
||||
void BuildPage(SectionBuilder &builder) {
|
||||
Arcanegram::Settings::AddBoolRow(
|
||||
builder,
|
||||
u"arcanegram/sync_enabled"_q,
|
||||
rpl::single(u"cloud sync (experimental)"_q),
|
||||
rpl::single(u"sync arcanegram-only settings between your devices via the arcanesync backend."_q),
|
||||
tr::ag_sync_enabled_setting(),
|
||||
tr::ag_sync_enabled_info(),
|
||||
Config::Sync::Enabled);
|
||||
|
||||
Arcanegram::Settings::AddTextRow(
|
||||
builder,
|
||||
rpl::single(u"endpoint"_q),
|
||||
tr::ag_sync_endpoint_placeholder(),
|
||||
Config::Sync::Endpoint);
|
||||
|
||||
auto statusText = []() -> rpl::producer<QString> {
|
||||
|
|
@ -60,4 +79,38 @@ void Setup(::Settings::Builder::SectionBuilder &builder) {
|
|||
Arcanegram::Settings::AddStatusRow(builder, std::move(statusText));
|
||||
}
|
||||
|
||||
const auto kPageMeta = BuildHelper({
|
||||
.id = Page::Id(),
|
||||
.parentId = Arcanegram::Settings::Id(),
|
||||
.title = &tr::ag_settings_sync_title,
|
||||
.icon = &st::menuIconLink,
|
||||
}, [](SectionBuilder &builder) {
|
||||
BuildPage(builder);
|
||||
});
|
||||
|
||||
const SectionBuildMethod kPageSection = kPageMeta.build;
|
||||
|
||||
Page::Page(
|
||||
QWidget *parent,
|
||||
not_null<Window::SessionController*> controller)
|
||||
: Section(parent, controller) {
|
||||
setupContent();
|
||||
}
|
||||
|
||||
void Page::setupContent() {
|
||||
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
|
||||
build(content, kPageSection);
|
||||
Ui::ResizeFitChild(this, content);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void Setup(::Settings::Builder::SectionBuilder &builder) {
|
||||
builder.addSectionButton({
|
||||
.title = tr::ag_settings_sync_title(),
|
||||
.targetSection = Page::Id(),
|
||||
.icon = { &st::menuIconLink },
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace Arcanegram::CloudSync
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "arcanegram/ui/ag_hidden_users_settings.h"
|
||||
|
||||
#include "arcanegram/features/ag_hidden_users.h"
|
||||
#include "arcanegram/ui/ag_settings_main.h"
|
||||
#include "core/application.h"
|
||||
#include "data/data_peer.h"
|
||||
#include "data/data_session.h"
|
||||
|
|
@ -9,64 +10,114 @@
|
|||
#include "main/main_domain.h"
|
||||
#include "main/main_session.h"
|
||||
#include "settings/settings_builder.h"
|
||||
#include "settings/settings_common_session.h"
|
||||
#include "styles/style_menu_icons.h"
|
||||
#include "styles/style_settings.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/wrap/vertical_layout.h"
|
||||
#include "window/window_session_controller.h"
|
||||
|
||||
namespace Arcanegram::HiddenUsers {
|
||||
namespace {
|
||||
|
||||
using namespace ::Settings;
|
||||
using namespace ::Settings::Builder;
|
||||
|
||||
[[nodiscard]] PeerData *AnyLoadedPeer(PeerId id) {
|
||||
for (const auto &entry : Core::App().domain().accounts()) {
|
||||
if (const auto session = entry.account->maybeSession()) {
|
||||
if (const auto peer = session->data().peerLoaded(id)) {
|
||||
return peer;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
for (const auto &entry : Core::App().domain().accounts()) {
|
||||
if (const auto session = entry.account->maybeSession()) {
|
||||
if (const auto peer = session->data().peerLoaded(id)) {
|
||||
return peer;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Rebuild(not_null<Ui::VerticalLayout*> container) {
|
||||
while (container->count()) {
|
||||
delete container->widgetAt(0);
|
||||
}
|
||||
const auto &set = List();
|
||||
if (set.empty()) {
|
||||
container->add(
|
||||
object_ptr<Ui::FlatLabel>(
|
||||
container,
|
||||
tr::ag_hidden_users_empty(),
|
||||
st::boxDividerLabel),
|
||||
st::defaultBoxDividerLabelPadding);
|
||||
return;
|
||||
}
|
||||
for (const auto &id : set) {
|
||||
const auto peer = AnyLoadedPeer(id);
|
||||
const auto label = peer
|
||||
? peer->name()
|
||||
: QString::number(id.value);
|
||||
const auto row = container->add(
|
||||
object_ptr<Ui::SettingsButton>(
|
||||
container,
|
||||
rpl::single(label),
|
||||
st::settingsButtonNoIcon));
|
||||
row->setClickedCallback([id] { Unhide(id); });
|
||||
}
|
||||
while (container->count()) {
|
||||
delete container->widgetAt(0);
|
||||
}
|
||||
const auto &set = List();
|
||||
if (set.empty()) {
|
||||
container->add(
|
||||
object_ptr<Ui::FlatLabel>(
|
||||
container,
|
||||
tr::ag_hidden_users_empty(),
|
||||
st::boxDividerLabel),
|
||||
st::defaultBoxDividerLabelPadding);
|
||||
return;
|
||||
}
|
||||
for (const auto &id : set) {
|
||||
const auto peer = AnyLoadedPeer(id);
|
||||
const auto label = peer
|
||||
? peer->name()
|
||||
: QString::number(id.value);
|
||||
const auto row = container->add(
|
||||
object_ptr<Ui::SettingsButton>(
|
||||
container,
|
||||
rpl::single(label),
|
||||
st::settingsButtonNoIcon));
|
||||
row->setClickedCallback([id] { Unhide(id); });
|
||||
}
|
||||
}
|
||||
|
||||
class Page : public Section<Page> {
|
||||
public:
|
||||
Page(QWidget *parent, not_null<Window::SessionController*> controller);
|
||||
|
||||
[[nodiscard]] rpl::producer<QString> title() override {
|
||||
return tr::ag_hidden_users_title();
|
||||
}
|
||||
|
||||
private:
|
||||
void setupContent();
|
||||
};
|
||||
|
||||
void BuildPage(SectionBuilder &builder) {
|
||||
const auto outer = builder.container();
|
||||
const auto inner = outer->add(object_ptr<Ui::VerticalLayout>(outer));
|
||||
Rebuild(inner);
|
||||
Changes(
|
||||
) | rpl::on_next([=](PeerId) {
|
||||
Rebuild(inner);
|
||||
}, inner->lifetime());
|
||||
builder.addDividerText(tr::ag_hidden_users_info());
|
||||
}
|
||||
|
||||
const auto kPageMeta = BuildHelper({
|
||||
.id = Page::Id(),
|
||||
.parentId = Arcanegram::Settings::Id(),
|
||||
.title = &tr::ag_hidden_users_title,
|
||||
.icon = &st::menuIconStealth,
|
||||
}, [](SectionBuilder &builder) {
|
||||
BuildPage(builder);
|
||||
});
|
||||
|
||||
const SectionBuildMethod kPageSection = kPageMeta.build;
|
||||
|
||||
Page::Page(
|
||||
QWidget *parent,
|
||||
not_null<Window::SessionController*> controller)
|
||||
: Section(parent, controller) {
|
||||
setupContent();
|
||||
}
|
||||
|
||||
void Page::setupContent() {
|
||||
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
|
||||
build(content, kPageSection);
|
||||
Ui::ResizeFitChild(this, content);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void Setup(::Settings::Builder::SectionBuilder &builder) {
|
||||
const auto outer = builder.container();
|
||||
const auto inner = outer->add(object_ptr<Ui::VerticalLayout>(outer));
|
||||
Rebuild(inner);
|
||||
Changes(
|
||||
) | rpl::on_next([=](PeerId) {
|
||||
Rebuild(inner);
|
||||
}, inner->lifetime());
|
||||
builder.addDividerText(tr::ag_hidden_users_info());
|
||||
builder.addSectionButton({
|
||||
.title = tr::ag_hidden_users_title(),
|
||||
.targetSection = Page::Id(),
|
||||
.icon = { &st::menuIconStealth },
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace Arcanegram::HiddenUsers
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
#include "arcanegram/ui/ag_settings_main.h"
|
||||
|
||||
#include "arcanegram/features/ag_forwarded_header.h"
|
||||
#include "arcanegram/features/ag_show_seconds.h"
|
||||
#include "arcanegram/features/ag_chat_wallpaper.h"
|
||||
#include "arcanegram/features/ag_fast_messages.h"
|
||||
#include "arcanegram/features/ag_forwarded_header.h"
|
||||
#include "arcanegram/features/ag_show_seconds.h"
|
||||
#include "arcanegram/features/ag_sync_feature.h"
|
||||
#include "arcanegram/ui/ag_hidden_users_settings.h"
|
||||
#include "lang/lang_keys.h"
|
||||
|
|
@ -11,6 +11,7 @@
|
|||
#include "settings/settings_builder.h"
|
||||
#include "settings/settings_common_session.h"
|
||||
#include "styles/style_arcanegram.h"
|
||||
#include "styles/style_menu_icons.h"
|
||||
#include "ui/wrap/vertical_layout.h"
|
||||
#include "window/window_session_controller.h"
|
||||
|
||||
|
|
@ -32,13 +33,57 @@ private:
|
|||
void setupContent();
|
||||
};
|
||||
|
||||
void BuildContent(SectionBuilder &builder) {
|
||||
class Appearance : public Section<Appearance> {
|
||||
public:
|
||||
Appearance(QWidget *parent, not_null<Window::SessionController*> controller);
|
||||
|
||||
[[nodiscard]] rpl::producer<QString> title() override {
|
||||
return tr::ag_settings_appearance();
|
||||
}
|
||||
|
||||
private:
|
||||
void setupContent();
|
||||
};
|
||||
|
||||
void BuildAppearance(SectionBuilder &builder) {
|
||||
Arcanegram::ForwardedHeader::Setup(builder);
|
||||
Arcanegram::Time::Setup(builder);
|
||||
Arcanegram::ChatWallpaper::Setup(builder);
|
||||
}
|
||||
|
||||
const auto kAppearanceMeta = BuildHelper({
|
||||
.id = Appearance::Id(),
|
||||
.parentId = Main::Id(),
|
||||
.title = &tr::ag_settings_appearance,
|
||||
.icon = &st::menuIconPalette,
|
||||
}, [](SectionBuilder &builder) {
|
||||
BuildAppearance(builder);
|
||||
});
|
||||
|
||||
const SectionBuildMethod kAppearanceSection = kAppearanceMeta.build;
|
||||
|
||||
Appearance::Appearance(
|
||||
QWidget *parent,
|
||||
not_null<Window::SessionController*> controller)
|
||||
: Section(parent, controller) {
|
||||
setupContent();
|
||||
}
|
||||
|
||||
void Appearance::setupContent() {
|
||||
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
|
||||
build(content, kAppearanceSection);
|
||||
Ui::ResizeFitChild(this, content);
|
||||
}
|
||||
|
||||
void BuildContent(SectionBuilder &builder) {
|
||||
builder.addSectionButton({
|
||||
.title = tr::ag_settings_appearance(),
|
||||
.targetSection = Appearance::Id(),
|
||||
.icon = { &st::menuIconPalette },
|
||||
});
|
||||
Arcanegram::HiddenUsers::Setup(builder);
|
||||
Arcanegram::CloudSync::Setup(builder);
|
||||
Arcanegram::FastMessages::Setup(builder);
|
||||
Arcanegram::CloudSync::Setup(builder);
|
||||
}
|
||||
|
||||
const auto kMeta = BuildHelper({
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue