When native SDK users end a meeting the view gets disposed and detached from
React, and then the entire app gets destroyed and these errors get printed at
the error level, throwing some people off.
This was hit on a corner case when ConnectionService will deny
the request to start the call. I am not sure, but it could have been
that the conference object has been disposed or closed or something
else, but the fact is that 'conference.room' was not defined and things
crashed. It is not safe to access conference's private field 'room'. It
is true JitsiConference doesn't follow the practice of marking this
field as private with the underscore '_', but it is not a public field.
* Updates kick showing who kicked us.
* Notify participants that someone was kicked.
* Shows notification to user who is remotely muted.
* Updates the notification type.
* Muted by notification for mobile.
* Moves code to react and adds the kick notifications to mobile.
* Updates lib-jitsi-meet.
If a value is not set in localStorage then null is
returned. null should not be converted to an empty
string (via _.escape) because that will then be
stored in localStorage as the user set preference
and will keep overriding any other values set
in localStorage for the displayname.
- Use actions to notify the rest of the app that
a mic or camera error has occurred
- Use middleware to respond to those notifications
of errors by showing in-app notifications and
notifying the external api
This PR changes the logic for connecting / disconnecting conferences. Instead of
doing it in mount / unmount events from the Conference component, it moves the
logic to the appNavigatee action.
This fixes a regression introduced in 774c5ecd when trying to make sure the
conference terminated event is always sent.
By moving the logic to appNavigate we no longer depend on side-effects for
connecting / disconnecting, and the code should be more maintainable moving
forward.
An improvement to this is the concept of sessions, which, while not tackled
here, was taken into consideration.
For the external api to fire update events out of the iframe, it
must first be initialized within the jitsi app. Any invocations
by the app to send updates events before initialization will
cause the api to swallow the events. The chosen fix is to
initialize the api earlier so the first update of app's redux
store fires update events that the api will also fire out of
the iframe.
This change will affect current behavior in that right now
the update event of the initial set of the avatar url is
blocked, but the change will make that event fire out of the
iframe.
Currently devices set through the api are stored
as ids, and not user selected. This can cause
other existing user selected devices to take
precedence over the devices passed into the api.
* Fix detecting preferred audio output.
Fixes detecting when a new output device is found and we have stored user preference of using that device.
* Does not store which is the currently open device on save.
Does not save the currently opened device when saving settings dialog, this will be done once we successfully replace the tracks to use the new devices.
* Saves opened audio device after successfully changing it.
If we do it earlier _updateAudioDeviceId is using localAudio and can store wrong value.
* Adds notification for new non preferred devices.
A notification is shown which gives an option to the user to select and use the newly plugged devices.
Adding custom button and handler for the action to the notifications.
* Changes logic to search and handle all newly added devices from array.
* Moves some utility methods to features/base/devices.
The state about currently opened devices is filtered and not stored, where we only store when user selects a device preferences.
Also allow changing input devices for Firefox when we are not in a conference.
* Prints errors in case of wrong initialization.
Not printing can masks some errors in the code.
* Allow only one Follow Me moderator in a meeting.
* Sends Follow Me state with all presences of the moderator.
This fixes an issue where the moderator sends the Follow Me state and then for example mute or unmute video (this will produce a presence without Follow Me state) and the new comers will not reflect current Follow Me state till a change of it comes.
* Changes fixing comments.
* Changes fixing comments.
Dear reader, I'm not proud at all of what you are about to read, but sometimes
life just gives you lemons, so enjoy some lemonade!
Joining a conference implies first creating the XMPP connection and then joining
the MUC. It's very possible the XMPP connection was made but there was no chance
for the conference to be created.
This patch fixes this case by artificially genrating a conference terminated
event in such case. In order to have all the necessary knowledge for this event
to be sent the connection now keeps track of the conference that runs it.
In addition, there is an even more obscure corner case: it's not impossible to
try to disconnect when there is not even a connection. This was fixed by
creating a fake disconnect event. Alas the location URL is lost at this point,
but it's better than nothing I guess.
Searching for a device (id) by label alone can result in
false results when devices share labels, such as a mic
and speaker having the same label. To prevent such,
specify the device kind to be found instead of iterating
over all device kinds.
When the iFrame api is used to set a preferred audio output using
options passed into the JitsiMeetExternalAPI constructor, no logic
fires to actually change the audio output destination.
Using anything non-serializable for action types is discouraged:
https://redux.js.org/faq/actions#actions
In fact, this is the Flow definition for dispatching actions:
declare export type DispatchAPI<A> = (action: A) => A;
declare export type Dispatch<A: { type: $Subtype<string> }> = DispatchAPI<A>;
Note how the `type` field is defined as a subtype of string, which Symbol isn’t.
* Adds new format of phoneList service and re-design dial in numbers page.
Adds flags and country names (with translations) for the numbers if using the new format.
* Fixes tests and fixes get default number.
* Updates swagger with new format.
* Moves html back yo table.
Fixes displaying on mobile and also the tel: URI generation. The tel: URI is tested on Android and iOS and seems to work (Android was not interpreting 'p', but both seems to like ',').
* Fixes a wrong return statement.
* Small fixes.
This reverts commit 7c911eca96.
I'm dumb. We need global mode because otherwise lastIndex is not updated in the
regex object, which we rely upon, so this is intentional.
Looks like custom-scheme links no longer work in all browsers. They do on
Firefox, but the don't in Chrome and other default browsers.
So, switch to intent links on Android:
https://developer.chrome.com/multidevice/android/intents
Example:
```
<a href="intent://meet.jit.si/test123#Intent;scheme=org.jitsi.meet;package=org.jitsi.meet;end">Open Jitsi Meet</a>
```
Dominant speaker events can trigger local participant updates
without a display name. Do not update the name unless there
is an explicit update in the action.
Instead of bundling it in lib-jitsi-meet, which unnecessarily increases
lib-jitsi-meet's bundle size, polyfill it here so it's available in the global
scope, just like the web does.
* fix(local-recording): allow config override to enable
Config overrides are not set until some time after
APP_WILL_MOUNT has completed and not in the same execution
context as when APP_WILL_MOUNT is called. So instead
choose recording controller initialization at a later time.
The time chosen is after conference join because the
controller needs the conference instance to work.
* remove redundant conditional check
Analytics is erroring when unpinning because the logged
event sends null for the objectId. The objectId should
be the id of the person getting unpinned.
This feature is intended for spot. Spot can have an
HDMI -> usb adapter hooked up to it. In that case,
attempting to screenshare should use that adapter
as a screensharing source. Jitsi-Meet should pass
a configured screenshare source into lib-jitsi-meet
so it can be used as a source.
componentWillMount is a deprecated lifecycle method;
componentDidMount should be used to kick off things
like ajax. In the case of the _App hierarchy, a promise
chain is used to perform initialization, and it is
first started in the constructor by initializing
storage. However, by the time storage is initialized,
resolving the first promise, _App has already mounted.
So, move it all to the componentDidMount lifecycle.
The package now requires using a ModalTransition component
to handle animations. The existing DialogContainer component
has been split into native and web implementations to support
this change.
Updating react-native-fast-image brings a couple of interesting changes:
- onLoad is not called for cached images (reported and ignored upstream)
- load progress not working if component not displayed (on Android)
In order to fix this, a combination of 2 approaches was used:
- onLoadEnd / onError are used to detect if the image is loaded
- off-screen rendering is used on Android to get progress events
While implementing the above, yours truly noticed the complexity was increasing
way too much, so some extra refactoring was also performed:
- componentWillReceiveProps is dropped
- an auxiliary component (AvatarContent) is used for the actual content of the
Avatar, with the former passing the key prop to the latter
Using the key prop ensures AvatarContent will be recreated if the URI changes,
which is not a bad idea anyway, since the new image needs to be downloaded.
The upstream package has been unmaintained for 2 years now, and making the litle
changes needed as React Native needs them is getting old. The actual
funcionality is a couple of one-liners plus tons of boliterplate, which gets
reduced by quite a bit if we just embed it. So here it goes.
It doesn't seem like videoTrack needs to be set onto state
if it can be accessed directly from props. Removing the state
automatically removes the deprecated componentWillReceiveProps.
Filmstrip remote thumbnails display under certain conditions, as
defined in filmstrip/functions.web.js. Previously the raw
participant count was used, which included fake participants.
Using the selector getParticipantCount excludes fake participants,
causing YouTube thumbnails to remain hidden in a 1-on-1 call.
- Derive the showOverlay state. When the sidebar should be hidden,
the internal showOverlay state should remain true until the
animation hides it. When the sidebar should show, the showOverlay
state should become true immediately.
- Use PureComponent to prevent additional animation triggers
instead of explicitly checking changes to the "show" prop.
Based on react-native docs, looks like animations should be
started after mount. Updating animation states I'm not certain
on so I moved it to componentDidUpdate and tested with the
live streaming label to ensure the component still animated fine.
For the most part the changes are taking the "static propTypes" declaration off
of components and declaring them as Flow types. Sometimes to support flow some
method signatures had to be added. There are some exceptions in which more had
to be done to tame the beast:
- AbstractVideoTrack: put in additional truthy checks for videoTrack.
- Video: add truthy checks for the _videoElement ref.
- shouldRenderVideoTrack function: Some component could pass null for the
videoTrack argument and Flow wanted that called out explicitly.
- DisplayName: Add a truthy check for the input ref before acting on it.
- NumbersList: Move array checks inline for Flow to comprehend array methods
could be called. Add type checks in the Object.entries loop as the value is
assumed to be a mixed type by Flow.
- AbstractToolbarButton: add additional truthy check for passed in type.
- Change "features/chat" to support listening for new chat messages
and storing them, removing that logic from conference.js.
- Combine chat.scss and side_toolbar_container.css, and remove unused
scss files. Chat is the only side panel so the two concepts have
been merged.
- Remove direct access to the chat feature from non-react and non-redux
flows.
- Modify the i18n translate function to take in an options object.
By default the option "wait" is set to true, but that causes
components to mount after the parent has been notified of
an update, which means autoscrolling down to the latest rendered
messages does not work. With "wait" set to false, the children
will mount and then the parent will trigger componentDidUpdate.
- Create react components for chat. Chat is the side panel
plus the entiren chat feature. ChatInput is a child of Chat and
is used for composing messages. ChatMessage displays one message
and extends PureComponent to limit re-renders.
- Fix a bug where the toolbar was not showing automatically when
chat is closed and a new message is received.
- Import react-transition-group to time the animation of the
side panel showing/hiding and unmounting the Chat component.
This gets around the issue of having to control autofocus if the
component were always mounted and visibility toggled, but
introduces not being able to store previous scroll state
(without additional work or re-work).
There are (at least) two changes that are breaking:
- defaultTab is gone
- The re-rendering logic looks to have been re-written so that
passing in a new array of tabs causes a re-render, which can
reset the currently selected tab.
The fixes involved removing defaultTab from each tab configuration,
as it is no longer respected anyway. Also, instead of letting Tabs
be uncontrolled and allowing it to set its own selected, which
would result in the first tab automatically being selected on
Tabs re-render, use Tabs a controlled prop to dicate which
tab is selected; this is accomplished by specifying a selected
prop.
* feat(tile-view): initial implementation for mobile
- Create a tile view component for displaying thumbnails in a
two-dimensional grid.
- Update the existing TileViewButton so it shows a label in the
overflow menu.
- Modify conference so it can display TileView while hiding
Filmstrip.
- Modify Thumbnail so its width/height can be set and to prevent
pinning while in tile view mode.
* use style array for thumbnail styles
* change ternary to math.min for expressiveness
* use dimensiondetector
* pass explicit disableTint prop
* use makeAspectRatioAware instead of aspectRatio prop
* update docs
* fix docs again (fix laziest copy/paste job I've ever done)
* large-video: rename onPress prop to onClick
* change forEach to for...of
* use truthy check fallthrough logic instead of explicit if
* put tile view button second to last in menu
* move spacer to a constant
* the magical incantation to make flow shut up
Extracts methods which share the common logic. There are still some
leftovers on the web side left which are not used on RN. But this can be
a first step.
* Add joing button to the calendar events.
* Add space between calendar lines.
* Adjust recent list name.
* Fixes test failure.
* Restyle mobile recent list message.
* Add analytics events.
* Addressing PR review comments.
* Implements calendar entries edit.
Share text generation between calendar-sync and the share-room feature.
* Fixing comments.
* Clone the event element we modify on update.
If a relative BOSH URL is found (as docker-jitsi-meet does) construct a full URL
based on the location URL and context root.
Also remove some default options since we need the config file anyway, so I see
no point in doing the extra work.
* Refactor calendar-sync feature to be loaded on web.
For the web part it just adds new property to enable/disable calendar web integration, disabled by default.
* Initial implementation of retrieving google calendar events.
* Initial implementation of retrieving microsoft calendar events.
* Fixes comments.
* Rework to use the promise part of microsoft-graph-client api.
* Moves dispatching some actions, fixing comments.
* Makes sure we do not initializeClient google-api client multiple times.
* Do not try to login when fetching calendar entries.
The case where there is a calendar type google selected, but not logged in, trying to login on loading welcome page will show a warning that it tried to open a popup, which was denied by browser.
* Updates profile display data on sign in.
* Propagate google-api state to calendar-sync only if we use google cal.
* Adds sign out action.
* Clears the event listener when the popup closes.
* Clears calendarIntegrationInstance on signOut.
* WIP: UI for calendar settings, refactor auth flows
* Clean up some unused constants, functions and exports.
* break circular dependency of function and constant
* Exports only isCalendarEnabled from functions.
* Checks isSignedIn when doing fetchCalendarEntries on web.
* address comments
List microsoftApiApplicationClientID in undocument config.
remove unused SET_CALENDAR_TYPE action
use helper for calendar enabled in bootstrap
reorder actions
reorder imports
change order of signin -> set type -> update profile
add logging for signout error
reword setting dialog desc to avoid redundancy
add jsdoc to microsoft button props
reorder calendar constants
move default state to reducer (not reused anywhere)
update comment about calendar-sync due to removal of getCalendarState
update comment for getCalendarIntegration
remove vague comment
alpha order reducer, return default state on reset
alpha order persistence registry
remove unnecessary getType from apis
update comments in microsoftCalendar
alpha order google-api exports, use api.get in loadGoogleAPI
set jsdoc for google signin props
alpha order googleapi methods
fix calendartab docs
* Moves fetching calendar from APP_WILL_MOUNT to SET_CONFIG.
The web part needs configuration in order to refresh tokens (Microsoft).
* Fixes storing token expire time and refreshing tokens in Microsoft impl.
* Address comments
updateProfile changed to getCurrentEmail
rename result to results
stop storing integration in redux, store if ready for use
use existing helpers to parse redirect url
* update jsdocs, get google app id from redux
* clear integration instead of actual sign out
* feat(tile-view): initial implementation for tile view
- Modify the classname on the app root so layout can adjust
depending on the desired layout mode--vertical filmstrip,
horizontal filmstrip, and tile view.
- Create a button for toggling tile view.
- Add a StateListenerRegistry to automatically update the
selected participant and max receiver frame height on tile
view toggle.
- Rezise thumbnails when switching in and out of tile view.
- Move the local video when switching in and out of tile view.
- Update reactified pieces of thumbnails when switching in and
out of tile view.
- Cap the max receiver video quality in tile view based on tile
size.
- Use CSS to hide UI components that should not display in tile
view.
- Signal follow me changes.
* change local video id for tests
* change approach: leverage more css
* squash: fix some formatting
* squash: prevent pinning, hide pin border in tile view
* squash: change logic for maxReceiverQuality due to sidestepping resizing logic
* squash: fix typo, columns configurable, remove unused constants
* squash: resize with js again
* squash: use yana's math for calculating tile size
* feat: Displays the E2E RTT in the connection stats table.
* fix: Whitelists the ping config properties.
* ref: Addresses feedback.
* npm: Updates lib-jitsi-meet to e097a1189ed99838605d90b959e129155bc0e50a.
* ref: Moves the e2ertt and region to the existing stats object.
* feat(welcome-page): be able to open settings dialog
- Create a getter for getting a settings tab's props so the device
selection tab can get updated available devices.
- Be able to call a function from a tab after it has mounted. This is
used for device selection to essentially call enumerateDevices on
the welcome page so the device selectors are populated.
- Remove event UIEvents.AUDIO_OUTPUT_DEVICE_CHANGED. Instead directly call
setAudioOutputDeviceId where possible.
- Fix initialization of the audioOutputDeviceId in settings by defaulting
the audio output device to the one set in settings.
* squash: updateAvailableDevices -> getAvailableDevices, add comment for propsUpdateFunction
Use react-native-fastimage, which uses 2 full-native image impleentations using
well known and mature (native) libraries.
This gets us rid of 2 libraries which were observerd as a source of bugs and
created trouble with dependencies: react-native-fetch-blob and
react-native-img-cache. They are also no longer well maintained.
* [WEB] add UI for transcription
* add analytics event for button, do not use global APP object
* use props instead of state, use local conference to kick participant
* put imports in alphabetical order
* add translation for TranscribingLabel
* fix merge conflict
* add closed caption button
* purge OverFlowMenuItem which starts and stops Transcription
* readd closed caption icon and fix small issues due to purge
* delete unused icon in _font.scss
Move away from middleware and instead update video quality
when the selected video quality updates in redux. This also
lead to removing of automatically exiting audio only because
with the change it's not so readily possible to tell if the
user switched off audio only by re-selecting the already
preferred video quality. Removing this automagic removed
some additional checking done for mobile.
The internal max will be used for tile view. Whatever the
user has set for preferred video quality, the internal
maximum will be respected. This allows for the case where
the user prefers high definition video, but in tile view
it only makes sense to send low definition; ux wise the
user is allowed to continue messing with the video quality
slider.
- "preferred" is being appended because in tile view there is a
concept of what the user prefers to be the maximum video quality
but there is also a maximum respected internall. For example,
the user may prefer HD, but in tile view the tiles may be small
so internall the preferred would be set to LD.
- "receive" is being renamed to "receiver" to be consistent with
the naming in lib-jitsi-meet.
* ref(popover): allow for popover content from the right
Popovers contents can display to the left of the trigger
and above the trigger. Add the ability to display to the
right of the trigger my adding mouseover padding. This
may be needed for tile view, depending on where the triggers
are located.
* squash: abstract common css proprties into placeholder class
* Show subtitles when Jigasi sends transcription results in JSON
* fix: Import PropTypes from prop-types.
* apply feedback on initial PR
* Changed Object to Map, alphabetic ordering fixes ,css changes in transcription subtitles
* Sends Map of transcriptMessages as prop to Component
* Documentation fixes and uses config in redux state
* Minor doc fix
* rename feature 'transcription' to 'subtitles'
* Moves subtitles config to interfaceConfig and minor fixes
* minor lint fix
BaseApp does all the heavy-lifting related to creating the redux store,
navigation, and so on.
App currently handles URL props and actually triggering navigation based on
them.
Move it away from AbstractApp into an auxiliary function. In addition, introduce
a new `getServerURL` function which gets the configured server URL and defaults
to meet.jit.si as before.
Unfortunately, as the Jitsi Meet development evolved the routing mechanism
became more complex and thre logic ended up spread across multiple parts of the
codebase, which made it hard to follow and extend.
This change aims to fix that by rewriting the routing logic and centralizing it
in (pretty much) a single place, with no implicit inter-dependencies.
In order to arrive there, however, some extra changes were needed, which were
not caught early enough and are thus part of this change:
- JitsiMeetJS initialization is now synchronous: there is nothing async about
it, and the only async requirement (Temasys support) was lifted. See [0].
- WebRTC support can be detected early: building on top of the above, WebRTC
support can now be detected immediately, so take advantage of this to simplify
how we handle unsupported browsers. See [0].
The new router takes decissions based on the Redux state at the time of
invocation. A route can be represented by either a component or a URl reference,
with the latter taking precedence. On mobile, obviously, there is no concept of
URL reference so routing is based solely on components.
[0]: https://github.com/jitsi/lib-jitsi-meet/pull/779
* fix(connection): reload immediately on possible split-brain
There isn't an explicit way to know when a split brain
scenario has happened. It is assumed it arises when an
"item-not-found" connection error is encountered early
on in the conference. So, store when a connection has
happened so it be calculated how much time has
elapsed and if the threshold has not been exceeded
then do an immediate reload of the app instead of
showing the overlay with a reload timer.
* squash: rename isItemNotFoundError -> isShardChangedError
Up until now, mobile was oblivious to participants' presence state. Presence
state handling is required (probably, amongst other things) for "call flows".
So, let's add it! This is done by gathering the presence state when a
participant first joins, and handling subsequent changes.
* feat(settings): setting dialog
- Move device selection, profile edit, language select, moderator
options, and server auth into one modal with tabs.
- Remove side panel profile and settings and logic used to update
them.
- Pipe server auth status into redux to display in the settings
dialog.
- Change filmstrip only device selection popup to use the new
stateless settings dialog component.
* squash: do not show profile tab if not guest
* squash: profile button not clickable if no profile to show
* squash: nits
* ref: Settings dialog.
Emits CONFERENCE_FAILED in response to CONNECTION_FAILED event
which then triggers JitsiConference.leave() through the middleware
processing. Also base/conference state will be adjusted. It is to have
a consistent redux state in which both connection and conference are
failed. It could happen that in a buggy environment the XMPP connection
is dropped, but the media is still flowing which would result in weird
user experience.
Currently the listeners for disconnected and failed connection events
are unsubscribed as soon as the connection is established, so
the CONNECTION_DISCONNECTED is never triggered which would clear the
'connection' field. This commit will clear the 'connection' state on
CONNECTION_WILL_CONNECT. It's needed anyway given that there's no
guarantee on when and if the async disconnect operation will finish.
One issue caused by the 'connection' not cleared was that
CONNECTION_FAILED was not reduced correctly and the reload screen was
not displayed for the following scenario:
1. Join and leave any working conference.
2. Turn off network connectivity on the device.
3. Wait for CONNECTION_FAILED. The reload screen will not be displayed,
because CONNECTION_FAILED is not reduced correctly, because the old
'connection' value is still there.
* Adds an option to disable features based on token data.
Reverts changes from b84e910086, removes disableDesktopSharing option and an interface_config option.
* Disable recording button based on token features data.
Hide recording if local participant isGuest and roles based on token.
When enableUserRolesBasedOnToken is enabled we were not hiding the record button for guests.
* Adds filtering of jibri iqs and rayo based on features.
Moves feature checking in separate utility function.
Renames utility method.
* Adds a footer text when outbound-call is not feature enabled.
* Fixes comments.
Use it unless the connection is not ACTIVE. We don't really care if it's
recovering or whatever, if it's not active it has problems, so that's that.
This fixes a potential edge case in which the connection remains in RESTORING
state for some time.
* ref(toolbar): show recording features based on explicit configs
* squash: bring back button configs, use final config names
* squash: update interfaceConfig comment, remove unused config whitelist
* squash: change order of button enabled checks to reduce diff
* squash: fileRecording -> fileRecordings
Layout:
Use an absolute-fill view as the background with the sidebar on top of. This
greatly simplifies styling, as there is no need to calculate how large the
backdrop needs to be.
Animation:
Switch to a translateX transform animation. This serves 2 purposes: first,
there seems to be a bug somewhere in React Native 0.51-0.55 where the content
that is being animated starts to be clipped. Very weird! But more importantly,
translateX transmorm animations are supported by the native animation driver!
https://facebook.github.io/react-native/blog/2017/02/14/using-native-driver-for-animated.html8f5ebe5952/Libraries/Animated/src/NativeAnimatedHelper.js (L138-L176)
This makes the animation more performant and buttery smooth.
Some small cleanups are also included here.
Instead of keeping dominant speaker locally, get it from redux and be
updated when the dominant speaker changes. This is in an attempt to mimic
the video layout being reactified and connected to redux.
The visibility of the toolbar can be toggled by interacting with the main screen.
This change allows the toolbar to be configured to be 'always visible'. This voids
the 'toggle' functionality.
Simplify parts of the logic introduced in
11b7144ad0.
Specificaly, using all the state change avoiding functions doesn't give us much
since we need to copy the state for sure.
Makes sure that whenever a conference is left or switched, the local
participant's id will be equal to the default value.
The problem fixed by this commit is a situation where the local
participant may end up sharing the same ID with it's "ghost" when
rejoining a disconnected conference. The most important and easiest to
hit case is when the conference is left after the CONFERENCE_FAILED
event.
Another rare and harder to encounter in the real world issue is
where CONFERENCE_LEFT may come with the delay due to it's asynchronous
nature. The step by step scenario is as follows: trying to leave a
conference, but the network is not doing well, so it takes time,
requests are timing out. After getting back to the welcome page the
the CONFERENCE_LEFT has not arrived yet. The same conference is joined
again and the load config may timeout, but it will be read from the
cache. Now the network gets better and conference is joining which
results in our ghost participant added to the redux state. At this point
there's the root issue: two participants with the same id, because the
local one was neither cleared nor set to the new one yet
(PARTICIPANT_JOINED come, before CONFERENCE_JOINED where we adjust the
id). Then comes CONFERENCE_JOINED and we try to update our local id.
We're updating the ID of both ghost and local participant. It could be
also that the delayed CONFERENCE_LEFT comes for the old conference, but
it's too late and it would update the id for both participants.
The approach here reasons that the ID of the local participant
may be reset as soon as the local participant and, respectively, her ID
is no longer involved in a recoverable JitsiConference of interest to
the user and, consequently, the app.
Co-authored-by: Pawel Domas <pawel.domas@jitsi.org>
Co-authored-by: Lyubo Marinov <lmarinov@atlassian.com>
If the ID of a remote participant was the same as the ID of the local
participant (across multiple conferences), removing the remote
participant on PARTICIPANT_LEFT would remove the local participant.
Like the preceding commit "ref(base/conference): clear the 'conference'
field on WILL_LEAVE", this commit is part of the story how we are to
deal with conferences which take noticeable time to leave.
Like the preceding commit "ref(base/conference): clear the 'conference'
field on WILL_LEAVE", this commit is part of the story how we are to
deal with conferences which take noticeable time to leave.
If a leave is delayed and the leaving JitsiConference manages to sneak a
PARTICIPANT_JOINED in, it may create a remote participant who even
collides with the local participant.
With so many abstractions called conference, I'm not surprised I made a
mistake and my reviewer didn't catch it.
As we are transitioning from remote participants identified by ID alone
to an ID-conference pair, the subsequent commits "Protect against late
PARTICIPANT_JOINED" and "Refine PARTICIPANT_LEFT for ID collisions"
caught the error.
Pawel Domas said:
The conference state field is referring to the current conference in
progress, so it feels like this field should be cleared as soon as we
declare that the conference is being left and the asynchronous process
of leaving the conference starts (which happens on
CONFERENCE_WILL_LEAVE).
Lyubo Marinov said:
Merely setting conference to undefined is incomplete because there are
other redux state properties associated with conference.
What we're doing here is redefining the redux action
CONFERENCE_WILL_LEAVE:
The redux action CONFERENCE_WILL_LEAVE represents the order of the user
to leave a JitsiConference instance. From the user's perspective, there's
no going back (with respect to the instance itself). The app will perform
due clean-up like leaving the associated room, but the instance is no
longer the focus of the attention of the user and, consequently, the app.
Now CONFERENCE_LEFT and CONFERENCE_WILL_LEAVE have more in common than
before and we can do a much better job by expressing the common parts in
source code. Additionally, our source code can be rewritten to better
express the meaning of any of these two actions.
Co-authored-by: Pawel Domas <pawel.domas@jitsi.org>
Co-authored-by: Lyubo Marinov <lmarinov@atlassian.com>
Add ability to provide a display name in the configOverwrite object that
when available it will be used to customize the name of the meeting in
callkit screen and recent call list.
Co-authored-by: Daniel Ornelas <daniel.ob64@gmail.com>
Co-authored-by: Lyubo Marinov <lmarinov@atlassian.com>
This fix is based on storing the location URL object we are loading the
configuration for in the redux store. Once the config has been loaded (or it has
failed, for that matter!) we'll check if the current "config URL" is the same we
set, and discard the old one if they don't match.
The Jitsi Meet app always has at most 1 conference of primary interest.
It may have to juggle with 2 JitsiConference instances at the same time
if 1 is in the process of being left and one is joining/joined. But the
one which is joining or joined (which we call conference in the
features/base/conference redux state) is the one "of interest", the
other one is "clean up". Consequently, the remote participants of the
conference "of interest" are the remote participants "of interest" and
the others are "clean up". In order to reduce the time during which
there may be multiplying remote thumbnails, clean the remote
participants who are no longer "of interest" up.
As part of the work on fixing the problem with the multiplying
thumbnails, we've associated remote participant w/ JitsiConference.
However, there are periods of time when multiple JitsiConferences are in
the redux state (and that period is going to be shorted by
StateListenerRegistry). In order to give more control to the feature
base/participants, reduce the occurrences of direct access to the
features/base/participants redux state and utilize the feature's
existing read access functions. Which will allow us in the future to
enhance these functions to access participants which are relevant to the
current conference of interest to the user only.
The commit message of "Associate remote participant w/ JitsiConference
(_JOINED)" explains the motivation for this commit.
Practically, _JOINED and _LEFT combined with "Remove remote participants
who are no longer of interest" should alleviate the problem with
multiplying remote participants to an acceptable level of annoyance.
Technically though, a remote participant cannot be identified by an ID
only. The ID is (somewhat) "unique" in the context of a single
JitsiConference instance. So in order to not have to scratch our heads
over an obscure corner, racing case, it's better to always identify
remote participants by the pair id-conference. Unfortunately, that's a
bit of a high order given the existing source code. So I've implemented
the cases which are the easiest so that new source code written with
participantUpdated is more likely to identify a remote participant with
the pair id-conference.
Additionally, the commit "Reduce direct read access to the
features/base/participants redux state" brings more control back to the
functions of the feature base/participants so that one day we can (if we
choose to) do something like, for example:
If getParticipants is called with a conference, it returns the
participants from features/base/participants who are associated with the
specified conference. If no conference is specified in the function
call, then default to the conference which is the primary focus of the
app at the time of the function call. Added to the above, this should
allow us to further reduce the cases in which we're identifying remote
participants by id only and get us even closer to a more "predictable"
behavior in corner, racing cases.
The plan set in motion here is to associate remote participants with the
JitsiConference instances that created them in order to be able to
remove remote participants when a JitsiConference is no longer the
primary focus of the jitsi-meet app. And that's supposed to alleviate a
problem with multiplying remote thumbnails.
Doing all of the above in a single commit is a bit of a high order. So
I'm splitting the whole into multiple successive commits for the
purposes of observability, comprehension. Each commit is supposed to be
safe even if subsequent commits are not accepted, are reverted,
whatever. Obviously, without the successive commits, a commit may be
"unused".
One of the important pieces of the multiplying remote thumbnails "fix"
offered is removing remote participants who are no longer of interest
i.e. PARTICIPANT_LEFT. But in order for _LEFT to be implemented, _JOINED
must be implemented first.
Because a conference can fail before or after it's joined it must be
"left" in order to release any allocated resources like peerconnections,
tracks and all the other things.
Doing so in CONFERENCE_JOINED is too late because if we are moderators that
event will come first and we won't know what ID to match it with.
This is safe because our local ID is created early.
* feat(recording): frontend logic can support live streaming and recording
Instead of either live streaming or recording, now both can live together. The
changes to facilitate such include the following:
- Killing the state storing in Recording.js. Instead state is stored in the lib
and updated in redux for labels to display the necessary state updates.
- Creating a new container, Labels, for recording labels. Previously labels were
manually created and positioned. The container can create a reasonable number
of labels and only the container itself needs to be positioned with CSS. The
VideoQualityLabel has been shoved into the container as well because it moves
along with the recording labels.
- The action for updating recording state has been modified to enable updating
an array of recording sessions to support having multiple sessions.
- Confirmation dialogs for stopping and starting a file recording session have
been created, as they previously were jquery modals opened by Recording.js.
- Toolbox.web displays live streaming and recording buttons based on
configuration instead of recording availability.
- VideoQualityLabel and RecordingLabel have been simplified to remove any
positioning logic, as the Labels container handles such.
- Previous recording state update logic has been moved into the RecordingLabel
component. Each RecordingLabel is in charge of displaying state for a
recording session. The display UX has been left alone.
- Sipgw availability is no longer broadcast so remove logic depending on its
state. Some moving around of code was necessary to get around linting errors
about the existing code being too deeply nested (even though I didn't touch
it).
* work around lib-jitsi-meet circular dependency issues
* refactor labels to use html base
* pass in translation keys to video quality label
* add video quality classnames for torture tests
* break up, rearrange recorder session update listener
* add comment about disabling startup resize animation
* rename session to sessionData
* chore(deps): update to latest lib for recording changes
Contributing all buttons in one place goes against the designs that we
set out at the beginning of the project's rewrite and that multiple of
us have been following since then.
Knowledge is power, man!
The config.js cache predates the feature base/known-domains.
Technically, it's also able to recall more domains that the feature
recent-list can (because the latter limits its entries).
Make it more generic by accepting any content except of just rows with text and
icons.
In addition, rework its structure so the animation is smoother, by putting the
background overlay outside of the Modal. This way, the animation doesn't affect
the background, which won't slide down.
With this the RN component and the consumer app can share same CallKit
provider, configuration, and enable to be part of multiple listeners of
the CallKit flow events. The main driver of this is to enable the
consumer app to be able to report an incoming call to the OS before
loading the JitsiMeetView. Once the user answers the call, the app can
instantiate a JitsiMeetView, pass the CallKit call UUIID, and the Jitsi
Meet components will handle the connection and report back to CallKit
that the call has been established.
- Update font files to add new icon.
- Update markup and style so the icon has a small background
to fill in the text of the icon.
- Remove some css transitions that don't seem to do much.
In order to be able to add analytics to the deep-linking pages the
lib-jitsi-meet initialization has been moved so it happens earlier.
The introduced `initPromise` will eventually disappear, once conference is
migrated into React and / or support for Temasys is dropped. At that stage, it
can be turned into a sync function which all platforms share.
* Adds in memory log storage, to be used while testing.
Enabling it only when config.debug is set, a configuration provided by jitsi-meet-torture.
* Moves to using config.testing.testMode property for logs storage.
* Fixes comments.
Since the main conference container is no longer "clickable" there must
be a way for clicking on the "large video". A clickable TestHint nested
in ParticipantView makes it easier for dealing with the fact that the
click handler is not always on the same component (required for the
pinch and zoom feature to work correctly).
Allows to bind a click handler to a TestHint.
When a mobile test wants to click an UI element it must be able to
locate it through the accessibility layer. Now the problem with that is
that there is currently no uniform way for finding element on both iOS
and Android. This problem is solved by TestHint component which takes
an id parameter which then can be specified in the corresponding java
TestHint class in jitsi-meet-torture to easily find it. By being able to
add a click handler to a TestHint, it's possible to duplicate original
handler under nested TestHint and then find it easily on the torture
side.
Adds the logic to render TestHint only when the test mode is enabled
in order to be able to put independent TestHints in other places than
the TestConnectionInfo component.
It's too sensitive and most of the time I cannot perform an onPress. In
contrast, the builtin/default/standard onPress is noticeably more
forgiving. While we fix the sensitivity of "pinch to zoom", don't use
its onPress unless absolutely necessary i.e. use it only for desktop
streams.
Zoltan Bettenbuk suggested the following:
const state = getState();
if (desiredTypes.length === 0) {
- const { audio, video } = state['features/base/media'];
-
- audio.muted || desiredTypes.push(MEDIA_TYPE.AUDIO);
- video.muted || desiredTypes.push(MEDIA_TYPE.VIDEO);
+ const startAudioOnly = getPropertyValue(state, 'startAudioOnly');
+ const startWithAudioMuted
+ = getPropertyValue(state, 'startWithAudioMuted');
+ const startWithVideoMuted
+ = getPropertyValue(state, 'startWithVideoMuted');
+
+ if (!startWithAudioMuted) {
+ desiredTypes.push(MEDIA_TYPE.AUDIO);
+ }
+ if (!startAudioOnly && !startWithVideoMuted) {
+ desiredTypes.push(MEDIA_TYPE.VIDEO);
+ }
}
const availableTypes
The final commit is really a different implementation of the same idea
but takes into account that the state of base/media already contains the
intent of the URL and notices the delay in the realization of the
background app state.
Additionally, unbreaks one more case where setAudioOnly is incorrectly
dispatched on CONFERENCE_LEFT or CONFERENCE_FAILED and, consequently,
overrides the intent of the URL.
* feat(Deeplinking): Implement for web.
* ref(unsupported_browser): Move the mobile version to deeplinking feature
* feat(deeplinking_mobile): Redesign.
* fix(deeplinking): Use interface.NATIVE_APP_NAME.
* feat(dial_in_summary): Add the PIN to the number link.
* fix(deep_linking): Handle use case when there isn't deep linking image.
* fix(deep_linking): css
* fix(deep_linking): deeplink -> "deep linking"
* fix(deeplinking_css): Remove position: fixed
* docs(deeplinking): Add comment for the openWebApp action.
On Android the files will be copied to the assets/sounds directory of
the SDK bundle on build time. To play the "asset:/" prefix has to be
used to locate the files correctly.
On iOS each sound file must be added to the SDK's Xcode project in order
to be bundled correctly. To playback we need to know the path of the SDK
bundle which is now exposed by the AppInfo iOS module.
TouchableWithoutFeedback and TouchableHighlight interfere with the
implementation of 'pinch to zoom' to come. We prepare for it by driving
the onClick/onPress handler(s) out of Conference, through LargeVideo and
ParticipantView into Video itself where the bulk of 'pinch to zoom' will
be implemented.
In preparation for "pinch to zoom" support in desktop streams on mobile, make
certain Views not intervene in touch event handling. While the modification is
necessary for "pinch to zoom" which is coming later, it really makes sense for
the modified Views to not be involved in touching because they're used to aid
layout and/or animations and are to behave to the user as if they're not there.