Skip to content

Commit d51a263

Browse files
committed
Duplicate proxy
1 parent d704fff commit d51a263

7 files changed

Lines changed: 147 additions & 20 deletions

File tree

YtFlowApp/AssetModel.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ namespace winrt::YtFlowApp::implementation
66
{
77
using Windows::UI::Xaml::Data::PropertyChangedEventArgs;
88

9-
IObservableVector<ProxyGroupModel> AssetModel::ProxyGroups()
9+
IObservableVector<YtFlowApp::ProxyGroupModel> AssetModel::ProxyGroups()
1010
{
1111
return m_proxyGroups;
1212
}
13-
void AssetModel::ProxyGroups(IObservableVector<ProxyGroupModel> const &value)
13+
void AssetModel::ProxyGroups(IObservableVector<YtFlowApp::ProxyGroupModel> const &value)
1414
{
1515
if (m_proxyGroupsChangeHandle)
1616
{
@@ -40,11 +40,11 @@ namespace winrt::YtFlowApp::implementation
4040
{
4141
m_propertyChanged.remove(token);
4242
}
43-
ProxyGroupModel AssetModel::CurrentProxyGroupModel() const
43+
YtFlowApp::ProxyGroupModel AssetModel::CurrentProxyGroupModel() const
4444
{
4545
return m_currentProxyModel;
4646
}
47-
void AssetModel::CurrentProxyGroupModel(ProxyGroupModel const &value)
47+
void AssetModel::CurrentProxyGroupModel(YtFlowApp::ProxyGroupModel const &value)
4848
{
4949
m_currentProxyModel = value;
5050
m_propertyChanged(*this, PropertyChangedEventArgs(L"CurrentProxyGroupModel"));

YtFlowApp/AssetModel.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,20 @@ namespace winrt::YtFlowApp::implementation
99
{
1010
AssetModel() = default;
1111

12-
IObservableVector<ProxyGroupModel> ProxyGroups();
13-
void ProxyGroups(IObservableVector<ProxyGroupModel> const &value);
12+
IObservableVector<YtFlowApp::ProxyGroupModel> ProxyGroups();
13+
void ProxyGroups(IObservableVector<YtFlowApp::ProxyGroupModel> const &value);
1414
bool IsProxyGroupsEmpty() const;
15-
ProxyGroupModel CurrentProxyGroupModel() const;
16-
void CurrentProxyGroupModel(ProxyGroupModel const &value);
15+
YtFlowApp::ProxyGroupModel CurrentProxyGroupModel() const;
16+
void CurrentProxyGroupModel(YtFlowApp::ProxyGroupModel const &value);
1717

1818
event_token PropertyChanged(Windows::UI::Xaml::Data::PropertyChangedEventHandler const &handler);
1919
void PropertyChanged(event_token const &token) noexcept;
2020

2121
private:
22-
IObservableVector<ProxyGroupModel> m_proxyGroups;
22+
IObservableVector<YtFlowApp::ProxyGroupModel> m_proxyGroups;
2323
event_token m_proxyGroupsChangeHandle;
2424
event<Windows::UI::Xaml::Data::PropertyChangedEventHandler> m_propertyChanged;
25-
ProxyGroupModel m_currentProxyModel{nullptr};
25+
YtFlowApp::ProxyGroupModel m_currentProxyModel{nullptr};
2626
};
2727
}
2828
namespace winrt::YtFlowApp::factory_implementation

YtFlowApp/LibraryPage.cpp

Lines changed: 104 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,15 @@ namespace winrt::YtFlowApp::implementation
9292
{
9393
model->AttachSubscriptionInfo(subscriptionInfo);
9494
}
95-
m_model->ProxyGroups(single_threaded_observable_vector(std::move(proxyGroupModels)));
95+
auto observableProxyGroups = single_threaded_observable_vector(std::move(proxyGroupModels));
96+
observableProxyGroups.VectorChanged([weak = lifetime->get_weak()](auto const &, auto const &) {
97+
if (auto const self = weak.get())
98+
{
99+
self->PopulateProxyGroupItemsForMenu();
100+
}
101+
});
102+
m_model->ProxyGroups(std::move(observableProxyGroups));
103+
lifetime->PopulateProxyGroupItemsForMenu();
96104
}
97105
catch (...)
98106
{
@@ -234,11 +242,12 @@ namespace winrt::YtFlowApp::implementation
234242
co_await resume_background();
235243
auto conn = FfiDbInstance.Connect();
236244
auto const newGroupId = conn.CreateProxyGroup(newGroupName.c_str(), "manual");
237-
auto const newGroupModel = make<ProxyGroupModel>(conn.GetProxyGroupById(newGroupId));
245+
auto newGroup = conn.GetProxyGroupById(newGroupId);
238246
co_await resume_foreground(lifetime->Dispatcher());
239247

248+
auto newGroupModel = make<ProxyGroupModel>(std::move(newGroup));
240249
m_model->ProxyGroups().Append(newGroupModel);
241-
RenameProxyGroupItem(newGroupModel);
250+
RenameProxyGroupItem(std::move(newGroupModel));
242251
}
243252
catch (...)
244253
{
@@ -429,6 +438,26 @@ namespace winrt::YtFlowApp::implementation
429438
Frame().Navigate(xaml_typename<YtFlowApp::EditProxyPage>(), make<EditProxyPageParam>(isReadonly, proxyModel));
430439
}
431440

441+
void LibraryPage::PopulateProxyGroupItemsForMenu()
442+
{
443+
ProxyGroupProxyDuplicateFlyout().Items().Clear();
444+
auto const proxyGroups = m_model->ProxyGroups();
445+
for (auto const proxyGroupModel : proxyGroups)
446+
{
447+
auto const proxyGroup = get_self<ProxyGroupModel>(proxyGroupModel);
448+
if (proxyGroup->IsSubscription())
449+
{
450+
continue;
451+
}
452+
453+
MenuFlyoutItem const menuItemForDuplicate;
454+
menuItemForDuplicate.Text(proxyGroup->Name());
455+
menuItemForDuplicate.DataContext(proxyGroupModel);
456+
menuItemForDuplicate.Click({get_weak(), &LibraryPage::ProxyGroupItemDuplicate_Click});
457+
ProxyGroupProxyDuplicateFlyout().Items().Append(menuItemForDuplicate);
458+
}
459+
}
460+
432461
void LibraryPage::ProxyGroupItem_Click(IInspectable const &sender, RoutedEventArgs const &)
433462
{
434463
auto const source = sender.as<FrameworkElement>();
@@ -641,8 +670,8 @@ namespace winrt::YtFlowApp::implementation
641670
}
642671
}
643672

644-
fire_and_forget LibraryPage::ProxyGroupUnlockProxyButton_Click(Windows::Foundation::IInspectable const &sender,
645-
Windows::UI::Xaml::RoutedEventArgs const &e)
673+
fire_and_forget LibraryPage::ProxyGroupUnlockButton_Click(Windows::Foundation::IInspectable const &sender,
674+
Windows::UI::Xaml::RoutedEventArgs const &e)
646675
{
647676
auto const lifetime = get_strong();
648677
if (std::exchange(isDialogsShown, true))
@@ -699,6 +728,76 @@ namespace winrt::YtFlowApp::implementation
699728
}
700729
EditProxyInCurrentProxyGroup(proxy);
701730
}
731+
fire_and_forget LibraryPage::ProxyGroupItemDuplicate_Click(Windows::Foundation::IInspectable const &sender,
732+
Windows::UI::Xaml::RoutedEventArgs const &)
733+
{
734+
try
735+
{
736+
auto const lifetime = get_strong();
737+
738+
auto const targetGroup = sender.as<FrameworkElement>().DataContext().try_as<ProxyGroupModel>();
739+
if (targetGroup == nullptr)
740+
{
741+
co_return;
742+
}
743+
auto const targetGroupId = targetGroup->Id();
744+
auto const allProxies = ProxyGroupProxyList().Items();
745+
using std::ranges::sort;
746+
using std::ranges::to;
747+
using std::ranges::views::filter;
748+
using std::ranges::views::transform;
749+
auto items = ProxyGroupProxyList().SelectedItems() | to<std::vector>();
750+
sort(items, [&allProxies](auto const &lhs, auto const &rhs) {
751+
uint32_t lhsIndex{}, rhsIndex{};
752+
allProxies.IndexOf(lhs, lhsIndex);
753+
allProxies.IndexOf(rhs, rhsIndex);
754+
return lhsIndex < rhsIndex;
755+
});
756+
auto newProxies =
757+
items | transform([](auto const &item) { return item.try_as<ProxyModel>(); }) |
758+
filter([](auto const &item) { return static_cast<bool>(item); }) | transform([](auto const &proxy) {
759+
return FfiDataProxy{
760+
.id = INVALID_DB_ID, .name = to_string(proxy->Name()), .proxy = proxy->ProxyRaw()};
761+
}) |
762+
to<std::vector>();
763+
764+
co_await resume_background();
765+
auto conn = FfiDbInstance.Connect();
766+
for (auto &proxy : newProxies)
767+
{
768+
try
769+
{
770+
proxy.id =
771+
conn.CreateProxy(targetGroupId, proxy.name.c_str(), proxy.proxy.data(), proxy.proxy.size(), 0);
772+
// TODO: order_num
773+
}
774+
catch (...)
775+
{
776+
NotifyException(L"Duplicating a proxy");
777+
}
778+
}
779+
780+
co_await resume_foreground(lifetime->Dispatcher());
781+
size_t newProxyModelSize{};
782+
auto const targetGroupProxies = targetGroup->Proxies();
783+
for (auto &&newProxyModel : newProxies | filter([](auto const &proxy) {
784+
return proxy.id != INVALID_DB_ID;
785+
}) | transform([](auto const &proxy) { return make<ProxyModel>(proxy); }))
786+
{
787+
if (targetGroupProxies)
788+
{
789+
targetGroupProxies.Append(std::move(newProxyModel));
790+
}
791+
newProxyModelSize++;
792+
}
793+
NotifyUser(L"Duplicated " + to_hstring(newProxyModelSize) + L" proxies to " + targetGroup->Name(),
794+
L"Duplicate Proxies");
795+
}
796+
catch (...)
797+
{
798+
NotifyException(L"Duplicating proxies");
799+
}
800+
}
702801
uint32_t LibraryPage::ProxyGroupProxySelectedCount()
703802
{
704803
return ProxyGroupProxyList().SelectedItems().Size();

YtFlowApp/LibraryPage.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,14 @@ namespace winrt::YtFlowApp::implementation
5656
Windows::UI::Xaml::RoutedEventArgs const &e);
5757
fire_and_forget ProxyGroupNewProxyButton_Click(winrt::Windows::Foundation::IInspectable const &sender,
5858
winrt::Windows::UI::Xaml::RoutedEventArgs const &e);
59-
fire_and_forget ProxyGroupUnlockProxyButton_Click(Windows::Foundation::IInspectable const &sender,
59+
fire_and_forget ProxyGroupUnlockButton_Click(Windows::Foundation::IInspectable const &sender,
6060
Windows::UI::Xaml::RoutedEventArgs const &e);
6161
void ProxyGroupShareProxyButton_Click(Windows::Foundation::IInspectable const &sender,
6262
Windows::UI::Xaml::RoutedEventArgs const &e);
6363
void ProxyGroupEditProxyButton_Click(Windows::Foundation::IInspectable const &sender,
6464
Windows::UI::Xaml::RoutedEventArgs const &e);
65+
fire_and_forget ProxyGroupItemDuplicate_Click(Windows::Foundation::IInspectable const &sender,
66+
Windows::UI::Xaml::RoutedEventArgs const &e);
6567
uint32_t ProxyGroupProxySelectedCount();
6668
bool IsProxyGroupLocked() const;
6769

@@ -81,6 +83,7 @@ namespace winrt::YtFlowApp::implementation
8183
fire_and_forget LoadProxiesForProxyGroup(ProxyGroupModel const &model);
8284
fire_and_forget UpdateSubscription(std::optional<uint32_t> id);
8385
void EditProxyInCurrentProxyGroup(com_ptr<ProxyModel> proxyModel) const;
86+
void PopulateProxyGroupItemsForMenu();
8487

8588
com_ptr<AssetModel> m_model = make_self<AssetModel>();
8689
bool isDialogsShown{false};

YtFlowApp/LibraryPage.xaml

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,19 @@
219219
<RowDefinition Height="*" />
220220
</Grid.RowDefinitions>
221221

222-
<CommandBar Grid.Row="0" DefaultLabelPosition="Right" IsSticky="True" VerticalContentAlignment="Center">
222+
<CommandBar
223+
Grid.Row="0"
224+
DefaultLabelPosition="Right"
225+
VerticalContentAlignment="Center"
226+
>
227+
<CommandBar.Resources>
228+
<MenuFlyout
229+
x:Name="ProxyGroupProxyDuplicateFlyout"
230+
Placement="Left"
231+
contract7Present:ShowMode="TransientWithDismissOnPointerMoveAway"
232+
>
233+
</MenuFlyout>
234+
</CommandBar.Resources>
223235
<CommandBar.PrimaryCommands>
224236
<AppBarButton
225237
x:Name="ProxyGroupEditProxyButton"
@@ -259,11 +271,19 @@
259271
<contract7Present:FontIcon Glyph="&#xECC8;" />
260272
</contract7Present:AppBarButton.Icon>
261273
</AppBarButton>
274+
<AppBarButton
275+
Label="Duplicate"
276+
IsEnabled="{x:Bind local:LibraryPage.IsProxyGroupProxyShareEnabled(ProxyGroupProxySelectedCount), Mode=OneWay}"
277+
FlyoutBase.AttachedFlyout="{StaticResource ProxyGroupProxyDuplicateFlyout}"
278+
Flyout="{StaticResource ProxyGroupProxyDuplicateFlyout}"
279+
contract7Present:Icon="Copy"
280+
>
281+
</AppBarButton>
262282
<AppBarButton
263283
Label="Unlock"
264284
Visibility="{x:Bind local:BoolToObjectConverter.ToVisibility(Model.CurrentProxyGroupModel.IsSubscription), Mode=OneWay}"
265285
IsEnabled="{x:Bind IsProxyGroupLocked, Mode=OneWay}"
266-
Click="ProxyGroupUnlockProxyButton_Click"
286+
Click="ProxyGroupUnlockButton_Click"
267287
>
268288
<contract7Present:AppBarButton.Icon>
269289
<contract7Present:FontIcon Glyph="&#xE785;" />

YtFlowApp/ProxyModel.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ namespace winrt::YtFlowApp::implementation
3232
{
3333
return com_array(m_proxy);
3434
}
35+
std::vector<uint8_t> ProxyModel::ProxyRaw() const
36+
{
37+
return m_proxy;
38+
}
3539
void ProxyModel::Proxy(array_view<uint8_t const> value)
3640
{
3741
m_proxy = std::vector(value.begin(), value.end());

YtFlowApp/ProxyModel.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ namespace winrt::YtFlowApp::implementation
1919
hstring Name() const;
2020
void Name(hstring const &value);
2121
com_array<uint8_t> Proxy() const;
22+
std::vector<uint8_t> ProxyRaw() const;
2223
void Proxy(array_view<uint8_t const> value);
2324
uint16_t ProxyVersion() const;
2425
void ProxyVersion(uint16_t value);
@@ -31,10 +32,10 @@ namespace winrt::YtFlowApp::implementation
3132
void Update() const;
3233

3334
private:
34-
uint32_t m_id;
35+
uint32_t m_id{};
3536
hstring m_name;
3637
std::vector<uint8_t> m_proxy;
37-
uint16_t m_proxyVersion;
38+
uint16_t m_proxyVersion{};
3839
mutable std::optional<FfiProxy> m_analyzedProxy;
3940
event<Windows::UI::Xaml::Data::PropertyChangedEventHandler> m_propertyChanged;
4041
};

0 commit comments

Comments
 (0)