├── CHANGELOG.md ├── example ├── assets │ └── icon.png ├── web │ ├── favicon.png │ ├── icons │ │ ├── Icon-192.png │ │ ├── Icon-512.png │ │ ├── Icon-maskable-192.png │ │ └── Icon-maskable-512.png │ ├── splash │ │ └── img │ │ │ ├── dark-1x.png │ │ │ ├── dark-2x.png │ │ │ ├── dark-3x.png │ │ │ ├── dark-4x.png │ │ │ ├── light-1x.png │ │ │ ├── light-2x.png │ │ │ ├── light-3x.png │ │ │ └── light-4x.png │ ├── manifest.json │ └── index.html ├── analysis_options.yaml ├── pubspec.yaml ├── README.md ├── .gitignore ├── lib │ ├── main.dart │ ├── common_widgets.dart │ ├── user_details_view.dart │ ├── telegram_details_view.dart │ └── home_view.dart └── pubspec.lock ├── lib ├── src │ ├── helpers │ │ ├── telegram_web_utils.dart │ │ ├── color_utils.dart │ │ ├── telegram_web_events.dart │ │ └── telegram_theme.dart │ ├── models │ │ ├── telegram_haptic_feedback.dart │ │ ├── telegram_back_button.dart │ │ ├── web_app_chat.dart │ │ ├── theme_params.dart │ │ ├── web_app_user.dart │ │ ├── models_export.dart │ │ ├── web_app_init_data.dart │ │ ├── telegram_popup.dart │ │ └── telegram_main_button.dart │ └── flutter_telegram_web.dart └── flutter_telegram_web_app.dart ├── analysis_options.yaml ├── .gitignore ├── pubspec.yaml ├── .metadata ├── LICENSE ├── .vscode └── launch.json └── README.md /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.0.1 2 | 3 | * Initial Release 4 | -------------------------------------------------------------------------------- /example/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitsangwan01/flutter_telegram_web_app/HEAD/example/assets/icon.png -------------------------------------------------------------------------------- /example/web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitsangwan01/flutter_telegram_web_app/HEAD/example/web/favicon.png -------------------------------------------------------------------------------- /example/web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitsangwan01/flutter_telegram_web_app/HEAD/example/web/icons/Icon-192.png -------------------------------------------------------------------------------- /example/web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitsangwan01/flutter_telegram_web_app/HEAD/example/web/icons/Icon-512.png -------------------------------------------------------------------------------- /example/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | 3 | linter: 4 | rules: 5 | avoid_print: false 6 | 7 | -------------------------------------------------------------------------------- /example/web/splash/img/dark-1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitsangwan01/flutter_telegram_web_app/HEAD/example/web/splash/img/dark-1x.png -------------------------------------------------------------------------------- /example/web/splash/img/dark-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitsangwan01/flutter_telegram_web_app/HEAD/example/web/splash/img/dark-2x.png -------------------------------------------------------------------------------- /example/web/splash/img/dark-3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitsangwan01/flutter_telegram_web_app/HEAD/example/web/splash/img/dark-3x.png -------------------------------------------------------------------------------- /example/web/splash/img/dark-4x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitsangwan01/flutter_telegram_web_app/HEAD/example/web/splash/img/dark-4x.png -------------------------------------------------------------------------------- /example/web/splash/img/light-1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitsangwan01/flutter_telegram_web_app/HEAD/example/web/splash/img/light-1x.png -------------------------------------------------------------------------------- /example/web/splash/img/light-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitsangwan01/flutter_telegram_web_app/HEAD/example/web/splash/img/light-2x.png -------------------------------------------------------------------------------- /example/web/splash/img/light-3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitsangwan01/flutter_telegram_web_app/HEAD/example/web/splash/img/light-3x.png -------------------------------------------------------------------------------- /example/web/splash/img/light-4x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitsangwan01/flutter_telegram_web_app/HEAD/example/web/splash/img/light-4x.png -------------------------------------------------------------------------------- /lib/src/helpers/telegram_web_utils.dart: -------------------------------------------------------------------------------- 1 | /// Telegram Web Utils 2 | /// 3 | /// Add some utils for Telegram Web... 4 | class TelegramWebUtils {} 5 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | 3 | linter: 4 | rules: 5 | non_constant_identifier_names: false 6 | 7 | -------------------------------------------------------------------------------- /example/web/icons/Icon-maskable-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitsangwan01/flutter_telegram_web_app/HEAD/example/web/icons/Icon-maskable-192.png -------------------------------------------------------------------------------- /example/web/icons/Icon-maskable-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitsangwan01/flutter_telegram_web_app/HEAD/example/web/icons/Icon-maskable-512.png -------------------------------------------------------------------------------- /lib/src/models/telegram_haptic_feedback.dart: -------------------------------------------------------------------------------- 1 | import 'package:js/js.dart'; 2 | 3 | ///https://core.telegram.org/bots/webapps#hapticfeedback 4 | @JS() 5 | class TelegramHapticFeedback { 6 | external void impactOccurred(style); 7 | external void notificationOccurred(type); 8 | external void selectionChanged(); 9 | } 10 | -------------------------------------------------------------------------------- /lib/src/models/telegram_back_button.dart: -------------------------------------------------------------------------------- 1 | import 'package:js/js.dart'; 2 | 3 | ///https://core.telegram.org/bots/webapps#backbutton 4 | @JS() 5 | class TelegramBackButton { 6 | external bool isVisible; 7 | external void onClick(jsVoidCallback); 8 | external void offClick(jsVoidCallback); 9 | external Future show(); 10 | external Future hide(); 11 | } 12 | -------------------------------------------------------------------------------- /lib/src/models/web_app_chat.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: non_constant_identifier_names 2 | 3 | import 'package:js/js.dart'; 4 | 5 | ///https://core.telegram.org/bots/webapps#webappchat 6 | @JS() 7 | class WebAppChat { 8 | external int get id; 9 | external String get photo_url; 10 | external String get type; 11 | external String get title; 12 | external String get username; 13 | } 14 | -------------------------------------------------------------------------------- /lib/src/models/theme_params.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: non_constant_identifier_names 2 | 3 | import 'package:js/js.dart'; 4 | 5 | ///https://core.telegram.org/bots/webapps#themeparams 6 | @JS() 7 | class ThemeParams { 8 | external String get bg_color; 9 | external String get text_color; 10 | external String get hint_color; 11 | external String get link_color; 12 | external String get button_color; 13 | external String get button_text_color; 14 | external String get secondary_bg_color; 15 | } 16 | -------------------------------------------------------------------------------- /lib/src/models/web_app_user.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: non_constant_identifier_names 2 | 3 | import 'package:js/js.dart'; 4 | 5 | ///https://core.telegram.org/bots/webapps#webappuser 6 | @JS() 7 | class WebAppUser { 8 | external int get id; 9 | external bool get is_bot; 10 | external bool get is_premium; 11 | external String get first_name; 12 | external String get last_name; 13 | external String get username; 14 | external String get photo_url; 15 | external String get language_code; 16 | } 17 | -------------------------------------------------------------------------------- /lib/flutter_telegram_web_app.dart: -------------------------------------------------------------------------------- 1 | library flutter_telegram_web_app; 2 | 3 | export 'package:flutter_telegram_web_app/src/helpers/telegram_web_utils.dart'; 4 | export 'package:flutter_telegram_web_app/src/helpers/telegram_web_events.dart'; 5 | export 'package:flutter_telegram_web_app/src/models/models_export.dart'; 6 | export 'package:flutter_telegram_web_app/src/helpers/color_utils.dart'; 7 | export 'package:flutter_telegram_web_app/src/helpers/telegram_theme.dart'; 8 | export 'package:flutter_telegram_web_app/src/flutter_telegram_web.dart'; 9 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_telegram_web_example 2 | publish_to: none 3 | description: Demonstrates how to use the flutter_telegram_web plugin. 4 | environment: 5 | sdk: '>=3.0.1 <4.0.0' 6 | 7 | dependencies: 8 | flutter: 9 | sdk: flutter 10 | flutter_telegram_web_app: 11 | path: ../ 12 | 13 | dev_dependencies: 14 | flutter_lints: ^2.0.0 15 | flutter_native_splash: ^2.3.0 16 | 17 | flutter_native_splash: 18 | color: "#ffffff" 19 | image: assets/icon.png 20 | web: true 21 | 22 | 23 | flutter: 24 | uses-material-design: true 25 | 26 | -------------------------------------------------------------------------------- /lib/src/models/models_export.dart: -------------------------------------------------------------------------------- 1 | export 'package:flutter_telegram_web_app/src/models/telegram_back_button.dart'; 2 | export 'package:flutter_telegram_web_app/src/models/telegram_haptic_feedback.dart'; 3 | export 'package:flutter_telegram_web_app/src/models/telegram_main_button.dart'; 4 | export 'package:flutter_telegram_web_app/src/models/telegram_popup.dart'; 5 | export 'package:flutter_telegram_web_app/src/models/theme_params.dart'; 6 | export 'package:flutter_telegram_web_app/src/models/web_app_chat.dart'; 7 | export 'package:flutter_telegram_web_app/src/models/web_app_init_data.dart'; 8 | export 'package:flutter_telegram_web_app/src/models/web_app_user.dart'; 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 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 | # Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. 26 | /pubspec.lock 27 | **/doc/api/ 28 | .dart_tool/ 29 | .packages 30 | build/ 31 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # flutter_telegram_web_example 2 | 3 | Demonstrates how to use the flutter_telegram_web 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. 17 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_telegram_web_app 2 | description: Build a Telegram Web App using Flutter Web 3 | version: 0.0.1 4 | homepage: https://github.com/rohitsangwan01/flutter_telegram_web_app 5 | repository: https://github.com/rohitsangwan01/flutter_telegram_web_app 6 | issue_tracker: https://github.com/rohitsangwan01/flutter_telegram_web_app/issues 7 | 8 | environment: 9 | sdk: '>=3.0.1 <4.0.0' 10 | flutter: ">=3.3.0" 11 | 12 | dependencies: 13 | flutter: 14 | sdk: flutter 15 | js: ^0.6.7 16 | 17 | dev_dependencies: 18 | flutter_test: 19 | sdk: flutter 20 | flutter_lints: ^2.0.0 21 | 22 | flutter: 23 | plugin: 24 | platforms: 25 | web: 26 | -------------------------------------------------------------------------------- /lib/src/models/web_app_init_data.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: non_constant_identifier_names 2 | 3 | import 'package:flutter_telegram_web_app/src/models/web_app_chat.dart'; 4 | import 'package:flutter_telegram_web_app/src/models/web_app_user.dart'; 5 | import 'package:js/js.dart'; 6 | 7 | /// https://core.telegram.org/bots/webapps#webappinitdata 8 | @JS() 9 | class WebAppInitData { 10 | external String? get query_id; 11 | external WebAppUser? get user; 12 | external WebAppUser? get receiver; 13 | external WebAppChat? get chat; 14 | external String? get chat_type; 15 | external String? get chat_instance; 16 | external String? get start_param; 17 | external int? get can_send_after; 18 | external int? get auth_date; 19 | external String? get hash; 20 | } 21 | -------------------------------------------------------------------------------- /lib/src/helpers/color_utils.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | /// Extension to convert a [Color] to a hex string 4 | extension ColorsExtensions on Color { 5 | String toHex() { 6 | return '#${red.toRadixString(16).padLeft(2, '0')}${green.toRadixString(16).padLeft(2, '0')}${blue.toRadixString(16).padLeft(2, '0')}' 7 | .toUpperCase(); 8 | } 9 | } 10 | 11 | /// Extension to convert a [String] to a Color 12 | extension StringExtensions on String { 13 | Color toColor() { 14 | try { 15 | var hexColor = toUpperCase().replaceAll('#', ''); 16 | if (hexColor.length == 6) hexColor = 'FF$hexColor'; 17 | var data = int.parse(hexColor, radix: 16); 18 | return Color(data); 19 | } catch (e) { 20 | /// Return transparent color if the color is not valid 21 | return const Color(0x00000000); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 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 | .packages 31 | .pub-cache/ 32 | .pub/ 33 | /build/ 34 | 35 | # Symbolication related 36 | app.*.symbols 37 | 38 | # Obfuscation related 39 | app.*.map.json 40 | 41 | # Android Studio will place build artifacts here 42 | /android/app/debug 43 | /android/app/profile 44 | /android/app/release 45 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled. 5 | 6 | version: 7 | revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2 8 | channel: stable 9 | 10 | project_type: plugin 11 | 12 | # Tracks metadata for the flutter migrate command 13 | migration: 14 | platforms: 15 | - platform: root 16 | create_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2 17 | base_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2 18 | - platform: web 19 | create_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2 20 | base_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2 21 | 22 | # User provided section 23 | 24 | # List of Local paths (relative to this file) that should be 25 | # ignored by the migrate tool. 26 | # 27 | # Files that are not part of the templates will be ignored by default. 28 | unmanaged_files: 29 | - 'lib/main.dart' 30 | - 'ios/Runner.xcodeproj/project.pbxproj' 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2023 Rohit Sangwan 2 | Permission is hereby granted, free of charge, to any person obtaining a copy 3 | of this software and associated documentation files (the "Software"), to deal 4 | in the Software without restriction, including without limitation the rights 5 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | copies of the Software, and to permit persons to whom the Software is 7 | furnished to do so, subject to the following conditions: 8 | The above copyright notice and this permission notice shall be included in all 9 | copies or substantial portions of the Software. 10 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 11 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 13 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 14 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 15 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 16 | SOFTWARE. -------------------------------------------------------------------------------- /example/web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flutter_telegram_web_example", 3 | "short_name": "flutter_telegram_web_example", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "Demonstrates how to use the flutter_telegram_web plugin.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | }, 22 | { 23 | "src": "icons/Icon-maskable-192.png", 24 | "sizes": "192x192", 25 | "type": "image/png", 26 | "purpose": "maskable" 27 | }, 28 | { 29 | "src": "icons/Icon-maskable-512.png", 30 | "sizes": "512x512", 31 | "type": "image/png", 32 | "purpose": "maskable" 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /lib/src/models/telegram_popup.dart: -------------------------------------------------------------------------------- 1 | import '../flutter_telegram_web.dart'; 2 | 3 | enum PopupButtonType { cancel, ok, close, destructive } 4 | 5 | class TelegramPopup { 6 | String title; 7 | String message; 8 | List? buttons; 9 | Function(String buttonId)? onTap; 10 | 11 | TelegramPopup({ 12 | required this.title, 13 | required this.message, 14 | this.buttons, 15 | this.onTap, 16 | }); 17 | 18 | /// use [TelegramPopup.show()] to show the popup 19 | void show() { 20 | var buttonsList = buttons 21 | ?.map((PopupButton? e) => 22 | (id: e?.id, type: e?.type?.name ?? "default", text: e?.text)) 23 | .toList(); 24 | showPopup( 25 | ( 26 | title: title, 27 | message: message, 28 | buttons: buttonsList ?? [(id: "cancel", type: "cancel", text: "Cancel")] 29 | ), 30 | JsCallback((String buttonId) { 31 | onTap?.call(buttonId); 32 | }), 33 | ); 34 | } 35 | } 36 | 37 | class PopupButton { 38 | String id; 39 | PopupButtonType? type; 40 | String? text; 41 | PopupButton({ 42 | required this.id, 43 | this.type, 44 | this.text, 45 | }); 46 | } 47 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_telegram_web_app/flutter_telegram_web_app.dart' as tg; 3 | import 'package:flutter_telegram_web_app/flutter_telegram_web_app.dart'; 4 | import 'package:flutter_telegram_web_example/home_view.dart'; 5 | 6 | void main() { 7 | runApp(const MyApp()); 8 | } 9 | 10 | // user below method to update theme mode 11 | void updateThemeMode() { 12 | _notifier.value = tg.isDarkMode ? ThemeMode.dark : ThemeMode.light; 13 | } 14 | 15 | final ValueNotifier _notifier = 16 | ValueNotifier(tg.isDarkMode ? ThemeMode.dark : ThemeMode.light); 17 | 18 | class MyApp extends StatelessWidget { 19 | const MyApp({super.key}); 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | return ValueListenableBuilder( 24 | valueListenable: _notifier, 25 | builder: (_, mode, __) { 26 | return MaterialApp( 27 | title: "Telegram Web JS", 28 | debugShowCheckedModeBanner: false, 29 | theme: TelegramTheme.light, 30 | darkTheme: TelegramTheme.dark, 31 | themeMode: mode, 32 | home: const HomeView(), 33 | ); 34 | }, 35 | ); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /lib/src/models/telegram_main_button.dart: -------------------------------------------------------------------------------- 1 | import 'package:js/js.dart'; 2 | 3 | ///https://core.telegram.org/bots/webapps#mainbutton 4 | @JS() 5 | class TelegramMainButton { 6 | /// use these properties as getters or setters 7 | external String text; 8 | external String color; 9 | external String textColor; 10 | external bool isVisible; 11 | external bool isActive; 12 | external bool get isProgressVisible; 13 | 14 | /// methods to use from JS API 15 | external void setText(String text); 16 | external void onClick(jsVoidCallback); 17 | external void offClick(jsVoidCallback); 18 | external Future show(); 19 | external Future hide(); 20 | external void enable(); 21 | external void disable(); 22 | external void showProgress(bool leaveActive); 23 | external void hideProgress(); 24 | external void setParams(MainButtonParams mainButtonParams); 25 | } 26 | 27 | class MainButtonParams { 28 | String text; 29 | String color; 30 | String textColor; 31 | bool isVisible; 32 | bool isActive; 33 | MainButtonParams({ 34 | required this.text, 35 | required this.color, 36 | required this.textColor, 37 | this.isVisible = true, 38 | this.isActive = false, 39 | }); 40 | } 41 | -------------------------------------------------------------------------------- /example/lib/common_widgets.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_telegram_web_app/flutter_telegram_web_app.dart'; 3 | 4 | class KButton extends StatelessWidget { 5 | final String text; 6 | final Function() onTap; 7 | const KButton({super.key, required this.text, required this.onTap}); 8 | 9 | @override 10 | Widget build(BuildContext context) { 11 | return Padding( 12 | padding: const EdgeInsets.all(8.0), 13 | child: ElevatedButton( 14 | onPressed: onTap, 15 | child: Text(text), 16 | ), 17 | ); 18 | } 19 | } 20 | 21 | class KDetailsList extends StatelessWidget { 22 | final String title; 23 | final dynamic value; 24 | final bool isColor; 25 | const KDetailsList( 26 | this.title, 27 | this.value, { 28 | this.isColor = false, 29 | super.key, 30 | }); 31 | 32 | @override 33 | Widget build(BuildContext context) { 34 | return value == null 35 | ? const SizedBox() 36 | : Column( 37 | children: [ 38 | ListTile( 39 | leading: Text("$title : "), 40 | title: Text(value?.toString() ?? "Not Available"), 41 | trailing: !isColor 42 | ? null 43 | : Container( 44 | width: 20, 45 | height: 20, 46 | color: value.toString().toColor(), 47 | )), 48 | const Divider(), 49 | ], 50 | ); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "flutter_telegram_web", 9 | "request": "launch", 10 | "type": "dart" 11 | }, 12 | { 13 | "name": "flutter_telegram_web (profile mode)", 14 | "request": "launch", 15 | "type": "dart", 16 | "flutterMode": "profile" 17 | }, 18 | { 19 | "name": "flutter_telegram_web (release mode)", 20 | "request": "launch", 21 | "type": "dart", 22 | "flutterMode": "release" 23 | }, 24 | { 25 | "name": "example", 26 | "cwd": "example", 27 | "request": "launch", 28 | "type": "dart" 29 | }, 30 | { 31 | "name": "example_web", 32 | "cwd": "example", 33 | "request": "launch", 34 | "type": "dart", 35 | "args": ["-d", "web-server","--web-port", "8000", "--web-hostname", "0.0.0.0"], 36 | }, 37 | { 38 | "name": "example (profile mode)", 39 | "cwd": "example", 40 | "request": "launch", 41 | "type": "dart", 42 | "flutterMode": "profile" 43 | }, 44 | { 45 | "name": "example (release mode)", 46 | "cwd": "example", 47 | "request": "launch", 48 | "type": "dart", 49 | "flutterMode": "release" 50 | } 51 | ] 52 | } -------------------------------------------------------------------------------- /lib/src/helpers/telegram_web_events.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_telegram_web_app/flutter_telegram_web_app.dart' as tg; 2 | import 'package:flutter_telegram_web_app/flutter_telegram_web_app.dart'; 3 | 4 | typedef ViewPortListener = Function( 5 | bool isStable, double height, double stableHeight); 6 | typedef ThemeChangeListener = Function(bool isDarkMode, ThemeParams params); 7 | 8 | class TelegramWebEvent { 9 | /// Event listeners for Telegram WebViewPort Changes 10 | static void setViewPortChangeListener(ViewPortListener listener) { 11 | onEvent(TelegramWebEventType.viewportChanged, JsCallback((data) { 12 | bool isStateStable = data?.isStateStable ?? false; 13 | double? height = viewportHeight; 14 | double? stableHeight = viewportStableHeight; 15 | listener(isStateStable, height ?? 0, stableHeight ?? 0); 16 | })); 17 | } 18 | 19 | /// Event listeners for Telegram theme changes, this will return [isDarkMode], but also 20 | /// we can get [themeParams] from [tg.themeParams] to get the theme colors 21 | static void setThemeChangeListener(ThemeChangeListener listener) => onEvent( 22 | TelegramWebEventType.themeChanged, 23 | JsVoidCallback(() => listener.call(tg.isDarkMode, tg.themeParams))); 24 | } 25 | 26 | /// Event types for Telegram Web 27 | /// we can use [onEvent] to listen to these events 28 | /// or few examples are added in [TelegramWebEvent] to listen to these events 29 | class TelegramWebEventType { 30 | static const String themeChanged = "themeChanged"; 31 | static const String viewportChanged = "viewportChanged"; 32 | static const String mainButtonClicked = "mainButtonClicked"; 33 | static const String backButtonClicked = "backButtonClicked"; 34 | static const String settingsButtonClicked = "settingsButtonClicked"; 35 | static const String invoiceClosed = "invoiceClosed"; 36 | static const String popupClosed = "popupClosed"; 37 | static const String qrTextReceived = "qrTextReceived"; 38 | static const String clipboardTextReceived = "clipboardTextReceived"; 39 | } 40 | -------------------------------------------------------------------------------- /example/lib/user_details_view.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_telegram_web_app/flutter_telegram_web_app.dart' as tg; 3 | import 'package:flutter_telegram_web_app/flutter_telegram_web_app.dart'; 4 | import 'package:flutter_telegram_web_example/common_widgets.dart'; 5 | 6 | class UserDetailsView extends StatefulWidget { 7 | const UserDetailsView({super.key}); 8 | 9 | @override 10 | State createState() => _UserDetailsState(); 11 | } 12 | 13 | class _UserDetailsState extends State { 14 | final WebAppInitData webAppInitData = tg.initDataUnsafe; 15 | 16 | @override 17 | void initState() { 18 | tg.BackButton.show(); 19 | super.initState(); 20 | } 21 | 22 | @override 23 | void dispose() { 24 | tg.BackButton.hide(); 25 | super.dispose(); 26 | } 27 | 28 | @override 29 | Widget build(BuildContext context) { 30 | return Scaffold( 31 | body: Center( 32 | child: Column( 33 | children: [ 34 | KDetailsList("Query", webAppInitData.query_id), 35 | KDetailsList("chat_type", webAppInitData.chat_type), 36 | KDetailsList("chat_instance", webAppInitData.chat_instance), 37 | KDetailsList("start_param", webAppInitData.start_param), 38 | KDetailsList("auth_date", webAppInitData.auth_date), 39 | KDetailsList("hash", webAppInitData.hash), 40 | KDetailsList("name", 41 | '${webAppInitData.user?.first_name} ${webAppInitData.user?.last_name}'), 42 | KDetailsList("username", webAppInitData.user?.username), 43 | KDetailsList("photoUrl", webAppInitData.user?.photo_url), 44 | KDetailsList( 45 | "receiver_username", webAppInitData.receiver?.username), 46 | KDetailsList("chat_username", webAppInitData.chat?.username), 47 | KDetailsList("chat_title", webAppInitData.chat?.title), 48 | KDetailsList("chat_url", webAppInitData.chat?.photo_url), 49 | ], 50 | ), 51 | ), 52 | ); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Flutter Telegram Web App 2 | [![flutter_telegram_web_app version](https://img.shields.io/pub/v/flutter_telegram_web_app?label=flutter_telegram_web_app)](https://pub.dev/packages/flutter_telegram_web_app) 3 | 4 | Build telegram web apps in flutter using flutter_telegram_web library 5 | 6 | ## Getting Started 7 | Import Library in your pubspec.yaml 8 | 9 | And add this line in `web/index.html` 10 | 11 | ```html 12 | 13 | .... 14 | 15 | 16 | ``` 17 | 18 | Checkout details of available telegram_web apis [here](https://core.telegram.org/bots/webapps#webappinitdata) 19 | 20 | 21 | ## TODO 22 | Add complete documentation, for now checkout `\example` folder 23 | 24 | ## Setup for development 25 | 26 | - To test in telegram while development/debugging, enable debugging in telegram webApp, checkout [this](https://core.telegram.org/bots/webapps#debug-mode-for-web-apps) post 27 | - Then navigate to `\example` folder : `cd example` 28 | - Run web-server : `flutter run -d web-server --web-port 8000 --web-hostname 0.0.0.0` 29 | - Now expose your `localhost:8000` , to internet ,using [ngrok](https://ngrok.com/) or any other alternative 30 | - Use that url to load webapp in telegram, after debugging, host flutterWeb app somewhere and replace the url 31 | 32 | 33 | ## Show the user a button to open a Web App. There are two ways: 34 | 35 | 1. Show the user a special menu button (near the message input field): 36 | 1. Go to [Bot Father](https://t.me/BotFather) 37 | 2. Select your bot 38 | 3. `Bot Settings` — `Menu Button` — `Specify..`/`Edit menu button URL` 39 | 4. Send url of flutter web app 40 | 41 | 2. The second way is to send a button with the data that contains field `web_app` with a URL to a Web App from bot : 42 | ```json 43 | { 44 | "text": "Test web_app", 45 | "web_app": { 46 | "url": "FLUTTER_WEB_APP_URL" 47 | } 48 | } 49 | ``` 50 | 51 | 52 | ## Additional information 53 | 54 | This is Just The Initial Version feel free to Contribute or Report any Bug! 55 | -------------------------------------------------------------------------------- /example/lib/telegram_details_view.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_telegram_web_app/flutter_telegram_web_app.dart' as tg; 3 | import 'package:flutter_telegram_web_example/common_widgets.dart'; 4 | 5 | class TelegramDetailsView extends StatefulWidget { 6 | const TelegramDetailsView({super.key}); 7 | 8 | @override 9 | State createState() => _TelegramDetailsViewState(); 10 | } 11 | 12 | class _TelegramDetailsViewState extends State { 13 | @override 14 | void initState() { 15 | tg.BackButton.show(); 16 | super.initState(); 17 | } 18 | 19 | @override 20 | void dispose() { 21 | tg.BackButton.hide(); 22 | super.dispose(); 23 | } 24 | 25 | @override 26 | Widget build(BuildContext context) { 27 | return Scaffold( 28 | body: SingleChildScrollView( 29 | child: Column( 30 | children: [ 31 | KDetailsList("Version", tg.version), 32 | KDetailsList("Platform", tg.platform), 33 | KDetailsList("IsDarkMode", tg.isDarkMode), 34 | KDetailsList("ColorScheme", tg.colorScheme), 35 | KDetailsList("IsClosingConfirmationEnabled", 36 | tg.isClosingConfirmationEnabled), 37 | KDetailsList("IsExpanded", tg.isExpanded), 38 | KDetailsList("ViewportHeight", tg.viewportHeight), 39 | KDetailsList( 40 | "HeaderColor", 41 | tg.headerColor, 42 | isColor: true, 43 | ), 44 | KDetailsList( 45 | "ThemeBackgroundColor", 46 | tg.themeParams.bg_color, 47 | isColor: true, 48 | ), 49 | KDetailsList( 50 | "SecondaryBackgroundColor", 51 | tg.themeParams.secondary_bg_color, 52 | isColor: true, 53 | ), 54 | KDetailsList( 55 | "TextColor", 56 | tg.themeParams.text_color, 57 | isColor: true, 58 | ), 59 | KDetailsList( 60 | "ButtonColor", 61 | tg.themeParams.button_color, 62 | isColor: true, 63 | ), 64 | ], 65 | ), 66 | ), 67 | ); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /lib/src/helpers/telegram_theme.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_telegram_web_app/src/flutter_telegram_web.dart'; 3 | import 'package:flutter_telegram_web_app/src/helpers/color_utils.dart'; 4 | 5 | /// Implement theme colors from telegram `themeParams` to flutter `ThemeData` 6 | class TelegramTheme { 7 | 8 | static ThemeData? get currentTheme => isDarkMode ? dark : light; 9 | 10 | static ThemeData get light => ThemeData.light().copyWith( 11 | primaryColor: rawTheme?.primaryColor, 12 | scaffoldBackgroundColor: rawTheme?.scaffoldBackgroundColor, 13 | elevatedButtonTheme: rawTheme?.elevatedButtonTheme, 14 | textButtonTheme: rawTheme?.textButtonTheme, 15 | appBarTheme: rawTheme?.appBarTheme, 16 | ); 17 | 18 | static ThemeData get dark { 19 | return ThemeData.dark().copyWith( 20 | primaryColor: rawTheme?.primaryColor, 21 | scaffoldBackgroundColor: rawTheme?.scaffoldBackgroundColor, 22 | elevatedButtonTheme: rawTheme?.elevatedButtonTheme, 23 | textButtonTheme: rawTheme?.textButtonTheme, 24 | appBarTheme: rawTheme?.appBarTheme, 25 | ); 26 | } 27 | 28 | /// Raw themData from telegram `themeParams` 29 | /// This will return null if the theme is not supported (not telegram web) 30 | static ThemeData? get rawTheme { 31 | if (!isSupported) return null; 32 | return ThemeData( 33 | primaryColor: themeParams.bg_color.toColor(), 34 | scaffoldBackgroundColor: themeParams.secondary_bg_color.toColor(), 35 | elevatedButtonTheme: ElevatedButtonThemeData( 36 | style: ElevatedButton.styleFrom( 37 | backgroundColor: themeParams.button_color.toColor(), 38 | textStyle: TextStyle( 39 | color: themeParams.button_text_color.toColor(), 40 | ), 41 | ), 42 | ), 43 | textButtonTheme: TextButtonThemeData( 44 | style: TextButton.styleFrom( 45 | backgroundColor: themeParams.button_color.toColor(), 46 | textStyle: TextStyle( 47 | color: themeParams.button_text_color.toColor(), 48 | ), 49 | ), 50 | ), 51 | appBarTheme: AppBarTheme( 52 | titleTextStyle: TextStyle( 53 | color: themeParams.text_color.toColor(), 54 | ), 55 | backgroundColor: themeParams.bg_color.toColor(), 56 | ), 57 | ); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /lib/src/flutter_telegram_web.dart: -------------------------------------------------------------------------------- 1 | @JS("Telegram.WebApp") 2 | library telegram_webapp; 3 | 4 | import 'package:js/js.dart'; 5 | import 'models/models_export.dart'; 6 | 7 | /// All the properties and methods of the Telegram Web JS API 8 | /// https://core.telegram.org/bots/webapps 9 | /// 10 | /// [isDarkMode] is reliable only if used inside Telegram web 11 | bool get isDarkMode => colorScheme == "dark"; 12 | 13 | /// [isSupported] will return true only if opened inside Telegram web 14 | bool get isSupported => platform.toLowerCase() != "unknown"; 15 | 16 | /// Getters for properties 17 | /// 18 | external String get initData; 19 | external String get version; 20 | external String get platform; 21 | external String get colorScheme; 22 | external String get headerColor; 23 | external String get backgroundColor; 24 | external bool get isClosingConfirmationEnabled; 25 | external bool get isExpanded; 26 | external double? get viewportHeight; 27 | external double? get viewportStableHeight; 28 | 29 | /// Getters for classes and objects 30 | /// 31 | external ThemeParams get themeParams; 32 | external TelegramBackButton get BackButton; 33 | external TelegramMainButton get MainButton; 34 | external WebAppInitData get initDataUnsafe; 35 | external TelegramHapticFeedback get HapticFeedback; 36 | 37 | /// Functions 38 | /// 39 | external Future ready(); 40 | external Future expand(); 41 | external Future close(); 42 | external Future enableClosingConfirmation(); 43 | external Future disableClosingConfirmation(); 44 | external Future sendData(dynamic data); 45 | external Future isVersionAtLeast(version); 46 | external Future setHeaderColor(String color); 47 | external Future setBackgroundColor(String color); 48 | external Future switchInlineQuery(query, [choose_chat_types]); 49 | external Future openLink(url, [options]); 50 | external Future openTelegramLink(String url); 51 | external Future openInvoice(String url, [JsCallback]); 52 | external Future readTextFromClipboard(JsCallback); 53 | 54 | ///Dialogs 55 | /// 56 | /// use [TelegramPopup.show()] to show the popup, instead of this method directly 57 | external Future showPopup(Record param, [JsCallback]); 58 | external Future showAlert(String message, [JsCallback]); 59 | external Future showConfirm(String message, [JsCallback]); 60 | external Future showScanQrPopup(Record params, [JsCallback]); 61 | external Future closeScanQrPopup(); 62 | 63 | ///Events 64 | /// 65 | /// Available events: https://core.telegram.org/bots/webapps#events-available-for-web-apps 66 | /// use [TelegramWebEventType] to get the event names, and use [JsVoidCallback] for callbacks 67 | /// or if any callback requires a return value, use [JsCallback] with the return type 68 | external void onEvent(String eventType, JsCallback); 69 | external void offEvent(String eventType, JsCallback); 70 | 71 | ///Callbacks 72 | /// 73 | /// Always use these method for callbacks 74 | JsCallback(Function(T) callback) => allowInterop(callback); 75 | JsVoidCallback(Function() callback) => allowInterop(callback); 76 | -------------------------------------------------------------------------------- /example/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | flutter_telegram_web_example 31 | 32 | 33 | 37 | 38 | 39 | 40 | 98 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /example/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | archive: 5 | dependency: transitive 6 | description: 7 | name: archive 8 | sha256: "0c8368c9b3f0abbc193b9d6133649a614204b528982bebc7026372d61677ce3a" 9 | url: "https://pub.dev" 10 | source: hosted 11 | version: "3.3.7" 12 | args: 13 | dependency: transitive 14 | description: 15 | name: args 16 | sha256: c372bb384f273f0c2a8aaaa226dad84dc27c8519a691b888725dec59518ad53a 17 | url: "https://pub.dev" 18 | source: hosted 19 | version: "2.4.1" 20 | characters: 21 | dependency: transitive 22 | description: 23 | name: characters 24 | sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" 25 | url: "https://pub.dev" 26 | source: hosted 27 | version: "1.3.0" 28 | collection: 29 | dependency: transitive 30 | description: 31 | name: collection 32 | sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" 33 | url: "https://pub.dev" 34 | source: hosted 35 | version: "1.17.1" 36 | convert: 37 | dependency: transitive 38 | description: 39 | name: convert 40 | sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" 41 | url: "https://pub.dev" 42 | source: hosted 43 | version: "3.1.1" 44 | crypto: 45 | dependency: transitive 46 | description: 47 | name: crypto 48 | sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab 49 | url: "https://pub.dev" 50 | source: hosted 51 | version: "3.0.3" 52 | csslib: 53 | dependency: transitive 54 | description: 55 | name: csslib 56 | sha256: b36c7f7e24c0bdf1bf9a3da461c837d1de64b9f8beb190c9011d8c72a3dfd745 57 | url: "https://pub.dev" 58 | source: hosted 59 | version: "0.17.2" 60 | flutter: 61 | dependency: "direct main" 62 | description: flutter 63 | source: sdk 64 | version: "0.0.0" 65 | flutter_lints: 66 | dependency: "direct dev" 67 | description: 68 | name: flutter_lints 69 | sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c 70 | url: "https://pub.dev" 71 | source: hosted 72 | version: "2.0.1" 73 | flutter_native_splash: 74 | dependency: "direct dev" 75 | description: 76 | name: flutter_native_splash 77 | sha256: "02df24aec455c26428dadc637f20d4c548bda23ee2179479a8e8c39f1ecb75b3" 78 | url: "https://pub.dev" 79 | source: hosted 80 | version: "2.3.0" 81 | flutter_telegram_web_app: 82 | dependency: "direct main" 83 | description: 84 | path: ".." 85 | relative: true 86 | source: path 87 | version: "0.0.1" 88 | flutter_web_plugins: 89 | dependency: transitive 90 | description: flutter 91 | source: sdk 92 | version: "0.0.0" 93 | html: 94 | dependency: transitive 95 | description: 96 | name: html 97 | sha256: "58e3491f7bf0b6a4ea5110c0c688877460d1a6366731155c4a4580e7ded773e8" 98 | url: "https://pub.dev" 99 | source: hosted 100 | version: "0.15.3" 101 | image: 102 | dependency: transitive 103 | description: 104 | name: image 105 | sha256: a72242c9a0ffb65d03de1b7113bc4e189686fc07c7147b8b41811d0dd0e0d9bf 106 | url: "https://pub.dev" 107 | source: hosted 108 | version: "4.0.17" 109 | js: 110 | dependency: transitive 111 | description: 112 | name: js 113 | sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 114 | url: "https://pub.dev" 115 | source: hosted 116 | version: "0.6.7" 117 | lints: 118 | dependency: transitive 119 | description: 120 | name: lints 121 | sha256: "6b0206b0bf4f04961fc5438198ccb3a885685cd67d4d4a32cc20ad7f8adbe015" 122 | url: "https://pub.dev" 123 | source: hosted 124 | version: "2.1.0" 125 | material_color_utilities: 126 | dependency: transitive 127 | description: 128 | name: material_color_utilities 129 | sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 130 | url: "https://pub.dev" 131 | source: hosted 132 | version: "0.2.0" 133 | meta: 134 | dependency: transitive 135 | description: 136 | name: meta 137 | sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" 138 | url: "https://pub.dev" 139 | source: hosted 140 | version: "1.9.1" 141 | path: 142 | dependency: transitive 143 | description: 144 | name: path 145 | sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" 146 | url: "https://pub.dev" 147 | source: hosted 148 | version: "1.8.3" 149 | petitparser: 150 | dependency: transitive 151 | description: 152 | name: petitparser 153 | sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 154 | url: "https://pub.dev" 155 | source: hosted 156 | version: "5.4.0" 157 | pointycastle: 158 | dependency: transitive 159 | description: 160 | name: pointycastle 161 | sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c" 162 | url: "https://pub.dev" 163 | source: hosted 164 | version: "3.7.3" 165 | sky_engine: 166 | dependency: transitive 167 | description: flutter 168 | source: sdk 169 | version: "0.0.99" 170 | source_span: 171 | dependency: transitive 172 | description: 173 | name: source_span 174 | sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" 175 | url: "https://pub.dev" 176 | source: hosted 177 | version: "1.10.0" 178 | string_scanner: 179 | dependency: transitive 180 | description: 181 | name: string_scanner 182 | sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" 183 | url: "https://pub.dev" 184 | source: hosted 185 | version: "1.2.0" 186 | term_glyph: 187 | dependency: transitive 188 | description: 189 | name: term_glyph 190 | sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 191 | url: "https://pub.dev" 192 | source: hosted 193 | version: "1.2.1" 194 | typed_data: 195 | dependency: transitive 196 | description: 197 | name: typed_data 198 | sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c 199 | url: "https://pub.dev" 200 | source: hosted 201 | version: "1.3.2" 202 | universal_io: 203 | dependency: transitive 204 | description: 205 | name: universal_io 206 | sha256: "06866290206d196064fd61df4c7aea1ffe9a4e7c4ccaa8fcded42dd41948005d" 207 | url: "https://pub.dev" 208 | source: hosted 209 | version: "2.2.0" 210 | vector_math: 211 | dependency: transitive 212 | description: 213 | name: vector_math 214 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" 215 | url: "https://pub.dev" 216 | source: hosted 217 | version: "2.1.4" 218 | xml: 219 | dependency: transitive 220 | description: 221 | name: xml 222 | sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84" 223 | url: "https://pub.dev" 224 | source: hosted 225 | version: "6.3.0" 226 | yaml: 227 | dependency: transitive 228 | description: 229 | name: yaml 230 | sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" 231 | url: "https://pub.dev" 232 | source: hosted 233 | version: "3.1.2" 234 | sdks: 235 | dart: ">=3.0.1 <4.0.0" 236 | flutter: ">=3.3.0" 237 | -------------------------------------------------------------------------------- /example/lib/home_view.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'package:flutter_telegram_web_example/common_widgets.dart'; 4 | import 'package:flutter_telegram_web_app/flutter_telegram_web_app.dart' as tg; 5 | import 'package:flutter_telegram_web_app/flutter_telegram_web_app.dart'; 6 | import 'package:flutter_telegram_web_example/main.dart'; 7 | import 'package:flutter_telegram_web_example/telegram_details_view.dart'; 8 | import 'package:flutter_telegram_web_example/user_details_view.dart'; 9 | 10 | class HomeView extends StatefulWidget { 11 | const HomeView({super.key}); 12 | 13 | @override 14 | State createState() => _HomeViewState(); 15 | } 16 | 17 | class _HomeViewState extends State { 18 | final TelegramMainButton _mainButton = tg.MainButton; 19 | final TelegramBackButton _backButton = tg.BackButton; 20 | bool isStateStable = true; 21 | 22 | @override 23 | void initState() { 24 | onEvent(TelegramWebEventType.settingsButtonClicked, JsVoidCallback(() { 25 | print("settingsButtonClicked"); 26 | setState(() {}); 27 | })); 28 | 29 | _mainButton.onClick(JsVoidCallback(() { 30 | // we can also use onEvent(TelegramWebEventType.mainButtonClicked) 31 | tg.showConfirm("Main Button Clicked"); 32 | setState(() {}); 33 | })); 34 | 35 | _backButton.onClick(JsVoidCallback(() { 36 | // we can also use onEvent(TelegramWebEventType.backButtonClicked) 37 | Navigator.of(context).pop(); 38 | })); 39 | 40 | TelegramWebEvent.setThemeChangeListener( 41 | (bool isDarkMode, ThemeParams themeParams) { 42 | setState(() {}); 43 | updateThemeMode(); 44 | }); 45 | 46 | TelegramWebEvent.setViewPortChangeListener( 47 | (bool isStable, height, stableHeight) { 48 | setState(() { 49 | isStateStable = isStable; 50 | }); 51 | }); 52 | 53 | super.initState(); 54 | } 55 | 56 | void onShowPopup() { 57 | TelegramPopup( 58 | title: "Title", 59 | message: "Message", 60 | buttons: [ 61 | PopupButton( 62 | id: "delete", 63 | type: PopupButtonType.destructive, 64 | text: "Delete button test", 65 | ), 66 | PopupButton( 67 | id: "faq", 68 | text: "Open FAQ", 69 | ), 70 | PopupButton( 71 | id: "cancel", 72 | type: PopupButtonType.cancel, 73 | ), 74 | ], 75 | onTap: (String buttonId) { 76 | if (buttonId == "cancel") return null; 77 | if (buttonId == "faq") return tg.openLink("https://telegram.org/faq"); 78 | showAlert("Button $buttonId clicked"); 79 | }, 80 | ).show(); 81 | } 82 | 83 | @override 84 | Widget build(BuildContext context) { 85 | return Scaffold( 86 | body: SingleChildScrollView( 87 | child: Column( 88 | crossAxisAlignment: CrossAxisAlignment.start, 89 | children: [ 90 | // Top Buttons 91 | Column( 92 | crossAxisAlignment: CrossAxisAlignment.start, 93 | children: [ 94 | Row( 95 | children: [ 96 | Padding( 97 | padding: const EdgeInsets.all(8.0), 98 | child: Text("Opened in telegram : ${tg.isSupported},"), 99 | ), 100 | Padding( 101 | padding: const EdgeInsets.all(8.0), 102 | child: Text("Platform : ${tg.platform}"), 103 | ), 104 | ], 105 | ), 106 | Row( 107 | children: [ 108 | Padding( 109 | padding: const EdgeInsets.all(8.0), 110 | child: Text("IsDarkMode : $isDarkMode"), 111 | ), 112 | Padding( 113 | padding: const EdgeInsets.all(8.0), 114 | child: Text("IsExpanded : ${tg.isExpanded}"), 115 | ), 116 | ], 117 | ), 118 | Padding( 119 | padding: const EdgeInsets.all(8.0), 120 | child: Text( 121 | "Viewport- Height: ${tg.viewportHeight?.toInt()}, StableHeight: ${tg.viewportStableHeight?.toInt()}"), 122 | ), 123 | Padding( 124 | padding: const EdgeInsets.all(8.0), 125 | child: Text("IsStateStable: $isStateStable"), 126 | ), 127 | ], 128 | ), 129 | const Divider(), 130 | Row( 131 | children: [ 132 | KButton( 133 | text: "Toggle Back Button", 134 | onTap: () async { 135 | try { 136 | var data = _backButton.isVisible 137 | ? await _backButton.hide() 138 | : await _backButton.show(); 139 | print("ToggleBackButton: $data"); 140 | } catch (e) { 141 | print("ToggleBackButtonError: $e"); 142 | } 143 | }), 144 | KButton( 145 | text: "Toggle Main Button", 146 | onTap: () async { 147 | try { 148 | _mainButton.isVisible 149 | ? await _mainButton.hide() 150 | : await _mainButton.show(); 151 | } catch (e) { 152 | print("ToggleMainButtonError: $e"); 153 | } 154 | }), 155 | ], 156 | ), 157 | const Divider(), 158 | Row( 159 | children: [ 160 | const KButton(text: "Expand", onTap: tg.expand), 161 | const KButton(text: "Close", onTap: tg.close), 162 | KButton(text: "Popup", onTap: onShowPopup), 163 | KButton( 164 | text: "Alert", 165 | onTap: () async { 166 | try { 167 | await tg.showAlert("Alert Message"); 168 | } catch (e) { 169 | print("Error: $e"); 170 | } 171 | }), 172 | ], 173 | ), 174 | const Divider(), 175 | SingleChildScrollView( 176 | scrollDirection: Axis.horizontal, 177 | child: Row( 178 | children: [ 179 | KButton( 180 | text: "ShowScanQr", 181 | onTap: () => tg.showScanQrPopup(( 182 | text: "Scan QR", 183 | JsCallback((data) { 184 | showAlert(data?.toString() ?? "data is null"); 185 | }) 186 | )), 187 | ), 188 | KButton( 189 | text: "CloseScanQr", 190 | onTap: () => tg.closeScanQrPopup(), 191 | ), 192 | KButton( 193 | text: "ClipboardText", 194 | onTap: () => tg.readTextFromClipboard( 195 | JsCallback((dynamic data) { 196 | showAlert(data?.toString() ?? "data is null"); 197 | })), 198 | ), 199 | ], 200 | ), 201 | ), 202 | const Divider(), 203 | SingleChildScrollView( 204 | scrollDirection: Axis.horizontal, 205 | child: Row( 206 | children: [ 207 | KButton( 208 | text: "EnableClosingConfirmation", 209 | onTap: () => tg.enableClosingConfirmation(), 210 | ), 211 | KButton( 212 | text: "DisableClosingConfirmation", 213 | onTap: () => tg.disableClosingConfirmation(), 214 | ), 215 | ], 216 | ), 217 | ), 218 | 219 | const Divider(), 220 | Row( 221 | children: [ 222 | KButton( 223 | text: "Telegram Details >", 224 | onTap: () { 225 | Navigator.of(context).push(MaterialPageRoute( 226 | builder: (context) => const TelegramDetailsView())); 227 | }), 228 | KButton( 229 | text: "Chat Details >", 230 | onTap: () { 231 | Navigator.of(context).push(MaterialPageRoute( 232 | builder: (context) => const UserDetailsView())); 233 | }), 234 | ], 235 | ), 236 | const Divider(), 237 | SingleChildScrollView( 238 | scrollDirection: Axis.horizontal, 239 | child: Row( 240 | children: [ 241 | KButton( 242 | text: "SendData", 243 | onTap: () => tg.sendData("Hello from Flutter"), 244 | ), 245 | ], 246 | ), 247 | ), 248 | ], 249 | ), 250 | ), 251 | ); 252 | } 253 | } 254 | --------------------------------------------------------------------------------