Skip to content

Commit 86a1d8f

Browse files
committed
Initial Commit
1 parent e1d8e4c commit 86a1d8f

File tree

75 files changed

+5601
-1
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+5601
-1
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,7 @@ doc/api/
2525

2626
.flutter-plugins
2727
.flutter-plugins-dependencies
28+
29+
.idea/
30+
31+
.DS_Store

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
## 0.0.1
2+
3+
* TODO: Describe initial release.

README.md

Lines changed: 110 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,110 @@
1-
# web_callkit
1+
# web_callkit
2+
3+
**This project is a Web Flutter plugin that facilitates handling of calls.**
4+
5+
Inspired by the iOS CallKit framework, this plugin provides the boilerplate to manage calls via a
6+
simple API and provides a browser call control mechanism through browser notifications.
7+
8+
### Notes
9+
10+
Due to many voip providers e.g. twilio-voice.js providing their own SDKs and audio handling (
11+
incoming ringing, etc), this plugin is intended to be used as a boilerplate for call management and
12+
not as a full-fledged voip solution.
13+
14+
A bird's eye overview/usage of the plugin:
15+
16+
- Notify callkit of an incoming call
17+
- Update state of call from VOIP/SIP provider
18+
- Add/update call capabilities (hold, mute, etc)
19+
20+
## Features
21+
22+
- Boilerplate for call management
23+
- Integration with browser notifications
24+
- Support background calls
25+
- Custom audio sounds for incoming calls, etc.
26+
27+
## Limitations
28+
29+
### Browser notifications
30+
31+
Use native browser integration, the following limitations apply to each platform. Usage of Flutter
32+
package [js_notifications](https://pub.dev/packages/js_notifications) is assist in browser
33+
notification integration to native systems. See [js_notifications > platform limitations](https://github.com/cybex-dev/js_notifications?tab=readme-ov-file#platform-limitations)
34+
for more information
35+
36+
## Installation
37+
38+
### Import the package
39+
40+
```dart
41+
import 'package:web_callkit/web_callkit.dart';
42+
```
43+
44+
### Display the system call screen
45+
46+
Inform the plugin that an incoming call is being received. This will hook into the browser
47+
notification system.
48+
49+
```dart
50+
WebCallKit.instance.displayIncomingCall(
51+
uuid: '1234',
52+
handle: 'John Doe',
53+
);
54+
```
55+
56+
### End the call
57+
58+
End the call by calling the `endCall` method. This will remove the call screen and stop the browser
59+
notification. Calls are disconnected for various reasons, via local user requests or remote errors
60+
or disconnects with VoIP calls due to internet disruptions.
61+
62+
The CallKit supports `DisconnectResponse` enum to specify the reason for the call disconnection.
63+
64+
e.g. `WebCallKit.instance.reportCallDisconnected('1234', response: DisconnectResponse.local);`
65+
66+
| Reason | Description |
67+
|----------|---------------------------------------------------------------------------------------|
68+
| local | Disconnect due to a local end call request. |
69+
| remote | Disconnect due to a remote end call request or remote party failed to answer in time. |
70+
| canceled | Disconnect due to a call was cancelled. |
71+
| missed | Disconnect due to a incoming call was not answered in time. |
72+
| rejected | Disconnect due to incoming call was rejected. |
73+
| busy | Disconnect due to remote party being busy. |
74+
| error | Disconnect due to an error. |
75+
| unknown | Disconnect response is unknown. |
76+
77+
### Features
78+
79+
#### Call Management
80+
81+
CallKit provides a simple API to manage calls. The plugin provides methods to report incoming calls,
82+
end calls, and update call information. Futher, inspiration is taken from Android's ConnectionService
83+
providing a set of capabilities to manage calls, such as:
84+
85+
| Reason | Description |
86+
|--------------|-------------------------------------------------------------|
87+
| hold | Ability to place a call on hold after the call has started. |
88+
| supportHold | Ability to place a call on hold from the start of the call. |
89+
| mute | Ability to mute a call. |
90+
91+
##### Incoming Calls
92+
93+
Incoming calls are displayed on the screen with the caller's name and number. The call screen can be
94+
customized with the caller's name, number, and profile picture.
95+
96+
```dart
97+
WebCallKit.instance.reportNewCall(
98+
uuid: '1234',
99+
handle: 'John Doe',
100+
);
101+
```
102+
103+
#### Notification Integration
104+
105+
#### Capabilities
106+
107+
## Limitations / Future work
108+
109+
- Support video & desktop streaming natively
110+

analysis_options.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
include: package:flutter_lints/flutter.yaml
2+
3+
# Additional information about this file can be found at
4+
# https://dart.dev/guides/language/analysis-options

example/.gitignore

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Miscellaneous
2+
*.class
3+
*.log
4+
*.pyc
5+
*.swp
6+
.DS_Store
7+
.atom/
8+
.buildlog/
9+
.history
10+
.svn/
11+
migrate_working_dir/
12+
13+
# IntelliJ related
14+
*.iml
15+
*.ipr
16+
*.iws
17+
.idea/
18+
19+
# The .vscode folder contains launch configuration and tasks you configure in
20+
# VS Code which you may wish to be included in version control, so this line
21+
# is commented out by default.
22+
#.vscode/
23+
24+
# Flutter/Dart/Pub related
25+
**/doc/api/
26+
**/ios/Flutter/.last_build_id
27+
.dart_tool/
28+
.flutter-plugins
29+
.flutter-plugins-dependencies
30+
.pub-cache/
31+
.pub/
32+
/build/
33+
34+
# Symbolication related
35+
app.*.symbols
36+
37+
# Obfuscation related
38+
app.*.map.json
39+
40+
# Android Studio will place build artifacts here
41+
/android/app/debug
42+
/android/app/profile
43+
/android/app/release

example/README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# web_callkit_example
2+
3+
Demonstrates how to use the web_callkit plugin.
4+
5+
## Getting Started
6+
7+
This project is a starting point for a Flutter application.
8+
9+
A few resources to get you started if this is your first Flutter project:
10+
11+
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
12+
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
13+
14+
For help getting started with Flutter development, view the
15+
[online documentation](https://docs.flutter.dev/), which offers tutorials,
16+
samples, guidance on mobile development, and a full API reference.

example/analysis_options.yaml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# This file configures the analyzer, which statically analyzes Dart code to
2+
# check for errors, warnings, and lints.
3+
#
4+
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
5+
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
6+
# invoked from the command line by running `flutter analyze`.
7+
8+
# The following line activates a set of recommended lints for Flutter apps,
9+
# packages, and plugins designed to encourage good coding practices.
10+
include: package:flutter_lints/flutter.yaml
11+
12+
linter:
13+
# The lint rules applied to this project can be customized in the
14+
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
15+
# included above or to enable additional rules. A list of all available lints
16+
# and their documentation is published at https://dart.dev/lints.
17+
#
18+
# Instead of disabling a lint rule for the entire project in the
19+
# section below, it can also be suppressed for a single line of code
20+
# or a specific dart file by using the `// ignore: name_of_lint` and
21+
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
22+
# producing the lint.
23+
rules:
24+
# avoid_print: false # Uncomment to disable the `avoid_print` rule
25+
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
26+
27+
# Additional information about this file can be found at
28+
# https://dart.dev/guides/language/analysis-options
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// // This is a basic Flutter integration test.
2+
// //
3+
// // Since integration tests run in a full Flutter application, they can interact
4+
// // with the host side of a plugin implementation, unlike Dart unit tests.
5+
// //
6+
// // For more information about Flutter integration tests, please see
7+
// // https://docs.flutter.dev/cookbook/testing/integration/introduction
8+
//
9+
//
10+
// import 'package:flutter_test/flutter_test.dart';
11+
// import 'package:integration_test/integration_test.dart';
12+
//
13+
// import 'package:web_callkit/web_callkit.dart';
14+
//
15+
// void main() {
16+
// IntegrationTestWidgetsFlutterBinding.ensureInitialized();
17+
//
18+
// testWidgets('getPlatformVersion test', (WidgetTester tester) async {
19+
// final WebCallkit plugin = WebCallkit();
20+
// final String? version = await plugin.getPlatformVersion();
21+
// // The version string depends on the host platform running the test, so
22+
// // just assert that some non-empty string is returned.
23+
// expect(version?.isNotEmpty, true);
24+
// });
25+
// }

example/lib/main.dart

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import 'package:flutter/material.dart';
2+
3+
import 'package:web_callkit/web_callkit.dart';
4+
import 'package:web_callkit_example/utils.dart';
5+
6+
import 'screens/home_screen.dart';
7+
import 'theme.dart';
8+
9+
void main() {
10+
runApp(const MyApp());
11+
}
12+
13+
class MyApp extends StatefulWidget {
14+
const MyApp({super.key});
15+
16+
@override
17+
State<MyApp> createState() => _MyAppState();
18+
}
19+
20+
class _MyAppState extends State<MyApp> {
21+
@override
22+
void initState() {
23+
super.initState();
24+
final webCallkitPlugin = WebCallkit.instance;
25+
webCallkitPlugin.setConfiguration(const CKConfiguration());
26+
webCallkitPlugin.setOnCallActionHandler((uuid, action, source) {
27+
// ignore: avoid_print
28+
print("onCallActionHandler: $uuid, $action, $source");
29+
if(action == CKCallAction.answer) {
30+
webCallkitPlugin.updateCallStatus(uuid, callStatus: CallState.active);
31+
} else if(action == CKCallAction.decline) {
32+
webCallkitPlugin.reportCallDisconnected(uuid, response: DisconnectResponse.declined);
33+
}
34+
});
35+
webCallkitPlugin.setOnCallEventListener((event, source) {
36+
// ignore: avoid_print
37+
print("onCallEventListener: $event, $source");
38+
});
39+
webCallkitPlugin.setOnCallTypeChangeListener((event, callType, source) {
40+
// ignore: avoid_print
41+
webCallkitPlugin.updateCallType(event.uuid, callType: callType);
42+
});
43+
webCallkitPlugin.setOnDisconnectListener((uuid, response, source) {
44+
// ignore: avoid_print
45+
webCallkitPlugin.reportCallDisconnected(uuid, response: response);
46+
// webCallkitPlugin.updateCallStatus(uuid, callStatus: CallState.disconnected);
47+
});
48+
webCallkitPlugin.setOnDismissedListener((uuid, source) {
49+
final call = webCallkitPlugin.getCall(uuid);
50+
if(call != null) {
51+
webCallkitPlugin.renotify(call.uuid, silent: true);
52+
}
53+
});
54+
// webCallkitPlugin.setOnActionAnswered((uuid, call, source) {
55+
// printDebug("onActionAnswered: $uuid, $call, $source");
56+
// webCallkitPlugin.updateCallStatus(uuid, callStatus: CallState.active);
57+
// });
58+
// webCallkitPlugin.setOnActionHangup((uuid, call, source, response) {
59+
// printDebug("onActionHangup: $uuid, $call, $source, $response");
60+
// webCallkitPlugin.reportCallDisconnected(uuid, response: response);
61+
// });
62+
// webCallkitPlugin.setOnActionDecline((uuid, call, source, response) {
63+
// printDebug("onActionDecline: $uuid, $call, $source, $response");
64+
// webCallkitPlugin.reportCallDisconnected(uuid, response: response);
65+
// });
66+
// webCallkitPlugin.setOnActionCallback((uuid, call, source) {
67+
// printDebug("onActionCallback: $uuid, $call, $source");
68+
// webCallkitPlugin.reportNewCall(
69+
// uuid: uuid,
70+
// handle: call.localizedName,
71+
// data: call.data,
72+
// attributes: call.attributes,
73+
// capabilities: call.capabilities,
74+
// );
75+
// });
76+
// webCallkitPlugin.setOnActionDismiss((uuid, call, source) {
77+
// printDebug("onActionDismiss: $uuid, $call, $source");
78+
// });
79+
}
80+
81+
@override
82+
Widget build(BuildContext context) {
83+
return MaterialApp(
84+
theme: getThemeData(context),
85+
home: const HomeScreen(),
86+
);;
87+
}
88+
}

0 commit comments

Comments
 (0)