mac_touchbar_manager.mm 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #include "platform/mac/touchbar/mac_touchbar_manager.h"
  8. #include "apiwrap.h" // ApiWrap::updateStickers()
  9. #include "core/application.h"
  10. #include "data/data_chat_participant_status.h" // Data::CanSendAnyOf.
  11. #include "data/data_forum_topic.h"
  12. #include "data/data_session.h"
  13. #include "data/stickers/data_stickers.h" // Stickers::setsRef()
  14. #include "main/main_domain.h"
  15. #include "main/main_session.h"
  16. #include "media/audio/media_audio_capture.h"
  17. #include "media/player/media_player_instance.h"
  18. #include "platform/mac/touchbar/mac_touchbar_audio.h"
  19. #include "platform/mac/touchbar/mac_touchbar_common.h"
  20. #include "platform/mac/touchbar/mac_touchbar_main.h"
  21. #include "ui/widgets/fields/input_field.h"
  22. #include "window/window_controller.h"
  23. #include "window/window_session_controller.h"
  24. #import <AppKit/NSGroupTouchBarItem.h>
  25. using namespace TouchBar::Main;
  26. namespace {
  27. const auto kMainItemIdentifier = @"touchbarMain";
  28. const auto kAudioItemIdentifier = @"touchbarAudio";
  29. } // namespace
  30. @interface GroupTouchBarItem : NSGroupTouchBarItem
  31. - (rpl::lifetime &)lifetime;
  32. @end // @interface GroupTouchBarItem
  33. @implementation GroupTouchBarItem {
  34. rpl::lifetime _lifetime;
  35. }
  36. - (rpl::lifetime &)lifetime {
  37. return _lifetime;
  38. }
  39. @end // GroupTouchBarItem
  40. #pragma mark - RootTouchBar
  41. @interface RootTouchBar()
  42. @end // @interface RootTouchBar
  43. @implementation RootTouchBar {
  44. Main::Session *_session;
  45. Window::Controller *_controller;
  46. rpl::variable<Ui::MarkdownEnabledState> _markdownState;
  47. rpl::event_stream<> _touchBarSwitches;
  48. rpl::lifetime _lifetime;
  49. }
  50. - (id)init:(rpl::producer<Ui::MarkdownEnabledState>)markdownState
  51. controller:(not_null<Window::Controller*>)controller
  52. domain:(not_null<Main::Domain*>)domain {
  53. self = [super init];
  54. if (!self) {
  55. return self;
  56. }
  57. self.delegate = self;
  58. TouchBar::CustomEnterToCocoaEventLoop([=] {
  59. self.defaultItemIdentifiers = @[];
  60. });
  61. _controller = controller;
  62. _markdownState = std::move(markdownState);
  63. auto sessionChanges = domain->activeSessionChanges(
  64. ) | rpl::map([=](Main::Session *session) {
  65. if (session && session->data().stickers().setsRef().empty()) {
  66. session->api().updateStickers();
  67. }
  68. return session;
  69. });
  70. const auto type = AudioMsgId::Type::Song;
  71. auto audioPlayer = rpl::merge(
  72. Media::Player::instance()->stops(type) | rpl::map_to(false),
  73. Media::Player::instance()->startsPlay(type) | rpl::map_to(true)
  74. );
  75. auto voiceRecording = ::Media::Capture::instance()->startedChanges();
  76. rpl::combine(
  77. std::move(sessionChanges),
  78. rpl::single(false) | rpl::then(Core::App().passcodeLockChanges()),
  79. rpl::single(false) | rpl::then(std::move(audioPlayer)),
  80. rpl::single(false) | rpl::then(std::move(voiceRecording))
  81. ) | rpl::start_with_next([=](
  82. Main::Session *session,
  83. bool lock,
  84. bool audio,
  85. bool recording) {
  86. TouchBar::CustomEnterToCocoaEventLoop([=] {
  87. _touchBarSwitches.fire({});
  88. if (!audio) {
  89. self.defaultItemIdentifiers = @[];
  90. }
  91. self.defaultItemIdentifiers = (lock || recording)
  92. ? @[]
  93. : audio
  94. ? @[kAudioItemIdentifier]
  95. : session
  96. ? @[kMainItemIdentifier]
  97. : @[];
  98. });
  99. }, _lifetime);
  100. return self;
  101. }
  102. - (NSTouchBarItem*)touchBar:(NSTouchBar*)touchBar
  103. makeItemForIdentifier:(NSTouchBarItemIdentifier)itemId {
  104. if (!touchBar || !_controller->sessionController()) {
  105. return nil;
  106. }
  107. const auto isEqual = [&](NSString *string) {
  108. return [itemId isEqualToString:string];
  109. };
  110. if (isEqual(kMainItemIdentifier)) {
  111. auto *item = [[GroupTouchBarItem alloc] initWithIdentifier:itemId];
  112. item.groupTouchBar
  113. = [[[TouchBarMain alloc]
  114. init:_controller
  115. touchBarSwitches:_touchBarSwitches.events()] autorelease];
  116. rpl::combine(
  117. _markdownState.value(),
  118. _controller->sessionController()->activeChatValue(
  119. ) | rpl::map([](Dialogs::Key k) {
  120. const auto topic = k.topic();
  121. const auto peer = k.peer();
  122. const auto rights = ChatRestriction::SendStickers
  123. | ChatRestriction::SendOther;
  124. return topic
  125. ? Data::CanSendAnyOf(topic, rights)
  126. : (peer && Data::CanSendAnyOf(peer, rights));
  127. }) | rpl::distinct_until_changed()
  128. ) | rpl::start_with_next([=](
  129. Ui::MarkdownEnabledState state,
  130. bool hasActiveChat) {
  131. item.groupTouchBar.defaultItemIdentifiers = @[
  132. kPinnedPanelItemIdentifier,
  133. (!state.disabled()
  134. ? kPopoverInputItemIdentifier
  135. : hasActiveChat
  136. ? kPopoverPickerItemIdentifier
  137. : @"")];
  138. }, [item lifetime]);
  139. return [item autorelease];
  140. } else if (isEqual(kAudioItemIdentifier)) {
  141. auto *item = [[GroupTouchBarItem alloc] initWithIdentifier:itemId];
  142. auto *touchBar = [[[TouchBarAudioPlayer alloc] init]
  143. autorelease];
  144. item.groupTouchBar = touchBar;
  145. [touchBar closeRequests] | rpl::start_with_next([=] {
  146. Media::Player::instance()->stopAndClose();
  147. }, [item lifetime]);
  148. return [item autorelease];
  149. }
  150. return nil;
  151. }
  152. @end // @implementation RootTouchBar