fix(@desktop/general): app/os notifications

Fixes #4409
This commit is contained in:
Sale Djenic 2022-02-09 18:35:59 +01:00 committed by saledjenic
parent 3a25f8d1c8
commit 6186bf9c8c
40 changed files with 452 additions and 409 deletions

View File

@ -154,7 +154,7 @@ ifneq ($(detected_OS),Windows)
DOTHERSIDE := vendor/DOtherSide/build/lib/libDOtherSideStatic.a
DOTHERSIDE_CMAKE_PARAMS := -DENABLE_DYNAMIC_LIBS=OFF -DENABLE_STATIC_LIBS=ON
# order matters here, due to "-Wl,-as-needed"
NIM_PARAMS += --passL:"$(DOTHERSIDE)" --passL:"$(shell PKG_CONFIG_PATH="$(QT5_PCFILEDIR)" pkg-config --libs Qt5Core Qt5Qml Qt5Gui Qt5Quick Qt5QuickControls2 Qt5Widgets Qt5Svg)"
NIM_PARAMS += --passL:"$(DOTHERSIDE)" --passL:"$(shell PKG_CONFIG_PATH="$(QT5_PCFILEDIR)" pkg-config --libs Qt5Core Qt5Qml Qt5Gui Qt5Quick Qt5QuickControls2 Qt5Widgets Qt5Svg Qt5Multimedia)"
else
DOTHERSIDE := vendor/DOtherSide/build/lib/Release/DOtherSide.dll
DOTHERSIDE_CMAKE_PARAMS := -T"v141" -A x64 -DENABLE_DYNAMIC_LIBS=ON -DENABLE_STATIC_LIBS=OFF

View File

@ -1,7 +1,6 @@
import NimQml
import ../../app_service/service/general/service as general_service
import ../../app_service/service/os_notification/service as os_notification_service
import ../../app_service/service/eth/service as eth_service
import ../../app_service/service/keychain/service as keychain_service
import ../../app_service/service/accounts/service as accounts_service
@ -35,7 +34,6 @@ import ../../app_service/service/ens/service as ens_service
import ../modules/startup/module as startup_module
import ../modules/main/module as main_module
import ../global/local_account_settings
import ../global/global_singleton
import ../core/[main]
@ -53,7 +51,6 @@ type
# Services
generalService: general_service.Service
osNotificationService: os_notification_service.Service
keychainService: keychain_service.Service
ethService: eth_service.Service
accountsService: accounts_service.Service
@ -124,7 +121,6 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController =
result.settingsService = settings_service.newService()
result.nodeConfigurationService = node_configuration_service.newService(statusFoundation.fleetConfiguration,
result.settingsService)
result.osNotificationService = os_notification_service.newService(statusFoundation.events)
result.keychainService = keychain_service.newService(statusFoundation.events)
result.ethService = eth_service.newService()
result.accountsService = accounts_service.newService(statusFoundation.fleetConfiguration)
@ -226,7 +222,6 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController =
proc delete*(self: AppController) =
singletonInstance.delete
self.osNotificationService.delete
self.keychainService.delete
self.contactsService.delete
self.bookmarkService.delete
@ -279,7 +274,6 @@ proc startupDidLoad*(self: AppController) =
self.startupModule.startUpUIRaised()
proc mainDidLoad*(self: AppController) =
self.statusFoundation.onLoggedIn()
self.startupModule.moveToAppState()
self.mainModule.checkForStoringPassword()
@ -347,8 +341,6 @@ proc userLoggedIn*(self: AppController) =
if(importedAccount.isValid()):
self.privacyService.removeMnemonic()
self.osNotificationService.userLoggedIn()
proc buildAndRegisterLocalAccountSensitiveSettings(self: AppController) =
var pubKey = self.settingsService.getPublicKey()
singletonInstance.localAccountSensitiveSettings.setFileName(pubKey)

View File

@ -4,16 +4,18 @@ import
./fleets/fleet_configuration,
./tasks/marathon,
./tasks/threadpool,
./signals/signals_manager
./signals/signals_manager,
./notifications/notifications_manager
export eventemitter
export marathon, task_runner, signals_manager, fleet_configuration
export marathon, task_runner, signals_manager, fleet_configuration, notifications_manager
type StatusFoundation* = ref object
events*: EventEmitter
fleetConfiguration*: FleetConfiguration
threadpool*: ThreadPool
signalsManager*: SignalsManager
notificationsManager*: NotificationsManager
proc newStatusFoundation*(fleetConfig: string): StatusFoundation =
result = StatusFoundation()
@ -21,11 +23,10 @@ proc newStatusFoundation*(fleetConfig: string): StatusFoundation =
result.fleetConfiguration = newFleetConfiguration(fleetConfig)
result.threadpool = newThreadPool()
result.signalsManager = newSignalsManager(result.events)
result.notificationsManager = newNotificationsManager(result.events)
proc delete*(self: StatusFoundation) =
self.threadpool.teardown()
self.fleetConfiguration.delete()
self.signalsManager.delete()
proc onLoggedIn*(self: StatusFoundation) =
discard
self.notificationsManager.delete()

View File

@ -0,0 +1,39 @@
{.used.}
import json
include ../../../app_service/common/json_utils
type
NotificationType* {.pure.} = enum
NewContactRequest = 1,
AcceptedContactRequest,
JoinCommunityRequest,
MyRequestToJoinCommunityAccepted,
MyRequestToJoinCommunityRejected,
NewMessage,
NewMention
NotificationDetails* = object
notificationType*: NotificationType
sectionId*: string
chatId*: string
messageId*: string
proc toNotificationDetails*(jsonObj: JsonNode): NotificationDetails =
var notificationType: int
if (not (jsonObj.getProp("notificationType", notificationType) and
jsonObj.getProp("sectionId", result.sectionId) and
jsonObj.getProp("chatId", result.chatId) and
jsonObj.getProp("messageId", result.messageId))):
return NotificationDetails()
result.notificationType = notificationType.NotificationType
proc toJsonNode*(self: NotificationDetails): JsonNode =
result = %* {
"notificationType": self.notificationType.int,
"sectionId": self.sectionId,
"chatId": self.chatId,
"messageId": self.messageId
}

View File

@ -0,0 +1,183 @@
import NimQml, json, chronicles
import ../../global/app_signals
import ../../global/global_singleton
import ../eventemitter
import details
export details
logScope:
topics = "notifications-manager"
const NOTIFICATION_SOUND = "qrc:/imports/assets/audio/notification.wav"
# Signals which may be emitted by this class:
const SIGNAL_DISPLAY_APP_NOTIFICATION* = "displayAppNotification"
const SIGNAL_OS_NOTIFICATION_CLICKED* = "osNotificationClicked"
# Notification preferences
const NOTIFY_ABOUT_ALL_MESSAGES = 0
const NOTIFY_JUST_ABOUT_MENTIONS = 1
const NOTIFY_NOTHING_ABOUT = 2
# Anonymous preferences
const PREVIEW_ANONYMOUS = 0
const PREVIEW_NAME_ONLY = 1
const PREVIEW_NAME_AND_MESSAGE = 2
type
NotificationArgs* = ref object of Args
title*: string
message*: string
details*: NotificationDetails
ClickedNotificationArgs* = ref object of Args
details*: NotificationDetails
QtObject:
type NotificationsManager* = ref object of QObject
events: EventEmitter
osNotification: StatusOSNotification
soundManager: StatusSoundManager
proc processNotification(self: NotificationsManager, title: string, message: string, details: NotificationDetails)
proc setup(self: NotificationsManager, events: EventEmitter) =
self.QObject.setup
self.events = events
self.osNotification = newStatusOSNotification()
self.soundManager = newStatusSoundManager()
signalConnect(self.osNotification, "notificationClicked(QString)", self, "onOSNotificationClicked(QString)", 2)
signalConnect(singletonInstance.globalEvents, "showNormalMessageNotification(QString, QString, QString, QString, QString)",
self, "onShowNormalMessageNotification(QString, QString, QString, QString, QString)", 2)
signalConnect(singletonInstance.globalEvents, "showMentionMessageNotification(QString, QString, QString, QString, QString)",
self, "onShowMentionMessageNotification(QString, QString, QString, QString, QString)", 2)
signalConnect(singletonInstance.globalEvents, "showNewContactRequestNotification(QString, QString, QString)",
self, "onShowNewContactRequestNotification(QString, QString, QString)", 2)
signalConnect(singletonInstance.globalEvents, "newCommunityMembershipRequestNotification(QString, QString, QString)",
self, "onNewCommunityMembershipRequestNotification(QString, QString, QString)", 2)
signalConnect(singletonInstance.globalEvents, "myRequestToJoinCommunityHasBeenAcccepted(QString, QString, QString)",
self, "onMyRequestToJoinCommunityHasBeenAcccepted(QString, QString, QString)", 2)
signalConnect(singletonInstance.globalEvents, "myRequestToJoinCommunityHasBeenRejected(QString, QString, QString)",
self, "onMyRequestToJoinCommunityHasBeenRejected(QString, QString, QString)", 2)
proc delete*(self: NotificationsManager) =
self.osNotification.delete
self.QObject.delete
proc newNotificationsManager*(events: EventEmitter): NotificationsManager =
new(result, delete)
result.setup(events)
proc showOSNotification(self: NotificationsManager, title: string, message: string, identifier: string) =
## This method will add new notification to the OS Notification center. Param
## "identifier" is used to uniquely define notification bubble.
self.osNotification.showNotification(title, message, identifier)
proc onOSNotificationClicked(self: NotificationsManager, identifier: string) {.slot.} =
## This slot is called once user clicks OS notificaiton bubble, "identifier"
## contains data which uniquely define that notification.
debug "OS notification clicked", identifier=identifier
# Make the app the top most window.
app_makeItActive(singletonInstance.engine)
let details = toNotificationDetails(parseJson(identifier))
if(details.notificationType == NotificationType.NewMessage or
details.notificationType == NotificationType.NewMention):
let data = ActiveSectionChatArgs(sectionId: details.sectionId, chatId: details.chatId, messageId: details.messageId)
self.events.emit(SIGNAL_MAKE_SECTION_CHAT_ACTIVE, data)
else:
self.events.emit(SIGNAL_OS_NOTIFICATION_CLICKED, ClickedNotificationArgs(details: details))
proc onShowNormalMessageNotification(self: NotificationsManager, title: string, message: string, sectionId: string,
chatId: string, messageId: string) {.slot.} =
let details = NotificationDetails(notificationType: NotificationType.NewMessage, sectionId: sectionId,
chatId: chatId, messageId: messageId)
self.processNotification(title, message, details)
proc onShowMentionMessageNotification(self: NotificationsManager, title: string, message: string, sectionId: string,
chatId: string, messageId: string) {.slot.} =
let details = NotificationDetails(notificationType: NotificationType.NewMention, sectionId: sectionId,
chatId: chatId, messageId: messageId)
self.processNotification(title, message, details)
proc onShowNewContactRequestNotification*(self: NotificationsManager, title: string, message: string,
sectionId: string) {.slot.} =
let details = NotificationDetails(notificationType: NotificationType.NewContactRequest, sectionId: sectionId)
self.processNotification(title, message, details)
proc onNewCommunityMembershipRequestNotification*(self: NotificationsManager, title: string, message: string,
sectionId: string) {.slot.} =
let details = NotificationDetails(notificationType: NotificationType.JoinCommunityRequest, sectionId: sectionId)
self.processNotification(title, message, details)
proc onMyRequestToJoinCommunityHasBeenAcccepted*(self: NotificationsManager, title: string, message: string,
sectionId: string) {.slot.} =
let details = NotificationDetails(notificationType: NotificationType.MyRequestToJoinCommunityAccepted,
sectionId: sectionId)
self.processNotification(title, message, details)
proc onMyRequestToJoinCommunityHasBeenRejected*(self: NotificationsManager, title: string, message: string,
sectionId: string) {.slot.} =
let details = NotificationDetails(notificationType: NotificationType.MyRequestToJoinCommunityRejected,
sectionId: sectionId)
self.processNotification(title, message, details)
proc processNotification(self: NotificationsManager, title: string, message: string, details: NotificationDetails) =
## This is the main method which need to be called to process an event according to the preferences set in the
## notifications panel of the settings section.
##
## This method determines whether a notification need to be displayed or not, what notification to display, whether
## to display App or OS notification, what level of anonymous to apply, whether to play sound or not and so...
# I am not 100% sure about this.
# According to this:
# https://github.com/status-im/status-desktop/pull/4789#discussion_r805028513
# The app should use OS notification only in case it is not the active app or it's minimized at the moment
# we're processing an event.
if(singletonInstance.localAccountSensitiveSettings.getUseOSNotifications() and
app_isActive(singletonInstance.engine)):
return
var finalTitle = title
var finalMessage = message
# Check if notification need to be displayed
if(singletonInstance.localAccountSensitiveSettings.getNotificationSetting() == NOTIFY_NOTHING_ABOUT and
(details.notificationType == NotificationType.NewMessage or
details.notificationType == NotificationType.NewMention)):
return
if(singletonInstance.localAccountSensitiveSettings.getNotificationSetting() == NOTIFY_JUST_ABOUT_MENTIONS and
details.notificationType == NotificationType.NewMessage):
return
if(not singletonInstance.localAccountSensitiveSettings.getNotifyOnNewRequests() and
details.notificationType == NotificationType.NewContactRequest):
return
# Check anonymous level
if(singletonInstance.localAccountSensitiveSettings.getNotificationMessagePreviewSetting() == PREVIEW_ANONYMOUS):
finalTitle = "Status"
finalMessage = "You have a new message"
elif(singletonInstance.localAccountSensitiveSettings.getNotificationMessagePreviewSetting() == PREVIEW_NAME_ONLY):
finalMessage = "You have a new message"
# Check whether to display APP or OS notification
if(singletonInstance.localAccountSensitiveSettings.getUseOSNotifications()):
let identifier = $(details.toJsonNode())
debug "Add OS notification", title=finalTitle, message=finalMessage, identifier=identifier
self.showOSNotification(finalTitle, finalMessage, identifier)
else:
let data = NotificationArgs(title: finalTitle, message: finalMessage, details: details)
debug "Add APP notification", title=finalTitle, message=finalMessage
self.events.emit(SIGNAL_DISPLAY_APP_NOTIFICATION, data)
# Check whether to play a sound
if(singletonInstance.localAccountSensitiveSettings.getNotificationSoundsEnabled()):
let currentVolume = singletonInstance.localAccountSensitiveSettings.getVolume() * 10
self.soundManager.setPlayerVolume(currentVolume)
self.soundManager.playSound(NOTIFICATION_SOUND)

View File

@ -9,3 +9,16 @@ type
sectionType*: SectionType
const TOGGLE_SECTION* = "toggleSection"
## Emmiting this signal will turn on section/s with passed `sectionType` if that section type is
## turned off, or turn it off in case that section type is turned on.
type
ActiveSectionChatArgs* = ref object of Args
sectionId*: string
chatId*: string
messageId*: string
const SIGNAL_MAKE_SECTION_CHAT_ACTIVE* = "makeSectionChatActive"
## Emmiting this signal will switch the app to passed `sectionId`, after that if `chatId` is set
## it will make that chat an active one and at the end if `messageId` is set it will point to
## that message.

View File

@ -0,0 +1,28 @@
import NimQml
QtObject:
type GlobalEvents* = ref object of QObject
proc setup(self: GlobalEvents) =
self.QObject.setup
proc delete*(self: GlobalEvents) =
self.QObject.delete
proc newGlobalEvents*(): GlobalEvents =
new(result, delete)
result.setup
proc showNormalMessageNotification*(self: GlobalEvents, title: string, message: string, sectionId: string,
chatId: string, messageId: string) {.signal.}
proc showMentionMessageNotification*(self: GlobalEvents, title: string, message: string, sectionId: string,
chatId: string, messageId: string) {.signal.}
proc showNewContactRequestNotification*(self: GlobalEvents, title: string, message: string, sectionId: string)
{.signal.}
proc newCommunityMembershipRequestNotification*(self: GlobalEvents, title: string, message: string,
sectionId: string) {.signal.}
proc myRequestToJoinCommunityHasBeenAcccepted*(self: GlobalEvents, title: string, message: string,
sectionId: string) {.signal.}
proc myRequestToJoinCommunityHasBeenRejected*(self: GlobalEvents, title: string, message: string,
sectionId: string) {.signal.}

View File

@ -5,12 +5,14 @@ import local_account_sensitive_settings
import local_app_settings
import user_profile
import utils
import global_events
export local_account_settings
export local_account_sensitive_settings
export local_app_settings
export user_profile
export utils
export global_events
type
GlobalSingleton = object
@ -23,44 +25,44 @@ proc engine*(self: GlobalSingleton): QQmlApplicationEngine =
var qmlEngine {.global.}: QQmlApplicationEngine
if (qmlEngine.isNil):
qmlEngine = newQQmlApplicationEngine()
return qmlEngine
proc localAccountSettings*(self: GlobalSingleton): LocalAccountSettings =
var localAccountSettings {.global.}: LocalAccountSettings
if (localAccountSettings.isNil):
localAccountSettings = newLocalAccountSettings()
return localAccountSettings
proc localAccountSensitiveSettings*(self: GlobalSingleton): LocalAccountSensitiveSettings =
var localAccountSensitiveSettings {.global.}: LocalAccountSensitiveSettings
if (localAccountSensitiveSettings.isNil):
localAccountSensitiveSettings = newLocalAccountSensitiveSettings()
return localAccountSensitiveSettings
proc localAppSettings*(self: GlobalSingleton): LocalAppSettings =
var localAppSettings {.global.}: LocalAppSettings
if (localAppSettings.isNil):
localAppSettings = newLocalAppSettings("global")
return localAppSettings
proc userProfile*(self: GlobalSingleton): UserProfile =
var userProfile {.global.}: UserProfile
if (userProfile.isNil):
userProfile = newUserProfile()
return userProfile
proc utils*(self: GlobalSingleton): Utils =
var utils {.global.}: Utils
if (utils.isNil):
utils = newUtils()
return utils
proc globalEvents*(self: GlobalSingleton): GlobalEvents =
var globalEvents {.global.}: GlobalEvents
if (globalEvents.isNil):
globalEvents = newGlobalEvents()
return globalEvents
proc delete*(self: GlobalSingleton) =
self.engine.delete()
self.localAccountSettings.delete()

View File

@ -35,7 +35,7 @@ const DEFAULT_HIDDEN_COMMUNITY_WELCOME_BANNERS = ""
const LSS_KEY_HIDDEN_COMMUNITY_BACKUP_BANNERS* = "hiddenCommunityBackUpBanners"
const DEFAULT_HIDDEN_COMMUNITY_BACKUP_BANNERS = ""
const LSS_KEY_VOLUME* = "volume"
const DEFAULT_VOLUME: float = 0.2
const DEFAULT_VOLUME = 2
const LSS_KEY_NOTIFICATION_SETTING* = "notificationSetting"
const DEFAULT_NOTIFICATION_SETTING = 1 #notifyJustMentions from qml
const LSS_KEY_NOTIFICATION_SOUNDS_ENABLED* = "notificationSoundsEnabled"
@ -132,16 +132,16 @@ QtObject:
# float type must be exposed through QVariant property.
proc getSettingsPropQVariant(self: LocalAccountSensitiveSettings, prop: string, default: QVariant): QVariant =
result = if(self.settings.isNil): newQVariant() else: self.settings.value(prop, default)
result = if(self.settings.isNil): default else: self.settings.value(prop, default)
proc getSettingsPropString(self: LocalAccountSensitiveSettings, prop: string, default: QVariant): string =
result = if(self.settings.isNil): "" else: self.settings.value(prop, default).stringVal
result = if(self.settings.isNil): default.stringVal else: self.settings.value(prop, default).stringVal
proc getSettingsPropInt(self: LocalAccountSensitiveSettings, prop: string, default: QVariant): int =
result = if(self.settings.isNil): 0 else: self.settings.value(prop, default).intVal
result = if(self.settings.isNil): default.intVal else: self.settings.value(prop, default).intVal
proc getSettingsPropBool(self: LocalAccountSensitiveSettings, prop: string, default: QVariant): bool =
result = if(self.settings.isNil): false else: self.settings.value(prop, default).boolVal
result = if(self.settings.isNil): default.boolVal else: self.settings.value(prop, default).boolVal
template getSettingsProp[T](self: LocalAccountSensitiveSettings, prop: string, default: QVariant): untyped =
# This doesn't work in case of QVariant, such properties will be handled in a common way.
@ -380,13 +380,13 @@ QtObject:
proc volumeChanged*(self: LocalAccountSensitiveSettings) {.signal.}
proc getVolume*(self: LocalAccountSensitiveSettings): QVariant {.slot.} =
getSettingsPropQVariant(self, LSS_KEY_VOLUME, newQVariant(DEFAULT_VOLUME))
proc setVolume*(self: LocalAccountSensitiveSettings, value: QVariant) {.slot.} =
proc getVolume*(self: LocalAccountSensitiveSettings): int {.slot.} =
getSettingsProp[int](self, LSS_KEY_VOLUME, newQVariant(DEFAULT_VOLUME))
proc setVolume*(self: LocalAccountSensitiveSettings, value: int) {.slot.} =
setSettingsProp(self, LSS_KEY_VOLUME, newQVariant(value)):
self.volumeChanged()
QtProperty[QVariant] volume:
QtProperty[int] volume:
read = getVolume
write = setVolume
notify = volumeChanged

View File

@ -2,6 +2,7 @@ import Tables, stint
import ./controller_interface
import ./io_interface
import ../../../global/app_signals
import ../../../core/eventemitter
import ../../../../app_service/service/activity_center/service as activity_center_service
import ../../../../app_service/service/contacts/service as contacts_service
@ -104,4 +105,5 @@ method decodeContentHash*[T](self: Controller[T], hash: string): string =
return eth_utils.decodeContentHash(hash)
method switchTo*[T](self: Controller[T], sectionId, chatId, messageId: string) =
self.messageService.switchTo(sectionId, chatId, messageId)
let data = ActiveSectionChatArgs(sectionId: sectionId, chatId: chatId, messageId: messageId)
self.events.emit(SIGNAL_MAKE_SECTION_CHAT_ACTIVE, data)

View File

@ -1,6 +1,7 @@
import Tables, controller_interface, chronicles
import io_interface
import ../../../global/app_signals
import ../../../global/app_sections_config as conf
import ../../../../app_service/service/contacts/service as contact_service
import ../../../../app_service/service/chat/service as chat_service
@ -150,4 +151,7 @@ method resultItemClicked*(self: Controller, itemId: string) =
info "important: we don't have stored details for a searched result item with id: ", itemId
return
self.messageService.switchTo(itemDetails.sectionId, itemDetails.channelId, itemDetails.messageId)
let data = ActiveSectionChatArgs(sectionId: itemDetails.sectionId,
chatId: itemDetails.channelId,
messageId: itemDetails.messageId)
self.events.emit(SIGNAL_MAKE_SECTION_CHAT_ACTIVE, data)

View File

@ -10,6 +10,7 @@ import ../../../../../../app_service/service/message/service as message_service
import ../../../../../../app_service/service/mailservers/service as mailservers_service
import ../../../../../../app_service/service/wallet_account/service as wallet_account_service
import ../../../../../../app_service/service/eth/utils as eth_utils
import ../../../../../global/app_signals
import ../../../../../core/signals/types
import ../../../../../core/eventemitter

View File

@ -12,6 +12,7 @@ import ../../../../app_service/service/gif/service as gif_service
import ../../../../app_service/service/mailservers/service as mailservers_service
import ../../../core/signals/types
import ../../../global/app_signals
import ../../../core/eventemitter
export controller_interface
@ -255,16 +256,9 @@ method getCurrentFleet*(self: Controller): string =
method getContacts*(self: Controller): seq[ContactsDto] =
return self.contactService.getContacts()
method getContact*(self: Controller, id: string): ContactsDto =
return self.contactService.getContactById(id)
method getContactDetails*(self: Controller, id: string): ContactDetails =
return self.contactService.getContactDetails(id)
method getContactNameAndImage*(self: Controller, contactId: string):
tuple[name: string, image: string, isIdenticon: bool] =
return self.contactService.getContactNameAndImage(contactId)
method addContact*(self: Controller, publicKey: string) =
self.contactService.addContact(publicKey)
@ -374,3 +368,6 @@ method reorderCommunityCategories*(self: Controller, categoryId: string, positio
method reorderCommunityChat*(self: Controller, categoryId: string, chatId: string, position: int): string =
self.communityService.reorderCommunityChat(self.sectionId, categoryId, chatId, position)
method getRenderedText*(self: Controller, parsedTextArray: seq[ParsedText]): string =
return self.messageService.getRenderedText(parsedTextArray)

View File

@ -1,6 +1,7 @@
import ../../../../app_service/service/contacts/dto/[contacts, contact_details]
import ../../../../app_service/service/chat/dto/[chat]
import ../../../../app_service/service/community/dto/[community]
import ../../../../app_service/service/message/dto/[message]
type
AccessInterface* {.pure inheritable.} = ref object of RootObj
@ -76,16 +77,9 @@ method getCurrentFleet*(self: AccessInterface): string {.base.} =
method getContacts*(self: AccessInterface): seq[ContactsDto] {.base.} =
raise newException(ValueError, "No implementation available")
method getContact*(self: AccessInterface, id: string): ContactsDto {.base.} =
raise newException(ValueError, "No implementation available")
method getContactDetails*(self: AccessInterface, id: string): ContactDetails {.base.} =
raise newException(ValueError, "No implementation available")
method getContactNameAndImage*(self: AccessInterface, contactId: string):
tuple[name: string, image: string, isIdenticon: bool] {.base.} =
raise newException(ValueError, "No implementation available")
method addContact*(self: AccessInterface, publicKey: string): void {.base.} =
raise newException(ValueError, "No implementation available")
@ -152,8 +146,11 @@ method setCommunityMuted*(self: AccessInterface, muted: bool) {.base.} =
method inviteUsersToCommunity*(self: AccessInterface, pubKeys: string): string {.base.} =
raise newException(ValueError, "No implementation available")
method reorderCommunityCategories*(self: AccessInterface, categoryId: string, position: int) =
method reorderCommunityCategories*(self: AccessInterface, categoryId: string, position: int) {.base.} =
raise newException(ValueError, "No implementation available")
method reorderCommunityChat*(self: AccessInterface, categoryId: string, chatId: string, position: int): string =
method reorderCommunityChat*(self: AccessInterface, categoryId: string, chatId: string, position: int): string {.base.} =
raise newException(ValueError, "No implementation available")
method getRenderedText*(self: AccessInterface, parsedTextArray: seq[ParsedText]): string {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -1,4 +1,5 @@
import NimQml, Tables, chronicles, json, sequtils, strutils
import NimQml, Tables, chronicles, json, sequtils, strutils, strformat
import io_interface
import ../io_interface as delegate_interface
import view, controller, item, sub_item, sub_model, base_item
@ -8,6 +9,7 @@ import ../../shared_models/contacts_model as contacts_model
import chat_content/module as chat_content_module
import ../../../global/app_sections_config as conf
import ../../../global/global_singleton
import ../../../core/eventemitter
import ../../../../app_service/service/settings/service_interface as settings_service
@ -67,6 +69,9 @@ method delete*(self: Module) =
method isCommunity*(self: Module): bool =
return self.controller.isCommunity()
method getMySectionId*(self: Module): string =
return self.controller.getMySectionId()
proc amIMarkedAsAdminUser(self: Module, members: seq[ChatMember]): bool =
for m in members:
if (m.id == singletonInstance.userProfile.getPubKey() and m.admin):
@ -342,14 +347,14 @@ method getChatContentModule*(self: Module, chatId: string): QVariant =
return self.chatContentModules[chatId].getModuleAsVariant()
proc updateParentNotifications(self: Module) =
proc updateParentBadgeNotifications(self: Module) =
var (sectionHasUnreadMessages, sectionNotificationCount) = self.view.chatsModel().getAllNotifications()
if(not self.controller.isCommunity()):
sectionNotificationCount += self.view.contactRequestsModel().getCount()
sectionHasUnreadMessages = sectionHasUnreadMessages or sectionNotificationCount > 0
self.delegate.onNotificationsUpdated(self.controller.getMySectionId(), sectionHasUnreadMessages, sectionNotificationCount)
proc updateNotifications(self: Module, chatId: string, unviewedMessagesCount: int, unviewedMentionsCount: int) =
proc updateBadgeNotifications(self: Module, chatId: string, unviewedMessagesCount: int, unviewedMentionsCount: int) =
let hasUnreadMessages = unviewedMessagesCount > 0
# update model of this module (appropriate chat from the chats list (chats model))
self.view.chatsModel().updateNotificationsForItemOrSubItemById(chatId, hasUnreadMessages, unviewedMentionsCount)
@ -357,13 +362,13 @@ proc updateNotifications(self: Module, chatId: string, unviewedMessagesCount: in
if (self.chatContentModules.contains(chatId)):
self.chatContentModules[chatId].onNotificationsUpdated(hasUnreadMessages, unviewedMentionsCount)
# update parent module
self.updateParentNotifications()
self.updateParentBadgeNotifications()
method onActiveSectionChange*(self: Module, sectionId: string) =
if(sectionId != self.controller.getMySectionId()):
return
self.updateNotifications(self.controller.getActiveChatId(), unviewedMessagesCount=0, unviewedMentionsCount=0)
self.updateBadgeNotifications(self.controller.getActiveChatId(), unviewedMessagesCount=0, unviewedMentionsCount=0)
self.delegate.onActiveChatChange(self.controller.getMySectionId(), self.controller.getActiveChatId())
method chatsModel*(self: Module): chats_model.Model =
@ -547,7 +552,7 @@ method onChatUnmuted*(self: Module, chatId: string) =
self.view.chatsModel().muteUnmuteItemOrSubItemById(chatId, false)
method onMarkAllMessagesRead*(self: Module, chatId: string) =
self.updateNotifications(chatId, unviewedMessagesCount=0, unviewedMentionsCount=0)
self.updateBadgeNotifications(chatId, unviewedMessagesCount=0, unviewedMentionsCount=0)
method markAllMessagesRead*(self: Module, chatId: string) =
self.controller.markAllMessagesRead(chatId)
@ -564,7 +569,7 @@ method acceptContactRequest*(self: Module, publicKey: string) =
method onContactAccepted*(self: Module, publicKey: string) =
self.view.contactRequestsModel().removeItemWithPubKey(publicKey)
self.updateParentNotifications()
self.updateParentBadgeNotifications()
method acceptAllContactRequests*(self: Module) =
let pubKeys = self.view.contactRequestsModel().getPublicKeys()
@ -576,7 +581,7 @@ method rejectContactRequest*(self: Module, publicKey: string) =
method onContactRejected*(self: Module, publicKey: string) =
self.view.contactRequestsModel().removeItemWithPubKey(publicKey)
self.updateParentNotifications()
self.updateParentBadgeNotifications()
method rejectAllContactRequests*(self: Module) =
let pubKeys = self.view.contactRequestsModel().getPublicKeys()
@ -594,16 +599,20 @@ method onContactUnblocked*(self: Module, publicKey: string) =
self.view.chatsModel().blockUnblockItemOrSubItemById(publicKey, blocked=false)
method onContactDetailsUpdated*(self: Module, publicKey: string) =
let contact = self.controller.getContact(publicKey)
if (contact.requestReceived() and
not contact.isContact()and
not contact.isBlocked() and
let contactDetails = self.controller.getContactDetails(publicKey)
if (contactDetails.details.requestReceived() and
not contactDetails.details.isContact()and
not contactDetails.details.isBlocked() and
not self.view.contactRequestsModel().containsItemWithPubKey(publicKey)):
let item = self.createItemFromPublicKey(publicKey)
self.view.contactRequestsModel().addItem(item)
self.updateParentNotifications()
self.updateParentBadgeNotifications()
singletonInstance.globalEvents.showNewContactRequestNotification("New Contact Request",
fmt "{contactDetails.displayName} added you as contact", conf.CHAT_SECTION_ID)
let (chatName, chatImage, isIdenticon) = self.controller.getOneToOneChatNameAndImage(publicKey)
let chatName = contactDetails.displayName
let chatImage = contactDetails.icon
let isIdenticon = contactDetails.isIdenticon
self.view.chatsModel().updateItemDetails(publicKey, chatName, chatImage, isIdenticon)
method onNewMessagesReceived*(self: Module, chatId: string, unviewedMessagesCount: int, unviewedMentionsCount: int,
@ -611,7 +620,20 @@ method onNewMessagesReceived*(self: Module, chatId: string, unviewedMessagesCoun
if(self.controller.getMySectionId() == self.delegate.getActiveSectionId() and
self.controller.getActiveChatId() == chatId):
return
self.updateNotifications(chatId, unviewedMessagesCount, unviewedMentionsCount)
self.updateBadgeNotifications(chatId, unviewedMessagesCount, unviewedMentionsCount)
# Prepare bubble notification
let myPK = singletonInstance.userProfile.getPubKey()
for m in messages:
let contactDetails = self.controller.getContactDetails(m.`from`)
let renderedMessageText = self.controller.getRenderedText(m.parsedText)
let plainText = singletonInstance.utils.plainText(renderedMessageText)
if(m.isUserWithPkMentioned(myPK)):
singletonInstance.globalEvents.showMentionMessageNotification(contactDetails.displayName, plainText,
self.controller.getMySectionId(), chatId, m.id)
else:
singletonInstance.globalEvents.showNormalMessageNotification(contactDetails.displayName, plainText,
self.controller.getMySectionId(), chatId, m.id)
method addGroupMembers*(self: Module, chatId: string, pubKeys: string) =
self.controller.addGroupMembers(chatId, self.convertPubKeysToJson(pubKeys))

View File

@ -12,6 +12,9 @@ method getChatContentModule*(self: AccessInterface, chatId: string): QVariant {.
method isCommunity*(self: AccessInterface): bool {.base.} =
raise newException(ValueError, "No implementation available")
method getMySectionId*(self: AccessInterface): string {.base.} =
raise newException(ValueError, "No implementation available")
method createPublicChat*(self: AccessInterface, chatId: string) {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -56,6 +56,9 @@ QtObject:
proc isCommunity(self: View): bool {.slot.} =
return self.delegate.isCommunity()
method getMySectionId*(self: View): string {.slot.} =
return self.delegate.getMySectionId()
proc chatsModel*(self: View): chats_model.Model =
return self.model

View File

@ -4,6 +4,7 @@ import ../../global/global_singleton
import ../../global/app_signals
import ../../core/signals/types
import ../../core/eventemitter
import ../../core/notifications/notifications_manager
import ../../../app_service/service/settings/service_interface as settings_service
import ../../../app_service/service/keychain/service as keychain_service
import ../../../app_service/service/accounts/service_interface as accounts_service
@ -168,6 +169,14 @@ method init*(self: Controller) =
var args = ActiveSectionChatArgs(e)
let sectionType = if args.sectionId == conf.CHAT_SECTION_ID: SectionType.Chat else: SectionType.Community
self.setActiveSection(args.sectionId, sectionType)
self.events.on(SIGNAL_OS_NOTIFICATION_CLICKED) do(e: Args):
var args = ClickedNotificationArgs(e)
self.delegate.osNotificationClicked(args.details)
self.events.on(SIGNAL_NEW_REQUEST_TO_JOIN_COMMUNITY) do(e: Args):
var args = CommunityRequestArgs(e)
self.delegate.newCommunityMembershipRequestReceived(args.communityRequest)
method getJoinedCommunities*(self: Controller): seq[CommunityDto] =
return self.communityService.getJoinedCommunities()
@ -259,5 +268,9 @@ method resolveENS*(self: Controller, ensName: string, uuid: string = "") =
method isMnemonicBackedUp*(self: Controller): bool =
result = self.privacyService.isMnemonicBackedUp()
method switchTo*(self: Controller, sectionId, chatId: string) =
self.messageService.switchTo(sectionId, chatId, "")
method switchTo*(self: Controller, sectionId, chatId, messageId: string) =
let data = ActiveSectionChatArgs(sectionId: sectionId, chatId: chatId, messageId: messageId)
self.events.emit(SIGNAL_MAKE_SECTION_CHAT_ACTIVE, data)
method getCommunityById*(self: Controller, communityId: string): CommunityDto =
return self.communityService.getCommunityById(communityId)

View File

@ -57,5 +57,8 @@ method resolveENS*(self: AccessInterface, ensName: string, uuid: string = "") {.
method isMnemonicBackedUp*(self: AccessInterface): bool {.base.} =
raise newException(ValueError, "No implementation available")
method switchTo*(self: AccessInterface, sectionId, chatId: string) {.base.} =
method switchTo*(self: AccessInterface, sectionId, chatId, messageId: string) {.base.} =
raise newException(ValueError, "No implementation available")
method getCommunityById*(self: AccessInterface, communityId: string): CommunityDto {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -1,4 +1,4 @@
import NimQml, tables, json, sugar, sequtils
import NimQml, tables, json, sugar, sequtils, strformat
import io_interface, view, controller, chat_search_item, chat_search_model
import ./communities/models/[pending_request_item, pending_request_model]
@ -50,7 +50,7 @@ import ../../../app_service/service/gif/service as gif_service
import ../../../app_service/service/ens/service as ens_service
import ../../../app_service/service/network/service as network_service
import ../../core/notifications/details
import ../../core/eventemitter
export io_interface
@ -541,7 +541,7 @@ method rebuildChatSearchModel*[T](self: Module[T]) =
self.view.chatSearchModel().setItems(items)
method switchTo*[T](self: Module[T], sectionId, chatId: string) =
self.controller.switchTo(sectionId, chatId)
self.controller.switchTo(sectionId, chatId, "")
method onActiveChatChange*[T](self: Module[T], sectionId: string, chatId: string) =
self.appSearchModule.onActiveChatChange(sectionId, chatId)
@ -663,3 +663,21 @@ method mnemonicBackedUp*[T](self: Module[T]) =
conf.SETTINGS_SECTION_ID,
self.calculateProfileSectionHasNotification(),
notificationsCount = 0)
method osNotificationClicked*[T](self: Module[T], details: NotificationDetails) =
if(details.notificationType == NotificationType.NewContactRequest):
self.controller.switchTo(details.sectionId, "", "")
self.view.emitOpenContactRequestsPopupSignal()
elif(details.notificationType == NotificationType.JoinCommunityRequest):
self.controller.switchTo(details.sectionId, "", "")
self.view.emitOpenCommunityMembershipRequestsPopupSignal(details.sectionId)
elif(details.notificationType == NotificationType.MyRequestToJoinCommunityAccepted):
self.controller.switchTo(details.sectionId, "", "")
elif(details.notificationType == NotificationType.MyRequestToJoinCommunityRejected):
info "There is no particular action clicking on a notification informing you about rejection to join community"
method newCommunityMembershipRequestReceived*[T](self: Module[T], membershipRequest: CommunityMembershipRequestDto) =
let (contactName, _, _) = self.controller.getContactNameAndImage(membershipRequest.publicKey)
let community = self.controller.getCommunityById(membershipRequest.communityId)
singletonInstance.globalEvents.newCommunityMembershipRequestNotification("New membership request",
fmt "{contactName} asks to join {community.name}", community.id)

View File

@ -1,4 +1,5 @@
import ../../shared_models/section_item
import ../../../core/notifications/details
method offerToStorePassword*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
@ -39,3 +40,10 @@ method contactUpdated*(self: AccessInterface, publicKey: string) {.base.} =
method mnemonicBackedUp*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method osNotificationClicked*(self: AccessInterface, details: NotificationDetails) {.base.} =
raise newException(ValueError, "No implementation available")
method newCommunityMembershipRequestReceived*(self: AccessInterface, membershipRequest: CommunityMembershipRequestDto)
{.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -157,3 +157,11 @@ QtObject:
proc resolvedENS*(self: View, resolvedPubKey: string, resolvedAddress: string, uuid: string) {.signal.}
proc emitResolvedENSSignal*(self: View, resolvedPubKey: string, resolvedAddress: string, uuid: string) =
self.resolvedENS(resolvedPubKey, resolvedAddress, uuid)
proc openContactRequestsPopup*(self: View) {.signal.}
proc emitOpenContactRequestsPopupSignal*(self: View) =
self.openContactRequestsPopup()
proc openCommunityMembershipRequestsPopup*(self: View, sectionId: string) {.signal.}
proc emitOpenCommunityMembershipRequestsPopupSignal*(self: View, sectionId: string) =
self.openCommunityMembershipRequestsPopup(sectionId)

View File

@ -78,6 +78,7 @@ const SIGNAL_COMMUNITY_CATEGORY_CREATED* = "communityCategoryCreated"
const SIGNAL_COMMUNITY_CATEGORY_EDITED* = "communityCategoryEdited"
const SIGNAL_COMMUNITY_CATEGORY_DELETED* = "communityCategoryDeleted"
const SIGNAL_COMMUNITY_MEMBER_APPROVED* = "communityMemberApproved"
const SIGNAL_NEW_REQUEST_TO_JOIN_COMMUNITY* = "newRequestToJoinCommunity"
QtObject:
type
@ -137,6 +138,8 @@ QtObject:
self.joinedCommunities[membershipRequest.communityId] = community
self.events.emit(SIGNAL_COMMUNITY_EDITED, CommunityArgs(community: community))
self.events.emit(SIGNAL_NEW_REQUEST_TO_JOIN_COMMUNITY, CommunityRequestArgs(communityRequest: membershipRequest))
proc mapChatToChatDto(chat: Chat, communityId: string): ChatDto =
result = ChatDto()
result.id = chat.id

View File

@ -1,6 +1,6 @@
{.used.}
import json
import json, strutils
include ../../../common/json_utils
@ -173,3 +173,10 @@ proc containsContactMentions*(self: MessageDto): bool =
if (child.type == PARSED_TEXT_CHILD_TYPE_MENTION):
return true
return false
proc isUserWithPkMentioned*(self: MessageDto, publicKey: string): bool =
for pText in self.parsedText:
for child in pText.children:
if (child.type == PARSED_TEXT_CHILD_TYPE_MENTION and child.literal.contains(publicKey)):
return true
return false

View File

@ -48,7 +48,6 @@ const SIGNAL_MESSAGE_REACTION_FROM_OTHERS* = "messageReactionFromOthers"
const SIGNAL_MESSAGE_DELETION* = "messageDeleted"
const SIGNAL_MESSAGE_EDITED* = "messageEdited"
const SIGNAL_MESSAGE_LINK_PREVIEW_DATA_LOADED* = "messageLinkPreviewDataLoaded"
const SIGNAL_MAKE_SECTION_CHAT_ACTIVE* = "makeSectionChatActive"
include async_tasks
@ -94,11 +93,6 @@ type
LinkPreviewDataArgs* = ref object of Args
response*: string
ActiveSectionChatArgs* = ref object of Args
sectionId*: string
chatId*: string
messageId*: string
QtObject:
type Service* = ref object of QObject
events: EventEmitter
@ -140,6 +134,10 @@ QtObject:
# We included `chats` in this condition cause that's the form how `status-go` sends updates.
# The first element from the `receivedData.chats` array contains details about the chat a messages received in
# `receivedData.messages` refer to.
if(chats.len == 0):
error "error: received `chats` array for handling messages update is empty"
return
let chatId = chats[0].id
let chatType = chats[0].chatType
let unviewedMessagesCount = chats[0].unviewedMessagesCount
@ -704,14 +702,5 @@ proc editMessage*(self: Service, messageId: string, msg: string) =
except Exception as e:
error "error: ", methodName="editMessage", errName = e.name, errDesription = e.msg
proc switchTo*(self: Service, sectionId: string, chatId: string, messageId: string) =
## Calling this proc the app will switch to passed `sectionId`, after that if `chatId` is set
## it will make that chat an active one and at the end if `messageId` is set it will point to
## that message.
## We should use this proc (or just emit a signal bellow) when we want to switch to certain
## section and/or chat and/or message
let data = ActiveSectionChatArgs(sectionId: sectionId, chatId: chatId, messageId: messageId)
self.events.emit(SIGNAL_MAKE_SECTION_CHAT_ACTIVE, data)
proc getWalletAccounts*(self: Service): seq[wallet_account_service.WalletAccountDto] =
return self.walletAccountService.getWalletAccounts()
return self.walletAccountService.getWalletAccounts()

View File

@ -1,40 +0,0 @@
{.used.}
import json
type
OsNotificationType* {.pure.} = enum
NewContactRequest = 1,
AcceptedContactRequest,
JoinCommunityRequest,
AcceptedIntoCommunity,
RejectedByCommunity,
NewMessage
OsNotificationDetails* = object
notificationType*: OsNotificationType
communityId*: string
channelId*: string
messageId*: string
proc toOsNotificationDetails*(json: JsonNode): OsNotificationDetails =
if (not (json.contains("notificationType") and
json.contains("communityId") and
json.contains("channelId") and
json.contains("messageId"))):
return OsNotificationDetails()
return OsNotificationDetails(
notificationType: json{"notificationType"}.getInt.OsNotificationType,
communityId: json{"communityId"}.getStr,
channelId: json{"channelId"}.getStr,
messageId: json{"messageId"}.getStr
)
proc toJsonNode*(self: OsNotificationDetails): JsonNode =
result = %* {
"notificationType": self.notificationType.int,
"communityId": self.communityId,
"channelId": self.channelId,
"messageId": self.messageId
}

View File

@ -1,59 +0,0 @@
import NimQml, json, chronicles
import details
import ../../../app/core/eventemitter
logScope:
topics = "os-notification-service"
# Signals which may be emitted by this service:
const SIGNAL_OS_NOTIFICATION_CLICKED* = "osNotificationClicked"
type
OsNotificationsArgs* = ref object of Args
details*: OsNotificationDetails
QtObject:
type Service* = ref object of QObject
events: EventEmitter
notification: StatusOSNotification
notificationSetUp: bool
proc setup(self: Service, events: EventEmitter) =
self.QObject.setup
self.events = events
proc delete*(self: Service) =
if self.notificationSetUp:
self.notification.delete
self.QObject.delete
proc newService*(events: EventEmitter): Service =
new(result, delete)
result.setup(events)
proc showNotification*(self: Service, title: string, message: string, details: OsNotificationDetails,
useOSNotifications: bool) =
## This method will add new notification to the Notification center. Param
## "details" is used to uniquely define a notification bubble.
# Whether we need to use OS notifications or not should be checked only here,
# but because we don't have settings class on the nim side yet, we're using
# useOSNotifications param sent from the qml side. Once we are able to check
# that here, we will remove useOSNotifications param from this method.
if(not useOSNotifications):
return
let identifier = $(details.toJsonNode())
self.notification.showNotification(title, message, identifier)
proc onNotificationClicked*(self: Service, identifier: string) {.slot.} =
## This slot is called once user clicks a notificaiton bubble, "identifier"
## contains data which uniquely define that notification.
let details = toOsNotificationDetails(parseJson(identifier))
self.events.emit(SIGNAL_OS_NOTIFICATION_CLICKED, OsNotificationsArgs(details: details))
proc userLoggedIn*(self: Service) =
self.notification = newStatusOSNotification()
signalConnect(self.notification, "notificationClicked(QString)", self, "onNotificationClicked(QString)", 2)
self.notificationSetUp = true

View File

@ -36,6 +36,10 @@ QtObject {
communitiesModuleInst.setObservedCommunity(communityId);
}
function getMySectionId() {
return chatCommunitySectionModule.getMySectionId()
}
function acceptContactRequest(pubKey) {
chatCommunitySectionModule.acceptContactRequest(pubKey)
}

View File

@ -104,17 +104,6 @@ Item {
tokenAddress)
}
function clickOnNotification() {
// So far we're just showing this app as the top most window. Once we decide about the way
// how to notify the app what channle should be displayed within the app when user clicks
// notificaiton bubble this part should be updated accordingly.
//
// I removed part of this function which caused app crash.
Global.applicationWindow.show()
Global.applicationWindow.raise()
Global.applicationWindow.requestActivate()
}
Timer {
interval: 60000; // 1 min
running: true
@ -336,72 +325,6 @@ Item {
messageContextMenu: contextmenu
}
Connections {
target: systemTray
onMessageClicked: function () {
clickOnNotification()
}
}
// Not Refactored Yet
// Connections {
// target: root.rootStore.chatsModelInst.messageView
// onMessageNotificationPushed: function(messageId, communityId, chatId, msg, contentType, chatType, timestamp, identicon, username, hasMention, isAddedContact, channelName) {
// if (localAccountSensitiveSettings.notificationSetting == Constants.notifyAllMessages ||
// (localAccountSensitiveSettings.notificationSetting == Constants.notifyJustMentions && hasMention)) {
// if (chatId === root.rootStore.chatsModelInst.channelView.activeChannel.id && applicationWindow.active === true) {
// // Do not show the notif if we are in the channel already and the window is active and focused
// return
// }
// root.currentNotificationChatId = chatId
// root.currentNotificationCommunityId = null
// let name;
// if (localAccountSensitiveSettings.notificationMessagePreviewSetting === Constants.notificationPreviewAnonymous) {
// name = "Status"
// } else if (chatType === Constants.chatType.publicChat) {
// name = chatId
// } else {
// name = chatType === Constants.chatType.privateGroupChat ? Utils.filterXSS(channelName) : Utils.removeStatusEns(username)
// }
// let message;
// if (localAccountSensitiveSettings.notificationMessagePreviewSetting > Constants.notificationPreviewNameOnly) {
// switch(contentType){
// //% "Image"
// case Constants.messageContentType.imageType: message = qsTrId("image"); break
// //% "Sticker"
// case Constants.messageContentType.stickerType: message = qsTrId("sticker"); break
// default: message = msg // don't parse emojis here as it emits HTML
// }
// } else {
// //% "You have a new message"
// message = qsTrId("you-have-a-new-message")
// }
// currentlyHasANotification = true
// if (Qt.platform.os === "linux") {
// // Linux Notifications are not implemented in Nim/C++ yet
// return systemTray.showMessage(name, message, systemTray.icon.source, 4000)
// }
// // Note:
// // Show notification should be moved to the nim side.
// // Left here only cause we don't have a way to deal with translations on the nim side.
// root.rootStore.chatsModelInst.showOSNotification(name,
// message,
// Constants.osNotificationType.newMessage,
// communityId,
// chatId,
// messageId,
// localAccountSensitiveSettings.useOSNotifications)
// }
// }
// }
// Not Refactored Yet
// Connections {
// target: root.rootStore.chatsModelInst.stickers

View File

@ -221,63 +221,6 @@ Item {
// onAppReady: {
// chatLogView.scrollToBottom(true)
// }
// }
// Connections {
// Not Refactored Yet
// target: root.store.chatsModelInst.communities
// // Note:
// // Whole this Connection object (both slots) should be moved to the nim side.
// // Left here only cause we don't have a way to deal with translations on the nim side.
// onMembershipRequestChanged: function (communityId, communityName, accepted) {
// chatColumnLayout.currentNotificationChatId = null
// chatColumnLayout.currentNotificationCommunityId = communityId
// const title = "Status"
// const message = //% "You have been accepted into the %1 community"
// accepted ? qsTrId("you-have-been-accepted-into-the---1--community").arg(communityName) :
// //% "Your request to join the %1 community was declined"
// qsTrId("your-request-to-join-the---1--community-was-declined").arg(communityName)
// if (Qt.platform.os === "linux") {
// // Linux Notifications are not implemented in Nim/C++ yet
// return systemTray.showMessage(title, message, systemTray.icon.source, 4000)
// }
// root.store.chatsModelInst.showOSNotification(title,
// message,
// accepted? Constants.osNotificationType.acceptedIntoCommunity :
// Constants.osNotificationType.rejectedByCommunity,
// communityId,
// "",
// "",
// localAccountSensitiveSettings.useOSNotifications)
// }
// onMembershipRequestPushed: function (communityId, communityName, pubKey) {
// chatColumnLayout.currentNotificationChatId = null
// chatColumnLayout.currentNotificationCommunityId = communityId
// //% "New membership request"
// const title = qsTrId("new-membership-request")
// //% "%1 asks to join %2"
// const message = qsTrId("-1-asks-to-join---2-").arg(Utils.getContactDetailsAsJson(pubKey).displayName).arg(communityName)
// if (Qt.platform.os === "linux") {
// // Linux Notifications are not implemented in Nim/C++ yet
// return systemTray.showMessage(title, message, systemTray.icon.source, 4000)
// }
// root.store.chatsModelInst.showOSNotification(title,
// message,
// Constants.osNotificationType.joinCommunityRequest,
// communityId,
// "",
// "",
// localAccountSensitiveSettings.useOSNotifications)
// }
// }
onContentYChanged: {

View File

@ -476,4 +476,17 @@ Item {
}
}
}
Connections {
target: root.store.mainModuleInst
onOpenCommunityMembershipRequestsPopup:{
if(root.store.getMySectionId() != sectionId)
return
Global.openPopup(membershipRequestPopup, {
communitySectionModule: root.communitySectionModule
})
}
}
}

View File

@ -461,4 +461,12 @@ Item {
Global.toastMessage.open()
}
}
Connections {
target: root.store.mainModuleInst
onOpenContactRequestsPopup:{
Global.openPopup(contactRequestsPopup)
}
}
}

View File

@ -45,11 +45,11 @@ Item {
to: 1.0
stepSize: 0.1
onValueChanged: {
localAccountSensitiveSettings.volume = volume.value
localAccountSensitiveSettings.volume = volume.value * 10
}
Component.onCompleted: {
value = localAccountSensitiveSettings.volume
value = localAccountSensitiveSettings.volume * 0.1
}
}
}

View File

@ -47,7 +47,7 @@ QtObject {
property var assets: walletSectionAccountTokens.model
// property MessageStore messageStore: MessageStore { }
property real volume: !!localAccountSensitiveSettings ? localAccountSensitiveSettings.volume : 0.0
property real volume: !!localAccountSensitiveSettings ? localAccountSensitiveSettings.volume * 0.1 : 0.2
property bool notificationSoundsEnabled: !!localAccountSensitiveSettings ? localAccountSensitiveSettings.notificationSoundsEnabled : false
property var walletSectionTransactionsInst: walletSectionTransactions

View File

@ -573,71 +573,6 @@ Item {
}
}
// Connections {
// target: chatsModel
// onNotificationClicked: {
// Global.applicationWindow.makeStatusAppActive()
// switch(notificationType){
// case Constants.osNotificationType.newContactRequest:
// appView.currentIndex = Constants.appViewStackIndex.chat
// appMain.openContactsPopup()
// break
// case Constants.osNotificationType.acceptedContactRequest:
// appView.currentIndex = Constants.appViewStackIndex.chat
// break
// case Constants.osNotificationType.joinCommunityRequest:
// case Constants.osNotificationType.acceptedIntoCommunity:
// case Constants.osNotificationType.rejectedByCommunity:
// // Not Refactored - Need to check what community exactly we need to switch to.
//// appView.currentIndex = Utils.getAppSectionIndex(Constants.community)
// break
// case Constants.osNotificationType.newMessage:
// appView.currentIndex = Constants.appViewStackIndex.chat
// break
// }
// }
// }
// Not Refactored Yet
// This
// Connections {
// target: appMain.rootStore.contactsModuleInst.model
// onContactRequestAdded: {
// if (!localAccountSensitiveSettings.notifyOnNewRequests) {
// return
// }
// const isContact = appMain.rootStore.contactsModuleInst.model.isAdded(address)
// // Note:
// // Whole this Connection object should be moved to the nim side.
// // Left here only cause we don't have a way to deal with translations on the nim side.
// const title = isContact ? qsTrId("contact-request-accepted") :
// //% "New contact request"
// qsTrId("new-contact-request")
// const message = //% "You can now chat with %1"
// isContact ? qsTrId("you-can-now-chat-with--1").arg(Utils.removeStatusEns(name)) :
// //% "%1 requests to become contacts"
// qsTrId("-1-requests-to-become-contacts").arg(Utils.removeStatusEns(name))
// if (Qt.platform.os === "linux") {
// // Linux Notifications are not implemented in Nim/C++ yet
// return systemTray.showMessage(title, message, systemTray.icon.source, 4000)
// }
// //% "Contact request accepted"
// profileModel.showOSNotification(title,
// message,
// isContact? Constants.osNotificationType.acceptedContactRequest :
// Constants.osNotificationType.newContactRequest,
// localAccountSensitiveSettings.useOSNotifications)
// }
// }
Component {
id: chooseBrowserPopupComponent
ChooseBrowserPopup {

View File

@ -14,7 +14,7 @@ QtObject {
property var walletSectionInst: !!walletSection ? walletSection : null
property var appSettings: !!localAppSettings ? localAppSettings : null
property var accountSensitiveSettings: !!localAccountSensitiveSettings ? localAccountSensitiveSettings : null
property real volume: !!accountSensitiveSettings ? accountSensitiveSettings.volume : 0.0
property real volume: !!accountSensitiveSettings ? accountSensitiveSettings.volume * 0.1 : 0.2
property bool isWalletEnabled: !!accountSensitiveSettings ? accountSensitiveSettings.isWalletEnabled : false
property bool notificationSoundsEnabled: !!accountSensitiveSettings ? accountSensitiveSettings.notificationSoundsEnabled : false
property bool neverAskAboutUnfurlingAgain: !!accountSensitiveSettings ? accountSensitiveSettings.neverAskAboutUnfurlingAgain : false

View File

@ -27,15 +27,6 @@ QtObject {
readonly property int node: 4
}
readonly property QtObject osNotificationType: QtObject{
readonly property int newContactRequest: 1
readonly property int acceptedContactRequest: 2
readonly property int joinCommunityRequest: 3
readonly property int acceptedIntoCommunity: 4
readonly property int rejectedByCommunity: 5
readonly property int newMessage: 6
}
readonly property QtObject userStatus: QtObject{
readonly property int offline: 0
readonly property int online: 1

View File

@ -150,15 +150,6 @@ StatusWindow {
}
}
}
onActiveChanged: {
if (applicationWindow.active && currentlyHasANotification) {
currentlyHasANotification = false
// QML doesn't have a function to hide notifications, but this does the trick
systemTray.hide()
systemTray.show()
}
}
}
Connections {
@ -215,8 +206,6 @@ StatusWindow {
signal navigateTo(string path)
property bool currentlyHasANotification: false
function makeStatusAppActive() {
applicationWindow.show()
applicationWindow.raise()

2
vendor/DOtherSide vendored

@ -1 +1 @@
Subproject commit 379e803d9467ddb460e3a32cae3455ccb2880d26
Subproject commit 5509d6f9630d675075b070ba27044361be21315a

2
vendor/nimqml vendored

@ -1 +1 @@
Subproject commit d3fdb6eed265b14cb902a16e06bf0ff6493ad6dd
Subproject commit fea98f226c58395347e987502a097c4386dac42a