Compare commits

..

1 Commits

Author SHA1 Message Date
Saúl Ibarra Corretgé
a56eb83346 rn: drop {AddPeople,Invite}Controller
We are going to implement the invite dialog *inside* the SDK, so there is no
need to have all this machinery anymore.
2019-02-07 11:48:24 +01:00
55 changed files with 437 additions and 1096 deletions

View File

@@ -113,6 +113,15 @@ allprojects {
}
}
task androidJavadocs(type: Javadoc) {
source = android.sourceSets.main.java.source
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
failOnError false
}
task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
classifier = 'javadoc'
from androidJavadocs.destinationDir
}
task androidSourcesJar(type: Jar) {
classifier = 'sources'
from android.sourceSets.main.java.source
@@ -128,6 +137,7 @@ allprojects {
extension "aar"
}
artifact(androidSourcesJar)
artifact(androidJavadocsJar)
pom.withXml {
def pomXml = asNode()
pomXml.appendNode('name', project.name)

View File

@@ -27,7 +27,6 @@ import android.support.v7.app.AppCompatActivity;
import android.view.KeyEvent;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.PermissionListener;
import java.net.URL;
@@ -53,11 +52,6 @@ public class JitsiMeetActivity
private static final int OVERLAY_PERMISSION_REQUEST_CODE
= (int) (Math.random() * Short.MAX_VALUE);
/**
* A color scheme object to override the default color is the SDK.
*/
private WritableMap colorScheme;
/**
* The default base {@code URL} used to join a conference when a partial URL
* (e.g. a room name only) is specified. The value is used only while
@@ -126,7 +120,6 @@ public class JitsiMeetActivity
// XXX Before calling JitsiMeetView#loadURL, make sure to call whatever
// is documented to need such an order in order to take effect:
view.setColorScheme(colorScheme);
view.setDefaultURL(defaultURL);
if (pictureInPictureEnabled != null) {
view.setPictureInPictureEnabled(
@@ -293,17 +286,6 @@ public class JitsiMeetActivity
ReactActivityLifecycleCallbacks.requestPermissions(this, permissions, requestCode, listener);
}
/**
* @see JitsiMeetView#setColorScheme(WritableMap)
*/
public void setColorScheme(WritableMap colorScheme) {
if (view == null) {
this.colorScheme = colorScheme;
} else {
view.setColorScheme(colorScheme);
}
}
/**
*
* @see JitsiMeetView#setDefaultURL(URL)

View File

@@ -22,9 +22,7 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap;
import java.lang.reflect.Method;
import java.net.URL;
@@ -71,11 +69,6 @@ public class JitsiMeetView
return loaded;
}
/**
* A color scheme object to override the default color is the SDK.
*/
private WritableMap colorScheme;
/**
* The default base {@code URL} used to join a conference when a partial URL
* (e.g. a room name only) is specified to {@link #loadURLString(String)} or
@@ -137,15 +130,6 @@ public class JitsiMeetView
}
}
/**
* Gets the color scheme used in the SDK.
*
* @return The color scheme map.
*/
public WritableMap getColorScheme() {
return colorScheme;
}
/**
* Gets the default base {@code URL} used to join a conference when a
* partial URL (e.g. a room name only) is specified to
@@ -224,11 +208,6 @@ public class JitsiMeetView
public void loadURLObject(@Nullable Bundle urlObject) {
Bundle props = new Bundle();
// color scheme
if (colorScheme != null) {
props.putBundle("colorScheme", Arguments.toBundle(colorScheme));
}
// defaultURL
if (defaultURL != null) {
props.putString("defaultURL", defaultURL.toString());
@@ -326,15 +305,6 @@ public class JitsiMeetView
onExternalAPIEvent(LISTENER_METHODS, name, data);
}
/**
* Sets the color scheme to override the default colors of the SDK.
*
* @param colorScheme The color scheme map.
*/
public void setColorScheme(WritableMap colorScheme) {
this.colorScheme = colorScheme;
}
/**
* Sets the default base {@code URL} used to join a conference when a
* partial URL (e.g. a room name only) is specified to

View File

@@ -146,7 +146,7 @@ var config = {
desktopSharingChromeExtId: null,
// Whether desktop sharing should be disabled on Chrome.
// desktopSharingChromeDisabled: false,
desktopSharingChromeDisabled: true,
// The media sources to use when using screen sharing with the Chrome
// extension.
@@ -156,7 +156,7 @@ var config = {
desktopSharingChromeMinExtVersion: '0.1',
// Whether desktop sharing should be disabled on Firefox.
// desktopSharingFirefoxDisabled: false,
desktopSharingFirefoxDisabled: false,
// Optional desktop sharing frame rate options. Default value: min:5, max:5.
// desktopSharingFrameRate: {

2
debian/control vendored
View File

@@ -21,7 +21,7 @@ Description: WebRTC JavaScript video conferences
Package: jitsi-meet-web-config
Architecture: all
Depends: openssl, openjdk-8-jre-headless | nginx | nginx-extras | apache2
Depends: openssl, openjdk-8-jre-headless | nginx | apache2
Description: Configuration for web serving of Jitsi Meet
Jitsi Meet is a WebRTC JavaScript application that uses Jitsi
Videobridge to provide high quality, scalable video conferences.

View File

@@ -52,11 +52,7 @@ case "$1" in
db_set jitsi-meet/jvb-hostname $JVB_HOSTNAME
NGINX_INSTALL_CHECK="$(dpkg-query -f '${Status}' -W 'nginx' 2>/dev/null | awk '{print $3}' || true)"
NGINX_EXTRAS_INSTALL_CHECK="$(dpkg-query -f '${Status}' -W 'nginx-extras' 2>/dev/null | awk '{print $3}' || true)"
if [ "$NGINX_INSTALL_CHECK" = "installed" ] \
|| [ "$NGINX_INSTALL_CHECK" = "unpacked" ] \
|| [ "$NGINX_EXTRAS_INSTALL_CHECK" = "installed" ] \
|| [ "$NGINX_EXTRAS_INSTALL_CHECK" = "unpacked" ] ; then
if [ "$NGINX_INSTALL_CHECK" = "installed" ] || [ "$NGINX_INSTALL_CHECK" = "unpacked" ] ; then
FORCE_NGINX="true"
fi
APACHE_INSTALL_CHECK="$(dpkg-query -f '${Status}' -W 'apache2' 2>/dev/null | awk '{print $3}' || true)"

View File

@@ -19,7 +19,6 @@
#import <React/RCTBridgeModule.h>
#import <React/RCTLog.h>
#import <WebRTC/WebRTC.h>
typedef enum {
kAudioModeDefault,
@@ -27,17 +26,16 @@ typedef enum {
kAudioModeVideoCall
} JitsiMeetAudioMode;
@interface AudioMode : NSObject<RCTBridgeModule, RTCAudioSessionDelegate>
@interface AudioMode : NSObject<RCTBridgeModule>
@property(nonatomic, strong) dispatch_queue_t workerQueue;
@end
@implementation AudioMode {
JitsiMeetAudioMode activeMode;
RTCAudioSessionConfiguration *defaultConfig;
RTCAudioSessionConfiguration *audioCallConfig;
RTCAudioSessionConfiguration *videoCallConfig;
NSString *_avCategory;
NSString *_avMode;
JitsiMeetAudioMode _mode;
}
RCT_EXPORT_MODULE();
@@ -57,32 +55,24 @@ RCT_EXPORT_MODULE();
- (instancetype)init {
self = [super init];
if (self) {
_avCategory = nil;
_avMode = nil;
_mode = kAudioModeDefault;
dispatch_queue_attr_t attributes =
dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL,
QOS_CLASS_USER_INITIATED, -1);
_workerQueue = dispatch_queue_create("AudioMode.queue", attributes);
activeMode = kAudioModeDefault;
defaultConfig = [[RTCAudioSessionConfiguration alloc] init];
defaultConfig.category = AVAudioSessionCategoryAmbient;
defaultConfig.categoryOptions = 0;
defaultConfig.mode = AVAudioSessionModeDefault;
audioCallConfig = [[RTCAudioSessionConfiguration alloc] init];
audioCallConfig.category = AVAudioSessionCategoryPlayAndRecord;
audioCallConfig.categoryOptions = AVAudioSessionCategoryOptionAllowBluetooth;
audioCallConfig.mode = AVAudioSessionModeVoiceChat;
videoCallConfig = [[RTCAudioSessionConfiguration alloc] init];
videoCallConfig.category = AVAudioSessionCategoryPlayAndRecord;
videoCallConfig.categoryOptions = AVAudioSessionCategoryOptionAllowBluetooth;
videoCallConfig.mode = AVAudioSessionModeVideoChat;
RTCAudioSession *session = [RTCAudioSession sharedInstance];
[session addDelegate:self];
// AVAudioSession is a singleton and other parts of the application such as
// WebRTC may undo the settings. Make sure that the settings are reapplied
// upon undoes.
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(routeChanged:)
name:AVAudioSessionRouteChangeNotification
object:nil];
}
return self;
}
@@ -91,74 +81,93 @@ RCT_EXPORT_MODULE();
return _workerQueue;
}
- (BOOL)setConfig:(RTCAudioSessionConfiguration *)config
error:(NSError * _Nullable *)outError {
- (void)routeChanged:(NSNotification*)notification {
NSInteger reason
= [[notification.userInfo
valueForKey:AVAudioSessionRouteChangeReasonKey]
integerValue];
RTCAudioSession *session = [RTCAudioSession sharedInstance];
[session lockForConfiguration];
BOOL success = [session setConfiguration:config error:outError];
[session unlockForConfiguration];
return success;
switch (reason) {
case AVAudioSessionRouteChangeReasonCategoryChange: {
// The category has changed. Check if it's the one we want and adjust as
// needed. This notification is posted on a secondary thread, so make
// sure we switch to our worker thread.
dispatch_async(_workerQueue, ^{
[self setCategory:self->_avCategory mode:self->_avMode error:nil];
});
break;
}
default:
// Do nothing.
break;
}
}
#pragma mark - Exported methods
- (BOOL)setCategory:(NSString *)category
mode:(NSString *)mode
error:(NSError * _Nullable *)outError {
AVAudioSession *session = [AVAudioSession sharedInstance];
// We don't want to touch the category when setting the default mode.
// This is to play well with other components which could be integrated
// into the final application.
if (_mode == kAudioModeDefault) {
return YES;
}
// Nothing to do.
if (category == nil && mode == nil) {
return YES;
}
if (session.category != category
&& ![session setCategory:category error:outError]) {
RCTLogError(@"Failed to (re)apply specified AVAudioSession category!");
return NO;
}
if (session.mode != mode && ![session setMode:mode error:outError]) {
RCTLogError(@"Failed to (re)apply specified AVAudioSession mode!");
return NO;
}
return YES;
}
RCT_EXPORT_METHOD(setMode:(int)mode
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject) {
RTCAudioSessionConfiguration *config;
NSString *avCategory = nil;
NSString *avMode = nil;
NSError *error;
switch (mode) {
case kAudioModeAudioCall:
config = audioCallConfig;
avCategory = AVAudioSessionCategoryPlayAndRecord;
avMode = AVAudioSessionModeVoiceChat;
break;
case kAudioModeDefault:
config = defaultConfig;
break;
case kAudioModeVideoCall:
config = videoCallConfig;
avCategory = AVAudioSessionCategoryPlayAndRecord;
avMode = AVAudioSessionModeVideoChat;
break;
default:
reject(@"setMode", @"Invalid mode", nil);
return;
}
activeMode = mode;
// Save the desired/specified category and mode so that they may be
// reapplied.
_avCategory = avCategory;
_avMode = avMode;
_mode = mode;
if ([self setConfig:config error:&error]) {
resolve(nil);
} else {
if (![self setCategory:avCategory mode:avMode error:&error] || error) {
reject(@"setMode", error.localizedDescription, error);
} else {
resolve(nil);
}
}
#pragma mark - RTCAudioSessionDelegate
- (void)audioSessionDidChangeRoute:(RTCAudioSession *)session
reason:(AVAudioSessionRouteChangeReason)reason
previousRoute:(AVAudioSessionRouteDescription *)previousRoute {
if (reason == AVAudioSessionRouteChangeReasonCategoryChange) {
// The category has changed. Check if it's the one we want and adjust as
// needed. This notification is posted on a secondary thread, so make
// sure we switch to our worker thread.
dispatch_async(_workerQueue, ^{
// We don't want to touch the category when in default mode.
// This is to play well with other components which could be integrated
// into the final application.
if (self->activeMode != kAudioModeDefault) {
NSLog(@"Audio route changed, reapplying RTCAudioSession config");
RTCAudioSessionConfiguration *config
= self->activeMode == kAudioModeAudioCall ? self->audioCallConfig : self->videoCallConfig;
[self setConfig:config error:nil];
}
});
}
}
- (void)audioSession:(RTCAudioSession *)audioSession didSetActive:(BOOL)active {
NSLog(@"[AudioMode] Audio session didSetActive:%d", active);
}
@end

View File

@@ -23,8 +23,6 @@
@property (class, copy, nonatomic, nullable) NSString *conferenceActivityType;
@property (nonatomic) NSDictionary *colorScheme;
@property (copy, nonatomic, nullable) NSURL *defaultURL;
@property (nonatomic, nullable, weak) id<JitsiMeetViewDelegate> delegate;

View File

@@ -231,7 +231,6 @@ static NSMapTable<NSString *, JitsiMeetView *> *views;
props[@"defaultURL"] = [self.defaultURL absoluteString];
}
props[@"colorScheme"] = self.colorScheme;
props[@"externalAPIScope"] = externalAPIScope;
props[@"pictureInPictureEnabled"] = @(self.pictureInPictureEnabled);
props[@"welcomePageEnabled"] = @(self.welcomePageEnabled);

View File

@@ -25,10 +25,6 @@
RCT_EXPORT_MODULE();
- (dispatch_queue_t)methodQueue {
return dispatch_get_main_queue();
}
/**
* Enables / disables the proximity sensor monitoring. On iOS enabling the
* proximity sensor automatically dims the screen and disables touch controls,

View File

@@ -1,6 +1,5 @@
/*
* Copyright @ 2019-present 8x8, Inc.
* Copyright @ 2018-2019 Atlassian Pty Ltd
* Copyright @ 2018-present Atlassian Pty Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -54,7 +53,6 @@ import Foundation
didSet {
if enabled == false {
provider.setDelegate(nil, queue: nil)
provider.invalidate()
}
}
}
@@ -62,8 +60,6 @@ import Foundation
@objc public static func configureProvider(localizedName: String,
ringtoneSound: String?,
iconTemplateImageData: Data?) {
guard enabled else { return }
let configuration = CXProviderConfiguration(localizedName: localizedName)
configuration.iconTemplateImageData = iconTemplateImageData
configuration.maximumCallGroups = 1
@@ -191,4 +187,3 @@ import Foundation
return update
}
}

View File

@@ -1,6 +1,5 @@
{
"en": "English",
"af": "Afrikaans",
"az": "Azerbaijani",
"bg": "Bulgarian",
"cs": "Czech",

43
package-lock.json generated
View File

@@ -2487,7 +2487,7 @@
"blueimp-md5": "^2.10.0",
"json3": "^3.3.2",
"lodash": "^4.17.4",
"ua-parser-js": "github:amplitude/ua-parser-js#ed538f1"
"ua-parser-js": "github:amplitude/ua-parser-js#ed538f16f5c6ecd8357da989b617d4f156dcf35d"
},
"dependencies": {
"ua-parser-js": {
@@ -6229,8 +6229,7 @@
},
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
"optional": true
"bundled": true
},
"aproba": {
"version": "1.2.0",
@@ -6248,13 +6247,11 @@
},
"balanced-match": {
"version": "1.0.0",
"bundled": true,
"optional": true
"bundled": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -6267,18 +6264,15 @@
},
"code-point-at": {
"version": "1.1.0",
"bundled": true,
"optional": true
"bundled": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
"optional": true
"bundled": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
"optional": true
"bundled": true
},
"core-util-is": {
"version": "1.0.2",
@@ -6381,8 +6375,7 @@
},
"inherits": {
"version": "2.0.3",
"bundled": true,
"optional": true
"bundled": true
},
"ini": {
"version": "1.3.5",
@@ -6392,7 +6385,6 @@
"is-fullwidth-code-point": {
"version": "1.0.0",
"bundled": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -6405,20 +6397,17 @@
"minimatch": {
"version": "3.0.4",
"bundled": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "0.0.8",
"bundled": true,
"optional": true
"bundled": true
},
"minipass": {
"version": "2.2.4",
"bundled": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.1",
"yallist": "^3.0.0"
@@ -6435,7 +6424,6 @@
"mkdirp": {
"version": "0.5.1",
"bundled": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -6508,8 +6496,7 @@
},
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
"optional": true
"bundled": true
},
"object-assign": {
"version": "4.1.1",
@@ -6519,7 +6506,6 @@
"once": {
"version": "1.4.0",
"bundled": true,
"optional": true,
"requires": {
"wrappy": "1"
}
@@ -6595,8 +6581,7 @@
},
"safe-buffer": {
"version": "5.1.1",
"bundled": true,
"optional": true
"bundled": true
},
"safer-buffer": {
"version": "2.1.2",
@@ -6626,7 +6611,6 @@
"string-width": {
"version": "1.0.2",
"bundled": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -6644,7 +6628,6 @@
"strip-ansi": {
"version": "3.0.1",
"bundled": true,
"optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -6683,13 +6666,11 @@
},
"wrappy": {
"version": "1.0.2",
"bundled": true,
"optional": true
"bundled": true
},
"yallist": {
"version": "3.0.2",
"bundled": true,
"optional": true
"bundled": true
}
}
},

View File

@@ -5,7 +5,6 @@ import { Linking } from 'react-native';
import '../../analytics';
import '../../authentication';
import { setColorScheme } from '../../base/color-scheme';
import { DialogContainer } from '../../base/dialog';
import '../../base/jwt';
import { Platform } from '../../base/react';
@@ -36,11 +35,6 @@ const logger = require('jitsi-meet-logger').getLogger(__filename);
*/
type Props = AbstractAppProps & {
/**
* An object of colors that override the default colors of the app/sdk.
*/
colorScheme: Object,
/**
* Whether Picture-in-Picture is enabled. If {@code true}, a toolbar button
* is rendered in the {@link Conference} view to afford entering
@@ -62,8 +56,6 @@ type Props = AbstractAppProps & {
* @extends AbstractApp
*/
export class App extends AbstractApp {
_init: Promise<*>;
/**
* Initializes a new {@code App} instance.
*
@@ -94,12 +86,6 @@ export class App extends AbstractApp {
componentDidMount() {
super.componentDidMount();
this._init.then(() => {
// We set the color scheme early enough so then we avoid any
// unnecessary re-renders.
this.state.store.dispatch(setColorScheme(this.props.colorScheme));
});
Linking.addEventListener('url', this._onLinkingURL);
}

View File

@@ -9,12 +9,10 @@ import {
CustomSubmitDialog,
FIELD_UNDERLINE,
PLACEHOLDER_COLOR,
_abstractMapStateToProps,
inputDialog as inputDialogStyle
} from '../../base/dialog';
import { translate } from '../../base/i18n';
import { JitsiConnectionErrors } from '../../base/lib-jitsi-meet';
import { StyleType } from '../../base/styles';
import { authenticateAndUpgradeRole, cancelLogin } from '../actions';
import styles from './styles';
@@ -40,11 +38,6 @@ type Props = {
*/
_connecting: boolean,
/**
* The color-schemed stylesheet of the base/dialog feature.
*/
_dialogStyles: StyleType,
/**
* The error which occurred during login/authentication.
*/
@@ -141,7 +134,6 @@ class LoginDialog extends Component<Props, State> {
render() {
const {
_connecting: connecting,
_dialogStyles,
_error: error,
_progress: progress,
t
@@ -194,7 +186,7 @@ class LoginDialog extends Component<Props, State> {
onChangeText = { this._onUsernameChange }
placeholder = { 'user@domain.com' }
placeholderTextColor = { PLACEHOLDER_COLOR }
style = { _dialogStyles.field }
style = { inputDialogStyle.field }
underlineColorAndroid = { FIELD_UNDERLINE }
value = { this.state.username } />
<TextInput
@@ -203,7 +195,7 @@ class LoginDialog extends Component<Props, State> {
placeholderTextColor = { PLACEHOLDER_COLOR }
secureTextEntry = { true }
style = { [
_dialogStyles.field,
inputDialogStyle.field,
inputDialogStyle.bottomField
] }
underlineColorAndroid = { FIELD_UNDERLINE }
@@ -297,7 +289,6 @@ class LoginDialog extends Component<Props, State> {
* _conference: JitsiConference,
* _configHosts: Object,
* _connecting: boolean,
* _dialogStyles: StyleType,
* _error: Object,
* _progress: number
* }}
@@ -316,7 +307,6 @@ function _mapStateToProps(state) {
} = state['features/base/connection'];
return {
..._abstractMapStateToProps(state),
_conference: authRequired,
_configHosts: configHosts,
_connecting: Boolean(connecting) || Boolean(thenableWithCancel),

View File

@@ -1,160 +0,0 @@
// @flow
import { toState } from '../redux';
import { StyleType } from '../styles';
import defaultScheme from './defaultScheme';
/**
* A registry class to register styles that need to be color-schemed.
*
* This class uses lazy initialization for scheme-ified style definitions on
* request.
*/
class ColorSchemeRegistry {
/**
* A map of already scheme-ified style definitions.
*/
_schemedStyles = new Map();
/**
* A map of registered style templates.
*/
_styleTemplates = new Map();
/**
* Clears the already scheme-ified style definitions. This is useful when
* the {@code SET_COLOR_SCHEME} action is dispatched (again).
*
* @returns {void}
*/
clear() {
this._schemedStyles.clear();
}
/**
* Retreives the color-scheme applied style definition of a component.
*
* @param {Object | Function} stateful - An object or function that can be
* resolved to Redux state using the {@code toState} function.
* @param {string} componentName - The name of the component whose style we
* want to retreive.
* @returns {StyleType}
*/
get(stateful: Object | Function, componentName: string): StyleType {
let schemedStyle = this._schemedStyles.get(componentName);
if (!schemedStyle) {
schemedStyle
= this._applyColorScheme(
stateful,
componentName,
this._styleTemplates.get(componentName));
this._schemedStyles.set(componentName, schemedStyle);
}
return schemedStyle;
}
/**
* Registers a style definition to the registry for color-scheming.
*
* NOTE: It's suggested to only use this registry on styles where color
* scheming is needed, otherwise just use a static style object as before.
*
* @param {string} componentName - The name of the component to register the
* style to (e.g. {@code 'Toolbox'}).
* @param {StyleType} style - The style definition to register.
* @returns {void}
*/
register(componentName: string, style: StyleType): void {
this._styleTemplates.set(componentName, style);
// If this is a style overwrite, we need to delete the processed version
// of the style from the other map
this._schemedStyles.delete(componentName);
}
/**
* Creates a color schemed style object applying the color scheme to every
* colors in the style object prepared in a special way.
*
* @param {Object | Function} stateful - An object or function that can be
* resolved to Redux state using the {@code toState} function.
* @param {string} componentName - The name of the component to apply the
* color scheme to.
* @param {StyleType} style - The style definition to apply the color scheme
* to.
* @returns {StyleType}
*/
_applyColorScheme(
stateful: Object | Function,
componentName: string,
style: StyleType): StyleType {
let schemedStyle;
if (Array.isArray(style)) {
// The style is an array of styles, we apply the same transformation
// to each, recursively.
schemedStyle = [];
for (const entry of style) {
schemedStyle.push(this._applyColorScheme(
stateful, componentName, entry));
}
} else {
// The style is an object, we create a copy of it to avoid in-place
// modification.
schemedStyle = {
...style
};
for (const [
styleName,
styleValue
] of Object.entries(schemedStyle)) {
if (typeof styleValue === 'object') {
// The value is another style object, we apply the same
// transformation recusively.
schemedStyle[styleName]
= this._applyColorScheme(
stateful, componentName, styleValue);
} else if (typeof styleValue === 'function') {
// The value is a function, which indicates that it's a
// dynamic, schemed color we need to resolve.
schemedStyle[styleName]
= this._getColor(stateful, componentName, styleValue());
}
}
}
return schemedStyle;
}
/**
* Function to get the color value for the provided identifier.
*
* @param {Object | Function} stateful - An object or function that can be
* resolved to Redux state using the {@code toState} function.
* @param {string} componentName - The name of the component to get the
* color value for.
* @param {string} colorDefinition - The string identifier of the color,
* e.g. {@code appBackground}.
* @returns {string}
*/
_getColor(
stateful: Object | Function,
componentName: string,
colorDefinition: string): string {
const colorScheme = toState(stateful)['features/base/color-scheme'];
return {
...defaultScheme[componentName],
...colorScheme[componentName]
}[colorDefinition];
}
}
export default new ColorSchemeRegistry();

View File

@@ -1,11 +0,0 @@
// @flow
/**
* Redux action to signal a color scheme change in the app/sdk.
*
* {
* type: SET_COLOR_SCHEME
* colorScheme: Object
* }
*/
export const SET_COLOR_SCHEME = Symbol('SET_COLOR_SCHEME');

View File

@@ -1,19 +0,0 @@
// @flow
import { SET_COLOR_SCHEME } from './actionTypes';
/**
* Dispatches a Redux action to set the color scheme of the app/sdk.
*
* @param {Object} colorScheme - The color scheme to set.
* @returns {{
* type: SET_COLOR_SCHEME,
* colorScheme: Object
* }}
*/
export function setColorScheme(colorScheme: Object): Object {
return {
type: SET_COLOR_SCHEME,
colorScheme
};
}

View File

@@ -1,35 +0,0 @@
// @flow
import { ColorPalette, getRGBAFormat } from '../styles';
/**
* The default color scheme of the application.
*/
export default {
'BottomSheet': {
background: ColorPalette.blackBlue,
icon: ColorPalette.white,
label: ColorPalette.white
},
'Dialog': {
background: ColorPalette.blackBlue,
border: getRGBAFormat(ColorPalette.white, 0.2),
icon: ColorPalette.white,
text: ColorPalette.white
},
'LargeVideo': {
background: ColorPalette.black
},
'Thumbnail': {
activeParticipantHighlight: ColorPalette.blue,
activeParticipantTint: ColorPalette.black,
background: ColorPalette.black
},
'Toolbox': {
button: getRGBAFormat(ColorPalette.white, 0.7),
buttonToggled: getRGBAFormat(ColorPalette.buttonUnderlay, 0.7),
buttonToggledBorder:
getRGBAFormat(ColorPalette.buttonUnderlay, 0.7),
hangup: ColorPalette.red
}
};

View File

@@ -1,13 +0,0 @@
// @flow
/**
* A special function to be used in the {@code createColorSchemedStyle} call,
* that denotes that the color is a dynamic color.
*
* @param {string} colorDefinition - The definition of the color to mark to be
* resolved.
* @returns {Function}
*/
export function schemeColor(colorDefinition: string): Function {
return () => colorDefinition;
}

View File

@@ -1,8 +0,0 @@
// @flow
export * from './actions';
export * from './actionTypes';
export * from './functions';
export { default as ColorSchemeRegistry } from './ColorSchemeRegistry';
import './reducer';

View File

@@ -1,20 +0,0 @@
// @flow
import { MiddlewareRegistry } from '../redux';
import { SET_COLOR_SCHEME } from './actionTypes';
import ColorSchemeRegistry from './ColorSchemeRegistry';
/**
* The middleware of the feature {@code base/color-scheme}.
*
* @returns {Function}
*/
MiddlewareRegistry.register((/* store */) => next => action => {
switch (action.type) {
case SET_COLOR_SCHEME:
return ColorSchemeRegistry.clear();
}
return next(action);
});

View File

@@ -1,21 +0,0 @@
// @flow
import _ from 'lodash';
import { ReducerRegistry } from '../redux';
import { SET_COLOR_SCHEME } from './actionTypes';
/**
* The reducer of the feature {@code base/color-scheme}.
*
* @returns {Function}
*/
ReducerRegistry.register('features/base/color-scheme', (state = {}, action) => {
switch (action.type) {
case SET_COLOR_SCHEME:
return _.cloneDeep(action.colorScheme) || state;
}
return state;
});

View File

@@ -8,7 +8,6 @@ import {
} from 'react-native';
import { Icon } from '../../../font-icons';
import { StyleType } from '../../../styles';
import AbstractDialog, {
type Props as AbstractProps,
@@ -19,11 +18,6 @@ import { brandedDialog as styles } from './styles';
export type Props = {
...AbstractProps,
/**
* The color-schemed stylesheet of the feature.
*/
_dialogStyles: StyleType,
t: Function
}
@@ -49,7 +43,7 @@ class BaseDialog<P: Props, S: State> extends AbstractDialog<P, S> {
* @returns {ReactElement}
*/
render() {
const { _dialogStyles, style } = this.props;
const { style } = this.props;
return (
<View
@@ -61,7 +55,7 @@ class BaseDialog<P: Props, S: State> extends AbstractDialog<P, S> {
<View
pointerEvents = 'box-none'
style = { [
_dialogStyles.dialog,
styles.dialog,
this.props.style
] }>
<TouchableOpacity
@@ -69,7 +63,7 @@ class BaseDialog<P: Props, S: State> extends AbstractDialog<P, S> {
style = { styles.closeWrapper }>
<Icon
name = 'close'
style = { _dialogStyles.closeStyle } />
style = { styles.closeStyle } />
</TouchableOpacity>
{ this._renderContent() }
</View>

View File

@@ -3,8 +3,6 @@
import React from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
import { StyleType } from '../../../styles';
import BaseDialog, { type Props as BaseProps } from './BaseDialog';
import {
brandedDialog
@@ -13,11 +11,6 @@ import {
type Props = {
...BaseProps,
/**
* The color-schemed stylesheet of the feature.
*/
_dialogStyles: StyleType,
t: Function
}
@@ -53,7 +46,7 @@ class BaseSubmitDialog<P: Props, S: *> extends BaseDialog<P, S> {
* @inheritdoc
*/
_renderContent() {
const { _dialogStyles, t } = this.props;
const { t } = this.props;
const additionalButtons = this._renderAdditionalButtons();
return (
@@ -72,7 +65,7 @@ class BaseSubmitDialog<P: Props, S: *> extends BaseDialog<P, S> {
? null : brandedDialog.buttonFarLeft,
brandedDialog.buttonFarRight
] }>
<Text style = { _dialogStyles.text }>
<Text style = { brandedDialog.text }>
{ t(this._getSubmitButtonKey()) }
</Text>
</TouchableOpacity>

View File

@@ -2,11 +2,8 @@
import React, { Component, type Node } from 'react';
import { TouchableWithoutFeedback, View } from 'react-native';
import { connect } from 'react-redux';
import { ColorSchemeRegistry } from '../../../color-scheme';
import { Modal } from '../../../react';
import { StyleType } from '../../../styles';
import { bottomSheetStyles as styles } from './styles';
@@ -15,11 +12,6 @@ import { bottomSheetStyles as styles } from './styles';
*/
type Props = {
/**
* The color-schemed stylesheet of the feature.
*/
_styles: StyleType,
/**
* The children to be displayed within this component.
*/
@@ -36,7 +28,7 @@ type Props = {
* A component emulating Android's BottomSheet. For all intents and purposes,
* this component has been designed to work and behave as a {@code Dialog}.
*/
class BottomSheet extends Component<Props> {
export default class BottomSheet extends Component<Props> {
/**
* Initializes a new {@code BottomSheet} instance.
*
@@ -55,8 +47,6 @@ class BottomSheet extends Component<Props> {
* @returns {ReactElement}
*/
render() {
const { _styles } = this.props;
return [
<View
key = 'overlay'
@@ -70,7 +60,7 @@ class BottomSheet extends Component<Props> {
onPress = { this._onCancel } >
<View style = { styles.backdrop } />
</TouchableWithoutFeedback>
<View style = { _styles.sheet }>
<View style = { styles.sheet }>
{ this.props.children }
</View>
</View>
@@ -92,19 +82,3 @@ class BottomSheet extends Component<Props> {
onCancel && onCancel();
}
}
/**
* Maps part of the Redux state to the props of this component.
*
* @param {Object} state - The Redux state.
* @returns {{
* _styles: StyleType
* }}
*/
function _mapStateToProps(state) {
return {
_styles: ColorSchemeRegistry.get(state, 'BottomSheet')
};
}
export default connect(_mapStateToProps)(BottomSheet);

View File

@@ -5,9 +5,6 @@ import { Text, TouchableOpacity } from 'react-native';
import { connect } from 'react-redux';
import { translate } from '../../../i18n';
import { StyleType } from '../../../styles';
import { _abstractMapStateToProps } from '../../functions';
import { type Props as BaseProps } from './BaseDialog';
import BaseSubmitDialog from './BaseSubmitDialog';
@@ -16,11 +13,6 @@ import { brandedDialog } from './styles';
type Props = {
...BaseProps,
/**
* The color-schemed stylesheet of the feature.
*/
_dialogStyles: StyleType,
/**
* Untranslated i18n key of the content to be displayed.
*
@@ -57,7 +49,7 @@ class ConfirmDialog extends BaseSubmitDialog<Props, *> {
* @inheritdoc
*/
_renderAdditionalButtons() {
const { _dialogStyles, t } = this.props;
const { t } = this.props;
return (
<TouchableOpacity
@@ -65,9 +57,9 @@ class ConfirmDialog extends BaseSubmitDialog<Props, *> {
style = { [
brandedDialog.button,
brandedDialog.buttonFarLeft,
_dialogStyles.buttonSeparator
brandedDialog.buttonSeparator
] }>
<Text style = { _dialogStyles.text }>
<Text style = { brandedDialog.text }>
{ t('dialog.confirmNo') }
</Text>
</TouchableOpacity>
@@ -80,14 +72,14 @@ class ConfirmDialog extends BaseSubmitDialog<Props, *> {
* @inheritdoc
*/
_renderSubmittable() {
const { _dialogStyles, contentKey, t } = this.props;
const { contentKey, t } = this.props;
const content
= typeof contentKey === 'string'
? t(contentKey)
: this._renderHTML(t(contentKey.key, contentKey.params));
return (
<Text style = { _dialogStyles.text }>
<Text style = { brandedDialog.text }>
{ content }
</Text>
);
@@ -96,4 +88,4 @@ class ConfirmDialog extends BaseSubmitDialog<Props, *> {
_renderHTML: string => Object | string
}
export default translate(connect(_abstractMapStateToProps)(ConfirmDialog));
export default translate(connect()(ConfirmDialog));

View File

@@ -2,8 +2,6 @@
import { connect } from 'react-redux';
import { _abstractMapStateToProps } from '../../functions';
import BaseDialog, { type Props } from './BaseDialog';
/**
@@ -21,4 +19,4 @@ class CustomDialog extends BaseDialog<Props, *> {
}
}
export default connect(_abstractMapStateToProps)(CustomDialog);
export default connect()(CustomDialog);

View File

@@ -4,8 +4,6 @@ import { connect } from 'react-redux';
import { translate } from '../../../i18n';
import { _abstractMapStateToProps } from '../../functions';
import { type Props as BaseProps } from './BaseDialog';
import BaseSubmitDialog from './BaseSubmitDialog';
@@ -29,5 +27,4 @@ class CustomSubmitDialog extends BaseSubmitDialog<Props, *> {
}
}
export default translate(
connect(_abstractMapStateToProps)(CustomSubmitDialog));
export default translate(connect()(CustomSubmitDialog));

View File

@@ -5,9 +5,6 @@ import { View, Text, TextInput, TouchableOpacity } from 'react-native';
import { connect } from 'react-redux';
import { translate } from '../../../i18n';
import { StyleType } from '../../../styles';
import { _abstractMapStateToProps } from '../../functions';
import { type State as AbstractState } from '../AbstractDialog';
@@ -21,11 +18,6 @@ import {
type Props = {
...BaseProps,
/**
* The color-schemed stylesheet of the feature.
*/
_dialogStyles: StyleType,
/**
* The untranslated i18n key for the field label on the dialog.
*/
@@ -71,7 +63,7 @@ class InputDialog extends BaseDialog<Props, State> {
* @inheritdoc
*/
_renderContent() {
const { _dialogStyles, okDisabled, t } = this.props;
const { okDisabled, t } = this.props;
return (
<View>
@@ -80,12 +72,12 @@ class InputDialog extends BaseDialog<Props, State> {
brandedDialog.mainWrapper,
styles.fieldWrapper
] }>
<Text style = { _dialogStyles.fieldLabel }>
<Text style = { styles.fieldLabel }>
{ t(this.props.contentKey) }
</Text>
<TextInput
onChangeText = { this._onChangeText }
style = { _dialogStyles.field }
style = { styles.field }
underlineColorAndroid = { FIELD_UNDERLINE }
value = { this.state.fieldValue }
{ ...this.props.textInputProps } />
@@ -99,7 +91,7 @@ class InputDialog extends BaseDialog<Props, State> {
brandedDialog.buttonFarLeft,
brandedDialog.buttonFarRight
] }>
<Text style = { _dialogStyles.text }>
<Text style = { brandedDialog.text }>
{ t('dialog.Ok') }
</Text>
</TouchableOpacity>
@@ -138,4 +130,4 @@ class InputDialog extends BaseDialog<Props, State> {
}
}
export default translate(connect(_abstractMapStateToProps)(InputDialog));
export default translate(connect()(InputDialog));

View File

@@ -2,12 +2,12 @@
import { StyleSheet } from 'react-native';
import { ColorSchemeRegistry, schemeColor } from '../../../color-scheme';
import { BoxModel, ColorPalette, createStyleSheet } from '../../../styles';
import { PREFERRED_DIALOG_SIZE } from '../../constants';
const BORDER_RADIUS = 5;
const DIALOG_BORDER_COLOR = 'rgba(255, 255, 255, 0.2)';
export const FIELD_UNDERLINE = ColorPalette.transparent;
@@ -22,6 +22,47 @@ export const MD_ITEM_MARGIN_PADDING = 16;
export const PLACEHOLDER_COLOR = ColorPalette.lightGrey;
/**
* Default styles for the items of a {@code BottomSheet}-based menu.
*
* These have been implemented as per the Material Design guidelines:
* {@link https://material.io/guidelines/components/bottom-sheets.html}.
*/
const bottomSheetItemStyles = createStyleSheet({
/**
* Container style for a generic item rendered in the menu.
*/
style: {
alignItems: 'center',
flexDirection: 'row',
height: MD_ITEM_HEIGHT
},
/**
* Style for the {@code Icon} element in a generic item of the menu.
*/
iconStyle: {
color: ColorPalette.white,
fontSize: 24
},
/**
* Style for the label in a generic item rendered in the menu.
*/
labelStyle: {
color: ColorPalette.white,
flexShrink: 1,
fontSize: MD_FONT_SIZE,
marginLeft: 32,
opacity: 0.90
}
});
export const bottomSheetItemStylesCombined = {
...bottomSheetItemStyles,
underlayColor: ColorPalette.overflowMenuItemUnderlay
};
/**
* The React {@code Component} styles of {@code BottomSheet}. These have
* been implemented as per the Material Design guidelines:
@@ -53,6 +94,16 @@ export const bottomSheetStyles = createStyleSheet({
overlay: {
...StyleSheet.absoluteFillObject,
backgroundColor: 'rgba(127, 127, 127, 0.6)'
},
/**
* Bottom sheet's base style.
*/
sheet: {
backgroundColor: 'rgb(0, 3, 6)',
flex: 1,
paddingHorizontal: MD_ITEM_MARGIN_PADDING,
paddingVertical: 8
}
});
@@ -80,17 +131,38 @@ export const brandedDialog = createStyleSheet({
borderBottomRightRadius: BORDER_RADIUS
},
buttonSeparator: {
borderRightColor: DIALOG_BORDER_COLOR,
borderRightWidth: 1
},
buttonWrapper: {
alignItems: 'stretch',
borderRadius: BORDER_RADIUS,
flexDirection: 'row'
},
closeStyle: {
color: ColorPalette.white,
fontSize: MD_FONT_SIZE
},
closeWrapper: {
alignSelf: 'flex-end',
padding: BoxModel.padding
},
dialog: {
alignItems: 'stretch',
backgroundColor: 'rgb(0, 3, 6)',
borderColor: DIALOG_BORDER_COLOR,
borderRadius: BORDER_RADIUS,
borderWidth: 1,
flex: 1,
flexDirection: 'column',
maxWidth: PREFERRED_DIALOG_SIZE
},
mainWrapper: {
alignSelf: 'stretch',
padding: BoxModel.padding * 2,
@@ -107,135 +179,56 @@ export const brandedDialog = createStyleSheet({
flexDirection: 'row',
justifyContent: 'center',
padding: 30
},
text: {
color: ColorPalette.white,
fontSize: MD_FONT_SIZE,
textAlign: 'center'
}
});
/**
* Reusable (colored) style for text in any branded dialogs.
* The React {@code Component} styles of {@code Dialog}.
*/
const brandedDialogText = {
color: schemeColor('text'),
fontSize: MD_FONT_SIZE,
textAlign: 'center'
};
export const dialog = createStyleSheet({
/**
* The style of the {@code Text} in a {@code Dialog} button.
*/
buttonText: {
color: ColorPalette.blue
},
/**
* The style of the {@code Text} in a {@code Dialog} button which is
* disabled.
*/
disabledButtonText: {
color: ColorPalette.darkGrey
}
});
export const inputDialog = createStyleSheet({
bottomField: {
marginBottom: 0
},
field: {
...brandedDialog.text,
borderBottomWidth: 1,
borderColor: DIALOG_BORDER_COLOR,
margin: BoxModel.margin,
textAlign: 'left'
},
fieldLabel: {
...brandedDialog.text,
margin: BoxModel.margin,
textAlign: 'left'
},
fieldWrapper: {
...brandedDialog.mainWrapper,
paddingBottom: BoxModel.padding * 2
}
});
/**
* Default styles for the items of a {@code BottomSheet}-based menu.
*
* These have been implemented as per the Material Design guidelines:
* {@link https://material.io/guidelines/components/bottom-sheets.html}.
*/
ColorSchemeRegistry.register('BottomSheet', {
/**
* Style for the {@code Icon} element in a generic item of the menu.
*/
iconStyle: {
color: schemeColor('icon'),
fontSize: 24
},
/**
* Style for the label in a generic item rendered in the menu.
*/
labelStyle: {
color: schemeColor('label'),
flexShrink: 1,
fontSize: MD_FONT_SIZE,
marginLeft: 32,
opacity: 0.90
},
/**
* Bottom sheet's base style.
*/
sheet: {
backgroundColor: schemeColor('background'),
flex: 1,
paddingHorizontal: MD_ITEM_MARGIN_PADDING,
paddingVertical: 8
},
/**
* Container style for a generic item rendered in the menu.
*/
style: {
alignItems: 'center',
flexDirection: 'row',
height: MD_ITEM_HEIGHT
},
/**
* Additional style that is not directly used as a style object.
*/
underlayColor: ColorPalette.overflowMenuItemUnderlay
});
/**
* Color schemed styles for all the component based on the abstract dialog.
*/
ColorSchemeRegistry.register('Dialog', {
/**
* Separator line for the buttons in a dialog.
*/
buttonSeparator: {
borderRightColor: schemeColor('border'),
borderRightWidth: 1
},
/**
* Style of the close icon on a dialog.
*/
closeStyle: {
color: schemeColor('icon'),
fontSize: MD_FONT_SIZE
},
/**
* Base style of the dialogs.
*/
dialog: {
alignItems: 'stretch',
backgroundColor: schemeColor('background'),
borderColor: schemeColor('border'),
borderRadius: BORDER_RADIUS,
borderWidth: 1,
flex: 1,
flexDirection: 'column',
maxWidth: PREFERRED_DIALOG_SIZE
},
/**
* Field on an input dialog.
*/
field: {
...brandedDialogText,
borderBottomWidth: 1,
borderColor: schemeColor('border'),
margin: BoxModel.margin,
textAlign: 'left'
},
/**
* Style for the field label on an input dialog.
*/
fieldLabel: {
...brandedDialogText,
margin: BoxModel.margin,
textAlign: 'left'
},
text: {
...brandedDialogText
}
});

View File

@@ -1,6 +1,5 @@
/* @flow */
import { ColorSchemeRegistry } from '../color-scheme';
import { toState } from '../redux';
/**
@@ -16,17 +15,3 @@ import { toState } from '../redux';
export function isDialogOpen(stateful: Function | Object, component: Object) {
return toState(stateful)['features/base/dialog'].component === component;
}
/**
* Maps part of the Redux state to the props of any Dialog based component.
*
* @param {Object} state - The Redux state.
* @returns {{
* _dialogStyles: StyleType
* }}
*/
export function _abstractMapStateToProps(state: Object): Object {
return {
_dialogStyles: ColorSchemeRegistry.get(state, 'Dialog')
};
}

View File

@@ -12,7 +12,6 @@ import {
VideoTrack
} from '../../media';
import { Container, TintedView } from '../../react';
import { StyleType } from '../../styles';
import { TestHint } from '../../testing/components';
import { getTrackByMediaTypeAndParticipant } from '../../tracks';
@@ -98,11 +97,6 @@ type Props = {
*/
tintEnabled: boolean,
/**
* The style of the tinting when applied.
*/
tintStyle: StyleType,
/**
* The test hint id which can be used to locate the {@code ParticipantView}
* on the jitsi-meet-torture side. If not provided, the
@@ -192,12 +186,11 @@ class ParticipantView extends Component<Props> {
*/
render() {
const {
onPress,
_avatar: avatar,
_connectionStatus: connectionStatus,
_renderVideo: renderVideo,
_videoTrack: videoTrack,
onPress,
tintStyle
_videoTrack: videoTrack
} = this.props;
const waitForVideoStarted = false;
@@ -206,10 +199,9 @@ class ParticipantView extends Component<Props> {
const renderAvatar = Boolean(!renderVideo && avatar);
// If the connection has problems, we will "tint" the video / avatar.
const connectionProblem
= connectionStatus !== JitsiParticipantConnectionStatus.ACTIVE;
const useTint
= connectionProblem || this.props.tintEnabled;
= connectionStatus !== JitsiParticipantConnectionStatus.ACTIVE
|| this.props.tintEnabled;
const testHintId
= this.props.testHintId
@@ -246,9 +238,7 @@ class ParticipantView extends Component<Props> {
{ useTint
// If the connection has problems, tint the video / avatar.
&& <TintedView
style = {
connectionProblem ? undefined : tintStyle } /> }
&& <TintedView /> }
{ this.props.useConnectivityInfoLabel
&& this._renderConnectionInfo(connectionStatus) }

View File

@@ -3,7 +3,7 @@
import React, { Component } from 'react';
import { StyleSheet, View } from 'react-native';
import { TINTED_VIEW_DEFAULT } from './styles';
import { ColorPalette } from '../../../styles';
/**
* Base style for the {@code TintedView} component.
@@ -24,6 +24,16 @@ type Props = {
*/
children?: React$Node,
/**
* Color used as the background of the view. Defaults to
*/
color: string,
/**
* Opacity for the
*/
opacity: number,
/**
* Style to override the base style.
*/
@@ -35,6 +45,15 @@ type Props = {
* the given color and opacity.
*/
export default class TintedView extends Component<Props> {
/**
* Default values for the component's props.
*/
static defaultProps = {
color: ColorPalette.appBackground,
opacity: 0.8,
style: {}
};
/**
* Implements React's {@link Component#render()}.
*
@@ -42,7 +61,7 @@ export default class TintedView extends Component<Props> {
* @returns {ReactElement}
*/
render() {
const { children, style } = this.props;
const { children, color, opacity, style } = this.props;
// XXX Don't tint the children, tint the background only.
return (
@@ -53,8 +72,11 @@ export default class TintedView extends Component<Props> {
pointerEvents = 'none'
style = { [
BASE_STYLE,
TINTED_VIEW_DEFAULT,
style
style,
{
backgroundColor: color,
opacity
}
] } />
<View
pointerEvents = 'box-none'

View File

@@ -324,11 +324,6 @@ const SIDEBAR_STYLES = {
}
};
export const TINTED_VIEW_DEFAULT = {
backgroundColor: ColorPalette.appBackground,
opacity: 0.8
};
/**
* The styles of the generic React {@code Component}s implemented by the feature
* base/react.

View File

@@ -18,7 +18,6 @@ export const ColorPalette = {
* the sake of consistency.
*/
black: BLACK,
blackBlue: 'rgb(0, 3, 6)',
blue: '#17A0DB',
blueHighlight: '#1081b2',
buttonUnderlay: '#495258',
@@ -28,7 +27,7 @@ export const ColorPalette = {
overflowMenuItemUnderlay: '#EEEEEE',
red: '#D00000',
transparent: 'rgba(0, 0, 0, 0)',
white: '#FFFFFF',
white: 'white',
/**
* These are colors from the atlaskit to be used on mobile, when needed.

View File

@@ -6,23 +6,6 @@ import { ColorPalette } from './components';
declare type StyleSheet = Object;
export type StyleType = StyleSheet | Array<StyleSheet>;
/**
* RegExp pattern for long HEX color format.
*/
const HEX_LONG_COLOR_FORMAT
= /^#([0-9A-F]{2,2})([0-9A-F]{2,2})([0-9A-F]{2,2})$/i;
/**
* RegExp pattern for short HEX color format.
*/
const HEX_SHORT_COLOR_FORMAT
= /^#([0-9A-F]{1,1})([0-9A-F]{1,1})([0-9A-F]{1,1})$/i;
/**
* RegExp pattern for RGB color format.
*/
const RGB_COLOR_FORMAT = /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/i;
/**
* The list of the well-known style properties which may not be numbers on Web
* but must be numbers on React Native.
@@ -104,49 +87,6 @@ export function fixAndroidViewClipping<T: StyleSheet>(styles: T): T {
return styles;
}
/**
* Returns an rgba format of the provided color if it's in hex or rgb format.
*
* NOTE: The function will return the same color if it's not in one of those
* two formats (e.g. 'white').
*
* @param {string} color - The string representation of the color in rgb or hex
* format.
* @param {number} alpha - The alpha value to apply.
* @returns {string}
*/
export function getRGBAFormat(color: string, alpha: number): string {
let match = color.match(HEX_LONG_COLOR_FORMAT);
if (match) {
return `#${match[1]}${match[2]}${match[3]}${_getAlphaInHex(alpha)}`;
}
match = color.match(HEX_SHORT_COLOR_FORMAT);
if (match) {
return `#${match[1]}${match[1]}${match[2]}${match[2]}${match[3]}${
match[3]}${_getAlphaInHex(alpha)}`;
}
match = color.match(RGB_COLOR_FORMAT);
if (match) {
return `rgba(${match[1]}, ${match[2]}, ${match[3]}, ${alpha})`;
}
return color;
}
/**
* Converts an [0..1] alpha value into HEX.
*
* @param {number} alpha - The alpha value to convert.
* @returns {string}
*/
function _getAlphaInHex(alpha: number): string {
return Number(Math.round(255 * alpha)).toString(16)
.padStart(2, '0');
}
/**
* Shims style properties to work correctly on native. Allows us to minimize the
* number of style declarations that need to be set or overridden for specific

View File

@@ -3,7 +3,6 @@
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { ColorSchemeRegistry } from '../../../base/color-scheme';
import { openDialog } from '../../../base/dialog';
import { Audio, MEDIA_TYPE } from '../../../base/media';
import {
@@ -13,7 +12,6 @@ import {
pinParticipant
} from '../../../base/participants';
import { Container } from '../../../base/react';
import { StyleType } from '../../../base/styles';
import { getTrackByMediaTypeAndParticipant } from '../../../base/tracks';
import { RemoteVideoMenu } from '../../../remote-video-menu';
@@ -55,11 +53,6 @@ type Props = {
*/
_onShowRemoteVideoMenu: ?Function,
/**
* The color-schemed stylesheet of the feature.
*/
_styles: StyleType,
/**
* The Redux representation of the participant's video track.
*/
@@ -113,7 +106,6 @@ class Thumbnail extends Component<Props> {
_largeVideo: largeVideo,
_onClick,
_onShowRemoteVideoMenu,
_styles,
_videoTrack: videoTrack,
disablePin,
disableTint,
@@ -143,7 +135,7 @@ class Thumbnail extends Component<Props> {
style = { [
styles.thumbnail,
participant.pinned && !disablePin
? _styles.thumbnailPinned : null,
? styles.thumbnailPinned : null,
this.props.styleOverrides || null
] }
touchFeedback = { false }>
@@ -156,9 +148,7 @@ class Thumbnail extends Component<Props> {
<ParticipantView
avatarSize = { AVATAR_SIZE }
participantId = { participantId }
style = { _styles.participantViewStyle }
tintEnabled = { participantInLargeVideo && !disableTint }
tintStyle = { _styles.activeThumbnailTint }
zOrder = { 1 } />
{ participant.role === PARTICIPANT_ROLE.MODERATOR
@@ -229,7 +219,6 @@ function _mapDispatchToProps(dispatch: Function, ownProps): Object {
* _audioTrack: Track,
* _isModerator: boolean,
* _largeVideo: Object,
* _styles: StyleType,
* _videoTrack: Track
* }}
*/
@@ -249,7 +238,6 @@ function _mapStateToProps(state, ownProps) {
_audioTrack: audioTrack,
_isModerator: isLocalParticipantModerator(state),
_largeVideo: largeVideo,
_styles: ColorSchemeRegistry.get(state, 'Thumbnail'),
_videoTrack: videoTrack
};
}

View File

@@ -1,6 +1,3 @@
// @flow
import { ColorSchemeRegistry, schemeColor } from '../../base/color-scheme';
import { ColorPalette } from '../../base/styles';
import { FILMSTRIP_SIZE } from '../constants';
@@ -137,6 +134,19 @@ export default {
position: 'absolute'
},
/**
* Pinned video thumbnail style.
*/
thumbnailPinned: {
borderColor: ColorPalette.blue,
shadowColor: ColorPalette.black,
shadowOffset: {
height: 5,
width: 5
},
shadowRadius: 5
},
tileView: {
alignSelf: 'center'
},
@@ -150,36 +160,3 @@ export default {
justifyContent: 'center'
}
};
/**
* Color schemed styles for the @{code Thumbnail} component.
*/
ColorSchemeRegistry.register('Thumbnail', {
/**
* Tinting style of the on-stage participant thumbnail.
*/
activeThumbnailTint: {
backgroundColor: schemeColor('activeParticipantTint')
},
/**
* Coloring if the thumbnail background.
*/
participantViewStyle: {
backgroundColor: schemeColor('background')
},
/**
* Pinned video thumbnail style.
*/
thumbnailPinned: {
borderColor: schemeColor('activeParticipantHighlight'),
shadowColor: schemeColor('activeParticipantHighlight'),
shadowOffset: {
height: 5,
width: 5
},
shadowRadius: 5
}
});

View File

@@ -274,19 +274,17 @@ export function invitePeopleAndChatRooms( // eslint-disable-line max-params
return Promise.resolve();
}
return fetch(
`${inviteServiceUrl}?token=${jwt}`,
{
body: JSON.stringify({
'invited': inviteItems,
'url': inviteUrl
}),
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
}
);
return new Promise((resolve, reject) => {
$.post(
`${inviteServiceUrl}?token=${jwt}`,
JSON.stringify({
'invited': inviteItems,
'url': inviteUrl
}),
resolve,
'json')
.fail((jqxhr, textStatus, error) => reject(error));
});
}
/**

View File

@@ -3,34 +3,27 @@
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { ColorSchemeRegistry } from '../../base/color-scheme';
import { ParticipantView } from '../../base/participants';
import { DimensionsDetector } from '../../base/responsive-ui';
import { StyleType } from '../../base/styles';
import { AVATAR_SIZE } from './styles';
import styles, { AVATAR_SIZE } from './styles';
/**
* The type of the React {@link Component} props of {@link LargeVideo}.
*/
type Props = {
/**
* Callback to invoke when the {@code LargeVideo} is clicked/pressed.
*/
onClick: Function,
/**
* The ID of the participant (to be) depicted by LargeVideo.
*
* @private
*/
_participantId: string,
/**
* The color-schemed stylesheet of the feature.
*/
_styles: StyleType,
/**
* Callback to invoke when the {@code LargeVideo} is clicked/pressed.
*/
onClick: Function,
_participantId: string
};
/**
@@ -121,7 +114,6 @@ class LargeVideo extends Component<Props, State> {
} = this.state;
const {
_participantId,
_styles,
onClick
} = this.props;
@@ -132,7 +124,7 @@ class LargeVideo extends Component<Props, State> {
avatarSize = { avatarSize }
onPress = { onClick }
participantId = { _participantId }
style = { _styles.largeVideo }
style = { styles.largeVideo }
testHintId = 'org.jitsi.meet.LargeVideo'
useConnectivityInfoLabel = { useConnectivityInfoLabel }
zOrder = { 0 }
@@ -148,14 +140,12 @@ class LargeVideo extends Component<Props, State> {
* @param {Object} state - Redux state.
* @private
* @returns {{
* _participantId: string,
* _styles: StyleType
* _participantId: string
* }}
*/
function _mapStateToProps(state) {
return {
_participantId: state['features/large-video'].participantId,
_styles: ColorSchemeRegistry.get(state, 'LargeVideo')
_participantId: state['features/large-video'].participantId
};
}

View File

@@ -1,16 +1,13 @@
import { StyleSheet } from 'react-native';
import { ColorSchemeRegistry, schemeColor } from '../../base/color-scheme';
import { ColorPalette, createStyleSheet } from '../../base/styles';
/**
* Size for the Avatar.
*/
export const AVATAR_SIZE = 200;
/**
* Color schemed styles for the @{LargeVideo} component.
*/
ColorSchemeRegistry.register('LargeVideo', {
export default createStyleSheet({
/**
* Large video container style.
@@ -18,7 +15,7 @@ ColorSchemeRegistry.register('LargeVideo', {
largeVideo: {
...StyleSheet.absoluteFillObject,
alignItems: 'stretch',
backgroundColor: schemeColor('background'),
backgroundColor: ColorPalette.appBackground,
flex: 1,
justifyContent: 'center'
}

View File

@@ -7,8 +7,7 @@ import {
CONFERENCE_FAILED,
CONFERENCE_LEFT,
CONFERENCE_JOINED,
SET_AUDIO_ONLY,
getCurrentConference
SET_AUDIO_ONLY
} from '../../base/conference';
import { MiddlewareRegistry } from '../../base/redux';
@@ -32,15 +31,9 @@ MiddlewareRegistry.register(({ getState }) => next => action => {
switch (action.type) {
case APP_WILL_MOUNT:
case CONFERENCE_FAILED:
case CONFERENCE_LEFT: {
const conference = getCurrentConference(getState());
if (typeof conference === 'undefined') {
mode = AudioMode.DEFAULT;
}
case CONFERENCE_LEFT:
mode = AudioMode.DEFAULT;
break;
}
/*
* NOTE: We moved the audio mode setting from CONFERENCE_WILL_JOIN to

View File

@@ -52,8 +52,7 @@ type State = {
*
* @extends Component
*/
export default class AbstractStreamKeyForm<P: Props>
extends Component<P, State> {
export default class AbstractStreamKeyForm extends Component<Props, State> {
helpURL: string;
_debouncedUpdateValidationErrorVisibility: Function;
@@ -62,7 +61,7 @@ export default class AbstractStreamKeyForm<P: Props>
*
* @inheritdoc
*/
constructor(props: P) {
constructor(props: Props) {
super(props);
this.state = {
@@ -89,7 +88,7 @@ export default class AbstractStreamKeyForm<P: Props>
*
* @inheritdoc
*/
componentDidUpdate(prevProps: P) {
componentDidUpdate(prevProps: Props) {
if (this.props.value !== prevProps.value) {
this._debouncedUpdateValidationErrorVisibility();
}

View File

@@ -4,9 +4,7 @@ import React, { Component } from 'react';
import { Text, View } from 'react-native';
import { connect } from 'react-redux';
import { _abstractMapStateToProps } from '../../../../base/dialog';
import { translate } from '../../../../base/i18n';
import { StyleType } from '../../../../base/styles';
import {
GOOGLE_API_STATES,
@@ -25,11 +23,6 @@ const logger = require('jitsi-meet-logger').getLogger(__filename);
*/
type Props = {
/**
* Style of the dialogs feature.
*/
_dialogStyles: StyleType,
/**
* The Redux dispatch Function.
*/
@@ -109,7 +102,7 @@ class GoogleSigninForm extends Component<Props> {
* @inheritdoc
*/
render() {
const { _dialogStyles, t } = this.props;
const { t } = this.props;
const { googleAPIState, googleResponse } = this.props;
const signedInUser = googleResponse
&& googleResponse.user
@@ -128,11 +121,7 @@ class GoogleSigninForm extends Component<Props> {
return (
<View style = { styles.formWrapper }>
<View style = { styles.helpText }>
<Text
style = { [
_dialogStyles.text,
styles.text
] }>
<Text style = { styles.text }>
{ userInfo }
</Text>
</View>
@@ -236,7 +225,6 @@ function _mapStateToProps(state: Object) {
const { googleAPIState, googleResponse } = state['features/google-api'];
return {
..._abstractMapStateToProps(state),
googleAPIState,
googleResponse
};

View File

@@ -2,24 +2,13 @@
import React from 'react';
import { Linking, Text, TextInput, TouchableOpacity, View } from 'react-native';
import { connect } from 'react-redux';
import { _abstractMapStateToProps } from '../../../../base/dialog';
import { translate } from '../../../../base/i18n';
import { StyleType } from '../../../../base/styles';
import AbstractStreamKeyForm, {
type Props as AbstractProps
type Props
} from '../AbstractStreamKeyForm';
type Props = AbstractProps & {
/**
* Style of the dialogs feature.
*/
_dialogStyles: StyleType
};
import styles, { PLACEHOLDER_COLOR } from './styles';
/**
@@ -27,7 +16,7 @@ import styles, { PLACEHOLDER_COLOR } from './styles';
*
* @extends Component
*/
class StreamKeyForm extends AbstractStreamKeyForm<Props> {
class StreamKeyForm extends AbstractStreamKeyForm {
/**
* Initializes a new {@code StreamKeyForm} instance.
*
@@ -48,16 +37,11 @@ class StreamKeyForm extends AbstractStreamKeyForm<Props> {
* @returns {ReactElement}
*/
render() {
const { _dialogStyles, t } = this.props;
const { t } = this.props;
return (
<View style = { styles.formWrapper }>
<Text
style = { [
_dialogStyles.text,
styles.text,
styles.streamKeyInputLabel
] }>
<Text style = { styles.streamKeyInputLabel }>
{
t('dialog.streamKey')
}
@@ -72,11 +56,7 @@ class StreamKeyForm extends AbstractStreamKeyForm<Props> {
{
this.state.showValidationError
? <View style = { styles.formFooterItem }>
<Text
style = { [
_dialogStyles.text,
styles.warningText
] }>
<Text style = { styles.warningText }>
{ t('liveStreaming.invalidStreamKey') }
</Text>
</View>
@@ -86,11 +66,7 @@ class StreamKeyForm extends AbstractStreamKeyForm<Props> {
<TouchableOpacity
onPress = { this._onOpenHelp }
style = { styles.streamKeyHelp } >
<Text
style = { [
_dialogStyles.text,
styles.text
] }>
<Text style = { styles.text }>
{
t('liveStreaming.streamIdHelp')
}
@@ -122,4 +98,4 @@ class StreamKeyForm extends AbstractStreamKeyForm<Props> {
}
}
export default translate(connect(_abstractMapStateToProps)(StreamKeyForm));
export default translate(StreamKeyForm);

View File

@@ -8,11 +8,8 @@ import {
TouchableOpacity,
View
} from 'react-native';
import { connect } from 'react-redux';
import { _abstractMapStateToProps } from '../../../../base/dialog';
import { translate } from '../../../../base/i18n';
import { StyleType } from '../../../../base/styles';
import { YOUTUBE_LIVE_DASHBOARD_URL } from '../constants';
@@ -20,11 +17,6 @@ import styles, { ACTIVE_OPACITY, TOUCHABLE_UNDERLAY } from './styles';
type Props = {
/**
* Style of the dialogs feature.
*/
_dialogStyles: StyleType,
/**
* The list of broadcasts the user can pick from.
*/
@@ -82,7 +74,7 @@ class StreamKeyPicker extends Component<Props, State> {
* @inheritdoc
*/
render() {
const { _dialogStyles, broadcasts } = this.props;
const { broadcasts } = this.props;
if (!broadcasts) {
return null;
@@ -93,11 +85,7 @@ class StreamKeyPicker extends Component<Props, State> {
<View style = { styles.formWrapper }>
<TouchableOpacity
onPress = { this._onOpenYoutubeDashboard }>
<Text
style = { [
_dialogStyles.text,
styles.warningText
] }>
<Text style = { styles.warningText }>
{ this.props.t(
'liveStreaming.getStreamKeyManually') }
</Text>
@@ -109,11 +97,7 @@ class StreamKeyPicker extends Component<Props, State> {
return (
<View style = { styles.formWrapper }>
<View style = { styles.streamKeyPickerCta }>
<Text
style = { [
_dialogStyles.text,
styles.text
] }>
<Text style = { styles.text }>
{ this.props.t('liveStreaming.choose') }
</Text>
</View>
@@ -129,11 +113,7 @@ class StreamKeyPicker extends Component<Props, State> {
? styles.streamKeyPickerItemHighlight : null
] }
underlayColor = { TOUCHABLE_UNDERLAY }>
<Text
style = { [
_dialogStyles.text,
styles.text
] }>
<Text style = { styles.text }>
{ broadcast.title }
</Text>
</TouchableHighlight>))
@@ -175,5 +155,4 @@ class StreamKeyPicker extends Component<Props, State> {
}
}
export default translate(
connect(_abstractMapStateToProps)(StreamKeyPicker));
export default translate(StreamKeyPicker);

View File

@@ -99,7 +99,8 @@ export default createStyleSheet({
* Label for the previous field.
*/
streamKeyInputLabel: {
alignSelf: 'flex-start'
alignSelf: 'flex-start',
color: ColorPalette.white
},
/**
@@ -145,8 +146,7 @@ export default createStyleSheet({
},
text: {
fontSize: 14,
textAlign: 'left'
color: ColorPalette.white
},
/**

View File

@@ -14,7 +14,7 @@ import AbstractStreamKeyForm, {
*
* @extends Component
*/
class StreamKeyForm extends AbstractStreamKeyForm<Props> {
class StreamKeyForm extends AbstractStreamKeyForm {
/**
* Initializes a new {@code StreamKeyForm} instance.

View File

@@ -7,10 +7,7 @@ import {
createRecordingDialogEvent,
sendAnalytics
} from '../../../analytics';
import {
DialogContent,
_abstractMapStateToProps
} from '../../../base/dialog';
import { DialogContent } from '../../../base/dialog';
import { translate } from '../../../base/i18n';
import {
Container,
@@ -18,7 +15,6 @@ import {
Switch,
Text
} from '../../../base/react';
import { StyleType } from '../../../base/styles';
import { authorizeDropbox, updateDropboxToken } from '../../../dropbox';
import styles from './styles';
@@ -26,11 +22,6 @@ import { getRecordingDurationEstimation } from '../../functions';
type Props = {
/**
* Style of the dialogs feature.
*/
_dialogStyles: StyleType,
/**
* The redux dispatch function.
*/
@@ -108,7 +99,7 @@ class StartRecordingDialogContent extends Component<Props> {
*/
_renderNoIntegrationsContent() {
return (
<DialogContent style = { this.props._dialogStyles.text }>
<DialogContent style = { styles.noIntegrationContent }>
{ this.props.t('recording.startRecordingBody') }
</DialogContent>
);
@@ -121,7 +112,7 @@ class StartRecordingDialogContent extends Component<Props> {
* @returns {React$Component}
*/
_renderIntegrationsContent() {
const { _dialogStyles, isTokenValid, isValidating, t } = this.props;
const { isTokenValid, isValidating, t } = this.props;
let content = null;
@@ -144,10 +135,7 @@ class StartRecordingDialogContent extends Component<Props> {
style = { styles.header }>
<Text
className = 'recording-title'
style = {{
..._dialogStyles.text,
...styles.title
}}>
style = { styles.title }>
{ t('recording.authDropboxText') }
</Text>
<Switch
@@ -260,5 +248,4 @@ class StartRecordingDialogContent extends Component<Props> {
}
}
export default translate(
connect(_abstractMapStateToProps)(StartRecordingDialogContent));
export default translate(connect()(StartRecordingDialogContent));

View File

@@ -28,6 +28,10 @@ export default createStyleSheet({
paddingBottom: _PADDING
},
noIntegrationContent: {
color: ColorPalette.white
},
startRecordingText: {
paddingBottom: _PADDING
},
@@ -38,6 +42,7 @@ export default createStyleSheet({
},
title: {
color: ColorPalette.white,
fontSize: 16,
fontWeight: 'bold'
},

View File

@@ -4,16 +4,15 @@ import React, { Component } from 'react';
import { Text, View } from 'react-native';
import { connect } from 'react-redux';
import { ColorSchemeRegistry } from '../../../base/color-scheme';
import {
BottomSheet
BottomSheet,
bottomSheetItemStylesCombined
} from '../../../base/dialog';
import {
Avatar,
getAvatarURL,
getParticipantDisplayName
} from '../../../base/participants';
import { StyleType } from '../../../base/styles';
import { hideRemoteVideoMenu } from '../../actions';
@@ -43,11 +42,6 @@ type Props = {
*/
_avatarURL: string,
/**
* The color-schemed stylesheet of the BottomSheet.
*/
_bottomSheetStyles: StyleType,
/**
* Display name of the participant retreived from Redux.
*/
@@ -79,7 +73,7 @@ class RemoteVideoMenu extends Component<Props> {
afterClick: this._onCancel,
showLabel: true,
participantID: this.props.participant.id,
styles: this.props._bottomSheetStyles
styles: bottomSheetItemStylesCombined
};
return (
@@ -119,7 +113,6 @@ class RemoteVideoMenu extends Component<Props> {
* @private
* @returns {{
* _avatarURL: string,
* _bottomSheetStyles: StyleType,
* _participantDisplayName: string
* }}
*/
@@ -128,8 +121,6 @@ function _mapStateToProps(state, ownProps) {
return {
_avatarURL: getAvatarURL(participant),
_bottomSheetStyles:
ColorSchemeRegistry.get(state, 'BottomSheet'),
_participantDisplayName: getParticipantDisplayName(
state, participant.id)
};

View File

@@ -4,12 +4,11 @@ import React, { Component } from 'react';
import { Platform } from 'react-native';
import { connect } from 'react-redux';
import { ColorSchemeRegistry } from '../../../base/color-scheme';
import {
BottomSheet,
bottomSheetItemStylesCombined,
hideDialog
} from '../../../base/dialog';
import { StyleType } from '../../../base/styles';
import { InviteButton } from '../../../invite';
import { AudioRouteButton } from '../../../mobile/audio-mode';
import { LiveStreamButton, RecordButton } from '../../../recording';
@@ -27,15 +26,10 @@ declare var __DEV__;
*/
type Props = {
/**
* The color-schemed stylesheet of the dialog feature.
*/
_bottomSheetStyles: StyleType,
/**
* Used for hiding the dialog when the selection was completed.
*/
dispatch: Function
dispatch: Function,
};
/**
@@ -74,7 +68,7 @@ class OverflowMenu extends Component<Props> {
const buttonProps = {
afterClick: this._onCancel,
showLabel: true,
styles: this.props._bottomSheetStyles
styles: bottomSheetItemStylesCombined
};
return (
@@ -112,22 +106,6 @@ class OverflowMenu extends Component<Props> {
}
}
/**
* Function that maps parts of Redux state tree into component props.
*
* @param {Object} state - Redux state.
* @private
* @returns {{
* _bottomSheetStyles: StyleType
* }}
*/
function _mapStateToProps(state) {
return {
_bottomSheetStyles:
ColorSchemeRegistry.get(state, 'BottomSheet')
};
}
OverflowMenu_ = connect(_mapStateToProps)(OverflowMenu);
OverflowMenu_ = connect()(OverflowMenu);
export default OverflowMenu_;

View File

@@ -5,19 +5,21 @@ import { View } from 'react-native';
import { connect } from 'react-redux';
import { Container } from '../../../base/react';
import { ColorSchemeRegistry } from '../../../base/color-scheme';
import { StyleType } from '../../../base/styles';
import { ChatButton } from '../../../chat';
import { isToolboxVisible } from '../../functions';
import { HANGUP_BUTTON_SIZE } from '../../constants';
import AudioMuteButton from '../AudioMuteButton';
import HangupButton from '../HangupButton';
import VideoMuteButton from '../VideoMuteButton';
import OverflowMenuButton from './OverflowMenuButton';
import styles from './styles';
import VideoMuteButton from '../VideoMuteButton';
import styles, {
chatButtonOverride,
hangupButtonStyles,
toolbarButtonStyles,
toolbarToggledButtonStyles
} from './styles';
/**
* The number of buttons other than {@link HangupButton} to render in
@@ -41,11 +43,6 @@ const _BUTTON_SIZE_FACTOR = 0.85;
*/
type Props = {
/**
* The color-schemed stylesheet of the feature.
*/
_styles: StyleType,
/**
* The indicator which determines whether the toolbox is visible.
*/
@@ -114,7 +111,6 @@ class Toolbox extends Component<Props, State> {
* @returns {number}
*/
_calculateButtonSize() {
const { _styles } = this.props;
const { width } = this.state;
if (width <= 0) {
@@ -122,8 +118,8 @@ class Toolbox extends Component<Props, State> {
return width;
}
const hangupButtonSize = HANGUP_BUTTON_SIZE;
const { style } = _styles.buttonStyles;
const hangupButtonSize = styles.hangupButton.width;
const { style } = toolbarButtonStyles;
let buttonSize
= (width
@@ -159,14 +155,12 @@ class Toolbox extends Component<Props, State> {
* @returns {Object | Array}
*/
_getChatButtonToggledStyle(baseStyle) {
const { _styles } = this.props;
if (Array.isArray(baseStyle.style)) {
return {
...baseStyle,
style: [
...baseStyle.style,
_styles.chatButtonOverride.toggled
chatButtonOverride.toggled
]
};
}
@@ -175,7 +169,7 @@ class Toolbox extends Component<Props, State> {
...baseStyle,
style: [
baseStyle.style,
_styles.chatButtonOverride.toggled
chatButtonOverride.toggled
]
};
}
@@ -202,9 +196,9 @@ class Toolbox extends Component<Props, State> {
* @returns {React$Node}
*/
_renderToolbar() {
const { _styles } = this.props;
const buttonSize = this._calculateButtonSize();
let { buttonStyles, toggledButtonStyles } = _styles;
let buttonStyles = toolbarButtonStyles;
let toggledButtonStyles = toolbarToggledButtonStyles;
if (buttonSize > 0) {
const extraButtonStyle = {
@@ -247,8 +241,7 @@ class Toolbox extends Component<Props, State> {
<AudioMuteButton
styles = { buttonStyles }
toggledStyles = { toggledButtonStyles } />
<HangupButton
styles = { _styles.hangupButtonStyles } />
<HangupButton styles = { hangupButtonStyles } />
<VideoMuteButton
styles = { buttonStyles }
toggledStyles = { toggledButtonStyles } />
@@ -268,13 +261,11 @@ class Toolbox extends Component<Props, State> {
* {@code Toolbox} props.
* @private
* @returns {{
* _styles: StyleType,
* _visible: boolean
* }}
*/
function _mapStateToProps(state: Object): Object {
return {
_styles: ColorSchemeRegistry.get(state, 'Toolbox'),
_visible: isToolboxVisible(state)
};
}

View File

@@ -1,6 +1,4 @@
// @flow
import { ColorSchemeRegistry, schemeColor } from '../../../base/color-scheme';
import { BoxModel, ColorPalette, createStyleSheet } from '../../../base/styles';
import { HANGUP_BUTTON_SIZE } from '../../constants';
@@ -11,7 +9,7 @@ import { HANGUP_BUTTON_SIZE } from '../../constants';
* The style of toolbar buttons.
*/
const toolbarButton = {
backgroundColor: schemeColor('button'),
backgroundColor: ColorPalette.white,
borderRadius: 20,
borderWidth: 0,
flex: 0,
@@ -22,6 +20,7 @@ const toolbarButton = {
// XXX We probably tested BoxModel.margin and discovered it to be too small
// for our taste.
marginHorizontal: 7,
opacity: 0.7,
width: 40
};
@@ -34,26 +33,29 @@ const toolbarButtonIcon = {
fontSize: 22
};
/**
* The style of toolbar buttons which display white icons.
*/
const whiteToolbarButton = {
...toolbarButton,
backgroundColor: schemeColor('buttonToggled')
};
/**
* The icon style of toolbar buttons which display white icons.
*/
const whiteToolbarButtonIcon = {
...toolbarButtonIcon,
color: ColorPalette.white
};
/**
* The Toolbox and toolbar related styles.
*/
const styles = createStyleSheet({
/**
* The style of the toolbar button which hangs the current conference up.
*/
hangupButton: {
...toolbarButton,
backgroundColor: ColorPalette.red,
borderRadius: 30,
height: HANGUP_BUTTON_SIZE,
width: HANGUP_BUTTON_SIZE
},
/**
* The icon style of toolbar buttons which hangs the current conference up.
*/
hangupButtonIcon: {
...toolbarButtonIcon,
color: ColorPalette.white,
fontSize: 24
},
/**
* The style of the toolbar.
@@ -67,60 +69,74 @@ const styles = createStyleSheet({
paddingHorizontal: BoxModel.margin
},
/**
* The style of toolbar buttons.
*/
toolbarButton,
/**
* The icon style of the toolbar buttons.
*/
toolbarButtonIcon,
/**
* The style of the root/top-level {@link Container} of {@link Toolbox}.
*/
toolbox: {
flexDirection: 'column',
flexGrow: 0
},
/**
* The style of toolbar buttons which display white icons.
*/
whiteToolbarButton: {
...toolbarButton,
backgroundColor: ColorPalette.buttonUnderlay
},
/**
* The icon style of toolbar buttons which display white icons.
*/
whiteToolbarButtonIcon: {
...toolbarButtonIcon,
color: ColorPalette.white
}
});
export default styles;
/**
* Color schemed styles for the @{Toolbox} component.
* Styles for the hangup button.
*/
ColorSchemeRegistry.register('Toolbox', {
/**
* Styles for buttons in the toolbar.
*/
buttonStyles: {
iconStyle: toolbarButtonIcon,
style: toolbarButton
},
export const hangupButtonStyles = {
iconStyle: styles.whiteToolbarButtonIcon,
style: styles.hangupButton,
underlayColor: ColorPalette.buttonUnderlay
};
/**
* Overrides to the standard styles that we apply to the chat button, as
* that behaves slightly differently to other buttons.
*/
chatButtonOverride: {
toggled: {
backgroundColor: ColorPalette.blue
}
},
/**
* Styles for buttons in the toolbar.
*/
export const toolbarButtonStyles = {
iconStyle: styles.toolbarButtonIcon,
style: styles.toolbarButton
};
hangupButtonStyles: {
iconStyle: whiteToolbarButtonIcon,
style: {
...toolbarButton,
backgroundColor: schemeColor('hangup'),
borderRadius: HANGUP_BUTTON_SIZE / 2,
height: HANGUP_BUTTON_SIZE,
width: HANGUP_BUTTON_SIZE
},
underlayColor: ColorPalette.buttonUnderlay
},
/**
* Styles for toggled buttons in the toolbar.
*/
export const toolbarToggledButtonStyles = {
iconStyle: styles.whiteToolbarButtonIcon,
style: styles.whiteToolbarButton
};
/**
* Styles for toggled buttons in the toolbar.
*/
toggledButtonStyles: {
iconStyle: whiteToolbarButtonIcon,
style: {
...whiteToolbarButton,
borderColor: schemeColor('buttonToggledBorder'),
borderWidth: 1
}
/**
* Overrides to the standard styles that we apply to the chat button, as that
* behaves slightly differently to other buttons.
*/
export const chatButtonOverride = createStyleSheet({
toggled: {
backgroundColor: ColorPalette.blue
}
});