mirror of https://github.com/jitsi/jitsi-meet
parent
c73ba37202
commit
c2cf09a2ca
@ -0,0 +1,176 @@ |
||||
// @flow
|
||||
|
||||
import { Component } from 'react'; |
||||
|
||||
import { connect } from '../../base/redux'; |
||||
import { getLocalizedDurationFormatter } from '../../base/i18n'; |
||||
import { getConferenceTimestamp } from '../../base/conference/functions'; |
||||
import { renderConferenceTimer } from '../'; |
||||
|
||||
/** |
||||
* The type of the React {@code Component} props of {@link ConferenceTimer}. |
||||
*/ |
||||
type Props = { |
||||
|
||||
/** |
||||
* The UTC timestamp representing the time when first participant joined. |
||||
*/ |
||||
_startTimestamp: ?number, |
||||
|
||||
/** |
||||
* The redux {@code dispatch} function. |
||||
*/ |
||||
dispatch: Function |
||||
}; |
||||
|
||||
/** |
||||
* The type of the React {@code Component} state of {@link ConferenceTimer}. |
||||
*/ |
||||
type State = { |
||||
|
||||
/** |
||||
* Value of current conference time. |
||||
*/ |
||||
timerValue: string |
||||
}; |
||||
|
||||
/** |
||||
* ConferenceTimer react component. |
||||
* |
||||
* @class ConferenceTimer |
||||
* @extends Component |
||||
*/ |
||||
class ConferenceTimer extends Component<Props, State> { |
||||
|
||||
/** |
||||
* Handle for setInterval timer. |
||||
*/ |
||||
_interval; |
||||
|
||||
/** |
||||
* Initializes a new {@code ConferenceTimer} instance. |
||||
* |
||||
* @param {Props} props - The read-only properties with which the new |
||||
* instance is to be initialized. |
||||
*/ |
||||
constructor(props: Props) { |
||||
super(props); |
||||
|
||||
this.state = { |
||||
timerValue: getLocalizedDurationFormatter(0) |
||||
}; |
||||
} |
||||
|
||||
/** |
||||
* Starts the conference timer when component will be |
||||
* mounted. |
||||
* |
||||
* @inheritdoc |
||||
*/ |
||||
componentDidMount() { |
||||
this._startTimer(); |
||||
} |
||||
|
||||
/** |
||||
* Stops the conference timer when component will be |
||||
* unmounted. |
||||
* |
||||
* @inheritdoc |
||||
*/ |
||||
componentWillUnmount() { |
||||
this._stopTimer(); |
||||
} |
||||
|
||||
/** |
||||
* Implements React's {@link Component#render()}. |
||||
* |
||||
* @inheritdoc |
||||
* @returns {ReactElement} |
||||
*/ |
||||
render() { |
||||
const { timerValue } = this.state; |
||||
const { _startTimestamp } = this.props; |
||||
|
||||
if (!_startTimestamp) { |
||||
return null; |
||||
} |
||||
|
||||
return renderConferenceTimer(timerValue); |
||||
} |
||||
|
||||
/** |
||||
* Sets the current state values that will be used to render the timer. |
||||
* |
||||
* @param {number} refValueUTC - The initial UTC timestamp value. |
||||
* @param {number} currentValueUTC - The current UTC timestamp value. |
||||
* |
||||
* @returns {void} |
||||
*/ |
||||
_setStateFromUTC(refValueUTC, currentValueUTC) { |
||||
|
||||
if (!refValueUTC || !currentValueUTC) { |
||||
return; |
||||
} |
||||
|
||||
if (currentValueUTC < refValueUTC) { |
||||
return; |
||||
} |
||||
|
||||
const timerMsValue = currentValueUTC - refValueUTC; |
||||
|
||||
const localizedTime = getLocalizedDurationFormatter(timerMsValue); |
||||
|
||||
this.setState({ |
||||
timerValue: localizedTime |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* Start conference timer. |
||||
* |
||||
* @returns {void} |
||||
*/ |
||||
_startTimer() { |
||||
if (!this._interval) { |
||||
this._setStateFromUTC(this.props._startTimestamp, (new Date()).getTime()); |
||||
|
||||
this._interval = setInterval(() => { |
||||
this._setStateFromUTC(this.props._startTimestamp, (new Date()).getTime()); |
||||
}, 1000); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Stop conference timer. |
||||
* |
||||
* @returns {void} |
||||
*/ |
||||
_stopTimer() { |
||||
if (this._interval) { |
||||
clearInterval(this._interval); |
||||
} |
||||
|
||||
this.setState({ |
||||
timerValue: getLocalizedDurationFormatter(0) |
||||
}); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Maps (parts of) the Redux state to the associated |
||||
* {@code ConferenceTimer}'s props. |
||||
* |
||||
* @param {Object} state - The Redux state. |
||||
* @private |
||||
* @returns {{ |
||||
* _startTimestamp: number |
||||
* }} |
||||
*/ |
||||
export function _mapStateToProps(state: Object) { |
||||
|
||||
return { |
||||
_startTimestamp: getConferenceTimestamp(state) |
||||
}; |
||||
} |
||||
|
||||
export default connect(_mapStateToProps)(ConferenceTimer); |
@ -0,0 +1,23 @@ |
||||
// @flow
|
||||
|
||||
import React from 'react'; |
||||
import { Text } from 'react-native'; |
||||
|
||||
import styles from './styles'; |
||||
|
||||
/** |
||||
* Returns native element to be rendered. |
||||
* |
||||
* @param {string} timerValue - String to display as time. |
||||
* |
||||
* @returns {ReactElement} |
||||
*/ |
||||
export default function renderConferenceTimer(timerValue: string) { |
||||
return ( |
||||
<Text |
||||
numberOfLines = { 4 } |
||||
style = { styles.roomTimer }> |
||||
{ timerValue } |
||||
</Text> |
||||
); |
||||
} |
@ -1,3 +1,4 @@ |
||||
// @flow
|
||||
|
||||
export { default as Conference } from './Conference'; |
||||
export { default as renderConferenceTimer } from './ConferenceTimerDisplay'; |
||||
|
@ -0,0 +1,16 @@ |
||||
// @flow
|
||||
|
||||
import React from 'react'; |
||||
|
||||
/** |
||||
* Returns web element to be rendered. |
||||
* |
||||
* @param {string} timerValue - String to display as time. |
||||
* |
||||
* @returns {ReactElement} |
||||
*/ |
||||
export default function renderConferenceTimer(timerValue: string) { |
||||
return ( |
||||
<span className = 'subject-conference-timer' >{ timerValue }</span> |
||||
); |
||||
} |
@ -1,3 +1,5 @@ |
||||
// @flow
|
||||
|
||||
export { default as Conference } from './Conference'; |
||||
export { default as renderConferenceTimer } from './ConferenceTimerDisplay'; |
||||
|
||||
|
@ -0,0 +1,5 @@ |
||||
local conference_duration_component |
||||
= module:get_option_string( |
||||
"conference_duration_component", "conference_duration"..module.host); |
||||
|
||||
module:add_identity("component", "conference_duration", conference_duration_component); |
@ -0,0 +1,66 @@ |
||||
local st = require "util.stanza"; |
||||
local socket = require "socket"; |
||||
local json = require "util.json"; |
||||
local ext_events = module:require "ext_events"; |
||||
local it = require "util.iterators"; |
||||
|
||||
-- we use async to detect Prosody 0.10 and earlier |
||||
local have_async = pcall(require, "util.async"); |
||||
if not have_async then |
||||
module:log("warn", "conference duration will not work with Prosody version 0.10 or less."); |
||||
return; |
||||
end |
||||
|
||||
local muc_component_host = module:get_option_string("muc_component"); |
||||
if muc_component_host == nil then |
||||
log("error", "No muc_component specified. No muc to operate on!"); |
||||
return; |
||||
end |
||||
|
||||
log("info", "Starting conference duration timer for %s", muc_component_host); |
||||
|
||||
function occupant_joined(event) |
||||
local room = event.room; |
||||
local occupant = event.occupant; |
||||
|
||||
local participant_count = it.count(room:each_occupant()); |
||||
|
||||
if participant_count > 1 then |
||||
|
||||
if room.created_timestamp == nil then |
||||
room.created_timestamp = os.time(os.date("!*t")) * 1000; -- Lua provides UTC time in seconds, so convert to milliseconds |
||||
end |
||||
|
||||
local body_json = {}; |
||||
body_json.type = 'conference_duration'; |
||||
body_json.created_timestamp = room.created_timestamp; |
||||
|
||||
local stanza = st.message({ |
||||
from = module.host; |
||||
to = occupant.jid; |
||||
}) |
||||
:tag("json-message", {xmlns='http://jitsi.org/jitmeet'}) |
||||
:text(json.encode(body_json)):up(); |
||||
|
||||
room:route_stanza(stanza); |
||||
end |
||||
end |
||||
|
||||
-- executed on every host added internally in prosody, including components |
||||
function process_host(host) |
||||
if host == muc_component_host then -- the conference muc component |
||||
module:log("info", "Hook to muc events on %s", host); |
||||
|
||||
local muc_module = module:context(host) |
||||
muc_module:hook("muc-occupant-joined", occupant_joined, -1); |
||||
end |
||||
end |
||||
|
||||
if prosody.hosts[muc_component_host] == nil then |
||||
module:log("info", "No muc component found, will listen for it: %s", muc_component_host); |
||||
|
||||
-- when a host or component is added |
||||
prosody.events.add_handler("host-activated", process_host); |
||||
else |
||||
process_host(muc_component_host); |
||||
end |
Loading…
Reference in new issue