Compare commits

...

25 Commits

Author SHA1 Message Date
Alex Bumbu
1893ced556 iOS: toggle audio mute & leave meeting lock screen widgets (#12581) 2022-11-18 13:25:48 +02:00
Calin-Teodor
7d9c13a618 feat(prejoin): updated styles 2022-11-18 11:02:05 +02:00
Hristo Terezov
48ed3b7dc6 fix(dialog): cancel hide timeout on openDialog
Since we unmount the dialog after a timeout because of an animation we
need to cancel the timeout in case we need to render new dialog.
Otherwise the actual hiding can be executed after we render the new
dialog.
2022-11-17 17:00:02 -06:00
Hristo Terezov
04abfe1a3b feat(dialog): add disableAutoHideOnSubmit prop
Needed for shared video dialog.
2022-11-17 17:00:02 -06:00
Alex Bumbu
d45decc393 Update JitsiMeet.h (#12574) 2022-11-17 16:31:37 +02:00
Saúl Ibarra Corretgé
88f8f48465 fix(participants) don't treat Jigasi like a fake participant
We only really want to know if a participant is Jigasi for displaying a
specific icon, for all other intents and purposes it's a normal
participant.
2022-11-17 15:13:54 +01:00
Saúl Ibarra Corretgé
8127ea2479 feat(redux) throw exception in case invalid listeners are registered
This allows catching mistakes early.
2022-11-17 11:07:57 +01:00
Saúl Ibarra Corretgé
b22915c169 fix(rn,filmstrip) fix invalid selector registered as state listener 2022-11-17 11:07:57 +01:00
Saúl Ibarra Corretgé
14fcd153e5 fix(rn,connection-indicator) align rendering with web
Use the same way for calculating que perceived quality and display it.
2022-11-17 11:07:57 +01:00
Robert Pintilii
48efe36cdf fix(dial-in) Fix warning (#12571)
Only show warning if the feature is enabled
2022-11-16 12:14:58 +02:00
Saúl Ibarra Corretgé
0c373e105b ref(StageFilmstrip) mark as experimental
THere are a bunch of unhandled corner cases involving virtual
screen-sharing participants.
2022-11-15 10:34:58 -06:00
Shawn
e57c7f92a8 refactor(end-conference): distinguish between component vs host module logic 2022-11-15 10:34:40 -06:00
Jaya Allamsetty
70fa44f85f chore(deps) lib-jitsi-meet@latest
https://github.com/jitsi/lib-jitsi-meet/compare/v1533.0.0+7b257686...v1535.0.0+e6263e7c
2022-11-15 11:08:37 -05:00
rinenweb
bcc5beb73d fix(lang) fixup main-el.json
Missing "{" in line 74 and name is not displayed at all when {name} is used in line 520.
2022-11-15 09:41:43 +01:00
Joseph Garrone
4ef4e45ee4 fix(styles) Remove Theme type annotation (#12544)
* tss-react doesn't need a type anotation for the Theme

* Update tss-react to 4.4.4
2022-11-15 09:50:22 +02:00
TTG
c9ff0bb75f lang: Remove Indonesian & Norwegian translations (#12554)
* Remove Indonesian translation

* Remove Norwegian translation
2022-11-13 21:38:42 -06:00
chipechop
282817db28 lang: Update main-it.json (#12541)
refining
2022-11-11 16:37:54 -06:00
Shawn
93ab7725e7 feat(toolbox) notify click for hangup-menu and end-meeting menu button 2022-11-11 16:06:53 -06:00
Calin-Teodor
53ccb97d34 fix(welcome/native): removed unused constant 2022-11-11 18:11:41 +01:00
Calin-Teodor
6346d99d0e fix(welcome/native): placeholder fix 2022-11-11 18:11:41 +01:00
Saúl Ibarra Corretgé
79c4cabbad feat(rn) make status bar visible at all times 2022-11-11 17:25:28 +01:00
Robert Pintilii
7a9f51b01b ref(TS) Convert some features to TS (#12546) 2022-11-11 10:20:33 +02:00
Robert Pintilii
a884a6b232 fix(ui) Fix new icons issues (#12545) 2022-11-11 09:58:55 +02:00
Jaya Allamsetty
b00a17c1c3 fix(connection-stats) Do not display max enabled resolution on SS tile. 2022-11-10 17:00:34 -05:00
bgrozev
99955df5c8 Cleanup sounds (switch to mp3, encode at lower bitrate).' (#12507)
* Reencode mp3 sounds at lower bitrate, mono.
* Encode wav sounds as mp3.
* Remove unused sound file.
* Add opus encoded sounds.
* Add a script to encode sounds.
2022-11-10 10:06:40 -06:00
227 changed files with 1985 additions and 2208 deletions

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#17A0DB</color>
<color name="colorPrimaryDark">#1081B2</color>
<color name="navigationBarColor">#161618</color>
</resources>

View File

@@ -2,7 +2,7 @@
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:editTextBackground">@drawable/rn_edit_text_material</item>
<item name="android:forceDarkAllowed">false</item>
<item name="android:navigationBarColor">@color/colorPrimaryDark</item>
<item name="android:navigationBarColor">@color/navigationBarColor</item>
<item name="android:windowDisablePreview">true</item>
</style>
</resources>

View File

@@ -767,11 +767,13 @@ var config = {
// 'desktop',
// 'download',
// 'embedmeeting',
// 'end-meeting',
// 'etherpad',
// 'feedback',
// 'filmstrip',
// 'fullscreen',
// 'hangup',
// 'hangup-menu',
// 'help',
// {
// key: 'invite',

1
globals.native.d.ts vendored
View File

@@ -27,6 +27,7 @@ interface IWindow {
clearTimeout: typeof clearTimeout;
setImmediate: typeof setImmediate;
clearImmediate: typeof clearImmediate;
addEventListener: Function;
}
interface INavigator {

View File

@@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,13 @@
{
"images" : [
{
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "end_call_button.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "microphone_off_button.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "microphone_on_button.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,101 @@
//
// DarwinNotificationsObserver.swift
// WidgetsExtension
//
// Created by Alex Bumbu on 17.10.2022.
//
import Foundation
enum DarwinNotification: String {
case meetingMutedChanged = "iOS_MeetingMutedChanged"
}
extension DarwinNotification {
var name: String { rawValue }
}
class DarwinNotificationsObserver {
private static var observers = Array<ProxyObserver>()
private let queue = DispatchQueue(label: "org.jitsi.meet.darwinNotificationObserver", qos: .default, autoreleaseFrequency: .workItem)
private var notificationCenter: CFNotificationCenter
init() {
notificationCenter = CFNotificationCenterGetDarwinNotifyCenter()
}
func observe(notification: DarwinNotification, handler: @escaping () -> Void) {
let proxyObserver = ProxyObserver(observer: self, notificationName: notification.name, handler: handler)
queue.async {
DarwinNotificationsObserver.observers.append(proxyObserver)
}
let callback: CFNotificationCallback = { _, observer, name, _, _ in
guard let observer = observer else {
return
}
// Extract pointer to `observer` from void pointer:
let proxyObserver = Unmanaged<ProxyObserver>.fromOpaque(observer).takeUnretainedValue()
var observers = DarwinNotificationsObserver.observers
if !proxyObserver.forwardNotification(), let index = observers.firstIndex(of: proxyObserver) {
// cleanup if `forwardNotification` fails
observers.remove(at: index)
}
}
CFNotificationCenterAddObserver(notificationCenter,
Unmanaged.passUnretained(proxyObserver).toOpaque(),
callback,
notification.name as CFString,
nil,
.deliverImmediately)
}
func stopObserving(notification: DarwinNotification) {
queue.sync {
DarwinNotificationsObserver.observers.removeAll { $0.observer == nil }
}
if let index = DarwinNotificationsObserver.observers.firstIndex(where: { $0.observer === self && $0.notificationName == notification.name }) {
let proxyObserver = DarwinNotificationsObserver.observers[index]
CFNotificationCenterRemoveObserver(notificationCenter,
Unmanaged.passUnretained(proxyObserver).toOpaque(),
CFNotificationName(notification.name as CFString),
nil)
queue.async {
DarwinNotificationsObserver.observers.remove(at: index)
}
}
}
}
private class ProxyObserver: Equatable {
let notificationName: String
weak var observer: AnyObject?
private let handler: () -> (Void)
static func == (lhs: ProxyObserver, rhs: ProxyObserver) -> Bool {
lhs.observer === rhs.observer && lhs.notificationName == rhs.notificationName
}
init(observer: AnyObject? = nil, notificationName: String, handler: @escaping () -> Void) {
self.notificationName = notificationName
self.handler = handler
self.observer = observer
}
func forwardNotification() -> Bool {
guard observer != nil else {
return false
}
handler()
return true
}
}

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.widgetkit-extension</string>
</dict>
</dict>
</plist>

View File

@@ -0,0 +1,54 @@
//
// LockScreenLeaveMeetingWidget.swift
// WidgetsExtension
//
// Created by Alex Bumbu on 31.10.2022.
//
import SwiftUI
import WidgetKit
struct LockScreenLeaveMeetingWidget: Widget {
let kind: String = "LockScreenLeaveMeetingWidget"
var body: some WidgetConfiguration {
StaticConfiguration(kind: kind, provider: Provider()) { entry in
WidgetsEntryView(entry: entry)
}
.configurationDisplayName("Leave Jitsi Meeting Widget")
.description("This is a lockscreen widget for leaving the ongoing Jitsi meeting.")
.supportedFamilies([.accessoryCircular])
}
}
//struct LockScreenLeaveMeetingWidget_Preview: PreviewProvider {
// static var previews: some View {
// let meetingState = MeetingState(audioMuted: true)
//
// WidgetsEntryView(entry: CurrentMeetingEntry(date: Date(), meetingState: meetingState))
// .previewContext(WidgetPreviewContext(family: .accessoryCircular))
// .previewDisplayName("Circular")
// }
//}
private struct WidgetsEntryView: View {
@Environment(\.widgetFamily) var widgetFamily
var entry: Provider.Entry
var body: some View {
if entry.meetingState != nil, widgetFamily == .accessoryCircular {
AccessoryCircularWidgetView()
} else {
EmptyView()
}
}
}
private struct AccessoryCircularWidgetView: View {
var body: some View {
Image("leave_meeting")
.resizable()
.aspectRatio(contentMode: .fit)
.widgetURL(URL(string: "meet/leaveMeeting")!)
}
}

View File

@@ -0,0 +1,89 @@
//
// LockScreenMuteAudioWidget.swift
// WidgetsExtension
//
// Created by Alex Bumbu on 31.10.2022.
//
import SwiftUI
import WidgetKit
struct LockScreenMuteAudioWidget: Widget {
let kind: String = "LockScreenMuteAudioWidget"
var body: some WidgetConfiguration {
StaticConfiguration(kind: kind, provider: Provider()) { entry in
WidgetsEntryView(entry: entry)
}
.configurationDisplayName("Mute Jitsi Audio Widget")
.description("This is a lockscreen widget for muting or unmuting the audio for the ongoing Jitsi meeting.")
.supportedFamilies([.accessoryCircular])
}
}
//struct LockScreenMuteAudioWidget_Preview: PreviewProvider {
// static var previews: some View {
// let meetingState = MeetingState(audioMuted: true)
//
// WidgetsEntryView(entry: CurrentMeetingEntry(date: Date(), meetingState: meetingState))
// .previewContext(WidgetPreviewContext(family: .accessoryInline))
// .previewDisplayName("Inline")
//
// WidgetsEntryView(entry: CurrentMeetingEntry(date: Date(), meetingState: meetingState))
// .previewContext(WidgetPreviewContext(family: .accessoryCircular))
// .previewDisplayName("Circular")
//
// WidgetsEntryView(entry: CurrentMeetingEntry(date: Date(), meetingState: meetingState))
// .previewContext(WidgetPreviewContext(family: .accessoryRectangular))
// .previewDisplayName("Rectangular")
// }
//}
private struct WidgetsEntryView: View {
@Environment(\.widgetFamily) var widgetFamily
var entry: Provider.Entry
var body: some View {
if let meetingState = entry.meetingState {
switch widgetFamily {
case .accessoryInline:
Text("Some meeting name")
case .accessoryRectangular:
AccessoryCircularWidgetView(audioMuted: meetingState.audioMuted)
case .accessoryCircular:
AccessoryCircularWidgetView(audioMuted: meetingState.audioMuted)
default:
EmptyView()
}
} else {
EmptyView()
}
}
}
private struct AccessoryRectangularWidgetView: View {
var audioMuted: Bool
var body: some View {
let imageName: String = audioMuted ? "microphone_on" : "microphone_off"
let caption: String = audioMuted ? "Unmute \naudio" : "Mute \naudio"
HStack {
Image(imageName)
.resizable()
.aspectRatio(contentMode: .fit)
Text(caption)
}.widgetURL(URL(string: "meet/toggleAudioMute")!)
}
}
private struct AccessoryCircularWidgetView: View {
var audioMuted: Bool
var body: some View {
let imageName: String = audioMuted ? "microphone_on" : "microphone_off"
Image(imageName)
.resizable()
.aspectRatio(contentMode: .fit)
.widgetURL(URL(string: "meet/toggleAudioMute")!)
}
}

View File

@@ -0,0 +1,30 @@
//
// MeetingState.swift
// WidgetsExtension
//
// Created by Alex Bumbu on 28.10.2022.
//
import Foundation
struct MeetingState: Decodable {
var audioMuted: Bool
}
extension MeetingState {
private static var stateFileURL: URL? {
return FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.org.jitsi.meet.appgroup")?.appending(component: "widgetState")
}
static func load() -> MeetingState? {
guard
let stateFileURL = stateFileURL,
let data = try? Data(contentsOf: stateFileURL)
else {
return nil
}
let decoder = PropertyListDecoder()
return try? decoder.decode(MeetingState.self, from: data)
}
}

View File

@@ -0,0 +1,44 @@
//
// Provider.swift
// WidgetsExtension
//
// Created by Alex Bumbu on 31.10.2022.
//
import WidgetKit
import SwiftUI
struct CurrentMeetingEntry: TimelineEntry {
let date: Date
var meetingState: MeetingState?
}
class Provider: TimelineProvider {
private var currentMeetingState: MeetingState? {
return MeetingState.load()
}
func placeholder(in context: Context) -> CurrentMeetingEntry {
CurrentMeetingEntry(date: Date(),
meetingState: MeetingState(audioMuted: false))
}
func getSnapshot(in context: Context, completion: @escaping (CurrentMeetingEntry) -> ()) {
var meetingState = currentMeetingState
if context.isPreview {
meetingState = MeetingState(audioMuted: false)
}
let entry = CurrentMeetingEntry(date: Date(), meetingState: meetingState)
completion(entry)
}
func getTimeline(in context: Context, completion: @escaping (Timeline<CurrentMeetingEntry>) -> ()) {
var entries: [CurrentMeetingEntry] = []
let entry = CurrentMeetingEntry(date: Date(), meetingState: currentMeetingState)
entries.append(entry)
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
}
}

View File

@@ -0,0 +1,19 @@
//
// Widgets.swift
// Widgets
//
// Created by Alex Bumbu on 17.10.2022.
// Copyright © 2022 Facebook. All rights reserved.
//
import WidgetKit
import SwiftUI
@main
struct Widgets: WidgetBundle {
@WidgetBundleBuilder
var body: some Widget {
LockScreenMuteAudioWidget()
LockScreenLeaveMeetingWidget()
}
}

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.jitsi.meet.appgroup</string>
</array>
</dict>
</plist>

View File

@@ -23,14 +23,26 @@
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
2681BB562C7A0B42CFBA6719 /* libPods-JitsiMeet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D6152FF9E9F7B0E86F70A21D /* libPods-JitsiMeet.a */; };
4E46D952290FF39E00761DEF /* LockScreenMuteAudioWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E46D951290FF39E00761DEF /* LockScreenMuteAudioWidget.swift */; };
4E46D954290FF55600761DEF /* LockScreenLeaveMeetingWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E46D953290FF55600761DEF /* LockScreenLeaveMeetingWidget.swift */; };
4E6920B828FD84D700645D9E /* DarwinNotificationsObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E6920B728FD84D700645D9E /* DarwinNotificationsObserver.swift */; };
4E6A3E17291024B900E6B0B5 /* Provider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E6A3E16291024B900E6B0B5 /* Provider.swift */; };
4E90F9402632D1AB001102D4 /* Atomic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E90F93F2632D1AB001102D4 /* Atomic.swift */; };
4EA73DA3290C1D6C00A16FF8 /* MeetingState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EA73DA2290C1D6C00A16FF8 /* MeetingState.swift */; };
4EB06024260E026600F524C5 /* ReplayKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4EC49B8625BED71300E76218 /* ReplayKit.framework */; };
4EB06027260E026600F524C5 /* SampleHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB06026260E026600F524C5 /* SampleHandler.swift */; };
4EB0602B260E026600F524C5 /* JitsiMeetBroadcastExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 4EB06023260E026600F524C5 /* JitsiMeetBroadcastExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
4EB0603C260E09D000F524C5 /* SocketConnection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB06039260E09D000F524C5 /* SocketConnection.swift */; };
4EB0603D260E09D000F524C5 /* DarwinNotificationCenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB0603A260E09D000F524C5 /* DarwinNotificationCenter.swift */; };
4EB0603E260E09D000F524C5 /* SampleUploader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB0603B260E09D000F524C5 /* SampleUploader.swift */; };
4EBB458A28FFFD4100855769 /* RoutesHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EBB458928FFFD4100855769 /* RoutesHandler.m */; };
4EBB458E2902E85B00855769 /* WidgetKitHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EBB458D2902E85B00855769 /* WidgetKitHelper.swift */; };
4ECA496628FD590000085365 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4ECA496528FD590000085365 /* WidgetKit.framework */; };
4ECA496828FD590000085365 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4ECA496728FD590000085365 /* SwiftUI.framework */; };
4ECA496B28FD590000085365 /* Widgets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4ECA496A28FD590000085365 /* Widgets.swift */; };
4ECA496D28FD590000085365 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4ECA496C28FD590000085365 /* Assets.xcassets */; };
4ECA497128FD590000085365 /* WidgetsExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 4ECA496428FD590000085365 /* WidgetsExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
C2116A7673E01A1CCD5DC1F4 /* libPods-JitsiMeet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0BF9FEBA4DEAB800AD735681 /* libPods-JitsiMeet.a */; };
DE4C456121DE1E4E00EA0709 /* FIRUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = DE4C455F21DE1E4E00EA0709 /* FIRUtilities.m */; };
DEA9F289258A6EA800D4CD74 /* JitsiMeetSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DEA9F288258A6EA800D4CD74 /* JitsiMeetSDK.framework */; };
DEA9F28A258A6EA800D4CD74 /* JitsiMeetSDK.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DEA9F288258A6EA800D4CD74 /* JitsiMeetSDK.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
@@ -64,6 +76,13 @@
remoteGlobalIDString = 4EB06022260E026600F524C5;
remoteInfo = "JitsiMeetBroadcast Extension";
};
4ECA496F28FD590000085365 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 4ECA496328FD590000085365;
remoteInfo = WidgetsExtension;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
@@ -108,6 +127,7 @@
dstPath = "";
dstSubfolderSpec = 13;
files = (
4ECA497128FD590000085365 /* WidgetsExtension.appex in Embed App Extensions */,
4EB0602B260E026600F524C5 /* JitsiMeetBroadcastExtension.appex in Embed App Extensions */,
);
name = "Embed App Extensions";
@@ -134,6 +154,7 @@
0BEA5C3A1F7B8F73000D0AB4 /* ComplicationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComplicationController.swift; sourceTree = "<group>"; };
0BEA5C3C1F7B8F73000D0AB4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
0BEA5C3E1F7B8F73000D0AB4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
0BF9FEBA4DEAB800AD735681 /* libPods-JitsiMeet.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-JitsiMeet.a"; sourceTree = BUILT_PRODUCTS_DIR; };
13B07F961A680F5B00A75B9A /* jitsi-meet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "jitsi-meet.app"; sourceTree = BUILT_PRODUCTS_DIR; };
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
@@ -141,8 +162,12 @@
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
3E0F4ED943C0B12BE77F6B45 /* Pods-JitsiMeet.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JitsiMeet.release.xcconfig"; path = "Target Support Files/Pods-JitsiMeet/Pods-JitsiMeet.release.xcconfig"; sourceTree = "<group>"; };
4E46D951290FF39E00761DEF /* LockScreenMuteAudioWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LockScreenMuteAudioWidget.swift; sourceTree = "<group>"; };
4E46D953290FF55600761DEF /* LockScreenLeaveMeetingWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LockScreenLeaveMeetingWidget.swift; sourceTree = "<group>"; };
4E6920B728FD84D700645D9E /* DarwinNotificationsObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DarwinNotificationsObserver.swift; sourceTree = "<group>"; };
4E6A3E16291024B900E6B0B5 /* Provider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Provider.swift; sourceTree = "<group>"; };
4E90F93F2632D1AB001102D4 /* Atomic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Atomic.swift; sourceTree = "<group>"; };
4EA73DA2290C1D6C00A16FF8 /* MeetingState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeetingState.swift; sourceTree = "<group>"; };
4EB06023260E026600F524C5 /* JitsiMeetBroadcastExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = JitsiMeetBroadcastExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
4EB06026260E026600F524C5 /* SampleHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleHandler.swift; sourceTree = "<group>"; };
4EB06028260E026600F524C5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -150,10 +175,21 @@
4EB06039260E09D000F524C5 /* SocketConnection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketConnection.swift; sourceTree = "<group>"; };
4EB0603A260E09D000F524C5 /* DarwinNotificationCenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DarwinNotificationCenter.swift; sourceTree = "<group>"; };
4EB0603B260E09D000F524C5 /* SampleUploader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SampleUploader.swift; sourceTree = "<group>"; };
4EBB458828FFFD4100855769 /* RoutesHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RoutesHandler.h; sourceTree = "<group>"; };
4EBB458928FFFD4100855769 /* RoutesHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RoutesHandler.m; sourceTree = "<group>"; };
4EBB458B2902A94700855769 /* WidgetsExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = WidgetsExtension.entitlements; sourceTree = "<group>"; };
4EBB458C2902E85B00855769 /* JitsiMeet-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "JitsiMeet-Bridging-Header.h"; sourceTree = "<group>"; };
4EBB458D2902E85B00855769 /* WidgetKitHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WidgetKitHelper.swift; sourceTree = "<group>"; };
4EC49B8625BED71300E76218 /* ReplayKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ReplayKit.framework; path = System/Library/Frameworks/ReplayKit.framework; sourceTree = SDKROOT; };
756FCE06C08D9B947653C98A /* Pods-JitsiMeet.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JitsiMeet.debug.xcconfig"; path = "Target Support Files/Pods-JitsiMeet/Pods-JitsiMeet.debug.xcconfig"; sourceTree = "<group>"; };
4ECA496428FD590000085365 /* WidgetsExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = WidgetsExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
4ECA496528FD590000085365 /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; };
4ECA496728FD590000085365 /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; };
4ECA496A28FD590000085365 /* Widgets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Widgets.swift; sourceTree = "<group>"; };
4ECA496C28FD590000085365 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
4ECA496E28FD590000085365 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
7052390E12D7319D36D8E4CA /* Pods-JitsiMeet.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JitsiMeet.debug.xcconfig"; path = "Target Support Files/Pods-JitsiMeet/Pods-JitsiMeet.debug.xcconfig"; sourceTree = "<group>"; };
8CAA3C5A38E868335D1C1EC1 /* Pods-JitsiMeet.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JitsiMeet.release.xcconfig"; path = "Target Support Files/Pods-JitsiMeet/Pods-JitsiMeet.release.xcconfig"; sourceTree = "<group>"; };
B3B083EB1D4955FF0069CEE7 /* app.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = app.entitlements; sourceTree = "<group>"; };
D6152FF9E9F7B0E86F70A21D /* libPods-JitsiMeet.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-JitsiMeet.a"; sourceTree = BUILT_PRODUCTS_DIR; };
DE050388256E904600DEE3A5 /* WebRTC.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = WebRTC.xcframework; path = "../../node_modules/react-native-webrtc/apple/WebRTC.xcframework"; sourceTree = "<group>"; };
DE4C455F21DE1E4E00EA0709 /* FIRUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FIRUtilities.m; sourceTree = "<group>"; };
DE4C456021DE1E4E00EA0709 /* FIRUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FIRUtilities.h; sourceTree = "<group>"; };
@@ -180,7 +216,7 @@
DED016F128ECBC9D009D5E8D /* WebRTC.xcframework in Frameworks */,
DEA9F289258A6EA800D4CD74 /* JitsiMeetSDK.framework in Frameworks */,
FD572B9827EDF32300A800FB /* GiphyUISDK.xcframework in Frameworks */,
2681BB562C7A0B42CFBA6719 /* libPods-JitsiMeet.a in Frameworks */,
C2116A7673E01A1CCD5DC1F4 /* libPods-JitsiMeet.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -199,6 +235,15 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
4ECA496128FD590000085365 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
4ECA496828FD590000085365 /* SwiftUI.framework in Frameworks */,
4ECA496628FD590000085365 /* WidgetKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
@@ -213,7 +258,9 @@
DEFDBBDB25656E3B00344B23 /* WebRTC.xcframework */,
0BD6B4361EF82A6B00D1F4CD /* WebRTC.framework */,
4EC49B8625BED71300E76218 /* ReplayKit.framework */,
D6152FF9E9F7B0E86F70A21D /* libPods-JitsiMeet.a */,
4ECA496528FD590000085365 /* WidgetKit.framework */,
4ECA496728FD590000085365 /* SwiftUI.framework */,
0BF9FEBA4DEAB800AD735681 /* libPods-JitsiMeet.a */,
);
name = Frameworks;
sourceTree = "<group>";
@@ -261,6 +308,10 @@
0BBD021F212EB69D00CCB19F /* Types.h */,
0B412F1D1EDEE6E800B1A0A6 /* ViewController.h */,
0B412F1E1EDEE6E800B1A0A6 /* ViewController.m */,
4EBB458828FFFD4100855769 /* RoutesHandler.h */,
4EBB458928FFFD4100855769 /* RoutesHandler.m */,
4EBB458D2902E85B00855769 /* WidgetKitHelper.swift */,
4EBB458C2902E85B00855769 /* JitsiMeet-Bridging-Header.h */,
);
path = src;
sourceTree = "<group>";
@@ -282,9 +333,25 @@
sourceTree = "<group>";
tabWidth = 4;
};
4ECA496928FD590000085365 /* Widgets Extension */ = {
isa = PBXGroup;
children = (
4ECA496A28FD590000085365 /* Widgets.swift */,
4E46D951290FF39E00761DEF /* LockScreenMuteAudioWidget.swift */,
4E46D953290FF55600761DEF /* LockScreenLeaveMeetingWidget.swift */,
4E6A3E16291024B900E6B0B5 /* Provider.swift */,
4EA73DA2290C1D6C00A16FF8 /* MeetingState.swift */,
4E6920B728FD84D700645D9E /* DarwinNotificationsObserver.swift */,
4ECA496C28FD590000085365 /* Assets.xcassets */,
4ECA496E28FD590000085365 /* Info.plist */,
);
path = "Widgets Extension";
sourceTree = "<group>";
};
83CBB9F61A601CBA00E9B192 = {
isa = PBXGroup;
children = (
4EBB458B2902A94700855769 /* WidgetsExtension.entitlements */,
B3B083EB1D4955FF0069CEE7 /* app.entitlements */,
0B26BE711EC5BC4D00EEFB41 /* Frameworks */,
83CBBA001A601CBA00E9B192 /* Products */,
@@ -292,11 +359,12 @@
0BEA5C261F7B8F73000D0AB4 /* Watch app */,
0BEA5C351F7B8F73000D0AB4 /* WatchKit extension */,
4EB06025260E026600F524C5 /* JitsiMeetBroadcast Extension */,
CDD71F5E1157E9F283DF92A8 /* Pods */,
4ECA496928FD590000085365 /* Widgets Extension */,
BD4E28FA984EA7018FD927DF /* Pods */,
);
indentWidth = 2;
indentWidth = 4;
sourceTree = "<group>";
tabWidth = 2;
tabWidth = 4;
};
83CBBA001A601CBA00E9B192 /* Products */ = {
isa = PBXGroup;
@@ -305,15 +373,16 @@
0BEA5C251F7B8F73000D0AB4 /* JitsiMeetCompanion.app */,
0BEA5C311F7B8F73000D0AB4 /* JitsiMeetCompanion Extension.appex */,
4EB06023260E026600F524C5 /* JitsiMeetBroadcastExtension.appex */,
4ECA496428FD590000085365 /* WidgetsExtension.appex */,
);
name = Products;
sourceTree = "<group>";
};
CDD71F5E1157E9F283DF92A8 /* Pods */ = {
BD4E28FA984EA7018FD927DF /* Pods */ = {
isa = PBXGroup;
children = (
756FCE06C08D9B947653C98A /* Pods-JitsiMeet.debug.xcconfig */,
3E0F4ED943C0B12BE77F6B45 /* Pods-JitsiMeet.release.xcconfig */,
7052390E12D7319D36D8E4CA /* Pods-JitsiMeet.debug.xcconfig */,
8CAA3C5A38E868335D1C1EC1 /* Pods-JitsiMeet.release.xcconfig */,
);
name = Pods;
path = ../Pods;
@@ -361,7 +430,7 @@
isa = PBXNativeTarget;
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "JitsiMeet" */;
buildPhases = (
69BC5020DBE393B56BD76636 /* [CP] Check Pods Manifest.lock */,
58E2CB346F2C2A873294F481 /* [CP] Check Pods Manifest.lock */,
0BBA83C41EC9F7600075A103 /* Run React packager */,
13B07F871A680F5B00A75B9A /* Sources */,
13B07F8C1A680F5B00A75B9A /* Frameworks */,
@@ -380,6 +449,7 @@
dependencies = (
0BEA5C401F7B8F73000D0AB4 /* PBXTargetDependency */,
4EB0602A260E026600F524C5 /* PBXTargetDependency */,
4ECA497028FD590000085365 /* PBXTargetDependency */,
);
name = JitsiMeet;
productName = "Jitsi Meet";
@@ -403,15 +473,32 @@
productReference = 4EB06023260E026600F524C5 /* JitsiMeetBroadcastExtension.appex */;
productType = "com.apple.product-type.app-extension";
};
4ECA496328FD590000085365 /* WidgetsExtension */ = {
isa = PBXNativeTarget;
buildConfigurationList = 4ECA497428FD590100085365 /* Build configuration list for PBXNativeTarget "WidgetsExtension" */;
buildPhases = (
4ECA496028FD590000085365 /* Sources */,
4ECA496128FD590000085365 /* Frameworks */,
4ECA496228FD590000085365 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = WidgetsExtension;
productName = WidgetsExtension;
productReference = 4ECA496428FD590000085365 /* WidgetsExtension.appex */;
productType = "com.apple.product-type.app-extension";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
83CBB9F71A601CBA00E9B192 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1240;
LastSwiftUpdateCheck = 1400;
LastUpgradeCheck = 1020;
ORGANIZATIONNAME = Facebook;
ORGANIZATIONNAME = "";
TargetAttributes = {
0BEA5C241F7B8F73000D0AB4 = {
CreatedOnToolsVersion = 9.0;
@@ -424,6 +511,7 @@
ProvisioningStyle = Automatic;
};
13B07F861A680F5B00A75B9A = {
LastSwiftMigration = 1400;
SystemCapabilities = {
com.apple.SafariKeychain = {
enabled = 1;
@@ -436,6 +524,9 @@
4EB06022260E026600F524C5 = {
CreatedOnToolsVersion = 12.4;
};
4ECA496328FD590000085365 = {
CreatedOnToolsVersion = 14.0.1;
};
};
};
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "app" */;
@@ -455,6 +546,7 @@
0BEA5C241F7B8F73000D0AB4 /* JitsiMeetCompanion */,
0BEA5C301F7B8F73000D0AB4 /* JitsiMeetCompanion Extension */,
4EB06022260E026600F524C5 /* JitsiMeetBroadcastExtension */,
4ECA496328FD590000085365 /* WidgetsExtension */,
);
};
/* End PBXProject section */
@@ -494,6 +586,14 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
4ECA496228FD590000085365 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
4ECA496D28FD590000085365 /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
@@ -543,7 +643,7 @@
shellPath = /bin/sh;
shellScript = "if test \"$PRODUCT_BUNDLE_IDENTIFIER\" = \"com.atlassian.JitsiMeet.ios\"; then\n ENTITLEMENTS_PLIST=\"$PROJECT_DIR/app.entitlements\"\n \n /usr/libexec/PlistBuddy -c \"Add :com.apple.developer.avfoundation.multitasking-camera-access bool 1\" $ENTITLEMENTS_PLIST\nfi\n";
};
69BC5020DBE393B56BD76636 /* [CP] Check Pods Manifest.lock */ = {
58E2CB346F2C2A873294F481 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@@ -642,8 +742,10 @@
files = (
0B412F1F1EDEE6E800B1A0A6 /* ViewController.m in Sources */,
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,
4EBB458E2902E85B00855769 /* WidgetKitHelper.swift in Sources */,
DE4C456121DE1E4E00EA0709 /* FIRUtilities.m in Sources */,
13B07FC11A68108700A75B9A /* main.m in Sources */,
4EBB458A28FFFD4100855769 /* RoutesHandler.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -659,6 +761,19 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
4ECA496028FD590000085365 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
4ECA496B28FD590000085365 /* Widgets.swift in Sources */,
4E6920B828FD84D700645D9E /* DarwinNotificationsObserver.swift in Sources */,
4E46D954290FF55600761DEF /* LockScreenLeaveMeetingWidget.swift in Sources */,
4EA73DA3290C1D6C00A16FF8 /* MeetingState.swift in Sources */,
4E6A3E17291024B900E6B0B5 /* Provider.swift in Sources */,
4E46D952290FF39E00761DEF /* LockScreenMuteAudioWidget.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
@@ -677,6 +792,11 @@
target = 4EB06022260E026600F524C5 /* JitsiMeetBroadcastExtension */;
targetProxy = 4EB06029260E026600F524C5 /* PBXContainerItemProxy */;
};
4ECA497028FD590000085365 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 4ECA496328FD590000085365 /* WidgetsExtension */;
targetProxy = 4ECA496F28FD590000085365 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
@@ -845,11 +965,12 @@
};
13B07F941A680F5B00A75B9A /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 756FCE06C08D9B947653C98A /* Pods-JitsiMeet.debug.xcconfig */;
baseConfigurationReference = 7052390E12D7319D36D8E4CA /* Pods-JitsiMeet.debug.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIconDebug;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = app.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
@@ -871,16 +992,20 @@
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.meet;
PRODUCT_NAME = "jitsi-meet";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "src/JitsiMeet-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
};
name = Debug;
};
13B07F951A680F5B00A75B9A /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 3E0F4ED943C0B12BE77F6B45 /* Pods-JitsiMeet.release.xcconfig */;
baseConfigurationReference = 8CAA3C5A38E868335D1C1EC1 /* Pods-JitsiMeet.release.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIconRelease;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = app.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
@@ -901,6 +1026,8 @@
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.meet;
PRODUCT_NAME = "jitsi-meet";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "src/JitsiMeet-Bridging-Header.h";
SWIFT_VERSION = 5.0;
};
name = Release;
};
@@ -973,6 +1100,91 @@
};
name = Release;
};
4ECA497228FD590100085365 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = WidgetsExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = FC967L3QRG;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "Widgets Extension/Info.plist";
INFOPLIST_KEY_CFBundleDisplayName = Widgets;
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2022 Facebook. All rights reserved.";
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.meet.widgets.extension;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
4ECA497328FD590100085365 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = WidgetsExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = FC967L3QRG;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "Widgets Extension/Info.plist";
INFOPLIST_KEY_CFBundleDisplayName = Widgets;
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2022 Facebook. All rights reserved.";
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.meet.widgets.extension;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
83CBBA201A601CBA00E9B192 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -1126,6 +1338,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
4ECA497428FD590100085365 /* Build configuration list for PBXNativeTarget "WidgetsExtension" */ = {
isa = XCConfigurationList;
buildConfigurations = (
4ECA497228FD590100085365 /* Debug */,
4ECA497328FD590100085365 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "app" */ = {
isa = XCConfigurationList;
buildConfigurations = (

View File

@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1400"
wasCreatedForAppExtension = "YES"
version = "2.0">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4ECA496328FD590000085365"
BuildableName = "WidgetsExtension.appex"
BlueprintName = "WidgetsExtension"
ReferencedContainer = "container:app.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "jitsi-meet.app"
BlueprintName = "JitsiMeet"
ReferencedContainer = "container:app.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = ""
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
launchStyle = "0"
askForAppToLaunch = "Yes"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES"
launchAutomaticallySubstyle = "2">
<RemoteRunnable
runnableDebuggingMode = "2"
BundleIdentifier = "com.apple.springboard">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4ECA496328FD590000085365"
BuildableName = "WidgetsExtension.appex"
BlueprintName = "WidgetsExtension"
ReferencedContainer = "container:app.xcodeproj">
</BuildableReference>
</RemoteRunnable>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "jitsi-meet.app"
BlueprintName = "JitsiMeet"
ReferencedContainer = "container:app.xcodeproj">
</BuildableReference>
</MacroExpansion>
<EnvironmentVariables>
<EnvironmentVariable
key = "_XCWidgetKind"
value = "LockScreenLeaveMeetingWidget"
isEnabled = "YES">
</EnvironmentVariable>
<EnvironmentVariable
key = "_XCWidgetDefaultView"
value = "timeline"
isEnabled = "NO">
</EnvironmentVariable>
<EnvironmentVariable
key = "_XCWidgetFamily"
value = "medium"
isEnabled = "NO">
</EnvironmentVariable>
</EnvironmentVariables>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES"
askForAppToLaunch = "Yes"
launchAutomaticallySubstyle = "2">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "jitsi-meet.app"
BlueprintName = "JitsiMeet"
ReferencedContainer = "container:app.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@@ -17,6 +17,7 @@
#import "AppDelegate.h"
#import "FIRUtilities.h"
#import "RoutesHandler.h"
#import "Types.h"
#import "ViewController.h"
@@ -69,7 +70,7 @@
- (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> *restorableObjects))restorationHandler {
if ([FIRUtilities appContainsRealServiceInfoPlist]) {
// 1. Attempt to handle Universal Links through Firebase in order to support
// its Dynamic Links (which we utilize for the purposes of deferred deep
@@ -107,6 +108,10 @@
if ([[url absoluteString] containsString:@"google/link/?dismiss=1&is_weak_match=1"]) {
return NO;
}
if ([[RoutesHandler sharedInstance] routeURL:url]) {
return YES;
}
NSURL *openUrl = url;

View File

@@ -1,6 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
"author" : "xcode",
"version" : 1
}
}
}

View File

@@ -0,0 +1,4 @@
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//

View File

@@ -0,0 +1,27 @@
//
// RoutesHandler.h
// JitsiMeet
//
// Created by Alex Bumbu on 19.10.2022.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@protocol RouteObserving <NSObject>
@property (nonatomic, readonly) void (^didRouteCallback)(NSString *route);
@end
@interface RoutesHandler : NSObject
+ (instancetype)sharedInstance;
- (void)registerObserver:(id<RouteObserving>)observer forRoute:(NSString *)route;
- (void)unregisterObserver:(id<RouteObserving>)observer;
- (BOOL)routeURL:(NSURL *)url;
@end
NS_ASSUME_NONNULL_END

123
ios/app/src/RoutesHandler.m Normal file
View File

@@ -0,0 +1,123 @@
//
// RoutesHandler.m
// JitsiMeet
//
// Created by Alex Bumbu on 19.10.2022.
//
#import "RoutesHandler.h"
@protocol Routing <NSObject>
@property (nonatomic, readonly) NSString *route;
@property (nonatomic, readonly) id<RouteObserving> observer;
@end
@interface Route: NSObject <Routing>
@property (nonatomic, readonly) NSString *route;
@property (nonatomic, readonly, weak) id<RouteObserving> observer;
+ (instancetype)routeWithString:(nonnull NSString *)route observer:(id<RouteObserving>)observer;
@end
#pragma mark -
@implementation RoutesHandler {
NSMutableArray *routes;
}
+ (instancetype)sharedInstance {
static RoutesHandler *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
- (instancetype)init {
self = [super init];
if (self) {
routes = [[NSMutableArray alloc] init];
}
return self;
}
- (void)registerObserver:(id<RouteObserving>)observer forRoute:(NSString *)route {
[routes addObject:[Route routeWithString:route observer:observer]];
}
- (void)unregisterObserver:(id<RouteObserving>)observer {
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id<Routing> _Nullable evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
return evaluatedObject.observer == nil || evaluatedObject.observer == observer;
}];
NSArray *routesToClear = [routes filteredArrayUsingPredicate:predicate];
[routes removeObjectsInArray:routesToClear];
}
- (BOOL)routeURL:(NSURL *)url {
[self clearRoutes];
NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:false];
if (!components) {
return false;
}
NSString *route = components.path;
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id<Routing> _Nullable evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
return [evaluatedObject.route isEqualToString:route];
}];
NSArray *routesToHandle = [routes filteredArrayUsingPredicate:predicate];
if ([routesToHandle count] == 0) {
return false;
}
for (id<Routing> route in routesToHandle) {
route.observer.didRouteCallback(route.route);
}
return true;
}
- (void)clearRoutes {
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id<Routing> _Nullable evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
return evaluatedObject.observer == nil;
}];
NSArray *routesToClear = [routes filteredArrayUsingPredicate:predicate];
[routes removeObjectsInArray:routesToClear];
}
@end
#pragma mark -
@interface Route()
@property (nonatomic, nonnull, copy) NSString *route;
@property (nonatomic, weak) id<RouteObserving> observer;
@end
@implementation Route
+ (instancetype)routeWithString:(nonnull NSString *)route observer:(nonnull id<RouteObserving>)observer {
return [[Route alloc] initWithString:route observer:observer];
}
- (instancetype)initWithString:(nonnull NSString *)route observer:(nonnull id<RouteObserving>)observer {
self = [super init];
if (self) {
self.route = route;
self.observer = observer;
}
return self;
}
@end

View File

@@ -21,8 +21,16 @@
@import JitsiMeetSDK;
#import "Types.h"
#import "RoutesHandler.h"
#import "ViewController.h"
#import "jitsi_meet-Swift.h"
@interface ViewController() <RouteObserving>
@property (nonatomic, nonnull, copy) void (^didRouteCallback)(NSString *);
@property (nonatomic, assign) BOOL audioMuted;
@end
@implementation ViewController
@@ -33,6 +41,8 @@
view.delegate = self;
[view join:[[JitsiMeet sharedInstance] getInitialConferenceOptions]];
[self registerRouteObserver];
}
// JitsiMeetViewDelegate
@@ -53,6 +63,10 @@
- (void)conferenceJoined:(NSDictionary *)data {
[self _onJitsiMeetViewDelegateEvent:@"CONFERENCE_JOINED" withData:data];
self.audioMuted = [[data objectForKey:@"isAudioMuted"] boolValue];
[self refreshWidgetState:self.audioMuted];
// Register a NSUserActivity for this conference so it can be invoked as a
// Siri shortcut.
@@ -82,6 +96,12 @@
- (void)conferenceTerminated:(NSDictionary *)data {
[self _onJitsiMeetViewDelegateEvent:@"CONFERENCE_TERMINATED" withData:data];
NSURL *sharedContainer = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.org.jitsi.meet.appgroup"];
NSURL *widgetStateFileURL = [sharedContainer URLByAppendingPathComponent:@"widgetState"];
[[NSFileManager defaultManager] removeItemAtURL:widgetStateFileURL error:nil];
[WidgetKitHelper reloadAllWidgets];
}
- (void)conferenceWillJoin:(NSDictionary *)data {
@@ -107,7 +127,16 @@
}
- (void)audioMutedChanged:(NSDictionary *)data {
NSLog(@"%@%@", @"Audio muted changed: ", data[@"muted"]);
NSLog(@"%@%@", @"Audio muted changed: ", data[@"muted"]);
// CFNotificationCenterRef notificationCenter = CFNotificationCenterGetDarwinNotifyCenter();
// CFNotificationCenterPostNotification(notificationCenter,
// (__bridge CFStringRef)@"iOS_MeetingMutedChanged",
// NULL,
// NULL,
// true);
self.audioMuted = [[data objectForKey:@"muted"] boolValue];
[self refreshWidgetState:self.audioMuted];
}
- (void)endpointTextMessageReceived:(NSDictionary *)data {
@@ -132,9 +161,40 @@
#pragma mark - Helpers
- (void)registerRouteObserver {
__weak typeof(self) weakSelf = self;
__weak JitsiMeetView *view = (JitsiMeetView *)self.view;
self.didRouteCallback = ^(NSString *route) {
if ([route isEqual:@"meet/toggleAudioMute"]) {
weakSelf.audioMuted = !weakSelf.audioMuted;
[view setAudioMuted:weakSelf.audioMuted];
} else if ([route isEqualToString:@"meet/leaveMeeting"]) {
[weakSelf terminate];
}
};
[[RoutesHandler sharedInstance] registerObserver:self forRoute:@"meet/toggleAudioMute"];
[[RoutesHandler sharedInstance] registerObserver:self forRoute:@"meet/leaveMeeting"];
}
- (void)terminate {
JitsiMeetView *view = (JitsiMeetView *) self.view;
[view leave];
}
- (void)refreshWidgetState:(BOOL)audioMuted {
// let sharedContainer = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: Constants.appGroupIdentifier)
// return sharedContainer?.appendingPathComponent("rtc_SSFD").path ?? ""
NSURL *sharedContainer = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.org.jitsi.meet.appgroup"];
NSURL *widgetStateFileURL = [sharedContainer URLByAppendingPathComponent:@"widgetState"];
NSDictionary *meetingState = @{@"audioMuted": @(audioMuted)};
if (![meetingState writeToURL:widgetStateFileURL atomically:true]) {
NSLog(@"error saving state file");
}
[WidgetKitHelper reloadAllWidgets];
}
@end

View File

@@ -0,0 +1,20 @@
//
// WidgetKitHelper.swift
// JitsiMeet
//
// Created by Alex Bumbu on 21.10.2022.
//
import WidgetKit
@available(iOS 14.0, *)
@objcMembers final class WidgetKitHelper: NSObject {
class func reloadAllWidgets(){
#if arch(arm64) || arch(i386) || arch(x86_64)
WidgetCenter.shared.reloadAllTimelines()
#endif
}
}

View File

@@ -57,8 +57,8 @@
openURL:(NSURL *_Nonnull)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *_Nonnull)options;
- (UIInterfaceOrientationMask)application:(UIApplication *)application
supportedInterfaceOrientationsForWindow:(UIWindow *)window;
- (UIInterfaceOrientationMask)application:(UIApplication *_Nonnull)application
supportedInterfaceOrientationsForWindow:(UIWindow *_Nonnull)window;
#pragma mark - Utility methods

View File

@@ -26,7 +26,6 @@
"hsb": "Hornjoserbšćina",
"hu": "Magyar",
"hy": "Հայերեն",
"id": "Bahasa Indonesia",
"is": "Íslenska",
"it": "Italiano",
"ja": "日本語",
@@ -37,7 +36,6 @@
"ml": "മലയാളം",
"mn": "Монгол",
"mr": "मराठी",
"nb": "Norsk Bokmål",
"nl": "Nederlands",
"oc": "Occitan",
"pl": "Polski",

View File

@@ -71,7 +71,7 @@
"titleWithPolls": "Εισάγετε ένα ψευδώνυμο για τη χρήση της συνομιλίας"
},
"noMessagesMessage": "Δεν υπάρχουν μηνύματα στη συνάντηση ακόμα. Ξεκινήστε μια συζήτηση εδώ!",
"privateNotice": "Ιδιωτικό μηνύμα στον / στην {recipient}}",
"privateNotice": "Ιδιωτικό μηνύμα στον / στην {{recipient}}",
"sendButton": "Στείλτε",
"title": "Συνομιλία",
"titleWithPolls": "Συνομιλία",
@@ -517,7 +517,7 @@
"oldElectronClientDescription3": " τώρα!",
"passwordRemovedRemotely": "Το $t(lockRoomPasswordUppercase) αφαιρέθηκε από έναν άλλον συμμετέχοντα",
"passwordSetRemotely": "Το $t(lockRoomPasswordUppercase) ορίστηκε από άλλον συμμετέχοντα",
"raisedHand": "Ο/Η {{name}} θα ήθελε να μιλήσει.",
"raisedHand": "Ο/Η {{participantDisplayName}} θα ήθελε να μιλήσει.",
"somebody": "Κάποιος",
"startSilentDescription": "Ξαναμπείτε στη συνάντηση για να ενεργοποιήσετε τον ήχο",
"startSilentTitle": "Μπήκες χωρίς συσκευή εξόδου ήχου!",

View File

@@ -1,791 +0,0 @@
{
"addPeople": {
"add": "Undang",
"countryNotSupported": "Negara ini belum tersedia.",
"countryReminder": "Memanggil di luar negara AS? Pastikan dengan menggunakan kode negara!",
"disabled": "Kamu tidak dapat mengundang.",
"failedToAdd": "Gagal menambahkan peserta",
"footerText": "Panggilan keluar di-nonaktifkan.",
"loading": "Sedang mencari orang dan nomor telepon.",
"loadingNumber": "Memvalidasi nomor telepon",
"loadingPeople": "Mencari orang untuk diundang",
"noResults": "Tidak ada pencarian yang cocok.",
"noValidNumbers": "Masukkan nomor telepon yang benar.",
"searchNumbers": "Mencari nomor telepon",
"searchPeople": "Mencari orang",
"searchPeopleAndNumbers": "Cari orang beserta nomor teleponnya",
"telephone": "Telepon: {{number}}",
"title": "Undang orang-orang ke sini."
},
"audioDevices": {
"bluetooth": "Bluetooth",
"headphones": "Headphones",
"none": "Perangkat suara tidak tersedia",
"phone": "Telepon",
"speaker": "Pengeras suara"
},
"audioOnly": {
"audioOnly": "Suara saja"
},
"calendarSync": {
"addMeetingURL": "Buat link pertemuan",
"confirmAddLink": "Tambahkan link Jitsi pada event ini?",
"error": {
"appConfiguration": "Ada konfigurasi yang tidak tepat.",
"generic": "Kesalahan terjadi. Cek pengaturan atau coba lakukan refresh.",
"notSignedIn": "Kesalahan berkaitan dengan autentikasi pada event. Cek pengaturan dan coba lagi"
},
"join": "Gabung",
"joinTooltip": "Gabung di pertemuan",
"nextMeeting": "Pertemuan Berikutnya",
"noEvents": "Belum ada event tersedia.",
"ongoingMeeting": "Pertemuan yang sedang berjalan",
"permissionButton": "Buka Pengaturan",
"permissionMessage": "Setelan permisi diperlukan untuk melihat pertemuan.",
"refresh": "Muat ulang",
"today": "Hari ini"
},
"chat": {
"error": "Error: your message was not sent. Reason: {{error}}",
"fieldPlaceHolder": "Type your message here",
"messageTo": "Private message to {{recipient}}",
"messagebox": "Type a message",
"nickname": {
"popover": "Choose a nickname",
"title": "Enter a nickname to use chat",
"titleWithPolls": "Enter a nickname to use chat"
},
"noMessagesMessage": "There are no messages in the meeting yet. Start a conversation here!",
"privateNotice": "Private message to {{recipient}}",
"sendButton": "Kirim",
"title": "Chat",
"titleWithPolls": "Chat",
"you": "you"
},
"chromeExtensionBanner": {
"buttonText": "Install Chrome Extension",
"dontShowAgain": "Dont show me this again",
"installExtensionText": "Install the extension for Google Calendar and Office 365 integration"
},
"connectingOverlay": {
"joiningRoom": "Connecting you to your meeting..."
},
"connection": {
"ATTACHED": "Attached",
"AUTHENTICATING": "Authenticating",
"AUTHFAIL": "Authentication failed",
"CONNECTED": "Connected",
"CONNECTING": "Connecting",
"CONNFAIL": "Connection failed",
"DISCONNECTED": "Disconnected",
"DISCONNECTING": "Disconnecting",
"ERROR": "Error",
"FETCH_SESSION_ID": "Obtaining session-id...",
"GET_SESSION_ID_ERROR": "Get session-id error: {{code}}",
"GOT_SESSION_ID": "Obtaining session-id... Done",
"LOW_BANDWIDTH": "Video for {{displayName}} has been turned off to save bandwidth"
},
"connectionindicator": {
"address": "Address:",
"bandwidth": "Estimated bandwidth:",
"bitrate": "Bitrate:",
"bridgeCount": "Server count: ",
"connectedTo": "Connected to:",
"framerate": "Frame rate:",
"less": "Show less",
"localaddress": "Local address:",
"localaddress_plural": "Local addresses:",
"localport": "Local port:",
"localport_plural": "Local ports:",
"more": "Show more",
"packetloss": "Packet loss:",
"quality": {
"good": "Good",
"inactive": "Inactive",
"lost": "Lost",
"nonoptimal": "Nonoptimal",
"poor": "Poor"
},
"remoteaddress": "Remote address:",
"remoteaddress_plural": "Remote addresses:",
"remoteport": "Remote port:",
"remoteport_plural": "Remote ports:",
"resolution": "Resolution:",
"status": "Connection:",
"transport": "Transport:",
"transport_plural": "Transports:"
},
"dateUtils": {
"earlier": "Earlier",
"today": "Today",
"yesterday": "Yesterday"
},
"deepLinking": {
"appNotInstalled": "You need the {{app}} mobile app to join this meeting on your phone.",
"description": "Nothing happened? We tried launching your meeting in the {{app}} desktop app. Try again or launch it in the {{app}} web app.",
"descriptionWithoutWeb": "Nothing happened? We tried launching your meeting in the {{app}} desktop app.",
"downloadApp": "Download the app",
"launchWebButton": "Launch in web",
"openApp": "Continue to the app",
"title": "Launching your meeting in {{app}}...",
"tryAgainButton": "Try again in desktop"
},
"defaultLink": "e.g. {{url}}",
"defaultNickname": "ex. Jane Pink",
"deviceError": {
"cameraError": "Failed to access your camera",
"cameraPermission": "Error obtaining camera permission",
"microphoneError": "Failed to access your microphone",
"microphonePermission": "Error obtaining microphone permission"
},
"deviceSelection": {
"noPermission": "Permission not granted",
"previewUnavailable": "Preview unavailable",
"selectADevice": "Select a device",
"testAudio": "Play a test sound"
},
"dialOut": {
"statusMessage": "is now {{status}}"
},
"dialog": {
"Back": "Back",
"Cancel": "Cancel",
"IamHost": "I am the host",
"Ok": "Ok",
"Remove": "Remove",
"Share": "Share",
"Submit": "Submit",
"WaitForHostMsg": "The conference has not yet started. If you are the host then please authenticate. Otherwise, please wait for the host to arrive.",
"WaitingForHost": "Waiting for the host ...",
"Yes": "Yes",
"accessibilityLabel": {
"liveStreaming": "Live Stream"
},
"allow": "Allow",
"alreadySharedVideoMsg": "Another participant is already sharing a video. This conference allows only one shared video at a time.",
"alreadySharedVideoTitle": "Only one shared video is allowed at a time",
"applicationWindow": "Application window",
"cameraConstraintFailedError": "Your camera does not satisfy some of the required constraints.",
"cameraNotFoundError": "Camera was not found.",
"cameraNotSendingData": "We are unable to access your camera. Please check if another application is using this device, select another device from the settings menu or try to reload the application.",
"cameraNotSendingDataTitle": "Unable to access camera",
"cameraPermissionDeniedError": "You have not granted permission to use your camera. You can still join the conference but others won't see you. Use the camera button in the address bar to fix this.",
"cameraUnknownError": "Cannot use camera for an unknown reason.",
"cameraUnsupportedResolutionError": "Your camera does not support required video resolution.",
"close": "Close",
"conferenceDisconnectMsg": "You may want to check your network connection. Reconnecting in {{seconds}} sec...",
"conferenceDisconnectTitle": "You have been disconnected.",
"conferenceReloadMsg": "We're trying to fix this. Reconnecting in {{seconds}} sec...",
"conferenceReloadTitle": "Unfortunately, something went wrong.",
"confirm": "Confirm",
"confirmNo": "No",
"confirmYes": "Yes",
"connectError": "Oops! Something went wrong and we couldn't connect to the conference.",
"connectErrorWithMsg": "Oops! Something went wrong and we couldn't connect to the conference: {{msg}}",
"connecting": "Connecting",
"contactSupport": "Contact support",
"copy": "Copy",
"dismiss": "Dismiss",
"displayNameRequired": "Hi! Whats your name?",
"done": "Done",
"enterDisplayName": "Enter your name here",
"error": "Error",
"externalInstallationMsg": "You need to install our desktop sharing extension.",
"externalInstallationTitle": "Extension required",
"goToStore": "Go to the webstore",
"gracefulShutdown": "Our service is currently down for maintenance. Please try again later.",
"incorrectPassword": "Incorrect username or password",
"incorrectRoomLockPassword": "Incorrect password",
"inlineInstallExtension": "Install now",
"inlineInstallationMsg": "You need to install our desktop sharing extension.",
"internalError": "Oops! Something went wrong. The following error occurred: {{error}}",
"internalErrorTitle": "Internal error",
"kickMessage": "You can contact {{participantDisplayName}} for more details.",
"kickParticipantButton": "Kick",
"kickParticipantDialog": "Are you sure you want to kick this participant?",
"kickParticipantTitle": "Kick this participant?",
"kickTitle": "Ouch! {{participantDisplayName}} kicked you out of the meeting",
"liveStreaming": "Live Streaming",
"liveStreamingDisabledForGuestTooltip": "Guests can't start live streaming.",
"liveStreamingDisabledTooltip": "Start live stream disabled.",
"lockMessage": "Failed to lock the conference.",
"lockRoom": "Add meeting $t(lockRoomPasswordUppercase)",
"lockTitle": "Lock failed",
"logoutQuestion": "Are you sure you want to logout and stop the conference?",
"logoutTitle": "Logout",
"maxUsersLimitReached": "The limit for maximum number of participants has been reached. The conference is full. Please contact the meeting owner or try again later!",
"maxUsersLimitReachedTitle": "Maximum participants limit reached",
"micConstraintFailedError": "Your microphone does not satisfy some of the required constraints.",
"micNotFoundError": "Microphone was not found.",
"micNotSendingData": "Go to your computer's settings to unmute your mic and adjust its level",
"micNotSendingDataTitle": "Your mic is muted by your system settings",
"micPermissionDeniedError": "You have not granted permission to use your microphone. You can still join the conference but others won't hear you. Use the camera button in the address bar to fix this.",
"micUnknownError": "Cannot use microphone for an unknown reason.",
"muteEveryoneDialog": "Are you sure you want to mute everyone? You won't be able to unmute them, but they can unmute themselves at any time.",
"muteEveryoneElseDialog": "Once muted, you won't be able to unmute them, but they can unmute themselves at any time.",
"muteEveryoneElseTitle": "Mute everyone except {{whom}}?",
"muteEveryoneSelf": "yourself",
"muteEveryoneStartMuted": "Everyone starts muted from now on",
"muteEveryoneTitle": "Mute everyone?",
"muteParticipantBody": "You won't be able to unmute them, but they can unmute themselves at any time.",
"muteParticipantButton": "Mute",
"muteParticipantDialog": "Are you sure you want to mute this participant? You won't be able to unmute them, but they can unmute themselves at any time.",
"muteParticipantTitle": "Mute this participant?",
"passwordLabel": "The meeting has been locked by a participant. Please enter the $t(lockRoomPassword) to join.",
"passwordNotSupported": "Setting a meeting $t(lockRoomPassword) is not supported.",
"passwordNotSupportedTitle": "$t(lockRoomPasswordUppercase) not supported",
"passwordRequired": "$t(lockRoomPasswordUppercase) required",
"popupError": "Your browser is blocking pop-up windows from this site. Please enable pop-ups in your browser's security settings and try again.",
"popupErrorTitle": "Pop-up blocked",
"recording": "Recording",
"recordingDisabledForGuestTooltip": "Guests can't start recordings.",
"recordingDisabledTooltip": "Start recording disabled.",
"rejoinNow": "Rejoin now",
"remoteControlAllowedMessage": "{{user}} accepted your remote control request!",
"remoteControlDeniedMessage": "{{user}} rejected your remote control request!",
"remoteControlErrorMessage": "An error occurred while trying to request remote control permissions from {{user}}!",
"remoteControlRequestMessage": "Will you allow {{user}} to remotely control your desktop?",
"remoteControlShareScreenWarning": "Note that if you press \"Allow\" you will share your screen!",
"remoteControlStopMessage": "The remote control session ended!",
"remoteControlTitle": "Remote desktop control",
"removePassword": "Remove $t(lockRoomPassword)",
"removeSharedVideoMsg": "Are you sure you would like to remove your shared video?",
"removeSharedVideoTitle": "Remove shared video",
"reservationError": "Reservation system error",
"reservationErrorMsg": "Error code: {{code}}, message: {{msg}}",
"retry": "Retry",
"screenSharingAudio": "Share audio",
"screenSharingFailedToInstall": "Oops! Your screen sharing extension failed to install.",
"screenSharingFailedToInstallTitle": "Screen sharing extension failed to install",
"screenSharingFirefoxPermissionDeniedError": "Something went wrong while we were trying to share your screen. Please make sure that you have given us permission to do so. ",
"screenSharingFirefoxPermissionDeniedTitle": "Oops! We werent able to start screen sharing!",
"screenSharingPermissionDeniedError": "Oops! Something went wrong with your screen sharing extension permissions. Please reload and try again.",
"sendPrivateMessage": "You recently received a private message. Did you intend to reply to that privately, or you want to send your message to the group?",
"sendPrivateMessageCancel": "Send to the group",
"sendPrivateMessageOk": "Send privately",
"sendPrivateMessageTitle": "Send privately?",
"serviceUnavailable": "Service unavailable",
"sessTerminated": "Call terminated",
"shareVideoLinkError": "Please provide a correct link.",
"shareVideoTitle": "Share a video",
"shareYourScreen": "Share your screen",
"shareYourScreenDisabled": "Screen sharing disabled.",
"shareYourScreenDisabledForGuest": "Guests can't screen share.",
"startLiveStreaming": "Start live stream",
"startRecording": "Start recording",
"startRemoteControlErrorMessage": "An error occurred while trying to start the remote control session!",
"stopLiveStreaming": "Stop live stream",
"stopRecording": "Stop recording",
"stopRecordingWarning": "Are you sure you would like to stop the recording?",
"stopStreamingWarning": "Are you sure you would like to stop the live streaming?",
"streamKey": "Live stream key",
"thankYou": "Thank you for using {{appName}}!",
"token": "token",
"tokenAuthFailed": "Sorry, you're not allowed to join this call.",
"tokenAuthFailedTitle": "Authentication failed",
"transcribing": "Transcribing",
"unlockRoom": "Remove meeting $t(lockRoomPassword)",
"userPassword": "user password",
"yourEntireScreen": "Your entire screen"
},
"documentSharing": {
"title": "Shared Document"
},
"feedback": {
"average": "Average",
"bad": "Bad",
"detailsLabel": "Tell us more about it.",
"good": "Good",
"rateExperience": "Rate your meeting experience",
"veryBad": "Very Bad",
"veryGood": "Very Good"
},
"helpView": {
"title": "Help centre"
},
"incomingCall": {
"answer": "Answer",
"audioCallTitle": "Incoming call",
"decline": "Dismiss",
"productLabel": "from Jitsi Meet",
"videoCallTitle": "Incoming video call"
},
"info": {
"accessibilityLabel": "Show info",
"addPassword": "Add $t(lockRoomPassword)",
"cancelPassword": "Cancel $t(lockRoomPassword)",
"conferenceURL": "Link:",
"country": "Country",
"dialANumber": "To join your meeting, dial one of these numbers and then enter the pin.",
"dialInConferenceID": "PIN:",
"dialInNotSupported": "Sorry, dialing in is currently not supported.",
"dialInNumber": "Dial-in:",
"dialInSummaryError": "Error fetching dial-in info now. Please try again later.",
"dialInTollFree": "Toll Free",
"genericError": "Whoops, something went wrong.",
"inviteLiveStream": "To view the live stream of this meeting, click this link: {{url}}",
"invitePhone": "To join by phone instead, tap this: {{number}},,{{conferenceID}}#\n",
"invitePhoneAlternatives": "Looking for a different dial-in number?\nSee meeting dial-in numbers: {{url}}\n\n\nIf also dialing-in through a room phone, join without connecting to audio: {{silentUrl}}",
"inviteURLFirstPartGeneral": "You are invited to join a meeting.",
"inviteURLFirstPartPersonal": "{{name}} is inviting you to a meeting.\n",
"inviteURLSecondPart": "\nJoin the meeting:\n{{url}}\n",
"label": "Meeting info",
"liveStreamURL": "Live stream:",
"moreNumbers": "More numbers",
"noNumbers": "No dial-in numbers.",
"noPassword": "None",
"noRoom": "No room was specified to dial-in into.",
"numbers": "Dial-in Numbers",
"password": "$t(lockRoomPasswordUppercase):",
"title": "Share",
"tooltip": "Share link and dial-in info for this meeting"
},
"inlineDialogFailure": {
"msg": "We stumbled a bit.",
"retry": "Try again",
"support": "Support",
"supportMsg": "If this keeps happening, reach out to"
},
"inviteDialog": {
"alertText": "Failed to invite some participants.",
"header": "Invite",
"searchCallOnlyPlaceholder": "Enter phone number",
"searchPeopleOnlyPlaceholder": "Search for participants",
"searchPlaceholder": "Participant or phone number",
"send": "Kirim"
},
"keyboardShortcuts": {
"focusLocal": "Focus on your video",
"focusRemote": "Focus on another person's video",
"fullScreen": "View or exit full screen",
"keyboardShortcuts": "Keyboard shortcuts",
"localRecording": "Show or hide local recording controls",
"mute": "Mute or unmute your microphone",
"pushToTalk": "Push to talk",
"raiseHand": "Raise or lower your hand",
"showSpeakerStats": "Show speaker stats",
"toggleChat": "Open or close the chat",
"toggleFilmstrip": "Show or hide video thumbnails",
"toggleScreensharing": "Switch between camera and screen sharing",
"toggleShortcuts": "Show or hide keyboard shortcuts",
"videoMute": "Start or stop your camera",
"videoQuality": "Manage call quality"
},
"liveStreaming": {
"busy": "We're working on freeing streaming resources. Please try again in a few minutes.",
"busyTitle": "All streamers are currently busy",
"changeSignIn": "Switch accounts.",
"choose": "Choose a live stream",
"chooseCTA": "Choose a streaming option. You're currently logged in as {{email}}.",
"enterStreamKey": "Enter your YouTube live stream key here.",
"error": "Live Streaming failed. Please try again.",
"errorAPI": "An error occurred while accessing your YouTube broadcasts. Please try logging in again.",
"errorLiveStreamNotEnabled": "Live Streaming is not enabled on {{email}}. Please enable live streaming or log into an account with live streaming enabled.",
"expandedOff": "The live streaming has stopped",
"expandedOn": "The meeting is currently being streamed to YouTube.",
"expandedPending": "The live streaming is being started...",
"failedToStart": "Live Streaming failed to start",
"getStreamKeyManually": "We werent able to fetch any live streams. Try getting your live stream key from YouTube.",
"googlePrivacyPolicy": "Google Privacy Policy",
"invalidStreamKey": "Live stream key may be incorrect.",
"off": "Live Streaming stopped",
"offBy": "{{name}} stopped the live streaming",
"on": "Live Streaming",
"onBy": "{{name}} started the live streaming",
"pending": "Starting Live Stream...",
"serviceName": "Live Streaming service",
"signIn": "Sign in with Google",
"signInCTA": "Sign in or enter your live stream key from YouTube.",
"signOut": "Sign out",
"signedInAs": "You are currently signed in as:",
"start": "Start a live stream",
"streamIdHelp": "What's this?",
"title": "Live Stream",
"unavailableTitle": "Live Streaming unavailable",
"youtubeTerms": "YouTube terms of services"
},
"localRecording": {
"clientState": {
"off": "Off",
"on": "On",
"unknown": "Unknown"
},
"dialogTitle": "Local Recording Controls",
"duration": "Duration",
"durationNA": "N/A",
"encoding": "Encoding",
"label": "LOR",
"labelToolTip": "Local recording is engaged",
"localRecording": "Local Recording",
"me": "Me",
"messages": {
"engaged": "Local recording engaged.",
"finished": "Recording session {{token}} finished. Please send the recorded file to the moderator.",
"finishedModerator": "Recording session {{token}} finished. The recording of the local track has been saved. Please ask the other participants to submit their recordings.",
"notModerator": "You are not the moderator. You cannot start or stop local recording."
},
"moderator": "Moderator",
"no": "No",
"participant": "Participant",
"participantStats": "Participant Stats",
"sessionToken": "Session Token",
"start": "Start Recording",
"stop": "Stop Recording",
"yes": "Yes"
},
"lockRoomPassword": "password",
"lockRoomPasswordUppercase": "Password",
"lonelyMeetingExperience": {
"button": "Invite others",
"youAreAlone": "You are the only one in the meeting"
},
"me": "me",
"notify": {
"OldElectronAPPTitle": "Security vulnerability!",
"connectedOneMember": "{{name}} joined the meeting",
"connectedThreePlusMembers": "{{name}} and {{count}} others joined the meeting",
"connectedTwoMembers": "{{first}} and {{second}} joined the meeting",
"disconnected": "disconnected",
"focus": "Conference focus",
"focusFail": "{{component}} not available - retry in {{ms}} sec",
"grantedTo": "Moderator rights granted to {{to}}!",
"invitedOneMember": "{{name}} has been invited",
"invitedThreePlusMembers": "{{name}} and {{count}} others have been invited",
"invitedTwoMembers": "{{first}} and {{second}} have been invited",
"kickParticipant": "{{kicked}} was kicked by {{kicker}}",
"me": "Me",
"moderator": "Moderator rights granted!",
"muted": "You have started the conversation muted.",
"mutedRemotelyDescription": "You can always unmute when you're ready to speak. Mute back when you're done to keep noise away from the meeting.",
"mutedRemotelyTitle": "You have been muted by {{participantDisplayName}}!",
"mutedTitle": "You're muted!",
"newDeviceAction": "Use",
"newDeviceAudioTitle": "New audio device detected",
"newDeviceCameraTitle": "New camera detected",
"oldElectronClientDescription1": "You appear to be using an old verion of the Jitsi Meet client which has known security vulnerabilities. Please make sure you update to our ",
"oldElectronClientDescription2": "latest build",
"oldElectronClientDescription3": " now!",
"passwordRemovedRemotely": "$t(lockRoomPasswordUppercase) removed by another participant",
"passwordSetRemotely": "$t(lockRoomPasswordUppercase) set by another participant",
"raisedHand": "{{name}} would like to speak.",
"somebody": "Somebody",
"startSilentDescription": "Rejoin the meeting to enable audio",
"startSilentTitle": "You joined with no audio output!",
"suboptimalBrowserWarning": "We are afraid your meeting experience isn't going to be that great here. We are looking for ways to improve this, but until then please try using one of the <a href='{{recommendedBrowserPageLink}}' target='_blank'>fully supported browsers</a>.",
"suboptimalExperienceTitle": "Browser Warning",
"unmute": "Unmute"
},
"passwordDigitsOnly": "Up to {{number}} digits",
"passwordSetRemotely": "set by another participant",
"poweredby": "powered by",
"presenceStatus": {
"busy": "Busy",
"calling": "Calling...",
"connected": "Connected",
"connecting": "Connecting...",
"connecting2": "Connecting*...",
"disconnected": "Disconnected",
"expired": "Expired",
"ignored": "Ignored",
"initializingCall": "Initializing Call...",
"invited": "Invited",
"rejected": "Rejected",
"ringing": "Ringing..."
},
"profile": {
"setDisplayNameLabel": "Set your display name",
"setEmailInput": "Enter email",
"setEmailLabel": "Set your gravatar email",
"title": "Profile"
},
"raisedHand": "Would like to speak",
"recording": {
"authDropboxText": "Upload to Dropbox",
"availableSpace": "Available space: {{spaceLeft}} MB (approximately {{duration}} minutes of recording)",
"beta": "BETA",
"busy": "We're working on freeing recording resources. Please try again in a few minutes.",
"busyTitle": "All recorders are currently busy",
"error": "Recording failed. Please try again.",
"expandedOff": "Recording has stopped",
"expandedOn": "The meeting is currently being recorded.",
"expandedPending": "Recording is being started...",
"failedToStart": "Recording failed to start",
"fileSharingdescription": "Share recording with meeting participants",
"live": "LIVE",
"loggedIn": "Logged in as {{userName}}",
"off": "Recording stopped",
"offBy": "{{name}} stopped the recording",
"on": "Recording",
"onBy": "{{name}} started the recording",
"pending": "Preparing to record the meeting...",
"rec": "REC",
"serviceDescription": "Your recording will be saved by the recording service",
"serviceName": "Recording service",
"signIn": "Sign in",
"signOut": "Sign out",
"title": "Recording",
"unavailable": "Oops! The {{serviceName}} is currently unavailable. We're working on resolving the issue. Please try again later.",
"unavailableTitle": "Recording unavailable"
},
"sectionList": {
"pullToRefresh": "Pull to refresh"
},
"settings": {
"calendar": {
"about": "The {{appName}} calendar integration is used to securely access your calendar so it can read upcoming events.",
"disconnect": "Disconnect",
"microsoftSignIn": "Sign in with Microsoft",
"signedIn": "Currently accessing calendar events for {{email}}. Click the Disconnect button below to stop accessing calendar events.",
"title": "Calendar"
},
"devices": "Devices",
"followMe": "Everyone follows me",
"language": "Language",
"loggedIn": "Logged in as {{name}}",
"microphones": "Microphones",
"moderator": "Moderator",
"more": "More",
"name": "Name",
"noDevice": "None",
"selectAudioOutput": "Audio output",
"selectCamera": "Camera",
"selectMic": "Microphone",
"speakers": "Speakers",
"startAudioMuted": "Everyone starts muted",
"startVideoMuted": "Everyone starts hidden",
"title": "Settings"
},
"settingsView": {
"advanced": "Advanced",
"alertOk": "OK",
"alertTitle": "Warning",
"alertURLText": "The entered server URL is invalid",
"buildInfoSection": "Build Information",
"conferenceSection": "Conference",
"disableCallIntegration": "Disable native call integration",
"disableP2P": "Disable Peer-To-Peer mode",
"displayName": "Display name",
"email": "Email",
"header": "Settings",
"profileSection": "Profile",
"serverURL": "Server URL",
"showAdvanced": "Show advanced settings",
"startWithAudioMuted": "Start with audio muted",
"startWithVideoMuted": "Start with video muted",
"version": "Version"
},
"share": {
"dialInfoText": "\n\n=====\n\nJust want to dial in on your phone?\n\n{{defaultDialInNumber}}Click this link to see the dial in phone numbers for this meeting\n{{dialInfoPageUrl}}",
"mainText": "Click the following link to join the meeting:\n{{roomUrl}}"
},
"speaker": "Speaker",
"speakerStats": {
"hours": "{{count}}h",
"minutes": "{{count}}m",
"name": "Name",
"seconds": "{{count}}s",
"speakerStats": "Speaker Stats",
"speakerTime": "Speaker Time"
},
"startupoverlay": {
"policyText": " ",
"title": "{{app}} needs to use your microphone and camera."
},
"suspendedoverlay": {
"rejoinKeyTitle": "Rejoin",
"text": "Press the <i>Rejoin</i> button to reconnect.",
"title": "Your video call was interrupted because this computer went to sleep."
},
"toolbar": {
"Settings": "Settings",
"accessibilityLabel": {
"Settings": "Toggle settings",
"audioOnly": "Toggle audio only",
"audioRoute": "Select the sound device",
"callQuality": "Manage video quality",
"cc": "Toggle subtitles",
"chat": "Toggle chat window",
"document": "Toggle shared document",
"download": "Download our apps",
"feedback": "Leave feedback",
"fullScreen": "Toggle full screen",
"hangup": "Leave the call",
"help": "Help",
"invite": "Invite people",
"kick": "Kick participant",
"localRecording": "Toggle local recording controls",
"lockRoom": "Toggle meeting password",
"moreActions": "Toggle more actions menu",
"moreActionsMenu": "More actions menu",
"moreOptions": "Show more options",
"mute": "Toggle mute audio",
"muteEveryone": "Mute everyone",
"pip": "Toggle Picture-in-Picture mode",
"privateMessage": "Send private message",
"profile": "Edit your profile",
"raiseHand": "Toggle raise hand",
"recording": "Toggle recording",
"remoteMute": "Mute participant",
"shareRoom": "Invite someone",
"shareYourScreen": "Toggle screenshare",
"sharedvideo": "Toggle video sharing",
"shortcuts": "Toggle shortcuts",
"show": "Show on stage",
"speakerStats": "Toggle speaker statistics",
"tileView": "Toggle tile view",
"toggleCamera": "Toggle camera",
"toggleFilmstrip": "Toggle filmstrip",
"videoblur": "Toggle video blur",
"videomute": "Toggle mute video"
},
"addPeople": "Add people to your call",
"audioOnlyOff": "Disable low bandwidth mode",
"audioOnlyOn": "Enable low bandwidth mode",
"audioRoute": "Select the sound device",
"authenticate": "Authenticate",
"callQuality": "Manage video quality",
"chat": "Open / Close chat",
"closeChat": "Close chat",
"documentClose": "Close shared document",
"documentOpen": "Open shared document",
"download": "Download our apps",
"enterFullScreen": "View full screen",
"enterTileView": "Enter tile view",
"exitFullScreen": "Exit full screen",
"exitTileView": "Exit tile view",
"feedback": "Leave feedback",
"hangup": "Leave",
"help": "Help",
"invite": "Invite people",
"login": "Login",
"logout": "Logout",
"lowerYourHand": "Lower your hand",
"moreActions": "More actions",
"moreOptions": "More options",
"mute": "Mute / Unmute",
"muteEveryone": "Mute everyone",
"noAudioSignalDesc": "If you did not purposely mute it from system settings or hardware, consider switching the device.",
"noAudioSignalDescSuggestion": "If you did not purposely mute it from system settings or hardware, consider switching to the suggested device.",
"noAudioSignalDialInDesc": "You can also dial-in using:",
"noAudioSignalDialInLinkDesc": "Dial-in numbers",
"noAudioSignalTitle": "There is no input coming from your mic!",
"noisyAudioInputDesc": "It sounds like your microphone is making noise, please consider muting or changing the device.",
"noisyAudioInputTitle": "Your microphone appears to be noisy!",
"openChat": "Open chat",
"pip": "Enter Picture-in-Picture mode",
"privateMessage": "Send private message",
"profile": "Edit your profile",
"raiseHand": "Raise / Lower your hand",
"raiseYourHand": "Raise your hand",
"shareRoom": "Invite someone",
"sharedvideo": "Share video",
"shortcuts": "View shortcuts",
"speakerStats": "Speaker stats",
"startScreenSharing": "Start screen sharing",
"startSubtitles": "Start subtitles",
"startvideoblur": "Blur my background",
"stopScreenSharing": "Stop screen sharing",
"stopSharedVideo": "Stop video",
"stopSubtitles": "Stop subtitles",
"stopvideoblur": "Disable background blur",
"talkWhileMutedPopup": "Trying to speak? You are muted.",
"tileViewToggle": "Toggle tile view",
"toggleCamera": "Toggle camera",
"videomute": "Start / Stop camera"
},
"transcribing": {
"ccButtonTooltip": "Start / Stop subtitles",
"error": "Transcribing failed. Please try again.",
"expandedLabel": "Transcribing is currently on",
"failedToStart": "Transcribing failed to start",
"labelToolTip": "The meeting is being transcribed",
"off": "Transcribing stopped",
"pending": "Preparing to transcribe the meeting...",
"start": "Start showing subtitles",
"stop": "Stop showing subtitles",
"tr": "TR"
},
"userMedia": {
"androidGrantPermissions": "Select <b><i>Allow</i></b> when your browser asks for permissions.",
"chromeGrantPermissions": "Select <b><i>Allow</i></b> when your browser asks for permissions.",
"edgeGrantPermissions": "Select <b><i>Yes</i></b> when your browser asks for permissions.",
"electronGrantPermissions": "Please grant permissions to use your camera and microphone",
"firefoxGrantPermissions": "Select <b><i>Share Selected Device</i></b> when your browser asks for permissions.",
"iexplorerGrantPermissions": "Select <b><i>OK</i></b> when your browser asks for permissions.",
"nwjsGrantPermissions": "Please grant permissions to use your camera and microphone",
"operaGrantPermissions": "Select <b><i>Allow</i></b> when your browser asks for permissions.",
"react-nativeGrantPermissions": "Select <b><i>Allow</i></b> when your browser asks for permissions.",
"safariGrantPermissions": "Select <b><i>OK</i></b> when your browser asks for permissions."
},
"videoSIPGW": {
"busy": "We're working on freeing resources. Please try again in a few minutes.",
"busyTitle": "The Room service is currently busy",
"errorAlreadyInvited": "{{displayName}} already invited",
"errorInvite": "Conference not established yet. Please try again later.",
"errorInviteFailed": "We're working on resolving the issue. Please try again later.",
"errorInviteFailedTitle": "Inviting {{displayName}} failed",
"errorInviteTitle": "Error inviting room",
"pending": "{{displayName}} has been invited"
},
"videoStatus": {
"audioOnly": "AUD",
"audioOnlyExpanded": "You are in low bandwidth mode. In this mode you will receive only audio and screen sharing.",
"callQuality": "Video Quality",
"hd": "HD",
"hdTooltip": "Viewing high definition video",
"highDefinition": "High definition",
"labelTooiltipNoVideo": "No video",
"labelTooltipAudioOnly": "Low bandwidth mode enabled",
"ld": "LD",
"ldTooltip": "Viewing low definition video",
"lowDefinition": "Low definition",
"onlyAudioAvailable": "Only audio is available",
"onlyAudioSupported": "We only support audio in this browser.",
"sd": "SD",
"sdTooltip": "Viewing standard definition video",
"standardDefinition": "Standard definition"
},
"videothumbnail": {
"domute": "Mute",
"domuteOthers": "Mute everyone else",
"flip": "Flip",
"kick": "Kick out",
"moderator": "Moderator",
"mute": "Participant is muted",
"muted": "Muted",
"remoteControl": "Start / Stop remote control",
"show": "Show on stage",
"videomute": "Participant has stopped the camera"
},
"welcomepage": {
"accessibilityLabel": {
"join": "Tap to join",
"roomname": "Enter room name"
},
"appDescription": "Go ahead, video chat with the whole team. In fact, invite everyone you know. {{app}} is a fully encrypted, 100% open source video conferencing solution that you can use all day, every day, for free — with no account needed.",
"audioVideoSwitch": {
"audio": "Voice",
"video": "Video"
},
"calendar": "Calendar",
"connectCalendarButton": "Connect your calendar",
"connectCalendarText": "Connect your calendar to view all your meetings in {{app}}. Plus, add {{provider}} meetings to your calendar and start them with one click.",
"enterRoomTitle": "Start a new meeting",
"getHelp": "Get help",
"go": "GO",
"goSmall": "GO",
"info": "Info",
"join": "CREATE / JOIN",
"privacy": "Privacy",
"recentList": "Recent",
"recentListDelete": "Delete",
"recentListEmpty": "Your recent list is currently empty. Chat with your team and you will find all your recent meetings here.",
"reducedUIText": "Welcome to {{app}}!",
"roomNameAllowedChars": "Meeting name should not contain any of these characters: ?, &, :, ', \", %, #.",
"roomname": "Enter room name",
"roomnameHint": "Enter the name or URL of the room you want to join. You may make a name up, just let the people you are meeting know it so that they enter the same name.",
"sendFeedback": "Send feedback",
"terms": "Terms",
"title": "Secure, fully featured, and completely free video conferencing"
}
}

View File

@@ -78,12 +78,12 @@
},
"carmode": {
"actions": {
"selectSoundDevice": "Scegli audio"
"selectSoundDevice": "Scegli uscita audio"
},
"labels": {
"buttonLabel": "Modalità Auto",
"title": "Modalità Auto",
"videoStopped": "Il tuo video è fermo"
"videoStopped": "Il tuo video è disabilitato"
}
},
"chat": {
@@ -143,7 +143,7 @@
"address": "Indirizzo:",
"audio_ssrc": "Audio SSRC:",
"bandwidth": "Banda stimata:",
"bitrate": "Bitrate:",
"bitrate": "Velocità:",
"bridgeCount": "Conteggio server:",
"codecs": "Codec (A/V): ",
"connectedTo": "Connesso a:",
@@ -278,13 +278,13 @@
"internalError": "Ops! Qualcosa è andato storto. Questo è l'errore: {{error}}",
"internalErrorTitle": "Errore interno",
"kickMessage": "Puoi contattare {{participantDisplayName}} per maggiori dettagli.",
"kickParticipantButton": "Escludi",
"kickParticipantDialog": "Sei sicuro di voler escludere questo partecipante?",
"kickParticipantTitle": "Escludi questo partecipante?",
"kickTitle": "Escluso dalla riunione",
"linkMeeting": "Link meeting",
"linkMeetingTitle": "Link meeting to Salesforce",
"liveStreaming": "Diretta",
"kickParticipantButton": "Espelli",
"kickParticipantDialog": "Sei sicuro di voler espellere questo partecipante?",
"kickParticipantTitle": "Espelli questo partecipante?",
"kickTitle": "Espulso dalla riunione",
"linkMeeting": "Collega la riunione",
"linkMeetingTitle": "Collega la riunione a Salesforce",
"liveStreaming": "Diretta streaming",
"liveStreamingDisabledBecauseOfActiveRecordingTooltip": "Impossibile durante la registrazione.",
"localUserControls": "Controlli dell'utente locale",
"lockMessage": "Impossibile bloccare la riunione.",
@@ -306,21 +306,21 @@
"moderationVideoLabel": "Permetti ai partecipanti di riattivare la videocamera",
"muteEveryoneDialog": "I partecipanti possono riaccenderli in quasiasi momento.",
"muteEveryoneDialogModerationOn": "I partecipanti possono fare richiesta di parlare in ogni momento.",
"muteEveryoneElseDialog": "Una volta spenti i microfoni non potrai riattivarli, ma loro potranno farlo in qualsiasi momento.",
"muteEveryoneElseTitle": "Spengo il microfono a tutti, eccetto a {{whom}}?",
"muteEveryoneElsesVideoDialog": "Una volta spente le videocamere non potrai riaccenderle, ma ogni partecipante potrà farlo in ogni momento.",
"muteEveryoneElsesVideoTitle": "Spengo tutte le videocamere, tranne a {{whom}}?",
"muteEveryoneElseDialog": "Una volta spenti i microfoni non potrai riattivarli, ma ogni partecipante potrà farlo in qualsiasi momento.",
"muteEveryoneElseTitle": "Spengo il microfono a tutti, tranne che a {{whom}}?",
"muteEveryoneElsesVideoDialog": "Una volta spente le videocamere non potrai riaccenderle, ma ogni partecipante potrà farlo in qualsiasi momento.",
"muteEveryoneElsesVideoTitle": "Spengo la videocamera a tutti, tranne che a {{whom}}?",
"muteEveryoneSelf": "tu",
"muteEveryoneStartMuted": "Tutti cominciano a microfono spento, d'adesso in avanti",
"muteEveryoneTitle": "Spengo i microfoni a tutti?",
"muteEveryonesVideoDialog": "Sei sicuro di voler spegnere le videocamere a tutti? Non potrai riaccenderle, ma ogni partecipante potrà farlo in ogni momento.",
"muteEveryoneTitle": "Spengo il microfono a tutti?",
"muteEveryonesVideoDialog": "Sei sicuro di voler spegnere le videocamere di tutti? Non potrai riaccenderle, ma ogni partecipante potrà farlo in qualsiasi momento.",
"muteEveryonesVideoDialogModerationOn": "I partecipanti possono fare richiesta di trasmettere video in ogni momento.",
"muteEveryonesVideoDialogOk": "Spegni",
"muteEveryonesVideoTitle": "Vuoi spegnere le videocamere di tutti?",
"muteEveryonesVideoTitle": "Spengo la videocamera a tutti?",
"muteParticipantBody": "Non sarai in grado di riattivare il loro microfono, ma loro potranno riattivarlo in qualsiasi momento.",
"muteParticipantButton": "Spegni audio",
"muteParticipantButton": "Silenzia",
"muteParticipantsVideoBody": "Una volta spenta la videocamera non potrai riaccenderla, ma lui potrà riattivarla in qualsiasi momento.",
"muteParticipantsVideoBodyModerationOn": "Non potrai riaccendere le videocamere, né potranno loro.",
"muteParticipantsVideoBodyModerationOn": "Non potrai riaccendere le videocamere, né loro potranno.",
"muteParticipantsVideoButton": "Spegni video",
"muteParticipantsVideoDialog": "Sei sicuro di voler spegnere la videocamera di questo partecipante? Lui potrà riattivarla in ogni momento.",
"muteParticipantsVideoDialogModerationOn": "Are you sure you want to turn off this participant's camera? You won't be able to turn the camera back on and neither will they.",
@@ -388,10 +388,10 @@
"shareYourScreen": "Condividi schermo",
"shareYourScreenDisabled": "Condivisione schermo disabilitata.",
"sharedVideoDialogError": "Errore: URL non valido",
"sharedVideoLinkPlaceholder": "Link YouTube o link video diretto",
"sharedVideoLinkPlaceholder": "Link YouTube o link diretto, al video",
"show": "Mostra",
"start": "Avvia ",
"startLiveStreaming": "Avvia diretta",
"startLiveStreaming": "Avvia diretta streaming",
"startRecording": "Inizia a registrare",
"startRemoteControlErrorMessage": "Si è verificato un errore nel tentativo di avviare la sessione di controllo remoto!",
"stopLiveStreaming": "Ferma la diretta streaming",
@@ -592,8 +592,8 @@
"nameField": "Scrivi il tuo nome",
"notificationLobbyAccessDenied": "{{targetParticipantName}} è stato respinto da {{originParticipantName}}",
"notificationLobbyAccessGranted": "{{targetParticipantName}} è stato autorizzato ad entrare da {{originParticipantName}}",
"notificationLobbyDisabled": "La sala d'attesa è stata disattivata da {{originParticipantName}}",
"notificationLobbyEnabled": "La sala d'attesa è stata attivata da {{originParticipantName}}",
"notificationLobbyDisabled": "{{originParticipantName}} ha aggiunto la sala d'attesa alla riunione",
"notificationLobbyEnabled": "{{originParticipantName}} ha tolto la sala d'attesa alla riunione",
"notificationTitle": "Sala d'attesa",
"passwordField": "Inserisci la password della riunione",
"passwordJoinButton": "Entra",
@@ -655,7 +655,7 @@
"focusFail": "{{component}} non disponibile - riprovo tra {{ms}} sec",
"gifsMenu": "GIPHY",
"groupTitle": "Notifiche",
"hostAskedUnmute": "Il moderatore ti dice di accendere il microfono",
"hostAskedUnmute": "Il moderatore ti chiede di accendere il microfono",
"invitedOneMember": "{{displayName}} è stato invitato",
"invitedThreePlusMembers": "Hai invitato {{name}} e altri {{count}}",
"invitedTwoMembers": "Hai invitato {{first}} e {{second}}",
@@ -686,7 +686,7 @@
"moderator": "Impostati i permessi di moderatore!",
"muted": "Hai iniziato la conversazione con audio disattivato.",
"mutedRemotelyDescription": "Puoi sempre attivare il microfono, quando vuoi parlare. Spegni il microfono quando hai finito, per non introdurre rumori di fondo nella riunione.",
"mutedRemotelyTitle": "Ti è stato disattivato l'audio da {{participantDisplayName}}!",
"mutedRemotelyTitle": "{{participantDisplayName}} ti ha spento il microfono",
"mutedTitle": "Hai audio disattivato!",
"newDeviceAction": "OK, usala",
"newDeviceAudioTitle": "Trovata nuova origine audio",
@@ -717,7 +717,7 @@
"suboptimalExperienceTitle": "Avviso sul browser",
"unmute": "Accendi microfono",
"videoMutedRemotelyDescription": "Puoi riaccenderla in qualsiasi momento.",
"videoMutedRemotelyTitle": "La videocamera ti è stata spenta da {{participantDisplayName}}!",
"videoMutedRemotelyTitle": "{{participantDisplayName}} ti ha spento la videocamera",
"videoUnmuteBlockedDescription": "Riattivazione video e condivisione schermo sono state momentaneamente bloccate per limiti di sistema.",
"videoUnmuteBlockedTitle": "Riattivazione video e condivisione schermo bloccate!",
"viewLobby": "Vedi sala d'attesa",
@@ -830,8 +830,8 @@
"initiated": "Chiamata avviata",
"joinAudioByPhone": "Collegati usando un telefono, per parlare",
"joinMeeting": "Collegati alla riunione",
"joinMeetingInLowBandwidthMode": "Entra con il solo audio",
"joinWithoutAudio": "Collegati senza poter parlare",
"joinMeetingInLowBandwidthMode": "Entra in modalità banda limitata",
"joinWithoutAudio": "Collegati senza poter parlare mai",
"keyboardShortcuts": "Attiva le scorciatoie da tastiera",
"linkCopied": "Collegamento copiato negli appunti",
"lookGood": "Sembra che il tuo microfono funzioni correttamente",
@@ -943,7 +943,7 @@
"security": {
"about": "Puoi aggiungere una $t(lockRoomPassword) alla riunione. I partecipanti dovranno fornire la $t(lockRoomPassword) per essere autorizzati a partecipare alla riunione.",
"aboutReadOnly": "I moderatori della riunione possono aggiungere $t(lockRoomPassword). I partecipanti dovranno fornire la $t(lockRoomPassword) per essere autorizzati a partecipare alla riunione.",
"insecureRoomNameWarning": "Il nome della riunione non è sicuro. Dei partecipanti indesiderati potrebbero unirsi alla riunione. Puoi proteggere l'accesso alla riunione col bottone sicurezza.",
"insecureRoomNameWarning": "Il nome della riunione non è sicuro. Dei partecipanti indesiderati potrebbero unirsi alla riunione. Puoi proteggere l'accesso alla riunione nelle Impostazioni di sicurezza.",
"title": "Impostazioni di sicurezza"
},
"settings": {
@@ -964,7 +964,7 @@
"incomingMessage": "Messaggio in arrivo",
"language": "Lingua",
"loggedIn": "Connesso come {{name}}",
"maxStageParticipants": "Numero massimo di partecipanti che possono essere aggiunti come oratori",
"maxStageParticipants": "Numero massimo video che possono essere fissati nella schemata",
"microphones": "Microfoni",
"moderator": "Moderatore",
"more": "Mostra di più",
@@ -985,7 +985,7 @@
"startAudioMuted": "Tutti cominciano a microfono spento",
"startReactionsMuted": "Spegni i suoni delle reazioni a tutti",
"startVideoMuted": "Tutti cominciano a videocamera disattivata",
"talkWhileMuted": "Parla senza microfono",
"talkWhileMuted": "Parli a microfono spento",
"title": "Impostazioni"
},
"settingsView": {
@@ -1278,7 +1278,7 @@
},
"videothumbnail": {
"connectionInfo": "Info connessione",
"domute": "Disattiva audio",
"domute": "Silenzia",
"domuteOthers": "Disattiva audio di tutti gli altri",
"domuteVideo": "Disattiva video",
"domuteVideoOfOthers": "Disattiva video di tutti gli altri",
@@ -1289,12 +1289,12 @@
"moderator": "Moderatore",
"mute": "Il partecipante ha il microfono spento",
"muted": "Audio disattivato",
"pinToStage": "Aggiungi agli oratori",
"pinToStage": "Fissa questo video",
"remoteControl": "Controllo remoto",
"screenSharing": "Il partecipante sta condividendo lo schermo",
"show": "Mostra tra gli oratori",
"showSelfView": "Mostra tua immagine",
"unpinFromStage": "Togli",
"unpinFromStage": "Libera questo video",
"videoMuted": "Video disattivato",
"videomute": "Il partecipante ha la videocamera spenta"
},

View File

@@ -1,716 +0,0 @@
{
"addPeople": {
"add": "Inviter",
"countryNotSupported": "",
"countryReminder": "",
"disabled": "Du kan ikke invitere folk.",
"failedToAdd": "Klarte ikke å lagge til deltagere",
"footerText": "Å ringe ut er avskrudd",
"loading": "Søker etter folk og telefonnumre",
"loadingNumber": "Bekrefter telefonnummer",
"loadingPeople": "Søker etter folk å inviterte",
"noResults": "",
"noValidNumbers": "Skriv inn et telefonnummer",
"searchNumbers": "Legg til telefonnumre",
"searchPeople": "Søk etter folk",
"searchPeopleAndNumbers": "Søk etter folk eller legg til telefonnumrene deres",
"telephone": "Telefon: {{number}}",
"title": "Inviter folk til dette møtet"
},
"audioDevices": {
"bluetooth": "Blåtann",
"headphones": "Hodetelefoner",
"none": "Ingen lydenheter tilgjengelig",
"phone": "Telefon",
"speaker": "Høyttaler"
},
"audioOnly": {
"audioOnly": "Lav båndbredde"
},
"calendarSync": {
"addMeetingURL": "Legg til en møtelenke",
"confirmAddLink": "Ønsker du å legge til en Jitsi-lenke til denne hendelsen?",
"join": "Ta del",
"joinTooltip": "Ta del i møtet",
"nextMeeting": "neste møte",
"noEvents": "",
"ongoingMeeting": "pågående møte",
"permissionButton": "Åpne innstillinger",
"permissionMessage": "",
"refresh": "",
"today": "I dag"
},
"chat": {
"error": "",
"fieldPlaceHolder": "Skriv inn din melding her",
"messageTo": "Privat melding til {{recipient}}",
"messagebox": "Skriv en melding",
"nickname": {
"popover": "Velg et kallenavn",
"title": "",
"titleWithPolls": ""
},
"sendButton": "Send",
"title": "",
"titleWithPolls": ""
},
"chromeExtensionBanner": {
"dontShowAgain": "Ikke vis meg dette igjen"
},
"connection": {
"ATTACHED": "Vedlagt",
"AUTHENTICATING": "Bekrefter",
"AUTHFAIL": "",
"CONNECTED": "Tilkoblet",
"CONNECTING": "Kobler til",
"CONNFAIL": "",
"DISCONNECTED": "Frakoblet",
"DISCONNECTING": "Kobler fra",
"ERROR": "Feil",
"FETCH_SESSION_ID": "Henter økt-ID…",
"GOT_SESSION_ID": "Henter økt-ID… Ferdig",
"RECONNECTING": ""
},
"connectionindicator": {
"address": "Adresse:",
"bandwidth": "Anslått båndbredde:",
"bitrate": "",
"bridgeCount": "",
"connectedTo": "Ansluttet til:",
"framerate": "",
"less": "Vis mindre",
"localaddress": "Lokal adresse:",
"localaddress_plural": "Lokale adresser:",
"localport": "Lokal port:",
"localport_plural": "Lokale porter:",
"more": "Vis mer",
"packetloss": "Pakketap:",
"quality": {
"good": "God",
"inactive": "Inaktiv",
"lost": "Tapt",
"nonoptimal": "Suboptimal",
"poor": "Dårlig"
},
"remoteaddress": "Fjernadresser:",
"remoteaddress_plural": "Fjernadresser:",
"remoteport": "",
"remoteport_plural": "",
"resolution": "Oppløsning:",
"status": "Tilknytning:",
"transport": "",
"transport_plural": "",
"turn": ""
},
"dateUtils": {
"earlier": "Tidligere",
"today": "I dag",
"yesterday": "I går"
},
"deepLinking": {
"downloadApp": "Last ned programmet",
"openApp": "Fortsett til programmet"
},
"defaultLink": "f.eks.",
"deviceError": {
"cameraError": "",
"cameraPermission": "",
"microphoneError": "",
"microphonePermission": ""
},
"deviceSelection": {
"noPermission": "Tilgang ikke innvilget",
"previewUnavailable": "Forhåndsvisning utilgjengelig",
"selectADevice": "Velg en enhet",
"testAudio": "Spill en testlyd"
},
"dialOut": {
"statusMessage": "er nå {{status}}"
},
"dialog": {
"Back": "Tilbake",
"Cancel": "Avbryt",
"IamHost": "Jeg er vertsskap",
"Ok": "OK",
"Remove": "Fjern",
"Share": "Del",
"Submit": "Send inn",
"WaitForHostMsg": "",
"WaitingForHost": "",
"Yes": "Ja",
"accessibilityLabel": {
"liveStreaming": ""
},
"allow": "Tillat",
"alreadySharedVideoMsg": "",
"alreadySharedVideoTitle": "",
"applicationWindow": "",
"cameraConstraintFailedError": "",
"cameraNotFoundError": "",
"cameraNotSendingData": "",
"cameraNotSendingDataTitle": "",
"cameraPermissionDeniedError": "",
"cameraUnknownError": "",
"cameraUnsupportedResolutionError": "",
"close": "",
"conferenceDisconnectMsg": "",
"conferenceDisconnectTitle": "Du har blitt frakoblet.",
"conferenceReloadMsg": "",
"conferenceReloadTitle": "",
"confirm": "Bekreft",
"confirmNo": "Nei",
"confirmYes": "Ja",
"connectError": "",
"connectErrorWithMsg": "",
"connecting": "Kobler til",
"contactSupport": "Kontakt brukerstøtte",
"copy": "Kopier",
"dismiss": "Forkast",
"displayNameRequired": "Hei. Hva heter du?",
"done": "Ferdig",
"enterDisplayName": "Skriv inn navnet ditt her",
"error": "Feil",
"externalInstallationMsg": "",
"externalInstallationTitle": "Programtillegg kreves",
"goToStore": "",
"gracefulShutdown": "",
"incorrectPassword": "",
"incorrectRoomLockPassword": "",
"inlineInstallExtension": "Installer nå",
"inlineInstallationMsg": "",
"internalError": "",
"internalErrorTitle": "",
"kickMessage": "",
"kickParticipantButton": "Kast ut",
"kickParticipantDialog": "Er du sikker på at du vil kaste ut denne deltageren?",
"kickParticipantTitle": "Kast ut denne deltageren?",
"kickTitle": "Oida. {{participantDisplayName}} kastet deg ut av møtet",
"liveStreaming": "",
"liveStreamingDisabledForGuestTooltip": "",
"liveStreamingDisabledTooltip": "",
"lockMessage": "Klarte ikke å låse konferansen.",
"lockRoom": "",
"lockTitle": "",
"logoutQuestion": "",
"logoutTitle": "Logg ut",
"maxUsersLimitReached": "",
"maxUsersLimitReachedTitle": "",
"micConstraintFailedError": "",
"micNotFoundError": "",
"micNotSendingData": "",
"micNotSendingDataTitle": "",
"micPermissionDeniedError": "",
"micUnknownError": "",
"muteEveryoneElseTitle": "Forstum alle unntatt {{whom}}?",
"muteEveryoneSelf": "deg selv",
"muteEveryoneStartMuted": "Alle starter forstummet fra nå av",
"muteEveryoneTitle": "Forstum alle?",
"muteParticipantBody": "Du vil ikke kunne oppheve forstumming av dem, men de kan oppheve forstumming selv når som helst.",
"muteParticipantButton": "Forstum",
"muteParticipantDialog": "",
"muteParticipantTitle": "",
"passwordLabel": "",
"passwordNotSupported": "",
"passwordNotSupportedTitle": "",
"passwordRequired": "",
"popupError": "",
"popupErrorTitle": "Oppsprett blokkert",
"recording": "",
"recordingDisabledForGuestTooltip": "",
"recordingDisabledTooltip": "",
"rejoinNow": "",
"remoteControlAllowedMessage": "",
"remoteControlDeniedMessage": "",
"remoteControlErrorMessage": "",
"remoteControlRequestMessage": "",
"remoteControlShareScreenWarning": "",
"remoteControlStopMessage": "",
"remoteControlTitle": "",
"removePassword": "Fjern",
"removeSharedVideoMsg": "",
"removeSharedVideoTitle": "Fjern delt video",
"reservationError": "",
"reservationErrorMsg": "",
"retry": "Prøv igjen",
"screenSharingAudio": "Del lyd",
"screenSharingFailedToInstall": "",
"screenSharingFailedToInstallTitle": "",
"screenSharingFirefoxPermissionDeniedError": "",
"screenSharingFirefoxPermissionDeniedTitle": "",
"screenSharingPermissionDeniedError": "",
"sendPrivateMessageCancel": "Send til gruppen",
"sendPrivateMessageOk": "Send privat",
"sendPrivateMessageTitle": "Send privat?",
"serviceUnavailable": "Tjenesten er utilgjengelig",
"sessTerminated": "",
"shareVideoLinkError": "",
"shareVideoTitle": "Del en video",
"shareYourScreen": "Del skjermen din",
"shareYourScreenDisabled": "Skjermdeling er avskrudd.",
"shareYourScreenDisabledForGuest": "",
"startLiveStreaming": "",
"startRecording": "Start opptak",
"startRemoteControlErrorMessage": "",
"stopLiveStreaming": "",
"stopRecording": "Stopp opptak",
"stopRecordingWarning": "",
"stopStreamingWarning": "",
"streamKey": "",
"thankYou": "Takk for at du bruker {{appName}}.",
"token": "symbol",
"tokenAuthFailed": "",
"tokenAuthFailedTitle": "",
"transcribing": "",
"unlockRoom": "",
"userPassword": "brukerpassord",
"yourEntireScreen": "Hele skjermen din"
},
"documentSharing": {
"title": "Delt dokument"
},
"feedback": {
"average": "Middels",
"bad": "Dårlig",
"detailsLabel": "Fortell oss om det.",
"good": "God",
"rateExperience": "Vurder din møteopplevelse",
"veryBad": "Veldig dårlig",
"veryGood": "Veldig god"
},
"incomingCall": {
"answer": "Svar",
"audioCallTitle": "",
"decline": "",
"productLabel": "",
"videoCallTitle": ""
},
"info": {
"accessibilityLabel": "Vis info",
"addPassword": "Legg til $t(lockRoomPassword)",
"cancelPassword": "Avbryt $t(lockRoomPassword)",
"conferenceURL": "Lenke:",
"country": "Land",
"dialANumber": "",
"dialInConferenceID": "",
"dialInNotSupported": "",
"dialInNumber": "",
"dialInSummaryError": "",
"dialInTollFree": "",
"genericError": "",
"inviteLiveStream": "",
"invitePhone": "",
"invitePhoneAlternatives": "",
"inviteURLFirstPartGeneral": "",
"inviteURLFirstPartPersonal": "",
"inviteURLSecondPart": "",
"label": "",
"liveStreamURL": "",
"moreNumbers": "Flere nummer",
"noNumbers": "",
"noPassword": "",
"noRoom": "",
"numbers": "",
"password": "",
"title": "Del",
"tooltip": ""
},
"inlineDialogFailure": {
"msg": "",
"retry": "Prøv igjen",
"support": "Brukerstøtte",
"supportMsg": ""
},
"inviteDialog": {
"alertText": "",
"header": "Inviter",
"searchCallOnlyPlaceholder": "",
"searchPeopleOnlyPlaceholder": "",
"searchPlaceholder": "",
"send": "Send"
},
"keyboardShortcuts": {
"focusLocal": "",
"focusRemote": "",
"fullScreen": "",
"keyboardShortcuts": "Tastatursnarveier",
"localRecording": "",
"mute": "",
"pushToTalk": "",
"raiseHand": "",
"showSpeakerStats": "",
"toggleChat": "",
"toggleFilmstrip": "",
"toggleScreensharing": "",
"toggleShortcuts": "",
"videoMute": ""
},
"liveStreaming": {
"busy": "",
"busyTitle": "",
"changeSignIn": "",
"choose": "",
"chooseCTA": "",
"enterStreamKey": "",
"error": "",
"errorAPI": "",
"errorLiveStreamNotEnabled": "",
"expandedOff": "",
"expandedOn": "",
"expandedPending": "",
"failedToStart": "",
"getStreamKeyManually": "",
"invalidStreamKey": "",
"off": "",
"on": "",
"pending": "",
"serviceName": "",
"signIn": "",
"signInCTA": "",
"signOut": "",
"signedInAs": "©",
"start": "",
"streamIdHelp": "",
"unavailableTitle": ""
},
"localRecording": {
"clientState": {
"off": "",
"on": "",
"unknown": ""
},
"dialogTitle": "",
"duration": "",
"durationNA": "",
"encoding": "",
"label": "",
"labelToolTip": "",
"localRecording": "",
"me": "",
"messages": {
"engaged": "",
"finished": "",
"finishedModerator": "",
"notModerator": ""
},
"moderator": "",
"no": "",
"participant": "",
"participantStats": "",
"sessionToken": "",
"start": "",
"stop": "",
"yes": ""
},
"lockRoomPassword": "",
"lockRoomPasswordUppercase": "",
"me": "",
"notify": {
"connectedOneMember": "",
"connectedThreePlusMembers": "",
"connectedTwoMembers": "",
"disconnected": "",
"focus": "",
"focusFail": "",
"grantedTo": "",
"invitedOneMember": "",
"invitedThreePlusMembers": "",
"invitedTwoMembers": "",
"kickParticipant": "",
"me": "",
"moderator": "",
"muted": "",
"mutedRemotelyDescription": "",
"mutedRemotelyTitle": "",
"mutedTitle": "",
"newDeviceAction": "",
"newDeviceAudioTitle": "",
"newDeviceCameraTitle": "",
"passwordRemovedRemotely": "",
"passwordSetRemotely": "",
"raisedHand": "",
"somebody": "",
"startSilentDescription": "",
"startSilentTitle": "",
"suboptimalExperienceDescription": "",
"suboptimalExperienceTitle": "",
"unmute": ""
},
"passwordDigitsOnly": "",
"passwordSetRemotely": "",
"poweredby": "",
"presenceStatus": {
"busy": "",
"calling": "",
"connected": "",
"connecting": "",
"connecting2": "",
"disconnected": "",
"expired": "",
"ignored": "",
"initializingCall": "",
"invited": "",
"rejected": "",
"ringing": ""
},
"profile": {
"setDisplayNameLabel": "",
"setEmailInput": "",
"setEmailLabel": "",
"title": ""
},
"recording": {
"authDropboxText": "",
"availableSpace": "",
"beta": "",
"busy": "",
"busyTitle": "",
"error": "",
"expandedOff": "",
"expandedOn": "",
"expandedPending": "",
"failedToStart": "",
"fileSharingdescription": "",
"live": "",
"loggedIn": "",
"off": "",
"on": "",
"pending": "",
"rec": "",
"serviceDescription": "",
"serviceName": "",
"signIn": "",
"signOut": "",
"unavailable": "",
"unavailableTitle": ""
},
"sectionList": {
"pullToRefresh": ""
},
"settings": {
"calendar": {
"about": "",
"disconnect": "",
"microsoftSignIn": "",
"signedIn": "",
"title": ""
},
"devices": "",
"followMe": "",
"language": "",
"loggedIn": "",
"moderator": "",
"more": "",
"name": "",
"noDevice": "",
"selectAudioOutput": "",
"selectCamera": "",
"selectMic": "",
"startAudioMuted": "",
"startVideoMuted": "",
"title": ""
},
"settingsView": {
"alertOk": "",
"alertTitle": "",
"alertURLText": "",
"buildInfoSection": "",
"conferenceSection": "",
"displayName": "",
"email": "",
"header": "",
"profileSection": "",
"serverURL": "",
"startWithAudioMuted": "",
"startWithVideoMuted": "",
"version": ""
},
"share": {
"dialInfoText": "",
"mainText": ""
},
"speaker": "",
"speakerStats": {
"hours": "",
"minutes": "",
"name": "",
"seconds": "",
"speakerStats": "",
"speakerTime": ""
},
"startupoverlay": {
"policyText": "",
"title": ""
},
"suspendedoverlay": {
"rejoinKeyTitle": "",
"text": "",
"title": ""
},
"toolbar": {
"Settings": "",
"accessibilityLabel": {
"Settings": "",
"audioOnly": "",
"audioRoute": "",
"callQuality": "",
"cc": "",
"chat": "",
"document": "",
"feedback": "",
"fullScreen": "",
"hangup": "",
"invite": "",
"kick": "",
"localRecording": "",
"lockRoom": "",
"moreActions": "",
"moreActionsMenu": "",
"mute": "",
"pip": "",
"profile": "",
"raiseHand": "",
"recording": "",
"remoteMute": "",
"shareRoom": "",
"shareYourScreen": "",
"sharedvideo": "",
"shortcuts": "",
"show": "",
"speakerStats": "",
"tileView": "",
"toggleCamera": "",
"videoblur": "",
"videomute": ""
},
"addPeople": "",
"audioOnlyOff": "",
"audioOnlyOn": "",
"audioRoute": "",
"authenticate": "",
"callQuality": "",
"chat": "",
"closeChat": "",
"documentClose": "",
"documentOpen": "",
"enterFullScreen": "",
"enterTileView": "",
"exitFullScreen": "",
"exitTileView": "",
"feedback": "",
"hangup": "",
"invite": "",
"login": "",
"logout": "",
"lowerYourHand": "",
"moreActions": "",
"mute": "",
"openChat": "",
"pip": "",
"profile": "",
"raiseHand": "",
"raiseYourHand": "",
"shareRoom": "",
"sharedvideo": "",
"shortcuts": "",
"speakerStats": "",
"startScreenSharing": "",
"startSubtitles": "",
"startvideoblur": "",
"stopScreenSharing": "",
"stopSharedVideo": "",
"stopSubtitles": "",
"stopvideoblur": "",
"talkWhileMutedPopup": "",
"tileViewToggle": "",
"toggleCamera": "",
"videomute": ""
},
"transcribing": {
"ccButtonTooltip": "",
"error": "",
"expandedLabel": "",
"failedToStart": "",
"labelToolTip": "",
"off": "",
"pending": "",
"start": "",
"stop": "",
"tr": ""
},
"userMedia": {
"androidGrantPermissions": "",
"chromeGrantPermissions": "",
"edgeGrantPermissions": "",
"electronGrantPermissions": "",
"firefoxGrantPermissions": "",
"iexplorerGrantPermissions": "",
"nwjsGrantPermissions": "",
"operaGrantPermissions": "",
"react-nativeGrantPermissions": "",
"safariGrantPermissions": ""
},
"videoSIPGW": {
"busy": "",
"busyTitle": "",
"errorAlreadyInvited": "",
"errorInvite": "",
"errorInviteFailed": "",
"errorInviteFailedTitle": "",
"errorInviteTitle": "",
"pending": ""
},
"videoStatus": {
"audioOnly": "",
"audioOnlyExpanded": "",
"callQuality": "",
"hd": "",
"highDefinition": "",
"labelTooiltipNoVideo": "",
"labelTooltipAudioOnly": "",
"ld": "",
"lowDefinition": "",
"onlyAudioAvailable": "",
"onlyAudioSupported": "",
"sd": "",
"standardDefinition": ""
},
"videothumbnail": {
"domute": "",
"flip": "",
"kick": "",
"moderator": "",
"mute": "",
"muted": "",
"remoteControl": "",
"show": "",
"videomute": ""
},
"welcomepage": {
"accessibilityLabel": {
"join": "",
"roomname": ""
},
"appDescription": "",
"audioVideoSwitch": {
"audio": "",
"video": ""
},
"calendar": "",
"connectCalendarButton": "",
"connectCalendarText": "",
"enterRoomTitle": "",
"go": "",
"info": "",
"join": "",
"privacy": "",
"recentList": "",
"recentListDelete": "",
"recentListEmpty": "",
"reducedUIText": "",
"roomname": "",
"roomnameHint": "",
"sendFeedback": "",
"terms": "",
"title": ""
}
}

View File

@@ -964,7 +964,7 @@
"incomingMessage": "Incoming message",
"language": "Language",
"loggedIn": "Logged in as {{name}}",
"maxStageParticipants": "Maximum number of participants who can be pinned to the main stage",
"maxStageParticipants": "Maximum number of participants who can be pinned to the main stage (EXPERIMENTAL)",
"microphones": "Microphones",
"moderator": "Moderator",
"more": "More",

24
package-lock.json generated
View File

@@ -74,7 +74,7 @@
"js-md5": "0.6.1",
"js-sha512": "0.8.0",
"jwt-decode": "2.2.0",
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1533.0.0+7b257686/lib-jitsi-meet.tgz",
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1535.0.0+e6263e7c/lib-jitsi-meet.tgz",
"lodash": "4.17.21",
"moment": "2.29.4",
"moment-duration-format": "2.2.2",
@@ -127,7 +127,7 @@
"resemblejs": "4.0.0",
"seamless-scroll-polyfill": "2.1.8",
"styled-components": "3.4.9",
"tss-react": "4.0.0",
"tss-react": "4.4.4",
"util": "0.12.1",
"uuid": "8.3.2",
"wasm-check": "2.0.1",
@@ -13497,8 +13497,8 @@
},
"node_modules/lib-jitsi-meet": {
"version": "0.0.0",
"resolved": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1533.0.0+7b257686/lib-jitsi-meet.tgz",
"integrity": "sha512-AOsGOXwuZJrdaJPSBCkLtoDUrg/JKWZOdcR1Sw/ZGjlszcQ+gyfT8UbM9NI+b5hC3h39K9gmnGVcI8acNxpBrQ==",
"resolved": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1535.0.0+e6263e7c/lib-jitsi-meet.tgz",
"integrity": "sha512-RgMoesoWyscWi2fL9Hxp8PUwDlUtHbo+GhXosD3GeKR0zmihu/kxTONMUifGQnF8XdtcjaZfL2jCJynLwYKlkw==",
"license": "Apache-2.0",
"dependencies": {
"@jitsi/js-utils": "2.0.0",
@@ -19019,9 +19019,9 @@
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
},
"node_modules/tss-react": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/tss-react/-/tss-react-4.0.0.tgz",
"integrity": "sha512-pPkOKWiWWPbKdQFnGGeHEgRceUwkjrv0eldVCAdBll3j6Y3Ys/xwqsnlWYwWOU3SMJygVRE/S4CsIYx6KPpOkA==",
"version": "4.4.4",
"resolved": "https://registry.npmjs.org/tss-react/-/tss-react-4.4.4.tgz",
"integrity": "sha512-Bzyg99bIQq3Lk4Rwc5XMOps58c1biw1rghCkApIX5XkAB+/VjGCIFSl63PePhmiRNvKRxJRpawGPPxHytiw1TA==",
"dependencies": {
"@emotion/cache": "*",
"@emotion/serialize": "*",
@@ -30510,8 +30510,8 @@
}
},
"lib-jitsi-meet": {
"version": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1533.0.0+7b257686/lib-jitsi-meet.tgz",
"integrity": "sha512-AOsGOXwuZJrdaJPSBCkLtoDUrg/JKWZOdcR1Sw/ZGjlszcQ+gyfT8UbM9NI+b5hC3h39K9gmnGVcI8acNxpBrQ==",
"version": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1535.0.0+e6263e7c/lib-jitsi-meet.tgz",
"integrity": "sha512-RgMoesoWyscWi2fL9Hxp8PUwDlUtHbo+GhXosD3GeKR0zmihu/kxTONMUifGQnF8XdtcjaZfL2jCJynLwYKlkw==",
"requires": {
"@jitsi/js-utils": "2.0.0",
"@jitsi/logger": "2.0.0",
@@ -34738,9 +34738,9 @@
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
},
"tss-react": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/tss-react/-/tss-react-4.0.0.tgz",
"integrity": "sha512-pPkOKWiWWPbKdQFnGGeHEgRceUwkjrv0eldVCAdBll3j6Y3Ys/xwqsnlWYwWOU3SMJygVRE/S4CsIYx6KPpOkA==",
"version": "4.4.4",
"resolved": "https://registry.npmjs.org/tss-react/-/tss-react-4.4.4.tgz",
"integrity": "sha512-Bzyg99bIQq3Lk4Rwc5XMOps58c1biw1rghCkApIX5XkAB+/VjGCIFSl63PePhmiRNvKRxJRpawGPPxHytiw1TA==",
"requires": {
"@emotion/cache": "*",
"@emotion/serialize": "*",

View File

@@ -79,7 +79,7 @@
"js-md5": "0.6.1",
"js-sha512": "0.8.0",
"jwt-decode": "2.2.0",
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1533.0.0+7b257686/lib-jitsi-meet.tgz",
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1535.0.0+e6263e7c/lib-jitsi-meet.tgz",
"lodash": "4.17.21",
"moment": "2.29.4",
"moment-duration-format": "2.2.2",
@@ -132,7 +132,7 @@
"resemblejs": "4.0.0",
"seamless-scroll-polyfill": "2.1.8",
"styled-components": "3.4.9",
"tss-react": "4.0.0",
"tss-react": "4.4.4",
"util": "0.12.1",
"uuid": "8.3.2",
"wasm-check": "2.0.1",

View File

@@ -1,5 +1,4 @@
/* eslint-disable react/jsx-no-bind */
import { Theme } from '@mui/material';
import React, { useEffect, useState } from 'react';
import { makeStyles } from 'tss-react/mui';
@@ -8,7 +7,7 @@ import { IconCheck, IconCopy } from '../icons/svg';
import { withPixelLineHeight } from '../styles/functions.web';
import { copyText } from '../util/copyText.web';
const useStyles = makeStyles()((theme: Theme) => {
const useStyles = makeStyles()(theme => {
return {
copyButton: {
...withPixelLineHeight(theme.typography.bodyShortBold),

View File

@@ -1,4 +1,3 @@
import { Theme } from '@mui/material';
import React, { ReactNode } from 'react';
import { makeStyles } from 'tss-react/mui';
@@ -76,7 +75,7 @@ interface IProps {
}
const useStyles = makeStyles()((theme: Theme) => {
const useStyles = makeStyles()(theme => {
return {
container: {
alignItems: 'center',

View File

@@ -58,6 +58,7 @@ export interface IJitsiConference {
isCallstatsEnabled: Function;
isEndConferenceSupported: Function;
isLobbySupported: Function;
isSIPCallingSupported: Function;
isStartAudioMuted: Function;
isStartVideoMuted: Function;
join: Function;

View File

@@ -39,11 +39,13 @@ type ButtonsWithNotifyClick = 'camera' |
'desktop' |
'download' |
'embedmeeting' |
'end-meeting' |
'etherpad' |
'feedback' |
'filmstrip' |
'fullscreen' |
'hangup' |
'hangup-menu' |
'help' |
'invite' |
'livestreaming' |
@@ -342,6 +344,7 @@ export interface IConfig {
iAmRecorder?: boolean;
iAmSipGateway?: boolean;
inviteAppName?: string | null;
jaasActuatorUrl?: string;
jaasFeedbackMetadataURL?: string;
jaasTokenUrl?: string;
lastNLimits?: {
@@ -391,6 +394,7 @@ export interface IConfig {
hideMuteAllButton?: boolean;
};
pcStatsInterval?: number;
peopleSearchUrl?: string;
preferH264?: boolean;
preferredTranscribeLanguage?: string;
prejoinConfig?: {
@@ -427,6 +431,7 @@ export interface IConfig {
mode?: 'always' | 'recording';
};
serviceUrl?: string;
sipInviteUrl?: string;
speakerStats?: {
disableSearch?: boolean;
disabled?: boolean;

View File

@@ -1,4 +1,3 @@
import { Theme } from '@mui/material';
import React from 'react';
import { makeStyles } from 'tss-react/mui';
@@ -45,7 +44,7 @@ interface IProps {
}
const useStyles = makeStyles()((theme: Theme) => {
const useStyles = makeStyles()(theme => {
return {
label: {
...withPixelLineHeight(theme.typography.labelRegular),

View File

@@ -1,79 +0,0 @@
// @flow
import React, { useCallback } from 'react';
import { StatusBar } from 'react-native';
import { ColorSchemeRegistry } from '../../color-scheme';
import { connect } from '../../redux';
import { isDarkColor } from '../../styles';
// Register style
import '../../react/components/native/headerstyles';
/**
* Constants for the (currently) supported statusbar colors.
*/
const STATUSBAR_DARK = 'dark-content';
const STATUSBAR_LIGHT = 'light-content';
type Props = {
/**
* The color schemed style of the component.
*/
_styles: Object
}
const JitsiStatusBar = ({ _styles }: Props) => {
const getStatusBarContentColor = useCallback(() => {
const { statusBarContent } = _styles;
if (statusBarContent) {
// We have the possibility to define the statusbar color in the
// color scheme feature, but since mobile devices (at the moment)
// only support two colors (light and dark) we need to normalize
// the value.
if (isDarkColor(statusBarContent)) {
return STATUSBAR_DARK;
}
return STATUSBAR_LIGHT;
}
// The statusbar color is not defined, so we need to base our choice
// on the header colors
const { statusBar, screenHeader } = _styles;
if (isDarkColor(statusBar || screenHeader.backgroundColor)) {
return STATUSBAR_LIGHT;
}
return STATUSBAR_DARK;
}, [ _styles ]);
return (
<StatusBar
backgroundColor = { _styles.statusBar }
barStyle = { getStatusBarContentColor() }
translucent = { false } />
);
};
/**
* Maps part of the Redux state to the props of the component.
*
* @param {Object} state - The Redux state.
* @returns {{
* _styles: Object
* }}
*/
function _mapStateToProps(state) {
return {
_styles: ColorSchemeRegistry.get(state, 'Header')
};
}
export default connect(_mapStateToProps)(JitsiStatusBar);

View File

@@ -32,7 +32,7 @@ const AVATAR_CHECKED_URLS = new Map();
/* eslint-disable arrow-body-style, no-unused-vars */
const AVATAR_CHECKER_FUNCTIONS = [
(participant: IParticipant) => {
return isJigasiParticipant(participant) ? JIGASI_PARTICIPANT_ICON : null;
return participant?.isJigasi ? JIGASI_PARTICIPANT_ICON : null;
},
(participant: IParticipant) => {
return isWhiteboardParticipant(participant) ? WHITEBOARD_PARTICIPANT_ICON : null;
@@ -281,16 +281,6 @@ export function getFakeParticipants(stateful: IStateful) {
return toState(stateful)['features/base/participants'].fakeParticipants;
}
/**
* Returns whether the fake participant is Jigasi.
*
* @param {IParticipant|undefined} participant - The participant entity.
* @returns {boolean} - True if it's a Jigasi participant.
*/
function isJigasiParticipant(participant?: IParticipant): boolean {
return participant?.fakeParticipant === FakeParticipant.Jigasi;
}
/**
* Returns whether the fake participant is a local screenshare.
*

View File

@@ -80,7 +80,7 @@ import {
} from './functions';
import logger from './logger';
import { PARTICIPANT_JOINED_FILE, PARTICIPANT_LEFT_FILE } from './sounds';
import { FakeParticipant, IJitsiParticipant } from './types';
import { IJitsiParticipant } from './types';
import './subscriber';
@@ -438,7 +438,7 @@ StateListenerRegistry.register(
store.dispatch(participantUpdated({
conference,
id: participant.getId(),
fakeParticipant: value ? FakeParticipant.Jigasi : undefined
isJigasi: value
})),
// eslint-disable-next-line @typescript-eslint/no-unused-vars
'features_screen-sharing': (participant: IJitsiParticipant, value: string) =>

View File

@@ -2,10 +2,10 @@
* The name of the bundled sound file which will be played when new participant
* joins the conference.
*/
export const PARTICIPANT_JOINED_FILE = 'joined.wav';
export const PARTICIPANT_JOINED_FILE = 'joined.mp3';
/**
* The name of the bundled sound file which will be played when any participant
* leaves the conference.
*/
export const PARTICIPANT_LEFT_FILE = 'left.wav';
export const PARTICIPANT_LEFT_FILE = 'left.mp3';

View File

@@ -1,5 +1,4 @@
export enum FakeParticipant {
Jigasi = 'Jigasi',
LocalScreenShare = 'LocalScreenShare',
RemoteScreenShare = 'RemoteScreenShare',
SharedVideo = 'SharedVideo',
@@ -21,6 +20,7 @@ export interface IParticipant {
};
getId?: Function;
id: string;
isJigasi?: boolean;
isReplaced?: boolean;
isReplacing?: number;
jwtId?: string;

View File

@@ -1,4 +1,3 @@
import { Theme } from '@mui/material';
import React, { ReactNode, useCallback } from 'react';
import { makeStyles } from 'tss-react/mui';
@@ -80,7 +79,7 @@ interface IProps {
type: string;
}
const useStyles = makeStyles()((theme: Theme) => {
const useStyles = makeStyles()(theme => {
return {
actionButton: {
...withPixelLineHeight(theme.typography.bodyLongBold),

View File

@@ -1,4 +1,3 @@
import { Theme } from '@mui/material';
import React, { useCallback, useState } from 'react';
import { WithTranslation } from 'react-i18next';
import { makeStyles } from 'tss-react/mui';
@@ -25,7 +24,7 @@ interface IProps extends WithTranslation {
connectionType?: string;
}
const useStyles = makeStyles()((theme: Theme) => {
const useStyles = makeStyles()(theme => {
return {
connectionStatus: {
borderRadius: '6px',

View File

@@ -1,5 +1,4 @@
/* eslint-disable lines-around-comment */
import { Theme } from '@mui/material';
import React, { ReactNode } from 'react';
import { makeStyles } from 'tss-react/mui';
@@ -85,7 +84,7 @@ interface IProps {
videoTrack?: Object;
}
const useStyles = makeStyles()((theme: Theme) => {
const useStyles = makeStyles()(theme => {
return {
subtitle: {
...withPixelLineHeight(theme.typography.heading5),

View File

@@ -136,6 +136,10 @@ class StateListenerRegistry {
* @returns {void}
*/
register(selector: Selector, listener: Listener, options?: RegistrationOptions) {
if (typeof selector !== 'function' || typeof listener !== 'function') {
throw new Error('Invalid selector or listener!');
}
this._selectorListeners.add({
listener,
selector,

View File

@@ -1,3 +1,8 @@
/**
* IMPORTANT: this file is deprecated. All of these colors should be moved to
* the theme instead.
*/
/**
* The application's definition of the default color black.
*/
@@ -18,29 +23,12 @@ export const ColorPalette = {
* the sake of consistency.
*/
black: BLACK,
blackBlue: 'rgb(0, 3, 6)',
blue: '#17A0DB',
blueHighlight: '#1081b2',
buttonUnderlay: '#495258',
darkGrey: '#555555',
darkBackground: 'rgb(19,21,25)',
green: '#40b183',
lightGrey: '#AAAAAA',
overflowMenuItemUnderlay: '#EEEEEE',
red: '#D00000',
transparent: 'rgba(0, 0, 0, 0)',
toggled: 'rgba(255,255,255,.15)',
warning: 'rgb(215, 121, 118)',
white: '#FFFFFF',
/**
* These are colors from the atlaskit to be used on mobile, when needed.
*
* FIXME: Maybe a better solution would be good, or a native packaging of
* the respective atlaskit components.
*/
G400: '#00875A', // Slime
N500: '#42526E', // McFanning
R400: '#DE350B', // Red dirt
Y200: '#FFC400' // Pub mix
white: '#FFFFFF'
};

View File

@@ -2,7 +2,7 @@
import React, { Component, Fragment } from 'react';
import { statsEmitter } from '../../../connection-indicator';
import statsEmitter from '../../../connection-indicator/statsEmitter';
import { getLocalParticipant } from '../../participants';
import { connect } from '../../redux';
import { isTestModeEnabled } from '../functions';

View File

@@ -1,4 +1,3 @@
import { Theme } from '@mui/material';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { makeStyles } from 'tss-react/mui';
@@ -47,7 +46,7 @@ interface IProps extends IButtonProps {
testId?: string;
}
const useStyles = makeStyles()((theme: Theme) => {
const useStyles = makeStyles()(theme => {
return {
button: {
backgroundColor: theme.palette.action01,
@@ -143,7 +142,7 @@ const useStyles = makeStyles()((theme: Theme) => {
},
iconButton: {
padding: '10px'
padding: theme.spacing(2)
},
textWithIcon: {
@@ -166,7 +165,7 @@ const useStyles = makeStyles()((theme: Theme) => {
...withPixelLineHeight(theme.typography.bodyShortBoldLarge),
'&.iconButton': {
padding: '14px'
padding: '12px'
}
},

View File

@@ -1,4 +1,3 @@
import { Theme } from '@mui/material';
import React from 'react';
import { makeStyles } from 'tss-react/mui';
@@ -40,7 +39,7 @@ interface ICheckboxProps {
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
}
const useStyles = makeStyles()((theme: Theme) => {
const useStyles = makeStyles()(theme => {
return {
formControl: {
...withPixelLineHeight(theme.typography.bodyLongRegular),

View File

@@ -1,4 +1,3 @@
import { Theme } from '@mui/material';
import React from 'react';
import { makeStyles } from 'tss-react/mui';
@@ -12,7 +11,7 @@ interface IProps {
onClick: () => void;
}
const useStyles = makeStyles()((theme: Theme) => {
const useStyles = makeStyles()(theme => {
return {
button: {
padding: '2px',

View File

@@ -1,4 +1,3 @@
import { Theme } from '@mui/material';
import React, { ReactNode, useEffect, useLayoutEffect, useRef, useState } from 'react';
import { useSelector } from 'react-redux';
import { makeStyles } from 'tss-react/mui';
@@ -104,7 +103,7 @@ interface IProps {
const MAX_HEIGHT = 400;
const useStyles = makeStyles()((theme: Theme) => {
const useStyles = makeStyles()(theme => {
return {
contextMenu: {
backgroundColor: theme.palette.ui01,

View File

@@ -1,4 +1,3 @@
import { Theme } from '@mui/material';
import React, { ReactNode } from 'react';
import { useSelector } from 'react-redux';
import { makeStyles } from 'tss-react/mui';
@@ -71,7 +70,7 @@ export interface IProps {
textClassName?: string;
}
const useStyles = makeStyles()((theme: Theme) => {
const useStyles = makeStyles()(theme => {
return {
contextMenuItem: {
alignItems: 'center',

View File

@@ -1,4 +1,3 @@
import { Theme } from '@mui/material';
import React, { ReactNode } from 'react';
import { makeStyles } from 'tss-react/mui';
@@ -18,7 +17,7 @@ interface IProps {
children?: ReactNode;
}
const useStyles = makeStyles()((theme: Theme) => {
const useStyles = makeStyles()(theme => {
return {
contextMenuItemGroup: {
'&:not(:empty)': {

View File

@@ -1,4 +1,3 @@
import { Theme } from '@mui/material';
import React, { useCallback, useContext, useEffect } from 'react';
import FocusLock from 'react-focus-lock';
import { useTranslation } from 'react-i18next';
@@ -15,7 +14,7 @@ import ClickableIcon from './ClickableIcon';
import { DialogTransitionContext } from './DialogTransition';
const useStyles = makeStyles()((theme: Theme) => {
const useStyles = makeStyles()(theme => {
return {
container: {
width: '100%',
@@ -191,6 +190,7 @@ interface IDialogProps {
children?: React.ReactNode;
className?: string;
description?: string;
disableAutoHideOnSubmit?: boolean;
disableBackdropClose?: boolean;
disableEnter?: boolean;
hideCloseButton?: boolean;
@@ -212,6 +212,7 @@ const Dialog = ({
children,
className,
description,
disableAutoHideOnSubmit = false,
disableBackdropClose,
hideCloseButton,
disableEnter,
@@ -233,7 +234,7 @@ const Dialog = ({
}, [ onCancel ]);
const submit = useCallback(() => {
dispatch(hideDialog());
!disableAutoHideOnSubmit && dispatch(hideDialog());
onSubmit?.();
}, [ onSubmit ]);

View File

@@ -2,18 +2,29 @@ import React, { ReactElement, useEffect, useState } from 'react';
export const DialogTransitionContext = React.createContext({ isUnmounting: false });
type TimeoutType = ReturnType<typeof setTimeout>;
const DialogTransition = ({ children }: { children: ReactElement | null; }) => {
const [ childrenToRender, setChildrenToRender ] = useState(children);
const [ isUnmounting, setIsUnmounting ] = useState(false);
const [ timeoutID, setTimeoutID ] = useState<TimeoutType | undefined>(undefined);
useEffect(() => {
if (children === null) {
setIsUnmounting(true);
setTimeout(() => {
setChildrenToRender(children);
setIsUnmounting(false);
}, 150);
if (typeof timeoutID === 'undefined') {
setTimeoutID(setTimeout(() => {
setChildrenToRender(children);
setIsUnmounting(false);
setTimeoutID(undefined);
}, 150));
}
} else {
if (typeof timeoutID !== 'undefined') {
clearTimeout(timeoutID);
setTimeoutID(undefined);
setIsUnmounting(false);
}
setChildrenToRender(children);
}
}, [ children ]);

View File

@@ -1,4 +1,3 @@
import { Theme } from '@mui/material';
import React, { useCallback } from 'react';
import TextareaAutosize from 'react-textarea-autosize';
import { makeStyles } from 'tss-react/mui';
@@ -26,7 +25,7 @@ interface IProps extends IInputProps {
type?: 'text' | 'email' | 'number' | 'password';
}
const useStyles = makeStyles()((theme: Theme) => {
const useStyles = makeStyles()(theme => {
return {
inputContainer: {
display: 'flex',

View File

@@ -1,4 +1,3 @@
import { Theme } from '@mui/material';
import React, { ChangeEvent } from 'react';
import { makeStyles } from 'tss-react/mui';
@@ -53,7 +52,7 @@ interface ISelectProps {
value: number | string;
}
const useStyles = makeStyles()((theme: Theme) => {
const useStyles = makeStyles()(theme => {
return {
container: {
display: 'flex',

View File

@@ -1,4 +1,3 @@
import { Theme } from '@mui/material';
import React, { useCallback } from 'react';
import { makeStyles } from 'tss-react/mui';
@@ -15,7 +14,7 @@ interface IProps extends ISwitchProps {
id?: string;
}
const useStyles = makeStyles()((theme: Theme) => {
const useStyles = makeStyles()(theme => {
return {
container: {
position: 'relative',

View File

@@ -1,4 +1,3 @@
import { Theme } from '@mui/material';
import React, { useCallback } from 'react';
import { makeStyles } from 'tss-react/mui';
@@ -18,7 +17,7 @@ interface ITabProps {
}>;
}
const useStyles = makeStyles()((theme: Theme) => {
const useStyles = makeStyles()(theme => {
return {
container: {
display: 'flex'

View File

@@ -1,4 +1,3 @@
import { Theme } from '@mui/material';
import React from 'react';
import { WithTranslation } from 'react-i18next';
import { makeStyles } from 'tss-react/mui';
@@ -17,7 +16,7 @@ export interface INewMessagesButtonProps extends WithTranslation {
onGoToFirstUnreadMessage: () => void;
}
const useStyles = makeStyles()((theme: Theme) => {
const useStyles = makeStyles()(theme => {
return {
container: {
position: 'absolute',

View File

@@ -4,4 +4,4 @@
*
* @type {string}
*/
export const INCOMING_MSG_SOUND_FILE = 'incomingMessage.wav';
export const INCOMING_MSG_SOUND_FILE = 'incomingMessage.mp3';

View File

@@ -2,7 +2,7 @@
import { useIsFocused } from '@react-navigation/native';
import React, { useEffect } from 'react';
import { BackHandler, NativeModules, SafeAreaView, StatusBar, View } from 'react-native';
import { BackHandler, NativeModules, SafeAreaView, View } from 'react-native';
import { withSafeAreaInsets } from 'react-native-safe-area-context';
import { appNavigate } from '../../../app/actions';
@@ -268,8 +268,7 @@ class Conference extends AbstractConference<Props, State> {
*/
render() {
const {
_brandingStyles,
_fullscreenEnabled
_brandingStyles
} = this.props;
return (
@@ -279,10 +278,6 @@ class Conference extends AbstractConference<Props, State> {
_brandingStyles
] }>
<BrandingImageBackground />
<StatusBar
barStyle = 'light-content'
hidden = { _fullscreenEnabled }
translucent = { _fullscreenEnabled } />
{ this._renderContent() }
</Container>
);

View File

@@ -1,4 +1,5 @@
/* eslint-disable lines-around-comment */
import React from 'react';
import { StyleProp, Text, View, ViewStyle } from 'react-native';
import { useSelector } from 'react-redux';
@@ -57,7 +58,9 @@ const TitleBar = (props: IProps): JSX.Element => {
<VideoQualityLabel />
</View>
<ConnectionIndicator
// @ts-ignore
iconStyle = { styles.connectionIndicatorIcon }
// @ts-ignore
participantId = { localParticipantId } />
<View style = { styles.headerLabels as StyleProp<ViewStyle> }>
<RecordingLabel mode = { JitsiRecordingConstants.mode.FILE } />

View File

@@ -4,7 +4,7 @@ import Tooltip from '@atlaskit/tooltip';
import React from 'react';
import { translate } from '../../../base/i18n';
import { IconWarning } from '../../../base/icons';
import { IconExclamationTriangle } from '../../../base/icons/svg';
import { Label } from '../../../base/label';
import { COLORS } from '../../../base/label/constants';
import { connect } from '../../../base/redux';
@@ -26,7 +26,7 @@ class InsecureRoomNameLabel extends AbstractInsecureRoomNameLabel {
position = 'bottom'>
<Label
color = { COLORS.red }
icon = { IconWarning } />
icon = { IconExclamationTriangle } />
</Tooltip>
);
}

View File

@@ -1,4 +1,3 @@
import { Theme } from '@mui/material';
import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { useDispatch, useSelector } from 'react-redux';
@@ -12,7 +11,7 @@ import Label from '../../../base/label/components/web/Label';
import { Tooltip } from '../../../base/tooltip';
import { open as openParticipantsPane } from '../../../participants-pane/actions';
const useStyles = makeStyles()((theme: Theme) => {
const useStyles = makeStyles()(theme => {
return {
label: {
backgroundColor: theme.palette.warning02,

View File

@@ -209,7 +209,7 @@ class AbstractConnectionIndicator<P: Props, S: State> extends Component<P, S> {
*/
export function mapStateToProps(state: Object) {
return {
_autoHideTimeout: state['features/base/config'].connectionIndicators.autoHideTimeout ?? defaultAutoHideTimeout
_autoHideTimeout: state['features/base/config'].connectionIndicators?.autoHideTimeout ?? defaultAutoHideTimeout
};
}

View File

@@ -1,3 +0,0 @@
// @flow
export * from './native';

View File

@@ -1,3 +0,0 @@
// @flow
export * from './web';

View File

@@ -1,68 +0,0 @@
// @flow
import React from 'react';
import { View } from 'react-native';
import { IconConnection } from '../../../base/icons';
import { BaseIndicator } from '../../../base/react';
import { connect } from '../../../base/redux';
import indicatorStyles from '../../../filmstrip/components/native/styles';
import AbstractConnectionIndicator, {
type Props,
type State
} from '../AbstractConnectionIndicator';
import { CONNECTOR_INDICATOR_COLORS, iconStyle } from './styles';
/**
* Implements an indicator to show the quality of the connection of a participant.
*/
class ConnectionIndicator extends AbstractConnectionIndicator<Props, State> {
/**
* Initializes a new {@code ConnectionIndicator} instance.
*
* @inheritdoc
*/
constructor(props: Props) {
super(props);
this.state = {
autoHideTimeout: undefined,
showIndicator: false,
stats: {}
};
}
/**
* Implements React's {@link Component#render()}.
*
* @inheritdoc
* @returns {ReactElement}
*/
render() {
const { showIndicator, stats } = this.state;
const { percent } = stats;
if (!showIndicator || typeof percent === 'undefined') {
return null;
}
// Signal level on a scale 0..2
const signalLevel = Math.floor(percent / 33.4);
return (
<View
style = {{
...indicatorStyles.indicatorContainer,
backgroundColor: CONNECTOR_INDICATOR_COLORS[signalLevel]
}}>
<BaseIndicator
icon = { IconConnection }
iconStyle = { this.props.iconStyle || iconStyle } />
</View>
);
}
}
export default connect()(ConnectionIndicator);

View File

@@ -0,0 +1,216 @@
/* eslint-disable lines-around-comment */
import React from 'react';
import { View } from 'react-native';
import { IReduxState } from '../../../app/types';
import { IconConnection } from '../../../base/icons/svg';
import { MEDIA_TYPE } from '../../../base/media/constants';
import {
getLocalParticipant,
getParticipantById,
isScreenShareParticipant
} from '../../../base/participants/functions';
// @ts-ignore
import BaseIndicator from '../../../base/react/components/native/BaseIndicator';
import { connect } from '../../../base/redux/functions';
import {
getTrackByMediaTypeAndParticipant
} from '../../../base/tracks/functions.native';
// @ts-ignore
import indicatorStyles from '../../../filmstrip/components/native/styles';
import {
isTrackStreamingStatusInactive,
isTrackStreamingStatusInterrupted
} from '../../functions';
import AbstractConnectionIndicator, {
type Props as AbstractProps,
mapStateToProps as _abstractMapStateToProps
// @ts-ignore
} from '../AbstractConnectionIndicator';
import {
CONNECTOR_INDICATOR_COLORS,
CONNECTOR_INDICATOR_LOST,
CONNECTOR_INDICATOR_OTHER,
iconStyle
} from './styles';
type IProps = AbstractProps & {
/**
* Whether connection indicators are disabled or not.
*/
_connectionIndicatorDisabled: boolean;
/**
* Whether the inactive connection indicator is disabled or not.
*/
_connectionIndicatorInactiveDisabled: boolean;
/**
* Whether the connection is inactive or not.
*/
_isConnectionStatusInactive: boolean;
/**
* Whether the connection is interrupted or not.
*/
_isConnectionStatusInterrupted: boolean;
/**
* Whether the current participant is a virtual screenshare.
*/
_isVirtualScreenshareParticipant: boolean;
/**
* Redux dispatch function.
*/
dispatch: Function;
/**
* Icon style override.
*/
iconStyle: any;
};
type IState = {
autoHideTimeout: number | undefined;
showIndicator: boolean;
stats: any;
};
/**
* Implements an indicator to show the quality of the connection of a participant.
*/
class ConnectionIndicator extends AbstractConnectionIndicator<IProps, IState> {
/**
* Initializes a new {@code ConnectionIndicator} instance.
*
* @inheritdoc
*/
constructor(props: IProps) {
super(props);
// @ts-ignore
this.state = {
autoHideTimeout: undefined,
showIndicator: false,
stats: {}
};
}
/**
* Get the icon configuration from CONNECTOR_INDICATOR_COLORS which has a percentage
* that matches or exceeds the passed in percentage. The implementation
* assumes CONNECTOR_INDICATOR_COLORS is already sorted by highest to lowest
* percentage.
*
* @param {number} percent - The connection percentage, out of 100, to find
* the closest matching configuration for.
* @private
* @returns {Object}
*/
_getDisplayConfiguration(percent: number): any {
return CONNECTOR_INDICATOR_COLORS.find(x => percent >= x.percent) || {};
}
/**
* Implements React's {@link Component#render()}.
*
* @inheritdoc
* @returns {ReactElement}
*/
render() {
const {
_connectionIndicatorInactiveDisabled,
_connectionIndicatorDisabled,
_isVirtualScreenshareParticipant,
_isConnectionStatusInactive,
_isConnectionStatusInterrupted
// @ts-ignore
} = this.props;
const {
showIndicator,
stats
// @ts-ignore
} = this.state;
const { percent } = stats;
if (!showIndicator || typeof percent === 'undefined'
|| _connectionIndicatorDisabled || _isVirtualScreenshareParticipant) {
return null;
}
let indicatorColor;
if (_isConnectionStatusInactive) {
if (_connectionIndicatorInactiveDisabled) {
return null;
}
indicatorColor = CONNECTOR_INDICATOR_OTHER;
} else if (_isConnectionStatusInterrupted) {
indicatorColor = CONNECTOR_INDICATOR_LOST;
} else {
const displayConfig = this._getDisplayConfiguration(percent);
if (!displayConfig) {
return null;
}
indicatorColor = displayConfig.color;
}
return (
<View
style = {{
...indicatorStyles.indicatorContainer,
backgroundColor: indicatorColor
}}>
<BaseIndicator
icon = { IconConnection }
// @ts-ignore
iconStyle = { this.props.iconStyle || iconStyle } />
</View>
);
}
}
/**
* Maps part of the Redux state to the props of this component.
*
* @param {Object} state - The Redux state.
* @param {IProps} ownProps - The own props of the component.
* @returns {IProps}
*/
export function _mapStateToProps(state: IReduxState, ownProps: IProps) {
const { participantId } = ownProps;
const tracks = state['features/base/tracks'];
const participant = participantId ? getParticipantById(state, participantId) : getLocalParticipant(state);
const _isVirtualScreenshareParticipant = isScreenShareParticipant(participant);
let _isConnectionStatusInactive;
let _isConnectionStatusInterrupted;
if (!_isVirtualScreenshareParticipant) {
const _videoTrack = getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.VIDEO, participantId);
_isConnectionStatusInactive = isTrackStreamingStatusInactive(_videoTrack);
_isConnectionStatusInterrupted = isTrackStreamingStatusInterrupted(_videoTrack);
}
return {
..._abstractMapStateToProps(state),
_connectionIndicatorInactiveDisabled:
Boolean(state['features/base/config'].connectionIndicators?.inactiveDisabled),
_connectionIndicatorDisabled:
Boolean(state['features/base/config'].connectionIndicators?.disabled),
_isVirtualScreenshareParticipant,
_isConnectionStatusInactive,
_isConnectionStatusInterrupted
};
}
// @ts-ignore
export default connect(_mapStateToProps)(ConnectionIndicator);

View File

@@ -1,3 +0,0 @@
// @flow
export { default as ConnectionIndicator } from './ConnectionIndicator';

View File

@@ -1,13 +0,0 @@
// @flow
import { ColorPalette } from '../../../base/styles';
export const CONNECTOR_INDICATOR_COLORS = [
ColorPalette.red,
ColorPalette.Y200,
ColorPalette.green
];
export const iconStyle = {
fontSize: 14
};

View File

@@ -0,0 +1,32 @@
/* eslint-disable lines-around-comment */
import BaseTheme from '../../../base/ui/components/BaseTheme.native';
// @ts-ignore
import { INDICATOR_DISPLAY_THRESHOLD } from '../AbstractConnectionIndicator';
export const CONNECTOR_INDICATOR_LOST = BaseTheme.palette.ui05;
export const CONNECTOR_INDICATOR_OTHER = BaseTheme.palette.action01;
export const CONNECTOR_INDICATOR_COLORS = [
// Full (3 bars)
{
color: BaseTheme.palette.success01,
percent: INDICATOR_DISPLAY_THRESHOLD
},
// 2 bars.
{
color: BaseTheme.palette.warning01,
percent: 10
},
// 1 bar.
{
color: BaseTheme.palette.iconError,
percent: 0
}
];
export const iconStyle = {
fontSize: 14
};

View File

@@ -27,7 +27,8 @@ import {
import AbstractConnectionIndicator, {
type Props as AbstractProps,
type State as AbstractState,
INDICATOR_DISPLAY_THRESHOLD
INDICATOR_DISPLAY_THRESHOLD,
mapStateToProps as _abstractMapStateToProps
// @ts-ignore
} from '../AbstractConnectionIndicator';
@@ -386,6 +387,7 @@ export function _mapStateToProps(state: IReduxState, ownProps: Props) {
const _isConnectionStatusInterrupted = isTrackStreamingStatusInterrupted(_videoTrack);
return {
..._abstractMapStateToProps(state),
_connectionIndicatorInactiveDisabled:
Boolean(state['features/base/config'].connectionIndicators?.inactiveDisabled),
_isVirtualScreenshareParticipant: isScreenShareParticipant(participant),

View File

@@ -1,5 +0,0 @@
// @flow
export * from './components';
export { default as statsEmitter } from './statsEmitter';

View File

@@ -637,7 +637,7 @@ class ConnectionStatsTable extends Component<IProps> {
* @returns {ReactElement}
*/
_renderResolution() {
const { resolution, maxEnabledResolution, t, videoSsrc } = this.props;
const { isVirtualScreenshareParticipant, maxEnabledResolution, resolution, t, videoSsrc } = this.props;
let resolutionString = 'N/A';
if (resolution && videoSsrc) {
@@ -646,7 +646,7 @@ class ConnectionStatsTable extends Component<IProps> {
if (width && height) {
resolutionString = `${width}x${height}`;
if (maxEnabledResolution && maxEnabledResolution < 720) {
if (maxEnabledResolution && maxEnabledResolution < 720 && !isVirtualScreenshareParticipant) {
const maxEnabledResolutionTitle = t('connectionindicator.maxEnabledResolution');
resolutionString += ` (${maxEnabledResolutionTitle} ${maxEnabledResolution}p)`;

View File

@@ -5,7 +5,7 @@ import React, { Component } from 'react';
import { translate } from '../../base/i18n/functions';
import Audio from '../../base/media/components/Audio';
const TEST_SOUND_PATH = 'sounds/ring.wav';
const TEST_SOUND_PATH = 'sounds/ring.mp3';
/**
* The type of the React {@code Component} props of {@link AudioOutputPreview}.

View File

@@ -1,5 +1,4 @@
/* eslint-disable lines-around-comment */
import { Theme } from '@mui/material';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useDispatch, useSelector } from 'react-redux';
@@ -50,7 +49,7 @@ interface IProps {
thumbnailType: string;
}
const useStyles = makeStyles()((theme: Theme) => {
const useStyles = makeStyles()(theme => {
return {
displayName: {
...withPixelLineHeight(theme.typography.labelBold),

View File

@@ -1,8 +1,7 @@
import { Theme } from '@mui/material';
import React from 'react';
import { makeStyles } from 'tss-react/mui';
const useStyles = makeStyles()((theme: Theme) => {
const useStyles = makeStyles()(theme => {
const { text01 } = theme.palette;
return {

View File

@@ -1,6 +1,5 @@
/* eslint-disable lines-around-comment */
import { Theme } from '@mui/material';
import React from 'react';
import { useSelector } from 'react-redux';
import { makeStyles } from 'tss-react/mui';
@@ -22,7 +21,7 @@ import { isLayoutTileView } from '../../../video-layout';
import DisplayNameBadge from './DisplayNameBadge';
const useStyles = makeStyles()((theme: Theme) => {
const useStyles = makeStyles()(theme => {
return {
badgeContainer: {
...withPixelLineHeight(theme.typography.bodyShortRegularLarge),

View File

@@ -1,13 +1,12 @@
// @flow
// @ts-expect-error
import { getJitsiMeetTransport } from '../../../modules/transport';
import {
CONFERENCE_FAILED,
CONFERENCE_JOINED,
DATA_CHANNEL_OPENED,
KICKED_OUT
} from '../base/conference';
import { SET_CONFIG } from '../base/config';
} from '../base/conference/actionTypes';
import { SET_CONFIG } from '../base/config/actionTypes';
import { NOTIFY_CAMERA_ERROR, NOTIFY_MIC_ERROR } from '../base/devices/actionTypes';
import { JitsiConferenceErrors } from '../base/lib-jitsi-meet';
import {
@@ -16,21 +15,21 @@ import {
PARTICIPANT_KICKED,
PARTICIPANT_LEFT,
PARTICIPANT_ROLE_CHANGED,
SET_LOADABLE_AVATAR_URL,
SET_LOADABLE_AVATAR_URL
} from '../base/participants/actionTypes';
import {
getDominantSpeakerParticipant,
getLocalParticipant,
getParticipantById
} from '../base/participants';
import { MiddlewareRegistry } from '../base/redux';
import { getBaseUrl } from '../base/util';
import { appendSuffix } from '../display-name';
import { SUBMIT_FEEDBACK_ERROR, SUBMIT_FEEDBACK_SUCCESS } from '../feedback';
import { SET_FILMSTRIP_VISIBLE } from '../filmstrip';
} from '../base/participants/functions';
import MiddlewareRegistry from '../base/redux/MiddlewareRegistry';
import { getBaseUrl } from '../base/util/helpers';
import { appendSuffix } from '../display-name/functions';
import { SUBMIT_FEEDBACK_ERROR, SUBMIT_FEEDBACK_SUCCESS } from '../feedback/actionTypes';
import { SET_FILMSTRIP_VISIBLE } from '../filmstrip/actionTypes';
import './subscriber';
declare var APP: Object;
/**
* The middleware of the feature {@code external-api}.
*
@@ -103,8 +102,8 @@ MiddlewareRegistry.register(store => next => action => {
const state = store.getState();
const { defaultLocalDisplayName } = state['features/base/config'];
const { room } = state['features/base/conference'];
const { loadableAvatarUrl, name, id, email } = getLocalParticipant(state);
const breakoutRoom = APP.conference.roomName.toString() !== room.toLowerCase();
const { loadableAvatarUrl, name, id, email } = getLocalParticipant(state) ?? {};
const breakoutRoom = APP.conference.roomName.toString() !== room?.toLowerCase();
// we use APP.conference.roomName as we do not update state['features/base/conference'].room when
// moving between rooms in case of breakout rooms and it stays always with the name of the main room
@@ -114,7 +113,7 @@ MiddlewareRegistry.register(store => next => action => {
{
displayName: name,
formattedDisplayName: appendSuffix(
name,
name ?? '',
defaultLocalDisplayName
),
avatarURL: loadableAvatarUrl,
@@ -132,7 +131,7 @@ MiddlewareRegistry.register(store => next => action => {
case KICKED_OUT:
APP.API.notifyKickedOut(
{
id: getLocalParticipant(store.getState()).id,
id: getLocalParticipant(store.getState())?.id,
local: true
},
{ id: action.participant ? action.participant.getId() : undefined }
@@ -142,7 +141,7 @@ MiddlewareRegistry.register(store => next => action => {
case NOTIFY_CAMERA_ERROR:
if (action.error) {
APP.API.notifyOnCameraError(
action.error.name, action.error.message);
action.error.name, action.error.message);
}
break;

View File

@@ -1,11 +1,7 @@
// @flow
import { getLocalParticipant } from '../base/participants';
import { StateListenerRegistry } from '../base/redux';
import { appendSuffix } from '../display-name';
import { shouldDisplayTileView } from '../video-layout';
declare var APP: Object;
import { getLocalParticipant } from '../base/participants/functions';
import StateListenerRegistry from '../base/redux/StateListenerRegistry';
import { appendSuffix } from '../display-name/functions';
import { shouldDisplayTileView } from '../video-layout/functions';
/**
* StateListenerRegistry provides a reliable way of detecting changes to

View File

@@ -25,7 +25,7 @@ import {
getVideoTrackByParticipant,
trackStreamingStatusChanged
} from '../../../base/tracks';
import { ConnectionIndicator } from '../../../connection-indicator';
import ConnectionIndicator from '../../../connection-indicator/components/native/ConnectionIndicator';
import { DisplayNameLabel } from '../../../display-name';
import { getGifDisplayMode, getGifForParticipant } from '../../../gifs/functions';
import {
@@ -191,6 +191,8 @@ class Thumbnail extends PureComponent<Props> {
dispatch(showSharedVideoMenu(_participantId));
}
// TODO: add support for getting info about the virtual screen shares.
if (!_fakeParticipant) {
dispatch(showContextMenuDetails(_participantId, _local));
}

View File

@@ -1,4 +1,3 @@
import { Theme } from '@mui/material';
import React from 'react';
import { useSelector } from 'react-redux';
import { makeStyles } from 'tss-react/mui';
@@ -31,7 +30,7 @@ interface IProps {
tooltipPosition: string;
}
const useStyles = makeStyles()((theme: Theme) => {
const useStyles = makeStyles()(theme => {
return {
raisedHandIndicator: {
backgroundColor: theme.palette.warning02,

View File

@@ -52,10 +52,6 @@ const useStyles = makeStyles()(() => {
'&>div': {
display: 'flex',
overflow: 'hidden'
},
'&:first-child': {
marginLeft: '6px'
}
}
};

View File

@@ -85,6 +85,16 @@ export function getActiveParticipantsIds(_state: any) {
return [];
}
/**
* Not implemented on mobile.
*
* @param {any} _state - Redux state.
* @returns {Array<Object>}
*/
export function getPinnedActiveParticipants(_state: any) {
return [];
}
/**
* Returns the number of participants displayed in tile view.
*

View File

@@ -1,7 +1,6 @@
/* eslint-disable lines-around-comment */
import { GiphyFetch, TrendingOptions } from '@giphy/js-fetch-api';
import { Grid } from '@giphy/react-components';
import { Theme } from '@mui/material';
import React, { useCallback, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { batch, useDispatch, useSelector } from 'react-redux';
@@ -29,7 +28,7 @@ import {
const OVERFLOW_DRAWER_PADDING = 16;
const useStyles = makeStyles()((theme: Theme) => {
const useStyles = makeStyles()(theme => {
return {
gifsMenu: {
width: '100%',

View File

@@ -183,7 +183,7 @@ function AddPeopleDialog({
&& <DialInSection phoneNumber = { _phoneNumber } />
}
{
!_dialInVisible && _isVpaasMeeting && <DialInLimit />
!_phoneNumber && _dialInVisible && _isVpaasMeeting && <DialInLimit />
}
</div>
</Dialog>

View File

@@ -1,4 +1,3 @@
import { Theme } from '@mui/material';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { makeStyles } from 'tss-react/mui';
@@ -15,7 +14,7 @@ interface IProps {
url: string;
}
const useStyles = makeStyles()((theme: Theme) => {
const useStyles = makeStyles()(theme => {
return {
label: {
display: 'block',

View File

@@ -1,4 +1,3 @@
import { Theme } from '@mui/material';
import React from 'react';
import { WithTranslation } from 'react-i18next';
import { makeStyles } from 'tss-react/mui';
@@ -7,7 +6,7 @@ import { translate } from '../../../../base/i18n/functions';
import { withPixelLineHeight } from '../../../../base/styles/functions.web';
import { UPGRADE_OPTIONS_LINK, UPGRADE_OPTIONS_TEXT } from '../../../constants';
const useStyles = makeStyles()((theme: Theme) => {
const useStyles = makeStyles()(theme => {
return {
limitContainer: {
backgroundColor: theme.palette.warning01,

View File

@@ -1,4 +1,3 @@
import { Theme } from '@mui/material';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { useSelector } from 'react-redux';
@@ -21,7 +20,7 @@ interface IProps {
phoneNumber: string;
}
const useStyles = makeStyles()((theme: Theme) => {
const useStyles = makeStyles()(theme => {
return {
container: {
'& .info-label': {

Some files were not shown because too many files have changed in this diff Show More