The autocompletion panel is reparented to the body element and placed
using an absolute position. However, as the body element used a flex
layout the absolute position of the panel was ignored. Therefore now all
the body elements are wrapped in another div element, which becomes the
flex element and acts like the body element, so the real body element is
no longer flex and reparenting the autocompletion panel to it then works
as expected.
Besides that the CSS for the autocompletion panel were not included in
public share auth pages.
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
In Firefox accessing "cssRules" may throw a "SecurityError" if the style
sheet was loaded from a different domain. The style sheets loaded by
Nextcloud all come from the same domain, but some Firefox extensions
inject their own stylesheets from a different domain. Due to this, when
the style sheet from the vue-at component was being looked for those
style sheets from a different domain could be iterated over, which
caused the exception to be thrown and stopped the load of Talk, which
ended causing a blank page.
In a similar way this caused an exception to be thrown when starting a
call in the Files app sidebar, which ended causing the call view to not
be shown in the sidebar.
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
The wrapped version roots all the rules of the default style sheet on
".talk.candidate-mentions", so the rules affect only the candidate
mentions of Talk. Otherwise, as the default rules are too broad (as they
use just ".atwho-XXX") they could mess with the autocompletion of other
elements (like the comments tab in the Files app).
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
This will be needed to limit the style applied only to the vue-at panel
created by Talk, as by default it uses "atwho-XXX" classes, which clash
for example with the autocompletion in the comments tab of the Files
app.
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
Although it is possible to use the "title" attribute of a style sheet as
an ID that is totally wrong and a complete misuse of the attribute.
Moreover, that only works when only a single style sheet has a title
set.
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
If the sidebar is opened in a different file during a call the sidebar
header contents may not be properly restored due to the order in which
the updates are handled, so it needs to be executed again when the
FileInfo has been set and it does not match the current conversation.
Otherwise the call view could be a child of the header instead of the
header actions, so if a call is started again "hidden-by-call" will be
set to the call view too, hiding it during the call.
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
When a video element is removed from the DOM and then added again it
will be frozen in its last frame until its "srcObject" is set again
(even overwriting itself with
"videoElement.srcObject = videoElement.srcObject" would be enough).
Closing and opening the sidebar removes it from and adds it back to the
DOM, but as "srcObject" is only set when the stream changes the video
element was frozen after opening the sidebar again.
Instead of notifying the child views that they were shown again (as it
does not seem to be possible to detect it from the child views
themselves) so they can refresh the "srcObjects", for simplicity now the
CallView is fully rendered again when the sidebar is opened after being
closed.
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
Currently this mimics the layout used in Talk 7 when the call view was
shown in the Files app sidebar (smaller avatars, videos and paddings, no
screensharing button...), but even once the call view is moved to the
new layout a special handling will be needed when the space is limited.
Ideally the call view should automatically change between layouts based
on its size (probably using something like
ResizeObserver/MutationObserver), but for the time being it is
explicitly enabled when the call view is shown in the Files app sidebar.
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
As the call view has a black background the close button of the sidebar
is forced to white during calls to make it visible.
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
During calls the call view is now moved from the header actions to the
header itself, and all the other elements in the header (except the
close button) are hidden. This is done by setting a special CSS class,
"hidden-by-call", which is defined in a style sheet added dynamically.
When the file is changed the sidebar is cleared until the new file is
loaded. However, "setFileInfo" is called once the new file has loaded,
so the call view can not be hidden based on when a new fileInfo is set,
as that would keep the call view shown while the sidebar only shows the
loading spinner. However, "OCA.Talk.fileInfo" is cleared by
"FilesSidebarTab" when the tab is destroyed, which happens when the rest
of the sidebar is cleared, so that fileInfo is the one used to show and
hide the call view.
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
Currently the dummy call view is simply shown when the user is in the
call and hidden otherwise.
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
The CallButton component uses the current conversation and participant
from the Vuex store to set its state. When changing to a different
conversation and joining a previous conversation again the CallButton
may be shown before the conversation and participants have been fetched
again, so they need to be removed when the conversation is left.
Otherwise the CallButton may show a wrong state for a while (like being
in a call if the user changed to a different conversation while being in
a call) when joining the conversation again.
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
The vue-at library only searches in the display name by default.
But luckily our server responds already only with matching items,
so we just filter none and show them all.
Signed-off-by: Joas Schilling <coding@schilljs.com>
In order to show the user label in the autocompletion panel but set the
user id in the content editable both attributes need to be included for
every vue-at member. When the members are objects instead of a string
the "name-key" property needs to be used so vue-at knows which attribute
to use to filter the panel based on the text after the "@". However, the
default embedded item uses that attribute, so a custom template is
needed to set the user id in the content editable. In turn, this causes
the content editable contents to be set as HTML elements instead of
plain text, so the HTML element of the mentions need to be converted to
plain "@userId" before sending them to the server.
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
The vue-at component is used to provide the autocompletion UI. This
component handles the edition in its wrapped contenteditable, so the
"vue-contenteditable-directive" is no longer needed. As the new message
form hides its overflowing children (and it can not be removed, as it
breaks the layout when typing long (tall) messages) the
"vue-at-reparenter" helper is used.
In this initial version the candidate mentions show the id of the user
or guest that matches the current "@" mention being written and, when
selected, adds that id as plain text to the editable content.
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
By default the "vue-contenteditable-directive" sets the text of a
contenteditable div using the "innerText" property, which causes any
HTML markup to become escaped plain text inside the div. In order to
provide rich text messages with mentions real HTML elements are needed,
so the "dangerousHTML" option needs to be enabled so the text is set to
the "innerHTML" property instead.
When real HTML elements are used the browser adds new lines using "<br>"
and spaces that would otherwise be collapsed into one (like several
white spaces in a row) using " ". Therefore now the raw text of the
contenteditable div needs to be converted to the format expected by the
server (that is, "\n" and regular white spaces).
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
The panel of the vue-at component is a child of the root element of the
component. In some cases a different parent may be needed, but the
component does not provide any way to change that, so a helper mixin
that works around that limitation was added.
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
The UserBubble component currently does not provide a way to set an
arbitrary letter on the avatar, only the first letter of the display
name or an icon. Therefore, for the time being, a user icon is used for
the avatar instead of the "?" character.
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
Due to the changes in the message list it is no longer needed to reset
the height of the chat view. Moreover, the chat view now needs to have a
height of 100% (which was the reset value before) in order to be
properly shown in Chromium.
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
The MessagesList starts getting messages once the current participant
has been set, so it needs to be fetched and set after joining the
conversation (as if the current user is not a participant of the
conversation yet only a limited data about the conversation will be
received). Getting the conversation automatically sets the current
participant, and as both the conversation and the participant will be
needed for the CallButton, which will be added later, the participant is
now set implicitly through the conversation.
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
join/leaveConversation are marked as asynchronous, so it is expected
that invoking them with await will wait until the conversation is joined
or left before continuing.
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
Instead of failing and redirecting to root,
we try to manually load the conversation in case it is a public one.
Signed-off-by: Joas Schilling <coding@schilljs.com>
When the current participant is in the lobby the messages and
participants can not be fetched.
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
As "getNewMessages" is enqueued to be executed in the next tick it could
happen (even if it is extremely rare) that the MessagesList component is
destroyed in the meantime. If that happens the component is disconnected
from the store, so it can access only those values already known. Due to
this the last known message ID is never updated, so when a new message
is sent the MessagesList enters in a infinite loop trying to get the new
messages again and again always using an old message ID.
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
The MessagesList component only started getting the messages after a
conversation was joined. Due to this the messages were not updated after
joining a call, as the original MessageList component was removed from
the main view and a new component was added to the sidebar, but as the
conversation was not changed the new MessagesList component did not
fetch new messages and only showed those that were already in the store.
Now getting the messages is done based on the conversation token and
whether the current participant is a participant of the conversation or
not. Both checks are needed and independent; when "token" changes that
signals a change in the current conversation, and when "isParticipant"
changes that signals that the current participant is now a participant
or not any longer of the conversation.
Note that getting the messages can not be done on 'routeChange' events,
as the token might not have been updated yet when the event is handled,
which would cause the messages for the new conversation to be got with
the token of the previous conversation (and with that all sort of
problems).
Finally, when scrolling to bottom it is necessary to check that there is
any message in the conversation. Otherwise "beforeUpdate" could be
triggered by some property change before the first batch of messages is
received, which would clear the "initiated" flag and thus no scrolling
would happen once the messages are finally got (although the scrolling
code need a revamp, this is just a small adjustment).
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
- Fix alignment and proper sizing of the elements
- Reduced star size for better antialiasing
Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
Several EventBus event handlers were registered in the components, but
never unregistered. Due to this even when the components were destroyed
the handlers were still active, so the references to the components
prevented them to be garbage collected.
Moreover, as the handlers were still active they were still called when
their associated event was triggered, which could cause for example an
infinite loop of requests to get new messages (as the store was
disconnected and thus the MessagesList component never got an updated
last known message ID, so it requested again and again new messages).
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>