DiscordViewModel.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. using System.ComponentModel;
  2. using DiscordRPC;
  3. using PixiEditor.AvaloniaUI.Helpers;
  4. using PixiEditor.AvaloniaUI.Models.Controllers;
  5. using PixiEditor.AvaloniaUI.ViewModels.Document;
  6. using PixiEditor.Extensions.CommonApi.UserPreferences.Settings;
  7. namespace PixiEditor.AvaloniaUI.ViewModels.SubViewModels;
  8. internal class DiscordViewModel : SubViewModel<ViewModelMain>, IDisposable
  9. {
  10. private DiscordRpcClient client;
  11. private string clientId;
  12. private DocumentViewModel currentDocument;
  13. public bool Enabled
  14. {
  15. get => client != null;
  16. set
  17. {
  18. if (Enabled != value)
  19. {
  20. if (value)
  21. {
  22. Start();
  23. }
  24. else
  25. {
  26. Stop();
  27. }
  28. }
  29. }
  30. }
  31. public DiscordViewModel(ViewModelMain owner, string clientId)
  32. : base(owner)
  33. {
  34. Owner.DocumentManagerSubViewModel.ActiveDocumentChanged += DocumentChanged;
  35. this.clientId = clientId;
  36. Enabled = PixiEditorSettings.EnableRichPresence.Value;
  37. PixiEditorSettings.EnableRichPresence.ValueChanged += (_, value) => Enabled = value;
  38. AppDomain.CurrentDomain.ProcessExit += (_, _) => Enabled = false;
  39. }
  40. public void Start()
  41. {
  42. client = new DiscordRpcClient(clientId);
  43. client.OnReady += OnReady;
  44. client.Initialize();
  45. }
  46. public void Stop()
  47. {
  48. client.ClearPresence();
  49. client.Dispose();
  50. client = null;
  51. }
  52. public void UpdatePresence(DocumentViewModel? document)
  53. {
  54. if (client == null)
  55. {
  56. return;
  57. }
  58. RichPresence richPresence = NewDefaultRP();
  59. if (document != null)
  60. {
  61. richPresence.WithTimestamps(new Timestamps(document.OpenedUTC));
  62. richPresence.Details = PixiEditorSettings.ShowDocumentName.Value
  63. ? $"Editing {document.FileName.Limit(128)}" : "Editing an image";
  64. string state = string.Empty;
  65. if (PixiEditorSettings.ShowDocumentSize.Value)
  66. {
  67. state = $"{document.Width}x{document.Height}";
  68. }
  69. if (PixiEditorSettings.ShowDocumentSize.Value && PixiEditorSettings.ShowLayerCount.Value)
  70. {
  71. state += ", ";
  72. }
  73. if (PixiEditorSettings.ShowLayerCount.Value)
  74. {
  75. int count = CountLayers(document.StructureRoot);
  76. state += count == 1 ? "1 layer" : $"{count} layers";
  77. }
  78. richPresence.State = state;
  79. }
  80. client.SetPresence(richPresence);
  81. }
  82. private int CountLayers(FolderViewModel folder)
  83. {
  84. int counter = 0;
  85. foreach (var child in folder.Children)
  86. {
  87. if (child is LayerViewModel)
  88. counter++;
  89. else if (child is FolderViewModel innerFolder)
  90. counter += CountLayers(innerFolder);
  91. }
  92. return counter;
  93. }
  94. public void Dispose()
  95. {
  96. Enabled = false;
  97. GC.SuppressFinalize(this);
  98. }
  99. private static RichPresence NewDefaultRP()
  100. {
  101. return new RichPresence
  102. {
  103. Details = "Staring at absolutely",
  104. State = "nothing",
  105. Assets = new Assets
  106. {
  107. LargeImageKey = "editorlogo",
  108. LargeImageText = "You've discovered PixiEditor's logo",
  109. SmallImageKey = "github",
  110. SmallImageText = "Download PixiEditor (pixieditor.net/download)!"
  111. },
  112. Timestamps = new Timestamps()
  113. {
  114. Start = DateTime.UtcNow
  115. }
  116. };
  117. }
  118. private void DocumentChanged(object sender, DocumentChangedEventArgs e)
  119. {
  120. if (currentDocument != null)
  121. {
  122. currentDocument.PropertyChanged -= DocumentPropertyChanged;
  123. currentDocument.LayersChanged -= DocumentLayerChanged;
  124. }
  125. currentDocument = e.NewDocument;
  126. if (currentDocument != null)
  127. {
  128. UpdatePresence(currentDocument);
  129. currentDocument.PropertyChanged += DocumentPropertyChanged;
  130. currentDocument.LayersChanged += DocumentLayerChanged;
  131. }
  132. }
  133. private void DocumentLayerChanged(object sender, LayersChangedEventArgs e)
  134. {
  135. UpdatePresence(currentDocument);
  136. }
  137. private void DocumentPropertyChanged(object sender, PropertyChangedEventArgs e)
  138. {
  139. if (e.PropertyName == nameof(currentDocument.FileName)
  140. || e.PropertyName == nameof(currentDocument.Width)
  141. || e.PropertyName == nameof(currentDocument.Height))
  142. {
  143. UpdatePresence(currentDocument);
  144. }
  145. }
  146. private void OnReady(object sender, DiscordRPC.Message.ReadyMessage args)
  147. {
  148. UpdatePresence(Owner.DocumentManagerSubViewModel.ActiveDocument);
  149. }
  150. ~DiscordViewModel()
  151. {
  152. Enabled = false;
  153. }
  154. }