Compare commits
18 Commits
master
...
join-muc-t
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d1d52c7f54 | ||
|
|
9714e99c4c | ||
|
|
b8408665f7 | ||
|
|
1acdf1c384 | ||
|
|
890597b2e7 | ||
|
|
100b5f8163 | ||
|
|
788a1c55ed | ||
|
|
b2898455e0 | ||
|
|
c05277c1d6 | ||
|
|
be12cdeeff | ||
|
|
171768faa6 | ||
|
|
b9e8981ecc | ||
|
|
31c17cec2d | ||
|
|
0465a9fdda | ||
|
|
b0491d7d2b | ||
|
|
1659b978a9 | ||
|
|
59dc791362 | ||
|
|
863cbab6b0 |
@@ -14,12 +14,3 @@ trim_trailing_whitespace = false
|
||||
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
|
||||
[*.{java,kt}]
|
||||
indent_size = 4
|
||||
|
||||
[*.xml]
|
||||
indent_size = 2
|
||||
|
||||
[*.{swift,m,mm,h}]
|
||||
indent_size = 4
|
||||
|
||||
12
.github/dependabot.yml
vendored
@@ -1,12 +0,0 @@
|
||||
version: 2
|
||||
updates:
|
||||
# Monitor GitHub Actions versions
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
labels:
|
||||
- "dependencies"
|
||||
- "github-actions"
|
||||
commit-message:
|
||||
prefix: "chore(ci)"
|
||||
2
.github/workflows/ci-lua.yml
vendored
@@ -7,7 +7,7 @@ jobs:
|
||||
name: Luacheck
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install luarocks
|
||||
run: sudo apt-get --install-recommends -y install luarocks
|
||||
|
||||
105
.github/workflows/ci.yml
vendored
@@ -7,8 +7,8 @@ jobs:
|
||||
name: Lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f #v6.3.0
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
@@ -42,8 +42,8 @@ jobs:
|
||||
matrix:
|
||||
os: [macos-latest, ubuntu-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f #v6.3.0
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
@@ -59,8 +59,8 @@ jobs:
|
||||
name: Build mobile bundle (Android)
|
||||
runs-on: macos-15
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f #v6.3.0
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
@@ -74,8 +74,8 @@ jobs:
|
||||
name: Build mobile bundle (iOS)
|
||||
runs-on: macos-15
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f #v6.3.0
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
@@ -96,37 +96,17 @@ jobs:
|
||||
ruby-version: '3.4'
|
||||
bundler-cache: true
|
||||
- run: npx react-native info
|
||||
- name: Cache CocoaPods
|
||||
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306
|
||||
with:
|
||||
path: |
|
||||
ios/Pods
|
||||
~/Library/Caches/CocoaPods
|
||||
key: ${{ runner.os }}-cocoapods-${{ hashFiles('ios/Podfile.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-cocoapods-
|
||||
- name: Install Pods
|
||||
working-directory: ./ios
|
||||
run: bundle exec pod install --deployment
|
||||
run: bundle exec pod install --repo-update --deployment
|
||||
- run: npx react-native bundle --entry-file react/index.native.js --platform ios --bundle-output /tmp/ios.bundle --reset-cache
|
||||
android-sdk-build:
|
||||
name: Build mobile SDK (Android)
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: reactnativecommunity/react-native-android:v15.0
|
||||
volumes:
|
||||
- /usr:/host/usr
|
||||
container: reactnativecommunity/react-native-android:v18.0
|
||||
steps:
|
||||
- name: Make space in image by removing preinstalled, but unused SDKs
|
||||
run: |
|
||||
df -h /
|
||||
rm -rf /host/usr/local/lib/android
|
||||
rm -rf /host/usr/local/.ghcup
|
||||
rm -rf /host/usr/share/dotnet
|
||||
rm -rf /host/usr/share/swift
|
||||
df -h /
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f #v6.3.0
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
@@ -135,26 +115,16 @@ jobs:
|
||||
node -v
|
||||
npm -v
|
||||
- run: npm install
|
||||
- name: Cache Gradle dependencies
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57
|
||||
with:
|
||||
path: /root/.gradle
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('android/**/*.gradle*', 'android/gradle.properties', 'android/gradle/wrapper/gradle-wrapper.properties') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- run: |
|
||||
cd android
|
||||
./gradlew :sdk:clean
|
||||
./gradlew :sdk:assembleRelease
|
||||
- run: |
|
||||
git config --global --add safe.directory /__w/jitsi-meet/jitsi-meet
|
||||
git clean -dfx
|
||||
ios-sdk-build:
|
||||
name: Build mobile SDK (iOS)
|
||||
runs-on: macos-15
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f #v6.3.0
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
@@ -169,38 +139,25 @@ jobs:
|
||||
xcode-select -p
|
||||
sudo xcode-select -s /Applications/Xcode_16.2.app/Contents/Developer
|
||||
xcodebuild -version
|
||||
- name: clean Xcode
|
||||
run: |
|
||||
rm -rf ios/sdk/out
|
||||
xcodebuild clean \
|
||||
-workspace ios/jitsi-meet.xcworkspace \
|
||||
-scheme JitsiMeetSDK
|
||||
- name: setup-cocoapods
|
||||
uses: ruby/setup-ruby@4fc31e1c823882afd7ef55985266a526c589de90 #v1.282.0
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: '3.4'
|
||||
bundler-cache: true
|
||||
- name: Cache CocoaPods
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 #v4.2.0
|
||||
with:
|
||||
path: |
|
||||
ios/Pods
|
||||
~/Library/Caches/CocoaPods
|
||||
key: ${{ runner.os }}-pods-${{ hashFiles('ios/Podfile.lock', 'Gemfile.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pods-
|
||||
- run: npx react-native info
|
||||
- name: Install Pods
|
||||
working-directory: ./ios
|
||||
run: bundle exec pod install --deployment
|
||||
run: bundle exec pod install --repo-update --deployment
|
||||
- run: |
|
||||
xcodebuild -downloadPlatform iOS -buildVersion 18.2
|
||||
xcodebuild clean \
|
||||
-workspace ios/jitsi-meet.xcworkspace \
|
||||
-scheme JitsiMeetSDK
|
||||
xcodebuild archive \
|
||||
-workspace ios/jitsi-meet.xcworkspace \
|
||||
-scheme JitsiMeetSDK \
|
||||
-configuration Release \
|
||||
-sdk iphoneos \
|
||||
-destination 'generic/platform=iOS' \
|
||||
-destination='generic/platform=iOS' \
|
||||
-archivePath ios/sdk/out/ios-device \
|
||||
SKIP_INSTALL=NO \
|
||||
BUILD_LIBRARY_FOR_DISTRIBUTION=YES
|
||||
@@ -208,30 +165,12 @@ jobs:
|
||||
-framework ios/sdk/out/ios-device.xcarchive/Products/Library/Frameworks/JitsiMeetSDK.framework \
|
||||
-output ios/sdk/out/JitsiMeetSDK.xcframework
|
||||
- run: ls -lR ios/sdk/out
|
||||
react-native-sdk-build:
|
||||
name: Build mobile SDK (React Native)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f #v6.3.0
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
- name: Check Node / npm versions
|
||||
run: |
|
||||
node -v
|
||||
npm -v
|
||||
- run: npm install
|
||||
- run: |
|
||||
cd react-native-sdk
|
||||
node update_sdk_dependencies.js
|
||||
npm install
|
||||
debian-build:
|
||||
name: Test Debian packages build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f #v6.3.0
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
|
||||
2
.github/workflows/stale.yml
vendored
@@ -7,7 +7,7 @@ jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f #v10.2.0
|
||||
- uses: actions/stale@v8
|
||||
with:
|
||||
stale-issue-message: 'This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.'
|
||||
stale-pr-message: 'This PR has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.'
|
||||
|
||||
267
CLAUDE.md
@@ -1,267 +0,0 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Development Commands
|
||||
|
||||
### Building and Development
|
||||
- `npm run lint-fix` - Automatically fix linting issues
|
||||
- `npm run tsc:ci` - Run TypeScript checks for both web and native platforms
|
||||
- `npm run tsc:web` - TypeScript check for web platform only
|
||||
- `npm run tsc:native` - TypeScript check for native platform only
|
||||
- `npm run lint:ci` - Run ESLint without type checking
|
||||
- `make dev` - Start development server with webpack-dev-server
|
||||
- `make compile` - Build production bundles
|
||||
- `make clean` - Clean build directory
|
||||
- `make all` - Full build (compile + deploy)
|
||||
|
||||
### Testing
|
||||
- `npm test` - Run full test suite using WebDriverIO
|
||||
- `npm run test-single -- <spec-file>` - Run single test file
|
||||
- `npm run test-dev` - Run tests against development environment
|
||||
- `npm run test-dev-single -- <spec-file>` - Run single test in dev mode
|
||||
|
||||
|
||||
### Language Tools
|
||||
- `npm run lang-sort` - Sort language files
|
||||
- `npm run lint:lang` - Validate JSON language files
|
||||
|
||||
### Platform-Specific TypeScript
|
||||
TypeScript configuration is split between web and native platforms with separate tsconfig files.
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
### Multi-Platform Structure
|
||||
Jitsi Meet supports both web and React Native platforms with platform-specific file extensions and directories:
|
||||
- `.web.ts/.web.tsx` - Web-specific implementations
|
||||
- `.native.ts/.native.tsx` - React Native-specific implementations
|
||||
- `.any.ts/.any.tsx` - Shared cross-platform code
|
||||
- `.android.ts/.android.tsx` - Android-specific code
|
||||
- `.ios.ts/.ios.tsx` - iOS-specific code
|
||||
- `web/` directories - Web-specific components and modules
|
||||
- `native/` directories - React Native-specific components and modules
|
||||
- `react/features/mobile/` - Native-only features
|
||||
|
||||
### Core Directories
|
||||
- `react/features/` - Main application features organized by domain (83+ feature modules)
|
||||
- `modules/` - Legacy JavaScript modules and APIs
|
||||
- `css/` - SCSS stylesheets compiled to CSS
|
||||
- `libs/` - Compiled output directory for JavaScript bundles
|
||||
- `static/` - Static assets and HTML files
|
||||
- `tests/` - WebDriverIO end-to-end tests
|
||||
|
||||
### Feature-Driven Architecture
|
||||
The application is organized under `react/features/` with each feature containing:
|
||||
|
||||
- **`actionTypes.ts`** - Redux action type constants
|
||||
- **`actions.ts`** - Redux action creators (platform-specific variants with `.any.ts`, `.web.ts`, `.native.ts`)
|
||||
- **`reducer.ts`** - Redux reducer functions
|
||||
- **`middleware.ts`** - Redux middleware for side effects
|
||||
- **`functions.ts`** - Utility functions and selectors
|
||||
- **`constants.ts`** - Feature-specific constants
|
||||
- **`logger.ts`** - Feature-specific logger instance
|
||||
- **`types.ts`** - TypeScript type definitions
|
||||
|
||||
### Key Application Files
|
||||
- `app.js` - Main web application entry point
|
||||
- `webpack.config.js` - Multi-bundle Webpack configuration
|
||||
- `Makefile` - Build system for development and production
|
||||
- `package.json` - Dependencies and scripts with version requirements
|
||||
|
||||
### Bundle Architecture
|
||||
The application builds multiple bundles:
|
||||
- `app.bundle.js` / `app.bundle.min.js` - Main application bundle (entry: `./app.js`)
|
||||
- `external_api.js` / `external_api.min.js` - External API for embedders (entry: `./modules/API/external/index.js`)
|
||||
- `alwaysontop.js` / `alwaysontop.min.js` - Always-on-top window functionality (entry: `./react/features/always-on-top/index.tsx`)
|
||||
- `close3.js` / `close3.min.js` - Close3 functionality (entry: `./static/close3.js`)
|
||||
- `face-landmarks-worker.js` / `face-landmarks-worker.min.js` - Face landmarks detection worker (entry: `./react/features/face-landmarks/faceLandmarksWorker.ts`)
|
||||
- `noise-suppressor-worklet.js` / `noise-suppressor-worklet.min.js` - Audio noise suppression worklet (entry: `./react/features/stream-effects/noise-suppression/NoiseSuppressorWorklet.ts`)
|
||||
- `screenshot-capture-worker.js` / `screenshot-capture-worker.min.js` - Screenshot capture worker (entry: `./react/features/screenshot-capture/worker.ts`)
|
||||
|
||||
### Redux Architecture
|
||||
Features follow a Redux-based architecture with:
|
||||
- Actions, reducers, and middleware in each feature directory
|
||||
- Cross-platform state management
|
||||
- Modular feature organization with clear boundaries
|
||||
|
||||
The codebase uses a registry-based Redux architecture:
|
||||
- **ReducerRegistry** - Features register their reducers independently
|
||||
- **MiddlewareRegistry** - Features register middleware without cross-dependencies
|
||||
- **IReduxState** - Global state is strongly typed with 80+ feature states
|
||||
|
||||
### Dependencies
|
||||
- Uses `lib-jitsi-meet` as the core WebRTC library
|
||||
- React with TypeScript support
|
||||
- React Native for mobile applications
|
||||
- Webpack for bundling with development server
|
||||
|
||||
### TypeScript Configuration
|
||||
- `tsconfig.web.json` - Web platform TypeScript config (excludes native files)
|
||||
- `tsconfig.native.json` - React Native TypeScript config (excludes web files)
|
||||
- Strict TypeScript settings with ES2024 target
|
||||
- Platform-specific module suffixes (`.web`, `.native`)
|
||||
|
||||
### Key Base Features
|
||||
- **`base/app/`** - Application lifecycle management
|
||||
- **`base/conference/`** - Core conference logic
|
||||
- **`base/tracks/`** - Media track management
|
||||
- **`base/participants/`** - Participant management
|
||||
- **`base/config/`** - Configuration management
|
||||
- **`base/redux/`** - Redux infrastructure
|
||||
|
||||
### Component Patterns
|
||||
- **Abstract Components** - Base classes for cross-platform components
|
||||
- **Platform-Specific Components** - Separate implementations in `web/` and `native/` directories
|
||||
- **Hook-based patterns** - Modern React patterns for component logic
|
||||
### Testing Framework
|
||||
- WebDriverIO for end-to-end testing
|
||||
- Test files are located in `tests/specs/` and use page objects in `tests/pageobjects/`.
|
||||
- Environment configuration via `.env` files
|
||||
- Support for Chrome, Firefox, and grid testing
|
||||
|
||||
## Development Guidelines
|
||||
|
||||
### Adding New Features
|
||||
1. Create feature directory under `react/features/[feature-name]/`
|
||||
2. Follow the standard file structure (actionTypes, actions, reducer, etc.)
|
||||
3. Register reducers and middleware using the registry pattern
|
||||
4. Define TypeScript interfaces for state and props
|
||||
5. Use platform-specific files for web/native differences
|
||||
6. Add feature-specific logger for debugging
|
||||
|
||||
### Working with Existing Features
|
||||
1. Check for existing `.any.ts`, `.web.ts`, `.native.ts` variants
|
||||
2. Follow established action-reducer-middleware patterns
|
||||
3. Use existing base utilities rather than creating new ones
|
||||
4. Leverage abstract components for cross-platform logic
|
||||
5. Maintain type safety across the entire state tree
|
||||
|
||||
### Testing
|
||||
The project uses WebDriver (WebdriverIO) for end-to-end testing. Test files are located in `tests/specs/` and use page objects in `tests/pageobjects/`.
|
||||
|
||||
### Build System
|
||||
- **Webpack** - Main build system for web bundles
|
||||
- **Makefile** - Coordinates build process and asset deployment
|
||||
- **Metro** - React Native bundler (configured in `metro.config.js`)
|
||||
|
||||
### Platform-Specific Notes
|
||||
- Web builds exclude files matching `**/native/*`, `**/*.native.ts`, etc.
|
||||
- Native builds exclude files matching `**/web/*`, `**/*.web.ts`, etc.
|
||||
- Use `moduleSuffixes` in TypeScript config to handle platform-specific imports
|
||||
- Check `tsconfig.web.json` and `tsconfig.native.json` for platform-specific exclusions
|
||||
|
||||
## Environment and Setup Requirements
|
||||
|
||||
### System Requirements
|
||||
- **Node.js and npm** are required
|
||||
- Development server runs at https://localhost:8080/
|
||||
- Certificate errors in development are expected (self-signed certificates)
|
||||
|
||||
### Development Workflow
|
||||
- Development server proxies to configurable target (default: https://alpha.jitsi.net)
|
||||
- Hot module replacement enabled for development
|
||||
- Bundle analysis available via `ANALYZE_BUNDLE=true` environment variable
|
||||
- Circular dependency detection via `DETECT_CIRCULAR_DEPS=true`
|
||||
|
||||
## Code Quality Requirements
|
||||
- All code must pass `npm run lint:ci` and `npm run tsc:ci` with 0 warnings before committing
|
||||
- TypeScript strict mode enabled - avoid `any` type
|
||||
- ESLint config extends `@jitsi/eslint-config`
|
||||
- Prefer TypeScript for new features, convert existing JavaScript when possible
|
||||
|
||||
## Code Style and Standards
|
||||
|
||||
### Conventional Commits Format
|
||||
Follow [Conventional Commits](https://www.conventionalcommits.org) with **mandatory scopes**:
|
||||
```
|
||||
feat(feature-name): description
|
||||
fix(feature-name): description
|
||||
docs(section): description
|
||||
```
|
||||
Available types: build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test
|
||||
|
||||
### Feature Layout Structure
|
||||
When adding new features:
|
||||
```
|
||||
react/features/sample/
|
||||
├── actionTypes.ts
|
||||
├── actions.ts
|
||||
├── components/
|
||||
│ ├── AnotherComponent.tsx
|
||||
│ └── OneComponent.tsx
|
||||
├── middleware.ts
|
||||
└── reducer.ts
|
||||
```
|
||||
|
||||
### TypeScript Requirements
|
||||
- All new features must be written in TypeScript
|
||||
- Convert JavaScript to TypeScript when modifying existing code
|
||||
- Import middleware in `react/features/app/middlewares.{any,native,web}.js`
|
||||
- Import reducers in appropriate registry files
|
||||
- Avoid `index` files
|
||||
|
||||
### Bundle Size Management
|
||||
- Bundle size limits are enforced to prevent bloat
|
||||
- For increases, analyze first: `npx webpack -p --analyze-bundle`
|
||||
- Open analyzer: `npx webpack-bundle-analyzer build/app-stats.json`
|
||||
- Justify any dependency additions that increase bundle size
|
||||
|
||||
## Testing and Quality Assurance
|
||||
|
||||
### Tests
|
||||
- End-to-end tests are defined in the tests/
|
||||
- Tests run automatically for project member PRs via Jenkins
|
||||
- Tests cover peer-to-peer, invites, iOS, Android, and web platforms
|
||||
- Beta testing available at https://beta.meet.jit.si/
|
||||
|
||||
### Manual Testing Checklist
|
||||
- Test with 2 participants (P2P mode)
|
||||
- Test with 3+ participants (JVB mode)
|
||||
- Verify audio/video in both modes
|
||||
- Test mobile apps if changes affect mobile
|
||||
- Check that TLS certificate chain is complete for mobile app compatibility
|
||||
|
||||
## Common Issues and Debugging
|
||||
|
||||
### P2P vs JVB Problems
|
||||
- **Works with 2 participants, fails with 3+**: JVB/firewall issue, check UDP 10000
|
||||
- **Works on web, fails on mobile apps**: TLS certificate chain issue, need fullchain.pem
|
||||
- Use the tests from tests/ directory to verify functionality across platforms
|
||||
|
||||
### Development Server Issues
|
||||
- Certificate warnings are normal for development (self-signed)
|
||||
- Use different backend with WEBPACK_DEV_SERVER_PROXY_TARGET environment variable
|
||||
- Check firewall settings if local development fails
|
||||
|
||||
### Configuration and Customization
|
||||
- Extensive configuration options documented in handbook
|
||||
- See `config.js` for client-side options
|
||||
- Options marked 🚫 are not overwritable through `configOverwrite`
|
||||
- Reference [Configuration Guide](https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-configuration) for details
|
||||
|
||||
## Architecture Deep Dive
|
||||
|
||||
### Core Application Files
|
||||
- **`./conference.js`** - Foundation for user-conference interactions (connection, joining, muting)
|
||||
- **`./modules/external-api`** - External API for iframe integration and events
|
||||
- **`./lang/`** - Translations in `main-[language].json` files
|
||||
- **`./css/`** - SCSS files organized by features, matching React feature structure
|
||||
|
||||
### State Management Flow
|
||||
1. Actions dispatched from components
|
||||
2. Middleware processes side effects
|
||||
3. Reducers update state
|
||||
4. Components re-render based on state changes
|
||||
5. Registry pattern keeps features decoupled
|
||||
|
||||
### Cross-Platform Strategy
|
||||
- Abstract components handle shared logic
|
||||
- Platform files (.web.ts, .native.ts) handle platform differences
|
||||
- Build system excludes irrelevant platform files
|
||||
- TypeScript configs ensure proper platform targeting
|
||||
|
||||
## External Resources
|
||||
- [Jitsi Handbook](https://jitsi.github.io/handbook/) - Comprehensive documentation
|
||||
- [Community Forum](https://community.jitsi.org/) - Ask questions and get support
|
||||
- [Architecture Guide](https://jitsi.github.io/handbook/docs/architecture) - System overview
|
||||
- [Contributing Guidelines](https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-contributing/) - Detailed contribution process
|
||||
26
Gemfile.lock
@@ -25,27 +25,25 @@ GEM
|
||||
json (>= 1.5.1)
|
||||
artifactory (3.0.17)
|
||||
atomos (0.1.3)
|
||||
aws-eventstream (1.4.0)
|
||||
aws-partitions (1.1220.0)
|
||||
aws-sdk-core (3.242.0)
|
||||
aws-eventstream (1.3.1)
|
||||
aws-partitions (1.1050.0)
|
||||
aws-sdk-core (3.218.1)
|
||||
aws-eventstream (~> 1, >= 1.3.0)
|
||||
aws-partitions (~> 1, >= 1.992.0)
|
||||
aws-sigv4 (~> 1.9)
|
||||
base64
|
||||
bigdecimal
|
||||
jmespath (~> 1, >= 1.6.1)
|
||||
logger
|
||||
aws-sdk-kms (1.122.0)
|
||||
aws-sdk-core (~> 3, >= 3.241.4)
|
||||
aws-sdk-kms (1.98.0)
|
||||
aws-sdk-core (~> 3, >= 3.216.0)
|
||||
aws-sigv4 (~> 1.5)
|
||||
aws-sdk-s3 (1.208.0)
|
||||
aws-sdk-core (~> 3, >= 3.234.0)
|
||||
aws-sdk-s3 (1.181.0)
|
||||
aws-sdk-core (~> 3, >= 3.216.0)
|
||||
aws-sdk-kms (~> 1)
|
||||
aws-sigv4 (~> 1.5)
|
||||
aws-sigv4 (1.12.1)
|
||||
aws-sigv4 (1.11.0)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
babosa (1.0.4)
|
||||
base64 (0.3.0)
|
||||
base64 (0.2.0)
|
||||
benchmark (0.4.0)
|
||||
bigdecimal (3.1.9)
|
||||
claide (1.1.0)
|
||||
@@ -104,7 +102,7 @@ GEM
|
||||
ethon (0.16.0)
|
||||
ffi (>= 1.15.0)
|
||||
excon (0.112.0)
|
||||
faraday (1.10.5)
|
||||
faraday (1.10.4)
|
||||
faraday-em_http (~> 1.0)
|
||||
faraday-em_synchrony (~> 1.0)
|
||||
faraday-excon (~> 1.1)
|
||||
@@ -120,10 +118,10 @@ GEM
|
||||
faraday (>= 0.8.0)
|
||||
http-cookie (~> 1.0.0)
|
||||
faraday-em_http (1.0.0)
|
||||
faraday-em_synchrony (1.0.1)
|
||||
faraday-em_synchrony (1.0.0)
|
||||
faraday-excon (1.1.0)
|
||||
faraday-httpclient (1.0.1)
|
||||
faraday-multipart (1.2.0)
|
||||
faraday-multipart (1.1.0)
|
||||
multipart-post (~> 2.0)
|
||||
faraday-net_http (1.0.2)
|
||||
faraday-net_http_persistent (1.2.0)
|
||||
|
||||
15
Makefile
@@ -5,8 +5,8 @@ LIBJITSIMEET_DIR = node_modules/lib-jitsi-meet
|
||||
OLM_DIR = node_modules/@matrix-org/olm
|
||||
TF_WASM_DIR = node_modules/@tensorflow/tfjs-backend-wasm/dist/
|
||||
RNNOISE_WASM_DIR = node_modules/@jitsi/rnnoise-wasm/dist
|
||||
EXCALIDRAW_DIR = node_modules/@jitsi/excalidraw/dist/prod
|
||||
EXCALIDRAW_DIR_DEV = node_modules/@jitsi/excalidraw/dist/dev
|
||||
EXCALIDRAW_DIR = node_modules/@jitsi/excalidraw/dist/excalidraw-assets
|
||||
EXCALIDRAW_DIR_DEV = node_modules/@jitsi/excalidraw/dist/excalidraw-assets-dev
|
||||
TFLITE_WASM = react/features/stream-effects/virtual-background/vendor/tflite
|
||||
MEET_MODELS_DIR = react/features/stream-effects/virtual-background/vendor/models
|
||||
FACE_MODELS_DIR = node_modules/@vladmandic/human-models/models
|
||||
@@ -59,7 +59,6 @@ deploy-appbundle:
|
||||
$(BUILD_DIR)/close3.min.js \
|
||||
$(BUILD_DIR)/close3.min.js.map \
|
||||
$(DEPLOY_DIR) || true
|
||||
cp -r $(BUILD_DIR)/chunks $(DEPLOY_DIR)/chunks
|
||||
|
||||
deploy-lib-jitsi-meet:
|
||||
cp \
|
||||
@@ -87,12 +86,14 @@ deploy-tflite:
|
||||
$(DEPLOY_DIR)
|
||||
|
||||
deploy-excalidraw:
|
||||
mkdir -p $(DEPLOY_DIR)/excalidraw
|
||||
cp -R $(EXCALIDRAW_DIR)/fonts $(DEPLOY_DIR)/excalidraw/
|
||||
cp -R \
|
||||
$(EXCALIDRAW_DIR) \
|
||||
$(DEPLOY_DIR)/
|
||||
|
||||
deploy-excalidraw-dev:
|
||||
mkdir -p $(DEPLOY_DIR)/excalidraw
|
||||
cp -R $(EXCALIDRAW_DIR_DEV)/fonts $(DEPLOY_DIR)/excalidraw/
|
||||
cp -R \
|
||||
$(EXCALIDRAW_DIR_DEV) \
|
||||
$(DEPLOY_DIR)/
|
||||
|
||||
deploy-meet-models:
|
||||
cp \
|
||||
|
||||
@@ -28,14 +28,6 @@ android {
|
||||
ndk {
|
||||
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
|
||||
}
|
||||
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
arguments "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON", "-DANDROID_STL=c++_shared"
|
||||
cppFlags "-std=c++17"
|
||||
cFlags "-DANDROID_PLATFORM=android-26"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
@@ -54,8 +46,8 @@ android {
|
||||
applicationIdSuffix ".debug"
|
||||
}
|
||||
release {
|
||||
// Uncomment the following line for signing a test release build.
|
||||
// signingConfig signingConfigs.debug
|
||||
// Uncomment the following line for singing a test release build.
|
||||
//signingConfig signingConfigs.debug
|
||||
minifyEnabled true
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules-release.pro'
|
||||
buildConfigField "boolean", "GOOGLE_SERVICES_ENABLED", "${googleServicesEnabled}"
|
||||
@@ -110,6 +102,8 @@ dependencies {
|
||||
|
||||
gradle.projectsEvaluated {
|
||||
// Dropbox integration
|
||||
//
|
||||
|
||||
def dropboxAppKey
|
||||
if (project.file('dropbox.key').exists()) {
|
||||
dropboxAppKey = project.file('dropbox.key').text.trim() - 'db-'
|
||||
@@ -180,6 +174,7 @@ gradle.projectsEvaluated {
|
||||
|
||||
packageTask.dependsOn(currentRunPackagerTask)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (googleServicesEnabled) {
|
||||
|
||||
@@ -6,5 +6,6 @@
|
||||
-keep public class * extends java.lang.Exception
|
||||
|
||||
# R8 missing classes - suppress warnings
|
||||
-dontwarn com.facebook.fresco.ui.common.LoggingListener
|
||||
-dontwarn com.facebook.memory.config.MemorySpikeConfig
|
||||
-dontwarn kotlinx.parcelize.Parcelize
|
||||
|
||||
5
android/app/proguard-rules.pro
vendored
@@ -96,3 +96,8 @@
|
||||
|
||||
# Rule to avoid build errors related to SVGs.
|
||||
-keep public class com.horcrux.svg.** {*;}
|
||||
|
||||
# https://github.com/facebook/fresco/issues/2638
|
||||
-keep public class com.facebook.imageutils.** {
|
||||
public *;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#17A0DB</color>
|
||||
<color name="navigationBarColor">#040404</color>
|
||||
<color name="statusBarColor">#040404</color>
|
||||
<color name="navigationBarColor">#161618</color>
|
||||
</resources>
|
||||
@@ -3,7 +3,6 @@
|
||||
<item name="android:editTextBackground">@drawable/rn_edit_text_material</item>
|
||||
<item name="android:forceDarkAllowed">false</item>
|
||||
<item name="android:navigationBarColor">@color/navigationBarColor</item>
|
||||
<item name="android:statusBarColor">@color/statusBarColor</item>
|
||||
<item name="android:windowDisablePreview">true</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
||||
@@ -7,11 +7,11 @@ import org.gradle.util.VersionNumber
|
||||
buildscript {
|
||||
ext {
|
||||
kotlinVersion = "2.0.21"
|
||||
gradlePluginVersion = "8.6.0"
|
||||
buildToolsVersion = "35.0.0"
|
||||
compileSdkVersion = 35
|
||||
gradlePluginVersion = "8.4.2"
|
||||
buildToolsVersion = "34.0.0"
|
||||
compileSdkVersion = 34
|
||||
minSdkVersion = 26
|
||||
targetSdkVersion = 35
|
||||
targetSdkVersion = 34
|
||||
supportLibVersion = "28.0.0"
|
||||
ndkVersion = "27.1.12297006"
|
||||
|
||||
@@ -75,6 +75,26 @@ allprojects {
|
||||
}
|
||||
}
|
||||
|
||||
// Due to a dependency conflict between React Native and the Fresco library used by GiphySDK,
|
||||
// GIFs appear as static images instead of animating
|
||||
// https://github.com/Giphy/giphy-react-native-sdk/commit/7fe466ed6fddfaec95f9cbc959d33bd75ad8f900
|
||||
|
||||
configurations.configureEach {
|
||||
resolutionStrategy {
|
||||
forcedModules = [
|
||||
'com.facebook.fresco:fresco:3.2.0',
|
||||
'com.facebook.fresco:animated-gif:3.2.0',
|
||||
'com.facebook.fresco:animated-base:3.2.0',
|
||||
'com.facebook.fresco:animated-drawable:3.2.0',
|
||||
'com.facebook.fresco:animated-webp:3.2.0',
|
||||
'com.facebook.fresco:webpsupport:3.2.0',
|
||||
'com.facebook.fresco:imagepipeline-okhttp3:3.2.0',
|
||||
'com.facebook.fresco:middleware:3.2.0',
|
||||
'com.facebook.fresco:nativeimagetranscoder:3.2.0'
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
// Third-party react-native modules which Jitsi Meet SDK for Android depends
|
||||
// on and which are not available in third-party Maven repositories need to
|
||||
// be deployed in a Maven repository of ours.
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
#!/bin/bash
|
||||
progname="${0##*/}"
|
||||
progname="${progname%.sh}"
|
||||
|
||||
# usage: check_elf_alignment.sh [path to *.so files|path to *.apk]
|
||||
|
||||
cleanup_trap() {
|
||||
if [ -n "${tmp}" -a -d "${tmp}" ]; then
|
||||
rm -rf ${tmp}
|
||||
fi
|
||||
exit $1
|
||||
}
|
||||
|
||||
usage() {
|
||||
echo "Host side script to check the ELF alignment of shared libraries."
|
||||
echo "Shared libraries are reported ALIGNED when their ELF regions are"
|
||||
echo "16 KB or 64 KB aligned. Otherwise they are reported as UNALIGNED."
|
||||
echo
|
||||
echo "Usage: ${progname} [input-path|input-APK|input-APEX]"
|
||||
}
|
||||
|
||||
if [ ${#} -ne 1 ]; then
|
||||
usage
|
||||
exit
|
||||
fi
|
||||
|
||||
case ${1} in
|
||||
--help | -h | -\?)
|
||||
usage
|
||||
exit
|
||||
;;
|
||||
|
||||
*)
|
||||
dir="${1}"
|
||||
;;
|
||||
esac
|
||||
|
||||
if ! [ -f "${dir}" -o -d "${dir}" ]; then
|
||||
echo "Invalid file: ${dir}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "${dir}" == *.apk ]]; then
|
||||
trap 'cleanup_trap' EXIT
|
||||
|
||||
echo
|
||||
echo "Recursively analyzing $dir"
|
||||
echo
|
||||
|
||||
if { zipalign --help 2>&1 | grep -q "\-P <pagesize_kb>"; }; then
|
||||
echo "=== APK zip-alignment ==="
|
||||
zipalign -v -c -P 16 4 "${dir}" | egrep 'lib/arm64-v8a|lib/x86_64|Verification'
|
||||
echo "========================="
|
||||
else
|
||||
echo "NOTICE: Zip alignment check requires build-tools version 35.0.0-rc3 or higher."
|
||||
echo " You can install the latest build-tools by running the below command"
|
||||
echo " and updating your \$PATH:"
|
||||
echo
|
||||
echo " sdkmanager \"build-tools;35.0.0-rc3\""
|
||||
fi
|
||||
|
||||
dir_filename=$(basename "${dir}")
|
||||
tmp=$(mktemp -d -t "${dir_filename%.apk}_out_XXXXX")
|
||||
unzip "${dir}" lib/* -d "${tmp}" >/dev/null 2>&1
|
||||
dir="${tmp}"
|
||||
fi
|
||||
|
||||
if [[ "${dir}" == *.apex ]]; then
|
||||
trap 'cleanup_trap' EXIT
|
||||
|
||||
echo
|
||||
echo "Recursively analyzing $dir"
|
||||
echo
|
||||
|
||||
dir_filename=$(basename "${dir}")
|
||||
tmp=$(mktemp -d -t "${dir_filename%.apex}_out_XXXXX")
|
||||
deapexer extract "${dir}" "${tmp}" || { echo "Failed to deapex." && exit 1; }
|
||||
dir="${tmp}"
|
||||
fi
|
||||
|
||||
RED="\e[31m"
|
||||
GREEN="\e[32m"
|
||||
ENDCOLOR="\e[0m"
|
||||
|
||||
unaligned_libs=()
|
||||
|
||||
echo
|
||||
echo "=== ELF alignment ==="
|
||||
|
||||
matches="$(find "${dir}" -type f)"
|
||||
IFS=$'\n'
|
||||
for match in $matches; do
|
||||
# We could recursively call this script or rewrite it to though.
|
||||
[[ "${match}" == *".apk" ]] && echo "WARNING: doesn't recursively inspect .apk file: ${match}"
|
||||
[[ "${match}" == *".apex" ]] && echo "WARNING: doesn't recursively inspect .apex file: ${match}"
|
||||
|
||||
[[ $(file "${match}") == *"ELF"* ]] || continue
|
||||
|
||||
res="$(objdump -p "${match}" | grep LOAD | awk '{ print $NF }' | head -1)"
|
||||
if [[ $res =~ 2\*\*(1[4-9]|[2-9][0-9]|[1-9][0-9]{2,}) ]]; then
|
||||
echo -e "${match}: ${GREEN}ALIGNED${ENDCOLOR} ($res)"
|
||||
else
|
||||
echo -e "${match}: ${RED}UNALIGNED${ENDCOLOR} ($res)"
|
||||
unaligned_libs+=("${match}")
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ${#unaligned_libs[@]} -gt 0 ]; then
|
||||
echo -e "${RED}Found ${#unaligned_libs[@]} unaligned libs (only arm64-v8a/x86_64 libs need to be aligned).${ENDCOLOR}"
|
||||
elif [ -n "${dir_filename}" ]; then
|
||||
echo -e "ELF Verification Successful"
|
||||
fi
|
||||
echo "====================="
|
||||
@@ -44,8 +44,10 @@ dependencies {
|
||||
api "com.facebook.react:react-android:$rootProject.ext.rnVersion"
|
||||
api "com.facebook.react:hermes-android:$rootProject.ext.rnVersion"
|
||||
|
||||
implementation 'com.facebook.fresco:animated-gif:2.5.0'
|
||||
implementation 'com.dropbox.core:dropbox-core-sdk:4.0.1'
|
||||
implementation 'com.jakewharton.timber:timber:5.0.1'
|
||||
implementation 'com.squareup.duktape:duktape-android:1.3.0'
|
||||
implementation 'com.google.code.gson:gson:2.8.6'
|
||||
implementation 'androidx.startup:startup-runtime:1.1.0'
|
||||
implementation 'com.google.j2objc:j2objc-annotations:3.0.0'
|
||||
@@ -73,6 +75,7 @@ dependencies {
|
||||
}
|
||||
implementation project(':react-native-gesture-handler')
|
||||
implementation project(':react-native-get-random-values')
|
||||
implementation project(':react-native-immersive-mode')
|
||||
implementation project(':react-native-keep-awake')
|
||||
implementation project(':react-native-orientation-locker')
|
||||
implementation project(':react-native-pager-view')
|
||||
@@ -85,7 +88,6 @@ dependencies {
|
||||
implementation project(':react-native-svg')
|
||||
implementation project(':react-native-video')
|
||||
implementation project(':react-native-webview')
|
||||
implementation project(':react-native-worklets-core')
|
||||
|
||||
// Use `api` here so consumers can use WebRTCModuleOptions.
|
||||
api project(':react-native-webrtc')
|
||||
|
||||
@@ -62,8 +62,7 @@
|
||||
<provider
|
||||
android:name="androidx.startup.InitializationProvider"
|
||||
android:authorities="${applicationId}.androidx-startup"
|
||||
android:exported="false"
|
||||
tools:node="merge">
|
||||
android:exported="false">
|
||||
<meta-data android:name="org.jitsi.meet.sdk.JitsiInitializer"
|
||||
android:value="androidx.startup" />
|
||||
</provider>
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright @ 2019-present 8x8, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import com.facebook.react.bridge.Promise;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
import com.squareup.duktape.Duktape;
|
||||
|
||||
@ReactModule(name = JavaScriptSandboxModule.NAME)
|
||||
class JavaScriptSandboxModule extends ReactContextBaseJavaModule {
|
||||
public static final String NAME = "JavaScriptSandbox";
|
||||
|
||||
public JavaScriptSandboxModule(ReactApplicationContext reactContext) {
|
||||
super(reactContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates the given code in a Duktape VM.
|
||||
* @param code - The code that needs to evaluated.
|
||||
* @param promise - Resolved with the output in case of success or rejected with an exception
|
||||
* in case of failure.
|
||||
*/
|
||||
@ReactMethod
|
||||
public void evaluate(String code, Promise promise) {
|
||||
Duktape vm = Duktape.create();
|
||||
try {
|
||||
Object res = vm.evaluate(code);
|
||||
promise.resolve(res.toString());
|
||||
} catch (Throwable tr) {
|
||||
promise.reject(tr);
|
||||
} finally {
|
||||
vm.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return NAME;
|
||||
}
|
||||
}
|
||||
@@ -24,17 +24,10 @@ import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.res.Configuration;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import com.facebook.react.modules.core.PermissionListener;
|
||||
@@ -94,57 +87,6 @@ public class JitsiMeetActivity extends AppCompatActivity
|
||||
launch(context, options);
|
||||
}
|
||||
|
||||
public static void addTopBottomInsets(@NonNull Window w, @NonNull View v) {
|
||||
|
||||
// Enable edge-to-edge mode
|
||||
androidx.core.view.WindowCompat.setDecorFitsSystemWindows(w, false);
|
||||
|
||||
// Make system bars transparent so content is visible underneath
|
||||
w.setStatusBarColor(android.graphics.Color.TRANSPARENT);
|
||||
w.setNavigationBarColor(android.graphics.Color.TRANSPARENT);
|
||||
|
||||
View decorView = w.getDecorView();
|
||||
|
||||
// Get display metrics for calculating density-independent caps
|
||||
final android.util.DisplayMetrics metrics = v.getContext().getResources().getDisplayMetrics();
|
||||
final int screenHeight = metrics.heightPixels;
|
||||
final float density = metrics.density;
|
||||
|
||||
// Listen for window inset changes
|
||||
// when system bars visibility is toggled or when the device rotates
|
||||
ViewCompat.setOnApplyWindowInsetsListener(decorView, (view, windowInsets) -> {
|
||||
|
||||
// Get the actual inset values reported by the system
|
||||
int statusBarInset = windowInsets.getInsets(WindowInsetsCompat.Type.statusBars()).top;
|
||||
int navBarInset = windowInsets.getInsets(WindowInsetsCompat.Type.navigationBars()).bottom;
|
||||
|
||||
// Calculate maximum allowed inset values to prevent device-specific bugs
|
||||
final int maxTopInset = Math.min((int)(60 * density), (int)(screenHeight * 0.10));
|
||||
final int maxBottomInset = Math.min((int)(120 * density), (int)(screenHeight * 0.10));
|
||||
|
||||
int topInset = Math.min(statusBarInset, maxTopInset);
|
||||
int bottomInset = Math.min(navBarInset, maxBottomInset);
|
||||
|
||||
// Apply calculated insets
|
||||
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
|
||||
|
||||
// Update margins only if they've changed
|
||||
if (params.topMargin != topInset || params.bottomMargin != bottomInset) {
|
||||
params.topMargin = topInset;
|
||||
params.bottomMargin = bottomInset;
|
||||
v.setLayoutParams(params);
|
||||
}
|
||||
|
||||
view.setBackgroundColor(JitsiMeetView.BACKGROUND_COLOR);
|
||||
|
||||
// Return CONSUMED to prevent double-application of margins
|
||||
return WindowInsetsCompat.CONSUMED;
|
||||
});
|
||||
|
||||
// Manually trigger the inset listener to apply margins immediately
|
||||
ViewCompat.requestApplyInsets(decorView);
|
||||
}
|
||||
|
||||
// Overrides
|
||||
//
|
||||
|
||||
@@ -165,13 +107,6 @@ public class JitsiMeetActivity extends AppCompatActivity
|
||||
JitsiMeetActivityDelegate.onHostResume(this);
|
||||
|
||||
setContentView(R.layout.activity_jitsi_meet);
|
||||
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM
|
||||
&& getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
|
||||
addTopBottomInsets(getWindow(), findViewById(android.R.id.content));
|
||||
}
|
||||
|
||||
this.jitsiView = findViewById(R.id.jitsiView);
|
||||
|
||||
registerForBroadcastMessages();
|
||||
|
||||
@@ -37,6 +37,7 @@ public class JitsiMeetActivityDelegate {
|
||||
* React Native module.
|
||||
*/
|
||||
private static PermissionListener permissionListener;
|
||||
private static Callback permissionsCallback;
|
||||
|
||||
/**
|
||||
* Tells whether or not the permissions request is currently in progress.
|
||||
@@ -141,6 +142,11 @@ public class JitsiMeetActivityDelegate {
|
||||
if (reactInstanceManager != null) {
|
||||
reactInstanceManager.onHostResume(activity, new DefaultHardwareBackBtnHandlerImpl(activity));
|
||||
}
|
||||
|
||||
if (permissionsCallback != null) {
|
||||
permissionsCallback.invoke();
|
||||
permissionsCallback = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,10 +169,15 @@ public class JitsiMeetActivityDelegate {
|
||||
|
||||
public static void onRequestPermissionsResult(
|
||||
final int requestCode, final String[] permissions, final int[] grantResults) {
|
||||
// Invoke the callback immediately
|
||||
if (permissionListener != null && permissionListener.onRequestPermissionsResult(requestCode, permissions, grantResults)) {
|
||||
permissionListener = null;
|
||||
}
|
||||
permissionsCallback = new Callback() {
|
||||
@Override
|
||||
public void invoke(Object... args) {
|
||||
if (permissionListener != null
|
||||
&& permissionListener.onRequestPermissionsResult(requestCode, permissions, grantResults)) {
|
||||
permissionListener = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static void requestPermissions(Activity activity, String[] permissions, int requestCode, PermissionListener listener) {
|
||||
|
||||
@@ -99,7 +99,6 @@ public class JitsiMeetOngoingConferenceService extends Service implements Ongoin
|
||||
|
||||
public static void launch(Context context, HashMap<String, Object> extraData) {
|
||||
List<String> permissionsList = new ArrayList<>();
|
||||
Activity activity = (Activity) context;
|
||||
|
||||
PermissionListener listener = new PermissionListener() {
|
||||
@Override
|
||||
@@ -135,7 +134,7 @@ public class JitsiMeetOngoingConferenceService extends Service implements Ongoin
|
||||
|
||||
if (permissionsArray.length > 0) {
|
||||
JitsiMeetActivityDelegate.requestPermissions(
|
||||
activity,
|
||||
(Activity) context,
|
||||
permissionsArray,
|
||||
PERMISSIONS_REQUEST_CODE,
|
||||
listener
|
||||
@@ -160,20 +159,12 @@ public class JitsiMeetOngoingConferenceService extends Service implements Ongoin
|
||||
stopSelf();
|
||||
JitsiMeetLogger.w(TAG + " Couldn't start service, notification is null");
|
||||
} else {
|
||||
try {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
startForeground(NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK | ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE);
|
||||
} else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) {
|
||||
startForeground(NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK);
|
||||
} else {
|
||||
startForeground(NOTIFICATION_ID, notification);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Handle ForegroundServiceStartNotAllowedException when app is in background and cannot start foreground service.
|
||||
// See: https://developer.android.com/develop/background-work/services/fgs/restrictions-bg-start#wiu-restrictions
|
||||
JitsiMeetLogger.w(TAG + " Failed to start foreground service", e);
|
||||
stopSelf();
|
||||
return;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
startForeground(NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK | ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE);
|
||||
} else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) {
|
||||
startForeground(NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK);
|
||||
} else {
|
||||
startForeground(NOTIFICATION_ID, notification);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,16 +30,13 @@ import com.facebook.react.ReactRootView;
|
||||
|
||||
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
|
||||
public class JitsiMeetView extends FrameLayout {
|
||||
|
||||
/**
|
||||
* Background color. Should match the background color set in JS.
|
||||
*/
|
||||
public static final int BACKGROUND_COLOR = 0xFF040404;
|
||||
private static final int BACKGROUND_COLOR = 0xFF040404;
|
||||
|
||||
/**
|
||||
* React Native root view.
|
||||
@@ -87,10 +84,6 @@ public class JitsiMeetView extends FrameLayout {
|
||||
result.putInt(key, (int)bValue);
|
||||
} else if (valueType.contentEquals("Bundle")) {
|
||||
result.putBundle(key, mergeProps((Bundle)aValue, (Bundle)bValue));
|
||||
} else if (valueType.contentEquals("String[]")) {
|
||||
// Convert String[] to ArrayList<String> for React Native bridge compatibility
|
||||
String[] stringArray = (String[]) bValue;
|
||||
result.putStringArrayList(key, new ArrayList<>(Arrays.asList(stringArray)));
|
||||
} else {
|
||||
throw new RuntimeException("Unsupported type: " + valueType);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -64,6 +65,7 @@ class ReactInstanceManagerHolder {
|
||||
new AudioModeModule(reactContext),
|
||||
new DropboxModule(reactContext),
|
||||
new ExternalAPIModule(reactContext),
|
||||
new JavaScriptSandboxModule(reactContext),
|
||||
new LocaleDetector(reactContext),
|
||||
new LogBridgeModule(reactContext),
|
||||
new PictureInPictureModule(reactContext),
|
||||
@@ -101,13 +103,13 @@ class ReactInstanceManagerHolder {
|
||||
new com.oney.WebRTCModule.WebRTCModulePackage(),
|
||||
new com.swmansion.gesturehandler.RNGestureHandlerPackage(),
|
||||
new org.linusu.RNGetRandomValuesPackage(),
|
||||
new com.rnimmersivemode.RNImmersiveModePackage(),
|
||||
new com.swmansion.rnscreens.RNScreensPackage(),
|
||||
new com.zmxv.RNSound.RNSoundPackage(),
|
||||
new com.th3rdwave.safeareacontext.SafeAreaContextPackage(),
|
||||
new com.horcrux.svg.SvgPackage(),
|
||||
new org.wonday.orientation.OrientationPackage(),
|
||||
new com.splashview.SplashViewPackage(),
|
||||
new com.worklets.WorkletsCorePackage(),
|
||||
new ReactPackageAdapter() {
|
||||
@Override
|
||||
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="navigationBarColor">#040404</color>
|
||||
<color name="statusBarColor">#040404</color>
|
||||
</resources>
|
||||
@@ -1,6 +1,3 @@
|
||||
<resources>
|
||||
<style name="JitsiMeetActivityStyle" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
<item name="android:navigationBarColor">@color/navigationBarColor</item>
|
||||
<item name="android:statusBarColor">@color/statusBarColor</item>
|
||||
</style>
|
||||
<style name="JitsiMeetActivityStyle" parent="Theme.AppCompat.Light.NoActionBar"/>
|
||||
</resources>
|
||||
|
||||
@@ -24,6 +24,8 @@ include ':react-native-giphy'
|
||||
project(':react-native-giphy').projectDir = new File(rootProject.projectDir, '../node_modules/@giphy/react-native-sdk/android')
|
||||
include ':react-native-google-signin'
|
||||
project(':react-native-google-signin').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-google-signin/google-signin/android')
|
||||
include ':react-native-immersive-mode'
|
||||
project(':react-native-immersive-mode').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-immersive-mode/android')
|
||||
include ':react-native-keep-awake'
|
||||
project(':react-native-keep-awake').projectDir = new File(rootProject.projectDir, '../node_modules/@sayem314/react-native-keep-awake/android')
|
||||
include ':react-native-orientation-locker'
|
||||
@@ -50,5 +52,3 @@ include ':react-native-webrtc'
|
||||
project(':react-native-webrtc').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webrtc/android')
|
||||
include ':react-native-webview'
|
||||
project(':react-native-webview').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webview/android')
|
||||
include ':react-native-worklets-core'
|
||||
project(':react-native-worklets-core').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-worklets-core/android')
|
||||
|
||||
@@ -8,13 +8,9 @@ module.exports = {
|
||||
|
||||
// This happens because react native has conflict with @babel/plugin-transform-private-methods plugin
|
||||
// https://github.com/ethers-io/ethers.js/discussions/4309#discussioncomment-6694524
|
||||
plugins: [
|
||||
'optional-require',
|
||||
[
|
||||
'@babel/plugin-transform-private-methods', {
|
||||
'loose': true
|
||||
}
|
||||
],
|
||||
'react-native-worklets-core/plugin'
|
||||
plugins: [ 'optional-require',
|
||||
[ '@babel/plugin-transform-private-methods', {
|
||||
'loose': true
|
||||
} ]
|
||||
]
|
||||
};
|
||||
|
||||
@@ -134,7 +134,6 @@ import {
|
||||
isLocalTrackMuted,
|
||||
isUserInteractionRequiredForUnmute
|
||||
} from './react/features/base/tracks/functions';
|
||||
import { getLocalJitsiAudioTrackSettings } from './react/features/base/tracks/functions.web';
|
||||
import { downloadJSON } from './react/features/base/util/downloadJSON';
|
||||
import { getJitsiMeetGlobalNSConnectionTimes } from './react/features/base/util/helpers';
|
||||
import { openLeaveReasonDialog } from './react/features/conference/actions.web';
|
||||
@@ -159,14 +158,13 @@ import { disableReceiver, stopReceiver } from './react/features/remote-control/a
|
||||
import { setScreenAudioShareState } from './react/features/screen-share/actions.web';
|
||||
import { isScreenAudioShared } from './react/features/screen-share/functions';
|
||||
import { toggleScreenshotCaptureSummary } from './react/features/screenshot-capture/actions';
|
||||
import { setAudioSettings } from './react/features/settings/actions.web';
|
||||
import { AudioMixerEffect } from './react/features/stream-effects/audio-mixer/AudioMixerEffect';
|
||||
import { createRnnoiseProcessor } from './react/features/stream-effects/rnnoise';
|
||||
import { handleToggleVideoMuted } from './react/features/toolbox/actions.any';
|
||||
import { transcriberJoined, transcriberLeft } from './react/features/transcribing/actions';
|
||||
import { muteLocal } from './react/features/video-menu/actions.any';
|
||||
|
||||
const logger = Logger.getLogger('app:conference-web');
|
||||
const logger = Logger.getLogger(__filename);
|
||||
let room;
|
||||
|
||||
/*
|
||||
@@ -389,7 +387,6 @@ export default {
|
||||
* Returns an object containing a promise which resolves with the created tracks &
|
||||
* the errors resulting from that process.
|
||||
* @param {object} options
|
||||
* @param {boolean} option.isBreakoutRoom - true if we are creating the initial local tracks in breakout room.
|
||||
* @param {boolean} options.startAudioOnly=false - if <tt>true</tt> then
|
||||
* only audio track will be created and the audio only mode will be turned
|
||||
* on.
|
||||
@@ -404,16 +401,14 @@ export default {
|
||||
*/
|
||||
createInitialLocalTracks(options = {}, recordTimeMetrics = false) {
|
||||
const errors = {};
|
||||
const { isBreakoutRoom = false } = options;
|
||||
|
||||
// Always get a handle on the audio input device so that we have statistics (such as "No audio input" or
|
||||
// "Are you trying to speak?" ) even if the user joins the conference muted.
|
||||
const initialDevices
|
||||
= config.startSilent || (config.disableInitialGUM && !isBreakoutRoom) ? [] : [ MEDIA_TYPE.AUDIO ];
|
||||
const requestedAudio = !config.disableInitialGUM || isBreakoutRoom;
|
||||
const initialDevices = config.startSilent || config.disableInitialGUM ? [] : [ MEDIA_TYPE.AUDIO ];
|
||||
const requestedAudio = !config.disableInitialGUM;
|
||||
let requestedVideo = false;
|
||||
|
||||
if ((!config.disableInitialGUM || isBreakoutRoom)
|
||||
if (!config.disableInitialGUM
|
||||
&& !options.startWithVideoMuted
|
||||
&& !options.startAudioOnly
|
||||
&& !options.startScreenSharing) {
|
||||
@@ -571,15 +566,7 @@ export default {
|
||||
if (browser.isWebKitBased()) {
|
||||
this.muteAudio(true, true);
|
||||
} else {
|
||||
localTracks = localTracks.filter(track => {
|
||||
if (track.getType() === MEDIA_TYPE.AUDIO) {
|
||||
track.stopStream();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
localTracks = localTracks.filter(track => track.getType() !== MEDIA_TYPE.AUDIO);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1378,7 +1365,7 @@ export default {
|
||||
}
|
||||
|
||||
APP.store.dispatch(updateRemoteParticipantFeatures(user));
|
||||
logger.log(`USER ${id} connected`);
|
||||
logger.log(`USER ${id} connected:`, user);
|
||||
APP.UI.addUser(user);
|
||||
});
|
||||
|
||||
@@ -1644,6 +1631,12 @@ export default {
|
||||
JitsiE2ePingEvents.E2E_RTT_CHANGED,
|
||||
(...args) => APP.store.dispatch(e2eRttChanged(...args)));
|
||||
|
||||
room.addCommandListener(this.commands.defaults.ETHERPAD,
|
||||
({ value }) => {
|
||||
APP.UI.initEtherpad(value);
|
||||
}
|
||||
);
|
||||
|
||||
room.addCommandListener(this.commands.defaults.EMAIL, (data, from) => {
|
||||
APP.store.dispatch(participantUpdated({
|
||||
conference: room,
|
||||
@@ -1717,7 +1710,15 @@ export default {
|
||||
}
|
||||
);
|
||||
|
||||
room.on(JitsiConferenceEvents.PERMISSIONS_RECEIVED, p => {
|
||||
const localParticipant = getLocalParticipant(APP.store.getState());
|
||||
|
||||
APP.store.dispatch(participantUpdated({
|
||||
id: localParticipant.id,
|
||||
local: true,
|
||||
features: p
|
||||
}));
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -1762,11 +1763,7 @@ export default {
|
||||
return this.useAudioStream(stream);
|
||||
})
|
||||
.then(() => {
|
||||
const state = APP.store.getState();
|
||||
const localAudio = getLocalJitsiAudioTrack(state);
|
||||
const settings = getLocalJitsiAudioTrackSettings(state);
|
||||
|
||||
APP.store.dispatch(setAudioSettings(settings));
|
||||
const localAudio = getLocalJitsiAudioTrack(APP.store.getState());
|
||||
|
||||
if (localAudio && isDefaultMicSelected) {
|
||||
// workaround for the default device to be shown as selected in the
|
||||
|
||||
70
config.js
@@ -139,9 +139,6 @@ var config = {
|
||||
// Disables polls feature.
|
||||
// disablePolls: false,
|
||||
|
||||
// Disables chat feature entirely including notifications, sounds, and private messages.
|
||||
// disableChat: false,
|
||||
|
||||
// Disables demote button from self-view
|
||||
// disableSelfDemote: false,
|
||||
|
||||
@@ -151,9 +148,6 @@ var config = {
|
||||
// Disables self-view settings in UI
|
||||
// disableSelfViewSettings: false,
|
||||
|
||||
// Shows/hides the moderator setting for chat permissions.
|
||||
// showChatPermissionsModeratorSetting: false,
|
||||
|
||||
// screenshotCapture : {
|
||||
// Enables the screensharing capture feature.
|
||||
// enabled: false,
|
||||
@@ -369,7 +363,6 @@ var config = {
|
||||
// Desktop sharing
|
||||
|
||||
// Optional desktop sharing frame rate options. Default value: min:5, max:5.
|
||||
// Setting higher min/max values will affect the resolution, it makes it worse.
|
||||
// desktopSharingFrameRate: {
|
||||
// min: 5,
|
||||
// max: 5,
|
||||
@@ -511,15 +504,6 @@ var config = {
|
||||
// // ./src/react/features/transcribing/transcriber-langs.json.
|
||||
// preferredLanguage: 'en-US',
|
||||
|
||||
// Allows extending the list of supported transcription languages.
|
||||
// Useful for custom transcription backends (e.g. Vosk).
|
||||
//
|
||||
// Example:
|
||||
// customLanguages: {
|
||||
// 'hsb-DE': 'Upper Sorbian (Germany)',
|
||||
// 'dsb-DE': 'Lower Sorbian (Germany)'
|
||||
// },
|
||||
|
||||
// // Enables automatic turning on transcribing when recording is started
|
||||
// autoTranscribeOnRecord: false,
|
||||
|
||||
@@ -532,6 +516,9 @@ var config = {
|
||||
// // Note: Starting transcriptions from the recording dialog will still work.
|
||||
// disableClosedCaptions: false,
|
||||
|
||||
// // Whether to invite jigasi when backend transcriptions are enabled (asyncTranscription is true in metadata).
|
||||
// // By default, we invite it.
|
||||
// inviteJigasiOnBackendTranscribing: true,
|
||||
// },
|
||||
|
||||
// Misc
|
||||
@@ -646,6 +633,21 @@ var config = {
|
||||
// sticky: 0,
|
||||
// },
|
||||
|
||||
// // Options for the recording limit notification.
|
||||
// recordingLimit: {
|
||||
//
|
||||
// // The recording limit in minutes. Note: This number appears in the notification text
|
||||
// // but doesn't enforce the actual recording time limit. This should be configured in
|
||||
// // jibri!
|
||||
// limit: 60,
|
||||
//
|
||||
// // The name of the app with unlimited recordings.
|
||||
// appName: 'Unlimited recordings APP',
|
||||
//
|
||||
// // The URL of the app with unlimited recordings.
|
||||
// appURL: 'https://unlimited.recordings.app.com/',
|
||||
// },
|
||||
|
||||
// Disables or enables RTX (RFC 4588) (defaults to false).
|
||||
// disableRtx: false,
|
||||
|
||||
@@ -720,8 +722,6 @@ var config = {
|
||||
// autoKnock: false,
|
||||
// // Enables the lobby chat. Replaces `enableLobbyChat`.
|
||||
// enableChat: true,
|
||||
// // Shows the hangup button in the lobby screen.
|
||||
// showHangUp: true,
|
||||
// },
|
||||
|
||||
// Configs for the security related UI elements.
|
||||
@@ -761,7 +761,7 @@ var config = {
|
||||
// hideDominantSpeakerBadge: false,
|
||||
|
||||
// Default language for the user interface. Cannot be overwritten.
|
||||
// For iframe integrations, use the `lang` option directly instead.
|
||||
// DEPRECATED! Use the `lang` iframe option directly instead.
|
||||
// defaultLanguage: 'en',
|
||||
|
||||
// Disables profile and the edit of all fields from the profile settings (display name and email)
|
||||
@@ -791,6 +791,7 @@ var config = {
|
||||
// Configs for prejoin page.
|
||||
// prejoinConfig: {
|
||||
// // When 'true', it shows an intermediate page before joining, where the user can configure their devices.
|
||||
// // This replaces `prejoinPageEnabled`. Defaults to true.
|
||||
// enabled: true,
|
||||
// // Hides the participant name editing field in the prejoin screen.
|
||||
// // If requireDisplayName is also set as true, a name should still be provided through
|
||||
@@ -802,9 +803,7 @@ var config = {
|
||||
// // By setting preCallTestEnabled, you enable the pre-call test in the prejoin page.
|
||||
// // ICE server credentials need to be provided over the preCallTestICEUrl
|
||||
// preCallTestEnabled: false,
|
||||
// preCallTestICEUrl: '',
|
||||
// // Shows the hangup button in the lobby screen.
|
||||
// showHangUp: true,
|
||||
// preCallTestICEUrl: ''
|
||||
// },
|
||||
|
||||
// When 'true', the user cannot edit the display name.
|
||||
@@ -901,8 +900,6 @@ var config = {
|
||||
// alwaysVisible: false,
|
||||
// // Indicates whether the toolbar should still autohide when chat is open
|
||||
// autoHideWhileChatIsOpen: false,
|
||||
// // Default background color for the main toolbar. Accepts any valid CSS color.
|
||||
// // backgroundColor: '#ffffff',
|
||||
// },
|
||||
|
||||
// Overrides the buttons displayed in the main toolbar. Depending on the screen size the number of displayed
|
||||
@@ -921,14 +918,6 @@ var config = {
|
||||
// [ 'microphone', 'camera' ]
|
||||
// ],
|
||||
|
||||
// Enable reduced UI on web.
|
||||
// reducedUIEnabled: true,
|
||||
|
||||
// Overrides the buttons displayed in the main toolbar for reduced UI.
|
||||
// When there isn't an override for a certain configuration the default jitsi-meet configuration will be used.
|
||||
// The order of the buttons in the array is preserved.
|
||||
// reducedUImainToolbarButtons: [ 'microphone', 'camera' ],
|
||||
|
||||
// Toolbar buttons which have their click/tap event exposed through the API on
|
||||
// `toolbarButtonClicked`. Passing a string for the button key will
|
||||
// prevent execution of the click/tap routine; passing an object with `key` and
|
||||
@@ -1374,9 +1363,7 @@ var config = {
|
||||
// disableGrantModerator: true,
|
||||
// // If set to 'all' the 'Private chat' button will be disabled for all participants.
|
||||
// // If set to 'allow-moderator-chat' the 'Private chat' button will be available for chats with moderators.
|
||||
// // If set to 'disable-visitor-chat' the 'Private chat' button will be disabled for visitor-main participant
|
||||
// // conversations.
|
||||
// disablePrivateChat: 'all' | 'allow-moderator-chat' | 'disable-visitor-chat',
|
||||
// disablePrivateChat: 'all' | 'allow-moderator-chat',
|
||||
// },
|
||||
|
||||
|
||||
@@ -1586,13 +1573,14 @@ var config = {
|
||||
// - electron=true (when web is loaded in electron app)
|
||||
// If there is a logout service you can specify its URL with:
|
||||
// tokenLogoutUrl: 'https://myservice.com/logout'
|
||||
// You can enable tokenAuthUrlAutoRedirect which will detect that you have logged in successfully before
|
||||
// and will automatically redirect to the token service to get the token for the meeting.
|
||||
// tokenAuthUrlAutoRedirect: false
|
||||
// An option to respect the context.tenant jwt field compared to the current tenant from the url
|
||||
// tokenRespectTenant: false,
|
||||
// An option to get for user info (name, picture, email) in the token outside the user context.
|
||||
// Can be used with Firebase tokens.
|
||||
// tokenGetUserInfoOutOfContext: false,
|
||||
// An option to pass the token in the iframe API directly instead of using the redirect flow.
|
||||
// tokenAuthInline: false,
|
||||
|
||||
// You can put an array of values to target different entity types in the invite dialog.
|
||||
// Valid values are "phone", "room", "sip", "user", "videosipgw" and "email"
|
||||
@@ -1613,10 +1601,6 @@ var config = {
|
||||
// audio: true,
|
||||
// video: true
|
||||
// },
|
||||
// // Hides the visitor count for visitors.
|
||||
// // hideVisitorCountForVisitors: false,
|
||||
// // Whether to show the join meeting dialog when joining as a visitor.
|
||||
// // showJoinMeetingDialog: true,
|
||||
// },
|
||||
// The default type of desktop sharing sources that will be used in the electron app.
|
||||
// desktopSharingSources: ['screen', 'window'],
|
||||
@@ -1863,10 +1847,6 @@ var config = {
|
||||
// userLimit: 25,
|
||||
// // The url for more info about the whiteboard and its usage limitations.
|
||||
// limitUrl: 'https://example.com/blog/whiteboard-limits',
|
||||
|
||||
// //Backend URL for storing whiteboard scenes and images
|
||||
// //This backend service handles scene persistence and file uploads
|
||||
// storageBackendUrl: 'https://excalidraw-s3-storage-backend.example.com',
|
||||
// },
|
||||
|
||||
// The watchRTC initialize config params as described :
|
||||
|
||||
@@ -45,7 +45,7 @@ body {
|
||||
|
||||
.jitsi-icon {
|
||||
&-default svg {
|
||||
fill: var(--icon-svg-fill, white);
|
||||
fill: white;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.always-on-top-toolbox {
|
||||
background-color: var(--toolbox-background-color, $newToolbarBackgroundColor);
|
||||
background-color: $newToolbarBackgroundColor;
|
||||
border-radius: 3px;
|
||||
display: flex;
|
||||
z-index: $toolbarZ;
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
.reactions-menu {
|
||||
width: 330px;
|
||||
background: var(--reactions-menu-background, #242528);
|
||||
box-shadow: 0px 3px 16px var(--reactions-menu-box-shadow-1, rgba(0, 0, 0, 0.6)), 0px 0px 4px 1px var(--reactions-menu-box-shadow-2, rgba(0, 0, 0, 0.25));
|
||||
background: #242528;
|
||||
box-shadow: 0px 3px 16px rgba(0, 0, 0, 0.6), 0px 0px 4px 1px rgba(0, 0, 0, 0.25);
|
||||
border-radius: 6px;
|
||||
padding: 16px;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
top: 3px;
|
||||
|
||||
& .toolbox-icon.toggled {
|
||||
background-color: var(--reactions-menu-button-toggled, #000000);
|
||||
background-color: #000000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,14 +196,4 @@
|
||||
color:#FFD740;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.youtube-go-live-warning {
|
||||
margin-bottom: 16px;
|
||||
padding: 8px 12px;
|
||||
background-color: rgba(248, 174, 26, 0.1);
|
||||
border-left: 3px solid #FFD740;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem;
|
||||
color: #FFD740;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Round badge.
|
||||
*/
|
||||
.badge-round {
|
||||
background-color: var(--toolbar-badge-background, #165ECC);
|
||||
background-color: #165ECC;
|
||||
border-radius: 50%;
|
||||
box-sizing: border-box;
|
||||
color: #FFFFFF;
|
||||
@@ -93,7 +93,7 @@
|
||||
|
||||
.toolbox-content-wrapper::after {
|
||||
content: '';
|
||||
background: var(--toolbox-background-color, $newToolbarBackgroundColor);
|
||||
background: $newToolbarBackgroundColor;
|
||||
padding-bottom: env(safe-area-inset-bottom, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ $welcomePageHeaderContainerMargin: $welcomePageHeaderContainerMarginTop auto 0;
|
||||
$welcomePageHeaderTextTitleMarginBottom: 0;
|
||||
$welcomePageHeaderTextTitleFontSize: 2.625rem;
|
||||
$welcomePageHeaderTextTitleFontWeight: normal;
|
||||
$welcomePageHeaderTextTitleLineHeight: 3.125rem;
|
||||
$welcomePageHeaderTextTitleLineHeight: 50px;
|
||||
$welcomePageHeaderTextTitleOpacity: 1;
|
||||
|
||||
$welcomePageEnterRoomDisplay: flex;
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
}
|
||||
|
||||
#notification-participant-list {
|
||||
background-color: var(--toolbox-background-color, $newToolbarBackgroundColor);
|
||||
background-color: $newToolbarBackgroundColor;
|
||||
border: 1px solid rgba(255, 255, 255, .4);
|
||||
border-radius: 8px;
|
||||
left: 0;
|
||||
|
||||
@@ -106,7 +106,7 @@
|
||||
}
|
||||
|
||||
#preview {
|
||||
background: var(--prejoin-preview-background, #040404);
|
||||
background: #040404;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
10
custom.d.ts
vendored
@@ -1,14 +1,4 @@
|
||||
declare module '*.css' {
|
||||
const content: Record<string, string>;
|
||||
export default content;
|
||||
}
|
||||
|
||||
declare module '*.svg' {
|
||||
const content: any;
|
||||
export default content;
|
||||
}
|
||||
|
||||
declare module '*.svg?raw' {
|
||||
const content: string;
|
||||
export default content;
|
||||
}
|
||||
|
||||
2
debian/control
vendored
@@ -34,7 +34,7 @@ Description: Configuration for web serving of Jitsi Meet
|
||||
|
||||
Package: jitsi-meet-prosody
|
||||
Architecture: all
|
||||
Depends: openssl, prosody (>= 0.12.0) | prosody-trunk | prosody-0.12 | prosody-13.0, ca-certificates-java, lua-sec, lua-basexx, lua-luaossl, lua-cjson, lua-inspect
|
||||
Depends: openssl, prosody (>= 0.12.0) | prosody-trunk | prosody-0.12 | prosody-13.0, lua-sec, lua-basexx, lua-luaossl, lua-cjson, lua-inspect
|
||||
Replaces: jitsi-meet-tokens
|
||||
Description: Prosody configuration for Jitsi Meet
|
||||
Jitsi Meet is a WebRTC JavaScript application that uses Jitsi
|
||||
|
||||
29
debian/jitsi-meet-prosody.postinst
vendored
@@ -124,17 +124,10 @@ case "$1" in
|
||||
ln -s $PROSODY_HOST_CONFIG /etc/prosody/conf.d/$JVB_HOSTNAME.cfg.lua
|
||||
fi
|
||||
PROSODY_CREATE_JICOFO_USER="true"
|
||||
fi
|
||||
|
||||
if ! grep -q "VirtualHost \"$JVB_HOSTNAME\"" $PROSODY_CONFIG_OLD; then
|
||||
# on some distributions main prosody config doesn't include configs
|
||||
# from conf.d folder enable it as this where we put our config by default
|
||||
# also when upgrading to new prosody version from prosody repo we need to add it again
|
||||
if ! grep -q "Include \"conf\.d\/\*\.cfg.lua\"" $PROSODY_CONFIG_OLD; then
|
||||
echo -e "\nInclude \"conf.d/*.cfg.lua\"" >> $PROSODY_CONFIG_OLD
|
||||
|
||||
# trigger a restart
|
||||
PROSODY_CONFIG_PRESENT="false"
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -161,16 +154,6 @@ case "$1" in
|
||||
PROSODY_CONFIG_PRESENT="false"
|
||||
fi
|
||||
|
||||
# Start using the polls component
|
||||
if ! grep -q "Component \"polls.$JVB_HOSTNAME\"" $PROSODY_HOST_CONFIG ;then
|
||||
echo -e "\nComponent \"polls.$JVB_HOSTNAME\" \"polls_component\"" >> $PROSODY_HOST_CONFIG
|
||||
PROSODY_CONFIG_PRESENT="false"
|
||||
fi
|
||||
if ! grep -q -- '--"polls";' $PROSODY_HOST_CONFIG ;then
|
||||
sed -i "s/\"polls\";/--\"polls\";/g" $PROSODY_HOST_CONFIG
|
||||
PROSODY_CONFIG_PRESENT="false"
|
||||
fi
|
||||
|
||||
# Old versions of jitsi-meet-prosody come with the extra plugin path commented out (https://github.com/jitsi/jitsi-meet/commit/e11d4d3101e5228bf956a69a9e8da73d0aee7949)
|
||||
# Make sure it is uncommented, as it contains required modules.
|
||||
if grep -q -- '--plugin_paths = { "/usr/share/jitsi-meet/prosody-plugins/" }' $PROSODY_HOST_CONFIG ;then
|
||||
@@ -284,17 +267,13 @@ case "$1" in
|
||||
# and drop the wait and the prosody restart
|
||||
sleep 1
|
||||
invoke-rc.d prosody restart || true
|
||||
fi
|
||||
;;
|
||||
triggered)
|
||||
for trigger in $2; do
|
||||
if [ "$trigger" = "update-ca-certificates-java" ]; then
|
||||
echo "Java certificates updated, restarting Jitsi components..."
|
||||
|
||||
# In case we had updated the certificates and restarted prosody, let's restart and the bridge and jicofo if possible
|
||||
if [ -d /run/systemd/system ] && [ "$CERT_ADDED_TO_TRUST" = "true" ]; then
|
||||
systemctl restart jitsi-videobridge2.service >/dev/null || true
|
||||
systemctl restart jicofo.service >/dev/null || true
|
||||
fi
|
||||
done
|
||||
exit 0
|
||||
fi
|
||||
;;
|
||||
|
||||
abort-upgrade|abort-remove|abort-deconfigure)
|
||||
|
||||
1
debian/jitsi-meet-prosody.triggers
vendored
@@ -1 +0,0 @@
|
||||
interest-noawait update-ca-certificates-java
|
||||
@@ -83,6 +83,7 @@ Component "conference.jitmeet.example.com" "muc"
|
||||
"muc_hide_all";
|
||||
"muc_meeting_id";
|
||||
"muc_domain_mapper";
|
||||
"polls";
|
||||
--"token_verification";
|
||||
"muc_rate_limit";
|
||||
"muc_password_whitelist";
|
||||
@@ -158,10 +159,9 @@ Component "lobby.jitmeet.example.com" "muc"
|
||||
modules_enabled = {
|
||||
"muc_hide_all";
|
||||
"muc_rate_limit";
|
||||
"polls";
|
||||
}
|
||||
|
||||
Component "metadata.jitmeet.example.com" "room_metadata_component"
|
||||
muc_component = "conference.jitmeet.example.com"
|
||||
breakout_rooms_component = "breakout.jitmeet.example.com"
|
||||
|
||||
Component "polls.jitmeet.example.com" "polls_component"
|
||||
|
||||
@@ -10,7 +10,6 @@ no-cli
|
||||
no-loopback-peers
|
||||
no-tcp-relay
|
||||
no-tcp
|
||||
no-dtls
|
||||
listening-port=3478
|
||||
tls-listening-port=5349
|
||||
no-tlsv1
|
||||
|
||||
@@ -26,22 +26,6 @@ map $arg_vnode $prosody_node {
|
||||
v7 v7;
|
||||
v8 v8;
|
||||
}
|
||||
# Matches any URI or Referer with some matches and redacts the whole
|
||||
# query string. log_format and map must be at the http context level.
|
||||
map $request_uri $loggable_uri {
|
||||
~^(?P<path>[^?]*)\?.*(?:jwt|token)= "${path}?[params_redacted]";
|
||||
default $request_uri;
|
||||
}
|
||||
|
||||
map $http_referer $loggable_referer {
|
||||
~^(?P<url>[^?]*)\?.*(?:jwt|token)= "${url}?[params_redacted]";
|
||||
default $http_referer;
|
||||
}
|
||||
|
||||
log_format jitsi_log '$remote_addr - $remote_user [$time_local] '
|
||||
'"$request_method $loggable_uri $server_protocol" '
|
||||
'$status $body_bytes_sent "$loggable_referer" "$http_user_agent"';
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
@@ -82,8 +66,6 @@ server {
|
||||
|
||||
root /usr/share/jitsi-meet;
|
||||
|
||||
access_log /var/log/nginx/access.log jitsi_log;
|
||||
|
||||
# ssi on with javascript for multidomain variables in config.js
|
||||
ssi on;
|
||||
ssi_types application/x-javascript application/javascript;
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
// Stub replacement for @giphy/js-analytics to prevent beforeunload handlers
|
||||
// This completely disables all Giphy analytics functionality
|
||||
|
||||
export const pingback = () => {
|
||||
// Completely disabled - do nothing
|
||||
|
||||
};
|
||||
|
||||
export const mergeAttributes = (attributes, newAttributes) => {
|
||||
// Return merged attributes without any analytics calls
|
||||
return { ...attributes,
|
||||
...newAttributes };
|
||||
};
|
||||
|
||||
// Ensure no beforeunload handlers are ever registered
|
||||
export default pingback;
|
||||
@@ -22,7 +22,7 @@
|
||||
: pathname.substring(0, contextRootEndIndex + 1)
|
||||
);
|
||||
}
|
||||
window.EXCALIDRAW_ASSET_PATH = 'libs/excalidraw/';
|
||||
window.EXCALIDRAW_ASSET_PATH = 'libs/';
|
||||
// Dynamically generate the manifest location URL. It must be served from the document origin, and we may have
|
||||
// the base pointing to the CDN. This way we can generate a full URL which will bypass the base.
|
||||
document.querySelector('#manifest-placeholder').setAttribute('href', window.location.origin + contextRoot(window.location.pathname) + 'manifest.json');
|
||||
|
||||
@@ -44,6 +44,7 @@ target 'JitsiMeetSDK' do
|
||||
pod 'giphy-react-native-sdk', :path => '../node_modules/@giphy/react-native-sdk'
|
||||
pod 'RNCalendarEvents', :path => '../node_modules/react-native-calendar-events'
|
||||
pod 'RNGoogleSignin', :path => '../node_modules/@react-native-google-signin/google-signin'
|
||||
pod 'RNWatch', :path => '../node_modules/react-native-watch-connectivity'
|
||||
|
||||
# Native pod dependencies
|
||||
#
|
||||
|
||||
@@ -64,11 +64,11 @@ PODS:
|
||||
- GoogleUtilities/UserDefaults (~> 7.7)
|
||||
- PromisesObjC (< 3.0, >= 1.2)
|
||||
- fmt (11.0.2)
|
||||
- Giphy (2.2.16):
|
||||
- Giphy (2.2.13):
|
||||
- libwebp
|
||||
- giphy-react-native-sdk (4.1.0):
|
||||
- giphy-react-native-sdk (3.3.1):
|
||||
- DoubleConversion
|
||||
- Giphy (= 2.2.16)
|
||||
- Giphy (= 2.2.13)
|
||||
- glog
|
||||
- hermes-engine
|
||||
- RCT-Folly (= 2024.11.18.00)
|
||||
@@ -1382,9 +1382,9 @@ PODS:
|
||||
- React-Core
|
||||
- react-native-netinfo (11.1.0):
|
||||
- React-Core
|
||||
- react-native-orientation-locker (1.5.0):
|
||||
- react-native-orientation-locker (1.6.0):
|
||||
- React-Core
|
||||
- react-native-pager-view (6.8.1):
|
||||
- react-native-pager-view (6.4.1):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- hermes-engine
|
||||
@@ -1407,7 +1407,7 @@ PODS:
|
||||
- Yoga
|
||||
- react-native-performance (5.1.2):
|
||||
- React-Core
|
||||
- react-native-safe-area-context (5.6.1):
|
||||
- react-native-safe-area-context (5.4.0):
|
||||
- React-Core
|
||||
- react-native-slider (4.5.6):
|
||||
- DoubleConversion
|
||||
@@ -1473,7 +1473,7 @@ PODS:
|
||||
- ReactCommon/turbomodule/bridging
|
||||
- ReactCommon/turbomodule/core
|
||||
- Yoga
|
||||
- react-native-webrtc (124.0.7):
|
||||
- react-native-webrtc (124.0.4):
|
||||
- JitsiWebRTC (~> 124.0.0)
|
||||
- React-Core
|
||||
- react-native-webview (13.13.5):
|
||||
@@ -1497,27 +1497,6 @@ PODS:
|
||||
- ReactCommon/turbomodule/bridging
|
||||
- ReactCommon/turbomodule/core
|
||||
- Yoga
|
||||
- react-native-worklets-core (1.6.2):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- hermes-engine
|
||||
- RCT-Folly (= 2024.11.18.00)
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
- React-Core
|
||||
- React-debug
|
||||
- React-Fabric
|
||||
- React-featureflags
|
||||
- React-graphics
|
||||
- React-ImageManager
|
||||
- React-NativeModulesApple
|
||||
- React-RCTFabric
|
||||
- React-rendererdebug
|
||||
- React-utils
|
||||
- ReactCodegen
|
||||
- ReactCommon/turbomodule/bridging
|
||||
- ReactCommon/turbomodule/core
|
||||
- Yoga
|
||||
- React-nativeconfig (0.77.2)
|
||||
- React-NativeModulesApple (0.77.2):
|
||||
- glog
|
||||
@@ -1815,7 +1794,7 @@ PODS:
|
||||
- React-Core
|
||||
- RNDefaultPreference (1.4.4):
|
||||
- React-Core
|
||||
- RNDeviceInfo (12.1.0):
|
||||
- RNDeviceInfo (10.9.0):
|
||||
- React-Core
|
||||
- RNGestureHandler (2.24.0):
|
||||
- DoubleConversion
|
||||
@@ -1870,6 +1849,8 @@ PODS:
|
||||
- React-Core
|
||||
- RNSVG (15.11.2):
|
||||
- React-Core
|
||||
- RNWatch (1.1.0):
|
||||
- React
|
||||
- SocketRocket (0.7.1)
|
||||
- SplashView (0.0.18):
|
||||
- DoubleConversion
|
||||
@@ -1951,7 +1932,6 @@ DEPENDENCIES:
|
||||
- react-native-video (from `../node_modules/react-native-video`)
|
||||
- react-native-webrtc (from `../node_modules/react-native-webrtc`)
|
||||
- react-native-webview (from `../node_modules/react-native-webview`)
|
||||
- react-native-worklets-core (from `../node_modules/react-native-worklets-core`)
|
||||
- React-nativeconfig (from `../node_modules/react-native/ReactCommon`)
|
||||
- React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`)
|
||||
- React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`)
|
||||
@@ -1991,6 +1971,7 @@ DEPENDENCIES:
|
||||
- RNScreens (from `../node_modules/react-native-screens`)
|
||||
- RNSound (from `../node_modules/react-native-sound`)
|
||||
- RNSVG (from `../node_modules/react-native-svg`)
|
||||
- RNWatch (from `../node_modules/react-native-watch-connectivity`)
|
||||
- SplashView (from `../node_modules/react-native-splash-view`)
|
||||
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
|
||||
|
||||
@@ -2120,8 +2101,6 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/react-native-webrtc"
|
||||
react-native-webview:
|
||||
:path: "../node_modules/react-native-webview"
|
||||
react-native-worklets-core:
|
||||
:path: "../node_modules/react-native-worklets-core"
|
||||
React-nativeconfig:
|
||||
:path: "../node_modules/react-native/ReactCommon"
|
||||
React-NativeModulesApple:
|
||||
@@ -2200,6 +2179,8 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/react-native-sound"
|
||||
RNSVG:
|
||||
:path: "../node_modules/react-native-svg"
|
||||
RNWatch:
|
||||
:path: "../node_modules/react-native-watch-connectivity"
|
||||
SplashView:
|
||||
:path: "../node_modules/react-native-splash-view"
|
||||
Yoga:
|
||||
@@ -2220,8 +2201,8 @@ SPEC CHECKSUMS:
|
||||
FirebaseCrashlytics: feb07e4e9187be3c23c6a846cce4824e5ce2dd0b
|
||||
FirebaseInstallations: 40bd9054049b2eae9a2c38ef1c3dd213df3605cd
|
||||
fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd
|
||||
Giphy: 55914215541027873875757f350530e6d8986fba
|
||||
giphy-react-native-sdk: 733177b2537b527cfa55979c396cc1f2046eb457
|
||||
Giphy: a11dd02b51ac2ec37b881de1717ebf2cc8e9df62
|
||||
giphy-react-native-sdk: 678a115ea5a47a43d39d1b61703e0d08b1e48917
|
||||
glog: eb93e2f488219332457c3c4eafd2738ddc7e80b8
|
||||
GoogleAppMeasurement: 4c19f031220c72464d460c9daa1fb5d1acce958e
|
||||
GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a
|
||||
@@ -2268,15 +2249,14 @@ SPEC CHECKSUMS:
|
||||
react-native-get-random-values: d16467cf726c618e9c7a8c3c39c31faa2244bbba
|
||||
react-native-keep-awake: 03b74eebe4f2bb5e8478fc8f420651a92463b6f8
|
||||
react-native-netinfo: 5364263f903da576bdef9c84a76fe243ab06812c
|
||||
react-native-orientation-locker: dbd3f6ddbe9e62389cb0807dc2af63f6c36dec36
|
||||
react-native-pager-view: 11662c698c8f11d39e05891316d2a144fa00adc4
|
||||
react-native-orientation-locker: ee8bb2177365ca74f51dc1e11218fe544634d523
|
||||
react-native-pager-view: 68e8a65a607a6f91a1e25865002192c3c4f53fcf
|
||||
react-native-performance: 125a96c145e29918b55b45ce25cbba54f1e24dcd
|
||||
react-native-safe-area-context: 2243039f43d10cb1ea30ec5ac57fc6d1448413f4
|
||||
react-native-safe-area-context: 9d72abf6d8473da73033b597090a80b709c0b2f1
|
||||
react-native-slider: 1205801a8d29b28cacc14eef08cb120015cdafcb
|
||||
react-native-video: eb861d67a71dfef1bbf6086a811af5f338b13781
|
||||
react-native-webrtc: e8f0ce746353adc2744a2b933645e1aeb41eaa74
|
||||
react-native-webrtc: 2261a482150195092246fe70b3aff976f2e11ec5
|
||||
react-native-webview: 079eca50edf657503318b66687dadfb903731aa8
|
||||
react-native-worklets-core: b59cf88762c8fb6132d8796babd4cec15217d6f0
|
||||
React-nativeconfig: ecf4dc92c40b97e2b3f0c619938f78bfd6507b08
|
||||
React-NativeModulesApple: f457bbfb30fb3bc41979b1a87b99d292d7340d39
|
||||
React-perflogger: 1111b5feb064c4cc83df88fb403efda54b387951
|
||||
@@ -2310,16 +2290,17 @@ SPEC CHECKSUMS:
|
||||
RNCAsyncStorage: aa75595c1aefa18f868452091fa0c411a516ce11
|
||||
RNCClipboard: 7c3e3b5f71d84ef61690ad377b6c50cf27864ff5
|
||||
RNDefaultPreference: ee13d69e6693d193cd223d10e15e5b3c012d31ba
|
||||
RNDeviceInfo: 723e97dd98af9b7913477e7a40252c15517c258c
|
||||
RNDeviceInfo: 8af23685571b7867d8dc15fb89e7fb5fa8607e1e
|
||||
RNGestureHandler: 9f3109e11ed88fe5bed280bf7762b25e4c52f396
|
||||
RNGoogleSignin: 30e1aee80140dc0706cd78a4951c411376c88329
|
||||
RNScreens: 9ef996b6041d0960a4794a845f7d0808b171b4ef
|
||||
RNSound: 314cc5226453ef4a3314a196c65e8a65e5106a7b
|
||||
RNSVG: 67de7abef81f367387b708ba6d2acefe7d4f5895
|
||||
RNWatch: 28fe1f5e0c6410d45fd20925f4796fce05522e3f
|
||||
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
|
||||
SplashView: ed71a114c3ffe60dc3a9e5aa2cefb352c3794a70
|
||||
Yoga: 31a098f74c16780569aebd614a0f37a907de0189
|
||||
|
||||
PODFILE CHECKSUM: 7c37a89916893e11159576c8b308b7b5c25246c9
|
||||
PODFILE CHECKSUM: eac4bba07b2f30174fc20bccbaf64f86676d9b1f
|
||||
|
||||
COCOAPODS: 1.16.2
|
||||
|
||||
@@ -30,14 +30,6 @@
|
||||
<string>35F9.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryDiskSpace</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>85F4.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>NSPrivacyCollectedDataTypes</key>
|
||||
<array/>
|
||||
|
||||
@@ -7,6 +7,16 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
0B5418471F7C5D8C00A2DD86 /* MeetingRowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B5418461F7C5D8C00A2DD86 /* MeetingRowController.swift */; };
|
||||
0B7001701F7C51CC005944F4 /* InCallController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B70016F1F7C51CC005944F4 /* InCallController.swift */; };
|
||||
0BEA5C291F7B8F73000D0AB4 /* Interface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0BEA5C271F7B8F73000D0AB4 /* Interface.storyboard */; };
|
||||
0BEA5C2B1F7B8F73000D0AB4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0BEA5C2A1F7B8F73000D0AB4 /* Assets.xcassets */; };
|
||||
0BEA5C321F7B8F73000D0AB4 /* JitsiMeetCompanion Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 0BEA5C311F7B8F73000D0AB4 /* JitsiMeetCompanion Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
0BEA5C371F7B8F73000D0AB4 /* InterfaceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BEA5C361F7B8F73000D0AB4 /* InterfaceController.swift */; };
|
||||
0BEA5C391F7B8F73000D0AB4 /* ExtensionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BEA5C381F7B8F73000D0AB4 /* ExtensionDelegate.swift */; };
|
||||
0BEA5C3B1F7B8F73000D0AB4 /* ComplicationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BEA5C3A1F7B8F73000D0AB4 /* ComplicationController.swift */; };
|
||||
0BEA5C3D1F7B8F73000D0AB4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0BEA5C3C1F7B8F73000D0AB4 /* Assets.xcassets */; };
|
||||
0BEA5C411F7B8F73000D0AB4 /* JitsiMeetCompanion.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = 0BEA5C251F7B8F73000D0AB4 /* JitsiMeetCompanion.app */; };
|
||||
13B07FBD1A68108700A75B9A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.storyboard */; };
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||
2681BB562C7A0B42CFBA6719 /* libPods-JitsiMeet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D6152FF9E9F7B0E86F70A21D /* libPods-JitsiMeet.a */; };
|
||||
@@ -26,11 +36,27 @@
|
||||
DEA9F28A258A6EA800D4CD74 /* JitsiMeetSDK.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DEA9F288258A6EA800D4CD74 /* JitsiMeetSDK.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
DED016F128ECBC9D009D5E8D /* WebRTC.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = DED016F028ECBC9D009D5E8D /* WebRTC.xcframework */; };
|
||||
DED016F228ECBC9D009D5E8D /* WebRTC.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DED016F028ECBC9D009D5E8D /* WebRTC.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
E588011722789D43008B0561 /* JitsiMeetContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = E58801132278944E008B0561 /* JitsiMeetContext.swift */; };
|
||||
E5C97B63227A1EB400199214 /* JitsiMeetCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5C97B62227A1EB400199214 /* JitsiMeetCommands.swift */; };
|
||||
FD572B9827EDF32300A800FB /* GiphyUISDK.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = FD572B9727EDF32300A800FB /* GiphyUISDK.xcframework */; };
|
||||
FD572B9927EDF32300A800FB /* GiphyUISDK.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = FD572B9727EDF32300A800FB /* GiphyUISDK.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
0BEA5C331F7B8F73000D0AB4 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 0BEA5C301F7B8F73000D0AB4;
|
||||
remoteInfo = "JitsiMeetCompanion Extension";
|
||||
};
|
||||
0BEA5C3F1F7B8F73000D0AB4 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 0BEA5C241F7B8F73000D0AB4;
|
||||
remoteInfo = JitsiMeetCompanion;
|
||||
};
|
||||
4EB06029260E026600F524C5 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
|
||||
@@ -55,12 +81,24 @@
|
||||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
0BEA5C471F7B8F73000D0AB4 /* Embed App Extensions */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 13;
|
||||
files = (
|
||||
0BEA5C321F7B8F73000D0AB4 /* JitsiMeetCompanion Extension.appex in Embed App Extensions */,
|
||||
);
|
||||
name = "Embed App Extensions";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
0BEA5C491F7B8F73000D0AB4 /* Embed Watch Content */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "$(CONTENTS_FOLDER_PATH)/Watch";
|
||||
dstSubfolderSpec = 16;
|
||||
files = (
|
||||
0BEA5C411F7B8F73000D0AB4 /* JitsiMeetCompanion.app in Embed Watch Content */,
|
||||
);
|
||||
name = "Embed Watch Content";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -80,7 +118,19 @@
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
0B26BE6D1EC5BC3C00EEFB41 /* JitsiMeet.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = JitsiMeet.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
0B5418461F7C5D8C00A2DD86 /* MeetingRowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeetingRowController.swift; sourceTree = "<group>"; };
|
||||
0B70016F1F7C51CC005944F4 /* InCallController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InCallController.swift; sourceTree = "<group>"; };
|
||||
0BD6B4361EF82A6B00D1F4CD /* WebRTC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebRTC.framework; path = "../../node_modules/react-native-webrtc/ios/WebRTC.framework"; sourceTree = "<group>"; };
|
||||
0BEA5C251F7B8F73000D0AB4 /* JitsiMeetCompanion.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JitsiMeetCompanion.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
0BEA5C281F7B8F73000D0AB4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Interface.storyboard; sourceTree = "<group>"; };
|
||||
0BEA5C2A1F7B8F73000D0AB4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
0BEA5C2C1F7B8F73000D0AB4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
0BEA5C311F7B8F73000D0AB4 /* JitsiMeetCompanion Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "JitsiMeetCompanion Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
0BEA5C361F7B8F73000D0AB4 /* InterfaceController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InterfaceController.swift; sourceTree = "<group>"; };
|
||||
0BEA5C381F7B8F73000D0AB4 /* ExtensionDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionDelegate.swift; sourceTree = "<group>"; };
|
||||
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>"; };
|
||||
13B07F961A680F5B00A75B9A /* jitsi-meet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "jitsi-meet.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = src/Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
|
||||
@@ -106,10 +156,19 @@
|
||||
DEA9F288258A6EA800D4CD74 /* JitsiMeetSDK.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = JitsiMeetSDK.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DED016F028ECBC9D009D5E8D /* WebRTC.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = WebRTC.xcframework; path = ../Pods/JitsiWebRTC/WebRTC.xcframework; sourceTree = "<group>"; };
|
||||
DEFDBBDB25656E3B00344B23 /* WebRTC.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = WebRTC.xcframework; path = "../../node_modules/react-native-webrtc/ios/WebRTC.xcframework"; sourceTree = "<group>"; };
|
||||
E58801132278944E008B0561 /* JitsiMeetContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JitsiMeetContext.swift; sourceTree = "<group>"; };
|
||||
E5C97B62227A1EB400199214 /* JitsiMeetCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JitsiMeetCommands.swift; sourceTree = "<group>"; };
|
||||
FD572B9727EDF32300A800FB /* GiphyUISDK.xcframework */ = {isa = PBXFileReference; expectedSignature = "AppleDeveloperProgram:925PGC4MV7:Giphy, Inc."; lastKnownFileType = wrapper.xcframework; name = GiphyUISDK.xcframework; path = ../Pods/Giphy/GiphySDK/GiphyUISDK.xcframework; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
0BEA5C2E1F7B8F73000D0AB4 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -122,6 +181,13 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
1F021A8A5B056078665DE530 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
4EB06020260E026600F524C5 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -150,6 +216,34 @@
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0BEA5C261F7B8F73000D0AB4 /* Watch app */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0BEA5C271F7B8F73000D0AB4 /* Interface.storyboard */,
|
||||
0BEA5C2A1F7B8F73000D0AB4 /* Assets.xcassets */,
|
||||
0BEA5C2C1F7B8F73000D0AB4 /* Info.plist */,
|
||||
);
|
||||
name = "Watch app";
|
||||
path = watchos/app;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0BEA5C351F7B8F73000D0AB4 /* WatchKit extension */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0BEA5C361F7B8F73000D0AB4 /* InterfaceController.swift */,
|
||||
0BEA5C381F7B8F73000D0AB4 /* ExtensionDelegate.swift */,
|
||||
0BEA5C3A1F7B8F73000D0AB4 /* ComplicationController.swift */,
|
||||
0BEA5C3C1F7B8F73000D0AB4 /* Assets.xcassets */,
|
||||
0BEA5C3E1F7B8F73000D0AB4 /* Info.plist */,
|
||||
0B70016F1F7C51CC005944F4 /* InCallController.swift */,
|
||||
0B5418461F7C5D8C00A2DD86 /* MeetingRowController.swift */,
|
||||
E58801132278944E008B0561 /* JitsiMeetContext.swift */,
|
||||
E5C97B62227A1EB400199214 /* JitsiMeetCommands.swift */,
|
||||
);
|
||||
name = "WatchKit extension";
|
||||
path = watchos/extension;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
13B07FAE1A68108700A75B9A /* src */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -185,10 +279,11 @@
|
||||
0B26BE711EC5BC4D00EEFB41 /* Frameworks */,
|
||||
83CBBA001A601CBA00E9B192 /* Products */,
|
||||
13B07FAE1A68108700A75B9A /* src */,
|
||||
0BEA5C261F7B8F73000D0AB4 /* Watch app */,
|
||||
0BEA5C351F7B8F73000D0AB4 /* WatchKit extension */,
|
||||
4EB06025260E026600F524C5 /* JitsiMeetBroadcast Extension */,
|
||||
CDD71F5E1157E9F283DF92A8 /* Pods */,
|
||||
5C1BE20ECD5DEEB48FED90B5 /* PrivacyInfo.xcprivacy */,
|
||||
DEAC44E22E97D2C200AD7BEE /* Recovered References */,
|
||||
);
|
||||
indentWidth = 2;
|
||||
sourceTree = "<group>";
|
||||
@@ -198,6 +293,8 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07F961A680F5B00A75B9A /* jitsi-meet.app */,
|
||||
0BEA5C251F7B8F73000D0AB4 /* JitsiMeetCompanion.app */,
|
||||
0BEA5C311F7B8F73000D0AB4 /* JitsiMeetCompanion Extension.appex */,
|
||||
4EB06023260E026600F524C5 /* JitsiMeetBroadcastExtension.appex */,
|
||||
);
|
||||
name = Products;
|
||||
@@ -213,17 +310,44 @@
|
||||
path = ../Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DEAC44E22E97D2C200AD7BEE /* Recovered References */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07FB11A68108700A75B9A /* LaunchScreen.storyboard */,
|
||||
);
|
||||
name = "Recovered References";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
0BEA5C241F7B8F73000D0AB4 /* JitsiMeetCompanion */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 0BEA5C481F7B8F73000D0AB4 /* Build configuration list for PBXNativeTarget "JitsiMeetCompanion" */;
|
||||
buildPhases = (
|
||||
0BEA5C231F7B8F73000D0AB4 /* Resources */,
|
||||
0BEA5C471F7B8F73000D0AB4 /* Embed App Extensions */,
|
||||
1F021A8A5B056078665DE530 /* Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
0BEA5C341F7B8F73000D0AB4 /* PBXTargetDependency */,
|
||||
);
|
||||
name = JitsiMeetCompanion;
|
||||
productName = JitsiMeetCompanion;
|
||||
productReference = 0BEA5C251F7B8F73000D0AB4 /* JitsiMeetCompanion.app */;
|
||||
productType = "com.apple.product-type.application.watchapp2";
|
||||
};
|
||||
0BEA5C301F7B8F73000D0AB4 /* JitsiMeetCompanion Extension */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 0BEA5C461F7B8F73000D0AB4 /* Build configuration list for PBXNativeTarget "JitsiMeetCompanion Extension" */;
|
||||
buildPhases = (
|
||||
0BEA5C2D1F7B8F73000D0AB4 /* Sources */,
|
||||
0BEA5C2E1F7B8F73000D0AB4 /* Frameworks */,
|
||||
0BEA5C2F1F7B8F73000D0AB4 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "JitsiMeetCompanion Extension";
|
||||
productName = "JitsiMeetCompanion Extension";
|
||||
productReference = 0BEA5C311F7B8F73000D0AB4 /* JitsiMeetCompanion Extension.appex */;
|
||||
productType = "com.apple.product-type.watchkit2-extension";
|
||||
};
|
||||
13B07F861A680F5B00A75B9A /* JitsiMeet */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "JitsiMeet" */;
|
||||
@@ -245,6 +369,7 @@
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
0BEA5C401F7B8F73000D0AB4 /* PBXTargetDependency */,
|
||||
4EB0602A260E026600F524C5 /* PBXTargetDependency */,
|
||||
);
|
||||
name = JitsiMeet;
|
||||
@@ -279,6 +404,16 @@
|
||||
LastUpgradeCheck = 1020;
|
||||
ORGANIZATIONNAME = Jitsi;
|
||||
TargetAttributes = {
|
||||
0BEA5C241F7B8F73000D0AB4 = {
|
||||
CreatedOnToolsVersion = 9.0;
|
||||
DevelopmentTeam = FC967L3QRG;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
0BEA5C301F7B8F73000D0AB4 = {
|
||||
CreatedOnToolsVersion = 9.0;
|
||||
DevelopmentTeam = FC967L3QRG;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
13B07F861A680F5B00A75B9A = {
|
||||
LastSwiftMigration = 1620;
|
||||
SystemCapabilities = {
|
||||
@@ -309,12 +444,31 @@
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
13B07F861A680F5B00A75B9A /* JitsiMeet */,
|
||||
0BEA5C241F7B8F73000D0AB4 /* JitsiMeetCompanion */,
|
||||
0BEA5C301F7B8F73000D0AB4 /* JitsiMeetCompanion Extension */,
|
||||
4EB06022260E026600F524C5 /* JitsiMeetBroadcastExtension */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
0BEA5C231F7B8F73000D0AB4 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
0BEA5C2B1F7B8F73000D0AB4 /* Assets.xcassets in Resources */,
|
||||
0BEA5C291F7B8F73000D0AB4 /* Interface.storyboard in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
0BEA5C2F1F7B8F73000D0AB4 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
0BEA5C3D1F7B8F73000D0AB4 /* Assets.xcassets in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
13B07F8E1A680F5B00A75B9A /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -468,6 +622,20 @@
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
0BEA5C2D1F7B8F73000D0AB4 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
0B7001701F7C51CC005944F4 /* InCallController.swift in Sources */,
|
||||
E5C97B63227A1EB400199214 /* JitsiMeetCommands.swift in Sources */,
|
||||
0B5418471F7C5D8C00A2DD86 /* MeetingRowController.swift in Sources */,
|
||||
E588011722789D43008B0561 /* JitsiMeetContext.swift in Sources */,
|
||||
0BEA5C391F7B8F73000D0AB4 /* ExtensionDelegate.swift in Sources */,
|
||||
0BEA5C371F7B8F73000D0AB4 /* InterfaceController.swift in Sources */,
|
||||
0BEA5C3B1F7B8F73000D0AB4 /* ComplicationController.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
13B07F871A680F5B00A75B9A /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -492,6 +660,16 @@
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
0BEA5C341F7B8F73000D0AB4 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 0BEA5C301F7B8F73000D0AB4 /* JitsiMeetCompanion Extension */;
|
||||
targetProxy = 0BEA5C331F7B8F73000D0AB4 /* PBXContainerItemProxy */;
|
||||
};
|
||||
0BEA5C401F7B8F73000D0AB4 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 0BEA5C241F7B8F73000D0AB4 /* JitsiMeetCompanion */;
|
||||
targetProxy = 0BEA5C3F1F7B8F73000D0AB4 /* PBXContainerItemProxy */;
|
||||
};
|
||||
4EB0602A260E026600F524C5 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 4EB06022260E026600F524C5 /* JitsiMeetBroadcastExtension */;
|
||||
@@ -500,6 +678,14 @@
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
0BEA5C271F7B8F73000D0AB4 /* Interface.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
0BEA5C281F7B8F73000D0AB4 /* Base */,
|
||||
);
|
||||
name = Interface.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
13B07FB11A68108700A75B9A /* LaunchScreen.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
@@ -511,10 +697,155 @@
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
0BEA5C421F7B8F73000D0AB4 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = FC967L3QRG;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
IBSC_MODULE = JitsiMeetCompanion_Extension;
|
||||
INFOPLIST_FILE = watchos/app/Info.plist;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.meet.watchkit;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = watchos;
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = 4;
|
||||
WATCHOS_DEPLOYMENT_TARGET = 4.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
0BEA5C431F7B8F73000D0AB4 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = FC967L3QRG;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
IBSC_MODULE = JitsiMeetCompanion_Extension;
|
||||
INFOPLIST_FILE = watchos/app/Info.plist;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.meet.watchkit;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = watchos;
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = 4;
|
||||
WATCHOS_DEPLOYMENT_TARGET = 4.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
0BEA5C441F7B8F73000D0AB4 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = FC967L3QRG;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
INFOPLIST_FILE = watchos/extension/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.meet.watchkit.extension;
|
||||
PRODUCT_NAME = "${TARGET_NAME}";
|
||||
SDKROOT = watchos;
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = 4;
|
||||
WATCHOS_DEPLOYMENT_TARGET = 4.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
0BEA5C451F7B8F73000D0AB4 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = FC967L3QRG;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
INFOPLIST_FILE = watchos/extension/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.meet.watchkit.extension;
|
||||
PRODUCT_NAME = "${TARGET_NAME}";
|
||||
SDKROOT = watchos;
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = 4;
|
||||
WATCHOS_DEPLOYMENT_TARGET = 4.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
13B07F941A680F5B00A75B9A /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 756FCE06C08D9B947653C98A /* Pods-JitsiMeet.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIconDebug;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = app.entitlements;
|
||||
@@ -551,6 +882,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 3E0F4ED943C0B12BE77F6B45 /* Pods-JitsiMeet.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIconRelease;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = app.entitlements;
|
||||
@@ -799,6 +1131,24 @@
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
0BEA5C461F7B8F73000D0AB4 /* Build configuration list for PBXNativeTarget "JitsiMeetCompanion Extension" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
0BEA5C441F7B8F73000D0AB4 /* Debug */,
|
||||
0BEA5C451F7B8F73000D0AB4 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
0BEA5C481F7B8F73000D0AB4 /* Build configuration list for PBXNativeTarget "JitsiMeetCompanion" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
0BEA5C421F7B8F73000D0AB4 /* Debug */,
|
||||
0BEA5C431F7B8F73000D0AB4 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "JitsiMeet" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"size" : "24x24",
|
||||
"idiom" : "watch",
|
||||
"filename" : "Icon-24@2x.png",
|
||||
"scale" : "2x",
|
||||
"role" : "notificationCenter",
|
||||
"subtype" : "38mm"
|
||||
},
|
||||
{
|
||||
"size" : "27.5x27.5",
|
||||
"idiom" : "watch",
|
||||
"filename" : "Icon-27.5@2x.png",
|
||||
"scale" : "2x",
|
||||
"role" : "notificationCenter",
|
||||
"subtype" : "42mm"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "watch",
|
||||
"filename" : "Icon-29@2x.png",
|
||||
"role" : "companionSettings",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "watch",
|
||||
"filename" : "Icon-29@3x.png",
|
||||
"role" : "companionSettings",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "watch",
|
||||
"filename" : "Icon-40@2x.png",
|
||||
"scale" : "2x",
|
||||
"role" : "appLauncher",
|
||||
"subtype" : "38mm"
|
||||
},
|
||||
{
|
||||
"size" : "44x44",
|
||||
"idiom" : "watch",
|
||||
"filename" : "Icon-88@2x.png",
|
||||
"scale" : "2x",
|
||||
"role" : "appLauncher",
|
||||
"subtype" : "40mm"
|
||||
},
|
||||
{
|
||||
"size" : "50x50",
|
||||
"idiom" : "watch",
|
||||
"filename" : "Icon-100@2x.png",
|
||||
"scale" : "2x",
|
||||
"role" : "appLauncher",
|
||||
"subtype" : "44mm"
|
||||
},
|
||||
{
|
||||
"size" : "86x86",
|
||||
"idiom" : "watch",
|
||||
"filename" : "Icon-86@2x.png",
|
||||
"scale" : "2x",
|
||||
"role" : "quickLook",
|
||||
"subtype" : "38mm"
|
||||
},
|
||||
{
|
||||
"size" : "98x98",
|
||||
"idiom" : "watch",
|
||||
"filename" : "Icon-98@2x.png",
|
||||
"scale" : "2x",
|
||||
"role" : "quickLook",
|
||||
"subtype" : "42mm"
|
||||
},
|
||||
{
|
||||
"size" : "108x108",
|
||||
"idiom" : "watch",
|
||||
"filename" : "Icon-216@2x.png",
|
||||
"scale" : "2x",
|
||||
"role" : "quickLook",
|
||||
"subtype" : "44mm"
|
||||
},
|
||||
{
|
||||
"size" : "1024x1024",
|
||||
"idiom" : "watch-marketing",
|
||||
"filename" : "Icon-1024@1x.png",
|
||||
"scale" : "1x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 8.3 KiB |
|
After Width: | Height: | Size: 158 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 7.3 KiB |
|
After Width: | Height: | Size: 18 KiB |
6
ios/app/watchos/app/Assets.xcassets/Contents.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
21
ios/app/watchos/app/Assets.xcassets/hangup.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "hangup@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
ios/app/watchos/app/Assets.xcassets/hangup.imageset/hangup@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
21
ios/app/watchos/app/Assets.xcassets/mute-off.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "mute-off@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
ios/app/watchos/app/Assets.xcassets/mute-off.imageset/mute-off@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
21
ios/app/watchos/app/Assets.xcassets/mute-on.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "mute-on@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
ios/app/watchos/app/Assets.xcassets/mute-on.imageset/mute-on@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
85
ios/app/watchos/app/Base.lproj/Interface.storyboard
Normal file
@@ -0,0 +1,85 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder.WatchKit.Storyboard" version="3.0" toolsVersion="14490.70" targetRuntime="watchKit" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="AgC-eL-Hgc">
|
||||
<device id="watch38" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="watchOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBWatchKitPlugin" version="14490.21"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--Meetings-->
|
||||
<scene sceneID="aou-V4-d1y">
|
||||
<objects>
|
||||
<controller title="Meetings" id="AgC-eL-Hgc" customClass="InterfaceController" customModule="JitsiMeetCompanion" customModuleProvider="target">
|
||||
<items>
|
||||
<label alignment="left" textAlignment="left" numberOfLines="0" id="OQN-sx-tDt"/>
|
||||
<table alignment="left" id="gpO-ql-Xsr">
|
||||
<items>
|
||||
<tableRow identifier="MeetingRowType" id="GGl-av-xeJ" customClass="MeetingRowController" customModule="JitsiMeetCompanion_Extension">
|
||||
<group key="rootItem" width="1" height="0.0" alignment="left" layout="vertical" id="5XE-gq-qzG">
|
||||
<items>
|
||||
<label alignment="left" text="Label" id="Sij-up-N4p"/>
|
||||
<label alignment="left" text="Label" id="V5K-sm-jEH">
|
||||
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<fontDescription key="font" style="UICTFontTextStyleFootnote"/>
|
||||
</label>
|
||||
</items>
|
||||
<connections>
|
||||
<segue destination="9RD-qP-1Z0" kind="push" id="Boa-6E-eZs"/>
|
||||
</connections>
|
||||
</group>
|
||||
<connections>
|
||||
<outlet property="roomLabel" destination="Sij-up-N4p" id="PdS-SO-ylc"/>
|
||||
<outlet property="rowGroup" destination="5XE-gq-qzG" id="GZN-2c-2Gz"/>
|
||||
<outlet property="timeLabel" destination="V5K-sm-jEH" id="fWQ-kx-vE4"/>
|
||||
</connections>
|
||||
</tableRow>
|
||||
</items>
|
||||
</table>
|
||||
</items>
|
||||
<connections>
|
||||
<outlet property="infoLabel" destination="OQN-sx-tDt" id="Juv-tb-SNj"/>
|
||||
<outlet property="table" destination="gpO-ql-Xsr" id="aVV-iZ-z3l"/>
|
||||
</connections>
|
||||
</controller>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-99" y="117"/>
|
||||
</scene>
|
||||
<!--Meetings-->
|
||||
<scene sceneID="ns4-Kh-qqU">
|
||||
<objects>
|
||||
<controller identifier="InCallController" title="Meetings" hidesWhenLoading="NO" id="9RD-qP-1Z0" customClass="InCallController" customModule="JitsiMeetCompanion" customModuleProvider="target">
|
||||
<items>
|
||||
<label alignment="center" text="Label" id="vFt-lL-SNY"/>
|
||||
<timer alignment="center" textAlignment="center" previewedSeconds="0" id="W8S-uZ-MPm">
|
||||
<color key="textColor" red="0.024725984125768763" green="1" blue="0.24241188365329402" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<fontDescription key="font" style="UICTFontTextStyleHeadline"/>
|
||||
</timer>
|
||||
<group alignment="center" verticalAlignment="bottom" spacing="10" id="Hfk-a0-uWj">
|
||||
<items>
|
||||
<button width="60" height="60" alignment="left" verticalAlignment="bottom" backgroundImage="hangup" id="8jF-SI-UHz">
|
||||
<connections>
|
||||
<action selector="hangupClicked" destination="9RD-qP-1Z0" id="cXK-lw-tsd"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button width="60" height="60" alignment="right" verticalAlignment="bottom" backgroundImage="mute-off" id="LmN-FI-aQq">
|
||||
<connections>
|
||||
<action selector="muteClicked" destination="9RD-qP-1Z0" id="dJg-kV-cqH"/>
|
||||
</connections>
|
||||
</button>
|
||||
</items>
|
||||
</group>
|
||||
</items>
|
||||
<connections>
|
||||
<outlet property="mutedButton" destination="LmN-FI-aQq" id="gfi-4T-gdN"/>
|
||||
<outlet property="roomLabel" destination="vFt-lL-SNY" id="cYB-Tf-Efz"/>
|
||||
<outlet property="timer" destination="W8S-uZ-MPm" id="r7T-j1-9VJ"/>
|
||||
</connections>
|
||||
</controller>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="213" y="117"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
33
ios/app/watchos/app/Info.plist
Normal file
@@ -0,0 +1,33 @@
|
||||
<?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>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>Jitsi Meet</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>99.0.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
</array>
|
||||
<key>WKCompanionAppBundleIdentifier</key>
|
||||
<string>org.jitsi.meet</string>
|
||||
<key>WKWatchKitApp</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
6
ios/app/watchos/extension/Assets.xcassets/Contents.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
21
ios/app/watchos/extension/Assets.xcassets/jitsi.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "jitsi@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
ios/app/watchos/extension/Assets.xcassets/jitsi.imageset/jitsi@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
81
ios/app/watchos/extension/ComplicationController.swift
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright @ 2018-present 8x8, Inc.
|
||||
* Copyright @ 2017-2018 Atlassian Pty Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import ClockKit
|
||||
|
||||
|
||||
class ComplicationController: NSObject, CLKComplicationDataSource {
|
||||
|
||||
// MARK: - Timeline Configuration
|
||||
|
||||
func getSupportedTimeTravelDirections(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimeTravelDirections) -> Void) {
|
||||
handler([])
|
||||
}
|
||||
|
||||
func getPrivacyBehavior(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationPrivacyBehavior) -> Void) {
|
||||
handler(.showOnLockScreen)
|
||||
}
|
||||
|
||||
// MARK: - Timeline Population
|
||||
|
||||
func getCurrentTimelineEntry(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimelineEntry?) -> Void) {
|
||||
// Call the handler with the current timeline entry
|
||||
getLocalizableSampleTemplate(for: complication) {template in
|
||||
guard let template = template else {
|
||||
handler(nil)
|
||||
return
|
||||
}
|
||||
handler(CLKComplicationTimelineEntry(date: Date(), complicationTemplate: template))
|
||||
}
|
||||
}
|
||||
|
||||
func getTimelineEntries(for complication: CLKComplication, before date: Date, limit: Int, withHandler handler: @escaping ([CLKComplicationTimelineEntry]?) -> Void) {
|
||||
// Call the handler with the timeline entries prior to the given date
|
||||
handler(nil)
|
||||
}
|
||||
|
||||
func getTimelineEntries(for complication: CLKComplication, after date: Date, limit: Int, withHandler handler: @escaping ([CLKComplicationTimelineEntry]?) -> Void) {
|
||||
// Call the handler with the timeline entries after to the given date
|
||||
handler(nil)
|
||||
}
|
||||
|
||||
// MARK: - Placeholder Templates
|
||||
|
||||
func getLocalizableSampleTemplate(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTemplate?) -> Void) {
|
||||
// This method will be called once per supported complication, and the results will be cached
|
||||
|
||||
let imageProvider = CLKImageProvider(onePieceImage: UIImage(named: "jitsi")!)
|
||||
if complication.family == .circularSmall {
|
||||
let small = CLKComplicationTemplateCircularSmallRingImage()
|
||||
small.imageProvider = imageProvider
|
||||
small.ringStyle = .closed
|
||||
small.fillFraction = 0
|
||||
handler(small)
|
||||
} else if complication.family == .utilitarianSmall {
|
||||
let utilitarian = CLKComplicationTemplateUtilitarianSmallSquare()
|
||||
utilitarian.imageProvider = imageProvider
|
||||
handler(utilitarian)
|
||||
} else if complication.family == .modularSmall {
|
||||
let modular = CLKComplicationTemplateModularSmallRingImage()
|
||||
modular.imageProvider = imageProvider
|
||||
modular.ringStyle = .closed
|
||||
modular.fillFraction = 0
|
||||
handler(modular)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
103
ios/app/watchos/extension/ExtensionDelegate.swift
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright @ 2018-present 8x8, Inc.
|
||||
* Copyright @ 2017-2018 Atlassian Pty Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import WatchConnectivity
|
||||
import WatchKit
|
||||
|
||||
class ExtensionDelegate: NSObject, WCSessionDelegate, WKExtensionDelegate {
|
||||
|
||||
var currentContext : JitsiMeetContext = JitsiMeetContext()
|
||||
|
||||
static var currentJitsiMeetContext: JitsiMeetContext {
|
||||
get {
|
||||
return (WKExtension.shared().delegate as! ExtensionDelegate).currentContext
|
||||
}
|
||||
}
|
||||
|
||||
func applicationDidFinishLaunching() {
|
||||
// Start Watch Connectivity
|
||||
if WCSession.isSupported() {
|
||||
let session = WCSession.default
|
||||
session.delegate = self
|
||||
session.activate()
|
||||
}
|
||||
}
|
||||
|
||||
func handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>) {
|
||||
// Sent when the system needs to launch the application in the background to process tasks. Tasks arrive in a set, so loop through and process each one.
|
||||
for task in backgroundTasks {
|
||||
// Use a switch statement to check the task type
|
||||
switch task {
|
||||
case let backgroundTask as WKApplicationRefreshBackgroundTask:
|
||||
// Be sure to complete the background task once you’re done.
|
||||
backgroundTask.setTaskCompletedWithSnapshot(false)
|
||||
case let snapshotTask as WKSnapshotRefreshBackgroundTask:
|
||||
// Snapshot tasks have a unique completion call, make sure to set your expiration date
|
||||
snapshotTask.setTaskCompleted(restoredDefaultState: true, estimatedSnapshotExpiration: Date.distantFuture, userInfo: nil)
|
||||
case let connectivityTask as WKWatchConnectivityRefreshBackgroundTask:
|
||||
// Be sure to complete the connectivity task once you’re done.
|
||||
connectivityTask.setTaskCompletedWithSnapshot(false)
|
||||
case let urlSessionTask as WKURLSessionRefreshBackgroundTask:
|
||||
// Be sure to complete the URL session task once you’re done.
|
||||
urlSessionTask.setTaskCompletedWithSnapshot(false)
|
||||
default:
|
||||
// make sure to complete unhandled task types
|
||||
task.setTaskCompletedWithSnapshot(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func session(_ session: WCSession, activationDidCompleteWith
|
||||
activationState: WCSessionActivationState, error: Error?) {
|
||||
if let error = error {
|
||||
print("WATCH Session activation failed with error: \(error.localizedDescription)")
|
||||
return
|
||||
}
|
||||
print("WATCH Session activated with state: \(activationState.rawValue)")
|
||||
}
|
||||
|
||||
func session(_ session: WCSession, didReceiveApplicationContext applicationContext: [String : Any]) {
|
||||
DispatchQueue.main.async {
|
||||
let newContext = JitsiMeetContext(context: applicationContext)
|
||||
|
||||
print("WATCH got new context: \(newContext.description)");
|
||||
|
||||
// Update context on the root controller which displays the recent list
|
||||
let controller = WKExtension.shared().rootInterfaceController as! InterfaceController
|
||||
controller.updateUI(newContext)
|
||||
|
||||
// If the current controller is not the in-call controller and we have a
|
||||
// conference URL, show the in-call controller
|
||||
if let currentController = WKExtension.shared().visibleInterfaceController as? InterfaceController {
|
||||
// Go to the in-call controller only if the conference URL has changed, because the user may have
|
||||
// clicked the back button
|
||||
if newContext.conferenceURL != nil
|
||||
&& self.currentContext.conferenceURL != newContext.conferenceURL {
|
||||
currentController.pushController(withName: "InCallController", context: newContext)
|
||||
}
|
||||
} else if let inCallController = WKExtension.shared().visibleInterfaceController as? InCallController {
|
||||
if newContext.conferenceURL == nil {
|
||||
inCallController.popToRootController()
|
||||
} else {
|
||||
inCallController.updateUI(newContext)
|
||||
}
|
||||
}
|
||||
|
||||
self.currentContext = newContext;
|
||||
}
|
||||
}
|
||||
}
|
||||
109
ios/app/watchos/extension/InCallController.swift
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright @ 2018-present 8x8, Inc.
|
||||
* Copyright @ 2017-2018 Atlassian Pty Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import WatchConnectivity
|
||||
import WatchKit
|
||||
import Foundation
|
||||
|
||||
|
||||
class InCallController: WKInterfaceController {
|
||||
@IBOutlet var mutedButton: WKInterfaceButton!
|
||||
@IBOutlet var roomLabel: WKInterfaceLabel!
|
||||
@IBOutlet var timer: WKInterfaceTimer!
|
||||
|
||||
@IBAction func hangupClicked() {
|
||||
sendCommand(JitsiMeetCommands.CMD_HANG_UP, message: nil)
|
||||
}
|
||||
|
||||
@IBAction func muteClicked() {
|
||||
if var micMuted = ExtensionDelegate.currentJitsiMeetContext.micMuted {
|
||||
micMuted = !micMuted;
|
||||
sendCommand(
|
||||
JitsiMeetCommands.CMD_SET_MUTED,
|
||||
message: [
|
||||
"muted": micMuted ? "true" : "false"
|
||||
])
|
||||
updateMutedButton(withMuted: micMuted)
|
||||
}
|
||||
}
|
||||
|
||||
func sendCommand(_ command: JitsiMeetCommands, message: [String : Any]?) {
|
||||
if WCSession.isSupported() {
|
||||
let session = WCSession.default
|
||||
var data = [String: Any]()
|
||||
|
||||
if let sessionID = ExtensionDelegate.currentJitsiMeetContext.sessionID {
|
||||
if message != nil {
|
||||
message!.forEach { data[$0] = $1 }
|
||||
}
|
||||
|
||||
data["command"] = command.rawValue;
|
||||
data["sessionID"] = sessionID;
|
||||
|
||||
session.sendMessage(data, replyHandler: nil, errorHandler: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func updateUI(_ newContext: JitsiMeetContext) {
|
||||
var conferenceURL = newContext.conferenceURL
|
||||
|
||||
if let joinConferenceURL = newContext.joinConferenceURL {
|
||||
sendCommand(JitsiMeetCommands.CMD_JOIN_CONFERENCE, message: [ "data" : joinConferenceURL ])
|
||||
conferenceURL = joinConferenceURL
|
||||
}
|
||||
|
||||
let newRoomName = conferenceURL != nil ? conferenceURL!.components(separatedBy: "/").last : ""
|
||||
|
||||
roomLabel.setText(newRoomName)
|
||||
|
||||
if let newTimestamp = newContext.conferenceTimestamp {
|
||||
restartTimer(newTimestamp)
|
||||
}
|
||||
if let newMuted = newContext.micMuted {
|
||||
updateMutedButton(withMuted: newMuted)
|
||||
}
|
||||
}
|
||||
|
||||
func restartTimer(_ conferenceTimestamp: Int64) {
|
||||
if (conferenceTimestamp != 0) {
|
||||
let newDate = Date(timeIntervalSince1970: TimeInterval(conferenceTimestamp / 1000))
|
||||
timer.setDate(newDate)
|
||||
timer.start();
|
||||
print("WATCH timer set date to: \(newDate) and start")
|
||||
} else {
|
||||
print("WATCH timer stop")
|
||||
timer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
func updateMutedButton(withMuted isMuted: Bool) {
|
||||
if isMuted {
|
||||
mutedButton.setBackgroundImageNamed("mute-on.png")
|
||||
} else {
|
||||
mutedButton.setBackgroundImageNamed("mute-off.png")
|
||||
}
|
||||
}
|
||||
|
||||
override func awake(withContext context: Any?) {
|
||||
super.awake(withContext: context)
|
||||
|
||||
if let data = context as? JitsiMeetContext {
|
||||
updateUI(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
44
ios/app/watchos/extension/Info.plist
Normal file
@@ -0,0 +1,44 @@
|
||||
<?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>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>Jitsi Meet Companion Extension</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>XPC!</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>99.0.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>CLKComplicationPrincipalClass</key>
|
||||
<string>$(PRODUCT_MODULE_NAME).ComplicationController</string>
|
||||
<key>CLKComplicationSupportedFamilies</key>
|
||||
<array>
|
||||
<string>CLKComplicationFamilyModularSmall</string>
|
||||
<string>CLKComplicationFamilyUtilitarianSmall</string>
|
||||
<string>CLKComplicationFamilyCircularSmall</string>
|
||||
</array>
|
||||
<key>NSExtension</key>
|
||||
<dict>
|
||||
<key>NSExtensionAttributes</key>
|
||||
<dict>
|
||||
<key>WKAppBundleIdentifier</key>
|
||||
<string>org.jitsi.meet.watchkit</string>
|
||||
</dict>
|
||||
<key>NSExtensionPointIdentifier</key>
|
||||
<string>com.apple.watchkit</string>
|
||||
</dict>
|
||||
<key>WKExtensionDelegateClassName</key>
|
||||
<string>$(PRODUCT_MODULE_NAME).ExtensionDelegate</string>
|
||||
</dict>
|
||||
</plist>
|
||||
94
ios/app/watchos/extension/InterfaceController.swift
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright @ 2018-present 8x8, Inc.
|
||||
* Copyright @ 2017-2018 Atlassian Pty Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import WatchKit
|
||||
import WatchConnectivity
|
||||
import Foundation
|
||||
|
||||
|
||||
class InterfaceController: WKInterfaceController {
|
||||
|
||||
@IBOutlet var infoLabel: WKInterfaceLabel!
|
||||
@IBOutlet var table: WKInterfaceTable!
|
||||
|
||||
override func didAppear(){
|
||||
self.updateUI(ExtensionDelegate.currentJitsiMeetContext)
|
||||
}
|
||||
|
||||
func updateUI(_ newContext:JitsiMeetContext) {
|
||||
if (newContext.recentURLs == nil || newContext.recentURLs!.count == 0) {
|
||||
infoLabel.setText("There are no recent meetings. Please use the app on the phone to start a new call.")
|
||||
|
||||
table.setHidden(true)
|
||||
infoLabel.setHidden(false)
|
||||
} else {
|
||||
updateRecents(withRecents: newContext.recentURLs!, currentContext: newContext)
|
||||
|
||||
table.setHidden(false)
|
||||
infoLabel.setHidden(true)
|
||||
}
|
||||
}
|
||||
|
||||
private func updateRecents(withRecents recents: NSArray, currentContext: JitsiMeetContext) {
|
||||
// Updating the # of rows only if it actually changed prevents from blinking the UI
|
||||
if (table.numberOfRows != recents.count) {
|
||||
table.setNumberOfRows(recents.count, withRowType: "MeetingRowType")
|
||||
}
|
||||
|
||||
for (index, entry) in recents.enumerated() {
|
||||
let entryDict = entry as! NSDictionary
|
||||
let roomURL = entryDict["conference"] as! NSString
|
||||
let timestamp = entryDict["date"] as! NSNumber
|
||||
|
||||
// Prepare values
|
||||
let room = roomURL.components(separatedBy: "/").last
|
||||
let date = Date(timeIntervalSince1970: timestamp.doubleValue / 1000) // timestamp is taken with Date.now() in JS, which uses milliseconds
|
||||
let dateFormatter = DateFormatter()
|
||||
dateFormatter.timeZone = TimeZone.current
|
||||
dateFormatter.locale = NSLocale.current
|
||||
dateFormatter.dateFormat = "HH:mm yyyy-MM-dd"
|
||||
let strDate = dateFormatter.string(from: date)
|
||||
|
||||
// Update row controller
|
||||
let controller = table.rowController(at: index) as! MeetingRowController
|
||||
controller.room = room
|
||||
controller.roomUrl = roomURL as String
|
||||
controller.roomLabel.setText(room)
|
||||
controller.timeLabel.setText(strDate)
|
||||
|
||||
// Change the background for the active meeting
|
||||
if (controller.roomUrl == currentContext.conferenceURL) {
|
||||
controller.rowGroup.setBackgroundColor(UIColor(red: 0.125, green: 0.58, blue: 0.98, alpha: 1))
|
||||
} else {
|
||||
controller.rowGroup.setBackgroundColor(UIColor(red: 0.949, green: 0.956, blue: 1, alpha: 0.14))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func contextForSegue(withIdentifier segueIdentifier: String, in table: WKInterfaceTable, rowIndex: Int) -> Any? {
|
||||
let controller = table.rowController(at: rowIndex) as! MeetingRowController
|
||||
let currentContext = ExtensionDelegate.currentJitsiMeetContext
|
||||
|
||||
// Copy the current context and add the joinConferenceURL to trigger the command when the in-call screen is displayed
|
||||
let actionContext = JitsiMeetContext(jmContext: currentContext)
|
||||
actionContext.joinConferenceURL = controller.roomUrl
|
||||
|
||||
print("WATCH contextForSegue: \(actionContext.description)");
|
||||
|
||||
return actionContext;
|
||||
}
|
||||
}
|
||||
27
ios/app/watchos/extension/JitsiMeetCommands.swift
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright @ 2018-present 8x8, Inc.
|
||||
* Copyright @ 2017-2018 Atlassian Pty Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// This needs to be in sync with features/mobile/watchos/constants.js
|
||||
enum JitsiMeetCommands : String {
|
||||
typealias RawValue = String
|
||||
|
||||
case CMD_HANG_UP = "hangup";
|
||||
|
||||
case CMD_JOIN_CONFERENCE = "joinConference";
|
||||
|
||||
case CMD_SET_MUTED = "setMuted";
|
||||
}
|
||||
71
ios/app/watchos/extension/JitsiMeetContext.swift
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright @ 2018-present 8x8, Inc.
|
||||
* Copyright @ 2017-2018 Atlassian Pty Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
|
||||
class JitsiMeetContext {
|
||||
private var dictionary : [String : Any]
|
||||
|
||||
var joinConferenceURL : String? = nil;
|
||||
|
||||
init() {
|
||||
dictionary = [:]
|
||||
}
|
||||
|
||||
init(context: [String : Any]) {
|
||||
dictionary = context
|
||||
}
|
||||
|
||||
init(jmContext: JitsiMeetContext) {
|
||||
dictionary = jmContext.dictionary
|
||||
joinConferenceURL = jmContext.joinConferenceURL
|
||||
}
|
||||
|
||||
var conferenceURL : String? {
|
||||
get {
|
||||
return dictionary["conferenceURL"] as? String
|
||||
}
|
||||
}
|
||||
|
||||
var conferenceTimestamp : Int64? {
|
||||
get {
|
||||
return dictionary["conferenceTimestamp"] as? Int64;
|
||||
}
|
||||
}
|
||||
|
||||
var sessionID : Int64? {
|
||||
get {
|
||||
return dictionary["sessionID"] as? Int64;
|
||||
}
|
||||
}
|
||||
|
||||
var recentURLs : NSArray? {
|
||||
get {
|
||||
return dictionary["recentURLs"] as? NSArray
|
||||
}
|
||||
}
|
||||
|
||||
var micMuted : Bool? {
|
||||
get {
|
||||
return (dictionary["micMuted"] as? NSNumber)?.boolValue ?? nil;
|
||||
}
|
||||
}
|
||||
|
||||
public var description: String {
|
||||
return "JitsiMeetContext[conferenceURL: \(String(describing: conferenceURL)), conferenceTimestamp: \(String(describing:conferenceTimestamp)), sessionID: \(String(describing:sessionID)), recentURLs: \(String(describing:recentURLs)), joinConferenceURL: \(String(describing:joinConferenceURL)) "
|
||||
}
|
||||
}
|
||||
27
ios/app/watchos/extension/MeetingRowController.swift
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright @ 2018-present 8x8, Inc.
|
||||
* Copyright @ 2017-2018 Atlassian Pty Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import WatchKit
|
||||
|
||||
class MeetingRowController: NSObject {
|
||||
@IBOutlet var roomLabel: WKInterfaceLabel!
|
||||
@IBOutlet var timeLabel: WKInterfaceLabel!
|
||||
@IBOutlet var rowGroup: WKInterfaceGroup!
|
||||
|
||||
var room: String!
|
||||
var roomUrl: String!
|
||||
}
|
||||
@@ -39,6 +39,36 @@ platform :ios do
|
||||
end
|
||||
)
|
||||
|
||||
# Set the (watch) app identifier
|
||||
update_app_identifier(
|
||||
xcodeproj: "app/app.xcodeproj",
|
||||
plist_path: "watchos/app/Info.plist",
|
||||
app_identifier: "com.atlassian.JitsiMeet.ios.watchkit"
|
||||
)
|
||||
|
||||
# Set the (watch) extension identifier
|
||||
update_app_identifier(
|
||||
xcodeproj: "app/app.xcodeproj",
|
||||
plist_path: "watchos/extension/Info.plist",
|
||||
app_identifier: "com.atlassian.JitsiMeet.ios.watchkit.extension"
|
||||
)
|
||||
|
||||
update_info_plist(
|
||||
xcodeproj: "app/app.xcodeproj",
|
||||
plist_path: "watchos/app/Info.plist",
|
||||
block: proc do |plist|
|
||||
plist["WKCompanionAppBundleIdentifier"] = "com.atlassian.JitsiMeet.ios"
|
||||
end
|
||||
)
|
||||
|
||||
update_info_plist(
|
||||
xcodeproj: "app/app.xcodeproj",
|
||||
plist_path: "watchos/extension/Info.plist",
|
||||
block: proc do |plist|
|
||||
plist["NSExtension"]["NSExtensionAttributes"]["WKAppBundleIdentifier"] = "com.atlassian.JitsiMeet.ios.watchkit"
|
||||
end
|
||||
)
|
||||
|
||||
# Increment the build number by 1
|
||||
increment_build_number(
|
||||
build_number: Time.now.to_i,
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
C81E9AB925AC5AD800B134D9 /* ExternalAPI.h in Headers */ = {isa = PBXBuildFile; fileRef = C81E9AB825AC5AD800B134D9 /* ExternalAPI.h */; };
|
||||
C8AFD27F2462C613000293D2 /* InfoPlistUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = C8AFD27D2462C613000293D2 /* InfoPlistUtil.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C8AFD2802462C613000293D2 /* InfoPlistUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = C8AFD27E2462C613000293D2 /* InfoPlistUtil.m */; };
|
||||
DE438CDA2350934700DD541D /* JavaScriptSandbox.m in Sources */ = {isa = PBXBuildFile; fileRef = DE438CD82350934700DD541D /* JavaScriptSandbox.m */; };
|
||||
DE65AACA2317FFCD00290BEC /* LogUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = DE65AAC92317FFCD00290BEC /* LogUtils.h */; };
|
||||
DE65AACC2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DE65AACB2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h */; };
|
||||
DE762DB422AFDE76000DEBD6 /* JitsiMeetUserInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DE762DB322AFDE76000DEBD6 /* JitsiMeetUserInfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@@ -97,6 +98,7 @@
|
||||
DE9A015C289A9A9A00E41CBB /* JitsiMeetLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = DE81A2D32316AC4D00AE1940 /* JitsiMeetLogger.m */; };
|
||||
DE9A015E289A9A9A00E41CBB /* JitsiMeetView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B412F171EDEC65D00B1A0A6 /* JitsiMeetView.m */; };
|
||||
DE9A015F289A9A9A00E41CBB /* JitsiMeet.m in Sources */ = {isa = PBXBuildFile; fileRef = DEFE535321FB1BF800011A3A /* JitsiMeet.m */; };
|
||||
DE9A0160289A9A9A00E41CBB /* JavaScriptSandbox.m in Sources */ = {isa = PBXBuildFile; fileRef = DE438CD82350934700DD541D /* JavaScriptSandbox.m */; };
|
||||
DE9A0162289A9A9A00E41CBB /* Intents.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0BB9AD781F5EC6D7001C08DB /* Intents.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
|
||||
DE9A0163289A9A9A00E41CBB /* CallKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0BB9AD761F5EC6CE001C08DB /* CallKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
|
||||
DE9A0166289A9A9A00E41CBB /* CallKitIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = 0BC4B8681F8C01E100CE8B21 /* CallKitIcon.png */; };
|
||||
@@ -159,6 +161,7 @@
|
||||
C81E9AB825AC5AD800B134D9 /* ExternalAPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ExternalAPI.h; sourceTree = "<group>"; };
|
||||
C8AFD27D2462C613000293D2 /* InfoPlistUtil.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InfoPlistUtil.h; sourceTree = "<group>"; };
|
||||
C8AFD27E2462C613000293D2 /* InfoPlistUtil.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InfoPlistUtil.m; sourceTree = "<group>"; };
|
||||
DE438CD82350934700DD541D /* JavaScriptSandbox.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JavaScriptSandbox.m; sourceTree = "<group>"; };
|
||||
DE65AAC92317FFCD00290BEC /* LogUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LogUtils.h; sourceTree = "<group>"; };
|
||||
DE65AACB2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "JitsiMeetBaseLogHandler+Private.h"; sourceTree = "<group>"; };
|
||||
DE762DB322AFDE76000DEBD6 /* JitsiMeetUserInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JitsiMeetUserInfo.h; sourceTree = "<group>"; };
|
||||
@@ -247,6 +250,7 @@
|
||||
C69EFA02209A0EFD0027712B /* callkit */,
|
||||
A4A934E7212F3AB8001E9388 /* dropbox */,
|
||||
0BD906E91EC0C00300C8C18E /* Info.plist */,
|
||||
DE438CD82350934700DD541D /* JavaScriptSandbox.m */,
|
||||
0BD906E81EC0C00300C8C18E /* JitsiMeet.h */,
|
||||
DEFE535821FB311F00011A3A /* JitsiMeet+Private.h */,
|
||||
DEA9F283258A5D9900D4CD74 /* JitsiMeetSDK.h */,
|
||||
@@ -677,6 +681,7 @@
|
||||
DE81A2D52316AC4D00AE1940 /* JitsiMeetLogger.m in Sources */,
|
||||
0B412F191EDEC65D00B1A0A6 /* JitsiMeetView.m in Sources */,
|
||||
DEFE535421FB1BF800011A3A /* JitsiMeet.m in Sources */,
|
||||
DE438CDA2350934700DD541D /* JavaScriptSandbox.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -709,6 +714,7 @@
|
||||
4E0EF63328CA2FB3005D1B03 /* JMCallKitEmitter.m in Sources */,
|
||||
DE9A015E289A9A9A00E41CBB /* JitsiMeetView.m in Sources */,
|
||||
DE9A015F289A9A9A00E41CBB /* JitsiMeet.m in Sources */,
|
||||
DE9A0160289A9A9A00E41CBB /* JavaScriptSandbox.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
||||
55
ios/sdk/src/JavaScriptSandbox.m
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright @ 2019-present 8x8, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
@import JavaScriptCore;
|
||||
|
||||
#import <React/RCTBridgeModule.h>
|
||||
|
||||
|
||||
@interface JavaScriptSandbox : NSObject<RCTBridgeModule>
|
||||
@end
|
||||
|
||||
@implementation JavaScriptSandbox
|
||||
|
||||
RCT_EXPORT_MODULE();
|
||||
|
||||
+ (BOOL)requiresMainQueueSetup {
|
||||
return NO;
|
||||
}
|
||||
|
||||
#pragma mark - Exported methods
|
||||
|
||||
RCT_EXPORT_METHOD(evaluate:(NSString *)code
|
||||
resolve:(RCTPromiseResolveBlock)resolve
|
||||
reject:(RCTPromiseRejectBlock)reject) {
|
||||
__block BOOL hasError = NO;
|
||||
JSContext *ctx = [[JSContext alloc] init];
|
||||
ctx.exceptionHandler = ^(JSContext *context, JSValue *exception) {
|
||||
hasError = YES;
|
||||
reject(@"evaluate", [exception toString], nil);
|
||||
};
|
||||
JSValue *ret = [ctx evaluateScript:code];
|
||||
if (!hasError) {
|
||||
NSString *result = [ret toString];
|
||||
if (result == nil) {
|
||||
reject(@"evaluate", @"Error in string coercion", nil);
|
||||
} else {
|
||||
resolve(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
127
ios/travis-ci/build-ipa.sh
Executable file
@@ -0,0 +1,127 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# The script is based on tutorial written by Antonis Tsakiridis published at:
|
||||
# https://medium.com/@atsakiridis/continuous-deployment-for-ios-using-travis-ci-55dcea342d9
|
||||
#
|
||||
# It is intended to be executed through the Travis CI REST API call, as it
|
||||
# requires few arguments which are mandatory with no default values provided:
|
||||
# PR_REPO_SLUG - the Github name of the repo to be merged into the origin/master
|
||||
# PR_BRANCH - the branch to be merged, if set to "master" no merge will happen
|
||||
# IPA_DEPLOY_LOCATION - the location understandable by the "scp" command
|
||||
# executed at the end of the script to deploy the output .ipa file
|
||||
# LIB_JITSI_MEET_PKG (optional) - the npm package for lib-jitsi-meet which will
|
||||
# be put in place of the current version in the package.json file.
|
||||
#
|
||||
# Other than that the script requires the following env variables to be set
|
||||
# (reading the tutorial mentioned above will help in understanding the
|
||||
# variables):
|
||||
#
|
||||
# APPLE_CERT_URL - the URL pointing to Apple certificate (set to
|
||||
# http://developer.apple.com/certificationauthority/AppleWWDRCA.cer by default)
|
||||
# DEPLOY_SSH_CERT_URL - the SSH private key used by the 'scp' command to deploy
|
||||
# the .ipa. It is expected to be encrypted with the $ENCRYPTION_PASSWORD.
|
||||
# ENCRYPTION_PASSWORD - the password used to decrypt certificate/key files used
|
||||
# in the script.
|
||||
# IOS_DEV_CERT_KEY_URL - URL pointing to provisioning profile certificate key
|
||||
# file (development-key.p12.enc from the tutorial) encrypted with the
|
||||
# $ENCRYPTION_PASSWORD.
|
||||
# IOS_DEV_CERT_URL - URL pointing to provisioning profile certificate file
|
||||
# (development-cert.cer.enc from the tutorial) encrypted with the
|
||||
# $ENCRYPTION_PASSWORD.
|
||||
# IOS_DEV_PROV_PROFILE_URL - URL pointing to provisioning profile file
|
||||
# (profile-development-olympus.mobileprovision.enc from the tutorial) encrypted
|
||||
# with the $ENCRYPTION_PASSWORD.
|
||||
# IOS_SIGNING_CERT_PASSWORD - the password to the provisioning profile
|
||||
# certificate key (used to open development-key.p12 from the tutorial).
|
||||
# IOS_TEAM_ID - the team ID inserted into build-ipa-.plist.template file in
|
||||
# place of "YOUR_TEAM_ID".
|
||||
|
||||
|
||||
# Travis will not print the last echo if there's no sleep 1
|
||||
function echoSleepAndExit1() {
|
||||
echo $1
|
||||
sleep 1
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "TRAVIS_BRANCH=${TRAVIS_BRANCH}"
|
||||
echo "TRAVIS_REPO_SLUG=${TRAVIS_REPO_SLUG}"
|
||||
|
||||
if [ -z $PR_REPO_SLUG ]; then
|
||||
echoSleepAndExit1 "No PR_REPO_SLUG defined"
|
||||
fi
|
||||
if [ -z $PR_BRANCH ]; then
|
||||
echoSleepAndExit1 "No PR_BRANCH defined"
|
||||
fi
|
||||
if [ -z $IPA_DEPLOY_LOCATION ]; then
|
||||
echoSleepAndExit1 "No IPA_DEPLOY_LOCATION defined"
|
||||
fi
|
||||
|
||||
echo "PR_REPO_SLUG=${PR_REPO_SLUG} PR_BRANCH=${PR_BRANCH}"
|
||||
|
||||
# do the merge and git log
|
||||
|
||||
if [ $PR_BRANCH != "master" ]; then
|
||||
echo "Will merge ${PR_REPO_SLUG}/${PR_BRANCH} into master"
|
||||
git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
|
||||
git fetch origin master
|
||||
git checkout master
|
||||
git pull https://github.com/${PR_REPO_SLUG}.git $PR_BRANCH --no-edit
|
||||
fi
|
||||
|
||||
# Link this lib-jitsi-meet checkout in jitsi-meet through the package.json
|
||||
if [ ! -z ${LIB_JITSI_MEET_PKG} ];
|
||||
then
|
||||
echo "Adjusting lib-jitsi-meet package in package.json to ${LIB_JITSI_MEET_PKG}"
|
||||
# escape for the sed
|
||||
LIB_JITSI_MEET_PKG=$(echo $LIB_JITSI_MEET_PKG | sed -e 's/\\/\\\\/g; s/\//\\\//g; s/&/\\\&/g')
|
||||
sed -i.bak -e "s/\"lib-jitsi-meet.*/\"lib-jitsi-meet\"\: \"${LIB_JITSI_MEET_PKG}\",/g" package.json
|
||||
echo "Package.json lib-jitsi-meet line:"
|
||||
grep lib-jitsi-meet package.json
|
||||
else
|
||||
echo "LIB_JITSI_MEET_PKG var not set - will not modify the package.json"
|
||||
fi
|
||||
|
||||
git log -20 --graph --pretty=format':%C(yellow)%h%Cblue%d%Creset %s %C(white) %an, %ar%Creset'
|
||||
|
||||
#certificates
|
||||
CERT_DIR="ios/travis-ci/certs"
|
||||
|
||||
mkdir -p $CERT_DIR
|
||||
|
||||
./ios/ci/setup-certificates.sh $CERT_DIR
|
||||
|
||||
curl -L -o ${CERT_DIR}/id_rsa.enc ${DEPLOY_SSH_CERT_URL}
|
||||
openssl aes-256-cbc -k "$ENCRYPTION_PASSWORD" -in ${CERT_DIR}/id_rsa.enc -d -a -out ${CERT_DIR}/id_rsa
|
||||
chmod 0600 ${CERT_DIR}/id_rsa
|
||||
ssh-add ${CERT_DIR}/id_rsa
|
||||
|
||||
npm install
|
||||
|
||||
# Ever since the Apple Watch app has been added the bitcode for WebRTC needs to be downloaded in order to build successfully
|
||||
./node_modules/react-native-webrtc/tools/downloadBitcode.sh
|
||||
|
||||
cd ios
|
||||
pod install --repo-update --no-ansi
|
||||
cd ..
|
||||
|
||||
mkdir -p /tmp/jitsi-meet/
|
||||
|
||||
xcodebuild archive -quiet -workspace ios/jitsi-meet.xcworkspace -scheme jitsi-meet -configuration Release -archivePath /tmp/jitsi-meet/jitsi-meet.xcarchive
|
||||
|
||||
sed -e "s/YOUR_TEAM_ID/${IOS_TEAM_ID}/g" ios/ci/build-ipa.plist.template > ios/ci/build-ipa.plist
|
||||
|
||||
IPA_EXPORT_DIR=/tmp/jitsi-meet/jitsi-meet-ipa
|
||||
|
||||
xcodebuild -quiet -exportArchive -archivePath /tmp/jitsi-meet/jitsi-meet.xcarchive -exportPath $IPA_EXPORT_DIR -exportOptionsPlist ios/ci/build-ipa.plist
|
||||
|
||||
echo "Will try deploy the .ipa to: ${IPA_DEPLOY_LOCATION}"
|
||||
|
||||
if [ ! -z ${SCP_PROXY_HOST} ];
|
||||
then
|
||||
scp -o ProxyCommand="ssh -t -A -l %r ${SCP_PROXY_HOST} -o \"StrictHostKeyChecking no\" -o \"BatchMode yes\" -W %h:%p" -o StrictHostKeyChecking=no -o LogLevel=DEBUG "${IPA_EXPORT_DIR}/jitsi-meet.ipa" "${IPA_DEPLOY_LOCATION}"
|
||||
else
|
||||
scp -o StrictHostKeyChecking=no -o LogLevel=DEBUG "${IPA_EXPORT_DIR}/jitsi-meet.ipa" "${IPA_DEPLOY_LOCATION}"
|
||||
fi
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
"en": "English",
|
||||
"eo": "Esperanto",
|
||||
"es": "Español",
|
||||
"es-US": "Español (Latinoamérica)",
|
||||
"esUS": "Español (Latinoamérica)",
|
||||
"et": "Eesti",
|
||||
"eu": "Euskara",
|
||||
"fa": "فارسی",
|
||||
"fi": "Suomi",
|
||||
"fr": "Français",
|
||||
"fr-CA": "Français (Canada)",
|
||||
"frCA": "Français (Canada)",
|
||||
"gl": "Galego",
|
||||
"he": "עברית",
|
||||
"hi": "हिन्दी",
|
||||
@@ -31,7 +31,6 @@
|
||||
"it": "Italiano",
|
||||
"ja": "日本語",
|
||||
"kab": "Taqbaylit",
|
||||
"kk": "Қазақша",
|
||||
"ko": "한국어",
|
||||
"lt": "Lietuvių",
|
||||
"lv": "Latviešu",
|
||||
@@ -44,7 +43,7 @@
|
||||
"oc": "Occitan",
|
||||
"pl": "Polski",
|
||||
"pt": "Português",
|
||||
"pt-BR": "Português (Brasil)",
|
||||
"ptBR": "Português (Brasil)",
|
||||
"ro": "Română",
|
||||
"ru": "Русский",
|
||||
"sc": "Sardu",
|
||||
@@ -57,6 +56,6 @@
|
||||
"tr": "Türkçe",
|
||||
"uk": "Українська",
|
||||
"vi": "Tiếng Việt",
|
||||
"zh-CN": "中文(简体)",
|
||||
"zh-TW": "中文(繁體)"
|
||||
"zhCN": "中文(简体)",
|
||||
"zhTW": "中文(繁體)"
|
||||
}
|
||||
|
||||
@@ -537,6 +537,8 @@
|
||||
"googlePrivacyPolicy": "سياسية خصوصية غوغل",
|
||||
"inProgress": "البث المباشر غير ممكّن على {{email}}. يرجى تمكين البث المباشر أو تسجيل الدخول إلى حساب مع تمكين البث المباشر.",
|
||||
"invalidStreamKey": "يحتمل كون مفتاح البث الحي غير صحيح.",
|
||||
"limitNotificationDescriptionNative": "سيقيَّد البث إلى {{limit}} د، ولكن إن أردت إجراء عملية بث غير محدودة، جرِّب {{app}}.",
|
||||
"limitNotificationDescriptionWeb": "نظرًا للضغط الكبير، سيقيَّد البث إلى {{limit}} د، ولكن إن أردت إجراء عملية بث غير محدودة، جرِّب <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>.",
|
||||
"off": "أُوقِف البث الحي",
|
||||
"offBy": "أوقف {{name}} البث الحي",
|
||||
"on": "بث حي",
|
||||
@@ -896,6 +898,8 @@
|
||||
"highlightMomentSuccess": "تم تمييز اللحظة",
|
||||
"highlightMomentSucessDescription": "ستتم إضافة اللحظة المميزة إلى ملخص المُلتقى.",
|
||||
"inProgress": "التسجيل أو البث المباشر قيد التقدم",
|
||||
"limitNotificationDescriptionNative": "نظرًا للضغط الكبير، سيقيَّد التسجيل إلى {{limit}} د، ولكن إن أردت التسجيل لمدة مفتوحة، جرِّب <3>{{app}}</3>.",
|
||||
"limitNotificationDescriptionWeb": "نظرًا للضغط الكبير، سيقيَّد التسجيل إلى {{limit}} د، ولكن إن أردت التسجيل لمدة مفتوحة، جرِّب <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>.",
|
||||
"linkGenerated": "لقد أنشأنا رابطًا لتسجيلك.",
|
||||
"live": "مباشر",
|
||||
"localRecordingNoNotificationWarning": "لن يتم الإعلان عن التسجيل للمشاركين الآخرين. ستحتاج إلى إخبارهم بأنه تم تسجيل الاجتماع.",
|
||||
|
||||
@@ -541,6 +541,8 @@
|
||||
"googlePrivacyPolicy": "Polítiques de privadesa de Google",
|
||||
"inProgress": "L'enregistrament o la transmissió en directe és en progrés",
|
||||
"invalidStreamKey": "La clau de transmissió en directe pot ser incorrecta.",
|
||||
"limitNotificationDescriptionNative": "L'emissió es limitarà a {{limit}} min. Per a emissions sense límit proveu {{app}}.",
|
||||
"limitNotificationDescriptionWeb": "Atesa l'alta demanda, la vostra emissió es limitarà a {{limit}} minuts. Per a emissions il·limitades, proveu <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>",
|
||||
"off": "S'ha aturat la transmissió en directe",
|
||||
"offBy": "{{name}} ha aturat la transmissió en directe",
|
||||
"on": "Ha començat la transmissió en directe",
|
||||
@@ -903,6 +905,8 @@
|
||||
"highlightMomentSuccess": "Moment destacat",
|
||||
"highlightMomentSucessDescription": "S'ha afegit el moment destacat al resum de la reunió.",
|
||||
"inProgress": "L'enregistrament o la transmissió en directe és en progrés",
|
||||
"limitNotificationDescriptionNative": "A causa de la gran demanda, el vostre enregistrament es limitarà a {{limit}} min. Per a enregistraments il·limitats, proveu <3>{{app}}</3>.",
|
||||
"limitNotificationDescriptionWeb": "A causa de la gran demanda, l'enregistrament es limitarà a {{limit}} min. Per a enregistraments il·limitats, proveu <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>.",
|
||||
"linkGenerated": "S'ha generat un enllaç a l'enregistrament.",
|
||||
"live": "EN DIRECTE",
|
||||
"localRecordingNoNotificationWarning": "L'enregistrament no s'anunciarà als altres participants. Els haureu d'informar que la reunió s'està enregistrant.",
|
||||
|
||||
@@ -635,6 +635,8 @@
|
||||
"googlePrivacyPolicy": "Zásady soukromí Google",
|
||||
"inProgress": "Probíhá nahrávání nebo živé visílání",
|
||||
"invalidStreamKey": "Klíč k živému přenosu může být chybný.",
|
||||
"limitNotificationDescriptionNative": "Váš živý přenos může trvat nejvýše {{limit}} min. Pro neomezený přenos vyzkoušejte {{app}}.",
|
||||
"limitNotificationDescriptionWeb": "Kvůli vysokému zájmu může váš přenos trvat nejvýše {{limit}} min. Pro neomezený přenos vyzkoušejte <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>.",
|
||||
"off": "Živý přenos skončil",
|
||||
"offBy": "{{name}} zastavil/a živý přenos",
|
||||
"on": "Živý přenos",
|
||||
@@ -1035,6 +1037,8 @@
|
||||
"highlightMomentSuccess": "Zvýrazněný okamžik",
|
||||
"highlightMomentSucessDescription": "Váš zvýrazněný okamžik bude přidán do shrnutí setkání.",
|
||||
"inProgress": "Probíhá nahrávání nebo živé vysílání",
|
||||
"limitNotificationDescriptionNative": "Kvůli vysokému zájmu bude vaše nahrávka omezena na nejvýše {{limit}} min. Pro neomezené nahrávání zkuste <3>{{app}}</3>.",
|
||||
"limitNotificationDescriptionWeb": "Kvůli vysokému zájmu bude vaše nahrávka omezena na nejvýše {{limit}} min. Pro neomezené nahrávání zkuste <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>.",
|
||||
"linkGenerated": "Vygenerovali jsme odkaz na vaši nahrávku.",
|
||||
"localRecordingNoNotificationWarning": "Nahrávka nebude oznámena ostatním účastníkům. Budete jim muset dát vědět, že schůzka je nahrána.",
|
||||
"localRecordingNoVideo": "Video se nenahrává",
|
||||
|
||||
1883
lang/main-da.json
@@ -10,7 +10,7 @@
|
||||
"copyLink": "Konferenzlink kopieren",
|
||||
"copyStream": "Livestreaminglink kopieren",
|
||||
"countryNotSupported": "Wir unterstützen dieses Land noch nicht.",
|
||||
"countryReminder": "Telefonnummer nicht in den USA? Bitte sicherstellen, dass die Telefonnummer mit dem Ländercode beginnt!",
|
||||
"countryReminder": "Telefonnummer nicht in den USA? Bitte sicherstellen, dass die Telefonnummer mit dem Ländercode beginnt.",
|
||||
"defaultEmail": "Ihre Standard-E-Mail",
|
||||
"disabled": "Sie können keine Personen einladen.",
|
||||
"failedToAdd": "Fehler beim Hinzufügen von Personen",
|
||||
@@ -109,15 +109,9 @@
|
||||
}
|
||||
},
|
||||
"chat": {
|
||||
"disabled": "Chat-Nachrichten sind deaktiviert.",
|
||||
"enter": "Chat-Raum betreten",
|
||||
"error": "Fehler: Ihre Nachricht wurde nicht versendet. Grund: {{error}}",
|
||||
"everyone": "Alle",
|
||||
"fieldPlaceHolder": "Geben Sie Ihre Nachricht hier ein",
|
||||
"fileAccessibleTitle": "{{user}} hat eine Datei hochgeladen",
|
||||
"fileAccessibleTitleMe": "Ich habe eine Datei hochgeladen",
|
||||
"fileDeleted": "Eine Datei wurde gelöscht",
|
||||
"guestsChatIndicator": "(Gast)",
|
||||
"lobbyChatMessageTo": "Lobby-Nachricht an {{recipient}}",
|
||||
"message": "Nachricht",
|
||||
"messageAccessibleTitle": "{{user}} sagt:",
|
||||
@@ -126,20 +120,11 @@
|
||||
"messagebox": "Nachricht eingeben",
|
||||
"newMessages": "Neue Nachrichten",
|
||||
"nickname": {
|
||||
"featureChat": "Chat",
|
||||
"featureClosedCaptions": "Untertitel",
|
||||
"featureFileSharing": "Dateien",
|
||||
"featurePolls": "Umfragen",
|
||||
"popover": "Wähle einen Alias",
|
||||
"title": "Geben Sie einen Alias zum Chatten ein",
|
||||
"titleWith1Features": "Geben Sie einen Alias ein, um {{feature1}} zu nutzen",
|
||||
"titleWith2Features": "Geben Sie einen Alias ein, um {{feature1}} und {{feature2}} zu nutzen",
|
||||
"titleWith3Features": "Geben Sie einen Alias ein, um {{feature1}}, {{feature2}} und {{feature3}} zu nutzen",
|
||||
"titleWith4Features": "Geben Sie einen Alias ein, um {{feature1}}, {{feature2}}, {{feature3}} und {{feature4}} zu nutzen",
|
||||
"titleWithCC": "Geben Sie einen Alias zum Chatten und für Untertitel ein",
|
||||
"titleWithPolls": "Geben Sie einen Alias zum Chatten und für Umfragen ein",
|
||||
"titleWithPollsAndCC": "Geben Sie einen Alias zum Chatten, für Umfragen und Untertitel ein",
|
||||
"titleWithPollsAndCCAndFileSharing": "Geben Sie einen Alias zum Chatten, für Umfragen, Untertitel und Dateien ein"
|
||||
"titleWithPollsAndCC": "Geben Sie einen Alias zum Chatten, für Umfragen und Untertitel ein"
|
||||
},
|
||||
"noMessagesMessage": "Es gibt noch keine Nachricht in dieser Konferenz. Starten Sie hier eine Unterhaltung!",
|
||||
"privateNotice": "Private Nachricht an {{recipient}}",
|
||||
@@ -147,16 +132,14 @@
|
||||
"smileysPanel": "Emoji-Auswahl",
|
||||
"systemDisplayName": "System",
|
||||
"tabs": {
|
||||
"chat": "Chat",
|
||||
"chat": "Chatten",
|
||||
"closedCaptions": "Untertitel",
|
||||
"fileSharing": "Dateien",
|
||||
"polls": "Umfragen"
|
||||
},
|
||||
"title": "Chat",
|
||||
"titleWithCC": "Untertitel",
|
||||
"titleWithFeatures": "Chat und",
|
||||
"titleWithFileSharing": "Dateien",
|
||||
"titleWithPolls": "Umfragen",
|
||||
"title": "Chatten",
|
||||
"titleWithCC": "Chatten und Untertitel",
|
||||
"titleWithPolls": "Chatten und Umfragen",
|
||||
"titleWithPollsAndCC": "Chatten, Umfragen und Untertitel",
|
||||
"you": "Sie"
|
||||
},
|
||||
"chromeExtensionBanner": {
|
||||
@@ -227,9 +210,6 @@
|
||||
"video_ssrc": "Video-SSRC:",
|
||||
"yes": "Ja"
|
||||
},
|
||||
"customPanel": {
|
||||
"close": "Schließen"
|
||||
},
|
||||
"dateUtils": {
|
||||
"earlier": "Früher",
|
||||
"today": "Heute",
|
||||
@@ -294,6 +274,7 @@
|
||||
"Submit": "OK",
|
||||
"Understand": "Verstanden, Stummschaltung beibehalten",
|
||||
"UnderstandAndUnmute": "Verstanden, bitte Stummschaltung aufheben",
|
||||
"WaitForHostMsg": "Die Konferenz wurde noch nicht gestartet. Falls Sie die Konferenz leiten, authentifizieren Sie sich bitte. Warten Sie andernfalls, bis die Konferenz gestartet wird.",
|
||||
"WaitForHostNoAuthMsg": "Die Konferenz wurde noch nicht gestartet. Bitte warten Sie, bis die Konferenz gestartet wird.",
|
||||
"WaitingForHostButton": "Auf Moderation warten",
|
||||
"WaitingForHostTitle": "Warten auf den Beginn der Konferenz …",
|
||||
@@ -315,12 +296,6 @@
|
||||
"alreadySharedVideoTitle": "Nur ein geteiltes Video gleichzeitig",
|
||||
"applicationWindow": "Anwendungsfenster",
|
||||
"authenticationRequired": "Authentifizierung benötigt",
|
||||
"cameraCaptureDialog": {
|
||||
"description": "Ein Bild mit Ihrer Kamera aufnehmen und senden",
|
||||
"ok": "Kamera starten",
|
||||
"reject": "Jetzt nicht",
|
||||
"title": "Ein Bild aufnehmen"
|
||||
},
|
||||
"cameraConstraintFailedError": "Ihre Kamera erfüllt die notwendigen Anforderungen nicht.",
|
||||
"cameraNotFoundError": "Kamera nicht gefunden.",
|
||||
"cameraNotSendingData": "Die Kamera ist nicht verfügbar. Bitte prüfen, ob eine andere Applikation die Kamera verwendet, eine andere Kamera vom Einstellungs-Menü auswählen oder die Applikation neu laden.",
|
||||
@@ -359,7 +334,7 @@
|
||||
"error": "Fehler",
|
||||
"errorRoomCreationRestriction": "Sie haben versucht, zu schnell beizutreten, bitte versuchen Sie es gleich noch einmal.",
|
||||
"gracefulShutdown": "Der Dienst steht momentan wegen Wartungsarbeiten nicht zur Verfügung. Bitte versuchen Sie es später noch einmal.",
|
||||
"grantModeratorDialog": "Möchten Sie wirklich Moderationsrechte an {{participantName}} vergeben?",
|
||||
"grantModeratorDialog": "Möchten Sie wirklich Moderationsrechte an diese Person vergeben?",
|
||||
"grantModeratorTitle": "Moderationsrechte vergeben",
|
||||
"hide": "Ausblenden",
|
||||
"hideShareAudioHelper": "Diese Meldung nicht mehr anzeigen",
|
||||
@@ -383,9 +358,6 @@
|
||||
"lockRoom": "Konferenz$t(lockRoomPassword) hinzufügen",
|
||||
"lockTitle": "Sperren fehlgeschlagen",
|
||||
"login": "Anmelden",
|
||||
"loginFailed": "Anmeldung fehlgeschlagen.",
|
||||
"loginOnResume": "Ihre Anmeldung ist abgelaufen. Sie müssen sich neu anmelden um weiter an der Konferenz teilzunehmen.",
|
||||
"loginPopupBlocked": "Das Popup für die Anmeldung wurde von Ihrem Browser blockiert.",
|
||||
"loginQuestion": "Sind Sie sicher, dass sie sich anmelden und die Konferenz verlassen möchten?",
|
||||
"logoutQuestion": "Sind Sie sicher, dass Sie sich abmelden und die Konferenz verlassen möchten?",
|
||||
"logoutTitle": "Abmelden",
|
||||
@@ -396,37 +368,25 @@
|
||||
"micNotSendingData": "Gehen Sie zu den Einstellungen Ihres Computers, um die Stummschaltung Ihres Mikrofons aufzuheben und seinen Pegel einzustellen",
|
||||
"micNotSendingDataTitle": "Ihr Mikrofon ist durch Ihre Systemeinstellungen stumm geschaltet",
|
||||
"micPermissionDeniedError": "Die Berechtigung zur Verwendung des Mikrofons wurde nicht erteilt. Sie können trotzdem an der Konferenz teilnehmen, aber die anderen Personen können Sie nicht hören. Verwenden Sie die Kamera-Schaltfläche in der Adressleiste, um die Berechtigungen zu erteilen.",
|
||||
"micTimeoutError": "Audioquelle konnte nicht gestartet werden. Zeitüberschreitung!",
|
||||
"micTimeoutError": "Audioquelle konnte nicht gestartet werden. Zeitüberschreitung",
|
||||
"micUnknownError": "Das Mikrofon kann aus einem unbekannten Grund nicht verwendet werden.",
|
||||
"moderationAudioLabel": "Erlaube Anwesenden die Stummschaltung für sich aufzuheben",
|
||||
"moderationDesktopLabel": "Erlaube Anwesenden ihren Bildschirm freizugeben",
|
||||
"moderationVideoLabel": "Erlaube Anwesenden ihre Kamera einzuschalten",
|
||||
"muteEveryoneDialog": "Wollen Sie wirklich alle stummschalten? Sie können deren Stummschaltung nicht mehr beenden, aber sie können ihre Stummschaltung jederzeit selbst beenden.",
|
||||
"muteEveryoneDialogModerationOn": "Die Anwesenden können eine Anfrage zum Sprechen jederzeit senden.",
|
||||
"muteEveryoneElseDialog": "Einmal stummgeschaltet, können Sie deren Stummschaltung nicht mehr beenden, aber sie können ihre Stummschaltung jederzeit selbst beenden.",
|
||||
"muteEveryoneElseTitle": "Alle außer {{whom}} stummschalten?",
|
||||
"muteEveryoneElsesDesktopDialog": "Sobald die Bildschirmfreigaben beendet sind, können Sie diese nicht mehr starten, aber die anderen können sie jederzeit wieder starten.",
|
||||
"muteEveryoneElsesDesktopTitle": "Alle Bildschirmfreigaben außer {{whom}} beenden?",
|
||||
"muteEveryoneElsesVideoDialog": "Sobald die Kamera für alle anderen Personen deaktiviert ist, können Sie diese nicht wieder für alle einschalten, die anderen Personen können ihre Kamera aber jederzeit wieder einschalten.",
|
||||
"muteEveryoneElsesVideoTitle": "Die Kamera von allen außer {{whom}} ausschalten?",
|
||||
"muteEveryoneSelf": "sich selbst",
|
||||
"muteEveryoneStartMuted": "Alle beginnen von jetzt an stummgeschaltet",
|
||||
"muteEveryoneTitle": "Alle stummschalten?",
|
||||
"muteEveryonesDesktopDialog": "Die Anwesenden können ihren Bildschirm jederzeit freigeben.",
|
||||
"muteEveryonesDesktopDialogModerationOn": "Die Anwesenden können jederzeit eine Anfrage zur Bildschirmfreigabe senden.",
|
||||
"muteEveryonesDesktopTitle": "Alle Bildschirmfreigaben beenden?",
|
||||
"muteEveryonesVideoDialog": "Sind Sie sicher, dass Sie die Kamera von allen Personen deaktivieren möchten? Sie können dies nicht wieder rückgängig machen, jede Personen kann ihre Kamera aber jederzeit wieder einschalten.",
|
||||
"muteEveryonesVideoDialogModerationOn": "Die Anwesenden können jederzeit eine Anfrage senden, um ihre Kamera einzuschalten.",
|
||||
"muteEveryonesVideoDialogOk": "deaktivieren",
|
||||
"muteEveryonesVideoTitle": "Die Kamera von allen anderen ausschalten?",
|
||||
"muteParticipantBody": "Sie können die Stummschaltung anderer Personen nicht aufheben, aber eine Person kann ihre eigene Stummschaltung jederzeit beenden.",
|
||||
"muteParticipantButton": "Stummschalten",
|
||||
"muteParticipantsDesktopBody": "Sie können Bildschirmfreigaben von anderen nicht starten, sie können dies aber jederzeit.",
|
||||
"muteParticipantsDesktopBodyModerationOn": "Weder Sie noch andere Anwesende können Bildschirmfreigaben starten.",
|
||||
"muteParticipantsDesktopButton": "Bildschirmfreigabe beenden",
|
||||
"muteParticipantsDesktopDialog": "Sind Sie sicher, dass Sie die Bildschirmfreigabe von dieser Person beenden möchten? Sie können diese nicht mehr starten, die Person aber jederzeit.",
|
||||
"muteParticipantsDesktopDialogModerationOn": "Sind Sie sicher, dass Sie die Bildschirmfreigabe von dieser Person beenden möchten? Weder Sie noch die Person kann die Bildschirmfreigabe wieder starten.",
|
||||
"muteParticipantsDesktopTitle": "Bildschirmfreigabe von dieser Person beenden?",
|
||||
"muteParticipantsVideoBody": "Sie können die Kamera nicht wieder einschalten, die Person kann ihre Kamera aber jederzeit wieder einschalten.",
|
||||
"muteParticipantsVideoBodyModerationOn": "Sie können die Kamera nicht wieder aktivieren und die Person selbst auch nicht.",
|
||||
"muteParticipantsVideoButton": "Kamera ausschalten",
|
||||
@@ -435,8 +395,8 @@
|
||||
"muteParticipantsVideoTitle": "Die Kamera von dieser Person ausschalten?",
|
||||
"noDropboxToken": "Kein gültiges Dropbox-Token",
|
||||
"password": "Passwort",
|
||||
"passwordLabel": "Diese Konferenz wurde gesichert. Bitte geben Sie das $t(lockRoomPassword) ein, um der Konferenz beizutreten.",
|
||||
"passwordNotSupported": "Das Festlegen eines $t(lockRoomPassword) wird nicht unterstützt.",
|
||||
"passwordLabel": "Diese Konferenz wurde gesichert. Bitte geben Sie das $t(lockRoomPasswordUppercase) ein, um der Konferenz beizutreten.",
|
||||
"passwordNotSupported": "Das Festlegen eines Konferenzpassworts wird nicht unterstützt.",
|
||||
"passwordNotSupportedTitle": "$t(lockRoomPasswordUppercase) nicht unterstützt",
|
||||
"passwordRequired": "$t(lockRoomPasswordUppercase) erforderlich",
|
||||
"permissionCameraRequiredError": "Der Zugriff auf die Kamera wird benötigt, um in Videokonferenzen teilzunehmen. Bitte in den Einstellungen zulassen",
|
||||
@@ -446,7 +406,9 @@
|
||||
"recentlyUsedObjects": "Ihre zuletzt verwendeten Objekte",
|
||||
"recording": "Aufnahme",
|
||||
"recordingDisabledBecauseOfActiveLiveStreamingTooltip": "Während eines Livestreams nicht möglich",
|
||||
"recordingInProgressDescription": "Diese Konferenz wird aufgezeichnet und von KI analysiert. Ihr Ton und Video ist deaktiviert, wenn Sie es aktivieren, stimmen Sie der Aufzeichnung zu.",
|
||||
"recordingInProgressDescription": "Diese Konferenz wird aufgezeichnet und von KI analysiert {{learnMore}}. Ihr Ton und Video ist deaktiviert, wenn Sie es aktivieren, stimmen Sie der Aufzeichnung zu.",
|
||||
"recordingInProgressDescriptionFirstHalf": "Diese Konferenz wird aufgezeichnet und von KI analysiert",
|
||||
"recordingInProgressDescriptionSecondHalf": ". Ihr Ton und Video ist deaktiviert, wenn Sie es aktivieren, stimmen Sie der Aufzeichnung zu.",
|
||||
"recordingInProgressTitle": "Aufnahme läuft",
|
||||
"rejoinNow": "Jetzt erneut beitreten",
|
||||
"remoteControlAllowedMessage": "{{user}} hat die Anfrage zur Fernsteuerung angenommen!",
|
||||
@@ -457,7 +419,7 @@
|
||||
"remoteControlStopMessage": "Die Fernsteuerung wurde beendet!",
|
||||
"remoteControlTitle": "Fernsteuerung",
|
||||
"remoteUserControls": "Remote Benutzersteuerung von {{username}}",
|
||||
"removePassword": "$t(lockRoomPassword) entfernen",
|
||||
"removePassword": "$t(lockRoomPasswordUppercase) entfernen",
|
||||
"removeSharedVideoMsg": "Sind Sie sicher, dass Sie das geteilte Video entfernen möchten?",
|
||||
"removeSharedVideoTitle": "Freigegebenes Video entfernen",
|
||||
"renameBreakoutRoomLabel": "Raumname",
|
||||
@@ -469,8 +431,6 @@
|
||||
"screenSharingFailed": "Ups! Beim Teilen des Bildschirms ist etwas schiefgegangen!",
|
||||
"screenSharingFailedTitle": "Bildschirmfreigabe fehlgeschlagen!",
|
||||
"screenSharingPermissionDeniedError": "Ups! Etwas stimmt nicht mit Ihren Berechtigungen zur Bildschirmfreigabe. Bitte neu laden und erneut versuchen.",
|
||||
"screenshareStoppedDiskSpace": "Dies passiert, wenn Sie die Bildschirmfreigabe über die macOS-Menüleiste gestoppt haben. Die Bildschirmfreigabe kann auch bei geringem freien Speicherplatz gestoppt werden.",
|
||||
"screenshareStoppedTitle": "Bildschirmfreigabe vom Betriebssystem gestoppt",
|
||||
"searchInSalesforce": "In Salesforce suchen",
|
||||
"searchResults": "Suchergebnisse({{count}})",
|
||||
"searchResultsDetailsError": "Beim Abrufen der Daten des Besitzers ist ein Fehler aufgetreten.",
|
||||
@@ -484,7 +444,7 @@
|
||||
"serviceUnavailable": "Dienst nicht verfügbar",
|
||||
"sessTerminated": "Konferenz beendet",
|
||||
"sessTerminatedReason": "Die Konferenz wurde beendet",
|
||||
"sessionRestarted": "Konferenz neugestartet.",
|
||||
"sessionRestarted": "Konferenz neugestartet",
|
||||
"shareAudio": "Fortfahren",
|
||||
"shareAudioAltText": "Um den gewünschten Inhalt zu teilen: Navigiere zu \"Browser tab\", wähle den Inhalt, aktiviere \"Audio teilen\" Kästchen Und klicke den “Teilen” schaltfläche",
|
||||
"shareAudioTitle": "Wie kann Audio geteilt werden",
|
||||
@@ -539,7 +499,6 @@
|
||||
"tokenAuthFailedWithReasons": "Teilnahme an der Konferenz fehlgeschlagen. Möglicher Grund: {{reason}}",
|
||||
"tokenAuthUnsupported": "Token-Authentifizierung wird nicht unterstützt.",
|
||||
"transcribing": "Wird transkribiert",
|
||||
"unauthenticatedAccessDisabled": "Zur Teilnahme an dieser Konferenz müssen Sie sich anmelden.",
|
||||
"unlockRoom": "Konferenz$t(lockRoomPassword) entfernen",
|
||||
"user": "Anmeldename",
|
||||
"userIdentifier": "Benutzername",
|
||||
@@ -580,26 +539,6 @@
|
||||
"veryBad": "Sehr schlecht",
|
||||
"veryGood": "Sehr gut"
|
||||
},
|
||||
"fileSharing": {
|
||||
"downloadFailedDescription": "Bitte nochmals versuchen.",
|
||||
"downloadFailedTitle": "Download fehlgeschlagen",
|
||||
"downloadFile": "Download",
|
||||
"downloadStarted": "Download gestartet",
|
||||
"dragAndDrop": "Dateien hier oder irgendwo auf dem Bildschirm loslassen",
|
||||
"fileAlreadyUploaded": "Datei wurde schon zur Konferenz hochgeladen.",
|
||||
"fileRemovedByOther": "Ihre Datei '{{ fileName }}' wurde entfernt",
|
||||
"fileTooLargeDescription": "Bitte stellen Sie sicher, dass Ihre Datei nicht die Maximalgröße von {{ maxFileSize }} überschreitet.",
|
||||
"fileTooLargeTitle": "Die ausgewählte Datei ist zu groß",
|
||||
"fileUploadProgress": "Datei wird hochgeladen",
|
||||
"fileUploadedSuccessfully": "Datei erfolgreich hochgeladen",
|
||||
"newFileNotification": "{{ participantName }} hat Datei '{{ fileName }}' hochgeladen",
|
||||
"removeFile": "Entfernen",
|
||||
"removeFileSuccess": "Datei erfolgreich entfernt",
|
||||
"uploadDisabled": "Keine Berechtigung, Dateien hochzuladen. Bitte bei der Moderation anfragen.",
|
||||
"uploadFailedDescription": "Bitte versuchen Sie es erneut.",
|
||||
"uploadFailedTitle": "Dateiupload fehlgeschlagen",
|
||||
"uploadFile": "Datei hochladen"
|
||||
},
|
||||
"filmstrip": {
|
||||
"accessibilityLabel": {
|
||||
"heading": "Videominiaturen"
|
||||
@@ -618,8 +557,8 @@
|
||||
},
|
||||
"info": {
|
||||
"accessibilityLabel": "Informationen anzeigen",
|
||||
"addPassword": "$t(lockRoomPassword) hinzufügen",
|
||||
"cancelPassword": "$t(lockRoomPassword) löschen",
|
||||
"addPassword": "$t(lockRoomPasswordUppercase) hinzufügen",
|
||||
"cancelPassword": "$t(lockRoomPasswordUppercase) löschen",
|
||||
"conferenceURL": "Link:",
|
||||
"copyNumber": "Nummer kopieren",
|
||||
"country": "Land",
|
||||
@@ -649,7 +588,7 @@
|
||||
"noRoom": "Keine Konferenz für die Einwahlinformationen angegeben.",
|
||||
"noWhiteboard": "Whiteboard konnte nicht geladen werden.",
|
||||
"numbers": "Einwahlnummern",
|
||||
"password": "$t(lockRoomPasswordUppercase): ",
|
||||
"password": "$t(lockRoomPasswordUppercase):",
|
||||
"reachedLimit": "Sie haben die Grenzen Ihres Tarifs erreicht.",
|
||||
"sip": "SIP-Adresse",
|
||||
"sipAudioOnly": "SIP-Adresse (nur Ton)",
|
||||
@@ -701,19 +640,20 @@
|
||||
"changeSignIn": "Konten wechseln.",
|
||||
"choose": "Livestream auswählen",
|
||||
"chooseCTA": "Streaming-Option auswählen. Sie sind aktuell als {{email}} angemeldet.",
|
||||
"chooseCTAWithChangeSignIn": "Streaming-Option auswählen. Sie sind aktuell als {{email}} angemeldet. <0>Account wechseln.</0>",
|
||||
"enterStreamKey": "Streamschlüssel für den YouTube-Livestream hier eingeben.",
|
||||
"error": "Das Livestreaming ist fehlgeschlagen. Bitte versuchen Sie es erneut.",
|
||||
"errorAPI": "Beim Abrufen der YouTube-Livestreams ist ein Fehler aufgetreten. Bitte versuchen Sie, sich erneut anzumelden.",
|
||||
"errorLiveStreamNotEnabled": "Livestreaming ist für {{email}} nicht aktiviert. Aktivieren Sie das Livestreaming oder melden Sie sich bei einem Konto mit aktiviertem Livestreaming an.",
|
||||
"expandedOff": "Livestream wurde angehalten",
|
||||
"expandedOn": "Die Konferenz wird momentan an YouTube gestreamt",
|
||||
"expandedOn": "Die Konferenz wird momentan an YouTube gestreamt.",
|
||||
"expandedPending": "Livestream wird gestartet …",
|
||||
"failedToStart": "Livestream konnte nicht gestartet werden",
|
||||
"getStreamKeyManually": "Wir waren nicht in der Lage, Livestreams abzurufen. Versuchen Sie, Ihren Livestream-Schlüssel von YouTube zu erhalten.",
|
||||
"googlePrivacyPolicy": "Google-Datenschutzerklärung",
|
||||
"inProgress": "Livestreaming gestartet",
|
||||
"invalidStreamKey": "Der Livestream-Schlüssel ist u. U. falsch.",
|
||||
"limitNotificationDescriptionNative": "Ihr Stream ist begrenzt auf {{limit}} Min. Für unlimitiertes Streaming, nutzen Sie bitte {{app}}.",
|
||||
"limitNotificationDescriptionWeb": "Wegen hoher Nachfrage ist Ihr Stream auf {{limit}} Min. begrenzt. Für unlimitiertes Streaming nutzen Sie bitte <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>.",
|
||||
"off": "Livestream gestoppt",
|
||||
"offBy": "{{name}} stoppte den Livestream",
|
||||
"on": "Livestream",
|
||||
@@ -730,7 +670,6 @@
|
||||
"streamIdHelp": "Was ist das?",
|
||||
"title": "Livestream",
|
||||
"unavailableTitle": "Livestreaming nicht verfügbar",
|
||||
"youTubeGoLiveWarning": "Denken Sie daran 'Go Live' im YouTube Studio auszuwählen, wenn Auto-Start/Auto-Stop deaktiviert ist. Ansonsten wird die Aufnahme nicht gestartet.",
|
||||
"youtubeTerms": "YouTube-Nutzungsbedingungen"
|
||||
},
|
||||
"lobby": {
|
||||
@@ -751,7 +690,7 @@
|
||||
"joinRejectedTitle": "Beitrittsanfrage abgelehnt.",
|
||||
"joinTitle": "Konferenz beitreten",
|
||||
"joinWithPasswordMessage": "Beitrittsversuch mit Passwort, bitte warten …",
|
||||
"joiningMessage": "Sie treten der Konferenz bei, sobald jemand Ihre Anfrage annimmt",
|
||||
"joiningMessage": "Sie treten der Konferenz bei, sobald jemand Ihre Anfrage annimmt.",
|
||||
"joiningTitle": "Beitritt anfragen …",
|
||||
"joiningWithPasswordTitle": "Mit Passwort beitreten …",
|
||||
"knockButton": "Beitritt anfragen",
|
||||
@@ -768,8 +707,7 @@
|
||||
"notificationTitle": "Lobby",
|
||||
"passwordJoinButton": "Beitreten",
|
||||
"title": "Lobby",
|
||||
"toggleLabel": "Lobby aktivieren",
|
||||
"waitForModerator": "Die Konferenz wurde noch nicht gestartet, da noch keine Moderation anwesend ist. Wenn Sie zur Moderation gehören, melden Sie sich bitte an, ansonsten warten Sie bitte."
|
||||
"toggleLabel": "Lobby aktivieren"
|
||||
},
|
||||
"localRecording": {
|
||||
"clientState": {
|
||||
@@ -812,23 +750,21 @@
|
||||
"me": "ich",
|
||||
"notify": {
|
||||
"OldElectronAPPTitle": "Sicherheitslücke!",
|
||||
"allowAll": "Alles einschalten",
|
||||
"allowAudio": "Mikrofon einschalten",
|
||||
"allowDesktop": "Bildschirmfreigabe einschalten",
|
||||
"allowBoth": "Beides",
|
||||
"allowVideo": "Kamera einschalten",
|
||||
"allowedUnmute": "Sie können die Stummschaltung aufheben, Ihre Kamera einschalten oder Ihren Bildschirm teilen.",
|
||||
"audioUnmuteBlockedDescription": "Díe Stummschaltung kann aus Überlastungsschutzgründen temporär nicht aufgehoben werden.",
|
||||
"audioUnmuteBlockedTitle": "Stummschaltung kann nicht aufgehoben werden!",
|
||||
"chatMessages": "Chatnachrichten",
|
||||
"connectedOneMember": "{{name}} nimmt an der Konferenz teil",
|
||||
"connectedThreePlusMembers": "{{name}} und viele andere Personen nehmen an der Konferenz teil",
|
||||
"connectedThreePlusMembers": "{{name}} und {{count}} andere Personen nehmen an der Konferenz teil",
|
||||
"connectedTwoMembers": "{{first}} und {{second}} nehmen an der Konferenz teil",
|
||||
"connectionFailed": "Verbindung fehlgeschlagen. Bitte versuchen Sie es später noch einmal!",
|
||||
"dataChannelClosed": "Schlechte Videoqualität",
|
||||
"dataChannelClosedDescription": "Die Steuerungsverbindung (Bridge Channel) wurde unterbrochen, daher ist die Videoqulität auf die schlechteste Stufe limitiert.",
|
||||
"dataChannelClosedDescriptionWithAudio": "Die Steuerungsverbindung (Bridge Channel) wurde unterbrochen, daher können Video- und Tonprobleme auftreten.",
|
||||
"dataChannelClosedWithAudio": "Ton- und Videoqualität können beeinträchtigt sein",
|
||||
"desktopMutedRemotelyTitle": "Ihre Bildschirmfreigabe wurde von {{participantDisplayName}} gestoppt",
|
||||
"disabledIframe": "Die Einbettung ist nur für Demo-Zwecke vorgesehen. Diese Konferenz wird in {{timeout}} Minuten beendet.",
|
||||
"disabledIframeSecondaryNative": "Die Einbettung von {{domain}} ist nur für Demo-Zwecke vorgesehen. Diese Konferenz wird in {{timeout}} Minuten beendet.",
|
||||
"disabledIframeSecondaryWeb": "Die Einbettung von {{domain}} ist nur für Demo-Zwecke vorgesehen. Diese Konferenz wird in {{timeout}} Minuten beendet. Bitte nutzen Sie <a href='{{jaasDomain}}' rel='noopener noreferrer' target='_blank'>Jitsi as a Service</a> für produktive Zwecke!",
|
||||
@@ -839,7 +775,7 @@
|
||||
"focusFail": "{{component}} ist im Moment nicht verfügbar – wiederholen in {{ms}} Sekunden",
|
||||
"gifsMenu": "GIPHY",
|
||||
"groupTitle": "Benachrichtigungen",
|
||||
"hostAskedUnmute": "Die Moderation bittet Sie, das Mikrofon zu aktivieren.",
|
||||
"hostAskedUnmute": "Die Moderation bittet Sie, das Mikrofon zu aktivieren",
|
||||
"invalidTenant": "Ungültiger Mandant",
|
||||
"invalidTenantHyphenDescription": "Der gewählte Mandantenname ist ungültig (beginnt oder endet mit '-').",
|
||||
"invalidTenantLengthDescription": "Der gewählte Mandantenname ist zu lang.",
|
||||
@@ -860,21 +796,21 @@
|
||||
"localRecordingStarted": "{{name}} hat eine lokale Aufzeichnung gestartet.",
|
||||
"localRecordingStopped": "{{name}} hat eine lokale Aufzeichnung gestoppt.",
|
||||
"me": "Ich",
|
||||
"moderationInEffectCSDescription": "Bitte melden um ein Video zu teilen.",
|
||||
"moderationInEffectCSDescription": "Bitte melden um ein Video zu teilen",
|
||||
"moderationInEffectCSTitle": "Die Videofreigabe ist von der Moderation gesperrt",
|
||||
"moderationInEffectDescription": "Bitte melden um zu sprechen.",
|
||||
"moderationInEffectDescription": "Bitte melden um zu sprechen",
|
||||
"moderationInEffectTitle": "Das Mikrofon ist von der Moderation gesperrt",
|
||||
"moderationInEffectVideoDescription": "Bitte melden um die Kamera zu starten.",
|
||||
"moderationInEffectVideoDescription": "Bitte melden um die Kamera zu starten",
|
||||
"moderationInEffectVideoTitle": "Die Kamera ist von der Moderation gesperrt",
|
||||
"moderationRequestFromModerator": "Die Moderation bittet Sie, das Mikrofon zu aktivieren",
|
||||
"moderationRequestFromParticipant": "möchte sprechen",
|
||||
"moderationStartedTitle": "Moderation gestartet",
|
||||
"moderationStoppedTitle": "Moderation gestoppt",
|
||||
"moderationToggleDescription": "von {{participantDisplayName}}",
|
||||
"moderator": "Sie sind jetzt Teil der Moderation",
|
||||
"moderator": "Moderationsrechte vergeben!",
|
||||
"muted": "Der Konferenz wurde stumm beigetreten.",
|
||||
"mutedRemotelyDescription": "Sie können jederzeit die Stummschaltung aufheben, wenn Sie bereit sind zu sprechen. Wenn Sie fertig sind, können Sie sich wieder stummschalten, um Geräusche von der Konferenz fernzuhalten.",
|
||||
"mutedRemotelyTitle": "Sie wurden von {{participantDisplayName}} stummgeschaltet",
|
||||
"mutedRemotelyTitle": "Sie wurden von {{participantDisplayName}} stummgeschaltet!",
|
||||
"mutedTitle": "Stummschaltung aktiv!",
|
||||
"newDeviceAction": "Verwenden",
|
||||
"newDeviceAudioTitle": "Neues Audiogerät erkannt",
|
||||
@@ -885,35 +821,33 @@
|
||||
"noiseSuppressionStereoDescription": "Rauschunterdrückung unterstützt aktuell keinen Stereoton.",
|
||||
"oldElectronClientDescription1": "Sie scheinen eine alte Version des Jitsi-Meet-Clients zu nutzen. Diese hat bekannte Schwachstellen. Bitte aktualisieren Sie auf unsere ",
|
||||
"oldElectronClientDescription2": "aktuelle Version",
|
||||
"oldElectronClientDescription3": " jetzt!",
|
||||
"openChat": "Chat öffnen",
|
||||
"oldElectronClientDescription3": "!",
|
||||
"participantWantsToJoin": "Möchte an der Konferenz teilnehmen",
|
||||
"participantsWantToJoin": "Möchten an der Konferenz teilnehmen",
|
||||
"passwordRemovedRemotely": "$t(lockRoomPasswordUppercase) von einer anderen Person entfernt",
|
||||
"passwordSetRemotely": "$t(lockRoomPasswordUppercase) von einer anderen Person gesetzt",
|
||||
"raiseHandAction": "Melden",
|
||||
"raisedHand": "möchte sprechen.",
|
||||
"raisedHand": "{{name}} möchte sprechen.",
|
||||
"raisedHands": "{{participantName}} und {{raisedHands}} weitere möchten sprechen",
|
||||
"reactionSounds": "Interaktionstöne deaktivieren",
|
||||
"reactionSoundsForAll": "Interaktionstöne für alle deaktivieren",
|
||||
"screenShareNoAudio": "Die Option \"Audio freigeben\" wurde bei der Auswahl des Fensters nicht ausgewählt.",
|
||||
"screenShareNoAudioTitle": "Systemton konnte nicht geteilt werden!",
|
||||
"screenShareNoAudioTitle": "Share audio was not checked",
|
||||
"screenSharingAudioOnlyDescription": "Durch die Bildschirmfreigabe wird der Modus \"Beste Leistung\" beeinflusst und daher mehr Datenrate benötigt.",
|
||||
"screenSharingAudioOnlyTitle": "Modus \"Beste Leistung\"",
|
||||
"selfViewTitle": "Sie können die eigene Ansicht immer in den Einstellungen reaktivieren",
|
||||
"somebody": "Jemand",
|
||||
"startSilentDescription": "Treten Sie der Konferenz noch einmal bei, um Ihr Audio zu aktivieren",
|
||||
"startSilentTitle": "Sie sind ohne Audioausgabe beigetreten!",
|
||||
"suboptimalBrowserWarning": "Tut uns leid, aber die Konferenz wird kein großartiges Erlebnis. Wir versuchen immer die Situation zu verbessern, bis dahin empfehlen wir aber die Verwendung einer der <a href=\"{{recommendedBrowserPageLink}}\" target=\"_blank\">vollständig unterstützen Browser</a>.",
|
||||
"suboptimalBrowserWarning": "Tut uns leid, aber die Konferenz wird mit {{appName}} kein großartiges Erlebnis. Wir versuchen immer die Situation zu verbessern, bis dahin empfehlen wir aber die Verwendung einer der <a href=\"{{recommendedBrowserPageLink}}\" target=\"_blank\">vollständig unterstützen Browser</a>.",
|
||||
"suboptimalExperienceTitle": "Browserwarnung",
|
||||
"suggestRecordingAction": "Starten",
|
||||
"suggestRecordingDescription": "Möchten Sie eine Aufzeichnung starten?",
|
||||
"suggestRecordingTitle": "Konferenz aufzeichnen",
|
||||
"unmute": "Stummschaltung aufheben",
|
||||
"unmuteScreen": "Bildschirmfreigabe starten",
|
||||
"unmuteVideo": "Kamera einschalten",
|
||||
"videoMutedRemotelyDescription": "Sie können sie jederzeit wieder einschalten.",
|
||||
"videoMutedRemotelyTitle": "Ihre Kamera wurde von {{participantDisplayName}} ausgeschaltet",
|
||||
"videoMutedRemotelyTitle": "Ihre Kamera wurde von {{participantDisplayName}} ausgeschaltet!",
|
||||
"videoUnmuteBlockedDescription": "Die Kamera und Bildschirmfreigabe kann aus Überlastungsschutzgründen temporär nicht eingeschaltet werden.",
|
||||
"videoUnmuteBlockedTitle": "Kamera und Bildschirmfreigabe kann nicht aktiviert werden!",
|
||||
"viewLobby": "Lobby ansehen",
|
||||
@@ -930,14 +864,11 @@
|
||||
"admit": "Zulassen",
|
||||
"admitAll": "Alle zulassen",
|
||||
"allow": "Anwesenden erlauben:",
|
||||
"allowDesktop": "Bildschirm freizugeben",
|
||||
"allowVideo": "Kamera einschalten",
|
||||
"askDesktop": "Anfragen, Bildschirm freizugeben",
|
||||
"askUnmute": "Anfragen, Stummschaltung aufzuheben",
|
||||
"audioModeration": "Für sich selbst die Stummschaltung aufzuheben",
|
||||
"blockEveryoneMicCamera": "Kamera und Mikrofon von allen sperren",
|
||||
"breakoutRooms": "Breakout-Räume",
|
||||
"desktopModeration": "Bildschirmfreigabe",
|
||||
"goLive": "Live gehen",
|
||||
"invite": "Person einladen",
|
||||
"lowerAllHands": "Alle Hände senken",
|
||||
@@ -949,8 +880,6 @@
|
||||
"muteAll": "Alle stummschalten",
|
||||
"muteEveryoneElse": "Alle anderen stummschalten",
|
||||
"reject": "Ablehnen",
|
||||
"stopDesktop": "Bildschirmfreigabe beenden",
|
||||
"stopEveryonesDesktop": "Alle Bildschirmfreigaben beenden",
|
||||
"stopEveryonesVideo": "Alle Kameras ausschalten",
|
||||
"stopVideo": "Kamera ausschalten",
|
||||
"unblockEveryoneMicCamera": "Kamera und Mikrofon von allen entsperren",
|
||||
@@ -960,11 +889,9 @@
|
||||
"headings": {
|
||||
"lobby": "Lobby ({{count}})",
|
||||
"participantsList": "Anwesende ({{count}})",
|
||||
"viewerRequests": "Zuschaueranfragen {{count}}",
|
||||
"visitorInQueue": " (Wartende Gäste {{count}})",
|
||||
"visitorRequests": " (Anfragen {{count}})",
|
||||
"visitors": "Gäste ({{count}})",
|
||||
"visitorsList": "Zuschauer ({{count}})",
|
||||
"waitingLobby": "In der Lobby ({{count}})"
|
||||
},
|
||||
"search": "Suche Anwesende",
|
||||
@@ -985,9 +912,6 @@
|
||||
"by": "Von {{ name }}",
|
||||
"closeButton": "Umfrage schließen",
|
||||
"create": {
|
||||
"accessibilityLabel": {
|
||||
"send": "Umfrage erstellen"
|
||||
},
|
||||
"addOption": "Antwort hinzufügen",
|
||||
"answerPlaceholder": "Antwort {{index}}",
|
||||
"cancel": "Abbrechen",
|
||||
@@ -996,7 +920,8 @@
|
||||
"pollQuestion": "Frage",
|
||||
"questionPlaceholder": "Eine Frage stellen",
|
||||
"removeOption": "Antwort entfernen",
|
||||
"save": "Erstellen"
|
||||
"save": "Erstellen",
|
||||
"send": "Senden"
|
||||
},
|
||||
"errors": {
|
||||
"notUniqueOption": "Optionen müssen einzigartig sein"
|
||||
@@ -1007,7 +932,7 @@
|
||||
},
|
||||
"results": {
|
||||
"changeVote": "Antwort ändern",
|
||||
"empty": "Es gibt bisher keine Umfragen in dieser Konferenz.",
|
||||
"empty": "Es gibt bisher keine Umfragen in dieser Konferenz. Sie können hier eine Umfrage starten!",
|
||||
"hideDetailedResults": "Details verbergen",
|
||||
"showDetailedResults": "Details anzeigen",
|
||||
"vote": "Vote"
|
||||
@@ -1016,7 +941,7 @@
|
||||
"poweredby": "Betrieben von",
|
||||
"prejoin": {
|
||||
"audioAndVideoError": "Audio- und Videofehler:",
|
||||
"audioDeviceProblem": "Es gibt ein Problem mit Ihrem Audiogerät",
|
||||
"audioDeviceProblem": "Es gibt ein Problem mit Ihrem Audiogerät.",
|
||||
"audioOnlyError": "Audiofehler:",
|
||||
"audioTrackError": "Audiotrack konnte nicht erstellt werden.",
|
||||
"callMe": "Mich anrufen",
|
||||
@@ -1027,8 +952,8 @@
|
||||
"connection": {
|
||||
"failed": "Verbindungstest fehlgeschlagen!",
|
||||
"good": "Ihre Internetverbindung sieht gut aus!",
|
||||
"nonOptimal": "Ihre Internetverbindung ist nicht optimal",
|
||||
"poor": "Sie haben eine schlechte Internetverbindung",
|
||||
"nonOptimal": "Ihre Internetverbindung ist nicht optimal.",
|
||||
"poor": "Sie haben eine schlechte Internetverbindung.",
|
||||
"running": "Verbindung wird getestet…"
|
||||
},
|
||||
"connectionDetails": {
|
||||
@@ -1055,7 +980,7 @@
|
||||
"errorDialOutDisconnected": "Anruf fehlgeschlagen. Verbindungsabbruch",
|
||||
"errorDialOutFailed": "Anruf fehlgeschlagen. Anruf fehlgeschlagen",
|
||||
"errorDialOutStatus": "Fehler beim Abrufen des Anrufstatus",
|
||||
"errorMissingName": "Bitte geben Sie Ihren Namen ein, um der Konferenz beizutreten",
|
||||
"errorMissingName": "Bitte geben Sie Ihren Namen ein, um der Konferenz beizutreten.",
|
||||
"errorNoPermissions": "Sie müssen den Zugriff auf Mikrofon und Kamera erlauben",
|
||||
"errorStatusCode": "Anruf fehlgeschlagen. Statuscode: {{status}}",
|
||||
"errorValidation": "Nummerverifikation fehlgeschlagen",
|
||||
@@ -1067,7 +992,7 @@
|
||||
"joinWithoutAudio": "Ohne Ton beitreten",
|
||||
"keyboardShortcuts": "Tastaturkurzbefehle aktivieren",
|
||||
"linkCopied": "Link in die Zwischenablage kopiert",
|
||||
"lookGood": "Alles scheint zu funktionieren",
|
||||
"lookGood": "Alles scheint zu funktionieren.",
|
||||
"or": "oder",
|
||||
"premeeting": "Vorschau",
|
||||
"proceedAnyway": "Trotzdem fortsetzen",
|
||||
@@ -1124,7 +1049,7 @@
|
||||
"error": "Die Aufzeichnung ist fehlgeschlagen. Bitte versuchen Sie es erneut.",
|
||||
"errorFetchingLink": "Der Link zur Aufzeichnung konnte nicht geladen werden.",
|
||||
"expandedOff": "Aufzeichnung wurde gestoppt",
|
||||
"expandedOn": "Die Konferenz wird momentan aufgezeichnet",
|
||||
"expandedOn": "Die Konferenz wird momentan aufgezeichnet.",
|
||||
"expandedPending": "Aufzeichnung wird gestartet…",
|
||||
"failedToStart": "Die Aufnahme konnte nicht gestartet werden",
|
||||
"fileSharingdescription": "Aufzeichnung mit den Personen der Konferenz teilen",
|
||||
@@ -1134,6 +1059,8 @@
|
||||
"highlightMomentSuccess": "Highlight festgehalten",
|
||||
"highlightMomentSucessDescription": "Ihr festgehaltener Moment wird zur Zusammenfassung der Konferenz hinzugefügt.",
|
||||
"inProgress": "Aufzeichnung gestartet",
|
||||
"limitNotificationDescriptionNative": "Wegen hoher Nachfrage ist Ihre Aufnahme auf {{limit}} Min. begrenzt. Für unlimitierte Aufnahmen nutzen Sie bitte <3>{{app}}</3>.",
|
||||
"limitNotificationDescriptionWeb": "Wegen hoher Nachfrage ist Ihre Aufnahme auf {{limit}} Min. begrenzt. Für unlimitierte Aufnahmen nutzen Sie bitte <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>.",
|
||||
"linkGenerated": "Link zur Aufzeichnung wurde generiert.",
|
||||
"localRecordingNoNotificationWarning": "Die Aufzeichnung wird anderen Anwesenden nicht mitgeteilt. Sie müssen diese selbst darauf hinweisen, dass die Konferenz aufgezeichnet wird.",
|
||||
"localRecordingNoVideo": "Videos werden nicht aufgenommen",
|
||||
@@ -1149,11 +1076,9 @@
|
||||
"offBy": "{{name}} stoppte die Aufnahme",
|
||||
"on": "Aufnahme",
|
||||
"onBy": "{{name}} startete die Aufnahme",
|
||||
"onByWithTranscription": "{{name}} startete die Aufnahme. Ein Transkript wird nach der Konferenz verfügbar sein.",
|
||||
"onWithTranscription": "Aufnahme gestartet. Ein Transkript wird nach der Konferenz verfügbar sein.",
|
||||
"onlyRecordSelf": "Nur eigenes Kamerabild und Ton aufzeichnen",
|
||||
"pending": "Aufzeichnung der Konferenz wird vorbereitet…",
|
||||
"policyError": "Sie haben die Aufzeichnung zu schnell gestartet. Bitte versuchen Sie es später noch einmal!",
|
||||
"policyError": "Sie haben die Aufzeichnung zu schnell gestartet. Bitte versuchen Sie es später noch einmal.",
|
||||
"recordAudioAndVideo": "Kamera und Ton aufzeichnen",
|
||||
"recordTranscription": "Transkription aufzeichnen",
|
||||
"saveLocalRecording": "Aufzeichnung lokal abspeichern",
|
||||
@@ -1176,8 +1101,8 @@
|
||||
"pullToRefresh": "Ziehen, um zu aktualisieren"
|
||||
},
|
||||
"security": {
|
||||
"about": "Sie können Ihre Konferenz mit einem $t(lockRoomPassword) sichern. Personen müssen das $t(lockRoomPassword) eingeben, bevor sie an der Konferenz teilnehmen dürfen.",
|
||||
"aboutReadOnly": "Mit Moderationsrechten kann die Konferenz mit einem $t(lockRoomPassword) gesichert werden. Personen müssen das $t(lockRoomPassword) eingeben, bevor sie an der Konferenz teilnehmen dürfen.",
|
||||
"about": "Sie können Ihre Konferenz mit einem Passwort sichern. Personen müssen dieses eingeben, bevor sie an der Sitzung teilnehmen dürfen.",
|
||||
"aboutReadOnly": "Mit Moderationsrechten kann die Konferenz mit einem Passwort gesichert werden. Personen müssen dieses eingeben, bevor sie an der Sitzung teilnehmen dürfen.",
|
||||
"insecureRoomNameWarningNative": "Der Raumname ist unsicher. Unerwünschte Personen könnten Ihrer Konferenz beitreten. {{recommendAction}} Lernen Sie mehr über die Absicherung Ihrer Konferenz ",
|
||||
"insecureRoomNameWarningWeb": "Der Raumname ist unsicher. Unerwünschte Personen könnten Ihrer Konferenz beitreten {{recommendAction}} Lernen Sie <a href=\"{{securityUrl}}\" rel=\"security\" target=\"_blank\">hier</a> mehr über die Absicherung Ihrer Konferenz.",
|
||||
"title": "Sicherheitsoptionen",
|
||||
@@ -1197,7 +1122,7 @@
|
||||
"signedIn": "Momentan wird auf Kalendertermine von {{email}} zugegriffen. Klicken Sie auf die folgende Schaltfläche „Trennen“, um den Zugriff auf die Kalendertermine zu stoppen.",
|
||||
"title": "Kalender"
|
||||
},
|
||||
"chatWithPermissions": "Chat nur für Moderation erlauben",
|
||||
"chatWithPermissions": "Chat mit Freigaben",
|
||||
"desktopShareFramerate": "Framerate für Bildschirmfreigabe",
|
||||
"desktopShareHighFpsWarning": "Eine höhere Framerate könnte sich auf Ihre Datenrate auswirken. Sie müssen die Bildschirmfreigabe neustarten, damit die Einstellung übernommen wird.",
|
||||
"desktopShareWarning": "Sie müssen die Bildschirmfreigabe neustarten, damit die Einstellung übernommen wird.",
|
||||
@@ -1280,9 +1205,9 @@
|
||||
"displayEmotions": "Emotionen anzeigen",
|
||||
"fearful": "Ängstlich",
|
||||
"happy": "Fröhlich",
|
||||
"hours": "{{count}} Std.",
|
||||
"hours": "{{count}} Std. ",
|
||||
"labelTooltip": "Anzahl der Personen: {{count}}",
|
||||
"minutes": "{{count}} Min.",
|
||||
"minutes": "{{count}} Min. ",
|
||||
"name": "Name",
|
||||
"neutral": "Neutral",
|
||||
"sad": "Traurig",
|
||||
@@ -1322,7 +1247,6 @@
|
||||
"chat": "Chatfenster öffnen / schließen",
|
||||
"clap": "Klatschen",
|
||||
"closeChat": "Chat schließen",
|
||||
"closeCustomPanel": "Schließen",
|
||||
"closeMoreActions": "„Weitere Einstellungen“ schließen",
|
||||
"closeParticipantsPane": "Anwesendenliste schließen",
|
||||
"closedCaptions": "Untertitel",
|
||||
@@ -1365,7 +1289,7 @@
|
||||
"muteEveryoneElse": "Alle anderen stummschalten",
|
||||
"muteEveryoneElsesVideoStream": "Alle anderen Kameras ausschalten",
|
||||
"muteEveryonesVideoStream": "Alle Kameras ausschalten",
|
||||
"muteGUMPending": "Mikrofon verbinden",
|
||||
"muteGUMPending": "Verbinde Ihr Mikrofon",
|
||||
"noiseSuppression": "Rauschunterdrückung",
|
||||
"openChat": "Chat öffnen",
|
||||
"participants": "Anwesenheitsliste öffnen. {{participantsCount}} anwesend",
|
||||
@@ -1400,24 +1324,10 @@
|
||||
"unmute": "Stummschaltung aufheben",
|
||||
"videoblur": "Unscharfer Hintergrund ein-/ausschalten",
|
||||
"videomute": "Kamera stoppen",
|
||||
"videomuteGUMPending": "Kamera verbinden",
|
||||
"videomuteGUMPending": "Verbinde Ihre Kamera",
|
||||
"videounmute": "Kamera einschalten"
|
||||
},
|
||||
"addPeople": "Personen zur Konferenz hinzufügen",
|
||||
"advancedAudioSettings": {
|
||||
"aec": {
|
||||
"label": "Echounterdrückung"
|
||||
},
|
||||
"agc": {
|
||||
"label": "Automatische Mikrofonlautstärke"
|
||||
},
|
||||
"ns": {
|
||||
"label": "Rauschunterdrückung"
|
||||
},
|
||||
"stereo": {
|
||||
"label": "Stereo"
|
||||
}
|
||||
},
|
||||
"audioOnlyOff": "Modus „Nur Audio“ deaktivieren",
|
||||
"audioOnlyOn": "Modus „Nur Audio“ aktivieren",
|
||||
"audioRoute": "Audiogerät auswählen",
|
||||
@@ -1428,11 +1338,9 @@
|
||||
"chat": "Chat öffnen / schließen",
|
||||
"clap": "Klatschen",
|
||||
"closeChat": "Chat schließen",
|
||||
"closeCustomPanel": "Schließen",
|
||||
"closeParticipantsPane": "Anwesenheitsliste schließen",
|
||||
"closeReactionsMenu": "Interaktionsmenü schließen",
|
||||
"closedCaptions": "Untertitel",
|
||||
"copilot": "Copilot",
|
||||
"disableNoiseSuppression": "Rauschunterdrückung deaktivieren",
|
||||
"disableReactionSounds": "Sie können die Interaktionstöne für diese Konferenz deaktivieren",
|
||||
"documentClose": "Geteiltes Dokument schließen",
|
||||
@@ -1447,7 +1355,6 @@
|
||||
"exitFullScreen": "Vollbildmodus verlassen",
|
||||
"exitTileView": "Kachelansicht ausschalten",
|
||||
"feedback": "Feedback hinterlassen",
|
||||
"fileSharing": "Dateien",
|
||||
"giphy": "GIPHY ein-/ausschalten",
|
||||
"hangup": "Konferenz verlassen",
|
||||
"help": "Hilfe",
|
||||
@@ -1470,7 +1377,7 @@
|
||||
"mute": "Audio stummschalten",
|
||||
"muteEveryone": "Alle stummschalten",
|
||||
"muteEveryonesVideo": "Alle Kameras ausschalten",
|
||||
"muteGUMPending": "Mikrofon verbinden",
|
||||
"muteGUMPending": "Verbinde Ihre Kamera",
|
||||
"noAudioSignalDesc": "Wenn Sie das Gerät nicht absichtlich über die Systemeinstellungen oder die Hardware stumm geschaltet haben, sollten Sie einen Wechsel des Geräts in Erwägung ziehen.",
|
||||
"noAudioSignalDescSuggestion": "Wenn Sie das Gerät nicht absichtlich über die Systemeinstellungen oder die Hardware stummgeschaltet haben, sollten Sie einen Wechsel auf das vorgeschlagene Gerät in Erwägung ziehen.",
|
||||
"noAudioSignalDialInDesc": "Sie können sich auch über die Einwahlnummer einwählen:",
|
||||
@@ -1483,7 +1390,6 @@
|
||||
"openReactionsMenu": "Interaktionsmenü öffnen",
|
||||
"participants": "Anwesende",
|
||||
"pip": "Bild-in-Bild-Modus einschalten",
|
||||
"polls": "Umfragen",
|
||||
"privateMessage": "Private Nachricht senden",
|
||||
"profile": "Profil bearbeiten",
|
||||
"raiseHand": "Hand heben",
|
||||
@@ -1493,7 +1399,6 @@
|
||||
"reactionHeart": "Herz senden",
|
||||
"reactionLaugh": "Lachen senden",
|
||||
"reactionLike": "Daumen hoch senden",
|
||||
"reactionLove": "Liebe senden",
|
||||
"reactionSilence": "Stille senden",
|
||||
"reactionSurprised": "Überrascht senden",
|
||||
"reactions": "Interaktionen",
|
||||
@@ -1507,7 +1412,7 @@
|
||||
"silence": "Stille",
|
||||
"speakerStats": "Sprechstatistik",
|
||||
"startScreenSharing": "Bildschirmfreigabe starten",
|
||||
"startSubtitles": "Untertitel • {{language}}",
|
||||
"startSubtitles": "Untertitel einschalten",
|
||||
"stopAudioSharing": "Audiofreigabe stoppen",
|
||||
"stopScreenSharing": "Bildschirmfreigabe stoppen",
|
||||
"stopSharedVideo": "Video stoppen",
|
||||
@@ -1519,19 +1424,15 @@
|
||||
"unmute": "Stummschaltung aufheben",
|
||||
"videoSettings": "Kamera-Einstellungen",
|
||||
"videomute": "Kamera stoppen",
|
||||
"videomuteGUMPending": "Kamera verbinden",
|
||||
"videomuteGUMPending": "Verbinde Ihre Kamera",
|
||||
"videounmute": "Kamera einschalten"
|
||||
},
|
||||
"transcribing": {
|
||||
"ccButtonTooltip": "Untertitel ein-/ausschalten",
|
||||
"expandedLabel": "Transkribieren ist derzeit eingeschaltet",
|
||||
"failed": "Transkribieren fehlgeschlagen",
|
||||
"labelTooltip": "Die Konferenz wird transkribiert.",
|
||||
"labelTooltip": "Die Konferenz wird transkribiert",
|
||||
"labelTooltipExtra": "Zusätzlich wird das Transkript später verfügbar sein.",
|
||||
"off": "Transkription gestoppt",
|
||||
"on": "Transkription gestartet",
|
||||
"onBy": "{{name}} startete die Transkription",
|
||||
"onWithRecording": "Ein Transkript wird nach der Konferenz verfügbar sein.",
|
||||
"openClosedCaptions": "Untertitel öffnen",
|
||||
"original": "Original",
|
||||
"sourceLanguageDesc": "Aktuell ist die Sprache der Konferenz auf <b>{{sourceLanguage}}</b> eingestellt. <br/> Sie könne dies hier ",
|
||||
@@ -1573,7 +1474,7 @@
|
||||
"ldTooltip": "Video wird in niedriger Auflösung angezeigt",
|
||||
"lowDefinition": "Niedrige Auflösung",
|
||||
"performanceSettings": "Qualitätseinstellungen",
|
||||
"recording": "Aufnahme läuft.",
|
||||
"recording": "Aufnahme läuft",
|
||||
"sd": "SD",
|
||||
"sdTooltip": "Video wird in Standardauflösung angezeigt",
|
||||
"standardDefinition": "Standardauflösung",
|
||||
@@ -1583,8 +1484,6 @@
|
||||
"connectionInfo": "Verbindungsinformationen",
|
||||
"demote": "Zu Gästen verschieben",
|
||||
"domute": "Stummschalten",
|
||||
"domuteDesktop": "Bildschirmfreigabe beenden",
|
||||
"domuteDesktopOfOthers": "Bildschirmfreigabe für alle beenden",
|
||||
"domuteOthers": "Alle anderen stummschalten",
|
||||
"domuteVideo": "Kamera ausschalten",
|
||||
"domuteVideoOfOthers": "Alle anderen Kameras auschalten",
|
||||
@@ -1614,7 +1513,6 @@
|
||||
"addBackground": "Hintergrund hinzufügen",
|
||||
"apply": "Anwenden",
|
||||
"backgroundEffectError": "Hintergrund konnte nicht aktiviert werden.",
|
||||
"backgroundLimitReached": "Maximale Zahl an Hintergründen erreicht",
|
||||
"blur": "Hintergrund unscharf",
|
||||
"deleteImage": "Bild löschen",
|
||||
"desktopShare": "Desktopfreigabe",
|
||||
@@ -1624,10 +1522,9 @@
|
||||
"image3": "Weißer leerer Raum",
|
||||
"image4": "Schwarze Stehlampe",
|
||||
"image5": "Berg",
|
||||
"image6": "Wald ",
|
||||
"image6": "Wald",
|
||||
"image7": "Sonnenaufgang",
|
||||
"none": "keiner",
|
||||
"oldestBackgroundRemoved": "Der älteste Hintergrund wurde gelöscht, um den Neuesten hinzuzufügen.",
|
||||
"pleaseWait": "Bitte warten…",
|
||||
"removeBackground": "Hintergrund entfernen",
|
||||
"slightBlur": "Hintergrund leicht unscharf",
|
||||
@@ -1642,7 +1539,7 @@
|
||||
"description": "Sie beobachten derzeit diese Konferenz.",
|
||||
"raiseHand": "Hand heben",
|
||||
"title": "Konferenz wird beigetreten",
|
||||
"wishToSpeak": "Wenn Sie sprechen möchten, heben Sie bitte unten Ihre Hand und warten Sie auf die Zustimmung der Moderation."
|
||||
"wishToSpeak": "Wenn Sie sprechen möchten, heben Sie bitte unten Ihre Hand und warten Sie auf die Zustimmung der Moderation"
|
||||
},
|
||||
"labelTooltip": "Anzahl Gäste: {{count}}",
|
||||
"notification": {
|
||||
@@ -1651,8 +1548,6 @@
|
||||
"noMainParticipantsTitle": "Diese Konferenz wurde noch nicht gestartet.",
|
||||
"noVisitorLobby": "Sie können nicht teilnehmen, solange die Lobby für diese Konferenz aktiviert ist.",
|
||||
"notAllowedPromotion": "Eine Person muss Ihre Anfrage erst erlauben.",
|
||||
"requestToJoin": "Hand gehoben",
|
||||
"requestToJoinDescription": "Ihre Anfrage wurde an die Moderation gesendet, bitte warten Sie!",
|
||||
"title": "Sie sind Gast in der Konferenz"
|
||||
},
|
||||
"waitingMessage": "Sie werden der Konferenz beitreten, sobald sie gestartet ist!"
|
||||
|
||||
@@ -543,6 +543,8 @@
|
||||
"googlePrivacyPolicy": "regule k woplěwanju datow pla Google",
|
||||
"inProgress": "Livestreaming jo se zachopił",
|
||||
"invalidStreamKey": "Kluc za livestream jo ewentuelnje wopacny.",
|
||||
"limitNotificationDescriptionNative": "Waš stream jo na {{limit}} minutow wobgranicowany. Za njelimitěrowany streaming, wužywajśo aplikaciju {{app}}.",
|
||||
"limitNotificationDescriptionWeb": "Dla intensiwnego wužywanja jo Waš stream na {{limit}} minutow wobgranicowany. Za njelimitěrowany streaming wužywajśo aplikaciju <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>.",
|
||||
"off": "Livestream jo zastajony",
|
||||
"offBy": "{{name}} jo livestream zastajił",
|
||||
"on": "livestream",
|
||||
@@ -903,6 +905,8 @@
|
||||
"highlightMomentSuccess": "highlight jo se markěrował",
|
||||
"highlightMomentSucessDescription": "Waš markěrowany moment pśidajo se k wopowěsći wót zmakanja.",
|
||||
"inProgress": "Nagrawanje abo livestream jo we źěle",
|
||||
"limitNotificationDescriptionNative": "Dla intensiwnego wužywanja jo Wašo nagrawanje na {{limit}} minutow wobgranicowane. Za njelimitěrowane nagrawanje wužyj aplikaciju <3>{{app}}</3>.",
|
||||
"limitNotificationDescriptionWeb": "Dla intensiwnego wužywanja jo Wašo nagrawanje na {{limit}} minutow wobgranicowane. Za njelimitěrowane nagrawanje wužyjśo aplikaciju <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>.",
|
||||
"linkGenerated": "Link k nagrawanju jo se generěrował.",
|
||||
"live": "LIVE",
|
||||
"localRecordingNoNotificationWarning": "Druge wobźělniki njedostanu powěsći wót nagrawanja. Wy musyśo jich sami informěrowaś, až konferenca se nagrawa.",
|
||||
|
||||
@@ -560,6 +560,8 @@
|
||||
"googlePrivacyPolicy": "Πολιτική Απορρήτου της Google",
|
||||
"inProgress": "Εγγραφή ή ζωντανή ροή σε εξέλιξη",
|
||||
"invalidStreamKey": "Το κλειδί ζωντανής ροής μπορεί να είναι εσφαλμένο.",
|
||||
"limitNotificationDescriptionNative": "Η ροή σας θα περιοριστεί σε {{limit}} λεπτά. Για ροή χωρίς όρια δοκιμάστε το {{app}}.",
|
||||
"limitNotificationDescriptionWeb": "Λόγω υψηλής ζήτησης η ροή θα περιοριστεί σε {{limit}} λεπτά. Για απεριόριστες ροές δοκιμάστε το <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>.",
|
||||
"off": "Η Ζωντανή Ροή σταμάτησε",
|
||||
"offBy": "{{name}} σταμάτησε τη ζωντανή ροή",
|
||||
"on": "Η Ζωντανή Ροή ξεκίνησε",
|
||||
@@ -917,6 +919,8 @@
|
||||
"highlightMomentSuccess": "Η στιγμή επισημάνθηκε",
|
||||
"highlightMomentSucessDescription": "Οι επισημασμένη στιγμή θα προστεθεί στη περίληψη της σύσκεψης.",
|
||||
"inProgress": "Σε εξέλιξη καταγραφή ή ζωντανή ροή",
|
||||
"limitNotificationDescriptionNative": "Λόγω υψηλής ζήτησης η εγγραφή σας θα περιοριστεί σε {{limit}} λεπτά. Για απεριόριστες εγγραφές, δοκιμάστε το <3>{{app}}</3>.",
|
||||
"limitNotificationDescriptionWeb": "Λόγω υψηλής ζήτησης η εγγραφή σας θα περιοριστεί σε {{limit}} λεπτά. Για απεριόριστες εγγραφές, δοκιμάστε το <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>.",
|
||||
"linkGenerated": "Δημιουργήσαμε ένα σύνδεσμο για τη καταγραφή σας.",
|
||||
"live": "ΖΩΝΤΑΝΑ",
|
||||
"localRecordingNoNotificationWarning": "Η καταγραφή δεν θα κοινοποιηθεί στους άλλους συμμετέχοντες. Θα πρέπει εσείς να τους ενημερώσετε ότι η σύσκεψη καταγράφεται.",
|
||||
|
||||
@@ -621,6 +621,8 @@
|
||||
"googlePrivacyPolicy": "Privatecpolitiko de Google",
|
||||
"inProgress": "Registrado aŭ vivelsendo farata",
|
||||
"invalidStreamKey": "La ŝlosilo de tuja elsendfluo povas esti malĝusta.",
|
||||
"limitNotificationDescriptionNative": "Via vivelsendo estos limigita al {{limit}} minutoj. Por senlima vivelsendo provu {{ app}}.",
|
||||
"limitNotificationDescriptionWeb": "Pro alta postulo, via vivelsendo estos limigita al {{limit}} minutoj. Por senlima vivelsendo provu <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>.",
|
||||
"off": "Tuja elsendfluo finiĝis",
|
||||
"offBy": "{{name}} ĉesigis la tujan elsendfluon",
|
||||
"on": "Tuja elsendfluo",
|
||||
@@ -994,6 +996,8 @@
|
||||
"highlightMomentSuccess": "Momento emfazita",
|
||||
"highlightMomentSucessDescription": "Via emfazita momento estos aldonita al la kunveno priskribo",
|
||||
"inProgress": "Registrado aŭ vivelsendo farata",
|
||||
"limitNotificationDescriptionNative": "Pro alta postulo via registrado estos limigita al {{ limo }} minutoj. Pro senlima registrado, provu <3>{{app}}</3>.",
|
||||
"limitNotificationDescriptionWeb": "Pro alta postulo via registrado estos limigita al {{ limo }} minutoj. Pro senlima registrado, provu <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>.",
|
||||
"linkGenerated": "Ni generis ligilon al via registrado.",
|
||||
"live": "LIVE",
|
||||
"localRecordingNoNotificationWarning": "La registrado ne estos anoncita al aliaj partoprenantoj. Vi devos sciigi al ili, ke la renkontiĝo estas registrita.",
|
||||
|
||||
@@ -578,6 +578,8 @@
|
||||
"googlePrivacyPolicy": "Política de Privacidad de Google",
|
||||
"inProgress": "Grabación o transmisión en vivo en curso",
|
||||
"invalidStreamKey": "Es posible que la clave de transmisión sea incorrecta, o no es de YouTube.",
|
||||
"limitNotificationDescriptionNative": "Su transmisión estará limitada a {{limit}} minutos. Puede obtener transmisiones ilimitadas en {{app}}.",
|
||||
"limitNotificationDescriptionWeb": "Debido a la alta demanda su transmisión estará limitada a {{limit}} minutos. Puede obtener transmisiones ilimitadas en <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>.",
|
||||
"off": "Se detuvo la transmisión",
|
||||
"offBy": "{{name}} detuvo la transmisión",
|
||||
"on": "Transmitiendo en vivo",
|
||||
@@ -883,7 +885,6 @@
|
||||
"or": "o",
|
||||
"premeeting": "Pre-reunión",
|
||||
"proceedAnyway": "Continuar de todos modos",
|
||||
"recordingWarning": "Otros participantes pueden estar grabando esta llamada",
|
||||
"screenSharingError": "Error al compartir pantalla:",
|
||||
"startWithPhone": "Iniciar con audio de llamada telefónica",
|
||||
"unsafeRoomConsent": "Comprendo los riesgos, quiero unirme a la reunión",
|
||||
@@ -946,6 +947,8 @@
|
||||
"highlightMomentSuccess": "Momento destacado",
|
||||
"highlightMomentSucessDescription": "Su momento destacado será agregado al resumen de la reunión.",
|
||||
"inProgress": "Grabación o transmisión en vivo en curso",
|
||||
"limitNotificationDescriptionNative": "Su grabación estará limitada a {{limit}} minutos. Puede obtener grabaciones ilimitadas en <3>{{app}}</3>.",
|
||||
"limitNotificationDescriptionWeb": "Debido a la alta demanda su grabación estará limitada a {{limit}} minutos. Puede obtener grabaciones ilimitadas en <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>.",
|
||||
"linkGenerated": "Hemos generado un enlace a su grabación.",
|
||||
"live": "EN VIVO",
|
||||
"localRecordingNoNotificationWarning": "La grabación no será anunciada al resto de participantes. Necesitarás hacerles saber que la reunión está siendo grabada.",
|
||||
|
||||
@@ -502,6 +502,8 @@
|
||||
"getStreamKeyManually": "No pudimos encontrar tu clave de transmisión. Por favor, obtenla de la página de YouTube y pégala.",
|
||||
"googlePrivacyPolicy": "Política de Privacidad de Google",
|
||||
"invalidStreamKey": "Es posible que la clave de transmisión sea incorrecta, o no es de YouTube.",
|
||||
"limitNotificationDescriptionNative": "Su transmisión estará limitada a {{limit}} minutos. Puede obtener transmisiones ilimitadas en {{app}}.",
|
||||
"limitNotificationDescriptionWeb": "Debido a la alta demanda su transmisión estará limitada a {{limit}} minutos. Puede obtener transmisiones ilimitadas en <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>.",
|
||||
"off": "Se detuvo la transmisión",
|
||||
"offBy": "{{name}} detuvo la transmisión",
|
||||
"on": "Transmitiendo en vivo",
|
||||
@@ -798,6 +800,8 @@
|
||||
"expandedPending": "La grabación se está iniciando…",
|
||||
"failedToStart": "No se pudo iniciar la grabación",
|
||||
"fileSharingdescription": "Compartir la grabación con los participantes de la reunión",
|
||||
"limitNotificationDescriptionNative": "Su grabación estará limitada a {{limit}} minutos. Puede obtener grabaciones ilimitadas en <3>{{app}}</3>.",
|
||||
"limitNotificationDescriptionWeb": "Debido a la alta demanda su grabación estará limitada a {{limit}} minutos. Puede obtener grabaciones ilimitadas en <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>.",
|
||||
"linkGenerated": "Hemos generado un enlace a su grabación.",
|
||||
"live": "EN VIVO",
|
||||
"loggedIn": "Sesión iniciada como {{userName}}",
|
||||