Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vmj-qt
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kulya
vmj-qt
Commits
9740c563
Commit
9740c563
authored
Apr 22, 2022
by
Tijmen de Mes
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added support for sip message to chat window
parent
6f413c5d
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
113 additions
and
8 deletions
+113
-8
chatwindow.py
blink/chatwindow.py
+113
-8
No files found.
blink/chatwindow.py
View file @
9740c563
...
@@ -3,6 +3,7 @@ import base64
...
@@ -3,6 +3,7 @@ import base64
import
locale
import
locale
import
os
import
os
import
re
import
re
import
uuid
from
PyQt5
import
uic
from
PyQt5
import
uic
from
PyQt5.QtCore
import
Qt
,
QBuffer
,
QEasingCurve
,
QEvent
,
QPoint
,
QPointF
,
QPropertyAnimation
,
QRect
,
QRectF
,
QSettings
,
QSize
,
QSizeF
,
QTimer
,
QUrl
,
pyqtSignal
from
PyQt5.QtCore
import
Qt
,
QBuffer
,
QEasingCurve
,
QEvent
,
QPoint
,
QPointF
,
QPropertyAnimation
,
QRect
,
QRectF
,
QSettings
,
QSize
,
QSizeF
,
QTimer
,
QUrl
,
pyqtSignal
...
@@ -37,6 +38,7 @@ from sipsimple.threading import run_in_thread
...
@@ -37,6 +38,7 @@ from sipsimple.threading import run_in_thread
from
blink.configuration.datatypes
import
FileURL
,
GraphTimeScale
from
blink.configuration.datatypes
import
FileURL
,
GraphTimeScale
from
blink.configuration.settings
import
BlinkSettings
from
blink.configuration.settings
import
BlinkSettings
from
blink.contacts
import
URIUtils
from
blink.contacts
import
URIUtils
from
blink.messages
import
MessageManager
from
blink.resources
import
IconManager
,
Resources
from
blink.resources
import
IconManager
,
Resources
from
blink.sessions
import
ChatSessionModel
,
ChatSessionListView
,
SessionManager
,
StreamDescription
from
blink.sessions
import
ChatSessionModel
,
ChatSessionListView
,
SessionManager
,
StreamDescription
from
blink.util
import
run_in_gui_thread
from
blink.util
import
run_in_gui_thread
...
@@ -305,10 +307,12 @@ class ChatMessage(ChatContent):
...
@@ -305,10 +307,12 @@ class ChatMessage(ChatContent):
direction
=
ChatContentStringAttribute
(
'direction'
,
allowed_values
=
(
'incoming'
,
'outgoing'
))
direction
=
ChatContentStringAttribute
(
'direction'
,
allowed_values
=
(
'incoming'
,
'outgoing'
))
autoreply
=
ChatContentBooleanOption
(
'autoreply'
)
autoreply
=
ChatContentBooleanOption
(
'autoreply'
)
def
__init__
(
self
,
message
,
sender
,
direction
,
history
=
False
,
focus
=
False
):
def
__init__
(
self
,
message
,
sender
,
direction
,
history
=
False
,
focus
=
False
,
id
=
None
):
super
(
ChatMessage
,
self
)
.
__init__
(
message
,
history
,
focus
)
super
(
ChatMessage
,
self
)
.
__init__
(
message
,
history
,
focus
)
self
.
sender
=
sender
self
.
sender
=
sender
self
.
direction
=
direction
self
.
direction
=
direction
self
.
id
=
str
(
uuid
.
uuid4
())
if
id
is
None
else
id
self
.
status
=
''
def
is_related_to
(
self
,
other
):
def
is_related_to
(
self
,
other
):
return
super
(
ChatMessage
,
self
)
.
is_related_to
(
other
)
and
self
.
sender
==
other
.
sender
and
self
.
direction
==
other
.
direction
return
super
(
ChatMessage
,
self
)
.
is_related_to
(
other
)
and
self
.
sender
==
other
.
sender
and
self
.
direction
==
other
.
direction
...
@@ -682,9 +686,27 @@ class ChatWidget(base_class, ui_class):
...
@@ -682,9 +686,27 @@ class ChatWidget(base_class, ui_class):
self
.
chat_element
.
appendInside
(
message
.
to_html
(
self
.
style
,
user_icons
=
self
.
user_icons_css_class
))
self
.
chat_element
.
appendInside
(
message
.
to_html
(
self
.
style
,
user_icons
=
self
.
user_icons_css_class
))
self
.
last_message
=
message
self
.
last_message
=
message
def
send_message
(
self
,
content
,
content_type
=
'text/plain'
,
recipients
=
None
,
courtesy_recipients
=
None
,
subject
=
None
,
timestamp
=
None
,
required
=
None
,
additional_headers
=
None
):
def
update_message_status
(
self
,
id
,
status
):
if
status
==
'failed'
:
icon
=
self
.
warning_icon
else
:
icon
=
self
.
checkmark_icon
insertion_point
=
self
.
chat_element
.
findFirst
(
f
'span#status-{id}'
)
insertion_point
.
replace
(
ChatMessageStatus
(
status
,
icon
.
filename
,
id
)
.
to_html
(
self
.
style
))
def
send_sip_message
(
self
,
content
,
content_type
=
'text/plain'
,
recipients
=
None
,
courtesy_recipients
=
None
,
subject
=
None
,
timestamp
=
None
,
required
=
None
,
additional_headers
=
None
,
id
=
None
):
account
=
self
.
session
.
blink_session
.
account
contact
=
self
.
session
.
blink_session
.
contact
manager
=
MessageManager
()
manager
.
send_message
(
account
,
contact
,
content
,
content_type
,
recipients
,
courtesy_recipients
,
subject
,
timestamp
,
required
,
additional_headers
,
id
)
def
send_message
(
self
,
content
,
content_type
=
'text/plain'
,
recipients
=
None
,
courtesy_recipients
=
None
,
subject
=
None
,
timestamp
=
None
,
required
=
None
,
additional_headers
=
None
,
id
=
None
):
blink_session
=
self
.
session
.
blink_session
blink_session
=
self
.
session
.
blink_session
if
blink_session
.
chat_type
is
None
:
self
.
send_sip_message
(
content
,
content_type
,
recipients
,
courtesy_recipients
,
subject
,
timestamp
,
required
,
additional_headers
,
id
)
return
if
blink_session
.
state
in
(
'initialized'
,
'ended'
):
if
blink_session
.
state
in
(
'initialized'
,
'ended'
):
blink_session
.
init_outgoing
(
blink_session
.
account
,
blink_session
.
contact
,
blink_session
.
contact_uri
,
[
StreamDescription
(
'chat'
)],
reinitialize
=
True
)
blink_session
.
init_outgoing
(
blink_session
.
account
,
blink_session
.
contact
,
blink_session
.
contact_uri
,
[
StreamDescription
(
'chat'
)],
reinitialize
=
True
)
blink_session
.
connect
()
blink_session
.
connect
()
...
@@ -810,6 +832,16 @@ class ChatWidget(base_class, ui_class):
...
@@ -810,6 +832,16 @@ class ChatWidget(base_class, ui_class):
self
.
_align_chat
(
scroll
=
True
)
self
.
_align_chat
(
scroll
=
True
)
def
_SH_ChatInputTextChanged
(
self
):
def
_SH_ChatInputTextChanged
(
self
):
if
self
.
session
.
blink_session
.
chat_type
is
None
:
manager
=
MessageManager
()
if
self
.
chat_input
.
empty
:
if
self
.
composing_timer
.
isActive
():
self
.
composing_timer
.
stop
()
manager
.
send_composing_indication
(
self
.
session
.
blink_session
,
'idle'
)
elif
not
self
.
composing_timer
.
isActive
():
manager
.
send_composing_indication
(
self
.
session
.
blink_session
,
'active'
)
self
.
composing_timer
.
start
(
10000
)
else
:
chat_stream
=
self
.
session
.
chat_stream
chat_stream
=
self
.
session
.
chat_stream
if
chat_stream
is
None
:
if
chat_stream
is
None
:
return
return
...
@@ -845,15 +877,16 @@ class ChatWidget(base_class, ui_class):
...
@@ -845,15 +877,16 @@ class ChatWidget(base_class, ui_class):
except
AttributeError
:
except
AttributeError
:
pass
pass
return
return
id
=
str
(
uuid
.
uuid4
())
try
:
try
:
self
.
send_message
(
text
,
content_type
=
'text/html'
)
self
.
send_message
(
text
,
content_type
=
'text/html'
,
id
=
id
)
except
Exception
as
e
:
except
Exception
as
e
:
self
.
add_message
(
ChatStatus
(
'Error sending message:
%
s'
%
e
))
# decide what type to use here. -Dan
self
.
add_message
(
ChatStatus
(
'Error sending message:
%
s'
%
e
))
# decide what type to use here. -Dan
else
:
else
:
account
=
self
.
session
.
blink_session
.
account
account
=
self
.
session
.
blink_session
.
account
content
=
HtmlProcessor
.
autolink
(
text
)
content
=
HtmlProcessor
.
autolink
(
text
)
sender
=
ChatSender
(
account
.
display_name
,
account
.
id
,
self
.
user_icon
.
filename
)
sender
=
ChatSender
(
account
.
display_name
,
account
.
id
,
self
.
user_icon
.
filename
)
self
.
add_message
(
ChatMessage
(
content
,
sender
,
'outgoing'
))
self
.
add_message
(
ChatMessage
(
content
,
sender
,
'outgoing'
,
id
=
id
))
def
_SH_ChatInputLockReleased
(
self
,
lock_type
):
def
_SH_ChatInputLockReleased
(
self
,
lock_type
):
if
lock_type
is
EncryptionLock
:
if
lock_type
is
EncryptionLock
:
...
@@ -861,6 +894,11 @@ class ChatWidget(base_class, ui_class):
...
@@ -861,6 +894,11 @@ class ChatWidget(base_class, ui_class):
def
_SH_ComposingTimerTimeout
(
self
):
def
_SH_ComposingTimerTimeout
(
self
):
self
.
composing_timer
.
stop
()
self
.
composing_timer
.
stop
()
if
self
.
session
.
blink_session
.
chat_type
is
None
:
manager
=
MessageManager
()
manager
.
send_composing_indication
(
self
.
session
.
blink_session
,
'idle'
)
return
chat_stream
=
self
.
session
.
chat_stream
or
Null
chat_stream
=
self
.
session
.
chat_stream
or
Null
try
:
try
:
chat_stream
.
send_composing_indication
(
'idle'
)
chat_stream
.
send_composing_indication
(
'idle'
)
...
@@ -1455,7 +1493,7 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin):
...
@@ -1455,7 +1493,7 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin):
sliding_panels
=
True
sliding_panels
=
True
__streamtypes__
=
{
'chat'
,
'screen-sharing'
,
'video'
}
# the stream types for which we show the chat window
__streamtypes__
=
{
'chat'
,
'screen-sharing'
,
'video'
,
'message'
}
# the stream types for which we show the chat window
def
__init__
(
self
,
parent
=
None
):
def
__init__
(
self
,
parent
=
None
):
super
(
ChatWindow
,
self
)
.
__init__
(
parent
)
super
(
ChatWindow
,
self
)
.
__init__
(
parent
)
...
@@ -1522,6 +1560,10 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin):
...
@@ -1522,6 +1560,10 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin):
notification_center
.
add_observer
(
self
,
name
=
'MediaStreamDidFail'
)
notification_center
.
add_observer
(
self
,
name
=
'MediaStreamDidFail'
)
notification_center
.
add_observer
(
self
,
name
=
'MediaStreamDidEnd'
)
notification_center
.
add_observer
(
self
,
name
=
'MediaStreamDidEnd'
)
notification_center
.
add_observer
(
self
,
name
=
'MediaStreamWillEnd'
)
notification_center
.
add_observer
(
self
,
name
=
'MediaStreamWillEnd'
)
notification_center
.
add_observer
(
self
,
name
=
'GotMessage'
)
notification_center
.
add_observer
(
self
,
name
=
'GotComposingIndication'
)
notification_center
.
add_observer
(
self
,
name
=
'DidAcceptMessage'
)
notification_center
.
add_observer
(
self
,
name
=
'DidNotDeliverMessage'
)
# self.splitter.splitterMoved.connect(self._SH_SplitterMoved) # check this and decide on what size to have in the window (see Notes) -Dan
# self.splitter.splitterMoved.connect(self._SH_SplitterMoved) # check this and decide on what size to have in the window (see Notes) -Dan
...
@@ -2262,6 +2304,69 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin):
...
@@ -2262,6 +2304,69 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin):
SIPApplication
.
alert_audio_bridge
.
add
(
player
)
SIPApplication
.
alert_audio_bridge
.
add
(
player
)
player
.
start
()
player
.
start
()
def
_NH_GotMessage
(
self
,
notification
):
blink_session
=
notification
.
sender
session
=
blink_session
.
items
.
chat
message
=
notification
.
data
if
session
is
None
:
return
if
message
.
content_type
.
startswith
(
'image/'
):
content
=
'''<img src="data:{};base64,{}" class="scaled-to-fit" />'''
.
format
(
message
.
content_type
,
message
.
content
.
decode
(
'base64'
)
.
rstrip
())
elif
message
.
content_type
.
startswith
(
'text/'
):
content
=
message
.
content
content
=
HtmlProcessor
.
autolink
(
content
if
message
.
content_type
==
'text/html'
else
QTextDocument
(
content
)
.
toHtml
())
else
:
return
try
:
uri
=
'
%
s@
%
s'
%
(
message
.
sender
.
uri
.
user
.
decode
(),
message
.
sender
.
uri
.
host
.
decode
())
except
AttributeError
:
uri
=
'
%
s@
%
s'
%
(
message
.
sender
.
uri
.
user
,
message
.
sender
.
uri
.
host
)
account_manager
=
AccountManager
()
if
account_manager
.
has_account
(
uri
):
account
=
account_manager
.
get_account
(
uri
)
sender
=
ChatSender
(
message
.
sender
.
display_name
or
account
.
display_name
,
uri
,
session
.
chat_widget
.
user_icon
.
filename
)
elif
blink_session
.
remote_focus
:
contact
,
contact_uri
=
URIUtils
.
find_contact
(
uri
)
sender
=
ChatSender
(
message
.
sender
.
display_name
or
contact
.
name
,
uri
,
contact
.
icon
.
filename
)
else
:
sender
=
ChatSender
(
message
.
sender
.
display_name
or
session
.
name
,
uri
,
session
.
icon
.
filename
)
session
.
chat_widget
.
add_message
(
ChatMessage
(
content
,
sender
,
'incoming'
,
id
=
message
.
id
))
session
.
remote_composing
=
False
settings
=
SIPSimpleSettings
()
if
settings
.
sounds
.
play_message_alerts
and
self
.
selected_session
is
session
:
player
=
WavePlayer
(
SIPApplication
.
alert_audio_bridge
.
mixer
,
Resources
.
get
(
'sounds/message_received.wav'
),
volume
=
20
)
SIPApplication
.
alert_audio_bridge
.
add
(
player
)
player
.
start
()
def
_NH_DidAcceptMessage
(
self
,
notification
):
blink_session
=
notification
.
sender
session
=
blink_session
.
items
.
chat
if
session
is
None
:
return
session
.
chat_widget
.
update_message_status
(
id
=
notification
.
data
.
id
,
status
=
'accepted'
)
def
_NH_DidNotDeliverMessage
(
self
,
notification
):
blink_session
=
notification
.
sender
session
=
blink_session
.
items
.
chat
if
session
is
None
:
return
session
.
chat_widget
.
add_message
(
ChatStatus
(
f
'Delivery failed: {notification.data.data.code} - {notification.data.data.reason}'
))
session
.
chat_widget
.
update_message_status
(
id
=
notification
.
data
.
id
,
status
=
'failed'
)
def
_NH_GotComposingIndication
(
self
,
notification
):
session
=
notification
.
sender
.
items
.
chat
if
session
is
None
:
return
session
.
update_composing_indication
(
notification
.
data
)
def
_NH_ChatStreamGotComposingIndication
(
self
,
notification
):
def
_NH_ChatStreamGotComposingIndication
(
self
,
notification
):
session
=
notification
.
sender
.
blink_session
.
items
.
chat
session
=
notification
.
sender
.
blink_session
.
items
.
chat
if
session
is
None
:
if
session
is
None
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment