From 3b0ff7b931746035ae27ca762dc58500faf8dc2b Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Wed, 17 Jun 2020 13:29:12 +0200 Subject: [PATCH 01/45] Added GetFileAsync method to ProtoService --- Unigram/Unigram/Services/ProtoService.cs | 29 ++++++++++++++--- .../ViewModels/DialogViewModel.Delegate.cs | 12 ++----- .../ViewModels/DialogViewModel.Media.cs | 2 +- .../ViewModels/DialogViewModel.Messages.cs | 32 ++++++++++++------- .../Gallery/GalleryViewModelBase.cs | 14 ++++---- 5 files changed, 58 insertions(+), 31 deletions(-) diff --git a/Unigram/Unigram/Services/ProtoService.cs b/Unigram/Unigram/Services/ProtoService.cs index ff309f3146..6bcb3f1da6 100644 --- a/Unigram/Unigram/Services/ProtoService.cs +++ b/Unigram/Unigram/Services/ProtoService.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -24,6 +23,8 @@ public interface IProtoService : ICacheService void Send(Function function, Action handler = null); Task SendAsync(Function function); + Task GetFileAsync(File file); + void DownloadFile(int fileId, int priority, int offset = 0, int limit = 0, bool synchronous = false); void CancelDownloadFile(int fileId, bool onlyIfPending = false); bool IsDownloadFileCanceled(int fileId); @@ -195,7 +196,7 @@ private void Initialize(bool online = true) var parameters = new TdlibParameters { - DatabaseDirectory = Path.Combine(ApplicationData.Current.LocalFolder.Path, $"{_session}"), + DatabaseDirectory = System.IO.Path.Combine(ApplicationData.Current.LocalFolder.Path, $"{_session}"), UseSecretChats = true, UseMessageDatabase = true, ApiId = Constants.ApiId, @@ -311,7 +312,7 @@ int TuesdayDate() { InitializeDiagnostics(); - _client.Send(new SetOption("language_pack_database_path", new OptionValueString(Path.Combine(ApplicationData.Current.LocalFolder.Path, "langpack")))); + _client.Send(new SetOption("language_pack_database_path", new OptionValueString(System.IO.Path.Combine(ApplicationData.Current.LocalFolder.Path, "langpack")))); _client.Send(new SetOption("localization_target", new OptionValueString("android"))); _client.Send(new SetOption("language_pack_id", new OptionValueString(SettingsService.Current.LanguagePackId))); //_client.Send(new SetOption("online", new OptionValueBoolean(online))); @@ -326,7 +327,7 @@ int TuesdayDate() private void InitializeDiagnostics() { - Client.Execute(new SetLogStream(new LogStreamFile(Path.Combine(ApplicationData.Current.LocalFolder.Path, "tdlib_log.txt"), 100 * 1024 * 1024))); + Client.Execute(new SetLogStream(new LogStreamFile(System.IO.Path.Combine(ApplicationData.Current.LocalFolder.Path, "tdlib_log.txt"), 100 * 1024 * 1024))); Client.Execute(new SetLogVerbosityLevel(SettingsService.Current.VerbosityLevel)); var tags = Client.Execute(new GetLogTags()) as LogTags; @@ -472,6 +473,26 @@ public Task SendAsync(Function function) private ConcurrentBag _canceledDownloads = new ConcurrentBag(); + public async Task GetFileAsync(File file) + { + if (file.Local.IsDownloadingCompleted) + { + var path = System.IO.Path.GetRelativePath(ApplicationData.Current.LocalFolder.Path, file.Local.Path); + + var item = await ApplicationData.Current.LocalFolder.TryGetItemAsync(path) as StorageFile; + if (item != null) + { + return item; + } + else + { + Send(new DeleteFileW(file.Id)); + } + } + + return null; + } + public void DownloadFile(int fileId, int priority, int offset = 0, int limit = 0, bool synchronous = false) { _client.Send(new DownloadFile(fileId, priority, offset, limit, synchronous)); diff --git a/Unigram/Unigram/ViewModels/DialogViewModel.Delegate.cs b/Unigram/Unigram/ViewModels/DialogViewModel.Delegate.cs index 9c183f8afa..6977131c06 100644 --- a/Unigram/Unigram/ViewModels/DialogViewModel.Delegate.cs +++ b/Unigram/Unigram/ViewModels/DialogViewModel.Delegate.cs @@ -241,17 +241,11 @@ public async void OpenFile(File file) return; } - try + var temp = await ProtoService.GetFileAsync(file); + if (temp != null) { - var temp = await StorageFile.GetFileFromPathAsync(file.Local.Path); - var result = await Windows.System.Launcher.LaunchFileAsync(temp); - //var folder = await temp.GetParentAsync(); - //var options = new Windows.System.FolderLauncherOptions(); - //options.ItemsToSelect.Add(temp); - - //var result = await Windows.System.Launcher.LaunchFolderAsync(folder, options); + await Windows.System.Launcher.LaunchFileAsync(temp); } - catch { } } } diff --git a/Unigram/Unigram/ViewModels/DialogViewModel.Media.cs b/Unigram/Unigram/ViewModels/DialogViewModel.Media.cs index 4c4c705f92..1257bc5983 100644 --- a/Unigram/Unigram/ViewModels/DialogViewModel.Media.cs +++ b/Unigram/Unigram/ViewModels/DialogViewModel.Media.cs @@ -956,7 +956,7 @@ private async void EditCurrentExecute() return; } - var file = await StorageFile.GetFileFromPathAsync(fileInfo.File.Local.Path); + var file = await ProtoService.GetFileAsync(fileInfo.File); if (file == null) { return; diff --git a/Unigram/Unigram/ViewModels/DialogViewModel.Messages.cs b/Unigram/Unigram/ViewModels/DialogViewModel.Messages.cs index 722ed67af7..01b163c54a 100644 --- a/Unigram/Unigram/ViewModels/DialogViewModel.Messages.cs +++ b/Unigram/Unigram/ViewModels/DialogViewModel.Messages.cs @@ -1252,6 +1252,12 @@ private async void MessageSaveMediaExecute(MessageViewModel message) return; } + var cached = await ProtoService.GetFileAsync(file); + if (cached == null) + { + return; + } + var fileName = result.FileName; if (string.IsNullOrEmpty(fileName)) { @@ -1280,7 +1286,6 @@ private async void MessageSaveMediaExecute(MessageViewModel message) { try { - var cached = await StorageFile.GetFileFromPathAsync(file.Local.Path); await cached.CopyAndReplaceAsync(picked); } catch { } @@ -1363,12 +1368,14 @@ private async void MessageOpenWithExecute(MessageViewModel message) return; } - var item = await StorageFile.GetFileFromPathAsync(file.Local.Path); - - var options = new LauncherOptions(); - options.DisplayApplicationPicker = true; + var item = await ProtoService.GetFileAsync(file); + if (item != null) + { + var options = new LauncherOptions(); + options.DisplayApplicationPicker = true; - await Launcher.LaunchFileAsync(item, options); + await Launcher.LaunchFileAsync(item, options); + } } #endregion @@ -1386,13 +1393,16 @@ private async void MessageOpenFolderExecute(MessageViewModel message) return; } - var item = await StorageFile.GetFileFromPathAsync(file.Local.Path); - var folder = await item.GetParentAsync(); + var item = await ProtoService.GetFileAsync(file); + if (item != null) + { + var folder = await item.GetParentAsync(); - var options = new FolderLauncherOptions(); - options.ItemsToSelect.Add(item); + var options = new FolderLauncherOptions(); + options.ItemsToSelect.Add(item); - await Launcher.LaunchFolderAsync(folder, options); + await Launcher.LaunchFolderAsync(folder, options); + } } #endregion diff --git a/Unigram/Unigram/ViewModels/Gallery/GalleryViewModelBase.cs b/Unigram/Unigram/ViewModels/Gallery/GalleryViewModelBase.cs index 33688d4aa6..ff567d7143 100644 --- a/Unigram/Unigram/ViewModels/Gallery/GalleryViewModelBase.cs +++ b/Unigram/Unigram/ViewModels/Gallery/GalleryViewModelBase.cs @@ -260,6 +260,12 @@ protected virtual async void SaveExecute() return; } + var cached = await ProtoService.GetFileAsync(file); + if (cached == null) + { + return; + } + var fileName = result.FileName; if (string.IsNullOrEmpty(fileName)) { @@ -282,7 +288,6 @@ protected virtual async void SaveExecute() { try { - var cached = await StorageFile.GetFileFromPathAsync(file.Local.Path); await cached.CopyAndReplaceAsync(picked); } catch { } @@ -301,17 +306,14 @@ protected virtual async void OpenWithExecute() var file = item.GetFile(); if (file != null && file.Local.IsDownloadingCompleted) { - try + var temp = await ProtoService.GetFileAsync(file); + if (temp != null) { - var temp = await StorageFile.GetFileFromPathAsync(file.Local.Path); - var options = new LauncherOptions(); options.DisplayApplicationPicker = true; await Launcher.LaunchFileAsync(temp, options); - } - catch { } } } From 3aa1cf992630dbc5d393d3529184b0b85f6f0d54 Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Wed, 17 Jun 2020 13:29:28 +0200 Subject: [PATCH 02/45] Privacy & security bug fixes --- .../Privacy/SettingsPrivacyViewModelBase.cs | 2 +- .../Password/SettingsPasswordCreatePage.xaml | 111 +++++++++++++++++- .../SettingsPasswordCreatePage.xaml.cs | 1 - .../Password/SettingsPasswordEmailPage.xaml | 10 +- .../Password/SettingsPasswordHintPage.xaml | 10 +- .../SettingsPrivacyAndSecurityPage.xaml | 53 ++++----- 6 files changed, 144 insertions(+), 43 deletions(-) diff --git a/Unigram/Unigram/ViewModels/Settings/Privacy/SettingsPrivacyViewModelBase.cs b/Unigram/Unigram/ViewModels/Settings/Privacy/SettingsPrivacyViewModelBase.cs index f13e52f36a..bab48e0cb7 100644 --- a/Unigram/Unigram/ViewModels/Settings/Privacy/SettingsPrivacyViewModelBase.cs +++ b/Unigram/Unigram/ViewModels/Settings/Privacy/SettingsPrivacyViewModelBase.cs @@ -30,7 +30,7 @@ public SettingsPrivacyViewModelBase(IProtoService protoService, ICacheService ca public override Task OnNavigatedToAsync(object parameter, NavigationMode mode, IDictionary state) { - if (mode != NavigationMode.Back) + //if (mode != NavigationMode.Back) { UpdatePrivacyAsync(); } diff --git a/Unigram/Unigram/Views/Settings/Password/SettingsPasswordCreatePage.xaml b/Unigram/Unigram/Views/Settings/Password/SettingsPasswordCreatePage.xaml index 1d4bfb3158..ec25b54ee1 100644 --- a/Unigram/Unigram/Views/Settings/Password/SettingsPasswordCreatePage.xaml +++ b/Unigram/Unigram/Views/Settings/Password/SettingsPasswordCreatePage.xaml @@ -14,6 +14,102 @@ + + @@ -21,8 +117,8 @@ x:Name="Walkthrough" Loaded="Walkthrough_Loaded" HeaderSource="ms-appx:///Assets/Animations/TwoFactorSetupMonkeyClose.tgs" - Title="[Create Password]" - ButtonText="[Create Password]" + Title="{CustomResource PleaseEnterFirstPassword}" + ButtonText="{CustomResource Continue}" ButtonCommand="{x:Bind ViewModel.SendCommand}"> @@ -45,8 +141,15 @@ - + Grid.Column="1" + Style="{StaticResource RevealButtonStyle}" + BorderThickness="{ThemeResource TextControlBorderThemeThickness}" + Padding="{ThemeResource HelperButtonThemePadding}" + IsTabStop="False" + FontSize="{ThemeResource ControlContentThemeFontSize}" + VerticalAlignment="Stretch" + MinWidth="34" /> + " : "<(/)>"; Field1.PasswordRevealMode = Reveal.IsChecked == true ? PasswordRevealMode.Visible : PasswordRevealMode.Hidden; Field2.PasswordRevealMode = Reveal.IsChecked == true ? PasswordRevealMode.Visible : PasswordRevealMode.Hidden; diff --git a/Unigram/Unigram/Views/Settings/Password/SettingsPasswordEmailPage.xaml b/Unigram/Unigram/Views/Settings/Password/SettingsPasswordEmailPage.xaml index cbed295395..4d7ff5b755 100644 --- a/Unigram/Unigram/Views/Settings/Password/SettingsPasswordEmailPage.xaml +++ b/Unigram/Unigram/Views/Settings/Password/SettingsPasswordEmailPage.xaml @@ -21,16 +21,16 @@ x:Name="Walkthrough" Loaded="Walkthrough_Loaded" HeaderSource="ms-appx:///Assets/Animations/TwoFactorSetupMonkeyTracking.tgs" - Title="[Recovery Email]" - Text="[You can set a recovery email to be able to reset your password and restore access to your Telegram account.]" - ButtonText="[Continue]" + Title="{CustomResource RecoveryEmailTitle}" + Text="{CustomResource YourEmailInfo}" + ButtonText="{CustomResource Continue}" ButtonCommand="{x:Bind ViewModel.SendCommand}" ButtonVisibility="{x:Bind ViewModel.Address, Mode=OneWay, Converter={StaticResource NullToVisibilityConverter}}"> @@ -39,7 +39,7 @@ x:Name="Field1" Text="{x:Bind ViewModel.Address, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectionChanged="Field_SelectionChanged" - PlaceholderText="[Your email address]"/> + PlaceholderText="{CustomResource RecoveryEmail}"/> diff --git a/Unigram/Unigram/Views/Settings/Password/SettingsPasswordHintPage.xaml b/Unigram/Unigram/Views/Settings/Password/SettingsPasswordHintPage.xaml index 709480822e..851c4f8272 100644 --- a/Unigram/Unigram/Views/Settings/Password/SettingsPasswordHintPage.xaml +++ b/Unigram/Unigram/Views/Settings/Password/SettingsPasswordHintPage.xaml @@ -11,23 +11,23 @@ + PlaceholderText="{CustomResource PasswordHintPlaceholder}"/> diff --git a/Unigram/Unigram/Views/Settings/SettingsPrivacyAndSecurityPage.xaml b/Unigram/Unigram/Views/Settings/SettingsPrivacyAndSecurityPage.xaml index a746bbc32a..a1937a7a22 100644 --- a/Unigram/Unigram/Views/Settings/SettingsPrivacyAndSecurityPage.xaml +++ b/Unigram/Unigram/Views/Settings/SettingsPrivacyAndSecurityPage.xaml @@ -18,36 +18,13 @@ VerticalScrollBarVisibility="Auto" VerticalScrollMode="Auto"> - - - - - - - + + + + + + + From 22895d36d120148f82930177b3efe790cb4d98ee Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Wed, 17 Jun 2020 13:51:58 +0200 Subject: [PATCH 03/45] Update chat bindings on activate --- Unigram/Unigram/Services/Navigation/NavigationService.cs | 4 +++- Unigram/Unigram/Views/ChatView.xaml.cs | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Unigram/Unigram/Services/Navigation/NavigationService.cs b/Unigram/Unigram/Services/Navigation/NavigationService.cs index 25b48e570a..868e4c42f0 100644 --- a/Unigram/Unigram/Services/Navigation/NavigationService.cs +++ b/Unigram/Unigram/Services/Navigation/NavigationService.cs @@ -163,8 +163,10 @@ async Task NavigateToAsync(NavigationMode mode, object parameter, object frameCo var page = frameContent as Page; if (page != null) { + var cleaned = false; if (page is IActivablePage cleanup) { + cleaned = true; cleanup.Activate(); } @@ -186,7 +188,7 @@ async Task NavigateToAsync(NavigationMode mode, object parameter, object frameCo // update bindings after NavTo initializes data //XamlUtils.InitializeBindings(page); - if (page.Content is UserControl pageWith) + if (page.Content is UserControl pageWith && !cleaned) { XamlUtils.UpdateBindings(pageWith); } diff --git a/Unigram/Unigram/Views/ChatView.xaml.cs b/Unigram/Unigram/Views/ChatView.xaml.cs index 5245dfe246..7a6431ed8e 100644 --- a/Unigram/Unigram/Views/ChatView.xaml.cs +++ b/Unigram/Unigram/Views/ChatView.xaml.cs @@ -507,6 +507,7 @@ public void Dispose() public void Activate() { DataContext = _getViewModel(this); + Bindings.Update(); ViewModel.TextField = TextField; ViewModel.ListField = Messages; From 140b753da310082d3d6af8afe71a907a1723fd0a Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Wed, 17 Jun 2020 18:23:02 +0200 Subject: [PATCH 04/45] Rewritten SVG rendering algorithm --- .../Unigram.Native/PlaceholderImageHelper.cpp | 176 ++++++------------ .../Unigram/ViewModels/BackgroundViewModel.cs | 33 +++- Unigram/Unigram/Views/BackgroundPage.xaml.cs | 9 +- 3 files changed, 100 insertions(+), 118 deletions(-) diff --git a/Unigram/Unigram.Native/PlaceholderImageHelper.cpp b/Unigram/Unigram.Native/PlaceholderImageHelper.cpp index 900fdc8b49..75ee3c7213 100644 --- a/Unigram/Unigram.Native/PlaceholderImageHelper.cpp +++ b/Unigram/Unigram.Native/PlaceholderImageHelper.cpp @@ -164,140 +164,88 @@ HRESULT PlaceholderImageHelper::InternalDrawSvg(String^ path, _In_ Color foregro ReturnIfFailed(result, m_d2dContext->CreateSolidColorBrush( D2D1::ColorF(foreground.R / 255.0f, foreground.G / 255.0f, foreground.B / 255.0f, foreground.A / 255.0f), &blackBrush)); - for (auto shape = image->shapes; shape != NULL; shape = shape->next) { - if (!(shape->flags & NSVG_FLAGS_VISIBLE)) { + for (auto shape = image->shapes; shape != NULL; shape = shape->next) + { + if (!(shape->flags & NSVG_FLAGS_VISIBLE) || (shape->fill.type == NSVG_PAINT_NONE && shape->stroke.type == NSVG_PAINT_NONE)) + { continue; } - if (shape->fill.type != NSVG_PAINT_NONE) { - - ComPtr geometry; - ReturnIfFailed(result, m_d2dFactory->CreatePathGeometry(&geometry)); - - ComPtr sink; - ReturnIfFailed(result, geometry->Open(&sink)); - ////CGContextSetFillColorWithColor(context, UIColorRGBA(shape->fill.color, shape->opacity).CGColor); - //CGContextSetFillColorWithColor(context, [foregroundColor colorWithAlphaComponent : shape->opacity].CGColor); - - bool isFirst = true; - bool hasStartPoint = false; - D2D1_POINT_2F startPoint; - for (NSVGpath* path = shape->paths; path != NULL; path = path->next) { - if (isFirst) { - //CGContextBeginPath(context); - sink->BeginFigure(D2D1::Point2F(path->pts[0], path->pts[1]), D2D1_FIGURE_BEGIN_FILLED); - isFirst = false; - hasStartPoint = true; - startPoint.x = path->pts[0]; - startPoint.y = path->pts[1]; - } - //CGContextMoveToPoint(context, path->pts[0], path->pts[1]); - else { - sink->AddLine(D2D1::Point2F(path->pts[0], path->pts[1])); - } - for (int i = 0; i < path->npts - 1; i += 3) { - float* p = &path->pts[i * 2]; - //CGContextAddCurveToPoint(context, p[2], p[3], p[4], p[5], p[6], p[7]); - sink->AddBezier(D2D1::BezierSegment(D2D1::Point2F(p[2], p[3]), D2D1::Point2F(p[4], p[5]), D2D1::Point2F(p[6], p[7]))); - } + blackBrush->SetOpacity(shape->opacity); - if (path->closed) { - if (hasStartPoint) { - hasStartPoint = false; - //CGContextAddLineToPoint(context, startPoint.x, startPoint.y); - sink->AddLine(startPoint); - } - } + ComPtr geometry; + ReturnIfFailed(result, m_d2dFactory->CreatePathGeometry(&geometry)); - if (path->next != NULL) { - int a = 1 + 2; - } - } - sink->EndFigure(D2D1_FIGURE_END_OPEN); - switch (shape->fillRule) { - case NSVG_FILLRULE_EVENODD: - //CGContextEOFillPath(context); - sink->SetFillMode(D2D1_FILL_MODE_ALTERNATE); - break; - default: - //CGContextFillPath(context); - sink->SetFillMode(D2D1_FILL_MODE_WINDING); - break; - } + ComPtr sink; + ReturnIfFailed(result, geometry->Open(&sink)); - ReturnIfFailed(result, sink->Close()); - m_d2dContext->FillGeometry(geometry.Get(), m_black.Get()); - } + for (NSVGpath* path = shape->paths; path != NULL; path = path->next) + { + sink->BeginFigure({ path->pts[0], path->pts[1] }, D2D1_FIGURE_BEGIN_FILLED); - if (shape->stroke.type != NSVG_PAINT_NONE) { - ComPtr geometry; - ReturnIfFailed(result, m_d2dFactory->CreatePathGeometry(&geometry)); + for (int i = 0; i < path->npts - 1; i += 3) + { + float* p = &path->pts[i * 2]; + sink->AddBezier({ { p[2], p[3] }, { p[4], p[5] }, { p[6], p[7] }}); + } - ComPtr sink; - ReturnIfFailed(result, geometry->Open(&sink)); + sink->EndFigure(path->closed ? D2D1_FIGURE_END_CLOSED : D2D1_FIGURE_END_OPEN); + } - ////CGContextSetStrokeColorWithColor(context, UIColorRGBA(shape->fill.color, shape->opacity).CGColor); - //CGContextSetStrokeColorWithColor(context, [foregroundColor colorWithAlphaComponent : shape->opacity].CGColor); - //CGContextSetMiterLimit(context, shape->miterLimit); + if (shape->fill.type != NSVG_PAINT_NONE) + { + switch (shape->fillRule) + { + case NSVG_FILLRULE_EVENODD: + sink->SetFillMode(D2D1_FILL_MODE_ALTERNATE); + break; + default: + sink->SetFillMode(D2D1_FILL_MODE_WINDING); + break; + } + ReturnIfFailed(result, sink->Close()); + m_d2dContext->FillGeometry(geometry.Get(), blackBrush.Get()); + } + if (shape->stroke.type != NSVG_PAINT_NONE) + { D2D1_STROKE_STYLE_PROPERTIES1 strokeProperties{}; strokeProperties.miterLimit = shape->miterLimit; - //CGContextSetLineWidth(context, shape->strokeWidth); - switch (shape->strokeLineCap) { - case NSVG_CAP_BUTT: - //CGContextSetLineCap(context, kCGLineCapButt); - strokeProperties.startCap = strokeProperties.endCap = D2D1_CAP_STYLE_FLAT; - break; - case NSVG_CAP_ROUND: - //CGContextSetLineCap(context, kCGLineCapRound); - strokeProperties.startCap = strokeProperties.endCap = D2D1_CAP_STYLE_ROUND; - break; - case NSVG_CAP_SQUARE: - //CGContextSetLineCap(context, kCGLineCapSquare); - strokeProperties.startCap = strokeProperties.endCap = D2D1_CAP_STYLE_SQUARE; - break; - default: - break; + switch (shape->strokeLineCap) + { + case NSVG_CAP_BUTT: + strokeProperties.startCap = strokeProperties.endCap = D2D1_CAP_STYLE_FLAT; + break; + case NSVG_CAP_ROUND: + strokeProperties.startCap = strokeProperties.endCap = D2D1_CAP_STYLE_ROUND; + break; + case NSVG_CAP_SQUARE: + strokeProperties.startCap = strokeProperties.endCap = D2D1_CAP_STYLE_SQUARE; + break; + default: + break; } - switch (shape->strokeLineJoin) { - case NSVG_JOIN_BEVEL: - //CGContextSetLineJoin(context, kCGLineJoinBevel); - strokeProperties.lineJoin = D2D1_LINE_JOIN_BEVEL; - break; - case NSVG_JOIN_MITER: - //CGContextSetLineCap(context, kCGLineJoinMiter); - strokeProperties.lineJoin = D2D1_LINE_JOIN_MITER; - break; - case NSVG_JOIN_ROUND: - //CGContextSetLineCap(context, kCGLineJoinRound); - strokeProperties.lineJoin = D2D1_LINE_JOIN_ROUND; - break; - default: - break; + + switch (shape->strokeLineJoin) + { + case NSVG_JOIN_BEVEL: + strokeProperties.lineJoin = D2D1_LINE_JOIN_BEVEL; + break; + case NSVG_JOIN_MITER: + strokeProperties.lineJoin = D2D1_LINE_JOIN_MITER; + break; + case NSVG_JOIN_ROUND: + strokeProperties.lineJoin = D2D1_LINE_JOIN_ROUND; + break; + default: + break; } ComPtr strokeStyle; ReturnIfFailed(result, m_d2dFactory->CreateStrokeStyle(strokeProperties, NULL, 0, &strokeStyle)); - for (NSVGpath* path = shape->paths; path != NULL; path = path->next) { - //CGContextBeginPath(context); - //CGContextMoveToPoint(context, path->pts[0], path->pts[1]); - sink->BeginFigure(D2D1::Point2F(path->pts[0], path->pts[1]), D2D1_FIGURE_BEGIN_HOLLOW); - for (int i = 0; i < path->npts - 1; i += 3) { - float* p = &path->pts[i * 2]; - //CGContextAddCurveToPoint(context, p[2], p[3], p[4], p[5], p[6], p[7]); - sink->AddBezier(D2D1::BezierSegment(D2D1::Point2F(p[2], p[3]), D2D1::Point2F(p[4], p[5]), D2D1::Point2F(p[6], p[7]))); - } - - //if (path->closed) { - // CGContextClosePath(context); - //} - sink->EndFigure(path->closed ? D2D1_FIGURE_END_CLOSED : D2D1_FIGURE_END_OPEN); - - //CGContextStrokePath(context); - } ReturnIfFailed(result, sink->Close()); m_d2dContext->DrawGeometry(geometry.Get(), blackBrush.Get(), shape->strokeWidth); diff --git a/Unigram/Unigram/ViewModels/BackgroundViewModel.cs b/Unigram/Unigram/ViewModels/BackgroundViewModel.cs index 66bbc217b2..f12e15cc76 100644 --- a/Unigram/Unigram/ViewModels/BackgroundViewModel.cs +++ b/Unigram/Unigram/ViewModels/BackgroundViewModel.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.CompilerServices; using System.Threading.Tasks; using Telegram.Td.Api; using Unigram.Collections; @@ -165,14 +166,24 @@ public bool IsMotionEnabled public BackgroundColor Color1 { get => _color1; - set => Set(ref _color1, value); + set => SetColor(ref _color1, value); } private BackgroundColor _color2; public BackgroundColor Color2 { get => _color2; - set => Set(ref _color2, value); + set => SetColor(ref _color2, value); + } + + private void SetColor(ref BackgroundColor storage, BackgroundColor value, [CallerMemberName] string propertyName = null) + { + Set(ref storage, value, propertyName); + + if (_item?.Type is BackgroundTypePattern) + { + //RaisePropertyChanged(() => Item); + } } public BackgroundFill GetFill() @@ -193,6 +204,24 @@ public BackgroundFill GetFill() return null; } + public Color GetPatternForeground() + { + if (!_color1.IsEmpty && !_color2.IsEmpty) + { + return ColorEx.GetPatternColor(ColorEx.GetAverageColor(_color1, _color2)); + } + else if (!_color1.IsEmpty) + { + return ColorEx.GetPatternColor(_color1); + } + else if (!_color2.IsEmpty) + { + return ColorEx.GetPatternColor(_color2); + } + + return Color.FromArgb(0x66, 0xFF, 0xFF, 0xFF); + } + private bool _isColor1Checked = true; public bool IsColor1Checked { diff --git a/Unigram/Unigram/Views/BackgroundPage.xaml.cs b/Unigram/Unigram/Views/BackgroundPage.xaml.cs index ed5b99aecb..56a7e417ac 100644 --- a/Unigram/Unigram/Views/BackgroundPage.xaml.cs +++ b/Unigram/Unigram/Views/BackgroundPage.xaml.cs @@ -205,7 +205,7 @@ private async void Image_DataContextChanged(FrameworkElement sender, DataContext //rectangle.Opacity = pattern.Intensity / 100d if (string.Equals(wallpaper.Document.MimeType, "application/x-tgwallpattern", StringComparison.OrdinalIgnoreCase)) { - rectangle.Fill = new TiledBrush { SvgSource = PlaceholderHelper.GetVectorSurface(ViewModel.ProtoService, big.DocumentValue, pattern.GetForeground()) }; + rectangle.Fill = new TiledBrush { SvgSource = PlaceholderHelper.GetVectorSurface(ViewModel.ProtoService, big.DocumentValue, ViewModel.GetPatternForeground()) }; } else { @@ -278,6 +278,11 @@ public async void UpdateBackground(Background wallpaper) #region Binding + private Background ConvertForeground(BackgroundColor color1, BackgroundColor color2, Background wallpaper) + { + return wallpaper; + } + private Brush ConvertBackground(BackgroundColor color1, BackgroundColor color2, int rotation) { var panel = PatternList.ItemsPanelRoot as ItemsStackPanel; @@ -378,7 +383,7 @@ public void Handle(UpdateFile update) //rectangle.Opacity = pattern.Intensity / 100d; if (string.Equals(wallpaper.Document.MimeType, "application/x-tgwallpattern", StringComparison.OrdinalIgnoreCase)) { - rectangle.Fill = new TiledBrush { SvgSource = PlaceholderHelper.GetVectorSurface(ViewModel.ProtoService, big.DocumentValue, pattern.GetForeground()) }; + rectangle.Fill = new TiledBrush { SvgSource = PlaceholderHelper.GetVectorSurface(ViewModel.ProtoService, big.DocumentValue, ViewModel.GetPatternForeground()) }; } else { From c10eb8394412dc30f8702f3722eb5a442d2d0903 Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Wed, 17 Jun 2020 20:47:00 +0200 Subject: [PATCH 05/45] Improved messages deletion --- .../ViewModels/DialogViewModel.Handle.cs | 77 +++++++++---------- 1 file changed, 38 insertions(+), 39 deletions(-) diff --git a/Unigram/Unigram/ViewModels/DialogViewModel.Handle.cs b/Unigram/Unigram/ViewModels/DialogViewModel.Handle.cs index 6d3f9daf0e..cb6add2aae 100644 --- a/Unigram/Unigram/ViewModels/DialogViewModel.Handle.cs +++ b/Unigram/Unigram/ViewModels/DialogViewModel.Handle.cs @@ -408,59 +408,58 @@ public void Handle(UpdateDeleteMessages update) { using (await _insertLock.WaitAsync()) { + var table = new HashSet(update.MessageIds); + for (int i = 0; i < Items.Count; i++) { - for (int j = 0; j < update.MessageIds.Count; j++) + var message = Items[i]; + if (message.MediaAlbumId != 0 && message.Content is MessageAlbum album) { - var message = Items[i]; - if (message.MediaAlbumId != 0 && message.Content is MessageAlbum album) - { - var found = false; + var found = false; - for (int k = 0; k < album.Layout.Messages.Count; k++) + for (int k = 0; k < album.Layout.Messages.Count; k++) + { + if (table.Contains(album.Layout.Messages[k].Id)) { - if (album.Layout.Messages[k].Id == update.MessageIds[j]) + album.Layout.Messages.RemoveAt(k); + + if (album.Layout.Messages.Count > 0) { - album.Layout.Messages.RemoveAt(k); - - if (album.Layout.Messages.Count > 0) - { - message.UpdateWith(album.Layout.Messages[0]); - album.Layout.Calculate(); - - Handle(new UpdateMessageContent(message.ChatId, message.Id, album)); - } - else - { - Items.RemoveAt(i); - i--; - } - - found = true; - break; + message.UpdateWith(album.Layout.Messages[0]); + album.Layout.Calculate(); + + Handle(new UpdateMessageContent(message.ChatId, message.Id, album)); + } + else + { + Items.RemoveAt(i); + i--; } - } - if (found) - { - continue; + found = true; + break; } } - if (message.Id == update.MessageIds[j]) + if (found) { - Items.RemoveAt(i); - i--; - - break; + continue; } - else if (message.ReplyToMessageId == update.MessageIds[j]) - { - message.ReplyToMessage = null; - message.ReplyToMessageState = ReplyToMessageState.Deleted; + } - Handle(message, bubble => bubble.UpdateMessageReply(message), service => service.UpdateMessage(message)); - } + if (table.Contains(message.Id)) + { + Items.RemoveAt(i); + i--; + + break; + } + else if (table.Contains(message.ReplyToMessageId)) + { + message.ReplyToMessage = null; + message.ReplyToMessageState = ReplyToMessageState.Deleted; + + Handle(message, bubble => bubble.UpdateMessageReply(message), service => service.UpdateMessage(message)); } if (i >= 0 && i == Items.Count - 1 && Items[i].Content is MessageHeaderUnread) From 2b237e78914483ef63cf73bbdfcae92de048b32b Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Thu, 18 Jun 2020 13:10:16 +0200 Subject: [PATCH 06/45] Fixed blocked users context menu --- Unigram/Unigram/Views/Settings/SettingsBlockedUsersPage.xaml.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Unigram/Unigram/Views/Settings/SettingsBlockedUsersPage.xaml.cs b/Unigram/Unigram/Views/Settings/SettingsBlockedUsersPage.xaml.cs index 77df4b7270..e0695e9108 100644 --- a/Unigram/Unigram/Views/Settings/SettingsBlockedUsersPage.xaml.cs +++ b/Unigram/Unigram/Views/Settings/SettingsBlockedUsersPage.xaml.cs @@ -87,7 +87,7 @@ private void User_ContextRequested(UIElement sender, ContextRequestedEventArgs a var flyout = new MenuFlyout(); var element = sender as FrameworkElement; - var user = element.Tag as User; + var user = ScrollingHost.ItemFromContainer(element) as User; flyout.Items.Add(new MenuFlyoutItem { Text = Strings.Resources.Unblock, Command = ViewModel.UnblockCommand, CommandParameter = user }); From 15f97f8a38a6673c8e804642050c06bfdf7177bd Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Thu, 18 Jun 2020 13:12:00 +0200 Subject: [PATCH 07/45] Fixed folder icon crash --- Unigram/Unigram/ViewModels/Folders/FolderViewModel.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Unigram/Unigram/ViewModels/Folders/FolderViewModel.cs b/Unigram/Unigram/ViewModels/Folders/FolderViewModel.cs index c5cae14ec5..19ece75c04 100644 --- a/Unigram/Unigram/ViewModels/Folders/FolderViewModel.cs +++ b/Unigram/Unigram/ViewModels/Folders/FolderViewModel.cs @@ -129,7 +129,7 @@ public ChatFilter Filter set => Set(ref _filter, value); } - private string _title; + private string _title = string.Empty; public string Title { get => _title; @@ -281,7 +281,7 @@ private bool SendCanExecute() private ChatFilter GetFilter() { var filter = new ChatFilter(); - filter.Title = Title; + filter.Title = Title ?? string.Empty; filter.IconName = _iconPicked ? Enum.GetName(typeof(ChatFilterIcon), Icon) : string.Empty; filter.PinnedChatIds = new List(); filter.IncludedChatIds = new List(); From 9df1331867761d0573f4b6ea40db11d7e9a40b44 Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Thu, 18 Jun 2020 13:15:25 +0200 Subject: [PATCH 08/45] Try catch AudioGraph initialization for some reason --- Unigram/Unigram/Common/SoundEffects.cs | 55 ++++++++++++++------------ 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/Unigram/Unigram/Common/SoundEffects.cs b/Unigram/Unigram/Common/SoundEffects.cs index 8de4d16749..5cf6078ad5 100644 --- a/Unigram/Unigram/Common/SoundEffects.cs +++ b/Unigram/Unigram/Common/SoundEffects.cs @@ -9,33 +9,38 @@ public static class SoundEffects { public static async void Play(SoundEffect effect) { - var settings = new AudioGraphSettings(AudioRenderCategory.SoundEffects); - settings.QuantumSizeSelectionMode = QuantumSizeSelectionMode.LowestLatency; - - var result = await AudioGraph.CreateAsync(settings); - if (result.Status != AudioGraphCreationStatus.Success) - { - return; - } - - var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/Audio/sent.mp3")); - - var fileInputNodeResult = await result.Graph.CreateFileInputNodeAsync(file); - if (fileInputNodeResult.Status != AudioFileNodeCreationStatus.Success) + try { - return; + // This seems to fail in some conditions. + var settings = new AudioGraphSettings(AudioRenderCategory.SoundEffects); + settings.QuantumSizeSelectionMode = QuantumSizeSelectionMode.SystemDefault; + + var result = await AudioGraph.CreateAsync(settings); + if (result.Status != AudioGraphCreationStatus.Success) + { + return; + } + + var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/Audio/sent.mp3")); + + var fileInputNodeResult = await result.Graph.CreateFileInputNodeAsync(file); + if (fileInputNodeResult.Status != AudioFileNodeCreationStatus.Success) + { + return; + } + + var deviceOutputNodeResult = await result.Graph.CreateDeviceOutputNodeAsync(); + if (deviceOutputNodeResult.Status != AudioDeviceNodeCreationStatus.Success) + { + return; + } + + fileInputNodeResult.FileInputNode + .AddOutgoingConnection(deviceOutputNodeResult.DeviceOutputNode); + + result.Graph.Start(); } - - var deviceOutputNodeResult = await result.Graph.CreateDeviceOutputNodeAsync(); - if (deviceOutputNodeResult.Status != AudioDeviceNodeCreationStatus.Success) - { - return; - } - - fileInputNodeResult.FileInputNode - .AddOutgoingConnection(deviceOutputNodeResult.DeviceOutputNode); - - result.Graph.Start(); + catch { } } } From 067763c8c8141a8a2e9a9c46ff2c640d0b9ba87e Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Thu, 18 Jun 2020 13:44:57 +0200 Subject: [PATCH 09/45] Fixed a crash in settings search, added folders --- Unigram/Unigram/Services/SettingsSearchService.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Unigram/Unigram/Services/SettingsSearchService.cs b/Unigram/Unigram/Services/SettingsSearchService.cs index db5f4c361b..752447b9bd 100644 --- a/Unigram/Unigram/Services/SettingsSearchService.cs +++ b/Unigram/Unigram/Services/SettingsSearchService.cs @@ -4,6 +4,7 @@ using Telegram.Td.Api; using Unigram.Common; using Unigram.Views; +using Unigram.Views.Folders; using Unigram.Views.Settings; using Unigram.Views.Settings.Privacy; @@ -51,7 +52,7 @@ private IEnumerable Search(string query, SettingsSearchEntr var results = new List(); //var sane = "\\b" + Regex.Escape(query).Replace(' ', '.'); - var sane = "\\b" + query.Replace(' ', '.'); + var sane = "\\b" + query.Replace(' ', '.').Replace("\\", "\\\\"); if (entry.IsValid && Regex.IsMatch(entry.Text, sane, RegexOptions.IgnoreCase)) { var clone = entry.Clone(); @@ -89,8 +90,7 @@ private async void BuildSearchIndex() BuildAppearance(), new SettingsSearchPage(null, Strings.Resources.Language, "\uE164"), new SettingsSearchPage(null, Strings.Resources.AskAQuestion, "\uED15"), - - //new SettingsSearchPage(typeof(WalletPage), Strings.Resources.Wallet, "\uD83D\uDC8E") + new SettingsSearchPage(typeof(FoldersPage), Strings.Resources.Filters, "\uF12B") }; // FAQ indexing is done asyncronously From a76744b1679bb94a7cd28455677b5e5e26225577 Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Thu, 18 Jun 2020 13:45:16 +0200 Subject: [PATCH 10/45] Try-catch paste to avoid crashes when the app can't access clipboard data --- Unigram/Unigram/Controls/Chats/ChatTextBox.cs | 131 ++++++++---------- 1 file changed, 61 insertions(+), 70 deletions(-) diff --git a/Unigram/Unigram/Controls/Chats/ChatTextBox.cs b/Unigram/Unigram/Controls/Chats/ChatTextBox.cs index d5fba73d55..220b645aeb 100644 --- a/Unigram/Unigram/Controls/Chats/ChatTextBox.cs +++ b/Unigram/Unigram/Controls/Chats/ChatTextBox.cs @@ -77,93 +77,84 @@ protected override void OnPaste() private async void OnPaste(object sender, TextControlPasteEventArgs e) { - // If the user tries to paste RTF content from any TOM control (Visual Studio, Word, Wordpad, browsers) - // we have to handle the pasting operation manually to allow plaintext only. - var package = Clipboard.GetContent(); - if (package.AvailableFormats.Contains(StandardDataFormats.Bitmap)) + try { - if (e != null) + // If the user tries to paste RTF content from any TOM control (Visual Studio, Word, Wordpad, browsers) + // we have to handle the pasting operation manually to allow plaintext only. + var package = Clipboard.GetContent(); + if (package.AvailableFormats.Contains(StandardDataFormats.Bitmap) || package.AvailableFormats.Contains(StandardDataFormats.StorageItems)) { - e.Handled = true; - } - - await ViewModel.HandlePackageAsync(package); - } - //else if (package.AvailableFormats.Contains(StandardDataFormats.WebLink)) - //{ + if (e != null) + { + e.Handled = true; + } - //} - else if (package.AvailableFormats.Contains(StandardDataFormats.StorageItems)) - { - if (e != null) - { - e.Handled = true; + await ViewModel.HandlePackageAsync(package); } - - await ViewModel.HandlePackageAsync(package); - } - else if (package.AvailableFormats.Contains(StandardDataFormats.Text) && package.AvailableFormats.Contains("application/x-tl-field-tags")) - { - if (e != null) + else if (package.AvailableFormats.Contains(StandardDataFormats.Text) && package.AvailableFormats.Contains("application/x-tl-field-tags")) { - e.Handled = true; - } - - // This is our field format - var text = await package.GetTextAsync(); - var data = await package.GetDataAsync("application/x-tl-field-tags") as IRandomAccessStream; - var reader = new DataReader(data.GetInputStreamAt(0)); - var length = await reader.LoadAsync((uint)data.Size); + if (e != null) + { + e.Handled = true; + } - var count = reader.ReadInt32(); - var entities = new List(count); + // This is our field format + var text = await package.GetTextAsync(); + var data = await package.GetDataAsync("application/x-tl-field-tags") as IRandomAccessStream; + var reader = new DataReader(data.GetInputStreamAt(0)); + var length = await reader.LoadAsync((uint)data.Size); - for (int i = 0; i < count; i++) - { - var entity = new TextEntity { Offset = reader.ReadInt32(), Length = reader.ReadInt32() }; - var type = reader.ReadByte(); + var count = reader.ReadInt32(); + var entities = new List(count); - switch (type) + for (int i = 0; i < count; i++) { - case 1: - entity.Type = new TextEntityTypeBold(); - break; - case 2: - entity.Type = new TextEntityTypeItalic(); - break; - case 3: - entity.Type = new TextEntityTypePreCode(); - break; - case 4: - entity.Type = new TextEntityTypeTextUrl { Url = reader.ReadString(reader.ReadUInt32()) }; - break; - case 5: - entity.Type = new TextEntityTypeMentionName { UserId = reader.ReadInt32() }; - break; + var entity = new TextEntity { Offset = reader.ReadInt32(), Length = reader.ReadInt32() }; + var type = reader.ReadByte(); + + switch (type) + { + case 1: + entity.Type = new TextEntityTypeBold(); + break; + case 2: + entity.Type = new TextEntityTypeItalic(); + break; + case 3: + entity.Type = new TextEntityTypePreCode(); + break; + case 4: + entity.Type = new TextEntityTypeTextUrl { Url = reader.ReadString(reader.ReadUInt32()) }; + break; + case 5: + entity.Type = new TextEntityTypeMentionName { UserId = reader.ReadInt32() }; + break; + } + + entities.Add(entity); } - entities.Add(entity); + InsertText(text, entities); } - - InsertText(text, entities); - } - else if (package.AvailableFormats.Contains(StandardDataFormats.Text) && package.AvailableFormats.Contains("application/x-td-field-tags")) - { - // This is Telegram Desktop mentions format - } - else if (package.AvailableFormats.Contains(StandardDataFormats.Text) /*&& package.Contains("Rich Text Format")*/) - { - if (e != null) + else if (package.AvailableFormats.Contains(StandardDataFormats.Text) && package.AvailableFormats.Contains("application/x-td-field-tags")) { - e.Handled = true; + // This is Telegram Desktop mentions format } + else if (package.AvailableFormats.Contains(StandardDataFormats.Text) /*&& package.Contains("Rich Text Format")*/) + { + if (e != null) + { + e.Handled = true; + } - var text = await package.GetTextAsync(); - var start = Document.Selection.StartPosition; + var text = await package.GetTextAsync(); + var start = Document.Selection.StartPosition; - Document.Selection.SetText(TextSetOptions.None, text); - Document.Selection.SetRange(start + text.Length, start + text.Length); + Document.Selection.SetText(TextSetOptions.None, text); + Document.Selection.SetRange(start + text.Length, start + text.Length); + } } + catch { } } public ListView Messages { get; set; } From 0fb6ded5fc510c29a45477faad0c72989df96f96 Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Thu, 18 Jun 2020 13:54:46 +0200 Subject: [PATCH 11/45] Fixed incremental loading from first chat message --- Unigram/Unigram/Controls/Chats/ChatListView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Unigram/Unigram/Controls/Chats/ChatListView.cs b/Unigram/Unigram/Controls/Chats/ChatListView.cs index 1891f4df35..af0480aa1c 100644 --- a/Unigram/Unigram/Controls/Chats/ChatListView.cs +++ b/Unigram/Unigram/Controls/Chats/ChatListView.cs @@ -108,7 +108,7 @@ private async void ScrollingHost_ViewChanged(object sender, ScrollViewerViewChan //if (ItemsStack.FirstCacheIndex == 0 && !e.IsIntermediate) using (await _loadMoreLock.WaitAsync()) { - if (ItemsStack.FirstCacheIndex == 0 && !e.IsIntermediate) + if (ItemsStack.FirstCacheIndex == 0 && ViewModel.IsLastSliceLoaded != true && !e.IsIntermediate) { await ViewModel.LoadNextSliceAsync(true); } From 78ff9df66f1cb3e57a6c27fa2726290dbc6aca7c Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Thu, 18 Jun 2020 17:03:35 +0200 Subject: [PATCH 12/45] Moved navigation services for the sake of moving them --- .../Services}/FrameFacade.cs | 0 .../Services}/INavigable.cs | 0 .../Services}/INavigationService.cs | 0 .../Services}/JournalEntry.cs | 0 .../Services}/NavigatedEventArgs.cs | 0 .../Services}/NavigatingEventArgs.cs | 0 .../Services}/NavigationService.cs | 0 .../Services}/NavigationServiceList.cs | 0 Unigram/Unigram/Unigram.csproj | 17 +++++++++-------- 9 files changed, 9 insertions(+), 8 deletions(-) rename Unigram/Unigram/{Services/Navigation => Navigation/Services}/FrameFacade.cs (100%) rename Unigram/Unigram/{Services/Navigation => Navigation/Services}/INavigable.cs (100%) rename Unigram/Unigram/{Services/Navigation => Navigation/Services}/INavigationService.cs (100%) rename Unigram/Unigram/{Services/Navigation => Navigation/Services}/JournalEntry.cs (100%) rename Unigram/Unigram/{Services/Navigation => Navigation/Services}/NavigatedEventArgs.cs (100%) rename Unigram/Unigram/{Services/Navigation => Navigation/Services}/NavigatingEventArgs.cs (100%) rename Unigram/Unigram/{Services/Navigation => Navigation/Services}/NavigationService.cs (100%) rename Unigram/Unigram/{Services/Navigation => Navigation/Services}/NavigationServiceList.cs (100%) diff --git a/Unigram/Unigram/Services/Navigation/FrameFacade.cs b/Unigram/Unigram/Navigation/Services/FrameFacade.cs similarity index 100% rename from Unigram/Unigram/Services/Navigation/FrameFacade.cs rename to Unigram/Unigram/Navigation/Services/FrameFacade.cs diff --git a/Unigram/Unigram/Services/Navigation/INavigable.cs b/Unigram/Unigram/Navigation/Services/INavigable.cs similarity index 100% rename from Unigram/Unigram/Services/Navigation/INavigable.cs rename to Unigram/Unigram/Navigation/Services/INavigable.cs diff --git a/Unigram/Unigram/Services/Navigation/INavigationService.cs b/Unigram/Unigram/Navigation/Services/INavigationService.cs similarity index 100% rename from Unigram/Unigram/Services/Navigation/INavigationService.cs rename to Unigram/Unigram/Navigation/Services/INavigationService.cs diff --git a/Unigram/Unigram/Services/Navigation/JournalEntry.cs b/Unigram/Unigram/Navigation/Services/JournalEntry.cs similarity index 100% rename from Unigram/Unigram/Services/Navigation/JournalEntry.cs rename to Unigram/Unigram/Navigation/Services/JournalEntry.cs diff --git a/Unigram/Unigram/Services/Navigation/NavigatedEventArgs.cs b/Unigram/Unigram/Navigation/Services/NavigatedEventArgs.cs similarity index 100% rename from Unigram/Unigram/Services/Navigation/NavigatedEventArgs.cs rename to Unigram/Unigram/Navigation/Services/NavigatedEventArgs.cs diff --git a/Unigram/Unigram/Services/Navigation/NavigatingEventArgs.cs b/Unigram/Unigram/Navigation/Services/NavigatingEventArgs.cs similarity index 100% rename from Unigram/Unigram/Services/Navigation/NavigatingEventArgs.cs rename to Unigram/Unigram/Navigation/Services/NavigatingEventArgs.cs diff --git a/Unigram/Unigram/Services/Navigation/NavigationService.cs b/Unigram/Unigram/Navigation/Services/NavigationService.cs similarity index 100% rename from Unigram/Unigram/Services/Navigation/NavigationService.cs rename to Unigram/Unigram/Navigation/Services/NavigationService.cs diff --git a/Unigram/Unigram/Services/Navigation/NavigationServiceList.cs b/Unigram/Unigram/Navigation/Services/NavigationServiceList.cs similarity index 100% rename from Unigram/Unigram/Services/Navigation/NavigationServiceList.cs rename to Unigram/Unigram/Navigation/Services/NavigationServiceList.cs diff --git a/Unigram/Unigram/Unigram.csproj b/Unigram/Unigram/Unigram.csproj index f20b0b50e7..aabceffcf5 100644 --- a/Unigram/Unigram/Unigram.csproj +++ b/Unigram/Unigram/Unigram.csproj @@ -28,7 +28,7 @@ 0 OnApplicationRun 7.3 - True + False 0 SHA256 @@ -474,6 +474,14 @@ + + + + + + + + @@ -538,13 +546,6 @@ - - - - - - - From f94ea4a5989dfa2354729599a4fb2eb912ec57bc Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Thu, 18 Jun 2020 17:04:12 +0200 Subject: [PATCH 13/45] Simplified event aggregator --- Unigram/Unigram/Services/EventAggregator.cs | 151 ++------------------ 1 file changed, 15 insertions(+), 136 deletions(-) diff --git a/Unigram/Unigram/Services/EventAggregator.cs b/Unigram/Unigram/Services/EventAggregator.cs index 3bc08b5bf3..ebbd87e7ca 100644 --- a/Unigram/Unigram/Services/EventAggregator.cs +++ b/Unigram/Unigram/Services/EventAggregator.cs @@ -1,9 +1,8 @@ using System; using System.Collections.Generic; -using System.Diagnostics; +using System.Collections.Immutable; using System.Linq; using System.Reflection; -using Unigram.Common; namespace Unigram.Services { @@ -30,14 +29,6 @@ public interface IHandle : IHandle /// public interface IEventAggregator { - /// - /// Gets or sets the default publication thread marshaller. - /// - /// - /// The default publication thread marshaller. - /// - Action PublicationThreadMarshaller { get; set; } - /// /// Searches the subscribed handlers to check if we have a handler for /// the message type supplied. @@ -66,14 +57,6 @@ public interface IEventAggregator /// Uses the default thread marshaller during publication. /// void Publish(object message); - void Publish(object message, object subscriber); - - /// - /// Publishes a message. - /// - /// The message instance. - /// Allows the publisher to provide a custom thread marshaller for the message publication. - void Publish(object message, object subscriber, Action marshal); } /// @@ -83,28 +66,6 @@ public class EventAggregator : IEventAggregator { readonly List handlers = new List(); - /// - /// The default thread marshaller used for publication; - /// - public static Action DefaultPublicationThreadMarshaller = action => action(); - - /// - /// Processing of handler results on publication thread. - /// - public static Action HandlerResultProcessing = (target, result) => { }; - - public static IEventAggregator Instance { get; protected set; } - - /// - /// Initializes a new instance of the class. - /// - public EventAggregator() - { - PublicationThreadMarshaller = DefaultPublicationThreadMarshaller; - - Instance = this; - } - /// /// Gets or sets the default publication thread marshaller. /// @@ -166,16 +127,10 @@ public virtual void Unsubscribe(object subscriber) } } - public static bool LogPublish { get; set; } - /// /// Publishes a message. /// /// The message instance. - /// - /// Does not marshall the the publication to any special thread by default. - /// - [DebuggerStepThrough] public virtual void Publish(object message) { if (message == null) @@ -183,81 +138,25 @@ public virtual void Publish(object message) throw new ArgumentNullException("message"); } -#if DEBUG - if (LogPublish) - { - Debug.WriteLine("Publish " + message.GetType()); - } -#endif - - Publish(message, null, PublicationThreadMarshaller); - } - - [DebuggerStepThrough] - public virtual void Publish(object message, object subscriber) - { - if (message == null) - { - throw new ArgumentNullException("message"); - } - -#if DEBUG - if (LogPublish) - { - Debug.WriteLine("Publish " + message.GetType()); - } -#endif - - Publish(message, subscriber, PublicationThreadMarshaller); - } - - /// - /// Publishes a message. - /// - /// The message instance. - /// Allows the publisher to provide a custom thread marshaller for the message publication. - public virtual void Publish(object message, object subscriber, Action marshal) - { - if (message == null) - { - throw new ArgumentNullException("message"); - } - if (marshal == null) - { - throw new ArgumentNullException("marshal"); - } - Handler[] toNotify; lock (handlers) { - var found = handlers.FirstOrDefault(x => x.Matches(subscriber)); - - if (found != null) - { - toNotify = handlers.Except(new[] { found }).ToArray(); - } - else - { - toNotify = handlers.ToArray(); - } + toNotify = handlers.ToArray(); } - marshal(() => - { - var messageType = message.GetType(); + var messageType = message.GetType(); - var dead = toNotify - .Where(handler => !handler.Handle(messageType, message)) - .ToList(); + var dead = toNotify + .Where(handler => !handler.Handle(messageType, message)) + .ToImmutableHashSet(); - if (dead.Any()) + if (dead.Any()) + { + lock (handlers) { - lock (handlers) - { - dead.Apply(x => handlers.Remove(x)); - } + handlers.RemoveAll(x => dead.Contains(x)); } - }); + } } class Handler @@ -274,28 +173,15 @@ public Handler(object handler) { reference = new WeakReference(handler); -#if WIN_RT - var handlerInfo = typeof(IHandle).GetTypeInfo(); - var interfaces = handler.GetType().GetTypeInfo().ImplementedInterfaces - .Where(x => handlerInfo.IsAssignableFrom(x.GetTypeInfo()) && x.GetTypeInfo().IsGenericType); - - foreach (var @interface in interfaces) - { - var type = @interface.GenericTypeArguments[0]; - var method = @interface.GetTypeInfo().DeclaredMethods.First(x => x.Name == "Handle"); - supportedHandlers[type] = method; - } -#else var interfaces = handler.GetType().GetInterfaces() .Where(x => typeof(IHandle).IsAssignableFrom(x) && x.IsConstructedGenericType); foreach (var @interface in interfaces) { - var type = @interface.GetGenericArguments()[0]; + var type = @interface.GenericTypeArguments[0]; var method = @interface.GetMethod("Handle"); supportedHandlers[type] = method; } -#endif } public bool Matches(object instance) @@ -311,16 +197,9 @@ public bool Handle(Type messageType, object message) return false; } - foreach (var pair in supportedHandlers) + if (supportedHandlers.TryGetValue(messageType, out MethodInfo method)) { - if (pair.Key.IsAssignableFrom(messageType)) - { - var result = pair.Value.Invoke(target, new[] { message }); - if (result != null) - { - HandlerResultProcessing(target, result); - } - } + method.Invoke(target, new[] { message }); } return true; @@ -328,7 +207,7 @@ public bool Handle(Type messageType, object message) public bool Handles(Type messageType) { - return supportedHandlers.Any(pair => pair.Key.IsAssignableFrom(messageType)); + return supportedHandlers.ContainsKey(messageType); } } } From cc7e82cbd4f0054663d07af2ad5807f3a0fcd45a Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Thu, 18 Jun 2020 17:17:27 +0200 Subject: [PATCH 14/45] Unigram.Services.Navigation -> Unigram.Navigation.Services --- Unigram/Unigram/App.xaml.cs | 3 +-- Unigram/Unigram/Common/Extensions.cs | 2 +- Unigram/Unigram/Common/MessageHelper.cs | 2 +- Unigram/Unigram/Common/NavigationService.cs | 2 +- Unigram/Unigram/Common/TLNavigationService.cs | 6 +----- Unigram/Unigram/Common/TLRootNavigationService.cs | 2 +- Unigram/Unigram/Common/WindowContext.cs | 2 +- Unigram/Unigram/Controls/Cells/ChatCell.xaml.cs | 2 +- .../Unigram/Controls/Cells/SharedLinkCell.xaml.cs | 2 +- Unigram/Unigram/Controls/MasterDetailView.cs | 2 +- Unigram/Unigram/Controls/OverlayPage.cs | 2 +- Unigram/Unigram/Controls/PlaybackHeader.xaml.cs | 2 +- Unigram/Unigram/Navigation/BootStrapper.cs | 8 ++++---- .../Unigram/Navigation/Services/FrameFacade.cs | 15 +++++++-------- Unigram/Unigram/Navigation/Services/INavigable.cs | 3 +-- .../Navigation/Services/INavigationService.cs | 3 +-- .../Navigation/Services/NavigatedEventArgs.cs | 2 +- .../Navigation/Services/NavigatingEventArgs.cs | 3 +-- .../Navigation/Services/NavigationService.cs | 11 +++++------ .../Navigation/Services/NavigationServiceList.cs | 2 +- Unigram/Unigram/Navigation/ViewModelBase.cs | 2 +- Unigram/Unigram/Navigation/WindowContext.cs | 6 +++--- .../Services/ViewService/ViewLifetimeControl.cs | 2 +- Unigram/Unigram/ViewModels/DialogViewModel.cs | 2 +- .../Settings/SettingsAppearanceViewModel.cs | 2 +- .../Settings/SettingsBlockedUsersViewModel.cs | 2 +- .../Unigram/ViewModels/TLMultipleViewModelBase.cs | 2 +- Unigram/Unigram/Views/Host/RootPage.xaml.cs | 2 +- Unigram/Unigram/Views/Host/StandalonePage.xaml.cs | 2 +- 29 files changed, 44 insertions(+), 54 deletions(-) diff --git a/Unigram/Unigram/App.xaml.cs b/Unigram/Unigram/App.xaml.cs index fdd4d2c80c..5e4e24c4ca 100644 --- a/Unigram/Unigram/App.xaml.cs +++ b/Unigram/Unigram/App.xaml.cs @@ -5,10 +5,9 @@ using Telegram.Td; using Telegram.Td.Api; using Unigram.Common; -using Unigram.Controls; using Unigram.Navigation; +using Unigram.Navigation.Services; using Unigram.Services; -using Unigram.Services.Navigation; using Unigram.Services.Updates; using Unigram.Views; using Unigram.Views.Host; diff --git a/Unigram/Unigram/Common/Extensions.cs b/Unigram/Unigram/Common/Extensions.cs index 91d197ee39..090493ec77 100644 --- a/Unigram/Unigram/Common/Extensions.cs +++ b/Unigram/Unigram/Common/Extensions.cs @@ -11,8 +11,8 @@ using Unigram.Controls.Messages; using Unigram.Native; using Unigram.Navigation; +using Unigram.Navigation.Services; using Unigram.Services; -using Unigram.Services.Navigation; using Windows.ApplicationModel; using Windows.ApplicationModel.DataTransfer; using Windows.Foundation; diff --git a/Unigram/Unigram/Common/MessageHelper.cs b/Unigram/Unigram/Common/MessageHelper.cs index 1c1035fa9d..783c9872d6 100644 --- a/Unigram/Unigram/Common/MessageHelper.cs +++ b/Unigram/Unigram/Common/MessageHelper.cs @@ -5,8 +5,8 @@ using Unigram.Controls; using Unigram.Converters; using Unigram.Navigation; +using Unigram.Navigation.Services; using Unigram.Services; -using Unigram.Services.Navigation; using Unigram.ViewModels; using Unigram.Views; using Unigram.Views.Host; diff --git a/Unigram/Unigram/Common/NavigationService.cs b/Unigram/Unigram/Common/NavigationService.cs index 4ca701efa4..5200b2f032 100644 --- a/Unigram/Unigram/Common/NavigationService.cs +++ b/Unigram/Unigram/Common/NavigationService.cs @@ -2,8 +2,8 @@ using System.Collections.Generic; using System.Threading.Tasks; using Telegram.Td.Api; +using Unigram.Navigation.Services; using Unigram.Services; -using Unigram.Services.Navigation; using Unigram.ViewModels; using Unigram.Views; using Unigram.Views.Payments; diff --git a/Unigram/Unigram/Common/TLNavigationService.cs b/Unigram/Unigram/Common/TLNavigationService.cs index 408f9069db..bb46258793 100644 --- a/Unigram/Unigram/Common/TLNavigationService.cs +++ b/Unigram/Unigram/Common/TLNavigationService.cs @@ -3,9 +3,8 @@ using System.Threading.Tasks; using Telegram.Td.Api; using Unigram.Controls; +using Unigram.Navigation.Services; using Unigram.Services; -using Unigram.Services.Navigation; -using Unigram.Services.ViewService; using Unigram.Views; using Unigram.Views.Popups; using Unigram.Views.Settings; @@ -23,10 +22,7 @@ public class TLNavigationService : NavigationService private readonly IProtoService _protoService; private readonly IPasscodeService _passcodeService; - private ViewLifetimeControl _walletLifetime; - private Dictionary _instantWindows = new Dictionary(); - private AppWindow _walletWindow; public TLNavigationService(IProtoService protoService, Frame frame, int session, string id) : base(frame, session, id) diff --git a/Unigram/Unigram/Common/TLRootNavigationService.cs b/Unigram/Unigram/Common/TLRootNavigationService.cs index 7b6624a697..1bdb223d23 100644 --- a/Unigram/Unigram/Common/TLRootNavigationService.cs +++ b/Unigram/Unigram/Common/TLRootNavigationService.cs @@ -1,7 +1,7 @@ using Telegram.Td.Api; using Unigram.Controls; +using Unigram.Navigation.Services; using Unigram.Services; -using Unigram.Services.Navigation; using Unigram.ViewModels.SignIn; using Unigram.Views; using Unigram.Views.SignIn; diff --git a/Unigram/Unigram/Common/WindowContext.cs b/Unigram/Unigram/Common/WindowContext.cs index 3c35b6b91c..f228f6f628 100644 --- a/Unigram/Unigram/Common/WindowContext.cs +++ b/Unigram/Unigram/Common/WindowContext.cs @@ -4,8 +4,8 @@ using Unigram.Controls; using Unigram.Native; using Unigram.Navigation; +using Unigram.Navigation.Services; using Unigram.Services; -using Unigram.Services.Navigation; using Unigram.Views; using Unigram.Views.Popups; using Unigram.Views.SignIn; diff --git a/Unigram/Unigram/Controls/Cells/ChatCell.xaml.cs b/Unigram/Unigram/Controls/Cells/ChatCell.xaml.cs index 873d8fe615..127df61b99 100644 --- a/Unigram/Unigram/Controls/Cells/ChatCell.xaml.cs +++ b/Unigram/Unigram/Controls/Cells/ChatCell.xaml.cs @@ -9,8 +9,8 @@ using Unigram.Controls.Messages; using Unigram.Converters; using Unigram.Navigation; +using Unigram.Navigation.Services; using Unigram.Services; -using Unigram.Services.Navigation; using Unigram.ViewModels.Delegates; using Windows.UI; using Windows.UI.Composition; diff --git a/Unigram/Unigram/Controls/Cells/SharedLinkCell.xaml.cs b/Unigram/Unigram/Controls/Cells/SharedLinkCell.xaml.cs index 08ee1c64e8..89cd592be5 100644 --- a/Unigram/Unigram/Controls/Cells/SharedLinkCell.xaml.cs +++ b/Unigram/Unigram/Controls/Cells/SharedLinkCell.xaml.cs @@ -2,8 +2,8 @@ using System.Collections.Generic; using Telegram.Td.Api; using Unigram.Common; +using Unigram.Navigation.Services; using Unigram.Services; -using Unigram.Services.Navigation; using Windows.System; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; diff --git a/Unigram/Unigram/Controls/MasterDetailView.cs b/Unigram/Unigram/Controls/MasterDetailView.cs index 228ec21bd4..7cd607e672 100644 --- a/Unigram/Unigram/Controls/MasterDetailView.cs +++ b/Unigram/Unigram/Controls/MasterDetailView.cs @@ -2,8 +2,8 @@ using System.Collections.Generic; using System.ComponentModel; using Unigram.Navigation; +using Unigram.Navigation.Services; using Unigram.Services; -using Unigram.Services.Navigation; using Unigram.Views; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; diff --git a/Unigram/Unigram/Controls/OverlayPage.cs b/Unigram/Unigram/Controls/OverlayPage.cs index 6672639915..b1ef72b57f 100644 --- a/Unigram/Unigram/Controls/OverlayPage.cs +++ b/Unigram/Unigram/Controls/OverlayPage.cs @@ -5,7 +5,7 @@ using System.Threading.Tasks; using Unigram.Common; using Unigram.Navigation; -using Unigram.Services.Navigation; +using Unigram.Navigation.Services; using Unigram.Services.ViewService; using Windows.ApplicationModel.Core; using Windows.Foundation; diff --git a/Unigram/Unigram/Controls/PlaybackHeader.xaml.cs b/Unigram/Unigram/Controls/PlaybackHeader.xaml.cs index 172de6cfc0..dbdb379008 100644 --- a/Unigram/Unigram/Controls/PlaybackHeader.xaml.cs +++ b/Unigram/Unigram/Controls/PlaybackHeader.xaml.cs @@ -4,8 +4,8 @@ using Unigram.Common; using Unigram.Controls.Cells; using Unigram.Converters; +using Unigram.Navigation.Services; using Unigram.Services; -using Unigram.Services.Navigation; using Windows.Media.Playback; using Windows.System; using Windows.UI.Xaml; diff --git a/Unigram/Unigram/Navigation/BootStrapper.cs b/Unigram/Unigram/Navigation/BootStrapper.cs index 73767c3ee4..1b8158e991 100644 --- a/Unigram/Unigram/Navigation/BootStrapper.cs +++ b/Unigram/Unigram/Navigation/BootStrapper.cs @@ -7,7 +7,7 @@ using System.Runtime.CompilerServices; using System.Threading.Tasks; using Unigram.Common; -using Unigram.Services.Navigation; +using Unigram.Navigation.Services; using Unigram.Services.ViewService; using Windows.ApplicationModel; using Windows.ApplicationModel.Activation; @@ -59,8 +59,8 @@ protected void Set(ref T storage, T value, [CallerMemberName] String property #region Debug [Conditional("DEBUG")] - static void DebugWrite(string text = null, Services.Logging.Severities severity = Services.Logging.Severities.Template10, [CallerMemberName] string caller = null) => - Services.Logging.LoggingService.WriteLine(text, severity, caller: $"BootStrapper.{caller}"); + static void DebugWrite(string text = null, Unigram.Services.Logging.Severities severity = Unigram.Services.Logging.Severities.Template10, [CallerMemberName] string caller = null) => + Unigram.Services.Logging.LoggingService.WriteLine(text, severity, caller: $"BootStrapper.{caller}"); #endregion @@ -78,7 +78,7 @@ private void Loaded() DebugWrite(); // Hook up keyboard and mouse Back handler - var keyboard = Services.Keyboard.KeyboardService.GetForCurrentView(); + var keyboard = Unigram.Services.Keyboard.KeyboardService.GetForCurrentView(); keyboard.AfterBackGesture = (key) => { DebugWrite(caller: nameof(keyboard.AfterBackGesture)); diff --git a/Unigram/Unigram/Navigation/Services/FrameFacade.cs b/Unigram/Unigram/Navigation/Services/FrameFacade.cs index 77dbf05d47..baf0589cd7 100644 --- a/Unigram/Unigram/Navigation/Services/FrameFacade.cs +++ b/Unigram/Unigram/Navigation/Services/FrameFacade.cs @@ -3,14 +3,13 @@ using System.ComponentModel; using System.Diagnostics; using System.Runtime.CompilerServices; -using Unigram.Navigation; using Unigram.Services.Serialization; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Media.Animation; using Windows.UI.Xaml.Navigation; -namespace Unigram.Services.Navigation +namespace Unigram.Navigation.Services { // DOCS: https://github.com/Windows-XAML/Template10/wiki/Docs-%7C-NavigationService public class FrameFacade @@ -18,8 +17,8 @@ public class FrameFacade #region Debug [Conditional("DEBUG")] - static void DebugWrite(string text = null, Services.Logging.Severities severity = Logging.Severities.Template10, [CallerMemberName] string caller = null) => - Logging.LoggingService.WriteLine(text, severity, caller: $"{nameof(FrameFacade)}.{caller}"); + static void DebugWrite(string text = null, Unigram.Services.Logging.Severities severity = Unigram.Services.Logging.Severities.Template10, [CallerMemberName] string caller = null) => + Unigram.Services.Logging.LoggingService.WriteLine(text, severity, caller: $"{nameof(FrameFacade)}.{caller}"); #endregion @@ -67,9 +66,9 @@ public void RaiseForwardRequested(HandledEventArgs args) private string GetFrameStateKey() => string.Format("{0}-PageState", FrameId); - private SettingsLegacy.ISettingsService FrameStateSettingsService() + private Unigram.Services.SettingsLegacy.ISettingsService FrameStateSettingsService() { - return SettingsLegacy.SettingsService.Create(GetFrameStateKey(), true); + return Unigram.Services.SettingsLegacy.SettingsService.Create(GetFrameStateKey(), true); } public void SetFrameState(string key, string value) @@ -97,13 +96,13 @@ private string GetPageStateKey(string frameId, Type type, int backStackDepth, ob return $"{frameId}-{type}-{backStackDepth}"; } - public SettingsLegacy.ISettingsService PageStateSettingsService(Type type, int depth = 0, object parameter = null) + public Unigram.Services.SettingsLegacy.ISettingsService PageStateSettingsService(Type type, int depth = 0, object parameter = null) { var key = GetPageStateKey(FrameId, type, BackStackDepth + depth, parameter); return FrameStateSettingsService().Open(key, true); } - public SettingsLegacy.ISettingsService PageStateSettingsService(string key) + public Unigram.Services.SettingsLegacy.ISettingsService PageStateSettingsService(string key) { return FrameStateSettingsService().Open(key, true); } diff --git a/Unigram/Unigram/Navigation/Services/INavigable.cs b/Unigram/Unigram/Navigation/Services/INavigable.cs index 3daa78e925..76171a65af 100644 --- a/Unigram/Unigram/Navigation/Services/INavigable.cs +++ b/Unigram/Unigram/Navigation/Services/INavigable.cs @@ -1,9 +1,8 @@ using System.Collections.Generic; using System.Threading.Tasks; -using Unigram.Navigation; using Windows.UI.Xaml.Navigation; -namespace Unigram.Services.Navigation +namespace Unigram.Navigation.Services { // DOCS: https://github.com/Windows-XAML/Template10/wiki/Docs-%7C-NavigationService public interface INavigable diff --git a/Unigram/Unigram/Navigation/Services/INavigationService.cs b/Unigram/Unigram/Navigation/Services/INavigationService.cs index 43b06cd818..c6c1681a47 100644 --- a/Unigram/Unigram/Navigation/Services/INavigationService.cs +++ b/Unigram/Unigram/Navigation/Services/INavigationService.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using Unigram.Navigation; using Unigram.Services.ViewService; using Windows.ApplicationModel.Core; using Windows.Foundation; @@ -9,7 +8,7 @@ using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Media.Animation; -namespace Unigram.Services.Navigation +namespace Unigram.Navigation.Services { public interface INavigationService { diff --git a/Unigram/Unigram/Navigation/Services/NavigatedEventArgs.cs b/Unigram/Unigram/Navigation/Services/NavigatedEventArgs.cs index 87a0c1a2fd..0619ccc278 100644 --- a/Unigram/Unigram/Navigation/Services/NavigatedEventArgs.cs +++ b/Unigram/Unigram/Navigation/Services/NavigatedEventArgs.cs @@ -2,7 +2,7 @@ using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Navigation; -namespace Unigram.Services.Navigation +namespace Unigram.Navigation.Services { // DOCS: https://github.com/Windows-XAML/Template10/wiki/Docs-%7C-NavigationService public class NavigatedEventArgs : EventArgs diff --git a/Unigram/Unigram/Navigation/Services/NavigatingEventArgs.cs b/Unigram/Unigram/Navigation/Services/NavigatingEventArgs.cs index 7c5ed776aa..3fcda475d5 100644 --- a/Unigram/Unigram/Navigation/Services/NavigatingEventArgs.cs +++ b/Unigram/Unigram/Navigation/Services/NavigatingEventArgs.cs @@ -1,9 +1,8 @@ using System; -using Unigram.Navigation; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Navigation; -namespace Unigram.Services.Navigation +namespace Unigram.Navigation.Services { // DOCS: https://github.com/Windows-XAML/Template10/wiki/Docs-%7C-NavigationService public class NavigatingEventArgs : NavigatedEventArgs diff --git a/Unigram/Unigram/Navigation/Services/NavigationService.cs b/Unigram/Unigram/Navigation/Services/NavigationService.cs index 868e4c42f0..6793d29954 100644 --- a/Unigram/Unigram/Navigation/Services/NavigationService.cs +++ b/Unigram/Unigram/Navigation/Services/NavigationService.cs @@ -5,7 +5,6 @@ using System.Runtime.CompilerServices; using System.Threading.Tasks; using Unigram.Common; -using Unigram.Navigation; using Unigram.Services.Serialization; using Unigram.Services.ViewService; using Windows.ApplicationModel.Core; @@ -16,12 +15,12 @@ using Windows.UI.Xaml.Media.Animation; using Windows.UI.Xaml.Navigation; -namespace Unigram.Services.Navigation +namespace Unigram.Navigation.Services { // DOCS: https://github.com/Windows-XAML/Template10/wiki/Docs-%7C-NavigationService public partial class NavigationService : INavigationService { - private readonly IViewService viewService = new ViewService.ViewService(); + private readonly IViewService viewService = new ViewService(); FrameFacade FrameFacadeInternal { get; } public FrameFacade FrameFacade => FrameFacadeInternal; public bool IsInMainView { get; } @@ -42,8 +41,8 @@ public string NavigationState #region Debug [Conditional("DEBUG")] - static void DebugWrite(string text = null, Services.Logging.Severities severity = Services.Logging.Severities.Template10, [CallerMemberName] string caller = null) => - Services.Logging.LoggingService.WriteLine(text, severity, caller: $"NavigationService.{caller}"); + static void DebugWrite(string text = null, Unigram.Services.Logging.Severities severity = Unigram.Services.Logging.Severities.Template10, [CallerMemberName] string caller = null) => + Unigram.Services.Logging.LoggingService.WriteLine(text, severity, caller: $"NavigationService.{caller}"); #endregion @@ -52,7 +51,7 @@ public string NavigationState public NavigationService(Frame frame, int session, string id) { - SerializationService = Services.Serialization.SerializationService.Json; + SerializationService = Unigram.Services.Serialization.SerializationService.Json; IsInMainView = CoreApplication.MainView == CoreApplication.GetCurrentView(); SessionId = session; FrameFacadeInternal = new FrameFacade(this, frame, id); diff --git a/Unigram/Unigram/Navigation/Services/NavigationServiceList.cs b/Unigram/Unigram/Navigation/Services/NavigationServiceList.cs index 08602131e9..d0a3d5bc47 100644 --- a/Unigram/Unigram/Navigation/Services/NavigationServiceList.cs +++ b/Unigram/Unigram/Navigation/Services/NavigationServiceList.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Linq; -namespace Unigram.Services.Navigation +namespace Unigram.Navigation.Services { public class NavigationServiceList : List { diff --git a/Unigram/Unigram/Navigation/ViewModelBase.cs b/Unigram/Unigram/Navigation/ViewModelBase.cs index 6c09a8c4af..55e21a020f 100644 --- a/Unigram/Unigram/Navigation/ViewModelBase.cs +++ b/Unigram/Unigram/Navigation/ViewModelBase.cs @@ -1,7 +1,7 @@ using Newtonsoft.Json; using System.Collections.Generic; using System.Threading.Tasks; -using Unigram.Services.Navigation; +using Unigram.Navigation.Services; using Windows.UI.Xaml.Navigation; namespace Unigram.Navigation diff --git a/Unigram/Unigram/Navigation/WindowContext.cs b/Unigram/Unigram/Navigation/WindowContext.cs index d3694a34cb..657376bb4e 100644 --- a/Unigram/Unigram/Navigation/WindowContext.cs +++ b/Unigram/Unigram/Navigation/WindowContext.cs @@ -3,7 +3,7 @@ using System.Diagnostics; using System.Linq; using System.Runtime.CompilerServices; -using Unigram.Services.Navigation; +using Unigram.Navigation.Services; using Windows.ApplicationModel.Core; using Windows.Foundation; using Windows.Graphics.Display; @@ -19,8 +19,8 @@ public class WindowContext #region Debug [Conditional("DEBUG")] - static void DebugWrite(string text = null, Services.Logging.Severities severity = Services.Logging.Severities.Template10, [CallerMemberName] string caller = null) => - Services.Logging.LoggingService.WriteLine(text, severity, caller: $"WindowWrapper.{caller}"); + static void DebugWrite(string text = null, Unigram.Services.Logging.Severities severity = Unigram.Services.Logging.Severities.Template10, [CallerMemberName] string caller = null) => + Unigram.Services.Logging.LoggingService.WriteLine(text, severity, caller: $"WindowWrapper.{caller}"); #endregion diff --git a/Unigram/Unigram/Services/ViewService/ViewLifetimeControl.cs b/Unigram/Unigram/Services/ViewService/ViewLifetimeControl.cs index d5473370d1..1c517d98c8 100644 --- a/Unigram/Unigram/Services/ViewService/ViewLifetimeControl.cs +++ b/Unigram/Unigram/Services/ViewService/ViewLifetimeControl.cs @@ -23,7 +23,7 @@ using System; using System.Collections.Concurrent; using Unigram.Navigation; -using Unigram.Services.Navigation; +using Unigram.Navigation.Services; using Windows.UI.Core; using Windows.UI.ViewManagement; using Windows.UI.Xaml; diff --git a/Unigram/Unigram/ViewModels/DialogViewModel.cs b/Unigram/Unigram/ViewModels/DialogViewModel.cs index 6380802b83..b7acbe272c 100644 --- a/Unigram/Unigram/ViewModels/DialogViewModel.cs +++ b/Unigram/Unigram/ViewModels/DialogViewModel.cs @@ -10,9 +10,9 @@ using Unigram.Controls; using Unigram.Controls.Chats; using Unigram.Navigation; +using Unigram.Navigation.Services; using Unigram.Services; using Unigram.Services.Factories; -using Unigram.Services.Navigation; using Unigram.Services.Updates; using Unigram.ViewModels.Chats; using Unigram.ViewModels.Delegates; diff --git a/Unigram/Unigram/ViewModels/Settings/SettingsAppearanceViewModel.cs b/Unigram/Unigram/ViewModels/Settings/SettingsAppearanceViewModel.cs index 45c8ef0af4..4155cdb0f5 100644 --- a/Unigram/Unigram/ViewModels/Settings/SettingsAppearanceViewModel.cs +++ b/Unigram/Unigram/ViewModels/Settings/SettingsAppearanceViewModel.cs @@ -2,8 +2,8 @@ using System.Collections.Generic; using System.Threading.Tasks; using Unigram.Common; +using Unigram.Navigation.Services; using Unigram.Services; -using Unigram.Services.Navigation; using Unigram.Services.Updates; using Unigram.Views.Popups; using Windows.Foundation.Metadata; diff --git a/Unigram/Unigram/ViewModels/Settings/SettingsBlockedUsersViewModel.cs b/Unigram/Unigram/ViewModels/Settings/SettingsBlockedUsersViewModel.cs index 4cbc0a8729..1954c716c3 100644 --- a/Unigram/Unigram/ViewModels/Settings/SettingsBlockedUsersViewModel.cs +++ b/Unigram/Unigram/ViewModels/Settings/SettingsBlockedUsersViewModel.cs @@ -7,8 +7,8 @@ using Unigram.Collections; using Unigram.Common; using Unigram.Controls; +using Unigram.Navigation.Services; using Unigram.Services; -using Unigram.Services.Navigation; using Unigram.ViewModels.Delegates; using Unigram.Views.Popups; using Windows.Foundation; diff --git a/Unigram/Unigram/ViewModels/TLMultipleViewModelBase.cs b/Unigram/Unigram/ViewModels/TLMultipleViewModelBase.cs index ff662d2ebc..d9db854c39 100644 --- a/Unigram/Unigram/ViewModels/TLMultipleViewModelBase.cs +++ b/Unigram/Unigram/ViewModels/TLMultipleViewModelBase.cs @@ -2,8 +2,8 @@ using System.Linq; using System.Threading.Tasks; using Unigram.Navigation; +using Unigram.Navigation.Services; using Unigram.Services; -using Unigram.Services.Navigation; using Windows.UI.Xaml.Navigation; namespace Unigram.ViewModels diff --git a/Unigram/Unigram/Views/Host/RootPage.xaml.cs b/Unigram/Unigram/Views/Host/RootPage.xaml.cs index 896631385d..3f2ae2ff00 100644 --- a/Unigram/Unigram/Views/Host/RootPage.xaml.cs +++ b/Unigram/Unigram/Views/Host/RootPage.xaml.cs @@ -7,8 +7,8 @@ using Unigram.Common; using Unigram.Controls; using Unigram.Navigation; +using Unigram.Navigation.Services; using Unigram.Services; -using Unigram.Services.Navigation; using Unigram.ViewModels; using Unigram.Views.SignIn; using Windows.Foundation; diff --git a/Unigram/Unigram/Views/Host/StandalonePage.xaml.cs b/Unigram/Unigram/Views/Host/StandalonePage.xaml.cs index 54e7b8f0db..851745cc12 100644 --- a/Unigram/Unigram/Views/Host/StandalonePage.xaml.cs +++ b/Unigram/Unigram/Views/Host/StandalonePage.xaml.cs @@ -2,8 +2,8 @@ using Unigram.Common; using Unigram.Controls; using Unigram.Navigation; +using Unigram.Navigation.Services; using Unigram.Services; -using Unigram.Services.Navigation; using Windows.ApplicationModel.Core; using Windows.System.Profile; using Windows.UI.Core; From 8ea5ae10db8d73f38206c43e8df912621c2898fc Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Thu, 18 Jun 2020 17:17:39 +0200 Subject: [PATCH 15/45] Reduce Action calls --- .../Collections/MvxObservableCollection.cs | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/Unigram/Unigram/Collections/MvxObservableCollection.cs b/Unigram/Unigram/Collections/MvxObservableCollection.cs index a433b1f56e..11ef293b1b 100644 --- a/Unigram/Unigram/Collections/MvxObservableCollection.cs +++ b/Unigram/Unigram/Collections/MvxObservableCollection.cs @@ -66,6 +66,11 @@ public bool EventsAreSuppressed get { return this._suppressEvents > 0; } } + public void Dispose() + { + _suppressEvents = int.MaxValue; + } + /// /// Raises the event with the provided event data. /// @@ -74,7 +79,7 @@ protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e) { if (!EventsAreSuppressed) { - InvokeOnMainThread(() => base.OnCollectionChanged(e)); + base.OnCollectionChanged(e); } } @@ -290,17 +295,6 @@ public void Reset() OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } - protected void InvokeOnMainThread(Action action) - { - action(); - //Execute.BeginOnUIThread(action); - } - - protected override void OnPropertyChanged(PropertyChangedEventArgs e) - { - InvokeOnMainThread(() => base.OnPropertyChanged(e)); - } - public virtual bool Set(ref T storage, T value, [CallerMemberName] string propertyName = null) { if (object.Equals(storage, value)) From 5ef5ed940cec20b23feedc63726466cb1818803a Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Thu, 18 Jun 2020 17:18:00 +0200 Subject: [PATCH 16/45] Improved MessagesCollection performances --- Unigram/Unigram/ViewModels/DialogViewModel.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Unigram/Unigram/ViewModels/DialogViewModel.cs b/Unigram/Unigram/ViewModels/DialogViewModel.cs index b7acbe272c..e7af09388d 100644 --- a/Unigram/Unigram/ViewModels/DialogViewModel.cs +++ b/Unigram/Unigram/ViewModels/DialogViewModel.cs @@ -3330,8 +3330,7 @@ public UserCommand(int userId, BotCommand command) public class MessageCollection : MvxObservableCollection { - private readonly Dictionary _messages = new Dictionary(); - private readonly HashSet _dates = new HashSet(); + private readonly HashSet _messages = new HashSet(); public Action> AttachChanged; @@ -3343,12 +3342,12 @@ public class MessageCollection : MvxObservableCollection public bool ContainsKey(long id) { - return _messages.ContainsKey(id); + return _messages.Contains(id); } protected override void InsertItem(int index, MessageViewModel item) { - _messages[item.Id] = item.Id; + _messages.Add(item.Id); item.IsFirst = true; item.IsLast = true; From 40170ca8fc0719f8b2df053458abd97006e3d676 Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Thu, 18 Jun 2020 17:22:39 +0200 Subject: [PATCH 17/45] ShowState --- Unigram/Unigram/Views/MainPage.xaml.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Unigram/Unigram/Views/MainPage.xaml.cs b/Unigram/Unigram/Views/MainPage.xaml.cs index bd15de475a..8aec7dc23c 100644 --- a/Unigram/Unigram/Views/MainPage.xaml.cs +++ b/Unigram/Unigram/Views/MainPage.xaml.cs @@ -439,16 +439,16 @@ public void Handle(UpdateConnectionState update) switch (update.State) { case ConnectionStateWaitingForNetwork waitingForNetwork: - ShowStatus(Strings.Resources.WaitingForNetwork); + ShowState(Strings.Resources.WaitingForNetwork); break; case ConnectionStateConnecting connecting: - ShowStatus(Strings.Resources.Connecting); + ShowState(Strings.Resources.Connecting); break; case ConnectionStateConnectingToProxy connectingToProxy: - ShowStatus(Strings.Resources.ConnectingToProxy); + ShowState(Strings.Resources.ConnectingToProxy); break; case ConnectionStateUpdating updating: - ShowStatus(Strings.Resources.Updating); + ShowState(Strings.Resources.Updating); break; case ConnectionStateReady ready: //ShowStatus(Strings.Resources.Connected); @@ -490,7 +490,7 @@ private void SetProxyVisibility(bool expectBlocking, int proxyId, ConnectionStat Proxy.Glyph = connectionState is ConnectionStateReady && proxyId != 0 ? "\uE916" : "\uE915"; } - private void ShowStatus(string text) + private void ShowState(string text) { Status.IsIndeterminate = true; StatusLabel.Text = text; From 55d57dc04cf89075afab17b70725e61d586db8ca Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Thu, 18 Jun 2020 17:46:29 +0200 Subject: [PATCH 18/45] ;) :D --- Unigram/Unigram/Common/Emoticon.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Unigram/Unigram/Common/Emoticon.cs b/Unigram/Unigram/Common/Emoticon.cs index 6372aa586b..a826f76ac6 100644 --- a/Unigram/Unigram/Common/Emoticon.cs +++ b/Unigram/Unigram/Common/Emoticon.cs @@ -202,7 +202,9 @@ public static class Emoticon { ":-*", "\U0001F61A" }, { "B-)", "\U0001F60E" }, { ":-D", "\U0001F603" }, + { ":D", "\U0001F600" }, { ";-)", "\U0001F609" }, + { ";)", "\U0001F609" }, { ";-P", "\U0001F61C" }, { ":-p", "\U0001F60B" }, { "3(", "\U0001F614" }, From 59b17bab4e8c8caf62d16232b3596b2957793fd5 Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Thu, 18 Jun 2020 17:46:51 +0200 Subject: [PATCH 19/45] PhotoContent improvements --- .../Messages/Content/PhotoContent.xaml.cs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/Unigram/Unigram/Controls/Messages/Content/PhotoContent.xaml.cs b/Unigram/Unigram/Controls/Messages/Content/PhotoContent.xaml.cs index 025b713ff5..5a1973b197 100644 --- a/Unigram/Unigram/Controls/Messages/Content/PhotoContent.xaml.cs +++ b/Unigram/Unigram/Controls/Messages/Content/PhotoContent.xaml.cs @@ -43,7 +43,7 @@ public void UpdateMessage(MessageViewModel message) var small = photo.GetSmall(); var big = photo.GetBig(); - if (small != null && !big.Photo.Local.IsDownloadingCompleted /*&& small.Photo.Id != big.Photo.Id*/) + if (small != null && !big.Photo.Local.IsDownloadingCompleted /*&& small.Photo.Id != big.Photo.Id*/ && !message.IsSecret()) { UpdateThumbnail(message, small.Photo); } @@ -156,7 +156,20 @@ public void UpdateFile(MessageViewModel message, File file) Overlay.Opacity = 0; - Texture.Source = new BitmapImage(new Uri("file:///" + file.Local.Path)); + var width = 0; + var height = 0; + + if (width > MaxWidth || height > MaxHeight) + { + double ratioX = MaxWidth / big.Width; + double ratioY = MaxHeight / big.Height; + double ratio = Math.Max(ratioX, ratioY); + + width = (int)(big.Width * ratio); + height = (int)(big.Height * ratio); + } + + Texture.Source = new BitmapImage(new Uri("file:///" + file.Local.Path)) { DecodePixelWidth = width, DecodePixelHeight = height }; } } } From 4397fa202f63ae5a4d084dea0bf948a31b3529fe Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Thu, 18 Jun 2020 17:47:15 +0200 Subject: [PATCH 20/45] Don't use anonymous handlers in ProgressBarRing --- Unigram/Unigram/Controls/ProgressBarRing.cs | 24 ++++++++++++--------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/Unigram/Unigram/Controls/ProgressBarRing.cs b/Unigram/Unigram/Controls/ProgressBarRing.cs index 6f88da4d03..3d4a89c7cc 100644 --- a/Unigram/Unigram/Controls/ProgressBarRing.cs +++ b/Unigram/Unigram/Controls/ProgressBarRing.cs @@ -109,16 +109,8 @@ private void OnApplyLegacyTemplate() _angleStoryboard.Children.Add(angleAnimation); _angleStoryboard.Completed += OnAngleStoryboardCompleted; - Loaded += (s, args) => - { - _foreverStoryboard.RepeatBehavior = RepeatBehavior.Forever; - _foreverStoryboard.Begin(); - }; - Unloaded += (s, args) => - { - _foreverStoryboard.RepeatBehavior = new RepeatBehavior(1); - _foreverStoryboard.Stop(); - }; + Loaded += OnLoaded; + Unloaded += OnUnloaded; } else { @@ -128,6 +120,18 @@ private void OnApplyLegacyTemplate() OnValueChanged(0, Value); } + private void OnLoaded(object sender, RoutedEventArgs e) + { + _foreverStoryboard.RepeatBehavior = RepeatBehavior.Forever; + _foreverStoryboard.Begin(); + } + + private void OnUnloaded(object sender, RoutedEventArgs e) + { + _foreverStoryboard.RepeatBehavior = new RepeatBehavior(1); + _foreverStoryboard.Stop(); + } + private void OnForeverStoryboardCompleted(object sender, object e) { } From 3d654ee8e583dc4a5ba14128ebe7fd3eb617cf4c Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Thu, 18 Jun 2020 17:48:03 +0200 Subject: [PATCH 21/45] Use NavigatedFrom rather than NavigatingFrom --- .../ViewModels/Settings/SettingsAppearanceViewModel.cs | 4 ++-- .../ViewModels/Settings/SettingsBlockedUsersViewModel.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Unigram/Unigram/ViewModels/Settings/SettingsAppearanceViewModel.cs b/Unigram/Unigram/ViewModels/Settings/SettingsAppearanceViewModel.cs index 4155cdb0f5..d7b8c03052 100644 --- a/Unigram/Unigram/ViewModels/Settings/SettingsAppearanceViewModel.cs +++ b/Unigram/Unigram/ViewModels/Settings/SettingsAppearanceViewModel.cs @@ -50,7 +50,7 @@ public override async Task OnNavigatedToAsync(object parameter, NavigationMode m await base.OnNavigatedToAsync(parameter, mode, state); } - public override Task OnNavigatingFromAsync(NavigatingEventArgs args) + public override Task OnNavigatedFromAsync(IDictionary pageState, bool suspending) { if (UseThreeLinesLayout != Settings.UseThreeLinesLayout) { @@ -58,7 +58,7 @@ public override Task OnNavigatingFromAsync(NavigatingEventArgs args) Aggregator.Publish(new UpdateChatListLayout(UseThreeLinesLayout)); } - return base.OnNavigatingFromAsync(args); + return base.OnNavigatedFromAsync(pageState, suspending); } private string _emojiSet; diff --git a/Unigram/Unigram/ViewModels/Settings/SettingsBlockedUsersViewModel.cs b/Unigram/Unigram/ViewModels/Settings/SettingsBlockedUsersViewModel.cs index 1954c716c3..6dc51cab62 100644 --- a/Unigram/Unigram/ViewModels/Settings/SettingsBlockedUsersViewModel.cs +++ b/Unigram/Unigram/ViewModels/Settings/SettingsBlockedUsersViewModel.cs @@ -37,7 +37,7 @@ public override Task OnNavigatedToAsync(object parameter, NavigationMode mode, I return Task.CompletedTask; } - public override Task OnNavigatingFromAsync(NavigatingEventArgs args) + public override Task OnNavigatedFromAsync(IDictionary pageState, bool suspending) { Aggregator.Unsubscribe(this); return Task.CompletedTask; From b869ece30fbe2d17ba85f3a5d6ebc58f14312e9d Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Thu, 18 Jun 2020 17:49:29 +0200 Subject: [PATCH 22/45] Logger namespace --- Unigram/Unigram/Logs/Logger.cs | 2 +- Unigram/Unigram/Navigation/DispatcherWrapper.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Unigram/Unigram/Logs/Logger.cs b/Unigram/Unigram/Logs/Logger.cs index 1b2b81e612..26ec99da49 100644 --- a/Unigram/Unigram/Logs/Logger.cs +++ b/Unigram/Unigram/Logs/Logger.cs @@ -57,7 +57,7 @@ public static void Info(Target tag, string message, [CallerMemberName] string me [Conditional("DEBUG")] private static void Log(Target tag, LogLevel level, Type type, string message, string member, string filePath, int line) { - Logs.Log.Write(LogHelper.CreateEntryWithoutType(DateTime.Now, level, member, line, message)); + //Logs.Log.Write(LogHelper.CreateEntryWithoutType(DateTime.Now, level, member, line, message)); System.Diagnostics.Debug.WriteLine(LogHelper.CreateEntryWithoutType(DateTime.Now, level, member, line, message)); } diff --git a/Unigram/Unigram/Navigation/DispatcherWrapper.cs b/Unigram/Unigram/Navigation/DispatcherWrapper.cs index 62904cf1f1..1f18b0b534 100644 --- a/Unigram/Unigram/Navigation/DispatcherWrapper.cs +++ b/Unigram/Unigram/Navigation/DispatcherWrapper.cs @@ -12,8 +12,8 @@ public class DispatcherWrapper : IDispatcherWrapper #region Debug [Conditional("DEBUG")] - static void DebugWrite(string text = null, Services.Logging.Severities severity = Services.Logging.Severities.Template10, [CallerMemberName] string caller = null) => - Services.Logging.LoggingService.WriteLine(text, severity, caller: $"DispatcherWrapper.{caller}"); + static void DebugWrite(string text = null, Unigram.Services.Logging.Severities severity = Unigram.Services.Logging.Severities.Template10, [CallerMemberName] string caller = null) => + Unigram.Services.Logging.LoggingService.WriteLine(text, severity, caller: $"DispatcherWrapper.{caller}"); #endregion From b4f213e733e507a79bb3cd47ba85b1ec841d9bfb Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Thu, 18 Jun 2020 17:50:11 +0200 Subject: [PATCH 23/45] Removed unused method --- .../Controls/Messages/MessageReference.xaml.cs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/Unigram/Unigram/Controls/Messages/MessageReference.xaml.cs b/Unigram/Unigram/Controls/Messages/MessageReference.xaml.cs index f3fb5206b2..d0e87b3214 100644 --- a/Unigram/Unigram/Controls/Messages/MessageReference.xaml.cs +++ b/Unigram/Unigram/Controls/Messages/MessageReference.xaml.cs @@ -827,19 +827,6 @@ private bool SetUnsupportedMediaTemplate(MessageViewModel message, string title) return true; } - private bool SetUnsupportedTemplate(MessageViewModel message, string title) - { - Visibility = Visibility.Collapsed; - - if (ThumbRoot != null) - ThumbRoot.Visibility = Visibility.Collapsed; - - TitleLabel.Text = string.Empty; - ServiceLabel.Text = string.Empty; - MessageLabel.Text = string.Empty; - return false; - } - #endregion private string GetFromLabel(MessageViewModel message, string title) From 85a61d459d833db8eb28ade0eb250fa20e45d798 Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Thu, 18 Jun 2020 17:59:43 +0200 Subject: [PATCH 24/45] OnNavigatingFrom must be syncronous --- Unigram/Unigram/Navigation/Deferral.cs | 42 ------------- .../Navigation/Services/FrameFacade.cs | 6 +- .../Unigram/Navigation/Services/INavigable.cs | 2 +- .../Services/NavigatingEventArgs.cs | 9 +-- .../Navigation/Services/NavigationService.cs | 10 ++-- Unigram/Unigram/Navigation/ViewModelBase.cs | 4 +- Unigram/Unigram/Unigram.csproj | 1 - Unigram/Unigram/ViewModels/DialogViewModel.cs | 59 ++----------------- .../ViewModels/TLMultipleViewModelBase.cs | 10 ++-- Unigram/Unigram/ViewModels/TLViewModelBase.cs | 2 - Unigram/Unigram/Views/ChatView.xaml.cs | 8 +-- 11 files changed, 26 insertions(+), 127 deletions(-) delete mode 100644 Unigram/Unigram/Navigation/Deferral.cs diff --git a/Unigram/Unigram/Navigation/Deferral.cs b/Unigram/Unigram/Navigation/Deferral.cs deleted file mode 100644 index 9ab602b84c..0000000000 --- a/Unigram/Unigram/Navigation/Deferral.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Threading.Tasks; - -namespace Unigram.Navigation -{ - public sealed class DeferralManager - { - int _count = 0; - TaskCompletionSource _completed = new TaskCompletionSource(); - public Deferral GetDeferral() - { - System.Threading.Interlocked.Increment(ref _count); - return new Deferral(() => - { - var count = System.Threading.Interlocked.Decrement(ref _count); - if (count == 0) _completed.SetResult(null); - }); - } - public bool IsComplete() - { - return WaitForDeferralsAsync().IsCompleted; - } - public Task WaitForDeferralsAsync() - { - if (_count == 0) return Task.CompletedTask; - return _completed.Task; - } - } - - public sealed class Deferral - { - private Action _callback; - public Deferral(Action callback) - { - _callback = callback; - } - public void Complete() - { - _callback.Invoke(); - } - } -} diff --git a/Unigram/Unigram/Navigation/Services/FrameFacade.cs b/Unigram/Unigram/Navigation/Services/FrameFacade.cs index baf0589cd7..1bae5f9686 100644 --- a/Unigram/Unigram/Navigation/Services/FrameFacade.cs +++ b/Unigram/Unigram/Navigation/Services/FrameFacade.cs @@ -296,7 +296,7 @@ void FacadeNavigatedEventHandler(object sender, Windows.UI.Xaml.Navigation.Navig add { if (!_navigatingEventHandlers.Contains(value)) _navigatingEventHandlers.Add(value); } remove { if (_navigatingEventHandlers.Contains(value)) _navigatingEventHandlers.Remove(value); } } - private async void FacadeNavigatingCancelEventHandler(object sender, NavigatingCancelEventArgs e) + private void FacadeNavigatingCancelEventHandler(object sender, NavigatingCancelEventArgs e) { DebugWrite(); @@ -309,13 +309,11 @@ private async void FacadeNavigatingCancelEventHandler(object sender, NavigatingC { throw new Exception("Your parameter must be serializable. If it isn't, then use SessionState.", ex); } - var deferral = new DeferralManager(); - var args = new NavigatingEventArgs(deferral, e, Content as Page, e.SourcePageType, parameter, e.Parameter); + var args = new NavigatingEventArgs(e, Content as Page, e.SourcePageType, parameter, e.Parameter); if (NavigationModeHint != NavigationMode.New) args.NavigationMode = NavigationModeHint; NavigationModeHint = NavigationMode.New; _navigatingEventHandlers.ForEach(x => x(this, args)); - await deferral.WaitForDeferralsAsync().ConfigureAwait(false); e.Cancel = args.Cancel; } } diff --git a/Unigram/Unigram/Navigation/Services/INavigable.cs b/Unigram/Unigram/Navigation/Services/INavigable.cs index 76171a65af..553c28c14e 100644 --- a/Unigram/Unigram/Navigation/Services/INavigable.cs +++ b/Unigram/Unigram/Navigation/Services/INavigable.cs @@ -9,7 +9,7 @@ public interface INavigable { Task OnNavigatedToAsync(object parameter, NavigationMode mode, IDictionary state); Task OnNavigatedFromAsync(IDictionary suspensionState, bool suspending); - Task OnNavigatingFromAsync(NavigatingEventArgs args); + void OnNavigatingFrom(NavigatingEventArgs args); INavigationService NavigationService { get; set; } IDispatcherWrapper Dispatcher { get; set; } IDictionary SessionState { get; set; } diff --git a/Unigram/Unigram/Navigation/Services/NavigatingEventArgs.cs b/Unigram/Unigram/Navigation/Services/NavigatingEventArgs.cs index 3fcda475d5..7494fadc3b 100644 --- a/Unigram/Unigram/Navigation/Services/NavigatingEventArgs.cs +++ b/Unigram/Unigram/Navigation/Services/NavigatingEventArgs.cs @@ -7,15 +7,12 @@ namespace Unigram.Navigation.Services // DOCS: https://github.com/Windows-XAML/Template10/wiki/Docs-%7C-NavigationService public class NavigatingEventArgs : NavigatedEventArgs { - DeferralManager Manager; - public Deferral GetDeferral() => Manager.GetDeferral(); - - public NavigatingEventArgs(DeferralManager manager) : base() + public NavigatingEventArgs() { - Manager = manager; + } - public NavigatingEventArgs(DeferralManager manager, NavigatingCancelEventArgs e, Page page, Type targetPageType, object parameter, object targetPageParameter) : this(manager) + public NavigatingEventArgs(NavigatingCancelEventArgs e, Page page, Type targetPageType, object parameter, object targetPageParameter) { NavigationMode = e.NavigationMode; PageType = e.SourcePageType; diff --git a/Unigram/Unigram/Navigation/Services/NavigationService.cs b/Unigram/Unigram/Navigation/Services/NavigationService.cs index 6793d29954..2da07c82c6 100644 --- a/Unigram/Unigram/Navigation/Services/NavigationService.cs +++ b/Unigram/Unigram/Navigation/Services/NavigationService.cs @@ -68,7 +68,7 @@ public NavigationService(Frame frame, int session, string id) if (dataContext != null) { // allow the viewmodel to cancel navigation - e.Cancel = !(await NavigatingFromAsync(page, e.PageType, e.Parameter, dataContext, false, e.NavigationMode)); + e.Cancel = !NavigatingFrom(page, e.PageType, e.Parameter, dataContext, false, e.NavigationMode); if (!e.Cancel) { await NavigateFromAsync(page, dataContext, false).ConfigureAwait(false); @@ -117,7 +117,7 @@ private INavigable ResolveForPage(Page page) } // before navigate (cancellable) - async Task NavigatingFromAsync(Page page, Type targetPageType, object targetPageParameter, INavigable dataContext, bool suspending, NavigationMode mode) + bool NavigatingFrom(Page page, Type targetPageType, object targetPageParameter, INavigable dataContext, bool suspending, NavigationMode mode) { DebugWrite($"Suspending: {suspending}"); @@ -125,8 +125,7 @@ async Task NavigatingFromAsync(Page page, Type targetPageType, object targ dataContext.Dispatcher = this.GetDispatcherWrapper(); dataContext.SessionState = BootStrapper.Current.SessionState; - var deferral = new DeferralManager(); - var args = new NavigatingEventArgs(deferral) + var args = new NavigatingEventArgs { NavigationMode = mode, PageType = FrameFacadeInternal.CurrentPageType, @@ -135,8 +134,7 @@ async Task NavigatingFromAsync(Page page, Type targetPageType, object targ TargetPageType = targetPageType, TargetPageParameter = targetPageParameter }; - await deferral.WaitForDeferralsAsync(); - await dataContext.OnNavigatingFromAsync(args).ConfigureAwait(false); + dataContext.OnNavigatingFrom(args); return !args.Cancel; } diff --git a/Unigram/Unigram/Navigation/ViewModelBase.cs b/Unigram/Unigram/Navigation/ViewModelBase.cs index 55e21a020f..593de5648c 100644 --- a/Unigram/Unigram/Navigation/ViewModelBase.cs +++ b/Unigram/Unigram/Navigation/ViewModelBase.cs @@ -19,9 +19,9 @@ public virtual Task OnNavigatedFromAsync(IDictionary pageState, return Task.CompletedTask; } - public virtual Task OnNavigatingFromAsync(NavigatingEventArgs args) + public virtual void OnNavigatingFrom(NavigatingEventArgs args) { - return Task.CompletedTask; + } [JsonIgnore] diff --git a/Unigram/Unigram/Unigram.csproj b/Unigram/Unigram/Unigram.csproj index aabceffcf5..5722abc420 100644 --- a/Unigram/Unigram/Unigram.csproj +++ b/Unigram/Unigram/Unigram.csproj @@ -523,7 +523,6 @@ - diff --git a/Unigram/Unigram/ViewModels/DialogViewModel.cs b/Unigram/Unigram/ViewModels/DialogViewModel.cs index e7af09388d..cedd816b6d 100644 --- a/Unigram/Unigram/ViewModels/DialogViewModel.cs +++ b/Unigram/Unigram/ViewModels/DialogViewModel.cs @@ -944,53 +944,6 @@ private async void NextMentionExecute() } } } - - //var dialog = _dialog; - //if (dialog == null) - //{ - // return; - //} - - //var responsez = await LegacyService.GetUnreadMentionsAsync(_peer, 0, dialog.UnreadMentionsCount - 1, 1, 0, 0); - //if (responsez.IsSucceeded && responsez.Result is ITLMessages result) - //{ - // var count = 0; - // if (responsez.Result is TLMessagesChannelMessages channelMessages) - // { - // count = channelMessages.Count; - // } - - // dialog.UnreadMentionsCount = count; - // dialog.RaisePropertyChanged(() => dialog.UnreadMentionsCount); - - // //if (response.Result.Messages.IsEmpty()) - // //{ - // // dialog.UnreadMentionsCount = 0; - // // dialog.RaisePropertyChanged(() => dialog.UnreadMentionsCount); - // // return; - // //} - - // var commonMessage = result.Messages.FirstOrDefault() as TLMessageCommonBase; - // if (commonMessage == null) - // { - // return; - // } - - // commonMessage.IsMediaUnread = false; - // commonMessage.RaisePropertyChanged(() => commonMessage.IsMediaUnread); - - // // DO NOT AWAIT - // LoadMessageSliceAsync(null, commonMessage.Id); - - // if (With is TLChannel channel) - // { - // await LegacyService.ReadMessageContentsAsync(channel.ToInputChannel(), new TLVector { commonMessage.Id }); - // } - // else - // { - // await LegacyService.ReadMessageContentsAsync(new TLVector { commonMessage.Id }); - // } - //} } public RelayCommand PreviousSliceCommand { get; } @@ -1898,7 +1851,7 @@ int TodayDate(int hour, int minute) ProtoService.Send(new GetChatAdministrators(chat.Id), result => { - if (result is Telegram.Td.Api.ChatAdministrators users) + if (result is ChatAdministrators users) { _admins[chat.Id] = users.Administrators; } @@ -1923,7 +1876,7 @@ int TodayDate(int hour, int minute) ProtoService.Send(new GetChatAdministrators(chat.Id), result => { - if (result is Telegram.Td.Api.ChatAdministrators users) + if (result is ChatAdministrators users) { _admins[chat.Id] = users.Administrators; } @@ -1950,14 +1903,14 @@ int TodayDate(int hour, int minute) // } //} - public override Task OnNavigatingFromAsync(NavigatingEventArgs args) + public override void OnNavigatingFrom(NavigatingEventArgs args) { Aggregator.Unsubscribe(this); var chat = _chat; if (chat == null) { - return Task.CompletedTask; + return; } #if !DEBUG @@ -1979,7 +1932,7 @@ public override Task OnNavigatingFromAsync(NavigatingEventArgs args) Logs.Logger.Debug(Logs.Target.Chat, string.Format("{0} - Removing scrolling position, generic reason", chat.Id)); - return Task.CompletedTask; + return; } var panel = field.ItemsPanelRoot as ItemsStackPanel; @@ -2038,8 +1991,6 @@ public override Task OnNavigatingFromAsync(NavigatingEventArgs args) { Dispatcher.Dispatch(SaveDraft); } - - return Task.CompletedTask; } private void ShowSwitchInline(IDictionary state) diff --git a/Unigram/Unigram/ViewModels/TLMultipleViewModelBase.cs b/Unigram/Unigram/ViewModels/TLMultipleViewModelBase.cs index d9db854c39..551ba31106 100644 --- a/Unigram/Unigram/ViewModels/TLMultipleViewModelBase.cs +++ b/Unigram/Unigram/ViewModels/TLMultipleViewModelBase.cs @@ -72,19 +72,19 @@ public override INavigationService NavigationService public override async Task OnNavigatedFromAsync(IDictionary pageState, bool suspending) { await base.OnNavigatedFromAsync(pageState, suspending); - await Task.WhenAll(Children.ToList().Select(x => x.OnNavigatedFromAsync(pageState, suspending))); + await Task.WhenAll(Children.Select(x => x.OnNavigatedFromAsync(pageState, suspending))); } public override async Task OnNavigatedToAsync(object parameter, NavigationMode mode, IDictionary state) { await base.OnNavigatedToAsync(parameter, mode, state); - await Task.WhenAll(Children.ToList().Select(x => x.OnNavigatedToAsync(parameter, mode, state))); + await Task.WhenAll(Children.Select(x => x.OnNavigatedToAsync(parameter, mode, state))); } - public override async Task OnNavigatingFromAsync(NavigatingEventArgs args) + public override void OnNavigatingFrom(NavigatingEventArgs args) { - await base.OnNavigatingFromAsync(args); - await Task.WhenAll(Children.ToList().Select(x => x.OnNavigatingFromAsync(args))); + base.OnNavigatingFrom(args); + Children.ForEach(x => x.OnNavigatingFrom(args)); } } diff --git a/Unigram/Unigram/ViewModels/TLViewModelBase.cs b/Unigram/Unigram/ViewModels/TLViewModelBase.cs index e9e28ddd6b..fe4fb42bad 100644 --- a/Unigram/Unigram/ViewModels/TLViewModelBase.cs +++ b/Unigram/Unigram/ViewModels/TLViewModelBase.cs @@ -14,8 +14,6 @@ public class TLViewModelBase : ViewModelBase private readonly ISettingsService _settingsService; private readonly IEventAggregator _aggregator; - private readonly IDispatcherWrapper _dispatcher; - public TLViewModelBase(IProtoService protoService, ICacheService cacheService, ISettingsService settingsService, IEventAggregator aggregator) { _protoService = protoService; diff --git a/Unigram/Unigram/Views/ChatView.xaml.cs b/Unigram/Unigram/Views/ChatView.xaml.cs index 7a6431ed8e..b4492b7b14 100644 --- a/Unigram/Unigram/Views/ChatView.xaml.cs +++ b/Unigram/Unigram/Views/ChatView.xaml.cs @@ -489,12 +489,13 @@ public void Dispose() { if (ViewModel != null) { - ViewModel.Items.Clear(); - ViewModel.PropertyChanged -= OnPropertyChanged; ViewModel.Items.AttachChanged = null; //ViewModel.Items.CollectionChanged -= OnCollectionChanged; + //ViewModel.Items.Dispose(); + //ViewModel.Items.Clear(); + ViewModel.Delegate = null; ViewModel.TextField = null; ViewModel.ListField = null; @@ -529,6 +530,7 @@ public void Activate() UpdateTextAreaRadius(); + TextField.IsReplaceEmojiEnabled = ViewModel.Settings.IsReplaceEmojiEnabled; TextField.IsTextPredictionEnabled = SettingsService.Current.AutocorrectWords; TextField.IsSpellCheckEnabled = SettingsService.Current.HighlightWords; TextField.Focus(FocusState.Programmatic); @@ -3725,8 +3727,6 @@ private void UpdateTextAreaRadius() Messages.Margin = new Thickness(0, 0, 0, -radius); Messages.Padding = new Thickness(0, 0, 0, radius + 6); - - TextField.IsReplaceEmojiEnabled = ViewModel.Settings.IsReplaceEmojiEnabled; } public void UpdateAutocomplete(Chat chat, IAutocompleteCollection collection) From 9915c5eaa43cabc2aff9da229a976311f8196a3b Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Thu, 18 Jun 2020 19:03:30 +0200 Subject: [PATCH 25/45] Removed NavigateAsync --- .../Navigation/Services/INavigationService.cs | 7 ++----- .../Navigation/Services/NavigationService.cs | 21 +++---------------- 2 files changed, 5 insertions(+), 23 deletions(-) diff --git a/Unigram/Unigram/Navigation/Services/INavigationService.cs b/Unigram/Unigram/Navigation/Services/INavigationService.cs index c6c1681a47..f20dc08505 100644 --- a/Unigram/Unigram/Navigation/Services/INavigationService.cs +++ b/Unigram/Unigram/Navigation/Services/INavigationService.cs @@ -17,11 +17,8 @@ public interface INavigationService object Content { get; } - void Navigate(Type page, object parameter = null, IDictionary state = null, NavigationTransitionInfo infoOverride = null); - void Navigate(T key, object parameter = null, IDictionary state = null, NavigationTransitionInfo infoOverride = null) where T : struct, IConvertible; - - Task NavigateAsync(Type page, object parameter = null, IDictionary state = null, NavigationTransitionInfo infoOverride = null); - Task NavigateAsync(T key, object parameter = null, IDictionary state = null, NavigationTransitionInfo infoOverride = null) where T : struct, IConvertible; + bool Navigate(Type page, object parameter = null, IDictionary state = null, NavigationTransitionInfo infoOverride = null); + bool Navigate(T key, object parameter = null, IDictionary state = null, NavigationTransitionInfo infoOverride = null) where T : struct, IConvertible; bool CanGoBack { get; } bool CanGoForward { get; } diff --git a/Unigram/Unigram/Navigation/Services/NavigationService.cs b/Unigram/Unigram/Navigation/Services/NavigationService.cs index 2da07c82c6..30bfd9b516 100644 --- a/Unigram/Unigram/Navigation/Services/NavigationService.cs +++ b/Unigram/Unigram/Navigation/Services/NavigationService.cs @@ -209,7 +209,7 @@ public Task OpenAsync(Func content, object param return viewService.OpenAsync(content, parameter); } - public async Task NavigateAsync(Type page, object parameter = null, IDictionary state = null, NavigationTransitionInfo infoOverride = null) + public bool Navigate(Type page, object parameter = null, IDictionary state = null, NavigationTransitionInfo infoOverride = null) { DebugWrite($"Page: {page}, Parameter: {parameter}, NavigationTransitionInfo: {infoOverride}"); @@ -254,13 +254,6 @@ public async Task NavigateAsync(Type page, object parameter = null, IDicti return FrameFacadeInternal.Navigate(page, parameter, infoOverride); } - public void Navigate(Type page, object parameter = null, IDictionary state = null, NavigationTransitionInfo infoOverride = null) - { - DebugWrite($"Page: {page}, Parameter: {parameter}, NavigationTransitionInfo: {infoOverride}"); - - NavigateAsync(page, parameter, state, infoOverride).ConfigureAwait(false).GetAwaiter().GetResult(); - } - /// /// Navigate allows developers to navigate using a /// page key instead of the view type.This is accomplished by @@ -283,7 +276,7 @@ public void Navigate(Type page, object parameter = null, IDictionary /// T must be the same custom Enum used with BootStrapper.PageKeys() - public async Task NavigateAsync(T key, object parameter = null, IDictionary state = null, NavigationTransitionInfo infoOverride = null) + public bool Navigate(T key, object parameter = null, IDictionary state = null, NavigationTransitionInfo infoOverride = null) where T : struct, IConvertible { DebugWrite($"Key: {key}, Parameter: {parameter}, NavigationTransitionInfo: {infoOverride}"); @@ -295,15 +288,7 @@ public async Task NavigateAsync(T key, object parameter = null, IDictio var page = keys[key]; - return await NavigateAsync(page, parameter, state, infoOverride).ConfigureAwait(false); - } - - public void Navigate(T key, object parameter = null, IDictionary state = null, NavigationTransitionInfo infoOverride = null) - where T : struct, IConvertible - { - DebugWrite($"Key: {key}, Parameter: {parameter}, NavigationTransitionInfo: {infoOverride}"); - - NavigateAsync(key, parameter, state, infoOverride).ConfigureAwait(false).GetAwaiter().GetResult(); + return Navigate(page, parameter, state, infoOverride); } public ISerializationService SerializationService { get; set; } From ab137fab2118334c75f250ccfbd354f9dbe22a4f Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Fri, 19 Jun 2020 12:39:56 +0200 Subject: [PATCH 26/45] NavigationService refactoring: - Do not serialize navigation parameters - Use internal cache key as chat navigation parameter --- Unigram/Unigram/App.xaml.cs | 2 - Unigram/Unigram/Common/NavigationService.cs | 23 +-- Unigram/Unigram/Controls/MasterDetailView.cs | 1 - Unigram/Unigram/Controls/OverlayPage.cs | 19 +- Unigram/Unigram/Navigation/BootStrapper.cs | 16 -- .../Navigation/Services/FrameFacade.cs | 93 +++++---- .../Navigation/Services/INavigationService.cs | 3 +- .../Navigation/Services/NavigatedEventArgs.cs | 8 +- .../Services/NavigatingEventArgs.cs | 4 +- .../Navigation/Services/NavigationService.cs | 188 ++++++----------- .../Navigation/Services/NavigationState.cs | 12 ++ .../Serialization/ISerializationService.cs | 25 --- .../Serialization/JsonSerializationService.cs | 139 ------------- .../Serialization/SerializationService.cs | 8 - .../Services/TLSerializationService.cs | 193 ------------------ Unigram/Unigram/Unigram.csproj | 5 +- Unigram/Unigram/ViewModels/ChatsViewModel.cs | 3 +- .../ViewModels/DialogViewModel.Messages.cs | 2 +- .../Unigram/ViewModels/ProfileViewModel.cs | 5 +- .../SupergroupAddRestrictedViewModel.cs | 3 +- .../SupergroupEditAdministratorViewModel.cs | 11 +- .../SupergroupEditRestrictedViewModel.cs | 11 +- .../Supergroups/SupergroupMembersViewModel.cs | 5 +- Unigram/Unigram/Views/GamePage.xaml.cs | 14 +- Unigram/Unigram/Views/Host/RootPage.xaml.cs | 1 - Unigram/Unigram/Views/IdenticonPage.xaml.cs | 4 +- Unigram/Unigram/Views/InstantPage.xaml.cs | 104 +--------- Unigram/Unigram/Views/MainPage.xaml.cs | 24 +-- .../Views/Settings/SettingsThemePage.xaml.cs | 2 +- .../SupergroupAddAdministratorPage.xaml.cs | 7 +- .../SupergroupAddRestrictedPage.xaml.cs | 7 +- .../SupergroupAdministratorsPage.xaml.cs | 4 +- .../Supergroups/SupergroupBannedPage.xaml.cs | 3 +- .../SupergroupPermissionsPage.xaml | 2 + .../SupergroupPermissionsPage.xaml.cs | 4 +- 35 files changed, 206 insertions(+), 749 deletions(-) create mode 100644 Unigram/Unigram/Navigation/Services/NavigationState.cs delete mode 100644 Unigram/Unigram/Services/Serialization/ISerializationService.cs delete mode 100644 Unigram/Unigram/Services/Serialization/JsonSerializationService.cs delete mode 100644 Unigram/Unigram/Services/Serialization/SerializationService.cs delete mode 100644 Unigram/Unigram/Services/TLSerializationService.cs diff --git a/Unigram/Unigram/App.xaml.cs b/Unigram/Unigram/App.xaml.cs index 5e4e24c4ca..f282bb367e 100644 --- a/Unigram/Unigram/App.xaml.cs +++ b/Unigram/Unigram/App.xaml.cs @@ -388,7 +388,6 @@ public override UIElement CreateRootElement(IActivatedEventArgs e) { var navigationFrame = new Frame { FlowDirection = ApiInfo.FlowDirection }; var navigationService = NavigationServiceFactory(BackButton.Ignore, ExistingContent.Include, navigationFrame, sessionId, $"Main{sessionId}", false) as NavigationService; - navigationService.SerializationService = TLSerializationService.Current; return navigationFrame; } @@ -396,7 +395,6 @@ public override UIElement CreateRootElement(IActivatedEventArgs e) { var navigationFrame = new Frame(); var navigationService = NavigationServiceFactory(BackButton.Ignore, ExistingContent.Include, navigationFrame, sessionId, $"{sessionId}", true) as NavigationService; - navigationService.SerializationService = TLSerializationService.Current; return new RootPage(navigationService) { FlowDirection = ApiInfo.FlowDirection }; } diff --git a/Unigram/Unigram/Common/NavigationService.cs b/Unigram/Unigram/Common/NavigationService.cs index 5200b2f032..da3ce0bbde 100644 --- a/Unigram/Unigram/Common/NavigationService.cs +++ b/Unigram/Unigram/Common/NavigationService.cs @@ -229,19 +229,6 @@ public static void RemovePeerFromStack(this INavigationService service, long tar } } - public static bool IsPeerActive(this INavigationService service, long chat) - { - if (service.CurrentPageType == typeof(ChatPage)) - { - if (TryGetPeerFromParameter(service, service.CurrentPageParam, out long chatId)) - { - return chat == chatId; - } - } - - return false; - } - public static long GetPeerFromBackStack(this INavigationService service) { if (service.CurrentPageType == typeof(ChatPage)) @@ -269,16 +256,16 @@ public static long GetPeerFromBackStack(this INavigationService service) public static bool TryGetPeerFromParameter(this INavigationService service, object parameter, out long chatId) { - if (parameter is string) - { - parameter = TLSerializationService.Current.Deserialize((string)parameter); - } - if (parameter is long) { chatId = (long)parameter; return true; } + else if (parameter is string cacheKey && service.CacheKeyToChatId.TryGetValue(cacheKey, out long value)) + { + chatId = value; + return true; + } chatId = 0; return false; diff --git a/Unigram/Unigram/Controls/MasterDetailView.cs b/Unigram/Unigram/Controls/MasterDetailView.cs index 7cd607e672..7af2448c6f 100644 --- a/Unigram/Unigram/Controls/MasterDetailView.cs +++ b/Unigram/Unigram/Controls/MasterDetailView.cs @@ -42,7 +42,6 @@ public void Initialize(string key, Frame parent, int session) if (service == null) { service = BootStrapper.Current.NavigationServiceFactory(BootStrapper.BackButton.Ignore, BootStrapper.ExistingContent.Exclude, session, key + session, false) as NavigationService; - service.SerializationService = TLSerializationService.Current; service.Frame.DataContext = new object(); service.FrameFacade.BackRequested += OnBackRequested; } diff --git a/Unigram/Unigram/Controls/OverlayPage.cs b/Unigram/Unigram/Controls/OverlayPage.cs index b1ef72b57f..227ddb62db 100644 --- a/Unigram/Unigram/Controls/OverlayPage.cs +++ b/Unigram/Unigram/Controls/OverlayPage.cs @@ -371,6 +371,8 @@ public void GoBack(NavigationTransitionInfo infoOverride = null) public int SessionId => throw new NotImplementedException(); + public IDictionary CacheKeyToChatId => throw new NotImplementedException(); + public event TypedEventHandler AfterRestoreSavedNavigation; public void ClearCache(bool removeCachedPagesInBackStack = false) @@ -393,22 +395,7 @@ public Task LoadAsync() throw new NotImplementedException(); } - public void Navigate(Type page, object parameter = null, IDictionary state = null, NavigationTransitionInfo infoOverride = null) - { - throw new NotImplementedException(); - } - - public void Navigate(T key, object parameter = null, IDictionary state = null, NavigationTransitionInfo infoOverride = null) where T : struct, IConvertible - { - throw new NotImplementedException(); - } - - public Task NavigateAsync(Type page, object parameter = null, IDictionary state = null, NavigationTransitionInfo infoOverride = null) - { - throw new NotImplementedException(); - } - - public Task NavigateAsync(T key, object parameter = null, IDictionary state = null, NavigationTransitionInfo infoOverride = null) where T : struct, IConvertible + public bool Navigate(Type page, object parameter = null, IDictionary state = null, NavigationTransitionInfo infoOverride = null) { throw new NotImplementedException(); } diff --git a/Unigram/Unigram/Navigation/BootStrapper.cs b/Unigram/Unigram/Navigation/BootStrapper.cs index 1b8158e991..e352e7ab39 100644 --- a/Unigram/Unigram/Navigation/BootStrapper.cs +++ b/Unigram/Unigram/Navigation/BootStrapper.cs @@ -782,22 +782,6 @@ public static AdditionalKinds DetermineStartCause(IActivatedEventArgs args) } } - private object _PageKeys; - // T must be a custom Enum - public Dictionary PageKeys() - where T : struct, IConvertible - { - if (!typeof(T).GetTypeInfo().IsEnum) - { - throw new ArgumentException("T must be an enumerated type"); - } - if (_PageKeys != null && _PageKeys is Dictionary) - { - return _PageKeys as Dictionary; - } - return (_PageKeys = new Dictionary()) as Dictionary; - } - public class LifecycleLogic { public async Task AutoRestoreAsync(ILaunchActivatedEventArgs e, INavigationService nav) diff --git a/Unigram/Unigram/Navigation/Services/FrameFacade.cs b/Unigram/Unigram/Navigation/Services/FrameFacade.cs index 1bae5f9686..1d24de65ad 100644 --- a/Unigram/Unigram/Navigation/Services/FrameFacade.cs +++ b/Unigram/Unigram/Navigation/Services/FrameFacade.cs @@ -3,7 +3,7 @@ using System.ComponentModel; using System.Diagnostics; using System.Runtime.CompilerServices; -using Unigram.Services.Serialization; +using Unigram.Views; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Media.Animation; @@ -26,8 +26,8 @@ internal FrameFacade(NavigationService navigationService, Frame frame, string id { NavigationService = navigationService; Frame = frame; - frame.Navigated += (s, e) => FacadeNavigatedEventHandler(s, e); - frame.Navigating += (s, e) => FacadeNavigatingCancelEventHandler(s, e); + frame.Navigated += FacadeNavigatedEventHandler; + frame.Navigating += FacadeNavigatingCancelEventHandler; // setup animations var t = new NavigationThemeTransition @@ -40,6 +40,33 @@ internal FrameFacade(NavigationService navigationService, Frame frame, string id FrameId = id; } + public void RaiseNavigated(long chatId) + { + if (Content is ChatPage) + { + NavigationService.CacheKeyToChatId[CurrentPageCacheKey] = chatId; + CurrentPageParam = chatId; + + var args = new NavigatedEventArgs + { + NavigationMode = NavigationMode.Refresh, + SourcePageType = CurrentPageType, + Parameter = CurrentPageParam, + Content = Frame.Content as Page + }; + + foreach (var handler in _navigatedEventHandlers) + { + if (handler.Target is INavigationService) + { + continue; + } + + handler(Frame, args); + } + } + } + public event EventHandler BackRequested; public void RaiseBackRequested(HandledEventArgs args) { @@ -138,24 +165,6 @@ public bool Navigate(Type page, object parameter, NavigationTransitionInfo infoO } } - internal ISerializationService SerializationService => NavigationService.SerializationService; - - [Obsolete("Use NavigationService.NavigationState instead")] - public void SetNavigationState(string state) - { - DebugWrite($"State {state}"); - - Frame.SetNavigationState(state); - } - - [Obsolete("Use NavigationService.NavigationState instead")] - public string GetNavigationState() - { - DebugWrite(); - - return Frame.GetNavigationState(); - } - public int BackStackDepth => Frame.BackStackDepth; public bool CanGoBack => Frame.CanGoBack; @@ -260,11 +269,7 @@ public void GoForward() public object CurrentPageParam { get; internal set; } - public object GetValue(DependencyProperty dp) => Frame.GetValue(dp); - - public void SetValue(DependencyProperty dp, object value) { Frame.SetValue(dp, value); } - - public void ClearValue(DependencyProperty dp) { Frame.ClearValue(dp); } + public string CurrentPageCacheKey { get; private set; } #endregion @@ -279,14 +284,25 @@ void FacadeNavigatedEventHandler(object sender, Windows.UI.Xaml.Navigation.Navig DebugWrite(); CurrentPageType = e.SourcePageType; - CurrentPageParam = SerializationService.Deserialize(e.Parameter?.ToString()); + CurrentPageParam = e.Parameter; + CurrentPageCacheKey = null; + + if (e.SourcePageType == typeof(ChatPage) && CurrentPageParam is string cacheKey) + { + CurrentPageParam = NavigationService.CacheKeyToChatId[cacheKey]; + CurrentPageCacheKey = cacheKey; + } + var args = new NavigatedEventArgs(e, Content as Page); + if (NavigationModeHint != NavigationMode.New) args.NavigationMode = NavigationModeHint; + NavigationModeHint = NavigationMode.New; + foreach (var handler in _navigatedEventHandlers) { - handler(this, args); + handler(Frame, args); } } @@ -300,22 +316,25 @@ private void FacadeNavigatingCancelEventHandler(object sender, NavigatingCancelE { DebugWrite(); - object parameter = null; - try + var parameter = e.Parameter; + if (parameter is string cacheKey && e.SourcePageType == typeof(ChatPage)) { - parameter = SerializationService.Deserialize(e.Parameter?.ToString()); - } - catch (Exception ex) - { - throw new Exception("Your parameter must be serializable. If it isn't, then use SessionState.", ex); + parameter = NavigationService.CacheKeyToChatId[cacheKey]; } + var args = new NavigatingEventArgs(e, Content as Page, e.SourcePageType, parameter, e.Parameter); + if (NavigationModeHint != NavigationMode.New) args.NavigationMode = NavigationModeHint; + NavigationModeHint = NavigationMode.New; - _navigatingEventHandlers.ForEach(x => x(this, args)); + + foreach (var handler in _navigatingEventHandlers) + { + handler(Frame, args); + } + e.Cancel = args.Cancel; } } - } diff --git a/Unigram/Unigram/Navigation/Services/INavigationService.cs b/Unigram/Unigram/Navigation/Services/INavigationService.cs index f20dc08505..4ac67da527 100644 --- a/Unigram/Unigram/Navigation/Services/INavigationService.cs +++ b/Unigram/Unigram/Navigation/Services/INavigationService.cs @@ -18,13 +18,14 @@ public interface INavigationService object Content { get; } bool Navigate(Type page, object parameter = null, IDictionary state = null, NavigationTransitionInfo infoOverride = null); - bool Navigate(T key, object parameter = null, IDictionary state = null, NavigationTransitionInfo infoOverride = null) where T : struct, IConvertible; bool CanGoBack { get; } bool CanGoForward { get; } string NavigationState { get; set; } + IDictionary CacheKeyToChatId { get; } + void Refresh(); void Refresh(object param); diff --git a/Unigram/Unigram/Navigation/Services/NavigatedEventArgs.cs b/Unigram/Unigram/Navigation/Services/NavigatedEventArgs.cs index 0619ccc278..52e728814b 100644 --- a/Unigram/Unigram/Navigation/Services/NavigatedEventArgs.cs +++ b/Unigram/Unigram/Navigation/Services/NavigatedEventArgs.cs @@ -10,15 +10,15 @@ public class NavigatedEventArgs : EventArgs public NavigatedEventArgs() { } public NavigatedEventArgs(NavigationEventArgs e, Page page) { - Page = page; - PageType = e.SourcePageType; + Content = page; + SourcePageType = e.SourcePageType; Parameter = e.Parameter; NavigationMode = e.NavigationMode; } public NavigationMode NavigationMode { get; set; } - public Type PageType { get; set; } + public Type SourcePageType { get; set; } public object Parameter { get; set; } - public Page Page { get; set; } + public Page Content { get; set; } } } diff --git a/Unigram/Unigram/Navigation/Services/NavigatingEventArgs.cs b/Unigram/Unigram/Navigation/Services/NavigatingEventArgs.cs index 7494fadc3b..6230326888 100644 --- a/Unigram/Unigram/Navigation/Services/NavigatingEventArgs.cs +++ b/Unigram/Unigram/Navigation/Services/NavigatingEventArgs.cs @@ -15,8 +15,8 @@ public NavigatingEventArgs() public NavigatingEventArgs(NavigatingCancelEventArgs e, Page page, Type targetPageType, object parameter, object targetPageParameter) { NavigationMode = e.NavigationMode; - PageType = e.SourcePageType; - Page = page; + SourcePageType = e.SourcePageType; + Content = page; Parameter = parameter; TargetPageType = targetPageType; TargetPageParameter = targetPageParameter; diff --git a/Unigram/Unigram/Navigation/Services/NavigationService.cs b/Unigram/Unigram/Navigation/Services/NavigationService.cs index 30bfd9b516..d4387ac74a 100644 --- a/Unigram/Unigram/Navigation/Services/NavigationService.cs +++ b/Unigram/Unigram/Navigation/Services/NavigationService.cs @@ -5,8 +5,8 @@ using System.Runtime.CompilerServices; using System.Threading.Tasks; using Unigram.Common; -using Unigram.Services.Serialization; using Unigram.Services.ViewService; +using Unigram.Views; using Windows.ApplicationModel.Core; using Windows.Foundation; using Windows.UI.ViewManagement; @@ -21,8 +21,7 @@ namespace Unigram.Navigation.Services public partial class NavigationService : INavigationService { private readonly IViewService viewService = new ViewService(); - FrameFacade FrameFacadeInternal { get; } - public FrameFacade FrameFacade => FrameFacadeInternal; + public FrameFacade FrameFacade { get; } public bool IsInMainView { get; } public Frame Frame => FrameFacade.Frame; public object Content => Frame.Content; @@ -38,6 +37,8 @@ public string NavigationState public int SessionId { get; private set; } + public IDictionary CacheKeyToChatId { get; } = new Dictionary(); + #region Debug [Conditional("DEBUG")] @@ -51,16 +52,15 @@ public string NavigationState public NavigationService(Frame frame, int session, string id) { - SerializationService = Unigram.Services.Serialization.SerializationService.Json; IsInMainView = CoreApplication.MainView == CoreApplication.GetCurrentView(); SessionId = session; - FrameFacadeInternal = new FrameFacade(this, frame, id); - FrameFacadeInternal.Navigating += async (s, e) => + FrameFacade = new FrameFacade(this, frame, id); + FrameFacade.Navigating += async (s, e) => { if (e.Suspending) return; - var page = FrameFacadeInternal.Content as Page; + var page = FrameFacade.Content as Page; if (page != null) { // call navagable override (navigating) @@ -68,7 +68,7 @@ public NavigationService(Frame frame, int session, string id) if (dataContext != null) { // allow the viewmodel to cancel navigation - e.Cancel = !NavigatingFrom(page, e.PageType, e.Parameter, dataContext, false, e.NavigationMode); + e.Cancel = !NavigatingFrom(page, e.SourcePageType, e.Parameter, dataContext, false, e.NavigationMode); if (!e.Cancel) { await NavigateFromAsync(page, dataContext, false).ConfigureAwait(false); @@ -81,16 +81,21 @@ public NavigationService(Frame frame, int session, string id) } } }; - FrameFacadeInternal.Navigated += async (s, e) => + FrameFacade.Navigated += async (s, e) => { - var parameter = SerializationService.Deserialize(e.Parameter?.ToString()); - var currentContent = FrameFacadeInternal.Frame.Content; + var parameter = e.Parameter; + if (parameter is string cacheKey && e.SourcePageType == typeof(ChatPage)) + { + parameter = CacheKeyToChatId[cacheKey]; + } + + var currentContent = FrameFacade.Frame.Content; //await this.GetDispatcherWrapper().DispatchAsync(async () => //{ try { - if (currentContent == FrameFacadeInternal.Frame.Content) - await NavigateToAsync(e.NavigationMode, parameter, FrameFacadeInternal.Frame.Content).ConfigureAwait(false); + if (currentContent == FrameFacade.Frame.Content) + await NavigateToAsync(e.NavigationMode, parameter, FrameFacade.Frame.Content).ConfigureAwait(false); } catch (Exception ex) { @@ -128,8 +133,8 @@ bool NavigatingFrom(Page page, Type targetPageType, object targetPageParameter, var args = new NavigatingEventArgs { NavigationMode = mode, - PageType = FrameFacadeInternal.CurrentPageType, - Parameter = FrameFacadeInternal.CurrentPageParam, + SourcePageType = FrameFacade.CurrentPageType, + Parameter = FrameFacade.CurrentPageParam, Suspending = suspending, TargetPageType = targetPageType, TargetPageParameter = targetPageParameter @@ -147,7 +152,7 @@ async Task NavigateFromAsync(Page page, INavigable dataContext, bool suspending) dataContext.Dispatcher = this.GetDispatcherWrapper(); dataContext.SessionState = BootStrapper.Current.SessionState; - var pageState = FrameFacadeInternal.PageStateSettingsService(page.GetType()).Values; + var pageState = FrameFacade.PageStateSettingsService(page.GetType()).Values; await dataContext.OnNavigatedFromAsync(pageState, suspending).ConfigureAwait(false); } @@ -155,7 +160,7 @@ async Task NavigateToAsync(NavigationMode mode, object parameter, object frameCo { DebugWrite($"Mode: {mode}, Parameter: {parameter} FrameContent: {frameContent}"); - frameContent = frameContent ?? FrameFacadeInternal.Frame.Content; + frameContent = frameContent ?? FrameFacade.Frame.Content; var page = frameContent as Page; if (page != null) @@ -180,7 +185,7 @@ async Task NavigateToAsync(NavigationMode mode, object parameter, object frameCo dataContext.NavigationService = this; dataContext.Dispatcher = this.GetDispatcherWrapper(); dataContext.SessionState = BootStrapper.Current.SessionState; - var pageState = FrameFacadeInternal.PageStateSettingsService(page.GetType(), parameter: parameter).Values; + var pageState = FrameFacade.PageStateSettingsService(page.GetType(), parameter: parameter).Values; await dataContext.OnNavigatedToAsync(parameter, mode, pageState); // update bindings after NavTo initializes data @@ -226,88 +231,39 @@ public bool Navigate(Type page, object parameter = null, IDictionary - /// Navigate allows developers to navigate using a - /// page key instead of the view type.This is accomplished by - /// creating a custom Enum and setting up the PageKeys dict - /// with the Key/Type pairs for your views.The dict is - /// shared by all NavigationServices and is stored in - /// the BootStrapper (or Application) of the app. - /// - /// Implementation example: - /// - /// // define your Enum - /// public Enum Pages { MainPage, DetailPage } - /// - /// // setup the keys dict - /// var keys = BootStrapper.PageKeys(); - /// keys.Add(Pages.MainPage, typeof(Views.MainPage)); - /// keys.Add(Pages.DetailPage, typeof(Views.DetailPage)); - /// - /// // use Navigate() - /// NavigationService.Navigate(Pages.MainPage); - /// - /// T must be the same custom Enum used with BootStrapper.PageKeys() - public bool Navigate(T key, object parameter = null, IDictionary state = null, NavigationTransitionInfo infoOverride = null) - where T : struct, IConvertible - { - DebugWrite($"Key: {key}, Parameter: {parameter}, NavigationTransitionInfo: {infoOverride}"); - - var keys = BootStrapper.Current.PageKeys(); - - if (!keys.ContainsKey(key)) - throw new KeyNotFoundException(key.ToString()); + if (page == typeof(ChatPage)) + { + var cacheKey = Guid.NewGuid().ToString(); + var chatId = (long)parameter; - var page = keys[key]; + parameter = cacheKey; + CacheKeyToChatId[cacheKey] = chatId; + } - return Navigate(page, parameter, state, infoOverride); + return FrameFacade.Navigate(page, parameter, infoOverride); } - public ISerializationService SerializationService { get; set; } - public event EventHandler> BeforeSavingNavigation; - public async Task SaveAsync() { - DebugWrite($"Frame: {FrameFacadeInternal.FrameId}"); + DebugWrite($"Frame: {FrameFacade.FrameId}"); if (CurrentPageType == null) return; - var args = new CancelEventArgs(FrameFacadeInternal.CurrentPageType); + var args = new CancelEventArgs(FrameFacade.CurrentPageType); BeforeSavingNavigation?.Invoke(this, args); if (args.Cancel) return; - var state = FrameFacadeInternal.PageStateSettingsService(GetType().ToString()); + var state = FrameFacade.PageStateSettingsService(GetType().ToString()); if (state == null) { throw new InvalidOperationException("State container is unexpectedly null"); @@ -315,95 +271,83 @@ public async Task SaveAsync() state.Write("CurrentPageType", CurrentPageType.AssemblyQualifiedName); state.Write("CurrentPageParam", CurrentPageParam); - state.Write("NavigateState", FrameFacadeInternal?.NavigationService.NavigationState); + state.Write("NavigateState", FrameFacade?.NavigationService.NavigationState); await Task.CompletedTask; } - [Obsolete("SaveNavigationAsync() is obsolete - please use SaveAsync() instead.")] - public async Task SaveNavigationAsync() - { - await SaveAsync(); - } - public event TypedEventHandler AfterRestoreSavedNavigation; public async Task LoadAsync() { - DebugWrite($"Frame: {FrameFacadeInternal.FrameId}"); + DebugWrite($"Frame: {FrameFacade.FrameId}"); try { - var state = FrameFacadeInternal.PageStateSettingsService(GetType().ToString()); + var state = FrameFacade.PageStateSettingsService(GetType().ToString()); if (state == null || !state.Exists("CurrentPageType")) { return false; } - FrameFacadeInternal.CurrentPageType = Type.GetType(state.Read("CurrentPageType")); - FrameFacadeInternal.CurrentPageParam = state.Read("CurrentPageParam"); - FrameFacadeInternal.NavigationService.NavigationState = state.Read("NavigateState"); + FrameFacade.CurrentPageType = Type.GetType(state.Read("CurrentPageType")); + FrameFacade.CurrentPageParam = state.Read("CurrentPageParam"); + FrameFacade.NavigationService.NavigationState = state.Read("NavigateState"); - await NavigateToAsync(NavigationMode.Refresh, FrameFacadeInternal.CurrentPageParam); - while (FrameFacadeInternal.Frame.Content == null) + await NavigateToAsync(NavigationMode.Refresh, FrameFacade.CurrentPageParam); + while (FrameFacade.Frame.Content == null) { await Task.Delay(1); } - AfterRestoreSavedNavigation?.Invoke(this, FrameFacadeInternal.CurrentPageType); + AfterRestoreSavedNavigation?.Invoke(this, FrameFacade.CurrentPageType); return true; } catch { return false; } } - [Obsolete("RestoreSavedNavigationAsync is obsolete - please use LoadAsync() instead.")] - public async Task RestoreSavedNavigationAsync() - { - return await LoadAsync(); - } - - public void Refresh() { FrameFacadeInternal.Refresh(); } - public void Refresh(object param) { FrameFacadeInternal.Refresh(param); } + public void Refresh() { FrameFacade.Refresh(); } + public void Refresh(object param) { FrameFacade.Refresh(param); } public void GoBack(NavigationTransitionInfo infoOverride = null) { - if (FrameFacadeInternal.CanGoBack) FrameFacadeInternal.GoBack(infoOverride); + if (FrameFacade.CanGoBack) FrameFacade.GoBack(infoOverride); } - public bool CanGoBack => FrameFacadeInternal.CanGoBack; + public bool CanGoBack => FrameFacade.CanGoBack; - public void GoForward() { FrameFacadeInternal.GoForward(); } + public void GoForward() { FrameFacade.GoForward(); } - public bool CanGoForward => FrameFacadeInternal.CanGoForward; + public bool CanGoForward => FrameFacade.CanGoForward; public void ClearCache(bool removeCachedPagesInBackStack = false) { - DebugWrite($"Frame: {FrameFacadeInternal.FrameId}"); + DebugWrite($"Frame: {FrameFacade.FrameId}"); - int currentSize = FrameFacadeInternal.Frame.CacheSize; + int currentSize = FrameFacade.Frame.CacheSize; if (removeCachedPagesInBackStack) { - FrameFacadeInternal.Frame.CacheSize = 0; + FrameFacade.Frame.CacheSize = 0; } else { - if (FrameFacadeInternal.Frame.BackStackDepth == 0) - FrameFacadeInternal.Frame.CacheSize = 1; + if (FrameFacade.Frame.BackStackDepth == 0) + FrameFacade.Frame.CacheSize = 1; else - FrameFacadeInternal.Frame.CacheSize = FrameFacadeInternal.Frame.BackStackDepth; + FrameFacade.Frame.CacheSize = FrameFacade.Frame.BackStackDepth; } - FrameFacadeInternal.Frame.CacheSize = currentSize; + FrameFacade.Frame.CacheSize = currentSize; } - public void ClearHistory() { FrameFacadeInternal.Frame.BackStack.Clear(); } + public void ClearHistory() { FrameFacade.Frame.BackStack.Clear(); } public async void Resuming() { - DebugWrite($"Frame: {FrameFacadeInternal.FrameId}"); + DebugWrite($"Frame: {FrameFacade.FrameId}"); - var page = FrameFacadeInternal.Content as Page; + var page = FrameFacade.Content as Page; if (page != null) { var dataContext = ResolveForPage(page); @@ -412,8 +356,8 @@ public async void Resuming() dataContext.NavigationService = this; dataContext.Dispatcher = this.GetDispatcherWrapper(); dataContext.SessionState = BootStrapper.Current.SessionState; - var pageState = FrameFacadeInternal.PageStateSettingsService(page.GetType(), parameter: FrameFacadeInternal.CurrentPageParam).Values; - await dataContext.OnNavigatedToAsync(FrameFacadeInternal.CurrentPageParam, NavigationMode.Refresh, pageState); + var pageState = FrameFacade.PageStateSettingsService(page.GetType(), parameter: FrameFacade.CurrentPageParam).Values; + await dataContext.OnNavigatedToAsync(FrameFacade.CurrentPageParam, NavigationMode.Refresh, pageState); // update bindings after NavTo initializes data //XamlUtils.InitializeBindings(page); @@ -431,11 +375,11 @@ public async void Resuming() public async Task SuspendingAsync() { - DebugWrite($"Frame: {FrameFacadeInternal.FrameId}"); + DebugWrite($"Frame: {FrameFacade.FrameId}"); await SaveAsync(); - var page = FrameFacadeInternal.Content as Page; + var page = FrameFacade.Content as Page; if (page != null) { var dataContext = ResolveForPage(page); @@ -446,8 +390,8 @@ public async Task SuspendingAsync() } } - public Type CurrentPageType => FrameFacadeInternal.CurrentPageType; - public object CurrentPageParam => FrameFacadeInternal.CurrentPageParam; + public Type CurrentPageType => FrameFacade.CurrentPageType; + public object CurrentPageParam => FrameFacade.CurrentPageParam; } } diff --git a/Unigram/Unigram/Navigation/Services/NavigationState.cs b/Unigram/Unigram/Navigation/Services/NavigationState.cs new file mode 100644 index 0000000000..38213272f4 --- /dev/null +++ b/Unigram/Unigram/Navigation/Services/NavigationState.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; + +namespace Unigram.Navigation.Services +{ + public class NavigationState : Dictionary + { + public static NavigationState GetChatMember(long chatId, int userId) + { + return new NavigationState { { "chatId", chatId }, { "userId", userId } }; + } + } +} diff --git a/Unigram/Unigram/Services/Serialization/ISerializationService.cs b/Unigram/Unigram/Services/Serialization/ISerializationService.cs deleted file mode 100644 index 0ede7c70da..0000000000 --- a/Unigram/Unigram/Services/Serialization/ISerializationService.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace Unigram.Services.Serialization -{ - public interface ISerializationService - { - /// - /// Serializes the parameter. - /// - string Serialize(object parameter); - - /// - /// Deserializes the parameter. - /// - object Deserialize(string parameter); - - /// - /// Deserializes the parameter. - /// - T Deserialize(string parameter); - - /// - /// Attempts to deserialize the parameter. - /// - bool TryDeserialize(string parameter, out T result); - } -} \ No newline at end of file diff --git a/Unigram/Unigram/Services/Serialization/JsonSerializationService.cs b/Unigram/Unigram/Services/Serialization/JsonSerializationService.cs deleted file mode 100644 index 0cae806e14..0000000000 --- a/Unigram/Unigram/Services/Serialization/JsonSerializationService.cs +++ /dev/null @@ -1,139 +0,0 @@ -using Newtonsoft.Json; -using System; -using System.Runtime.CompilerServices; - -namespace Unigram.Services.Serialization -{ - using System.Diagnostics; - - public sealed class JsonSerializationService : ISerializationService - { - private readonly JsonSerializerSettings settings; - - #region Debug - - [Conditional("DEBUG")] - static void DebugWrite(string text = null, Services.Logging.Severities severity = Logging.Severities.Template10, [CallerMemberName] string caller = null) => - Logging.LoggingService.WriteLine(text, severity, caller: $"{nameof(JsonSerializationService)}.{caller}"); - - #endregion - - /// - /// Initializes a new instance of the class. - /// - internal JsonSerializationService() - { - settings = new JsonSerializerSettings() - { - Formatting = Formatting.None, - TypeNameHandling = TypeNameHandling.Auto, - //TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple, - TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple, - PreserveReferencesHandling = PreserveReferencesHandling.All, - ReferenceLoopHandling = ReferenceLoopHandling.Ignore, - ObjectCreationHandling = ObjectCreationHandling.Auto, - ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor - }; - } - - /// - /// JSON serializer settings. - /// - public JsonSerializerSettings Settings => settings; - - /// - /// Serializes the value. - /// - public string Serialize(object value) - { - DebugWrite($"Value {value}"); - - if (value == null) - return null; - - if (value as string == string.Empty) - return string.Empty; - - // Serialize to json - var container = new Container - { - Type = value.GetType().AssemblyQualifiedName, - Data = JsonConvert.SerializeObject(value, Formatting.None, settings) - }; - return JsonConvert.SerializeObject(container); - } - - /// - /// Deserializes the value. - /// - public object Deserialize(string value) - { - DebugWrite($"Value {value}"); - - if (value == null) - return null; - - if (value == string.Empty) - return string.Empty; - - // Deserialize from json - var container = JsonConvert.DeserializeObject(value); - var type = Type.GetType(container.Type); - return JsonConvert.DeserializeObject(container.Data, type, settings); - } - - /// - /// Deserializes the value. - /// - public T Deserialize(string value) - { - object result = this.Deserialize(value); - if (result != null) - { - return (T)result; - } - return default(T); - } - - /// - /// Attempts to deserialize the value by absorbing the InvalidCastException that may occur. - /// - /// - /// True if deserialization succeeded with non-null result, otherwise False. - /// - /// - /// On success (or return True) deserialized result is copied to the 'out' variable. - /// On fail (or return False) default(T) is copied to the 'out' variable. - /// - public bool TryDeserialize(string value, out T result) - { - object r = this.Deserialize(value); - if (r == null) - { - result = default(T); - return false; - } - - try - { - result = (T)r; - return true; - } - catch - { - result = default(T); - return false; - } - } - - #region Internal Container Class - - sealed class Container - { - public string Type { get; set; } - public string Data { get; set; } - } - - #endregion - } -} \ No newline at end of file diff --git a/Unigram/Unigram/Services/Serialization/SerializationService.cs b/Unigram/Unigram/Services/Serialization/SerializationService.cs deleted file mode 100644 index ceb60ee4b3..0000000000 --- a/Unigram/Unigram/Services/Serialization/SerializationService.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Unigram.Services.Serialization -{ - public static class SerializationService - { - private static ISerializationService _json; - public static ISerializationService Json => _json ?? (_json = new JsonSerializationService()); - } -} \ No newline at end of file diff --git a/Unigram/Unigram/Services/TLSerializationService.cs b/Unigram/Unigram/Services/TLSerializationService.cs deleted file mode 100644 index a4d6aee33b..0000000000 --- a/Unigram/Unigram/Services/TLSerializationService.cs +++ /dev/null @@ -1,193 +0,0 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using System; -using System.Collections.Generic; -using System.Linq; -using Unigram.Services.Serialization; - -namespace Unigram.Services -{ - public class TLSerializationService : ISerializationService - { - private static TLSerializationService _current; - public static TLSerializationService Current - { - get - { - if (_current == null) - _current = new TLSerializationService(); - - return _current; - } - } - - public object Deserialize(string parameter) - { - return Deserialize(parameter); - } - - public bool TryDeserialize(string parameter, out T result) - { - try - { - result = Deserialize(parameter); - return true; - } - catch { } - - result = default(T); - return false; - } - - public T Deserialize(string parameter) - { - if (string.IsNullOrEmpty(parameter)) - { - return (T)(object)null; - } - - if (parameter.StartsWith("{")) - { - var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; - settings.Converters.Add(new TdConverter()); - - var container = JsonConvert.DeserializeObject(parameter); - var type = Type.GetType(container.Type); - - return (T)JsonConvert.DeserializeObject(container.Data, type, settings); - //return SerializationService.Json.Deserialize(parameter); - } - - return default(T); - - //var length = parameter.Length; - //var bytes = new byte[length / 2]; - //for (int i = 0; i < length; i += 2) - // bytes[i / 2] = Convert.ToByte(parameter.Substring(i, 2), 16); - - //if (parameter.StartsWith("0EFFFFFF")) - //{ - // return (T)(object)bytes.Skip(4).ToArray(); - //} - - //var buffer = bytes.AsBuffer(); - //var from = TLObjectSerializer.Deserialize(buffer); - - //return (T)(object)from; - } - - public string Serialize(object parameter) - { - if (parameter == null) - { - return null; - } - - //if (parameter is ITLObject obj) - //{ - // var buffer = TLObjectSerializer.Serialize(obj); - // var array = buffer.ToArray(); - - // return BitConverter.ToString(array).Replace("-", string.Empty); - //} - - var container = new Container - { - Type = parameter.GetType().AssemblyQualifiedName, - Data = JsonConvert.SerializeObject(parameter, Formatting.None, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All, TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Full }) - }; - - return JsonConvert.SerializeObject(container); - //return SerializationService.Json.Serialize(parameter); - } - - sealed class Container - { - public string Type { get; set; } - public string Data { get; set; } - } - } - - class TdConverter : JsonConverter - { - public override bool CanConvert(Type objectType) - { - return objectType.Namespace.StartsWith("Telegram.Td.Api") || objectType.Namespace.StartsWith("Ton.Tonlib.Api"); - } - - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - if (reader.TokenType == JsonToken.StartObject) - { - //var read = reader.Read(); - //var type = reader.ReadAsString(); - - var jobj = JObject.Load(reader); - var type = jobj["$type"].Value(); - - var obj = Activator.CreateInstance(Type.GetType(type)); - serializer.Populate(jobj.CreateReader(), obj); - - return obj; - } - - return null; - } - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - throw new NotImplementedException(); - } - } - - public class TdBundle : List - { - public void Add(string key, object value) - { - Add(new TdItem { Key = key, Value = value }); - } - - public bool TryGetValue(string key, out T value) - { - var result = this.FirstOrDefault(x => x.Key == key); - if (result != null) - { - value = (T)result.Value; - return true; - } - - value = default(T); - return false; - } - - public static TdBundle Deserialize(string data) - { - return JsonConvert.DeserializeObject(data, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }); - } - - public string Serialize() - { - return JsonConvert.SerializeObject(this, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }); - } - - - } - - public class TdItem - { - public string Key { get; set; } - public object Value { get; set; } - } - - public class ChatMemberNavigation - { - public long ChatId { get; set; } - public int UserId { get; set; } - - public ChatMemberNavigation(long chatId, int userId) - { - ChatId = chatId; - UserId = userId; - } - } -} diff --git a/Unigram/Unigram/Unigram.csproj b/Unigram/Unigram/Unigram.csproj index 5722abc420..36f2eaa8d2 100644 --- a/Unigram/Unigram/Unigram.csproj +++ b/Unigram/Unigram/Unigram.csproj @@ -545,9 +545,6 @@ - - - @@ -591,7 +588,7 @@ - + diff --git a/Unigram/Unigram/ViewModels/ChatsViewModel.cs b/Unigram/Unigram/ViewModels/ChatsViewModel.cs index edabf1075b..f1798dbd03 100644 --- a/Unigram/Unigram/ViewModels/ChatsViewModel.cs +++ b/Unigram/Unigram/ViewModels/ChatsViewModel.cs @@ -8,6 +8,7 @@ using Unigram.Collections; using Unigram.Common; using Unigram.Controls; +using Unigram.Navigation.Services; using Unigram.Services; using Unigram.ViewModels.Delegates; using Unigram.Views.Folders; @@ -635,7 +636,7 @@ private async void FolderRemoveExecute((int ChatFilterId, Chat Chat) data) public RelayCommand FolderCreateCommand { get; } private void FolderCreateExecute(Chat chat) { - NavigationService.Navigate(typeof(FolderPage), state: new Dictionary { { "included_chat_id", chat.Id } }); + NavigationService.Navigate(typeof(FolderPage), state: new NavigationState { { "included_chat_id", chat.Id } }); } #endregion diff --git a/Unigram/Unigram/ViewModels/DialogViewModel.Messages.cs b/Unigram/Unigram/ViewModels/DialogViewModel.Messages.cs index 01b163c54a..faa98b4247 100644 --- a/Unigram/Unigram/ViewModels/DialogViewModel.Messages.cs +++ b/Unigram/Unigram/ViewModels/DialogViewModel.Messages.cs @@ -1118,7 +1118,7 @@ public async void KeyboardButtonExecute(MessageViewModel message, object button) var response = await ProtoService.SendAsync(new GetCallbackQueryAnswer(chat.Id, message.Id, new CallbackQueryPayloadGame(game.Game.ShortName))); if (response is CallbackQueryAnswer answer && !string.IsNullOrEmpty(answer.Url)) { - var bundle = new TdBundle(); + var bundle = new Dictionary(); bundle.Add("title", game.Game.Title); bundle.Add("url", answer.Url); bundle.Add("message", message.Id); diff --git a/Unigram/Unigram/ViewModels/ProfileViewModel.cs b/Unigram/Unigram/ViewModels/ProfileViewModel.cs index 7add448506..1308d2b857 100644 --- a/Unigram/Unigram/ViewModels/ProfileViewModel.cs +++ b/Unigram/Unigram/ViewModels/ProfileViewModel.cs @@ -8,6 +8,7 @@ using Unigram.Common; using Unigram.Controls; using Unigram.Converters; +using Unigram.Navigation.Services; using Unigram.Services; using Unigram.ViewModels.Chats; using Unigram.ViewModels.Delegates; @@ -1125,7 +1126,7 @@ private void MemberPromoteExecute(ChatMember member) return; } - NavigationService.Navigate(typeof(SupergroupEditAdministratorPage), new ChatMemberNavigation(chat.Id, member.UserId)); + NavigationService.Navigate(typeof(SupergroupEditAdministratorPage), state: NavigationState.GetChatMember(chat.Id, member.UserId)); } public RelayCommand MemberRestrictCommand { get; } @@ -1137,7 +1138,7 @@ private void MemberRestrictExecute(ChatMember member) return; } - NavigationService.Navigate(typeof(SupergroupEditRestrictedPage), new ChatMemberNavigation(chat.Id, member.UserId)); + NavigationService.Navigate(typeof(SupergroupEditRestrictedPage), state: NavigationState.GetChatMember(chat.Id, member.UserId)); } public RelayCommand MemberRemoveCommand { get; } diff --git a/Unigram/Unigram/ViewModels/Supergroups/SupergroupAddRestrictedViewModel.cs b/Unigram/Unigram/ViewModels/Supergroups/SupergroupAddRestrictedViewModel.cs index 7b43cd3e16..71b428c830 100644 --- a/Unigram/Unigram/ViewModels/Supergroups/SupergroupAddRestrictedViewModel.cs +++ b/Unigram/Unigram/ViewModels/Supergroups/SupergroupAddRestrictedViewModel.cs @@ -1,6 +1,7 @@ using Telegram.Td.Api; using Unigram.Collections; using Unigram.Common; +using Unigram.Navigation.Services; using Unigram.Services; using Unigram.Views.Supergroups; @@ -50,7 +51,7 @@ private async void AddExecute(int userId) } else { - NavigationService.Navigate(typeof(SupergroupEditRestrictedPage), new ChatMemberNavigation(chat.Id, userId)); + NavigationService.Navigate(typeof(SupergroupEditRestrictedPage), state: NavigationState.GetChatMember(chat.Id, userId)); } } } diff --git a/Unigram/Unigram/ViewModels/Supergroups/SupergroupEditAdministratorViewModel.cs b/Unigram/Unigram/ViewModels/Supergroups/SupergroupEditAdministratorViewModel.cs index a8344255fd..d96ba7fa38 100644 --- a/Unigram/Unigram/ViewModels/Supergroups/SupergroupEditAdministratorViewModel.cs +++ b/Unigram/Unigram/ViewModels/Supergroups/SupergroupEditAdministratorViewModel.cs @@ -55,13 +55,10 @@ public ChatMember Member public override async Task OnNavigatedToAsync(object parameter, NavigationMode mode, IDictionary state) { - var bundle = parameter as ChatMemberNavigation; - if (bundle == null) - { - return; - } + state.TryGet("chatId", out long chatId); + state.TryGet("userId", out int userId); - Chat = ProtoService.GetChat(bundle.ChatId); + Chat = ProtoService.GetChat(chatId); var chat = _chat; if (chat == null) @@ -69,7 +66,7 @@ public override async Task OnNavigatedToAsync(object parameter, NavigationMode m return; } - var response = await ProtoService.SendAsync(new GetChatMember(chat.Id, bundle.UserId)); + var response = await ProtoService.SendAsync(new GetChatMember(chat.Id, userId)); if (response is ChatMember member) { var item = ProtoService.GetUser(member.UserId); diff --git a/Unigram/Unigram/ViewModels/Supergroups/SupergroupEditRestrictedViewModel.cs b/Unigram/Unigram/ViewModels/Supergroups/SupergroupEditRestrictedViewModel.cs index 73b46a8b2e..9e802d82f8 100644 --- a/Unigram/Unigram/ViewModels/Supergroups/SupergroupEditRestrictedViewModel.cs +++ b/Unigram/Unigram/ViewModels/Supergroups/SupergroupEditRestrictedViewModel.cs @@ -53,13 +53,10 @@ public ChatMember Member public override async Task OnNavigatedToAsync(object parameter, NavigationMode mode, IDictionary state) { - var bundle = parameter as ChatMemberNavigation; - if (bundle == null) - { - return; - } + state.TryGet("chatId", out long chatId); + state.TryGet("userId", out int userId); - Chat = ProtoService.GetChat(bundle.ChatId); + Chat = ProtoService.GetChat(chatId); var chat = _chat; if (chat == null) @@ -67,7 +64,7 @@ public override async Task OnNavigatedToAsync(object parameter, NavigationMode m return; } - var response = await ProtoService.SendAsync(new GetChatMember(chat.Id, bundle.UserId)); + var response = await ProtoService.SendAsync(new GetChatMember(chat.Id, userId)); if (response is ChatMember member) { var item = ProtoService.GetUser(member.UserId); diff --git a/Unigram/Unigram/ViewModels/Supergroups/SupergroupMembersViewModel.cs b/Unigram/Unigram/ViewModels/Supergroups/SupergroupMembersViewModel.cs index dfef8e5faf..48a7e85f38 100644 --- a/Unigram/Unigram/ViewModels/Supergroups/SupergroupMembersViewModel.cs +++ b/Unigram/Unigram/ViewModels/Supergroups/SupergroupMembersViewModel.cs @@ -4,6 +4,7 @@ using Telegram.Td.Api; using Unigram.Common; using Unigram.Controls; +using Unigram.Navigation.Services; using Unigram.Services; using Unigram.ViewModels.Delegates; using Unigram.Views.Popups; @@ -172,7 +173,7 @@ private void MemberPromoteExecute(ChatMember member) return; } - NavigationService.Navigate(typeof(SupergroupEditAdministratorPage), new ChatMemberNavigation(chat.Id, member.UserId)); + NavigationService.Navigate(typeof(SupergroupEditAdministratorPage), state: NavigationState.GetChatMember(chat.Id, member.UserId)); } public RelayCommand MemberRestrictCommand { get; } @@ -184,7 +185,7 @@ private void MemberRestrictExecute(ChatMember member) return; } - NavigationService.Navigate(typeof(SupergroupEditRestrictedPage), new ChatMemberNavigation(chat.Id, member.UserId)); + NavigationService.Navigate(typeof(SupergroupEditRestrictedPage), state: NavigationState.GetChatMember(chat.Id, member.UserId)); } public RelayCommand MemberRemoveCommand { get; } diff --git a/Unigram/Unigram/Views/GamePage.xaml.cs b/Unigram/Unigram/Views/GamePage.xaml.cs index dd766ae466..2bf6f6d563 100644 --- a/Unigram/Unigram/Views/GamePage.xaml.cs +++ b/Unigram/Unigram/Views/GamePage.xaml.cs @@ -1,8 +1,8 @@ using System; +using System.Collections.Generic; using Telegram.Td.Api; using Unigram.Common; using Unigram.Native; -using Unigram.Services; using Unigram.Views.Popups; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; @@ -21,19 +21,19 @@ public GamePage() protected override void OnNavigatedTo(NavigationEventArgs e) { - var bundle = TLSerializationService.Current.Deserialize((string)e.Parameter) as TdBundle; + var bundle = e.Parameter as Dictionary; if (bundle == null) { return; } - bundle.TryGetValue("title", out string title); - bundle.TryGetValue("username", out string username); + bundle.TryGet("title", out string title); + bundle.TryGet("username", out string username); - bundle.TryGetValue("url", out string url); + bundle.TryGet("url", out string url); - bundle.TryGetValue("message", out long messageId); - bundle.TryGetValue("chat", out long chatId); + bundle.TryGet("message", out long messageId); + bundle.TryGet("chat", out long chatId); _shareMessage = new Message { ChatId = chatId, Id = messageId }; diff --git a/Unigram/Unigram/Views/Host/RootPage.xaml.cs b/Unigram/Unigram/Views/Host/RootPage.xaml.cs index 3f2ae2ff00..640ee2982b 100644 --- a/Unigram/Unigram/Views/Host/RootPage.xaml.cs +++ b/Unigram/Unigram/Views/Host/RootPage.xaml.cs @@ -123,7 +123,6 @@ public void Switch(ISessionService session) if (service == null) { service = BootStrapper.Current.NavigationServiceFactory(BootStrapper.BackButton.Attach, BootStrapper.ExistingContent.Exclude, new Frame(), session.Id, $"{session.Id}", true) as NavigationService; - service.SerializationService = TLSerializationService.Current; service.Frame.Navigating += OnNavigating; service.Frame.Navigated += OnNavigated; diff --git a/Unigram/Unigram/Views/IdenticonPage.xaml.cs b/Unigram/Unigram/Views/IdenticonPage.xaml.cs index 0d0b0525d4..4a2d9d19ad 100644 --- a/Unigram/Unigram/Views/IdenticonPage.xaml.cs +++ b/Unigram/Unigram/Views/IdenticonPage.xaml.cs @@ -19,9 +19,9 @@ public IdenticonPage() protected override void OnNavigatedTo(NavigationEventArgs e) { var service = TLContainer.Current.Resolve(); - var data = TLSerializationService.Current.Deserialize((string)e.Parameter); + var chatId = (long)e.Parameter; - var chat = service.GetChat(data); + var chat = service.GetChat(chatId); if (chat.Type is ChatTypeSecret secret) { var secretChat = service.GetSecretChat(secret.SecretChatId); diff --git a/Unigram/Unigram/Views/InstantPage.xaml.cs b/Unigram/Unigram/Views/InstantPage.xaml.cs index 3c7f988c34..c9d8cc2b8b 100644 --- a/Unigram/Unigram/Views/InstantPage.xaml.cs +++ b/Unigram/Unigram/Views/InstantPage.xaml.cs @@ -155,7 +155,7 @@ protected override async void OnNavigatedTo(NavigationEventArgs e) ViewModel.Gallery.SelectedItem = null; _anchors.Clear(); - var url = TLSerializationService.Current.Deserialize((string)e.Parameter) as string; + var url = e.Parameter as string; if (url == null) { return; @@ -181,108 +181,6 @@ protected override async void OnNavigatedTo(NavigationEventArgs e) ViewModel.IsLoading = false; } - //if (url.StartsWith("http") == false) - //{ - // url = "http://" + url; - //} - - //if (Uri.TryCreate(url, UriKind.Absolute, out Uri uri)) - //{ - // ViewModel.ShareLink = uri; - // ViewModel.ShareTitle = webpage.HasTitle ? webpage.Title : webpage.Url; - //} - - //var webpageMedia = parameter as TLMessageMediaWebPage; - //if (webpageMedia != null) - //{ - // parameter = webpageMedia.WebPage as TLWebPage; - //} - - //var webpage = parameter as TLWebPage; - //if (webpage != null && webpage.HasCachedPage) - //{ - // var url = webpage.Url; - - // _webpageId = webpage.Id; - - // var photos = new List(webpage.CachedPage.Photos); - // var documents = new List(webpage.CachedPage.Documents); - - // if (webpage.HasPhoto) - // { - // photos.Insert(0, webpage.Photo); - // } - - // var processed = 0; - // TLPageBlockBase previousBlock = null; - // FrameworkElement previousElement = null; - // foreach (var block in webpage.CachedPage.Blocks) - // { - // var element = ProcessBlock(webpage.CachedPage, block, photos, documents); - // var spacing = SpacingBetweenBlocks(previousBlock, block); - // var padding = PaddingForBlock(block); - - // if (element != null) - // { - // if (block is TLPageBlockChannel && previousBlock is TLPageBlockCover) - // { - // if (previousElement is StackPanel stack && element is Button) - // { - // element.Style = Resources["CoverChannelBlockStyle"] as Style; - // element.Margin = new Thickness(padding, -40, padding, 0); - // stack.Children.Insert(1, element); - // } - // } - // else - // { - // element.Margin = new Thickness(padding, spacing, padding, 0); - // ScrollingHost.Items.Add(element); - // } - // } - - // previousBlock = block; - // previousElement = element; - // processed++; - // } - - // var part = webpage.CachedPage as TLPagePart; - // if (part != null) - // { - // var response = await MTProtoService.Current.GetWebPageAsync(webpage.Url, webpage.Hash); - // if (response.IsSucceeded) - // { - // var newpage = response.Result as TLWebPage; - // if (newpage != null && newpage.HasCachedPage) - // { - // photos = new List(newpage.CachedPage.Photos); - // documents = new List(newpage.CachedPage.Documents); - - // if (webpage.HasPhoto) - // { - // photos.Insert(0, webpage.Photo); - // } - - // for (int i = processed; i < newpage.CachedPage.Blocks.Count; i++) - // { - // var block = newpage.CachedPage.Blocks[i]; - // var element = ProcessBlock(newpage.CachedPage, block, photos, documents); - // var spacing = SpacingBetweenBlocks(previousBlock, block); - // var padding = PaddingForBlock(block); - - // if (element != null) - // { - // element.Margin = new Thickness(padding, spacing, padding, 0); - // ScrollingHost.Items.Add(element); - // } - - // previousBlock = newpage.CachedPage.Blocks[i]; - // previousElement = element; - // } - // } - // } - // } - //} - base.OnNavigatedTo(e); } diff --git a/Unigram/Unigram/Views/MainPage.xaml.cs b/Unigram/Unigram/Views/MainPage.xaml.cs index 8aec7dc23c..d90960c2a7 100644 --- a/Unigram/Unigram/Views/MainPage.xaml.cs +++ b/Unigram/Unigram/Views/MainPage.xaml.cs @@ -13,6 +13,7 @@ using Unigram.Controls.Chats; using Unigram.Converters; using Unigram.Navigation; +using Unigram.Navigation.Services; using Unigram.Services; using Unigram.Services.Updates; using Unigram.ViewModels; @@ -156,8 +157,8 @@ public void Dispose() viewModel.Dispose(); } - MasterDetail.NavigationService.Frame.Navigating -= OnNavigating; - MasterDetail.NavigationService.Frame.Navigated -= OnNavigated; + MasterDetail.NavigationService.FrameFacade.Navigating -= OnNavigating; + MasterDetail.NavigationService.FrameFacade.Navigated -= OnNavigated; MasterDetail.Dispose(); SettingsView.Dispose(); @@ -1168,8 +1169,8 @@ public void Initialize() if (MasterDetail.NavigationService == null) { MasterDetail.Initialize("Main", Frame, ViewModel.ProtoService.SessionId); - MasterDetail.NavigationService.Frame.Navigating += OnNavigating; - MasterDetail.NavigationService.Frame.Navigated += OnNavigated; + MasterDetail.NavigationService.FrameFacade.Navigating += OnNavigating; + MasterDetail.NavigationService.FrameFacade.Navigated += OnNavigated; } ViewModel.NavigationService = MasterDetail.NavigationService; @@ -1263,7 +1264,7 @@ public async void Activate(Uri scheme) } } - private void OnNavigating(object sender, NavigatingCancelEventArgs e) + private void OnNavigating(object sender, NavigatingEventArgs e) { var frame = sender as Frame; @@ -1276,7 +1277,7 @@ private void OnNavigating(object sender, NavigatingCancelEventArgs e) frame.CurrentSourcePageType == typeof(SupergroupEventLogPage) ? 1 : 0; } - private void OnNavigated(object sender, NavigationEventArgs e) + private void OnNavigated(object sender, NavigatedEventArgs e) { //if (e.SourcePageType == typeof(BlankPage)) //{ @@ -1301,16 +1302,7 @@ private void OnNavigated(object sender, NavigationEventArgs e) } UpdatePaneToggleButtonVisibility(); - - if (e.SourcePageType == typeof(ChatPage)) - { - var parameter = MasterDetail.NavigationService.SerializationService.Deserialize((string)e.Parameter); - UpdateListViewsSelectedItem((long)parameter); - } - else - { - UpdateListViewsSelectedItem(MasterDetail.NavigationService.GetPeerFromBackStack()); - } + UpdateListViewsSelectedItem(MasterDetail.NavigationService.GetPeerFromBackStack()); } private void OnStateChanged(object sender, EventArgs e) diff --git a/Unigram/Unigram/Views/Settings/SettingsThemePage.xaml.cs b/Unigram/Unigram/Views/Settings/SettingsThemePage.xaml.cs index d9a744106d..d3d4244843 100644 --- a/Unigram/Unigram/Views/Settings/SettingsThemePage.xaml.cs +++ b/Unigram/Unigram/Views/Settings/SettingsThemePage.xaml.cs @@ -36,7 +36,7 @@ protected override async void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); - var path = TLSerializationService.Current.Deserialize((string)e.Parameter) as string; + var path = e.Parameter as string; var file = await StorageFile.GetFileFromPathAsync(path); var theme = _theme = await TLContainer.Current.Resolve().DeserializeAsync(file); diff --git a/Unigram/Unigram/Views/Supergroups/SupergroupAddAdministratorPage.xaml.cs b/Unigram/Unigram/Views/Supergroups/SupergroupAddAdministratorPage.xaml.cs index f1ec7d724d..6704a48606 100644 --- a/Unigram/Unigram/Views/Supergroups/SupergroupAddAdministratorPage.xaml.cs +++ b/Unigram/Unigram/Views/Supergroups/SupergroupAddAdministratorPage.xaml.cs @@ -6,6 +6,7 @@ using Unigram.Common; using Unigram.Controls; using Unigram.Converters; +using Unigram.Navigation.Services; using Unigram.Services; using Unigram.ViewModels; using Unigram.ViewModels.Supergroups; @@ -61,17 +62,17 @@ private void ListView_ItemClick(object sender, ItemClickEventArgs e) if (e.ClickedItem is ChatMember member) { - ViewModel.NavigationService.Navigate(typeof(SupergroupEditAdministratorPage), new ChatMemberNavigation(chat.Id, member.UserId)); + ViewModel.NavigationService.Navigate(typeof(SupergroupEditAdministratorPage), state: NavigationState.GetChatMember(chat.Id, member.UserId)); } else if (e.ClickedItem is SearchResult result) { if (result.User is User user) { - ViewModel.NavigationService.Navigate(typeof(SupergroupEditAdministratorPage), new ChatMemberNavigation(chat.Id, user.Id)); + ViewModel.NavigationService.Navigate(typeof(SupergroupEditAdministratorPage), state: NavigationState.GetChatMember(chat.Id, user.Id)); } else if (result.Chat is Chat temp && temp.Type is ChatTypePrivate privata) { - ViewModel.NavigationService.Navigate(typeof(SupergroupEditAdministratorPage), new ChatMemberNavigation(chat.Id, privata.UserId)); + ViewModel.NavigationService.Navigate(typeof(SupergroupEditAdministratorPage), state: NavigationState.GetChatMember(chat.Id, privata.UserId)); } } } diff --git a/Unigram/Unigram/Views/Supergroups/SupergroupAddRestrictedPage.xaml.cs b/Unigram/Unigram/Views/Supergroups/SupergroupAddRestrictedPage.xaml.cs index 44357babb3..fedceb64df 100644 --- a/Unigram/Unigram/Views/Supergroups/SupergroupAddRestrictedPage.xaml.cs +++ b/Unigram/Unigram/Views/Supergroups/SupergroupAddRestrictedPage.xaml.cs @@ -6,6 +6,7 @@ using Unigram.Common; using Unigram.Controls; using Unigram.Converters; +using Unigram.Navigation.Services; using Unigram.Services; using Unigram.ViewModels; using Unigram.ViewModels.Supergroups; @@ -61,17 +62,17 @@ private void ListView_ItemClick(object sender, ItemClickEventArgs e) if (e.ClickedItem is ChatMember member) { - ViewModel.NavigationService.Navigate(typeof(SupergroupEditRestrictedPage), new ChatMemberNavigation(chat.Id, member.UserId)); + ViewModel.NavigationService.Navigate(typeof(SupergroupEditRestrictedPage), state: NavigationState.GetChatMember(chat.Id, member.UserId)); } else if (e.ClickedItem is SearchResult result) { if (result.User is User user) { - ViewModel.NavigationService.Navigate(typeof(SupergroupEditRestrictedPage), new ChatMemberNavigation(chat.Id, user.Id)); + ViewModel.NavigationService.Navigate(typeof(SupergroupEditRestrictedPage), state: NavigationState.GetChatMember(chat.Id, user.Id)); } else if (result.Chat is Chat temp && temp.Type is ChatTypePrivate privata) { - ViewModel.NavigationService.Navigate(typeof(SupergroupEditRestrictedPage), new ChatMemberNavigation(chat.Id, privata.UserId)); + ViewModel.NavigationService.Navigate(typeof(SupergroupEditRestrictedPage), state: NavigationState.GetChatMember(chat.Id, privata.UserId)); } } } diff --git a/Unigram/Unigram/Views/Supergroups/SupergroupAdministratorsPage.xaml.cs b/Unigram/Unigram/Views/Supergroups/SupergroupAdministratorsPage.xaml.cs index 68c410a8d0..fddd002c01 100644 --- a/Unigram/Unigram/Views/Supergroups/SupergroupAdministratorsPage.xaml.cs +++ b/Unigram/Unigram/Views/Supergroups/SupergroupAdministratorsPage.xaml.cs @@ -2,7 +2,7 @@ using Unigram.Common; using Unigram.Controls; using Unigram.Converters; -using Unigram.Services; +using Unigram.Navigation.Services; using Unigram.ViewModels.Delegates; using Unigram.ViewModels.Supergroups; using Windows.UI.Xaml; @@ -35,7 +35,7 @@ private void ListView_ItemClick(object sender, ItemClickEventArgs e) return; } - ViewModel.NavigationService.Navigate(typeof(SupergroupEditAdministratorPage), new ChatMemberNavigation(chat.Id, member.UserId)); + ViewModel.NavigationService.Navigate(typeof(SupergroupEditAdministratorPage), state: NavigationState.GetChatMember(chat.Id, member.UserId)); } #region Context menu diff --git a/Unigram/Unigram/Views/Supergroups/SupergroupBannedPage.xaml.cs b/Unigram/Unigram/Views/Supergroups/SupergroupBannedPage.xaml.cs index 50e6400303..180fe71a54 100644 --- a/Unigram/Unigram/Views/Supergroups/SupergroupBannedPage.xaml.cs +++ b/Unigram/Unigram/Views/Supergroups/SupergroupBannedPage.xaml.cs @@ -6,6 +6,7 @@ using Unigram.Controls; using Unigram.Converters; using Unigram.Navigation; +using Unigram.Navigation.Services; using Unigram.Services; using Unigram.ViewModels.Delegates; using Unigram.ViewModels.Supergroups; @@ -67,7 +68,7 @@ private void ListView_ItemClick(object sender, ItemClickEventArgs e) return; } - ViewModel.NavigationService.Navigate(typeof(SupergroupEditRestrictedPage), new ChatMemberNavigation(chat.Id, member.UserId)); + ViewModel.NavigationService.Navigate(typeof(SupergroupEditRestrictedPage), state: NavigationState.GetChatMember(chat.Id, member.UserId)); } #region Context menu diff --git a/Unigram/Unigram/Views/Supergroups/SupergroupPermissionsPage.xaml b/Unigram/Unigram/Views/Supergroups/SupergroupPermissionsPage.xaml index 6b7a954ba7..86adb29f99 100644 --- a/Unigram/Unigram/Views/Supergroups/SupergroupPermissionsPage.xaml +++ b/Unigram/Unigram/Views/Supergroups/SupergroupPermissionsPage.xaml @@ -86,6 +86,7 @@ ItemTemplate="{StaticResource MemberTemplate}" ItemClick="ListView_ItemClick" IsItemClickEnabled="True" + ChoosingItemContainer="OnChoosingItemContainer" ContainerContentChanging="OnContainerContentChanging" SelectionMode="None"> @@ -110,6 +111,7 @@ ItemTemplate="{StaticResource MemberTemplate}" ItemClick="ListView_ItemClick" IsItemClickEnabled="True" + ChoosingItemContainer="OnChoosingItemContainer" ContainerContentChanging="OnContainerContentChanging" SelectionMode="None" Grid.Row="1"> diff --git a/Unigram/Unigram/Views/Supergroups/SupergroupPermissionsPage.xaml.cs b/Unigram/Unigram/Views/Supergroups/SupergroupPermissionsPage.xaml.cs index c19a7e432f..2e1de2e962 100644 --- a/Unigram/Unigram/Views/Supergroups/SupergroupPermissionsPage.xaml.cs +++ b/Unigram/Unigram/Views/Supergroups/SupergroupPermissionsPage.xaml.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.ComponentModel; using System.Reactive.Linq; using Telegram.Td.Api; @@ -6,6 +7,7 @@ using Unigram.Controls; using Unigram.Converters; using Unigram.Navigation; +using Unigram.Navigation.Services; using Unigram.Services; using Unigram.ViewModels.Delegates; using Unigram.ViewModels.Supergroups; @@ -91,7 +93,7 @@ private void ListView_ItemClick(object sender, ItemClickEventArgs e) return; } - ViewModel.NavigationService.Navigate(typeof(SupergroupEditRestrictedPage), new ChatMemberNavigation(chat.Id, member.UserId)); + ViewModel.NavigationService.Navigate(typeof(SupergroupEditRestrictedPage), state: NavigationState.GetChatMember(chat.Id, member.UserId)); } #region Context menu From 180704d10291bc3e4a861f1ac3670c7355ab439e Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Fri, 19 Jun 2020 12:41:09 +0200 Subject: [PATCH 27/45] Improved messages incremental loading Resolves #1504 --- .../Unigram/Controls/Chats/ChatListView.cs | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/Unigram/Unigram/Controls/Chats/ChatListView.cs b/Unigram/Unigram/Controls/Chats/ChatListView.cs index af0480aa1c..fe0db45e13 100644 --- a/Unigram/Unigram/Controls/Chats/ChatListView.cs +++ b/Unigram/Unigram/Controls/Chats/ChatListView.cs @@ -21,6 +21,7 @@ public class ChatListView : PaddedListView public ItemsStackPanel ItemsStack { get; private set; } private DisposableMutex _loadMoreLock = new DisposableMutex(); + private bool _loadingMore = false; public ChatListView() { @@ -56,6 +57,8 @@ private async void OnLoaded(object sender, RoutedEventArgs e) SetScrollMode(); } + _loadingMore = true; + using (await _loadMoreLock.WaitAsync()) { if (ScrollingHost.ScrollableHeight < 200 && Items.Count > 0) @@ -68,6 +71,8 @@ private async void OnLoaded(object sender, RoutedEventArgs e) await ViewModel.LoadNextSliceAsync(false, true); } } + + _loadingMore = false; } protected override void OnApplyTemplate() @@ -80,6 +85,8 @@ protected override void OnApplyTemplate() private async void Panel_SizeChanged(object sender, SizeChangedEventArgs e) { + _loadingMore = true; + using (await _loadMoreLock.WaitAsync()) { if (ScrollingHost.ScrollableHeight < 200) @@ -95,24 +102,29 @@ private async void Panel_SizeChanged(object sender, SizeChangedEventArgs e) } } } + + _loadingMore = false; } private async void ScrollingHost_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e) { - if (ScrollingHost == null || ItemsStack == null || ViewModel == null) + if (ScrollingHost == null || ItemsStack == null || ViewModel == null || _loadingMore) { return; } + _loadingMore = true; + //if (ScrollingHost.VerticalOffset < 200 && ScrollingHost.ScrollableHeight > 0 && !e.IsIntermediate) //if (ItemsStack.FirstCacheIndex == 0 && !e.IsIntermediate) using (await _loadMoreLock.WaitAsync()) { - if (ItemsStack.FirstCacheIndex == 0 && ViewModel.IsLastSliceLoaded != true && !e.IsIntermediate) + if (ItemsStack.FirstCacheIndex == 0 && ViewModel.IsLastSliceLoaded != true) { await ViewModel.LoadNextSliceAsync(true); } - else if (ScrollingHost.ScrollableHeight - ScrollingHost.VerticalOffset < 200 && ScrollingHost.ScrollableHeight > 0 && !e.IsIntermediate) + //else if (ScrollingHost.ScrollableHeight - ScrollingHost.VerticalOffset < 200 && ScrollingHost.ScrollableHeight > 0) + else if (ItemsStack.LastCacheIndex == ViewModel.Items.Count - 1) { if (ViewModel.IsFirstSliceLoaded != true) { @@ -125,6 +137,8 @@ private async void ScrollingHost_ViewChanged(object sender, ScrollViewerViewChan } } } + + _loadingMore = false; } private ItemsUpdatingScrollMode? _pendingMode; From 63e1c7872aa9ff420f5db98642ce93950653437f Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Fri, 19 Jun 2020 12:41:51 +0200 Subject: [PATCH 28/45] Open game when clicking on thumbnail Resolves #1640 --- .../Unigram/ViewModels/DialogViewModel.Delegate.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Unigram/Unigram/ViewModels/DialogViewModel.Delegate.cs b/Unigram/Unigram/ViewModels/DialogViewModel.Delegate.cs index 6977131c06..d5c29bb2e0 100644 --- a/Unigram/Unigram/ViewModels/DialogViewModel.Delegate.cs +++ b/Unigram/Unigram/ViewModels/DialogViewModel.Delegate.cs @@ -498,6 +498,18 @@ public async void OpenMedia(MessageViewModel message, FrameworkElement target) await new PollResultsPopup(ProtoService, CacheService, Settings, Aggregator, this, message.ChatId, message.Id, poll.Poll).ShowQueuedAsync(); return; } + else if (message.Content is MessageGame game && message.ReplyMarkup is ReplyMarkupInlineKeyboard inline) + { + foreach (var row in inline.Rows) + foreach (var button in row) + { + if (button.Type is InlineKeyboardButtonTypeCallbackGame) + { + KeyboardButtonExecute(message, button); + return; + } + } + } GalleryViewModelBase viewModel = null; @@ -512,7 +524,7 @@ public async void OpenMedia(MessageViewModel message, FrameworkElement target) } } - if (viewModel == null && (message.Content is MessageVideoNote || (webPage != null && webPage.VideoNote != null) || message.Content is MessageAnimation || (webPage != null && webPage.Animation != null) || (message.Content is MessageGame game && game.Game.Animation != null))) + if (viewModel == null && (message.Content is MessageVideoNote || (webPage != null && webPage.VideoNote != null) || message.Content is MessageAnimation || (webPage != null && webPage.Animation != null))) { Delegate?.PlayMessage(message, target); } From d37d6b677b69e024754843a03400a2a84b51af42 Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Fri, 19 Jun 2020 13:09:34 +0200 Subject: [PATCH 29/45] Do not navigate to ChatPage but build navigation stack --- Unigram/Unigram/Common/NavigationService.cs | 8 +++--- Unigram/Unigram/Common/TLNavigationService.cs | 27 ++++++++++++------- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/Unigram/Unigram/Common/NavigationService.cs b/Unigram/Unigram/Common/NavigationService.cs index da3ce0bbde..9f20018eb1 100644 --- a/Unigram/Unigram/Common/NavigationService.cs +++ b/Unigram/Unigram/Common/NavigationService.cs @@ -129,19 +129,19 @@ public static void NavigateToInstant(this INavigationService service, string url } } - public static void NavigateToChat(this INavigationService service, Chat chat, long? message = null, string accessToken = null, IDictionary state = null, bool scheduled = false) + public static void NavigateToChat(this INavigationService service, Chat chat, long? message = null, string accessToken = null, IDictionary state = null, bool scheduled = false, bool force = true) { if (service is TLNavigationService serviceEx) { - serviceEx.NavigateToChat(chat, message, accessToken, state, scheduled); + serviceEx.NavigateToChat(chat, message, accessToken, state, scheduled, force); } } - public static void NavigateToChat(this INavigationService service, long chatId, long? message = null, string accessToken = null, IDictionary state = null, bool scheduled = false) + public static void NavigateToChat(this INavigationService service, long chatId, long? message = null, string accessToken = null, IDictionary state = null, bool scheduled = false, bool force = true) { if (service is TLNavigationService serviceEx) { - serviceEx.NavigateToChat(chatId, message, accessToken, state, scheduled); + serviceEx.NavigateToChat(chatId, message, accessToken, state, scheduled, force); } } diff --git a/Unigram/Unigram/Common/TLNavigationService.cs b/Unigram/Unigram/Common/TLNavigationService.cs index bb46258793..7fe1d9aa90 100644 --- a/Unigram/Unigram/Common/TLNavigationService.cs +++ b/Unigram/Unigram/Common/TLNavigationService.cs @@ -68,7 +68,7 @@ public async void NavigateToInstant(string url) } } - public async void NavigateToChat(Chat chat, long? message = null, string accessToken = null, IDictionary state = null, bool scheduled = false) + public async void NavigateToChat(Chat chat, long? message = null, string accessToken = null, IDictionary state = null, bool scheduled = false, bool force = true) { if (chat == null) { @@ -171,21 +171,30 @@ public async void NavigateToChat(Chat chat, long? message = null, string accessT } else { - await NavigateAsync(scheduled ? typeof(ChatScheduledPage) : typeof(ChatPage), chat.Id, state); + if (Frame.Content is ChatPage chatPage && !scheduled && !force) + { + chatPage.Dispose(); + chatPage.Activate(); + chatPage.ViewModel.NavigationService = this; + chatPage.ViewModel.Dispatcher = Dispatcher; + await chatPage.ViewModel.OnNavigatedToAsync(chat.Id, Windows.UI.Xaml.Navigation.NavigationMode.New, new Dictionary()); + + FrameFacade.RaiseNavigated(chat.Id); + } + else + { + Navigate(scheduled ? typeof(ChatScheduledPage) : typeof(ChatPage), chat.Id, state); + } } } } - public async void NavigateToChat(long chatId, long? message = null, string accessToken = null, IDictionary state = null, bool scheduled = false) + public async void NavigateToChat(long chatId, long? message = null, string accessToken = null, IDictionary state = null, bool scheduled = false, bool force = true) { var chat = _protoService.GetChat(chatId); if (chat == null) { - var response = await _protoService.SendAsync(new GetChat(chatId)); - if (response is Chat result) - { - chat = result; - } + chat = await _protoService.SendAsync(new GetChat(chatId)) as Chat; } if (chat == null) @@ -193,7 +202,7 @@ public async void NavigateToChat(long chatId, long? message = null, string acces return; } - NavigateToChat(chat, message, accessToken, state, scheduled); + NavigateToChat(chat, message, accessToken, state, scheduled, force); } public async void NavigateToPasscode() From d320bb547d5c27d81c7b59c06ef79c7af1d6424c Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Fri, 19 Jun 2020 14:54:06 +0200 Subject: [PATCH 30/45] Use free rather than delete[] --- Unigram/Unigram.Native/VideoAnimation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Unigram/Unigram.Native/VideoAnimation.cpp b/Unigram/Unigram.Native/VideoAnimation.cpp index cf30f4173e..0e29f012a4 100644 --- a/Unigram/Unigram.Native/VideoAnimation.cpp +++ b/Unigram/Unigram.Native/VideoAnimation.cpp @@ -452,7 +452,7 @@ int VideoAnimation::RenderSync(CanvasBitmap^ bitmap, bool preview) unknown->QueryInterface(IID_PPV_ARGS(&bitmapAbi)); bitmapAbi->SetPixelBytes(pixelWidth * pixelHeight * 4, (BYTE*)pixels); - delete[] pixels; + free(pixels); info->prevFrame = timestamp; info->prevDuration = (1000 * info->frame->pkt_duration * av_q2d(info->video_stream->time_base)); From 5c0ac09c7cddcd8a6454d2caa4724f510a42d78c Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Fri, 19 Jun 2020 15:01:54 +0200 Subject: [PATCH 31/45] ofc name --- Unigram/Unigram/Views/Host/RootPage.xaml | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/Unigram/Unigram/Views/Host/RootPage.xaml b/Unigram/Unigram/Views/Host/RootPage.xaml index 4654844d8e..1355f8dd60 100644 --- a/Unigram/Unigram/Views/Host/RootPage.xaml +++ b/Unigram/Unigram/Views/Host/RootPage.xaml @@ -78,15 +78,21 @@ - + - + Date: Sat, 20 Jun 2020 10:50:09 +0200 Subject: [PATCH 32/45] Monitor GetPosition and GetOrder --- Unigram/Unigram/Common/TdExtensions.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Unigram/Unigram/Common/TdExtensions.cs b/Unigram/Unigram/Common/TdExtensions.cs index 1c5270d5b4..cc7898ed2a 100644 --- a/Unigram/Unigram/Common/TdExtensions.cs +++ b/Unigram/Unigram/Common/TdExtensions.cs @@ -4,6 +4,7 @@ using System.Globalization; using System.Linq; using System.Text; +using System.Threading; using Telegram.Td.Api; using Unigram.Common; using Unigram.ViewModels; @@ -1097,14 +1098,18 @@ public static ChatPosition GetPosition(this Chat chat, ChatList chatList) return null; } + Monitor.Enter(chat); + for (int i = 0; i < chat.Positions.Count; i++) { if (chat.Positions[i].List.ListEquals(chatList)) { + Monitor.Exit(chat); return chat.Positions[i]; } } + Monitor.Exit(chat); return null; } @@ -1115,14 +1120,18 @@ public static long GetOrder(this Chat chat, ChatList chatList) return 0; } + Monitor.Enter(chat); + for (int i = 0; i < chat.Positions.Count; i++) { if (chat.Positions[i].List.ListEquals(chatList)) { + Monitor.Exit(chat); return chat.Positions[i].Order; } } + Monitor.Exit(chat); return 0; } From dda6d8143be0c18badd9f0f12766e3b0b4544efc Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Sat, 20 Jun 2020 12:08:42 +0200 Subject: [PATCH 33/45] Fixed URI initialization crash --- Unigram/Unigram/Common/AnimatedRepeaterHandler.cs | 2 +- Unigram/Unigram/Common/Extensions.cs | 13 +++++++++++++ .../Unigram/Controls/Gallery/GalleryView.xaml.cs | 2 +- Unigram/Unigram/Views/ChatView.Bubbles.xaml.cs | 2 +- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Unigram/Unigram/Common/AnimatedRepeaterHandler.cs b/Unigram/Unigram/Common/AnimatedRepeaterHandler.cs index fee4f4f853..b2c805363f 100644 --- a/Unigram/Unigram/Common/AnimatedRepeaterHandler.cs +++ b/Unigram/Unigram/Common/AnimatedRepeaterHandler.cs @@ -270,7 +270,7 @@ private void Play(IEnumerable<(Button Contaner, T Sticker)> items, bool auto) var presenter = new AnimationView(); presenter.AutoPlay = true; presenter.IsLoopingEnabled = true; - presenter.Source = new Uri("file:///" + data.File.Local.Path); + presenter.Source = UriEx.GetLocal(data.File.Local.Path); data.Presenter = presenter; data.Container.Children.Insert(1, presenter); diff --git a/Unigram/Unigram/Common/Extensions.cs b/Unigram/Unigram/Common/Extensions.cs index 090493ec77..f0389dfd58 100644 --- a/Unigram/Unigram/Common/Extensions.cs +++ b/Unigram/Unigram/Common/Extensions.cs @@ -921,4 +921,17 @@ public static WindowContext GetWindowWrapper(this INavigationService service) public static IDispatcherWrapper GetDispatcherWrapper(this INavigationService service) => service.GetWindowWrapper()?.Dispatcher; } + + public static class UriEx + { + public static Uri GetLocal(string path) + { + return new Uri("file:///" + Uri.EscapeUriString(path.Replace('\\', '/'))); + + var directory = Path.GetDirectoryName(path); + var file = Path.GetFileName(path); + + return new Uri("file:///" + directory + "\\" + Uri.EscapeUriString(file)); + } + } } diff --git a/Unigram/Unigram/Controls/Gallery/GalleryView.xaml.cs b/Unigram/Unigram/Controls/Gallery/GalleryView.xaml.cs index f5fe6d531a..9167548e64 100644 --- a/Unigram/Unigram/Controls/Gallery/GalleryView.xaml.cs +++ b/Unigram/Unigram/Controls/Gallery/GalleryView.xaml.cs @@ -625,7 +625,7 @@ private void Play(Grid parent, GalleryContent item, File file) } else { - _mediaPlayer.Source = MediaSource.CreateFromUri(new Uri("file:///" + file.Local.Path)); + _mediaPlayer.Source = MediaSource.CreateFromUri(UriEx.GetLocal(file.Local.Path)); } _mediaPlayer.IsLoopingEnabled = item.IsLoop; diff --git a/Unigram/Unigram/Views/ChatView.Bubbles.xaml.cs b/Unigram/Unigram/Views/ChatView.Bubbles.xaml.cs index 6816c2b39f..97b5e7475e 100644 --- a/Unigram/Unigram/Views/ChatView.Bubbles.xaml.cs +++ b/Unigram/Unigram/Views/ChatView.Bubbles.xaml.cs @@ -496,7 +496,7 @@ public void Play(IEnumerable items, bool auto, bool audio) presenter.AutoPlay = true; presenter.IsLoopingEnabled = true; presenter.IsHitTestVisible = false; - presenter.Source = new Uri("file:///" + data.File.Local.Path); + presenter.Source = UriEx.GetLocal(data.File.Local.Path); //if (data.Clip && ApiInformation.IsTypePresent("Windows.UI.Composition.CompositionGeometricClip")) //{ From 5e5c7b1e36a6da4d61953caf9f206e883670d404 Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Sat, 20 Jun 2020 12:09:49 +0200 Subject: [PATCH 34/45] Use a shared buffer to initialize AnimatedView and LottieView --- Unigram/Unigram/Controls/AnimationView.cs | 19 ++++++++++++++++--- Unigram/Unigram/Controls/LottieView.cs | 19 ++++++++++++------- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/Unigram/Unigram/Controls/AnimationView.cs b/Unigram/Unigram/Controls/AnimationView.cs index d1d6e2523d..140e39aa98 100644 --- a/Unigram/Unigram/Controls/AnimationView.cs +++ b/Unigram/Unigram/Controls/AnimationView.cs @@ -8,6 +8,7 @@ using Unigram.Common; using Unigram.Native; using Windows.Foundation; +using Windows.Graphics.DirectX; using Windows.Storage; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; @@ -91,10 +92,13 @@ private void OnUnloaded(object sender, RoutedEventArgs e) Dispose(); - //_animation?.Dispose(); + _device = null; + + _animation?.Dispose(); _animation = null; //_bitmap?.Dispose(); + _bitmap?.Dispose(); _bitmap = null; } @@ -115,6 +119,9 @@ private void OnInvalidate(object sender, EventArgs e) _canvas?.Invalidate(); } + private static object _reusableLock = new object(); + private static byte[] _reusableBuffer; + private void OnCreateResources(CanvasControl sender, CanvasCreateResourcesEventArgs args) { args.TrackAsyncAction(Task.Run(() => @@ -127,9 +134,15 @@ private void OnCreateResources(CanvasControl sender, CanvasCreateResourcesEventA _animation = animation; - var colors = new byte[_animation.PixelWidth * _animation.PixelHeight * 4]; + lock (_reusableLock) + { + if (_reusableBuffer == null || _reusableBuffer.Length < _animation.PixelWidth * _animation.PixelHeight * 4) + { + _reusableBuffer = new byte[_animation.PixelWidth * _animation.PixelHeight * 4]; + } + } - _bitmap = CanvasBitmap.CreateFromBytes(sender, colors, _animation.PixelWidth, _animation.PixelHeight, Windows.Graphics.DirectX.DirectXPixelFormat.R8G8B8A8UIntNormalized); + _bitmap = CanvasBitmap.CreateFromBytes(sender, _reusableBuffer, _animation.PixelWidth, _animation.PixelHeight, DirectXPixelFormat.R8G8B8A8UIntNormalized); _device = sender; }).AsAsyncAction()); diff --git a/Unigram/Unigram/Controls/LottieView.cs b/Unigram/Unigram/Controls/LottieView.cs index 5f4de99a65..60bc70f15e 100644 --- a/Unigram/Unigram/Controls/LottieView.cs +++ b/Unigram/Unigram/Controls/LottieView.cs @@ -144,10 +144,21 @@ private void OnInvalidate(object sender, EventArgs e) _canvas?.Invalidate(); } + private static object _reusableLock = new object(); + private static byte[] _reusableBuffer; + private void OnCreateResources(CanvasControl sender, CanvasCreateResourcesEventArgs args) { + lock (_reusableLock) + { + if (_reusableBuffer == null) + { + _reusableBuffer = new byte[256 * 256 * 4]; + } + } + _device = sender; - _bitmap = CanvasBitmap.CreateFromBytes(sender, new byte[256 * 256 * 4], 256, 256, DirectXPixelFormat.B8G8R8A8UIntNormalized); + _bitmap = CanvasBitmap.CreateFromBytes(sender, _reusableBuffer, 256, 256, DirectXPixelFormat.B8G8R8A8UIntNormalized); if (args.Reason == CanvasCreateResourcesReason.FirstTime) { @@ -324,12 +335,6 @@ private void OnSourceChanged(string newValue, string oldValue) _index = _isCachingEnabled ? 0 : _animationTotalFrame - 1; - var update = TimeSpan.FromSeconds(_animation.Duration / _animation.TotalFrame); - if (_limitFps && _animation.FrameRate >= 60) - { - update = TimeSpan.FromSeconds(update.TotalSeconds * 2); - } - //canvas.Paused = true; //canvas.ResetElapsedTime(); //canvas.TargetElapsedTime = update > TimeSpan.Zero ? update : TimeSpan.MaxValue; From cf90855dff9cf09870f73e5c676c0b258d76696b Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Sat, 20 Jun 2020 13:23:28 +0200 Subject: [PATCH 35/45] Fixed draft saving --- Unigram/Unigram/Common/TLNavigationService.cs | 2 ++ Unigram/Unigram/ViewModels/DialogViewModel.cs | 5 +---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Unigram/Unigram/Common/TLNavigationService.cs b/Unigram/Unigram/Common/TLNavigationService.cs index 7fe1d9aa90..1031bd0def 100644 --- a/Unigram/Unigram/Common/TLNavigationService.cs +++ b/Unigram/Unigram/Common/TLNavigationService.cs @@ -173,6 +173,8 @@ public async void NavigateToChat(Chat chat, long? message = null, string accessT { if (Frame.Content is ChatPage chatPage && !scheduled && !force) { + chatPage.ViewModel.OnNavigatingFrom(null); + chatPage.Dispose(); chatPage.Activate(); chatPage.ViewModel.NavigationService = this; diff --git a/Unigram/Unigram/ViewModels/DialogViewModel.cs b/Unigram/Unigram/ViewModels/DialogViewModel.cs index cedd816b6d..e33ed6eee7 100644 --- a/Unigram/Unigram/ViewModels/DialogViewModel.cs +++ b/Unigram/Unigram/ViewModels/DialogViewModel.cs @@ -1987,10 +1987,7 @@ public override void OnNavigatingFrom(NavigatingEventArgs args) Logs.Logger.Debug(Logs.Target.Chat, string.Format("{0} - Removing scrolling position, exception", chat.Id)); } - if (Dispatcher != null) - { - Dispatcher.Dispatch(SaveDraft); - } + SaveDraft(); } private void ShowSwitchInline(IDictionary state) From dd4dddd5fdeb1395e8095b31ed37b7f31581ab90 Mon Sep 17 00:00:00 2001 From: Fela Ameghino Date: Sun, 21 Jun 2020 14:53:30 +0200 Subject: [PATCH 36/45] Rebuilt recent actions from scratch --- Unigram/Unigram/Common/TdExtensions.cs | 30 +- .../Controls/Messages/MessageBubble.xaml.cs | 23 +- .../Controls/Messages/MessageService.cs | 2 +- Unigram/Unigram/Unigram.csproj | 19 +- Unigram/Unigram/ViewModelLocator.cs | 2 +- .../ViewModels/DialogEventLogViewModel.cs | 623 ++++++++++++ .../ViewModels/DialogScheduledViewModel.cs | 2 +- .../ViewModels/DialogViewModel.Handle.cs | 6 +- .../ViewModels/DialogViewModel.Media.cs | 4 +- Unigram/Unigram/ViewModels/DialogViewModel.cs | 103 +- .../Unigram/ViewModels/MessageViewModel.cs | 2 +- .../SupergroupAdministratorsViewModel.cs | 3 +- .../SupergroupEventLogViewModel.cs | 953 ------------------ Unigram/Unigram/Views/ChatEventLogPage.xaml | 16 + .../Unigram/Views/ChatEventLogPage.xaml.cs | 43 + Unigram/Unigram/Views/ChatPage.xaml.cs | 3 +- .../Unigram/Views/ChatScheduledPage.xaml.cs | 3 +- Unigram/Unigram/Views/ChatView.Drawers.cs | 4 +- Unigram/Unigram/Views/ChatView.xaml.cs | 38 +- Unigram/Unigram/Views/MainPage.xaml.cs | 24 +- .../SupergroupEventLogPage.Bubbles.cs | 59 -- .../Supergroups/SupergroupEventLogPage.xaml | 324 ------ .../SupergroupEventLogPage.xaml.cs | 292 ------ 23 files changed, 866 insertions(+), 1712 deletions(-) create mode 100644 Unigram/Unigram/ViewModels/DialogEventLogViewModel.cs delete mode 100644 Unigram/Unigram/ViewModels/Supergroups/SupergroupEventLogViewModel.cs create mode 100644 Unigram/Unigram/Views/ChatEventLogPage.xaml create mode 100644 Unigram/Unigram/Views/ChatEventLogPage.xaml.cs delete mode 100644 Unigram/Unigram/Views/Supergroups/SupergroupEventLogPage.Bubbles.cs delete mode 100644 Unigram/Unigram/Views/Supergroups/SupergroupEventLogPage.xaml delete mode 100644 Unigram/Unigram/Views/Supergroups/SupergroupEventLogPage.xaml.cs diff --git a/Unigram/Unigram/Common/TdExtensions.cs b/Unigram/Unigram/Common/TdExtensions.cs index cc7898ed2a..699126fc12 100644 --- a/Unigram/Unigram/Common/TdExtensions.cs +++ b/Unigram/Unigram/Common/TdExtensions.cs @@ -885,12 +885,12 @@ public static bool IsPhoto(this WebPage webPage) } } - return false; + return webPage.Photo != null; } public static bool IsSmallPhoto(this WebPage webPage) { - if (webPage.Photo != null) + if (webPage.Photo != null && (webPage.SiteName.Length > 0 || webPage.Title.Length > 0 || webPage.Author.Length > 0 || webPage.Description?.Text.Length > 0)) { return !webPage.IsMedia(); } @@ -1777,6 +1777,10 @@ public static bool UpdateFile(this Message message, File file) return voiceNote.UpdateFile(file); case MessageChatChangePhoto chatChangePhoto: return chatChangePhoto.UpdateFile(file); + + case MessageChatEvent chatEvent: + return chatEvent.UpdateFile(file); + default: return false; } @@ -2138,6 +2142,28 @@ public static bool UpdateFile(this MessageChatChangePhoto chatChangePhoto, File return chatChangePhoto.Photo.UpdateFile(file); } + public static bool UpdateFile(this MessageChatEvent chatEvent, File file) + { + if (chatEvent.Event.Action is ChatEventMessageDeleted messageDeleted) + { + return messageDeleted.Message.UpdateFile(file); + } + else if (chatEvent.Event.Action is ChatEventMessageEdited messageEdited) + { + return messageEdited.NewMessage.UpdateFile(file); + } + else if (chatEvent.Event.Action is ChatEventMessagePinned messagePinned) + { + return messagePinned.Message.UpdateFile(file); + } + else if (chatEvent.Event.Action is ChatEventPollStopped pollStopped) + { + return pollStopped.Message.UpdateFile(file); + } + + return false; + } + public static void Update(this File file, File update) diff --git a/Unigram/Unigram/Controls/Messages/MessageBubble.xaml.cs b/Unigram/Unigram/Controls/Messages/MessageBubble.xaml.cs index 96dfb6e6b1..e77713a681 100644 --- a/Unigram/Unigram/Controls/Messages/MessageBubble.xaml.cs +++ b/Unigram/Unigram/Controls/Messages/MessageBubble.xaml.cs @@ -291,6 +291,15 @@ private void MaybeUseInner(ref MessageViewModel message) else if (chatEvent.Event.Action is ChatEventMessageEdited messageEdited) { message = new MessageViewModel(message.ProtoService, message.PlaybackService, message.Delegate, messageEdited.NewMessage) { IsFirst = true, IsLast = true, IsOutgoing = false }; + + if (message.Content is MessageText editedText && messageEdited.OldMessage.Content is MessageText oldText) + { + editedText.WebPage = new WebPage + { + SiteName = Strings.Resources.EventLogOriginalMessages, + Description = oldText.Text + }; + } } else if (chatEvent.Event.Action is ChatEventMessagePinned messagePinned) { @@ -868,6 +877,8 @@ public void UpdateMessageContent(MessageViewModel message, bool padding = false) public void UpdateFile(MessageViewModel message, File file) { + MaybeUseInner(ref message); + if (Media.Child is IContentWithFile content) { content.UpdateFile(message, file); @@ -935,10 +946,10 @@ private void UpdateMessageText(MessageViewModel message) //Footer.HorizontalAlignment = adjust ? HorizontalAlignment.Left : HorizontalAlignment.Right; _placeholderVertical = adjust; - //if (adjust) - //{ - // Span.Inlines.Add(new LineBreak()); - //} + if (adjust) + { + Span.Inlines.Add(new LineBreak()); + } } private bool GetEntities(MessageViewModel message, Span span, string text, out bool adjust) @@ -1282,9 +1293,9 @@ private void OnSizeChanged(object sender, SizeChangedEventArgs e) var rect = Message.ContentEnd.GetCharacterRect(LogicalDirection.Forward); var diff = width - rect.Right; - if (diff < footerWidth || _placeholderVertical) + if (diff < footerWidth /*|| _placeholderVertical*/) { - if (Message.ActualHeight < rect.Height * 2 && width + footerWidth < _maxWidth - ContentPanel.Padding.Left - ContentPanel.Padding.Right && !_placeholderVertical) + if (Message.ActualHeight < rect.Height * 2 && width + footerWidth < _maxWidth - ContentPanel.Padding.Left - ContentPanel.Padding.Right /*&& !_placeholderVertical*/) { Message.Margin = new Thickness(0, 0, footerWidth, 0); } diff --git a/Unigram/Unigram/Controls/Messages/MessageService.cs b/Unigram/Unigram/Controls/Messages/MessageService.cs index c683a1bfe1..f0f2d512ca 100644 --- a/Unigram/Unigram/Controls/Messages/MessageService.cs +++ b/Unigram/Unigram/Controls/Messages/MessageService.cs @@ -118,7 +118,7 @@ private static (string Text, IList Entities) GetEntities(MessageView case ChatEventUsernameChanged usernameChanged: return UpdateUsernameChanged(message, usernameChanged, active); case ChatEventPollStopped pollStopped: - return UpdatePollStopped(message, pollStopped, active); + return UpdatePollStopped(new MessageViewModel(message.ProtoService, message.PlaybackService, message.Delegate, pollStopped.Message), pollStopped, active); case ChatEventSlowModeDelayChanged slowModeDelayChanged: return UpdateSlowModeDelayChanged(message, slowModeDelayChanged, active); default: diff --git a/Unigram/Unigram/Unigram.csproj b/Unigram/Unigram/Unigram.csproj index 36f2eaa8d2..14a623c670 100644 --- a/Unigram/Unigram/Unigram.csproj +++ b/Unigram/Unigram/Unigram.csproj @@ -484,6 +484,10 @@ + + + ChatEventLogPage.xaml + ChatSharedMediaPage.xaml @@ -741,7 +745,6 @@ - @@ -1073,12 +1076,6 @@ SupergroupEditTypePage.xaml - - SupergroupEventLogPage.xaml - - - SupergroupEventLogPage.xaml - SupergroupMembersPage.xaml @@ -2028,6 +2025,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -2564,10 +2565,6 @@ Designer MSBuild:Compile - - MSBuild:Compile - Designer - Designer MSBuild:Compile diff --git a/Unigram/Unigram/ViewModelLocator.cs b/Unigram/Unigram/ViewModelLocator.cs index b01cf2a916..1ed735020b 100644 --- a/Unigram/Unigram/ViewModelLocator.cs +++ b/Unigram/Unigram/ViewModelLocator.cs @@ -172,12 +172,12 @@ public IContainer Configure(int id) builder.RegisterType(); builder.RegisterType(); //.WithParameter((a, b) => a.Name == "dispatcher", (a, b) => WindowWrapper.Current().Dispatcher); builder.RegisterType(); + builder.RegisterType(); builder.RegisterType(); builder.RegisterType(); builder.RegisterType(); builder.RegisterType(); builder.RegisterType(); - builder.RegisterType(); builder.RegisterType(); builder.RegisterType(); builder.RegisterType(); diff --git a/Unigram/Unigram/ViewModels/DialogEventLogViewModel.cs b/Unigram/Unigram/ViewModels/DialogEventLogViewModel.cs new file mode 100644 index 0000000000..a2410a7683 --- /dev/null +++ b/Unigram/Unigram/ViewModels/DialogEventLogViewModel.cs @@ -0,0 +1,623 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Telegram.Td.Api; +using Unigram.Common; +using Unigram.Controls; +using Unigram.Converters; +using Unigram.Services; +using Unigram.Services.Factories; +using Unigram.Views.Popups; +using Windows.UI.Xaml.Controls; + +namespace Unigram.ViewModels +{ + public class DialogEventLogViewModel : DialogViewModel + { + public DialogEventLogViewModel(IProtoService protoService, ICacheService cacheService, ISettingsService settingsService, IEventAggregator aggregator, ILocationService locationService, INotificationsService pushService, IPlaybackService playbackService, IVoIPService voipService, INetworkService networkService, IMessageFactory messageFactory) + : base(protoService, cacheService, settingsService, aggregator, locationService, pushService, playbackService, voipService, networkService, messageFactory) + { + HelpCommand = new RelayCommand(HelpExecute); + } + + public override DialogType Type => DialogType.EventLog; + + private ChatEventLogFilters _filters = new ChatEventLogFilters(true, true, true, true, true, true, true, true, true, true); + public ChatEventLogFilters Filters + { + get => _filters; + set => Set(ref _filters, value); + } + + private IList _userIds = new int[0]; + public IList UserIds + { + get => _userIds; + set => Set(ref _userIds, value); + } + + protected override async void FilterExecute() + { + var chat = _chat; + if (chat == null) + { + return; + } + + var supergroup = CacheService.GetSupergroup(chat); + if (supergroup == null) + { + return; + } + + var dialog = new SupergroupEventLogFiltersPopup(); + + var confirm = await dialog.ShowAsync(ProtoService, supergroup.Id, _filters, _userIds); + if (confirm == ContentDialogResult.Primary) + { + Filters = dialog.Filters; + UserIds = dialog.UserIds; + + await LoadEventLogSliceAsync(); + } + } + + public RelayCommand HelpCommand { get; } + private async void HelpExecute() + { + var chat = _chat; + if (chat == null) + { + return; + } + + await MessagePopup.ShowAsync(chat.Type is ChatTypeSupergroup supergroup && supergroup.IsChannel ? Strings.Resources.EventLogInfoDetailChannel : Strings.Resources.EventLogInfoDetail, Strings.Resources.EventLogInfoTitle, Strings.Resources.OK); + } + + public override async Task LoadEventLogSliceAsync() + { + using (await _loadMoreLock.WaitAsync()) + { + var chat = _chat; + if (chat == null) + { + return; + } + + if (_isLoadingNextSlice || _isLoadingPreviousSlice) + { + return; + } + + _isLoadingNextSlice = true; + _isLoadingPreviousSlice = true; + IsLastSliceLoaded = null; + IsFirstSliceLoaded = null; + IsLoading = true; + + System.Diagnostics.Debug.WriteLine("DialogViewModel: LoadScheduledSliceAsync"); + + var response = await ProtoService.SendAsync(new GetChatEventLog(chat.Id, string.Empty, 0, 50, _filters, _userIds)); + if (response is ChatEvents events) + { + _groupedMessages.Clear(); + + if (events.Events.Count > 0) + { + SetScrollMode(ItemsUpdatingScrollMode.KeepLastItemInView, true); + Logs.Logger.Debug(Logs.Target.Chat, "Setting scroll mode to KeepLastItemInView"); + } + + var replied = ProcessEvents(events); + await ProcessMessagesAsync(chat, replied); + + var target = replied.FirstOrDefault(); + if (target != null) + { + replied.Insert(0, _messageFactory.Create(this, new Message(0, target.SenderUserId, target.ChatId, null, target.SchedulingState, target.IsOutgoing, false, false, true, false, target.IsChannelPost, false, target.Date, 0, null, 0, 0, 0, 0, string.Empty, 0, 0, string.Empty, new MessageHeaderDate(), null))); + } + + Items.ReplaceWith(replied); + + IsLastSliceLoaded = true; + IsFirstSliceLoaded = true; + } + + _isLoadingNextSlice = false; + _isLoadingPreviousSlice = false; + IsLoading = false; + } + } + + private Message CreateMessage(long chatId, bool isChannel, ChatEvent chatEvent) + { + return new Message(chatEvent.Id, chatEvent.UserId, chatId, null, null, false, false, false, false, false, isChannel, false, chatEvent.Date, 0, null, 0, 0, 0.0d, 0, string.Empty, 0, 0, string.Empty, null, null); + } + + private MessageViewModel GetMessage(long chatId, bool isChannel, ChatEvent chatEvent) + { + var message = _messageFactory.Create(this, CreateMessage(chatId, isChannel, chatEvent)); + message.IsFirst = true; + message.IsLast = true; + + return message; + } + + private IList ProcessEvents(ChatEvents events) + { + var result = new List(); + var channel = _chat.Type is ChatTypeSupergroup super && super.IsChannel; + + foreach (var item in events.Events) + { + //_minEventId = Math.Min(_minEventId, item.Id); + + MessageViewModel message = null; + switch (item.Action) + { + case ChatEventMemberInvited memberInvited: + message = GetMessage(_chat.Id, channel, item); + message.Content = new MessageChatAddMembers(new[] { memberInvited.UserId }); + break; + case ChatEventSlowModeDelayChanged slowModeDelayChanged: + case ChatEventPermissionsChanged permissionsChanged: + case ChatEventMemberRestricted memberRestricted: + case ChatEventMemberPromoted memberPromoted: + message = GetMessage(_chat.Id, channel, item); + //message.Content = new MessageChatEvent(item, true); + message.Content = GetMessageContent(item, channel); + break; + case ChatEventSignMessagesToggled signMessagesToggled: + case ChatEventStickerSetChanged stickerSetChanged: + case ChatEventInvitesToggled invitesToggled: + case ChatEventIsAllHistoryAvailableToggled isAllHistoryAvailableToggled: + case ChatEventMessageUnpinned messageUnpinned: + case ChatEventLinkedChatChanged linkedChatChanged: + case ChatEventLocationChanged locationChanged: + message = GetMessage(_chat.Id, channel, item); + message.Content = new MessageChatEvent(item, false); + break; + case ChatEventMemberLeft memberLeft: + message = GetMessage(_chat.Id, channel, item); + message.Content = new MessageChatDeleteMember(item.UserId); + break; + case ChatEventMessageDeleted messageDeleted: + case ChatEventMessageEdited messageEdited: + case ChatEventDescriptionChanged descriptionChanged: + case ChatEventMessagePinned messagePinned: + case ChatEventUsernameChanged usernameChanged: + case ChatEventPollStopped pollStopped: + message = GetMessage(_chat.Id, channel, item); + //message.Content = new MessageChatEvent(item, true); + message.Content = GetMessageContent(item, channel); + result.Add(message); + message = GetMessage(_chat.Id, channel, item); + message.Content = new MessageChatEvent(item, false); + break; + case ChatEventPhotoChanged photoChanged: + message = GetMessage(_chat.Id, channel, item); + if (photoChanged.NewPhoto == null) + { + message.Content = new MessageChatDeletePhoto(); + break; + } + + message.Content = new MessageChatChangePhoto(photoChanged.NewPhoto); + break; + case ChatEventMemberJoined memberJoined: + message = GetMessage(_chat.Id, channel, item); + message.Content = new MessageChatAddMembers(new int[] { item.UserId }); + break; + case ChatEventTitleChanged titleChanged: + message = GetMessage(_chat.Id, channel, item); + message.Content = new MessageChatChangeTitle(titleChanged.NewTitle); + break; + } + + + if (message != null) + { + result.Add(message); + } + } + + //if (response.Result.Events.Count < 50) + //{ + // _hasMore = false; + //} + + result.Reverse(); + return result; + } + + private MessageContent GetMessageContent(ChatEvent item, bool channel) + { + if (item.Action is ChatEventDescriptionChanged descriptionChanged) + { + var text = new FormattedText(descriptionChanged.NewDescription, new TextEntity[0]); + var webPage = string.IsNullOrEmpty(descriptionChanged.OldDescription) ? null : new WebPage { SiteName = Strings.Resources.EventLogPreviousGroupDescription, Description = new FormattedText { Text = descriptionChanged.OldDescription } }; + + return new MessageText(text, webPage); + } + else if (item.Action is ChatEventUsernameChanged usernameChanged) + { + var link = string.IsNullOrEmpty(usernameChanged.NewUsername) ? string.Empty : MeUrlPrefixConverter.Convert(CacheService, usernameChanged.NewUsername); + + var text = new FormattedText(link, new[] { new TextEntity(0, link.Length, new TextEntityTypeUrl()) }); + var webPage = string.IsNullOrEmpty(usernameChanged.OldUsername) ? null : new WebPage { SiteName = Strings.Resources.EventLogPreviousLink, Description = new FormattedText { Text = MeUrlPrefixConverter.Convert(CacheService, usernameChanged.OldUsername) } }; + + return new MessageText(text, webPage); + } + else if (item.Action is ChatEventPermissionsChanged permissionChanged) + { + var text = string.Empty; + var entities = new List(); + + ChatPermissions o = permissionChanged.OldPermissions; + ChatPermissions n = permissionChanged.NewPermissions; + + if (o == null) + { + o = new ChatPermissions(); + } + if (n == null) + { + n = new ChatPermissions(); + } + + var rights = new StringBuilder(Strings.Resources.EventLogDefaultPermissions); + var added = false; + + void AppendChange(bool value, string label) + { + if (!added) + { + rights.Append('\n'); + added = true; + } + + rights.Append('\n').Append(value ? '+' : '-').Append(' '); + rights.Append(label); + } + + //if (o.IsViewMessages != n.IsViewMessages) + //{ + // AppendChange(n.IsViewMessages, Strings.Resources.EventLogRestrictedReadMessages); + //} + if (o.CanSendMessages != n.CanSendMessages) + { + AppendChange(n.CanSendMessages, Strings.Resources.EventLogRestrictedSendMessages); + } + if (o.CanSendOtherMessages != n.CanSendOtherMessages) + { + AppendChange(n.CanSendOtherMessages, Strings.Resources.EventLogRestrictedSendStickers); + } + if (o.CanSendMediaMessages != n.CanSendMediaMessages) + { + AppendChange(n.CanSendMediaMessages, Strings.Resources.EventLogRestrictedSendMedia); + } + if (o.CanSendPolls != n.CanSendPolls) + { + AppendChange(n.CanSendPolls, Strings.Resources.EventLogRestrictedSendPolls); + } + if (o.CanAddWebPagePreviews != n.CanAddWebPagePreviews) + { + AppendChange(n.CanAddWebPagePreviews, Strings.Resources.EventLogRestrictedSendEmbed); + } + if (o.CanChangeInfo != n.CanChangeInfo) + { + AppendChange(n.CanChangeInfo, Strings.Resources.EventLogRestrictedChangeInfo); + } + if (o.CanInviteUsers != n.CanInviteUsers) + { + AppendChange(n.CanInviteUsers, Strings.Resources.EventLogRestrictedSendEmbed); + } + if (o.CanPinMessages != n.CanPinMessages) + { + AppendChange(n.CanPinMessages, Strings.Resources.EventLogRestrictedPinMessages); + } + + text = rights.ToString(); + + return new MessageText(new FormattedText(text, entities), null); + } + else if (item.Action is ChatEventMemberRestricted memberRestricted) + { + var text = string.Empty; + var entities = new List(); + + var whoUser = CacheService.GetUser(memberRestricted.UserId); + ChatMemberStatusRestricted o = null; + ChatMemberStatusRestricted n = null; + + if (memberRestricted.OldStatus is ChatMemberStatusRestricted oldRestricted) + { + o = oldRestricted; + } + else if (memberRestricted.OldStatus is ChatMemberStatusBanned oldBanned) + { + o = new ChatMemberStatusRestricted(false, oldBanned.BannedUntilDate, new ChatPermissions(false, false, false, false, false, false, false, false)); + } + else if (memberRestricted.OldStatus is ChatMemberStatusMember) + { + o = new ChatMemberStatusRestricted(true, 0, new ChatPermissions(true, true, true, true, true, true, true, true)); + } + + if (memberRestricted.NewStatus is ChatMemberStatusRestricted newRestricted) + { + n = newRestricted; + } + else if (memberRestricted.NewStatus is ChatMemberStatusBanned newBanned) + { + n = new ChatMemberStatusRestricted(false, newBanned.BannedUntilDate, new ChatPermissions(false, false, false, false, false, false, false, false)); + } + else if (memberRestricted.NewStatus is ChatMemberStatusMember) + { + n = new ChatMemberStatusRestricted(true, 0, new ChatPermissions(true, true, true, true, true, true, true, true)); + } + + if (!channel && (n == null || n != null && o != null /*&& n.RestrictedUntilDate != o.RestrictedUntilDate*/)) + { + StringBuilder rights; + String bannedDuration; + if (n != null && !n.IsForever()) + { + bannedDuration = ""; + int duration = n.RestrictedUntilDate - item.Date; + int days = duration / 60 / 60 / 24; + duration -= days * 60 * 60 * 24; + int hours = duration / 60 / 60; + duration -= hours * 60 * 60; + int minutes = duration / 60; + int count = 0; + for (int a = 0; a < 3; a++) + { + String addStr = null; + if (a == 0) + { + if (days != 0) + { + addStr = Locale.Declension("Days", days); + count++; + } + } + else if (a == 1) + { + if (hours != 0) + { + addStr = Locale.Declension("Hours", hours); + count++; + } + } + else + { + if (minutes != 0) + { + addStr = Locale.Declension("Minutes", minutes); + count++; + } + } + if (addStr != null) + { + if (bannedDuration.Length > 0) + { + bannedDuration += ", "; + } + bannedDuration += addStr; + } + if (count == 2) + { + break; + } + } + } + else + { + bannedDuration = Strings.Resources.UserRestrictionsUntilForever; + } + + var str = Strings.Resources.EventLogRestrictedUntil; + rights = new StringBuilder(String.Format(str, GetUserName(whoUser, entities, str.IndexOf("{0}")), bannedDuration)); + var added = false; + if (o == null) + { + o = new ChatMemberStatusRestricted(true, 0, new ChatPermissions(true, true, true, true, true, true, true, true)); + } + if (n == null) + { + n = new ChatMemberStatusRestricted(true, 0, new ChatPermissions(true, true, true, true, true, true, true, true)); + } + + void AppendChange(bool value, string label) + { + if (!added) + { + rights.Append('\n'); + added = true; + } + + rights.Append('\n').Append(value ? '+' : '-').Append(' '); + rights.Append(label); + } + + //if (o.IsViewMessages != n.IsViewMessages) + //{ + // AppendChange(n.IsViewMessages, Strings.Resources.EventLogRestrictedReadMessages); + //} + if (o.Permissions.CanSendMessages != n.Permissions.CanSendMessages) + { + AppendChange(n.Permissions.CanSendMessages, Strings.Resources.EventLogRestrictedSendMessages); + } + if (o.Permissions.CanSendOtherMessages != n.Permissions.CanSendOtherMessages) + { + AppendChange(n.Permissions.CanSendOtherMessages, Strings.Resources.EventLogRestrictedSendStickers); + } + if (o.Permissions.CanSendMediaMessages != n.Permissions.CanSendMediaMessages) + { + AppendChange(n.Permissions.CanSendMediaMessages, Strings.Resources.EventLogRestrictedSendMedia); + } + if (o.Permissions.CanSendPolls != n.Permissions.CanSendPolls) + { + AppendChange(n.Permissions.CanSendPolls, Strings.Resources.EventLogRestrictedSendPolls); + } + if (o.Permissions.CanAddWebPagePreviews != n.Permissions.CanAddWebPagePreviews) + { + AppendChange(n.Permissions.CanAddWebPagePreviews, Strings.Resources.EventLogRestrictedSendEmbed); + } + if (o.Permissions.CanChangeInfo != n.Permissions.CanChangeInfo) + { + AppendChange(n.Permissions.CanChangeInfo, Strings.Resources.EventLogRestrictedChangeInfo); + } + if (o.Permissions.CanInviteUsers != n.Permissions.CanInviteUsers) + { + AppendChange(n.Permissions.CanInviteUsers, Strings.Resources.EventLogRestrictedSendEmbed); + } + if (o.Permissions.CanPinMessages != n.Permissions.CanPinMessages) + { + AppendChange(n.Permissions.CanPinMessages, Strings.Resources.EventLogRestrictedPinMessages); + } + + text = rights.ToString(); + } + else + { + String str; + if (o == null || memberRestricted.NewStatus is ChatMemberStatusBanned) + { + str = Strings.Resources.EventLogChannelRestricted; + } + else + { + str = Strings.Resources.EventLogChannelUnrestricted; + } + + text = String.Format(str, GetUserName(whoUser, entities, str.IndexOf("{0}"))); + } + + return new MessageText(new FormattedText(text, entities), null); + } + else if (item.Action is ChatEventMemberPromoted memberPromoted) + { + var entities = new List(); + + var whoUser = CacheService.GetUser(memberPromoted.UserId); + var str = Strings.Resources.EventLogPromoted; + var userName = GetUserName(whoUser, entities, str.IndexOf("{0}")); + var builder = new StringBuilder(string.Format(str, userName)); + var added = false; + + ChatMemberStatusAdministrator o = null; + ChatMemberStatusAdministrator n = null; + + if (memberPromoted.OldStatus is ChatMemberStatusAdministrator oldAdmin) + { + o = oldAdmin; + } + if (memberPromoted.NewStatus is ChatMemberStatusAdministrator newAdmin) + { + n = newAdmin; + } + + if (o == null) + { + o = new ChatMemberStatusAdministrator(); + } + if (n == null) + { + n = new ChatMemberStatusAdministrator(); + } + + void AppendChange(bool value, string label) + { + if (!added) + { + builder.Append('\n'); + added = true; + } + + builder.Append('\n').Append(value ? '+' : '-').Append(' '); + builder.Append(label); + } + + if (o.CanChangeInfo != n.CanChangeInfo) + { + AppendChange(n.CanChangeInfo, channel ? Strings.Resources.EventLogPromotedChangeChannelInfo : Strings.Resources.EventLogPromotedChangeGroupInfo); + } + + if (channel) + { + if (o.CanPostMessages != n.CanPostMessages) + { + AppendChange(n.CanPostMessages, Strings.Resources.EventLogPromotedPostMessages); + } + if (o.CanEditMessages != n.CanEditMessages) + { + AppendChange(n.CanEditMessages, Strings.Resources.EventLogPromotedEditMessages); + } + } + if (o.CanDeleteMessages != n.CanDeleteMessages) + { + AppendChange(n.CanDeleteMessages, Strings.Resources.EventLogPromotedDeleteMessages); + } + if (o.CanPromoteMembers != n.CanPromoteMembers) + { + AppendChange(n.CanPromoteMembers, Strings.Resources.EventLogPromotedAddAdmins); + } + if (!channel) + { + if (o.CanRestrictMembers != n.CanRestrictMembers) + { + AppendChange(n.CanRestrictMembers, Strings.Resources.EventLogPromotedBanUsers); + } + } + if (o.CanInviteUsers != n.CanInviteUsers) + { + AppendChange(n.CanInviteUsers, Strings.Resources.EventLogPromotedAddUsers); + } + if (!channel) + { + if (o.CanPinMessages != n.CanPinMessages) + { + AppendChange(n.CanPinMessages, Strings.Resources.EventLogPromotedPinMessages); + } + } + + return new MessageText(new FormattedText(builder.ToString(), entities), null); + } + + return new MessageChatEvent(item, true); + } + + private string GetUserName(User user, List entities, int offset) + { + string name; + if (user == null) + { + name = string.Empty; + } + else + { + name = user.GetFullName(); + } + + if (offset >= 0) + { + entities.Add(new TextEntity(offset, name.Length, new TextEntityTypeMentionName(user.Id))); + } + + if (string.IsNullOrEmpty(user.Username)) + { + return name; + } + + if (offset >= 0) + { + entities.Add(new TextEntity((name.Length + offset) + 2, user.Username.Length + 1, new TextEntityTypeMentionName(user.Id))); + } + + return string.Format("{0} (@{1})", name, user.Username); + } + } +} diff --git a/Unigram/Unigram/ViewModels/DialogScheduledViewModel.cs b/Unigram/Unigram/ViewModels/DialogScheduledViewModel.cs index c5aa6ac2db..418e58c7b5 100644 --- a/Unigram/Unigram/ViewModels/DialogScheduledViewModel.cs +++ b/Unigram/Unigram/ViewModels/DialogScheduledViewModel.cs @@ -10,6 +10,6 @@ public DialogScheduledViewModel(IProtoService protoService, ICacheService cacheS { } - public override bool IsSchedule => true; + public override DialogType Type => DialogType.ScheduledMessages; } } diff --git a/Unigram/Unigram/ViewModels/DialogViewModel.Handle.cs b/Unigram/Unigram/ViewModels/DialogViewModel.Handle.cs index cb6add2aae..6ce40287a8 100644 --- a/Unigram/Unigram/ViewModels/DialogViewModel.Handle.cs +++ b/Unigram/Unigram/ViewModels/DialogViewModel.Handle.cs @@ -378,7 +378,7 @@ public void Handle(UpdateChatLastMessage update) private bool CheckSchedulingState(Message message) { - if (_isSchedule) + if (_type == DialogType.ScheduledMessages) { return message.SchedulingState != null; } @@ -451,8 +451,6 @@ public void Handle(UpdateDeleteMessages update) { Items.RemoveAt(i); i--; - - break; } else if (table.Contains(message.ReplyToMessageId)) { @@ -885,7 +883,7 @@ private async void InsertMessage(Message message, long? oldMessageId = null) //if (IsEndReached()) //if (endReached || IsEndReached()) - if (IsFirstSliceLoaded == true || IsSchedule) + if (IsFirstSliceLoaded == true || Type == DialogType.ScheduledMessages) { var messageCommon = _messageFactory.Create(this, message); messageCommon.GeneratedContentUnread = true; diff --git a/Unigram/Unigram/ViewModels/DialogViewModel.Media.cs b/Unigram/Unigram/ViewModels/DialogViewModel.Media.cs index 1257bc5983..02336ea09b 100644 --- a/Unigram/Unigram/ViewModels/DialogViewModel.Media.cs +++ b/Unigram/Unigram/ViewModels/DialogViewModel.Media.cs @@ -264,7 +264,7 @@ public async void SendFileExecute(IReadOnlyList files, FormattedTex var self = CacheService.IsSavedMessages(_chat); - var dialog = new SendFilesPopup(items, media, _chat.Type is ChatTypePrivate && !self, !_isSchedule, self); + var dialog = new SendFilesPopup(items, media, _chat.Type is ChatTypePrivate && !self, _type == DialogType.Normal, self); dialog.ViewModel = this; dialog.Caption = caption; @@ -560,7 +560,7 @@ public async Task PickSendMessageOptionsAsync(bool? schedule return null; } - if (schedule == true || (_isSchedule && schedule == null)) + if (schedule == true || (_type == DialogType.ScheduledMessages && schedule == null)) { var user = CacheService.GetUser(chat); diff --git a/Unigram/Unigram/ViewModels/DialogViewModel.cs b/Unigram/Unigram/ViewModels/DialogViewModel.cs index e33ed6eee7..7fc4b872dc 100644 --- a/Unigram/Unigram/ViewModels/DialogViewModel.cs +++ b/Unigram/Unigram/ViewModels/DialogViewModel.cs @@ -69,22 +69,22 @@ public void ExpandSelection(IEnumerable vector) SelectedItems = messages; } - private readonly ConcurrentDictionary _groupedMessages = new ConcurrentDictionary(); + protected readonly ConcurrentDictionary _groupedMessages = new ConcurrentDictionary(); - private static readonly ConcurrentDictionary> _admins = new ConcurrentDictionary>(); + protected static readonly ConcurrentDictionary> _admins = new ConcurrentDictionary>(); - private readonly DisposableMutex _loadMoreLock = new DisposableMutex(); - private readonly DisposableMutex _insertLock = new DisposableMutex(); + protected readonly DisposableMutex _loadMoreLock = new DisposableMutex(); + protected readonly DisposableMutex _insertLock = new DisposableMutex(); - private readonly StickerDrawerViewModel _stickers; - private readonly AnimationDrawerViewModel _animations; + protected readonly StickerDrawerViewModel _stickers; + protected readonly AnimationDrawerViewModel _animations; - private readonly ILocationService _locationService; - private readonly INotificationsService _pushService; - private readonly IPlaybackService _playbackService; - private readonly IVoIPService _voipService; - private readonly INetworkService _networkService; - private readonly IMessageFactory _messageFactory; + protected readonly ILocationService _locationService; + protected readonly INotificationsService _pushService; + protected readonly IPlaybackService _playbackService; + protected readonly IVoIPService _voipService; + protected readonly INetworkService _networkService; + protected readonly IMessageFactory _messageFactory; public IPlaybackService PlaybackService => _playbackService; @@ -237,7 +237,7 @@ public override IDispatcherWrapper Dispatcher } } - private Chat _migratedChat; + protected Chat _migratedChat; public Chat MigratedChat { get @@ -250,14 +250,14 @@ public Chat MigratedChat } } - private Chat _linkedChat; + protected Chat _linkedChat; public Chat LinkedChat { get => _linkedChat; set => Set(ref _linkedChat, value); } - private Chat _chat; + protected Chat _chat; public Chat Chat { get @@ -276,8 +276,8 @@ public Chat Chat // get => _isSchedule; // set => Set(ref _isSchedule, value); //} - private bool _isSchedule => IsSchedule; - public virtual bool IsSchedule => false; + private DialogType _type => Type; + public virtual DialogType Type => DialogType.Normal; private string _lastSeen; public string LastSeen @@ -595,10 +595,10 @@ public override bool IsLoading } } - private bool _isLoadingNextSlice; - private bool _isLoadingPreviousSlice; + protected bool _isLoadingNextSlice; + protected bool _isLoadingPreviousSlice; - private Stack _goBackStack = new Stack(); + protected Stack _goBackStack = new Stack(); public async Task LoadNextSliceAsync(bool force = false, bool init = false) { @@ -620,7 +620,7 @@ public async Task LoadNextSliceAsync(bool force = false, bool init = false) return; } - if (_isSchedule || _isLoadingNextSlice || _isLoadingPreviousSlice || Items.Count < 1 || IsLastSliceLoaded == true) + if (_type != DialogType.Normal || _isLoadingNextSlice || _isLoadingPreviousSlice || Items.Count < 1 || IsLastSliceLoaded == true) { return; } @@ -723,7 +723,7 @@ public async Task LoadPreviousSliceAsync(bool force = false, bool init = false) return; } - if (_isSchedule || _isLoadingNextSlice || _isLoadingPreviousSlice || chat == null || Items.Count < 1) + if (_type != DialogType.Normal || _isLoadingNextSlice || _isLoadingPreviousSlice || chat == null || Items.Count < 1) { return; } @@ -969,6 +969,11 @@ private async void PreviousSliceExecute() public async Task LoadMessageSliceAsync(long? previousId, long maxId, VerticalAlignment alignment = VerticalAlignment.Center, double? pixel = null, ScrollIntoViewAlignment? direction = null, bool? disableAnimation = null, bool second = false) { + if (_type != DialogType.Normal) + { + return; + } + if (direction == null) { var field = ListField; @@ -1190,6 +1195,11 @@ public async Task LoadScheduledSliceAsync() } } + public virtual Task LoadEventLogSliceAsync() + { + return Task.CompletedTask; + } + public async Task LoadDateSliceAsync(int dateOffset) { var chat = _chat; @@ -1238,7 +1248,7 @@ public void ScrollToBottom(object item) public MessageCollection Items { get; } = new MessageCollection(); - private async Task ProcessMessagesAsync(Chat chat, IList messages) + protected async Task ProcessMessagesAsync(Chat chat, IList messages) { if (Settings.IsLargeEmojiEnabled) { @@ -1305,11 +1315,32 @@ private void ProcessFiles(Chat chat, IList messages, MessageVi var target = parent ?? message; var content = message.GeneratedContent ?? message.Content as object; + if (content is MessageAlbum albumMessage) { ProcessFiles(chat, albumMessage.Layout.Messages, message); continue; } + else if (content is MessageChatEvent chatEvent) + { + if (chatEvent.Event.Action is ChatEventMessageDeleted messageDeleted) + { + content = messageDeleted.Message.Content; + } + else if (chatEvent.Event.Action is ChatEventMessageEdited messageEdited) + { + content = messageEdited.NewMessage.Content; + } + else if (chatEvent.Event.Action is ChatEventMessagePinned messagePinned) + { + content = messagePinned.Message.Content; + } + else if (chatEvent.Event.Action is ChatEventPollStopped pollStopped) + { + content = pollStopped.Message.Content; + } + } + if (content is MessageAnimation animationMessage) { content = animationMessage.Animation; @@ -1696,12 +1727,18 @@ public override async Task OnNavigatedToAsync(object parameter, NavigationMode m } #pragma warning disable CS4014 - if (_isSchedule) + if (_type == DialogType.ScheduledMessages) { Logs.Logger.Debug(Logs.Target.Chat, string.Format("{0} - Loadings scheduled messages", chat.Id)); LoadScheduledSliceAsync(); } + else if (_type == DialogType.EventLog) + { + Logs.Logger.Debug(Logs.Target.Chat, string.Format("{0} - Loadings event log", chat.Id)); + + LoadEventLogSliceAsync(); + } else if (state.TryGet("message_id", out long navigation)) { Logs.Logger.Debug(Logs.Target.Chat, string.Format("{0} - Loading messages from specific id", chat.Id)); @@ -3144,6 +3181,11 @@ private void ScheduledExecute() #region Action + protected virtual void FilterExecute() + { + + } + public RelayCommand ActionCommand { get; } private void ActionExecute() { @@ -3153,7 +3195,11 @@ private void ActionExecute() return; } - if (chat.Type is ChatTypePrivate privata) + if (_type == DialogType.EventLog) + { + FilterExecute(); + } + else if (chat.Type is ChatTypePrivate privata) { var fullInfo = ProtoService.GetUserFull(privata.UserId); if (fullInfo == null) @@ -3558,4 +3604,11 @@ public enum ReplyToMessageState Loading, Deleted } + + public enum DialogType + { + Normal, + ScheduledMessages, + EventLog + } } diff --git a/Unigram/Unigram/ViewModels/MessageViewModel.cs b/Unigram/Unigram/ViewModels/MessageViewModel.cs index f345bf3018..d76d366cd1 100644 --- a/Unigram/Unigram/ViewModels/MessageViewModel.cs +++ b/Unigram/Unigram/ViewModels/MessageViewModel.cs @@ -172,7 +172,7 @@ public bool IsShareable() // return true; //} //else - if (message.Content is MessageSticker) + if (message.Content is MessageSticker || message.Content is MessageChatEvent) { return false; } diff --git a/Unigram/Unigram/ViewModels/Supergroups/SupergroupAdministratorsViewModel.cs b/Unigram/Unigram/ViewModels/Supergroups/SupergroupAdministratorsViewModel.cs index c2d5e3cd34..1d2ef342e2 100644 --- a/Unigram/Unigram/ViewModels/Supergroups/SupergroupAdministratorsViewModel.cs +++ b/Unigram/Unigram/ViewModels/Supergroups/SupergroupAdministratorsViewModel.cs @@ -1,6 +1,7 @@ using Telegram.Td.Api; using Unigram.Common; using Unigram.Services; +using Unigram.Views; using Unigram.Views.Supergroups; namespace Unigram.ViewModels.Supergroups @@ -24,7 +25,7 @@ private void EventLogExecute() return; } - NavigationService.Navigate(typeof(SupergroupEventLogPage), chat.Id); + NavigationService.Navigate(typeof(ChatEventLogPage), chat.Id); } public RelayCommand AddCommand { get; } diff --git a/Unigram/Unigram/ViewModels/Supergroups/SupergroupEventLogViewModel.cs b/Unigram/Unigram/ViewModels/Supergroups/SupergroupEventLogViewModel.cs deleted file mode 100644 index 86469cd962..0000000000 --- a/Unigram/Unigram/ViewModels/Supergroups/SupergroupEventLogViewModel.cs +++ /dev/null @@ -1,953 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading.Tasks; -using Telegram.Td.Api; -using Unigram.Collections; -using Unigram.Common; -using Unigram.Controls; -using Unigram.Converters; -using Unigram.Services; -using Unigram.Services.Factories; -using Unigram.ViewModels.Delegates; -using Unigram.Views.Popups; -using Windows.UI.Xaml; -using Windows.UI.Xaml.Controls; -using Windows.UI.Xaml.Navigation; - -namespace Unigram.ViewModels.Supergroups -{ - public class SupergroupEventLogViewModel : TLViewModelBase, IDelegable, IMessageDelegate - { - private readonly IMessageFactory _messageFactory; - - public SupergroupEventLogViewModel(IProtoService protoService, ICacheService cacheService, ISettingsService settingsService, IMessageFactory messageFactory, IEventAggregator aggregator) - : base(protoService, cacheService, settingsService, aggregator) - { - _messageFactory = messageFactory; - - FiltersCommand = new RelayCommand(FiltersExecute); - HelpCommand = new RelayCommand(HelpExecute); - } - - public IChatDelegate Delegate { get; set; } - - protected Chat _chat; - public Chat Chat - { - get - { - return _chat; - } - set - { - Set(ref _chat, value); - } - } - - private ChatEventLogFilters _filters = new ChatEventLogFilters(true, true, true, true, true, true, true, true, true, true); - public ChatEventLogFilters Filters - { - get - { - return _filters; - } - set - { - Set(ref _filters, value); - } - } - - private IList _userIds = new int[0]; - public IList UserIds - { - get - { - return _userIds; - } - set - { - Set(ref _userIds, value); - } - } - - private bool _isEmpty = true; - public bool IsEmpty - { - get - { - return _isEmpty && !IsLoading; - } - set - { - Set(ref _isEmpty, value); - } - } - - public override bool IsLoading - { - get - { - return base.IsLoading; - } - set - { - base.IsLoading = value; - RaisePropertyChanged(() => IsEmpty); - } - } - - public override Task OnNavigatedToAsync(object parameter, NavigationMode mode, IDictionary state) - { - var chatId = (long)parameter; - - Chat = ProtoService.GetChat(chatId); - - var chat = _chat; - if (chat == null) - { - return Task.CompletedTask; - } - - Delegate?.UpdateChat(chat); - - Items = new ItemsCollection(ProtoService, _messageFactory, this, chat.Id, chat.Type is ChatTypeSupergroup supergroup && supergroup.IsChannel, _filters, _userIds); - Items.CollectionChanged += (s, args) => IsEmpty = Items.Count == 0; - - RaisePropertyChanged(() => Items); - - return Task.CompletedTask; - } - - public RelayCommand FiltersCommand { get; } - private async void FiltersExecute() - { - var chat = _chat; - if (chat == null) - { - return; - } - - var supergroup = CacheService.GetSupergroup(chat); - if (supergroup == null) - { - return; - } - - var dialog = new SupergroupEventLogFiltersPopup(); - - var confirm = await dialog.ShowAsync(ProtoService, supergroup.Id, _filters, _userIds); - if (confirm == ContentDialogResult.Primary) - { - Filters = dialog.Filters; - UserIds = dialog.UserIds; - Items = new ItemsCollection(ProtoService, _messageFactory, this, chat.Id, supergroup.IsChannel, dialog.Filters, dialog.AreAllAdministratorsSelected ? new int[0] : dialog.UserIds); - - RaisePropertyChanged(() => Items); - } - } - - public RelayCommand HelpCommand { get; } - private async void HelpExecute() - { - var chat = _chat; - if (chat == null) - { - return; - } - - await MessagePopup.ShowAsync(chat.Type is ChatTypeSupergroup supergroup && supergroup.IsChannel ? Strings.Resources.EventLogInfoDetailChannel : Strings.Resources.EventLogInfoDetail, Strings.Resources.EventLogInfoTitle, Strings.Resources.OK); - } - - public ItemsCollection Items { get; protected set; } - - public class ItemsCollection : IncrementalCollection - { - private readonly IProtoService _protoService; - private readonly IMessageFactory _messageFactory; - private readonly IMessageDelegate _delegate; - private readonly long _chatId; - private readonly bool _channel; - private readonly ChatEventLogFilters _filters; - private readonly IList _userIds; - - private long _minEventId = long.MaxValue; - private bool _hasMore; - - public ItemsCollection(IProtoService protoService, IMessageFactory messageFactory, IMessageDelegate delegato, long chatId, bool channel, ChatEventLogFilters filters, IList userIds) - { - _protoService = protoService; - _messageFactory = messageFactory; - _delegate = delegato; - _chatId = chatId; - _channel = channel; - _filters = filters; - _userIds = userIds; - - _hasMore = true; - } - - private Message newMessage(long chatId, bool isChannel, ChatEvent chatEvent) - { - return new Message(chatEvent.Id, chatEvent.UserId, chatId, null, null, false, false, false, false, false, isChannel, false, chatEvent.Date, 0, null, 0, 0, 0.0d, 0, string.Empty, 0, 0, string.Empty, null, null); - } - - private MessageViewModel GetMessage(long chatId, bool isChannel, ChatEvent chatEvent) - { - var message = _messageFactory.Create(_delegate, newMessage(chatId, isChannel, chatEvent)); - message.IsFirst = true; - message.IsLast = true; - - return message; - } - - public override async Task> LoadDataAsync() - { - _hasMore = false; - - var maxId = Count > 0 ? _minEventId : 0; - - var response = await _protoService.SendAsync(new GetChatEventLog(_chatId, string.Empty, 0, 50, _filters, _userIds)); - if (response is ChatEvents events) - { - var result = new List(); - - foreach (var item in events.Events) - { - _minEventId = Math.Min(_minEventId, item.Id); - - MessageViewModel message = null; - switch (item.Action) - { - case ChatEventMemberInvited memberInvited: - message = GetMessage(_chatId, _channel, item); - message.Content = new MessageChatAddMembers(new[] { memberInvited.UserId }); - break; - case ChatEventSlowModeDelayChanged slowModeDelayChanged: - case ChatEventPermissionsChanged permissionsChanged: - case ChatEventMemberRestricted memberRestricted: - case ChatEventMemberPromoted memberPromoted: - message = GetMessage(_chatId, _channel, item); - //message.Content = new MessageChatEvent(item, true); - message.Content = GetMessageContent(item); - break; - case ChatEventSignMessagesToggled signMessagesToggled: - case ChatEventStickerSetChanged stickerSetChanged: - case ChatEventInvitesToggled invitesToggled: - case ChatEventIsAllHistoryAvailableToggled isAllHistoryAvailableToggled: - case ChatEventMessageUnpinned messageUnpinned: - case ChatEventLinkedChatChanged linkedChatChanged: - case ChatEventLocationChanged locationChanged: - message = GetMessage(_chatId, _channel, item); - message.Content = new MessageChatEvent(item, false); - break; - case ChatEventMemberLeft memberLeft: - message = GetMessage(_chatId, _channel, item); - message.Content = new MessageChatDeleteMember(item.UserId); - break; - case ChatEventMessageDeleted messageDeleted: - case ChatEventMessageEdited messageEdited: - case ChatEventDescriptionChanged descriptionChanged: - case ChatEventMessagePinned messagePinned: - case ChatEventUsernameChanged usernameChanged: - case ChatEventPollStopped pollStopped: - message = GetMessage(_chatId, _channel, item); - //message.Content = new MessageChatEvent(item, true); - message.Content = GetMessageContent(item); - result.Add(message); - message = GetMessage(_chatId, _channel, item); - message.Content = new MessageChatEvent(item, false); - break; - case ChatEventPhotoChanged photoChanged: - message = GetMessage(_chatId, _channel, item); - if (photoChanged.NewPhoto == null) - { - message.Content = new MessageChatDeletePhoto(); - break; - } - - message.Content = new MessageChatChangePhoto(photoChanged.NewPhoto); - break; - case ChatEventMemberJoined memberJoined: - message = GetMessage(_chatId, _channel, item); - message.Content = new MessageChatAddMembers(new int[] { item.UserId }); - break; - case ChatEventTitleChanged titleChanged: - message = GetMessage(_chatId, _channel, item); - message.Content = new MessageChatChangeTitle(titleChanged.NewTitle); - break; - } - - - if (message != null) - { - result.Add(message); - } - } - - //if (response.Result.Events.Count < 50) - //{ - // _hasMore = false; - //} - - result.Reverse(); - return result; - } - - return new MessageViewModel[0]; - } - - private MessageContent GetMessageContent(ChatEvent item) - { - if (item.Action is ChatEventDescriptionChanged descriptionChanged) - { - var text = new FormattedText(descriptionChanged.NewDescription, new TextEntity[0]); - var webPage = string.IsNullOrEmpty(descriptionChanged.OldDescription) ? null : new WebPage { SiteName = Strings.Resources.EventLogPreviousGroupDescription, Description = new FormattedText { Text = descriptionChanged.OldDescription } }; - - return new MessageText(text, webPage); - } - else if (item.Action is ChatEventUsernameChanged usernameChanged) - { - var link = string.IsNullOrEmpty(usernameChanged.NewUsername) ? string.Empty : MeUrlPrefixConverter.Convert(_protoService, usernameChanged.NewUsername); - - var text = new FormattedText(link, new[] { new TextEntity(0, link.Length, new TextEntityTypeUrl()) }); - var webPage = string.IsNullOrEmpty(usernameChanged.OldUsername) ? null : new WebPage { SiteName = Strings.Resources.EventLogPreviousLink, Description = new FormattedText { Text = MeUrlPrefixConverter.Convert(_protoService, usernameChanged.OldUsername) } }; - - return new MessageText(text, webPage); - } - else if (item.Action is ChatEventPermissionsChanged permissionChanged) - { - var text = string.Empty; - var entities = new List(); - - ChatPermissions o = permissionChanged.OldPermissions; - ChatPermissions n = permissionChanged.NewPermissions; - - if (o == null) - { - o = new ChatPermissions(); - } - if (n == null) - { - n = new ChatPermissions(); - } - - var rights = new StringBuilder(Strings.Resources.EventLogDefaultPermissions); - var added = false; - - void AppendChange(bool value, string label) - { - if (!added) - { - rights.Append('\n'); - added = true; - } - - rights.Append('\n').Append(value ? '+' : '-').Append(' '); - rights.Append(label); - } - - //if (o.IsViewMessages != n.IsViewMessages) - //{ - // AppendChange(n.IsViewMessages, Strings.Resources.EventLogRestrictedReadMessages); - //} - if (o.CanSendMessages != n.CanSendMessages) - { - AppendChange(n.CanSendMessages, Strings.Resources.EventLogRestrictedSendMessages); - } - if (o.CanSendOtherMessages != n.CanSendOtherMessages) - { - AppendChange(n.CanSendOtherMessages, Strings.Resources.EventLogRestrictedSendStickers); - } - if (o.CanSendMediaMessages != n.CanSendMediaMessages) - { - AppendChange(n.CanSendMediaMessages, Strings.Resources.EventLogRestrictedSendMedia); - } - if (o.CanSendPolls != n.CanSendPolls) - { - AppendChange(n.CanSendPolls, Strings.Resources.EventLogRestrictedSendPolls); - } - if (o.CanAddWebPagePreviews != n.CanAddWebPagePreviews) - { - AppendChange(n.CanAddWebPagePreviews, Strings.Resources.EventLogRestrictedSendEmbed); - } - if (o.CanChangeInfo != n.CanChangeInfo) - { - AppendChange(n.CanChangeInfo, Strings.Resources.EventLogRestrictedChangeInfo); - } - if (o.CanInviteUsers != n.CanInviteUsers) - { - AppendChange(n.CanInviteUsers, Strings.Resources.EventLogRestrictedSendEmbed); - } - if (o.CanPinMessages != n.CanPinMessages) - { - AppendChange(n.CanPinMessages, Strings.Resources.EventLogRestrictedPinMessages); - } - - text = rights.ToString(); - - return new MessageText(new FormattedText(text, entities), null); - } - else if (item.Action is ChatEventMemberRestricted memberRestricted) - { - var text = string.Empty; - var entities = new List(); - - var whoUser = _protoService.GetUser(memberRestricted.UserId); - ChatMemberStatusRestricted o = null; - ChatMemberStatusRestricted n = null; - - if (memberRestricted.OldStatus is ChatMemberStatusRestricted oldRestricted) - { - o = oldRestricted; - } - else if (memberRestricted.OldStatus is ChatMemberStatusBanned oldBanned) - { - o = new ChatMemberStatusRestricted(false, oldBanned.BannedUntilDate, new ChatPermissions(false, false, false, false, false, false, false, false)); - } - else if (memberRestricted.OldStatus is ChatMemberStatusMember) - { - o = new ChatMemberStatusRestricted(true, 0, new ChatPermissions(true, true, true, true, true, true, true, true)); - } - - if (memberRestricted.NewStatus is ChatMemberStatusRestricted newRestricted) - { - n = newRestricted; - } - else if (memberRestricted.NewStatus is ChatMemberStatusBanned newBanned) - { - n = new ChatMemberStatusRestricted(false, newBanned.BannedUntilDate, new ChatPermissions(false, false, false, false, false, false, false, false)); - } - else if (memberRestricted.NewStatus is ChatMemberStatusMember) - { - n = new ChatMemberStatusRestricted(true, 0, new ChatPermissions(true, true, true, true, true, true, true, true)); - } - - if (!_channel && (n == null || n != null && o != null /*&& n.RestrictedUntilDate != o.RestrictedUntilDate*/)) - { - StringBuilder rights; - String bannedDuration; - if (n != null && !n.IsForever()) - { - bannedDuration = ""; - int duration = n.RestrictedUntilDate - item.Date; - int days = duration / 60 / 60 / 24; - duration -= days * 60 * 60 * 24; - int hours = duration / 60 / 60; - duration -= hours * 60 * 60; - int minutes = duration / 60; - int count = 0; - for (int a = 0; a < 3; a++) - { - String addStr = null; - if (a == 0) - { - if (days != 0) - { - addStr = Locale.Declension("Days", days); - count++; - } - } - else if (a == 1) - { - if (hours != 0) - { - addStr = Locale.Declension("Hours", hours); - count++; - } - } - else - { - if (minutes != 0) - { - addStr = Locale.Declension("Minutes", minutes); - count++; - } - } - if (addStr != null) - { - if (bannedDuration.Length > 0) - { - bannedDuration += ", "; - } - bannedDuration += addStr; - } - if (count == 2) - { - break; - } - } - } - else - { - bannedDuration = Strings.Resources.UserRestrictionsUntilForever; - } - - var str = Strings.Resources.EventLogRestrictedUntil; - rights = new StringBuilder(String.Format(str, GetUserName(whoUser, entities, str.IndexOf("{0}")), bannedDuration)); - var added = false; - if (o == null) - { - o = new ChatMemberStatusRestricted(true, 0, new ChatPermissions(true, true, true, true, true, true, true, true)); - } - if (n == null) - { - n = new ChatMemberStatusRestricted(true, 0, new ChatPermissions(true, true, true, true, true, true, true, true)); - } - - void AppendChange(bool value, string label) - { - if (!added) - { - rights.Append('\n'); - added = true; - } - - rights.Append('\n').Append(value ? '+' : '-').Append(' '); - rights.Append(label); - } - - //if (o.IsViewMessages != n.IsViewMessages) - //{ - // AppendChange(n.IsViewMessages, Strings.Resources.EventLogRestrictedReadMessages); - //} - if (o.Permissions.CanSendMessages != n.Permissions.CanSendMessages) - { - AppendChange(n.Permissions.CanSendMessages, Strings.Resources.EventLogRestrictedSendMessages); - } - if (o.Permissions.CanSendOtherMessages != n.Permissions.CanSendOtherMessages) - { - AppendChange(n.Permissions.CanSendOtherMessages, Strings.Resources.EventLogRestrictedSendStickers); - } - if (o.Permissions.CanSendMediaMessages != n.Permissions.CanSendMediaMessages) - { - AppendChange(n.Permissions.CanSendMediaMessages, Strings.Resources.EventLogRestrictedSendMedia); - } - if (o.Permissions.CanSendPolls != n.Permissions.CanSendPolls) - { - AppendChange(n.Permissions.CanSendPolls, Strings.Resources.EventLogRestrictedSendPolls); - } - if (o.Permissions.CanAddWebPagePreviews != n.Permissions.CanAddWebPagePreviews) - { - AppendChange(n.Permissions.CanAddWebPagePreviews, Strings.Resources.EventLogRestrictedSendEmbed); - } - if (o.Permissions.CanChangeInfo != n.Permissions.CanChangeInfo) - { - AppendChange(n.Permissions.CanChangeInfo, Strings.Resources.EventLogRestrictedChangeInfo); - } - if (o.Permissions.CanInviteUsers != n.Permissions.CanInviteUsers) - { - AppendChange(n.Permissions.CanInviteUsers, Strings.Resources.EventLogRestrictedSendEmbed); - } - if (o.Permissions.CanPinMessages != n.Permissions.CanPinMessages) - { - AppendChange(n.Permissions.CanPinMessages, Strings.Resources.EventLogRestrictedPinMessages); - } - - text = rights.ToString(); - } - else - { - String str; - if (o == null || memberRestricted.NewStatus is ChatMemberStatusBanned) - { - str = Strings.Resources.EventLogChannelRestricted; - } - else - { - str = Strings.Resources.EventLogChannelUnrestricted; - } - - text = String.Format(str, GetUserName(whoUser, entities, str.IndexOf("{0}"))); - } - - return new MessageText(new FormattedText(text, entities), null); - } - else if (item.Action is ChatEventMemberPromoted memberPromoted) - { - var entities = new List(); - - var whoUser = _protoService.GetUser(memberPromoted.UserId); - var str = Strings.Resources.EventLogPromoted; - var userName = GetUserName(whoUser, entities, str.IndexOf("{0}")); - var builder = new StringBuilder(string.Format(str, userName)); - var added = false; - - ChatMemberStatusAdministrator o = null; - ChatMemberStatusAdministrator n = null; - - if (memberPromoted.OldStatus is ChatMemberStatusAdministrator oldAdmin) - { - o = oldAdmin; - } - if (memberPromoted.NewStatus is ChatMemberStatusAdministrator newAdmin) - { - n = newAdmin; - } - - if (o == null) - { - o = new ChatMemberStatusAdministrator(); - } - if (n == null) - { - n = new ChatMemberStatusAdministrator(); - } - - void AppendChange(bool value, string label) - { - if (!added) - { - builder.Append('\n'); - added = true; - } - - builder.Append('\n').Append(value ? '+' : '-').Append(' '); - builder.Append(label); - } - - if (o.CanChangeInfo != n.CanChangeInfo) - { - AppendChange(n.CanChangeInfo, _channel ? Strings.Resources.EventLogPromotedChangeChannelInfo : Strings.Resources.EventLogPromotedChangeGroupInfo); - } - - if (_channel) - { - if (o.CanPostMessages != n.CanPostMessages) - { - AppendChange(n.CanPostMessages, Strings.Resources.EventLogPromotedPostMessages); - } - if (o.CanEditMessages != n.CanEditMessages) - { - AppendChange(n.CanEditMessages, Strings.Resources.EventLogPromotedEditMessages); - } - } - if (o.CanDeleteMessages != n.CanDeleteMessages) - { - AppendChange(n.CanDeleteMessages, Strings.Resources.EventLogPromotedDeleteMessages); - } - if (o.CanPromoteMembers != n.CanPromoteMembers) - { - AppendChange(n.CanPromoteMembers, Strings.Resources.EventLogPromotedAddAdmins); - } - if (!_channel) - { - if (o.CanRestrictMembers != n.CanRestrictMembers) - { - AppendChange(n.CanRestrictMembers, Strings.Resources.EventLogPromotedBanUsers); - } - } - if (o.CanInviteUsers != n.CanInviteUsers) - { - AppendChange(n.CanInviteUsers, Strings.Resources.EventLogPromotedAddUsers); - } - if (!_channel) - { - if (o.CanPinMessages != n.CanPinMessages) - { - AppendChange(n.CanPinMessages, Strings.Resources.EventLogPromotedPinMessages); - } - } - - return new MessageText(new FormattedText(builder.ToString(), entities), null); - } - - return new MessageChatEvent(item, true); - } - - private string GetUserName(User user, List entities, int offset) - { - string name; - if (user == null) - { - name = string.Empty; - } - else - { - name = user.GetFullName(); - } - - if (offset >= 0) - { - entities.Add(new TextEntity(offset, name.Length, new TextEntityTypeMentionName(user.Id))); - } - - if (string.IsNullOrEmpty(user.Username)) - { - return name; - } - - if (offset >= 0) - { - entities.Add(new TextEntity((name.Length + offset) + 2, user.Username.Length + 1, new TextEntityTypeMentionName(user.Id))); - } - - return string.Format("{0} (@{1})", name, user.Username); - } - - protected override bool GetHasMoreItems() - { - return _hasMore; - } - - #region Insert - - //protected override void InsertItem(int index, MessageViewModel item) - //{ - // base.InsertItem(index, item); - - // var previous = index > 0 ? this[index - 1] : null; - // var next = index < Count - 1 ? this[index + 1] : null; - - // //if (next is TLMessageEmpty) - // //{ - // // next = index > 1 ? this[index - 2] : null; - // //} - // //if (previous is TLMessageEmpty) - // //{ - // // previous = index < Count - 2 ? this[index + 2] : null; - // //} - - // UpdateSeparatorOnInsert(item, next, index); - // UpdateSeparatorOnInsert(previous, item, index - 1); - - // UpdateAttach(next, item, index + 1); - // UpdateAttach(item, previous, index); - //} - - //protected override void RemoveItem(int index) - //{ - // var next = index > 0 ? this[index - 1] : null; - // var previous = index < Count - 1 ? this[index + 1] : null; - - // UpdateAttach(previous, next, index + 1); - - // base.RemoveItem(index); - - // UpdateSeparatorOnRemove(next, previous, index); - //} - - //private void UpdateSeparatorOnInsert(MessageViewModel item, MessageViewModel previous, int index) - //{ - // if (item != null && previous != null) - // { - // if ((item is TLMessageService itemService && itemService.Action is TLMessageActionAdminLogEvent) || (previous is TLMessageService previousService && previousService.Action is TLMessageActionAdminLogEvent)) - // { - // return; - // } - - // if (item.Id == previous.Id) - // { - // return; - // } - - // var itemDate = Utils.UnixTimestampToDateTime(item.Date); - // var previousDate = Utils.UnixTimestampToDateTime(previous.Date); - // if (previousDate.Date != itemDate.Date) - // { - // var timestamp = (int)Utils.DateTimeToUnixTimestamp(previousDate.Date); - // var service = new TLMessageService - // { - // Date = timestamp, - // FromId = SettingsHelper.UserId, - // HasFromId = true, - // Action = new TLMessageActionDate - // { - // Date = timestamp - // } - // }; - - // base.InsertItem(index + 1, service); - // } - // } - //} - - //private void UpdateSeparatorOnRemove(MessageViewModel next, MessageViewModel previous, int index) - //{ - // if (next is TLMessageService && previous != null) - // { - // var action = ((TLMessageService)next).Action as TLMessageActionDate; - // if (action != null) - // { - // var itemDate = Utils.UnixTimestampToDateTime(action.Date); - // var previousDate = Utils.UnixTimestampToDateTime(previous.Date); - // if (previousDate.Date != itemDate.Date) - // { - // base.RemoveItem(index - 1); - // } - // } - // } - // else if (next is TLMessageService && previous == null) - // { - // var action = ((TLMessageService)next).Action as TLMessageActionDate; - // if (action != null) - // { - // base.RemoveItem(index - 1); - // } - // } - //} - - //private void UpdateAttach(MessageViewModel item, MessageViewModel previous, int index) - //{ - // if (item == null) - // { - // if (previous != null) - // { - // previous.IsLast = true; - // } - - // return; - // } - - // var oldFirst = item.IsFirst; - // var isItemPost = false; - // if (item is TLMessage) isItemPost = ((TLMessage)item).IsPost; - - // if (!isItemPost) - // { - // var attach = false; - // if (previous != null) - // { - // var isPreviousPost = false; - // if (previous is TLMessage) isPreviousPost = ((TLMessage)previous).IsPost; - - // attach = !isPreviousPost && - // !(previous is TLMessageService && !(((TLMessageService)previous).Action is TLMessageActionPhoneCall)) && - // !(previous.IsService()) && - // !(previous is TLMessageEmpty) && - // previous.FromId == item.FromId && - // item.Date - previous.Date < 900; - // } - - // item.IsFirst = !attach; - - // if (previous != null) - // { - // previous.IsLast = item.IsFirst || item.IsService(); - // } - // } - // else - // { - // item.IsFirst = true; - - // if (previous != null) - // { - // previous.IsLast = false; - // } - // } - //} - - #endregion - } - - #region Delegate - - public bool CanBeDownloaded(MessageViewModel message) - { - return false; - } - - public void DownloadFile(MessageViewModel message, File file) - { - } - - public void ReplyToMessage(MessageViewModel message) - { - } - - public void OpenReply(MessageViewModel message) - { - } - - public void OpenFile(File file) - { - } - - public void OpenWebPage(WebPage webPage) - { - } - - public void OpenSticker(Sticker sticker) - { - } - - public void OpenLocation(Location location, string title) - { - } - - public void OpenLiveLocation(MessageViewModel message) - { - - } - - public void OpenInlineButton(MessageViewModel message, InlineKeyboardButton button) - { - } - - public void OpenMedia(MessageViewModel message, FrameworkElement target) - { - } - - public void PlayMessage(MessageViewModel message) - { - } - - public void OpenUsername(string username) - { - } - - public void OpenHashtag(string hashtag) - { - } - - public void OpenBankCardNumber(string number) - { - } - - public void OpenUser(int userId) - { - } - - public void OpenChat(long chatId) - { - } - - public void OpenChat(long chatId, long messageId) - { - } - - public void OpenViaBot(int viaBotUserId) - { - } - - public void OpenUrl(string url, bool untrust) - { - } - - public void SendBotCommand(string command) - { - } - - public bool IsAdmin(int userId) - { - return false; - } - - public void Call(MessageViewModel message) - { - throw new NotImplementedException(); - } - - public void VotePoll(MessageViewModel message, IList options) - { - throw new NotImplementedException(); - } - - public string GetAdminTitle(int userId) - { - return null; - } - - #endregion - } -} diff --git a/Unigram/Unigram/Views/ChatEventLogPage.xaml b/Unigram/Unigram/Views/ChatEventLogPage.xaml new file mode 100644 index 0000000000..59539a29a2 --- /dev/null +++ b/Unigram/Unigram/Views/ChatEventLogPage.xaml @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/Unigram/Unigram/Views/ChatEventLogPage.xaml.cs b/Unigram/Unigram/Views/ChatEventLogPage.xaml.cs new file mode 100644 index 0000000000..b395e4f160 --- /dev/null +++ b/Unigram/Unigram/Views/ChatEventLogPage.xaml.cs @@ -0,0 +1,43 @@ +using System.ComponentModel; +using Unigram.Navigation; +using Unigram.ViewModels; +using Unigram.ViewModels.Delegates; +using Windows.UI.Xaml.Navigation; + +namespace Unigram.Views +{ + public sealed partial class ChatEventLogPage : HostedPage, INavigablePage, ISearchablePage, IActivablePage + { + public DialogEventLogViewModel ViewModel => DataContext as DialogEventLogViewModel; + public ChatView View => Content as ChatView; + + public ChatEventLogPage() + { + InitializeComponent(); + + Content = new ChatView(deleg => (DataContext = TLContainer.Current.Resolve(deleg)) as DialogEventLogViewModel); + Header = View.Header; + NavigationCacheMode = NavigationCacheMode.Required; + } + + public void OnBackRequested(HandledEventArgs args) + { + View.OnBackRequested(args); + } + + public void Search() + { + View.Search(); + } + + public void Dispose() + { + View.Dispose(); + } + + public void Activate() + { + View.Activate(); + } + } +} diff --git a/Unigram/Unigram/Views/ChatPage.xaml.cs b/Unigram/Unigram/Views/ChatPage.xaml.cs index 27b2a2c19f..d135d4b0a4 100644 --- a/Unigram/Unigram/Views/ChatPage.xaml.cs +++ b/Unigram/Unigram/Views/ChatPage.xaml.cs @@ -1,5 +1,4 @@ -using System; -using System.ComponentModel; +using System.ComponentModel; using Unigram.Navigation; using Unigram.ViewModels; using Unigram.ViewModels.Delegates; diff --git a/Unigram/Unigram/Views/ChatScheduledPage.xaml.cs b/Unigram/Unigram/Views/ChatScheduledPage.xaml.cs index dd9538eefb..154f703f25 100644 --- a/Unigram/Unigram/Views/ChatScheduledPage.xaml.cs +++ b/Unigram/Unigram/Views/ChatScheduledPage.xaml.cs @@ -1,5 +1,4 @@ -using System; -using System.ComponentModel; +using System.ComponentModel; using Unigram.Navigation; using Unigram.ViewModels; using Unigram.ViewModels.Delegates; diff --git a/Unigram/Unigram/Views/ChatView.Drawers.cs b/Unigram/Unigram/Views/ChatView.Drawers.cs index 769419612c..5b7bb2fadd 100644 --- a/Unigram/Unigram/Views/ChatView.Drawers.cs +++ b/Unigram/Unigram/Views/ChatView.Drawers.cs @@ -27,7 +27,7 @@ private void Sticker_ContextRequested(UIElement sender, ContextRequestedEventArg flyout.CreateFlyoutItem(ViewModel.StickerFaveCommand, (Sticker)sticker, Strings.Resources.AddToFavorites, new FontIcon { Glyph = Icons.Favorite }); } - if (!ViewModel.IsSchedule) + if (ViewModel.Type == ViewModels.DialogType.Normal) { var chat = ViewModel.Chat; if (chat == null) @@ -61,7 +61,7 @@ private void Animation_ContextRequested(UIElement sender, ContextRequestedEventA flyout.CreateFlyoutItem(ViewModel.AnimationSaveCommand, animation, Strings.Resources.SaveToGIFs, new FontIcon { Glyph = Icons.Animations }); } - if (!ViewModel.IsSchedule) + if (ViewModel.Type == ViewModels.DialogType.Normal) { var chat = ViewModel.Chat; if (chat == null) diff --git a/Unigram/Unigram/Views/ChatView.xaml.cs b/Unigram/Unigram/Views/ChatView.xaml.cs index b4492b7b14..0f31055a20 100644 --- a/Unigram/Unigram/Views/ChatView.xaml.cs +++ b/Unigram/Unigram/Views/ChatView.xaml.cs @@ -1874,7 +1874,7 @@ private void Send_ContextRequested(UIElement sender, ContextRequestedEventArgs a return; } - if (ViewModel.IsSchedule) + if (ViewModel.Type != DialogType.Normal) { return; } @@ -2065,7 +2065,7 @@ private bool MessageReschedule_Loaded(MessageViewModel message) private bool MessageReply_Loaded(MessageViewModel message) { - if (message.SchedulingState != null) + if (message.SchedulingState != null || ViewModel.Type != DialogType.Normal) { return false; } @@ -2089,7 +2089,7 @@ private bool MessageReply_Loaded(MessageViewModel message) private bool MessagePin_Loaded(MessageViewModel message) { - if (message.SchedulingState != null && message.IsService()) + if (message.SchedulingState != null || ViewModel.Type != DialogType.Normal || message.IsService()) { return false; } @@ -2145,7 +2145,7 @@ private bool MessageForward_Loaded(MessageViewModel message) private bool MessageUnvotePoll_Loaded(MessageViewModel message) { - if (message.Content is MessagePoll poll && poll.Poll.Type is PollTypeRegular) + if (ViewModel.Type == DialogType.Normal && message.Content is MessagePoll poll && poll.Poll.Type is PollTypeRegular) { return poll.Poll.Options.Any(x => x.IsChosen) && !poll.Poll.IsClosed; } @@ -2234,7 +2234,7 @@ private bool MessageCopyLink_Loaded(MessageViewModel message) { //var supergroup = ViewModel.ProtoService.GetSupergroup(supergroupType.SupergroupId); //return !string.IsNullOrEmpty(supergroup.Username); - return true; + return ViewModel.Type == DialogType.Normal; } return false; @@ -2242,7 +2242,7 @@ private bool MessageCopyLink_Loaded(MessageViewModel message) private bool MessageSelect_Loaded(MessageViewModel message) { - if (_myPeople || message.IsService()) + if (_myPeople || ViewModel.Type == DialogType.EventLog || message.IsService()) { return false; } @@ -3059,7 +3059,7 @@ public void UpdateChat(Chat chat) Report.Visibility = chat.CanBeReported ? Visibility.Visible : Visibility.Collapsed; - ButtonScheduled.Visibility = chat.HasScheduledMessages && !ViewModel.IsSchedule ? Visibility.Visible : Visibility.Collapsed; + ButtonScheduled.Visibility = chat.HasScheduledMessages && ViewModel.Type == DialogType.Normal ? Visibility.Visible : Visibility.Collapsed; ButtonTimer.Visibility = chat.Type is ChatTypeSecret ? Visibility.Visible : Visibility.Collapsed; ButtonSilent.Visibility = chat.Type is ChatTypeSupergroup supergroup && supergroup.IsChannel ? Visibility.Visible : Visibility.Collapsed; ButtonSilent.IsChecked = chat.DefaultDisableNotification; @@ -3078,7 +3078,7 @@ public void UpdateChatPermissions(Chat chat) public void UpdateChatTitle(Chat chat) { - if (ViewModel.IsSchedule) + if (ViewModel.Type == DialogType.ScheduledMessages) { Title.Text = ViewModel.CacheService.IsSavedMessages(chat) ? Strings.Resources.Reminders : Strings.Resources.ScheduledMessages; } @@ -3095,7 +3095,7 @@ public void UpdateChatPhoto(Chat chat) public void UpdateChatHasScheduledMessages(Chat chat) { - ButtonScheduled.Visibility = chat.HasScheduledMessages && !ViewModel.IsSchedule ? Visibility.Visible : Visibility.Collapsed; + ButtonScheduled.Visibility = chat.HasScheduledMessages && ViewModel.Type == DialogType.Normal ? Visibility.Visible : Visibility.Collapsed; } public void UpdateChatActionBar(Chat chat) @@ -3808,7 +3808,7 @@ public void UpdateUserStatus(Chat chat, User user) { ViewModel.LastSeen = null; } - else if (ViewModel.IsSchedule) + else if (ViewModel.Type == DialogType.ScheduledMessages) { ViewModel.LastSeen = null; } @@ -3891,6 +3891,15 @@ public void UpdateBasicGroupFullInfo(Chat chat, BasicGroup group, BasicGroupFull public async void UpdateSupergroup(Chat chat, Supergroup group) { + if (ViewModel.Type == DialogType.EventLog) + { + ShowAction(Strings.Resources.Settings, true); + + DiscussColumn.Width = new GridLength(0, GridUnitType.Auto); + DiscussButton.Visibility = Visibility.Collapsed; + return; + } + if (group.IsChannel) { if ((group.Status is ChatMemberStatusLeft && group.Username.Length > 0) || (group.Status is ChatMemberStatusCreator creator && !creator.IsMember)) @@ -3959,7 +3968,7 @@ public async void UpdateSupergroup(Chat chat, Supergroup group) } else if (!chat.Permissions.CanSendMessages) { - ShowAction(Strings.Resources.GlobalSendMessageRestricted, true); + ShowAction(Strings.Resources.GlobalSendMessageRestricted, false); } else { @@ -4008,6 +4017,11 @@ public async void UpdateSupergroup(Chat chat, Supergroup group) public void UpdateSupergroupFullInfo(Chat chat, Supergroup group, SupergroupFullInfo fullInfo) { + if (ViewModel.Type == DialogType.EventLog) + { + return; + } + ViewModel.LastSeen = Locale.Declension(group.IsChannel ? "Subscribers" : "Members", fullInfo.MemberCount); btnSendMessage.SlowModeDelay = fullInfo.SlowModeDelay; @@ -4051,7 +4065,7 @@ public void UpdateSupergroupFullInfo(Chat chat, Supergroup group, SupergroupFull - public void UpdateFile(Telegram.Td.Api.File file) + public void UpdateFile(File file) { if (_viewModel.TryGetMessagesForFileId(file.Id, out IList messages)) { diff --git a/Unigram/Unigram/Views/MainPage.xaml.cs b/Unigram/Unigram/Views/MainPage.xaml.cs index d90960c2a7..7d9370a0ef 100644 --- a/Unigram/Unigram/Views/MainPage.xaml.cs +++ b/Unigram/Unigram/Views/MainPage.xaml.cs @@ -1048,7 +1048,7 @@ private async void ProcessChatCommands(ShortcutCommand command, AcceleratorKeyEv var response = await ViewModel.ProtoService.SendAsync(new CreatePrivateChat(ViewModel.CacheService.Options.MyId, false)); if (response is Chat chat) { - MasterDetail.NavigationService.NavigateToChat(chat); + MasterDetail.NavigationService.NavigateToChat(chat, force: false); MasterDetail.NavigationService.GoBackAt(0, false); } } @@ -1217,7 +1217,7 @@ public async void Activate(string parameter) var response = await ViewModel.ProtoService.SendAsync(new CreatePrivateChat(from_id, false)); if (response is Chat chat) { - MasterDetail.NavigationService.NavigateToChat(chat); + MasterDetail.NavigationService.NavigateToChat(chat, force: false); } } else if (data.ContainsKey("chat_id") && int.TryParse(data["chat_id"], out int chat_id)) @@ -1225,7 +1225,7 @@ public async void Activate(string parameter) var response = await ViewModel.ProtoService.SendAsync(new CreateBasicGroupChat(chat_id, false)); if (response is Chat chat) { - MasterDetail.NavigationService.NavigateToChat(chat); + MasterDetail.NavigationService.NavigateToChat(chat, force: false); } } else if (data.ContainsKey("channel_id") && int.TryParse(data["channel_id"], out int channel_id)) @@ -1233,7 +1233,7 @@ public async void Activate(string parameter) var response = await ViewModel.ProtoService.SendAsync(new CreateSupergroupChat(channel_id, false)); if (response is Chat chat) { - MasterDetail.NavigationService.NavigateToChat(chat); + MasterDetail.NavigationService.NavigateToChat(chat, force: false); } } } @@ -1258,7 +1258,7 @@ public async void Activate(Uri scheme) var response = await ViewModel.ProtoService.SendAsync(new CreatePrivateChat(from_id, false)); if (response is Chat chat) { - MasterDetail.NavigationService.NavigateToChat(chat); + MasterDetail.NavigationService.NavigateToChat(chat, force: false); } } } @@ -1270,11 +1270,13 @@ private void OnNavigating(object sender, NavigatingEventArgs e) MasterDetail.BackgroundOpacity = e.SourcePageType == typeof(ChatPage) || + e.SourcePageType == typeof(ChatScheduledPage) || + e.SourcePageType == typeof(ChatEventLogPage) || e.SourcePageType == typeof(BlankPage) || - e.SourcePageType == typeof(SupergroupEventLogPage) || frame.CurrentSourcePageType == typeof(ChatPage) || - frame.CurrentSourcePageType == typeof(BlankPage) || - frame.CurrentSourcePageType == typeof(SupergroupEventLogPage) ? 1 : 0; + frame.CurrentSourcePageType == typeof(ChatScheduledPage) || + frame.CurrentSourcePageType == typeof(ChatEventLogPage) || + frame.CurrentSourcePageType == typeof(BlankPage) ? 1 : 0; } private void OnNavigated(object sender, NavigatedEventArgs e) @@ -1474,7 +1476,7 @@ public async void Navigate(object item) { ViewModel.Chats.SelectedItem = message.ChatId; - MasterDetail.NavigationService.NavigateToChat(message.ChatId, message: message.Id); + MasterDetail.NavigationService.NavigateToChat(message.ChatId, message: message.Id, force: false); } else { @@ -1530,7 +1532,7 @@ public async void Navigate(object item) folder.SelectedItem = chat.Id; } - MasterDetail.NavigationService.NavigateToChat(chat); + MasterDetail.NavigationService.NavigateToChat(chat, force: false); MasterDetail.NavigationService.GoBackAt(0, false); } } @@ -2344,7 +2346,7 @@ public async void NavigationView_ItemClick(RootDestination destination) var response = await ViewModel.ProtoService.SendAsync(new CreatePrivateChat(ViewModel.CacheService.Options.MyId, false)); if (response is Chat chat) { - MasterDetail.NavigationService.NavigateToChat(chat); + MasterDetail.NavigationService.NavigateToChat(chat, force: false); } } else if (destination == RootDestination.News) diff --git a/Unigram/Unigram/Views/Supergroups/SupergroupEventLogPage.Bubbles.cs b/Unigram/Unigram/Views/Supergroups/SupergroupEventLogPage.Bubbles.cs deleted file mode 100644 index aa286278a8..0000000000 --- a/Unigram/Unigram/Views/Supergroups/SupergroupEventLogPage.Bubbles.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System.Collections.Generic; -using Unigram.Controls; -using Unigram.ViewModels; -using Windows.UI.Xaml.Controls; -using Windows.UI.Xaml.Controls.Primitives; - -namespace Unigram.Views.Supergroups -{ - public partial class SupergroupEventLogPage : HostedPage, IGifPlayback - { - private ItemsStackPanel _panel; - private Dictionary _old = new Dictionary(); - - private void OnViewChanged(object sender, ScrollViewerViewChangedEventArgs e) - { - var index0 = _panel.FirstVisibleIndex; - var index1 = _panel.LastVisibleIndex; - - if (_panel.FirstVisibleIndex > -1 && _panel.LastVisibleIndex > -1 && !e.IsIntermediate) - { - var messages = new List(_panel.LastVisibleIndex - _panel.FirstVisibleIndex); - var auto = ViewModel.Settings.IsAutoPlayAnimationsEnabled; - var news = new Dictionary(); - - for (int i = index0; i <= index1; i++) - { - var container = Messages.ContainerFromIndex(i) as SelectorItem; - if (container != null) - { - var message = Messages.ItemFromContainer(container) as MessageViewModel; - if (message == null) - { - continue; - } - - messages.Add(message); - } - } - - Play(messages, auto); - } - } - - class MediaPlayerItem - { - public Grid Container { get; set; } - public MediaPlayerView Presenter { get; set; } - public bool Watermark { get; set; } - } - - public void Play(MessageViewModel message) - { - } - - public void Play(IEnumerable items, bool auto) - { - } - } -} diff --git a/Unigram/Unigram/Views/Supergroups/SupergroupEventLogPage.xaml b/Unigram/Unigram/Views/Supergroups/SupergroupEventLogPage.xaml deleted file mode 100644 index c5cd8bf4fc..0000000000 --- a/Unigram/Unigram/Views/Supergroups/SupergroupEventLogPage.xaml +++ /dev/null @@ -1,324 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -