Rhmn -- 27/05/1403 -- fix notification firebase,

This commit is contained in:
OkaykOrhmn 2024-08-17 10:46:03 +03:30
parent 1365673b93
commit 8b88463efe
52 changed files with 936 additions and 1476 deletions

View File

@ -22,6 +22,9 @@ if (flutterVersionName == null) {
}
apply plugin: 'com.android.application'
// START: FlutterFire Configuration
apply plugin: 'com.google.gms.google-services'
// END: FlutterFire Configuration
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
@ -32,7 +35,8 @@ if (keystorePropertiesFile.exists()) {
}
android {
compileSdkVersion 34
namespace "com.didvan.didvanapp"
compileSdk 34
ndkVersion "25.1.8937393"
compileOptions {
@ -53,7 +57,7 @@ android {
applicationId "com.didvan.didvanapp"
minSdkVersion 24
//noinspection ExpiredTargetSdkVersion
targetSdkVersion 30
targetSdkVersion 31
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
@ -79,6 +83,22 @@ android {
buildFeatures {
viewBinding true
}
splits {
//configure apks based on ABI
abi {
enable true
reset()
include "x86", "x86_64", "armeabi-v7a", "arm64-v8a"
universalApk true
}
// density {
// enable true
// reset()
// include "mdpi", "hdpi", "xhdpi", "xxhdpi", "xxxhdpi"
// }
}
}
flutter {
@ -86,10 +106,11 @@ flutter {
}
dependencies {
implementation platform('com.google.firebase:firebase-bom:29.1.0')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
// implementation platform('com.google.firebase:firebase-bom:29.1.0')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.10"
implementation 'com.google.code.gson:gson:2.10.1'
// implementation 'com.github.bumptech.glide:glide:4.16.0'
implementation 'com.squareup.picasso:picasso:2.8'
implementation 'com.android.support:cardview-v7:28.0.0'
implementation "androidx.room:room-runtime:2.2.5"
implementation "androidx.sqlite:sqlite-framework:2.1.0"
implementation "androidx.sqlite:sqlite:2.1.0"
}

View File

@ -29,6 +29,13 @@
{
"client_id": "935017686266-lebnol7rb05oi9h0mripb41c892d2gij.apps.googleusercontent.com",
"client_type": 3
},
{
"client_id": "935017686266-54hu01v9cc5pqpgofo1gk2n3hegj4r2m.apps.googleusercontent.com",
"client_type": 2,
"ios_info": {
"bundle_id": "com.didvan.didvanapp"
}
}
]
}

View File

@ -8,14 +8,14 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY"/>
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:icon="@mipmap/ic_launcher"
android:label="Didvan"
android:requestLegacyExternalStorage="true"
android:enableOnBackInvokedCallback="true"
android:usesCleartextTraffic="true">
<receiver
android:name=".FavWidget"
@ -36,8 +36,7 @@
</intent-filter>
</receiver>
<service android:name="es.antonborri.home_widget.HomeWidgetBackgroundService"
android:permission="android.permission.BIND_JOB_SERVICE" android:exported="true"/>
android:permission="android.permission.BIND_JOB_SERVICE" android:exported="true" />
<activity
@ -49,8 +48,14 @@
android:showWhenLocked="true"
android:theme="@style/LaunchTheme"
android:turnScreenOn="true"
android:exported="true"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="FLUTTER_NOTIFICATION_CLICK" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<!--
Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
@ -82,15 +87,9 @@
<activity
android:name="com.yalantis.ucrop.UCropActivity"
android:screenOrientation="portrait"
android:exported="true"
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
<service
android:name=".MyFirebaseMessagingService"
android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.messaging.RECEIVE" />
</intent-filter>
</service>
</application>
</manifest>

View File

@ -1,5 +1,10 @@
package com.didvan.didvanapp
import android.app.NotificationChannel
import android.app.NotificationManager
import android.os.Build
import android.os.Bundle
import android.os.PersistableBundle
import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
@ -9,5 +14,7 @@ class MainActivity: FlutterActivity() {
@Override
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine)
}
}

View File

@ -3,11 +3,12 @@ buildscript {
repositories {
google()
mavenCentral()
maven { url "https://jitpack.io" }
}
dependencies {
classpath 'com.android.tools.build:gradle:7.4.1'
classpath 'com.google.gms:google-services:4.3.10'
classpath 'com.google.gms:google-services:4.3.14'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
@ -16,6 +17,8 @@ allprojects {
repositories {
google()
mavenCentral()
maven { url "https://jitpack.io" }
}
}

View File

@ -1,14 +0,0 @@
kind: ExternalService
name: app-dev
spec:
allow_http: false
disable_default_domains: true
image: registry.gitlab.com/didvan/didvan-app/api:latest
image_pull_policy: Always
image_pull_secret: $SEC_NAME
path: /
replicas: 1
resources:
memory: 100Mi
domains:
- name: dev.didvan.app

View File

@ -1,14 +0,0 @@
kind: ExternalService
name: app-test
spec:
allow_http: false
disable_default_domains: true
image: registry.gitlab.com/didvan/didvan-app/api:latest
image_pull_policy: Always
image_pull_secret: $SEC_NAME
path: /
replicas: 1
resources:
memory: 150Mi
domains:
- name: test.didvan.app

1
firebase.json Normal file
View File

@ -0,0 +1 @@
{"flutter":{"platforms":{"android":{"default":{"projectId":"didvan-9b7da","appId":"1:935017686266:android:f9cbc9aba8e3d65ed2d543","fileOutput":"android/app/google-services.json"}},"dart":{"lib/firebase_options.dart":{"projectId":"didvan-9b7da","configurations":{"android":"1:935017686266:android:f9cbc9aba8e3d65ed2d543","ios":"1:935017686266:ios:de47638bd662463fd2d543","web":"1:935017686266:web:a93f7a19bed23c51d2d543"}}}}}}

76
lib/firebase_options.dart Normal file
View File

@ -0,0 +1,76 @@
// File generated by FlutterFire CLI.
// ignore_for_file: type=lint
import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
import 'package:flutter/foundation.dart'
show defaultTargetPlatform, kIsWeb, TargetPlatform;
/// Default [FirebaseOptions] for use with your Firebase apps.
///
/// Example:
/// ```dart
/// import 'firebase_options.dart';
/// // ...
/// await Firebase.initializeApp(
/// options: DefaultFirebaseOptions.currentPlatform,
/// );
/// ```
class DefaultFirebaseOptions {
static FirebaseOptions get currentPlatform {
if (kIsWeb) {
return web;
}
switch (defaultTargetPlatform) {
case TargetPlatform.android:
return android;
case TargetPlatform.iOS:
return ios;
case TargetPlatform.macOS:
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for macos - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
case TargetPlatform.windows:
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for windows - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
case TargetPlatform.linux:
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for linux - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
default:
throw UnsupportedError(
'DefaultFirebaseOptions are not supported for this platform.',
);
}
}
static const FirebaseOptions web = FirebaseOptions(
apiKey: 'AIzaSyA0HZjKpRuPOi1SC3f_EZTvlS3mcj9UVo0',
appId: '1:935017686266:web:a93f7a19bed23c51d2d543',
messagingSenderId: '935017686266',
projectId: 'didvan-9b7da',
authDomain: 'didvan-9b7da.firebaseapp.com',
storageBucket: 'didvan-9b7da.appspot.com',
measurementId: 'G-80B4H9E8Y0',
);
static const FirebaseOptions android = FirebaseOptions(
apiKey: 'AIzaSyBp-UHjWeM0H0UHtX5yguFKG-riMzvvCzw',
appId: '1:935017686266:android:f9cbc9aba8e3d65ed2d543',
messagingSenderId: '935017686266',
projectId: 'didvan-9b7da',
storageBucket: 'didvan-9b7da.appspot.com',
);
static const FirebaseOptions ios = FirebaseOptions(
apiKey: 'AIzaSyCMa-zg_uVhOfTnea5Klz6aPZlgHwVGj7U',
appId: '1:935017686266:ios:de47638bd662463fd2d543',
messagingSenderId: '935017686266',
projectId: 'didvan-9b7da',
storageBucket: 'didvan-9b7da.appspot.com',
iosClientId: '935017686266-54hu01v9cc5pqpgofo1gk2n3hegj4r2m.apps.googleusercontent.com',
iosBundleId: 'com.didvan.didvanapp',
);
}

View File

@ -1,8 +1,10 @@
import 'dart:io';
// ignore_for_file: deprecated_member_use
import 'package:android_intent_plus/android_intent.dart';
import 'package:bot_toast/bot_toast.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/firebase_options.dart';
import 'package:didvan/models/notification_data.dart';
import 'package:didvan/models/notification_message.dart';
import 'package:didvan/providers/media.dart';
import 'package:didvan/providers/theme.dart';
@ -10,9 +12,9 @@ import 'package:didvan/providers/user.dart';
import 'package:didvan/routes/route_generator.dart';
import 'package:didvan/routes/routes.dart';
import 'package:didvan/services/app_home_widget/home_widget_repository.dart';
import 'package:didvan/services/app_initalizer.dart';
import 'package:didvan/services/media/media.dart';
import 'package:didvan/services/notification/awsome/awsome_notification_handler.dart';
import 'package:didvan/services/notification/firebase_api.dart';
import 'package:didvan/services/notification/notification_service.dart';
import 'package:didvan/views/podcasts/podcasts_state.dart';
import 'package:didvan/views/podcasts/studio_details/studio_details_state.dart';
import 'package:firebase_core/firebase_core.dart';
@ -26,43 +28,18 @@ import 'package:provider/provider.dart';
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: kIsWeb
? const FirebaseOptions(
apiKey: "AIzaSyA0HZjKpRuPOi1SC3f_EZTvlS3mcj9UVo0",
authDomain: "didvan-9b7da.firebaseapp.com",
projectId: "didvan-9b7da",
storageBucket: "didvan-9b7da.appspot.com",
messagingSenderId: "935017686266",
appId: "1:935017686266:web:a93f7a19bed23c51d2d543",
measurementId: "G-80B4H9E8Y0")
: Platform.isAndroid
? const FirebaseOptions(
apiKey: 'AIzaSyBp-UHjWeM0H0UHtX5yguFKG-riMzvvCzw',
appId: '1:935017686266:android:f9cbc9aba8e3d65ed2d543',
messagingSenderId: '935017686266',
projectId: 'didvan-9b7da',
)
: const FirebaseOptions(
apiKey: 'AIzaSyCMa-zg_uVhOfTnea5Klz6aPZlgHwVGj7U',
appId: '1:935017686266:ios:de47638bd662463fd2d543',
messagingSenderId: '935017686266',
projectId: 'didvan-9b7da',
// iosBundleId: "com.didvan.didvanapp",
// storageBucket: "didvan-9b7da.appspot.com",
// iosClientId:
// "935017686266-54hu01v9cc5pqpgofo1gk2n3hegj4r2m.apps.googleusercontent.com"
),
);
print("background: ${NotificationMessage.fromJson(message.data).toJson()}");
try {
await AwsomeNotificationHandler().show(message);
} catch (e) {
rethrow;
Future _initPushNotification(RemoteMessage message) async {
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
if (kDebugMode) {
print("background: ${NotificationData.fromJson(message.data).toJson()}");
}
try {
NotificationService.showFirebaseNotification(message);
} catch (e) {
if (kDebugMode) {
print(e);
}
}
return;
}
@pragma('vm:entry-point')
@ -80,19 +57,16 @@ Future<void> _backgroundCallbackHomeWidget(Uri? uri) async {
void main() async {
WidgetsFlutterBinding.ensureInitialized();
try {
await AwsomeNotificationHandler().alarm();
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
//ignore: deprecated_member_use
HomeWidget.registerBackgroundCallback(_backgroundCallbackHomeWidget);
HomeWidget.registerInteractivityCallback(_backgroundCallbackHomeWidget);
await AppInitializer.initializeFirebase();
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
print(
"forground: ${NotificationMessage.fromJson(message.data).toJson()}");
AwsomeNotificationHandler().show(message);
});
await NotificationService.initializeNotification();
FirebaseMessaging.onBackgroundMessage(_initPushNotification);
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform);
await FirebaseApi().initNotification();
} catch (e) {
rethrow;
debugPrint;
}
runApp(const Didvan());
@ -113,7 +87,7 @@ class _DidvanState extends State<Didvan> with WidgetsBindingObserver {
@override
void initState() {
AwsomeNotificationHandler.startListeningNotificationEvents();
NotificationService.startListeningNotificationEvents();
super.initState();
WidgetsBinding.instance.addObserver(this);
@ -123,9 +97,9 @@ class _DidvanState extends State<Didvan> with WidgetsBindingObserver {
void dispose() {
WidgetsBinding.instance.removeObserver(this);
// MediaService.audioPlayer.dispose();
if(MediaService.currentPodcast != null){
MediaService.audioPlayer.dispose();
}
if (MediaService.currentPodcast != null) {
MediaService.audioPlayer.dispose();
}
super.dispose();
}

View File

@ -1,11 +1,13 @@
class DayTime{
String hour;
String minute;
Meridiem meridiem;
// ignore_for_file: constant_identifier_names
class DayTime {
String hour;
String minute;
Meridiem meridiem;
DayTime({this.hour = "1", this.minute = "0", this.meridiem = Meridiem.AM});
}
enum SelectorType { meridiem, hour, minute }
enum SelectorType { meridiem, hour, minute }
enum Meridiem { AM, PM }
enum Meridiem { AM, PM }

View File

@ -0,0 +1,49 @@
class NotificationData {
String? title;
String? body;
String? largeIcon;
String? bigPicture;
String? id;
String? notificationType;
String? type;
String? link;
String? groupKey;
NotificationData({
this.title,
this.body,
this.largeIcon,
this.bigPicture,
this.id,
this.notificationType,
this.type,
this.link,
this.groupKey,
});
NotificationData.fromJson(Map<String, dynamic> json) {
title = json['title'];
body = json['body'];
largeIcon = json['largeIcon'];
bigPicture = json['bigPicture'];
id = json['id'];
notificationType = json['notificationType'];
type = json['type'];
link = json['link'];
groupKey = json['groupKey'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['title'] = title;
data['body'] = body;
data['largeIcon'] = largeIcon;
data['bigPicture'] = bigPicture;
data['id'] = id;
data['notificationType'] = notificationType;
data['type'] = type;
data['link'] = link;
data['groupKey'] = groupKey;
return data;
}
}

View File

@ -7,17 +7,21 @@ class NotificationMessage {
String? link;
String? image;
String? photo;
String? groupKey;
String? userId;
NotificationMessage(
{this.notificationType,
this.title,
this.body,
this.id,
this.type,
this.link,
this.image,
this.photo,
});
NotificationMessage({
this.notificationType,
this.title,
this.body,
this.id,
this.type,
this.link,
this.image,
this.photo,
this.groupKey,
this.userId,
});
NotificationMessage.fromJson(Map<String, dynamic> json) {
notificationType = json['notificationType'];
@ -28,6 +32,8 @@ class NotificationMessage {
link = json['link'];
image = json['image'];
photo = json['photo'];
groupKey = json['groupKey'];
userId = json['userId'];
}
Map<String, dynamic> toJson() {
@ -40,8 +46,11 @@ class NotificationMessage {
data['link'] = link;
data['image'] = image;
data['photo'] = photo;
data['groupKey'] = groupKey;
data['userId'] = userId;
return data;
}
Map<String, String> toPayload() {
final Map<String, String> data = <String, String>{};
data['notificationType'] = notificationType!;
@ -52,6 +61,7 @@ class NotificationMessage {
data['link'] = link!;
data['image'] = image!;
data['photo'] = photo!;
data['userId'] = userId!;
return data;
}
}
}

View File

@ -4,9 +4,9 @@ import 'package:didvan/models/enums.dart';
import 'package:didvan/models/user.dart';
import 'package:didvan/models/view/alert_data.dart';
import 'package:didvan/providers/core.dart';
import 'package:didvan/services/app_initalizer.dart';
import 'package:didvan/services/network/request.dart';
import 'package:didvan/services/network/request_helper.dart';
import 'package:didvan/services/notification/firebase_api.dart';
import 'package:didvan/services/storage/storage.dart';
import 'package:didvan/utils/action_sheet.dart';
@ -64,9 +64,9 @@ class UserProvider extends CoreProvier {
value: service.result['user']['end'],
);
AppInitializer.initializeFirebase().then((_) {
_registerFirebaseToken();
}).catchError((err) {});
FirebaseApi()
.initNotification()
.then((value) => _registerFirebaseToken());
return true;
} catch (e) {
@ -78,13 +78,12 @@ class UserProvider extends CoreProvier {
}
Future<void> _registerFirebaseToken() async {
if (AppInitializer.fcmToken == null) {
return;
if (FirebaseApi.fcmToken != null) {
final service = RequestService(RequestHelper.firebaseToken, body: {
'token': FirebaseApi.fcmToken,
});
await service.put();
}
final service = RequestService(RequestHelper.firebaseToken, body: {
'token': AppInitializer.fcmToken,
});
await service.put();
}
Future<bool> setProfilePhoto(dynamic file) async {

View File

@ -16,7 +16,7 @@ import 'package:didvan/views/home/home_state.dart';
import 'package:didvan/views/home/new_statistic/new_statistics_state.dart';
import 'package:didvan/views/home/new_statistic/statistics_details/stat_cats_general_screen.dart';
import 'package:didvan/views/home/new_statistic/statistics_details/stat_cats_general_state.dart';
import 'package:didvan/views/home/new_statistic/stock/newStock_state.dart';
import 'package:didvan/views/home/new_statistic/stock/new_stock_state.dart';
import 'package:didvan/views/home/new_statistic/stock/new_stock.dart';
import 'package:didvan/views/mentions/mentions.dart';
import 'package:didvan/views/mentions/mentions_state.dart';
@ -48,8 +48,6 @@ import 'package:didvan/views/podcasts/studio_details/studio_details.mobile.dart'
if (dart.library.html) 'package:didvan/views/podcasts/studio_details/studio_details.web.dart';
import 'package:didvan/views/splash/splash.dart';
import 'package:didvan/routes/routes.dart';
import 'package:didvan/views/widgets/audio/player_navbar.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:home_widget/home_widget.dart';

View File

@ -1,6 +1,6 @@
import 'dart:io';
import 'package:didvan/main.dart';
import 'package:didvan/models/notification_message.dart';
import 'package:didvan/models/requests/news.dart';
import 'package:didvan/models/requests/radar.dart';
import 'package:didvan/models/requests/studio.dart';
@ -10,16 +10,11 @@ import 'package:didvan/services/media/media.dart';
import 'package:didvan/services/storage/storage.dart';
import 'package:didvan/views/home/home_state.dart';
import 'package:didvan/views/podcasts/studio_details/studio_details_state.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:provider/provider.dart';
import '../models/notification_message.dart';
import 'notification/awsome/awsome_notification_handler.dart';
class AppInitializer {
static String? fcmToken;
static String? clickAction;
@ -32,7 +27,7 @@ class AppInitializer {
}
// ignore: use_build_context_synchronously
final studioState = context.read<StudioDetailsState>();
MediaService.audioPlayer.isPlaying.listen((event) {
MediaService.audioPlayer.playingStream.listen((event) {
if (event &&
(MediaService.audioPlayerTag?.contains('podcast') ?? false)) {
studioState.handleTracking(
@ -150,67 +145,30 @@ class AppInitializer {
}
}
static Future<void> initializeFirebase() async {
try {
await Firebase.initializeApp(
options: kIsWeb
? const FirebaseOptions(
apiKey: "AIzaSyA0HZjKpRuPOi1SC3f_EZTvlS3mcj9UVo0",
authDomain: "didvan-9b7da.firebaseapp.com",
projectId: "didvan-9b7da",
storageBucket: "didvan-9b7da.appspot.com",
messagingSenderId: "935017686266",
appId: "1:935017686266:web:a93f7a19bed23c51d2d543",
measurementId: "G-80B4H9E8Y0")
: Platform.isAndroid
? const FirebaseOptions(
apiKey: 'AIzaSyBp-UHjWeM0H0UHtX5yguFKG-riMzvvCzw',
appId: '1:935017686266:android:f9cbc9aba8e3d65ed2d543',
messagingSenderId: '935017686266',
projectId: 'didvan-9b7da',
)
: const FirebaseOptions(
apiKey: 'AIzaSyCMa-zg_uVhOfTnea5Klz6aPZlgHwVGj7U',
appId: '1:935017686266:ios:de47638bd662463fd2d543',
messagingSenderId: '935017686266',
projectId: 'didvan-9b7da',
// iosBundleId: "com.didvan.didvanapp",
// storageBucket: "didvan-9b7da.appspot.com",
// iosClientId:
// "935017686266-54hu01v9cc5pqpgofo1gk2n3hegj4r2m.apps.googleusercontent.com"
),
);
} catch (e) {
Firebase.app();
static int createNotificationId(NotificationMessage data) {
int t = 0;
switch (data.type!) {
case "infography":
t = 1;
break;
case "news":
t = 2;
break;
case "radar":
t = 3;
break;
case "video":
t = 4;
break;
case "podcast":
t = 5;
break;
}
final initMsg = await FirebaseMessaging.instance.getInitialMessage();
if (initMsg != null) {
clickAction = initMsg.data['click_action'].replaceAll(
'navigate-',
'',
);
}
final FirebaseMessaging fcm = FirebaseMessaging.instance;
fcmToken = await fcm.getToken(
vapidKey: kIsWeb
? 'BMXHGd93t_htpS7c62ceuuLVVmia2cEDmqxp46g9Vt0B3OxNMKIqN9nupsUMtv2Vq8Yy2sQGIqgCm9FxUSKvssU'
: null,
);
print("FCM TOKEN: $fcmToken");
// await fcm.subscribeToTopic('general');
await fcm.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
int id = int.parse('${data.userId}${data.id}$t');
return id;
}
}

View File

@ -1,133 +0,0 @@
import 'dart:async';
import 'package:audioplayers/audioplayers.dart';
class AudioHandler {
late AudioPlayer _player;
PlayerState? _playerState;
Duration? audioDuration = Duration.zero;
Duration? audioPosition = Duration.zero;
bool isLoading = true;
StreamSubscription? durationSubscriptionS;
StreamSubscription? positionSubscriptionS;
StreamSubscription? playerCompleteSubscriptionS;
StreamSubscription? playerStateChangeSubscriptionS;
AudioPlayer get player => _player;
PlayerState? get playerState => _playerState;
bool get isPlaying => _playerState == PlayerState.playing;
bool get isPaused => _playerState == PlayerState.paused;
String get durationText => audioDuration?.toString().split('.').first ?? '';
String get positionText => audioPosition?.toString().split('.').first ?? '';
AudioHandler(String url) {
_player = AudioPlayer();
_player.setReleaseMode(ReleaseMode.stop);
_player
.play(UrlSource(url))
.then((value) {
_player.pause();
isLoading = false;
_playerState = PlayerState.paused;
});
player.getDuration().then((value) => audioDuration = value);
player.getCurrentPosition().then((value) => audioPosition = value);
}
StreamSubscription? durationSubscription(Function(Duration d) func) {
return durationSubscriptionS = player.onDurationChanged.listen((duration) {
// setState(() => _duration = duration);
audioDuration = duration;
func(duration);
});
}
StreamSubscription? positionSubscription(Function(Duration d) func) {
return positionSubscriptionS = player.onPositionChanged.listen(
(p) {
audioPosition = p;
func(p);
},
);
}
StreamSubscription? playerCompleteSubscription(Function() func) {
return playerCompleteSubscriptionS =
player.onPlayerComplete.listen((event) {
stop();
func();
});
}
StreamSubscription? playerStateChangeSubscription(
Function(PlayerState) func) {
return playerStateChangeSubscriptionS =
player.onPlayerStateChanged.listen((state) {
_playerState = state;
func(state);
});
}
Future<void> play() async {
await _player.resume();
// _playerState = PlayerState.playing;
}
Future<void> pause() async {
await _player.pause();
// _playerState = PlayerState.paused;
}
Future<void> stop() async {
await _player.stop();
// _playerState = PlayerState.stopped;
audioPosition = Duration.zero;
}
// void _initStreams() {
// durationSubscription = player.onDurationChanged.listen((duration) {
// setState(() => _duration = duration);
// });
//
// _positionSubscription = player.onPositionChanged.listen(
// (p) {
// setState(() {
// _position = p;
// for (var i = 0; i < bars.length / 10; i++) {
// if (i <= _position!.inSeconds) {
// bars[i].color = primaryColor;
// }
// }
// });
// },
// );
//
// _playerCompleteSubscription = player.onPlayerComplete.listen((event) {
// setState(() {
// _playerState = PlayerState.stopped;
// _position = Duration.zero;
// });
// });
//
// _playerCompleteSubscription = player.onSeekComplete.listen((event) {
// setState(() {
// print(
// "Complete------------------------------------------------------------");
// });
// });
//
// _playerStateChangeSubscription =
// player.onPlayerStateChanged.listen((state) {
// setState(() {
// _playerState = state;
// });
// });
// }
}

View File

@ -6,16 +6,15 @@ import 'package:didvan/services/network/request_helper.dart';
import 'package:didvan/services/storage/storage.dart';
import 'package:flutter/foundation.dart';
import 'package:image_picker/image_picker.dart';
import 'package:assets_audio_player/assets_audio_player.dart';
import 'package:just_audio/just_audio.dart';
class MediaService {
static final audioPlayer = AssetsAudioPlayer();
static final audioPlayer = AudioPlayer();
static String? audioPlayerTag;
static StudioDetailsData? currentPodcast;
static StudioRequestArgs? podcastPlaylistArgs;
static Duration? get duration =>
audioPlayer.current.valueOrNull?.audio.duration;
static Duration? get duration => audioPlayer.duration;
static Future<void> handleAudioPlayback({
required dynamic audioSource,
@ -33,13 +32,17 @@ class MediaService {
isNetworkAudio = false;
}
if (audioPlayerTag == tag) {
await audioPlayer.playOrPause();
if (audioPlayer.playerState ==
PlayerState(true, ProcessingState.ready)) {
await audioPlayer.pause();
} else {
await audioPlayer.play();
}
return;
}
// await audioPlayer.stop();
audioPlayerTag = tag;
Audio audio;
String source;
if (isNetworkAudio) {
if (isVoiceMessage) {
@ -48,38 +51,39 @@ class MediaService {
} else {
source = audioSource;
}
audio = Audio.network(
audioPlayer.setUrl(
kIsWeb ? source.replaceAll('%3A', ':') : source,
metas: isVoiceMessage
tag: isVoiceMessage
? null
: Metas(
artist: 'استودیو دیدوان',
title: currentPodcast?.title ?? '',
),
: {
"artist": 'استودیو دیدوان',
"title": currentPodcast?.title ?? '',
},
);
} else {
audio = Audio.file(
audioPlayer.setAsset(
audioSource,
metas: isVoiceMessage
tag: isVoiceMessage
? null
: Metas(
artist: 'استودیو دیدوان',
title: currentPodcast?.title ?? '',
),
: {
"artist": 'استودیو دیدوان',
"title": currentPodcast?.title ?? '',
},
);
}
await audioPlayer.open(
audio,
showNotification: !isVoiceMessage,
notificationSettings: NotificationSettings(
customStopAction: (_) => resetAudioPlayer(),
customNextAction: (_) => onTrackChanged?.call(true),
customPrevAction: (_) => onTrackChanged?.call(false),
),
);
await audioPlayer.play();
// await audioPlayer.open(
// audio,
// showNotification: !isVoiceMessage,
// notificationSettings: NotificationSettings(
// customStopAction: (_) => resetAudioPlayer(),
// customNextAction: (_) => onTrackChanged?.call(true),
// customPrevAction: (_) => onTrackChanged?.call(false),
// ),
// );
} catch (e) {
// resetAudioPlayer();
rethrow;
// rethrow;
}
}

View File

@ -63,7 +63,7 @@ class RequestService {
headers: _headers,
)
.timeout(
const Duration(seconds: 10),
const Duration(seconds: 30),
)
.catchError(
(e) => throw e,

View File

@ -1,44 +0,0 @@
import 'package:awesome_notifications/awesome_notifications.dart';
import 'package:didvan/services/app_home_widget/home_widget_repository.dart';
import '../../../models/notification_message.dart';
class NotificationController {
/// Use this method to detect when a new notification or a schedule is created
@pragma("vm:entry-point")
static Future<void> onNotificationCreatedMethod(
ReceivedNotification receivedNotification) async {
// Your code goes here
}
/// Use this method to detect every time that a new notification is displayed
@pragma("vm:entry-point")
static Future<void> onNotificationDisplayedMethod(
ReceivedNotification receivedNotification) async {
// Your code goes here
}
/// Use this method to detect if the user dismissed a notification
@pragma("vm:entry-point")
static Future<void> onDismissActionReceivedMethod(
ReceivedAction receivedAction) async {
// Your code goes here
}
/// Use this method to detect when the user taps on a notification or action button
@pragma("vm:entry-point")
static Future<void> onActionReceivedMethod(
ReceivedAction receivedAction) async {
NotificationMessage data =
NotificationMessage.fromJson(receivedAction.payload!);
// Your code goes here
HomeWidgetRepository.data = data;
await HomeWidgetRepository.decideWhereToGoNotif();
return;
// MyApp.navigatorKey.currentState?.pushNamedAndRemoveUntil('/notification-page',
// (route) => (route.settings.name != '/notification-page') || route.isFirst,
// arguments: receivedAction);
}
}

View File

@ -1,305 +0,0 @@
import 'dart:io';
import 'package:awesome_notifications/awesome_notifications.dart';
import 'package:didvan/services/storage/storage.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import '../../../models/notification_message.dart';
import '../../app_home_widget/home_widget_repository.dart';
import '../../network/request.dart';
import '../../network/request_helper.dart';
import 'awsome_notification_controller.dart';
class AwsomeNotificationHandler {
static ReceivedAction? initialAction;
alarm() async {
AwesomeNotifications().initialize(
// set the icon to null if you want to use the default app icon
null,
[
NotificationChannel(
channelKey: 'alerts',
channelName: 'Alerts',
channelDescription: 'Notification tests as alerts',
playSound: true,
onlyAlertOnce: true,
groupAlertBehavior: GroupAlertBehavior.Children,
importance: NotificationImportance.High,
defaultPrivacy: NotificationPrivacy.Public,
defaultColor: const Color(0xFF007EA7),
criticalAlerts: true,
ledColor: Colors.white,
)
],
// Channel groups are only visual and are not required
// channelGroups: [
// NotificationChannelGroup(
// channelGroupKey: 'basic_channel_group',
// channelGroupName: 'Basic group')
// ],
debug: true);
startListeningNotificationEvents();
// Get initial notification action is optional
initialAction = await AwesomeNotifications()
.getInitialNotificationAction(removeFromActionEvents: false);
if (initialAction?.payload != null) {
NotificationMessage data =
NotificationMessage.fromJson(initialAction!.payload!);
HomeWidgetRepository.data = data;
}
// Your code goes here
AwesomeNotifications().isNotificationAllowed().then((isAllowed) {
//It would be more appropriate if you can show your own dialog
//to the user before requesting the notifications permissons.
if (!isAllowed) {
AwesomeNotifications().requestPermissionToSendNotifications(
permissions: [
NotificationPermission.Alert,
NotificationPermission.Sound,
NotificationPermission.Badge,
NotificationPermission.Vibration,
NotificationPermission.Light,
NotificationPermission.FullScreenIntent,
],
);
}
});
}
@pragma("vm:entry-point")
static Future<void> startListeningNotificationEvents() async {
await AwesomeNotifications().setListeners(
onActionReceivedMethod: NotificationController.onActionReceivedMethod,
onNotificationCreatedMethod:
NotificationController.onNotificationCreatedMethod,
onNotificationDisplayedMethod:
NotificationController.onNotificationDisplayedMethod,
onDismissActionReceivedMethod:
NotificationController.onDismissActionReceivedMethod);
return;
}
show(RemoteMessage message) async {
NotificationMessage notificationMessage =
NotificationMessage.fromJson(message.data);
switch (notificationMessage.notificationType.toString()) {
case "1":
await showNotificationTypeNews(notificationMessage);
break;
case "2":
await showNotificationTypeMessage(notificationMessage);
break;
case "3":
await HomeWidgetRepository.fetchWidget();
break;
case "4":
await showNotificationTypeEmoji(notificationMessage);
break;
}
}
showNotificationTypeNews(NotificationMessage message) async {
DateTime? time = await _getTime();
if (time == null) {
AwesomeNotifications().createNotification(
content: NotificationContent(
id: DateTime.now().millisecondsSinceEpoch ~/ 1000,
channelKey: 'alerts',
actionType: ActionType.Default,
title: "\u200f ${message.title} \u200f",
body: message.body.toString(),
notificationLayout: NotificationLayout.BigPicture,
largeIcon: message.image.toString(),
bigPicture: message.image.toString(),
category: NotificationCategory.Social,
wakeUpScreen: true,
hideLargeIconOnExpand: true,
payload: message.toPayload(),
color: const Color(0xFF007EA7)),
);
} else {
AwesomeNotifications().createNotification(
content: NotificationContent(
id: DateTime.now().millisecondsSinceEpoch ~/ 1000,
channelKey: 'alerts',
actionType: ActionType.Default,
title: "\u200f ${message.title} \u200f",
// body: message.body.toString(),
notificationLayout: Platform.isAndroid
? NotificationLayout.Default
: NotificationLayout.BigPicture,
largeIcon: message.image.toString(),
bigPicture: Platform.isAndroid ? null : message.image.toString(),
payload: message.toPayload(),
color: const Color(0xFF007EA7)),
schedule: NotificationCalendar(
hour: time.hour,
minute: time.minute,
));
}
}
showNotificationTypeMessage(NotificationMessage message) async {
DateTime? time = await _getTime();
if (time == null) {
AwesomeNotifications().createNotification(
content: NotificationContent(
id: DateTime.now().millisecondsSinceEpoch ~/ 1000,
channelKey: 'alerts',
actionType: ActionType.Default,
body:
"<b>${message.title.toString()}</b> ${message.body.toString()}",
largeIcon: message.photo.toString(),
roundedLargeIcon: true,
bigPicture: message.image.toString(),
payload: message.toPayload(),
notificationLayout: NotificationLayout.BigPicture,
color: const Color(0xFF007EA7)),
);
} else {
AwesomeNotifications().createNotification(
content: NotificationContent(
id: DateTime.now().millisecondsSinceEpoch ~/ 1000,
channelKey: 'alerts',
actionType: ActionType.Default,
body:
"<b>${message.title.toString()}</b> ${message.body.toString()}",
largeIcon: Platform.isAndroid
? message.photo.toString()
: message.image.toString(),
roundedLargeIcon: true,
bigPicture: message.image.toString(),
payload: message.toPayload(),
notificationLayout: NotificationLayout.BigPicture,
color: const Color(0xFF007EA7)),
schedule: NotificationCalendar(
hour: time.hour,
minute: time.minute,
));
}
// actionButtons: [
// NotificationActionButton(
// key: 'REPLY',
// label: 'جواب دادن',
// requireInputText: true,
// actionType: ActionType.SilentAction),
// NotificationActionButton(
// key: 'DISMISS',
// label: 'خوانده شده',
// actionType: ActionType.DismissAction,
// isDangerousOption: true)
// ]
}
showNotificationTypeEmoji(NotificationMessage message) async {
AwesomeNotifications().createNotification(
content: NotificationContent(
id: DateTime.now().millisecondsSinceEpoch ~/ 1000,
channelKey: 'alerts',
title: 'Emojis are awes'
'ome too! ${Emojis.animals_lady_beetle}${Emojis.activites_balloon}${Emojis.emotion_red_heart}',
body:
'Simple body with a bunch of Emojis! ${Emojis.transport_police_car} ${Emojis.animals_dog} ${Emojis.flag_UnitedStates} ${Emojis.person_baby}',
largeIcon:
'https://cdn.britannica.com/72/232772-050-4E3D86CC/mind-blown-emoji-head-exploding-emoticon.jpg',
notificationLayout: NotificationLayout.Default,
payload: {
'title': 'Notification Title',
'body': 'Notification Body',
'image': 'path/to/smallImage.png', // Path to small image
'largeImage': 'path/to/largeImage.png', // Path to large image
}));
}
Future<DateTime?> _getTime() async {
final token = await StorageService.getValue(key: 'token');
final service = RequestService(RequestHelper.notificationTime(),
useAutherization: false,
requestHeaders: {
"accept": "*/*",
"Content-Type": "application/json; charset=UTF-8",
'Authorization': 'Bearer $token'
});
await service.httpGet();
if (service.isSuccess) {
final time = service.data('time');
DateTime result = DateTime.now();
if (time.toString().isNotEmpty) {
DateFormat format = DateFormat("HH:mm");
DateTime dateTime = format.parse(time);
result = DateTime.now()
.copyWith(hour: dateTime.hour, minute: dateTime.minute);
return result;
}
}
return null;
}
showNotificationScheduled(NotificationMessage message) async {
DateTime? time = await _getTime();
if (time == null) {
AwesomeNotifications().createNotification(
content: NotificationContent(
id: DateTime.now().millisecondsSinceEpoch ~/ 1000,
channelKey: 'alerts',
title: 'Emojis are awes'
'ome too! ${Emojis.animals_lady_beetle}${Emojis.activites_balloon}${Emojis.emotion_red_heart}',
body:
'Simple body with a bunch of Emojis! ${Emojis.transport_police_car} ${Emojis.animals_dog} ${Emojis.flag_UnitedStates} ${Emojis.person_baby}',
largeIcon:
'https://cdn.britannica.com/72/232772-050-4E3D86CC/mind-blown-emoji-head-exploding-emoticon.jpg',
notificationLayout: NotificationLayout.BigPicture,
wakeUpScreen: true,
category: NotificationCategory.Alarm,
payload: {
'title': 'Notification Title',
'body': 'Notification Body',
'image': 'path/to/smallImage.png', // Path to small image
'largeImage': 'path/to/largeImage.png', // Path to large image
}),
);
} else {
AwesomeNotifications().createNotification(
content: NotificationContent(
id: DateTime.now().millisecondsSinceEpoch ~/ 1000,
channelKey: 'alerts',
title: 'Emojis are awes'
'ome too! ${Emojis.animals_lady_beetle}${Emojis.activites_balloon}${Emojis.emotion_red_heart}',
body:
'Simple body with a bunch of Emojis! ${Emojis.transport_police_car} ${Emojis.animals_dog} ${Emojis.flag_UnitedStates} ${Emojis.person_baby}',
largeIcon:
'https://cdn.britannica.com/72/232772-050-4E3D86CC/mind-blown-emoji-head-exploding-emoticon.jpg',
notificationLayout: NotificationLayout.BigPicture,
wakeUpScreen: true,
category: NotificationCategory.Alarm,
payload: {
'title': 'Notification Title',
'body': 'Notification Body',
'image': 'path/to/smallImage.png', // Path to small image
'largeImage': 'path/to/largeImage.png', // Path to large image
}),
schedule: NotificationCalendar(
hour: time.hour,
minute: time.minute,
// timezone: await AwesomeNotifications().getLocalTimeZoneIdentifier()
));
}
}
}

View File

@ -1,72 +0,0 @@
import 'dart:io';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import '../../app_initalizer.dart';
class FirebaseNotificationHandler {
Future<void> initial() async {
try {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: kIsWeb
? const FirebaseOptions(
apiKey: "AIzaSyA0HZjKpRuPOi1SC3f_EZTvlS3mcj9UVo0",
authDomain: "didvan-9b7da.firebaseapp.com",
projectId: "didvan-9b7da",
storageBucket: "didvan-9b7da.appspot.com",
messagingSenderId: "935017686266",
appId: "1:935017686266:web:a93f7a19bed23c51d2d543",
measurementId: "G-80B4H9E8Y0")
: Platform.isAndroid
? const FirebaseOptions(
apiKey: 'AIzaSyBp-UHjWeM0H0UHtX5yguFKG-riMzvvCzw',
appId: '1:935017686266:android:f9cbc9aba8e3d65ed2d543',
messagingSenderId: '935017686266',
projectId: 'didvan-9b7da',
)
: const FirebaseOptions(
apiKey: 'AIzaSyCMa-zg_uVhOfTnea5Klz6aPZlgHwVGj7U',
appId: '1:935017686266:ios:de47638bd662463fd2d543',
messagingSenderId: '935017686266',
projectId: 'didvan-9b7da',
// iosBundleId: "com.didvan.didvanapp",
// storageBucket: "didvan-9b7da.appspot.com",
// iosClientId:
// "935017686266-54hu01v9cc5pqpgofo1gk2n3hegj4r2m.apps.googleusercontent.com"
),
);
final initMsg = await FirebaseMessaging.instance.getInitialMessage();
if (initMsg != null) {
AppInitializer.clickAction = initMsg.data['click_action'].replaceAll(
'navigate-',
'',
);
}
// LocalNotificationService.initialize();
NotificationSettings settings =
await FirebaseMessaging.instance.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
debugPrint(
'User granted notifications permission: ${settings.authorizationStatus}');
} catch (e) {
if (kDebugMode) {
print(e.toString());
}
}
}
}

View File

@ -0,0 +1,50 @@
import 'package:didvan/models/notification_data.dart';
import 'package:didvan/services/notification/notification_service.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/foundation.dart';
import 'package:get/get.dart';
class FirebaseApi {
final _firebaseMessaging = FirebaseMessaging.instance;
static String? fcmToken;
Future<void> initNotification() async {
await _firebaseMessaging.requestPermission();
try {
fcmToken = await _firebaseMessaging.getToken();
if (kDebugMode) {
print("fCMToken: $fcmToken");
}
} catch (e) {
e.printError();
}
await _firebaseMessaging.requestPermission(
alert: true,
announcement: true,
badge: true,
carPlay: false,
criticalAlert: true,
provisional: true,
sound: true,
);
FirebaseMessaging.instance.getInitialMessage();
FirebaseMessaging.onMessageOpenedApp.listen((event) {});
FirebaseMessaging.onMessage.listen((event) => handleMessage(event));
}
void handleMessage(RemoteMessage? message) async {
if (message == null) return;
//do ever you want with message
if (kDebugMode) {
print("forground: ${NotificationData.fromJson(message.data).toJson()}");
}
try {
await NotificationService.showFirebaseNotification(message);
} catch (e) {
rethrow;
}
}
}

View File

@ -1,130 +0,0 @@
import 'dart:io';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:http/http.dart';
import 'package:path_provider/path_provider.dart';
import '../../../models/notification_message.dart';
import '../../../views/widgets/notification/notification_dynamic_dialog.dart';
class LocalNotificationService {
// Instance of Flutternotification plugin
static final FlutterLocalNotificationsPlugin _notificationsPlugin =
FlutterLocalNotificationsPlugin();
static void initialize() {
// Initialization setting for android
const InitializationSettings initializationSettingsAndroid =
InitializationSettings(
android: AndroidInitializationSettings("@mipmap/ic_launcher"));
_notificationsPlugin.initialize(
initializationSettingsAndroid,
// to handle event when we receive notification
onDidReceiveNotificationResponse: (details) {
if (details.input != null) {}
},
);
}
static Future<void> display(RemoteMessage message) async {
// To display the notification in device
try {
final id = DateTime.now().millisecondsSinceEpoch ~/ 1000;
final BigPictureStyleInformation bigPictureStyleInformation =
BigPictureStyleInformation(
const FilePathAndroidBitmap(
"lib/assets/aaaa.jpg"),
contentTitle: NotificationMessage.fromJson(message.data).title,
htmlFormatContentTitle: true,
summaryText: NotificationMessage.fromJson(message.data).body,
htmlFormatSummaryText: true,
htmlFormatContent: true,
largeIcon: const FilePathAndroidBitmap(
"lib/assets/aaaa.jpg"));
NotificationDetails notificationDetails = const NotificationDetails(
android: AndroidNotificationDetails("Channel Id", "Main Channel",
groupKey: "gfg",
color: Colors.white,
importance: Importance.max,
playSound: true,
priority: Priority.high),
);
if (message.notification == null) {
final NotificationMessage notificationModel =
NotificationMessage.fromJson(message.data);
await _notificationsPlugin.show(id, notificationModel.title,
notificationModel.body, notificationDetails,
payload: message.data['route']);
} else {
await _notificationsPlugin.show(id, message.notification?.title,
message.notification?.body, notificationDetails,
payload: message.data['route']);
}
} catch (e) {
debugPrint(e.toString());
}
}
void messageListener(BuildContext context) {
// Either you can pass buildcontext or you
// can take a context from navigator key
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
print('Got a message in the foreground!');
print('Message data: ${message.data}');
print(
'Message also contained a notification: so it will pop up ${message.notification!.body}');
showDialog(
context: context,
// context: navigatorKey!.currentContext!,
builder: ((BuildContext context) {
return NotificationDynamicDialog(
title: message.notification!.title,
body: message.notification!.body);
}));
});
}
static Future<String> _downloadAndSaveFile(String url, String fileName) async {
final Directory directory = await getApplicationDocumentsDirectory();
final String filePath = '${directory.path}/$fileName';
final Response response = await get(Uri.parse(url));
final File file = File(filePath);
await file.writeAsBytes(response.bodyBytes);
return filePath;
}
static Future<void> showBigPictureNotification() async {
final String largeIconPath = await _downloadAndSaveFile(
'https://via.placeholder.com/48x48', 'largeIcon');
final String bigPicturePath = await _downloadAndSaveFile(
'https://via.placeholder.com/400x800', 'bigPicture');
final BigPictureStyleInformation bigPictureStyleInformation =
BigPictureStyleInformation(FilePathAndroidBitmap(bigPicturePath),
largeIcon: FilePathAndroidBitmap(largeIconPath),
contentTitle: 'overridden <b>big</b> content title',
htmlFormatContentTitle: true,
summaryText: 'summary <i>text</i>',
htmlFormatSummaryText: true);
final AndroidNotificationDetails androidPlatformChannelSpecifics =
AndroidNotificationDetails(
'big text channel id', 'big text channel name',
channelDescription: 'big text channel description',
largeIcon: FilePathAndroidBitmap(largeIconPath),
channelShowBadge: false,
styleInformation: bigPictureStyleInformation);
final NotificationDetails platformChannelSpecifics =
NotificationDetails(android: androidPlatformChannelSpecifics);
await _notificationsPlugin.show(
0, 'big text title', 'silent body', platformChannelSpecifics);
}
}

View File

@ -1,40 +0,0 @@
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
void showNotificationAndroid(String title, String value) async {
const AndroidNotificationDetails androidNotificationDetails =
AndroidNotificationDetails('channel_id', 'Channel Name',
channelDescription: 'Channel Description',
importance: Importance.max,
priority: Priority.high,
ticker: 'ticker');
int notificationId = 1;
const NotificationDetails notificationDetails =
NotificationDetails(android: androidNotificationDetails);
await FlutterLocalNotificationsPlugin().show(
notificationId, title, value, notificationDetails,
payload: 'Not present');
}
void showNotificationIos(String title, String value) async {
DarwinNotificationDetails iOSPlatformChannelSpecifics = DarwinNotificationDetails(
presentAlert: true,
// Present an alert when the notification is displayed and the application is in the foreground (only from iOS 10 onwards)
presentBadge: true,
// Present the badge number when the notification is displayed and the application is in the foreground (only from iOS 10 onwards)
presentSound: true,
// Play a sound when the notification is displayed and the application is in the foreground (only from iOS 10 onwards)
subtitle: title,
//Secondary description (only from iOS 10 onwards)
threadIdentifier: value);
int notificationId = 1;
NotificationDetails platformChannelSpecifics =
NotificationDetails(iOS: iOSPlatformChannelSpecifics);
await FlutterLocalNotificationsPlugin().show(
notificationId, title, value, platformChannelSpecifics,
payload: 'Not present');
}

View File

@ -0,0 +1,166 @@
import 'package:awesome_notifications/awesome_notifications.dart';
import 'package:didvan/models/notification_message.dart';
import 'package:didvan/services/app_home_widget/home_widget_repository.dart';
import 'package:didvan/services/app_initalizer.dart';
import 'package:didvan/services/storage/storage.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class NotificationService {
static Future<void> initializeNotification() async {
await AwesomeNotifications().initialize(
null,
[
NotificationChannel(
channelKey: 'content',
channelGroupKey: 'content',
channelName: 'content Notification',
channelDescription: 'Notification channel',
defaultColor: Colors.blueAccent,
ledColor: Colors.white,
importance: NotificationImportance.Max,
channelShowBadge: true,
onlyAlertOnce: true,
playSound: true,
criticalAlerts: true),
// NotificationChannel(
// channelKey: 'mention',
// channelGroupKey: 'mention',
// channelName: 'mention Notification',
// channelDescription: 'Notification channel',
// defaultColor: Colors.blueAccent,
// ledColor: Colors.white,
// importance: NotificationImportance.Max,
// channelShowBadge: true,
// onlyAlertOnce: true,
// playSound: true,
// criticalAlerts: true),
],
// channelGroups: [
// NotificationChannelGroup(
// channelGroupKey: 'mention', channelGroupName: 'Group mention'),
// ],
debug: true);
await AwesomeNotifications()
.isNotificationAllowed()
.then((isAllowed) async {
if (!isAllowed) {
await AwesomeNotifications().requestPermissionToSendNotifications();
}
});
await startListeningNotificationEvents();
}
@pragma("vm:entry-point")
static Future<void> startListeningNotificationEvents() async {
await AwesomeNotifications().setListeners(
onActionReceivedMethod: _onActionReceivedMethod,
onDismissActionReceivedMethod: _onDismissActionReceivedMethod,
);
return;
}
@pragma('vm:entry-point')
static Future<void> _onActionReceivedMethod(
ReceivedAction receivedAction) async {
try {
NotificationMessage data =
NotificationMessage.fromJson(receivedAction.payload!);
HomeWidgetRepository.data = data;
await HomeWidgetRepository.decideWhereToGoNotif();
await StorageService.delete(
key: 'notification${AppInitializer.createNotificationId(data)}');
} catch (e) {
e.printError();
}
return;
}
@pragma('vm:entry-point')
static Future<void> _onDismissActionReceivedMethod(
ReceivedAction receivedAction) async {
try {
NotificationMessage data =
NotificationMessage.fromJson(receivedAction.payload!);
if (data.notificationType!.contains('2')) {
await StorageService.delete(
key: 'notification${AppInitializer.createNotificationId(data)}');
}
} catch (e) {
e.printError();
}
}
// @pragma('vm:entry-point')
// static Future<void> _onNotificationCreatedMethod(
// ReceivedNotification receivedNotification) async {
// }
// static Future<void> _onNotificationDisplayedMethod(
// ReceivedNotification receivedNotification) async {}
static Future<void> showFirebaseNotification(RemoteMessage message) async {
try {
final data = NotificationMessage.fromJson(message.data);
if (data.notificationType!.contains('3')) {
HomeWidgetRepository.fetchWidget();
return;
}
NotificationService.showNotification(data);
} catch (e) {
e.printError();
}
}
static Future<void> showNotification(NotificationMessage data) async {
if (data.notificationType!.contains('2')) {
final String? storedValue = await StorageService.getValue(
key: 'notification${AppInitializer.createNotificationId(data)}');
if (storedValue != null) {
AwesomeNotifications()
.dismiss(AppInitializer.createNotificationId(data));
data.body = '${data.body}\n$storedValue';
}
}
await AwesomeNotifications().createNotification(
content: NotificationContent(
id: data.notificationType!.contains('1')
? DateTime.now().millisecondsSinceEpoch ~/ 1000
: AppInitializer.createNotificationId(data),
channelKey:
// data.notificationType!.contains('1') ?
'content'
// : 'mention'
,
title: data.title,
body: data.body,
actionType: ActionType.Default,
notificationLayout: data.notificationType!.contains('1')
? NotificationLayout.BigPicture
: NotificationLayout.Messaging,
summary:
data.notificationType!.contains('1') ? "خبر جدید" : "منشن شدید",
bigPicture: data.image,
largeIcon: data.photo,
hideLargeIconOnExpand: data.notificationType!.contains('1'),
displayOnBackground: true,
displayOnForeground: true,
wakeUpScreen: true,
icon: 'resource://drawable/logo',
roundedLargeIcon: data.notificationType!.contains('2'),
payload: data.toPayload()),
);
if (data.notificationType!.contains('2')) {
await StorageService.setValue(
key: 'notification${AppInitializer.createNotificationId(data)}',
value: data.body);
}
}
}

View File

@ -1,3 +1,5 @@
// ignore_for_file: deprecated_member_use
import 'package:didvan/config/design_config.dart';
import 'package:didvan/views/authentication/authentication_state.dart';
import 'package:didvan/views/authentication/screens/password.dart';

View File

@ -79,7 +79,8 @@ class _PasswordInputState extends State<PasswordInput> {
await ServerDataProvider.getData();
if (mounted) {
Navigator.of(context).pushReplacementNamed(Routes.home);
Future.delayed(Duration.zero,
() => Navigator.of(context).pushReplacementNamed(Routes.home));
}
_showResetPasswordDialog();

View File

@ -54,14 +54,19 @@ class _ResetPasswordState extends State<ResetPassword> {
.read<AuthenticationState>()
.resetPassword(_password);
if (!mounted) return;
if (result && context.read<UserProvider>().isAuthenticated) {
Navigator.of(context).pop();
Navigator.of(context).pop();
return;
}
Navigator.of(context).pushNamed(
Routes.authenticaion,
arguments: false,
Future.delayed(
Duration.zero,
() {
if (result && context.read<UserProvider>().isAuthenticated) {
Navigator.of(context).pop();
Navigator.of(context).pop();
return;
}
Navigator.of(context).pushNamed(
Routes.authenticaion,
arguments: false,
);
},
);
},
title: 'تغییر رمز عبور',

View File

@ -1,3 +1,5 @@
// ignore_for_file: deprecated_member_use
import 'dart:async';
import 'package:didvan/config/design_config.dart';

View File

@ -84,15 +84,20 @@ class CustomizeCategoryState extends CoreProvier {
);
await service.put();
if (service.isSuccess) {
if (toTimer) {
Navigator.of(context).pushNamed(Routes.notificationTime,
arguments: {"fromFav": toTimer});
} else {
Navigator.of(context).pop();
ActionSheetUtils.showAlert(AlertData(
message: "تغییرات شما با موفقیت اعمال شد.",
aLertType: ALertType.success));
}
Future.delayed(
Duration.zero,
() {
if (toTimer) {
Navigator.of(context).pushNamed(Routes.notificationTime,
arguments: {"fromFav": toTimer});
} else {
Navigator.of(context).pop();
ActionSheetUtils.showAlert(AlertData(
message: "تغییرات شما با موفقیت اعمال شد.",
aLertType: ALertType.success));
}
},
);
appState = AppState.idle;
await HomeWidgetRepository.fetchWidget();
@ -112,16 +117,21 @@ class CustomizeCategoryState extends CoreProvier {
);
await service.put();
if (service.isSuccess) {
if (toTimer) {
Navigator.of(context).pushNamed(Routes.notificationTime,
arguments: {"fromFav": toTimer});
} else {
Navigator.of(context).pop();
Navigator.of(context).pop();
ActionSheetUtils.showAlert(AlertData(
message: "تغییرات شما با موفقیت اعمال شد.",
aLertType: ALertType.success));
}
Future.delayed(
Duration.zero,
() {
if (toTimer) {
Navigator.of(context).pushNamed(Routes.notificationTime,
arguments: {"fromFav": toTimer});
} else {
Navigator.of(context).pop();
Navigator.of(context).pop();
ActionSheetUtils.showAlert(AlertData(
message: "تغییرات شما با موفقیت اعمال شد.",
aLertType: ALertType.success));
}
},
);
appState = AppState.idle;
await HomeWidgetRepository.fetchWidget();

View File

@ -1,3 +1,5 @@
// ignore_for_file: deprecated_member_use
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/constants/assets.dart';
import 'package:didvan/models/enums.dart';

View File

@ -1,6 +1,5 @@
import 'dart:io';
import 'package:assets_audio_player/assets_audio_player.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/models/requests/studio.dart';
@ -10,6 +9,7 @@ import 'package:didvan/views/widgets/audio/audio_slider.dart';
import 'package:didvan/views/podcasts/studio_details/studio_details_state.dart';
import 'package:didvan/views/widgets/didvan/icon_button.dart';
import 'package:flutter/material.dart';
import 'package:just_audio/just_audio.dart';
import 'package:provider/provider.dart';
class AudioWidget extends StatelessWidget {
@ -28,7 +28,7 @@ class AudioWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return StreamBuilder<bool>(
stream: MediaService.audioPlayer.isPlaying,
stream: MediaService.audioPlayer.playingStream,
builder: (context, snapshot) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
@ -36,12 +36,18 @@ class AudioWidget extends StatelessWidget {
Expanded(
child: Padding(
padding: const EdgeInsets.only(top: 12),
child: AudioSlider(
tag: audioMetaData != null
? '${audioMetaData!.type}-$id'
: 'message-$id',
duration: audioMetaData?.duration,
showTimer: true,
child: Row(
children: [
Expanded(
child: AudioSlider(
tag: audioMetaData != null
? '${audioMetaData!.type}-$id'
: 'message-$id',
duration: audioMetaData?.duration,
showTimer: true,
),
),
],
),
),
),
@ -79,11 +85,11 @@ class _AudioControllerButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return StreamBuilder<PlayingAudio?>(
stream: MediaService.audioPlayer.onReadyToPlay,
return StreamBuilder<PlayerState>(
stream: MediaService.audioPlayer.playerStateStream,
builder: (context, snapshot) {
return DidvanIconButton(
icon: MediaService.audioPlayer.isPlaying.value && _nowPlaying
icon: MediaService.audioPlayer.playing && _nowPlaying
? DidvanIcons.pause_circle_solid
: DidvanIcons.play_circle_solid,
gestureSize: 36,
@ -100,7 +106,7 @@ class _AudioControllerButton extends StatelessWidget {
}
if (snapshot.data == null &&
_nowPlaying &&
MediaService.audioPlayer.isPlaying.value) {
MediaService.audioPlayer.playing) {
return;
}
if (audioMetaData != null) {

View File

@ -1,17 +1,23 @@
// ignore_for_file: deprecated_member_use
import 'package:didvan/config/design_config.dart';
import 'package:didvan/models/notification_message.dart';
import 'package:didvan/models/view/action_sheet_data.dart';
import 'package:didvan/providers/theme.dart';
import 'package:didvan/services/app_initalizer.dart';
import 'package:didvan/services/notification/awsome/awsome_notification_handler.dart';
import 'package:didvan/services/notification/notification_service.dart';
import 'package:didvan/utils/action_sheet.dart';
import 'package:didvan/views/home/bookmarks/bookmarks.dart';
import 'package:didvan/views/home/categories/categories_page.dart';
import 'package:didvan/views/home/main/main_page.dart';
import 'package:didvan/views/home/home_state.dart';
import 'package:didvan/views/home/new_statistic/new_statistic.dart';
import 'package:didvan/views/home/search/search.dart';
import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:didvan/views/widgets/logo_app_bar.dart';
import 'package:didvan/views/widgets/didvan/bnb.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import '../../services/app_home_widget/home_widget_repository.dart';
@ -28,7 +34,7 @@ class _HomeState extends State<Home>
@override
void initState() {
AwsomeNotificationHandler.startListeningNotificationEvents();
NotificationService.startListeningNotificationEvents();
final state = context.read<HomeState>();
DesignConfig.updateSystemUiOverlayStyle();
@ -59,28 +65,50 @@ class _HomeState extends State<Home>
Widget build(BuildContext context) {
return Scaffold(
appBar: const LogoAppBar(),
body: Consumer<HomeState>(
builder: (context, state, child) => AnimatedCrossFade(
duration: DesignConfig.lowAnimationDuration,
crossFadeState: state.filtering
? CrossFadeState.showSecond
: CrossFadeState.showFirst,
firstChild: SizedBox(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: TabBarView(
physics: const NeverScrollableScrollPhysics(),
controller: _tabController,
children: const [
MainPage(),
NewStatistic(),
//Statistic(),
CategoriesPage(),
Bookmarks(),
],
body: WillPopScope(
onWillPop: () async {
if (context.read<HomeState>().tabController.index == 0) {
ActionSheetUtils.openDialog(
data: ActionSheetData(
content: const DidvanText(
'آیا قصد خروج از برنامه را دارید؟',
),
onConfirmed: () {
SystemChannels.platform.invokeMethod('SystemNavigator.pop');
},
isBackgroundDropBlur: true,
confrimTitle: 'بله',
onDismissed: Navigator.of(ActionSheetUtils.context).pop,
dismissTitle: 'خیر',
));
} else {
_tabController.animateTo(0);
}
return false;
},
child: Consumer<HomeState>(
builder: (context, state, child) => AnimatedCrossFade(
duration: DesignConfig.lowAnimationDuration,
crossFadeState: state.filtering
? CrossFadeState.showSecond
: CrossFadeState.showFirst,
firstChild: SizedBox(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: TabBarView(
physics: const NeverScrollableScrollPhysics(),
controller: _tabController,
children: const [
MainPage(),
NewStatistic(),
//Statistic(),
CategoriesPage(),
Bookmarks(),
],
),
),
secondChild: const SearchPage(),
),
secondChild: const SearchPage(),
),
),
bottomNavigationBar: Consumer<HomeState>(

View File

@ -3,7 +3,7 @@ import 'dart:async';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/views/home/new_statistic/stock/exchange.dart';
import 'package:didvan/views/home/new_statistic/stock/metal.dart';
import 'package:didvan/views/home/new_statistic/stock/newStock_state.dart';
import 'package:didvan/views/home/new_statistic/stock/new_stock_state.dart';
import 'package:didvan/views/home/new_statistic/stock/total_type3.dart';
import 'package:didvan/views/home/new_statistic/stock/total_type4.dart';
import 'package:didvan/views/home/new_statistic/stock/total_type6.dart';

View File

@ -17,8 +17,6 @@ class NewStockState extends CoreProvier {
int lastPage = 1;
List contents = [];
int? length;
int? length_type3;
int? length_type4;
Future<void> getStock({required int page}) async {
this.page = page;

View File

@ -53,8 +53,7 @@ class _MentionsState extends State<Mentions> {
bool get _isPage => widget.pageData['isPage'] != false;
void _onChange(MentionsState state, value) {
state.searchUsers = value;
void _onChange(MentionsState state, String value) {
state.getUsersMention(context.read<UserProvider>().user.id);
state.update();
}
@ -159,6 +158,7 @@ class _MentionsState extends State<Mentions> {
children: [
Expanded(
child: TextField(
controller: mentionsState.searchUsers,
focusNode: _focusNodeMention,
keyboardType: TextInputType.multiline,
textInputAction: TextInputAction.send,
@ -183,6 +183,8 @@ class _MentionsState extends State<Mentions> {
icon: DidvanIcons.close_regular,
onPressed: () {
mentionsState.showUsersForMentionsLayout = false;
mentionsState.searchUsers.text = '';
mentionsState.update();
}),
],
@ -233,12 +235,6 @@ class _MessageBoxState extends State<_MessageBox> {
@override
Widget build(BuildContext context) {
final state = context.watch<MentionsState>();
void onCheckBoxChange(bool b) {
state.hideMentionedUser = b;
state.update();
}
return Column(
children: [
AnimatedVisibility(

View File

@ -12,8 +12,8 @@ import 'package:provider/provider.dart';
class MentionsState extends CoreProvier {
TextEditingController textFieldController = TextEditingController();
TextEditingController searchUsers = TextEditingController();
List<UsersMention> mentionedUsers = [];
String searchUsers = '';
int? commentId;
UserOverview? replyingTo;
bool showReplyBox = false;
@ -51,7 +51,7 @@ class MentionsState extends CoreProvier {
Future<void> getUsersMention(int id) async {
final service = RequestService(
RequestHelper.usersMentions(searchUsers),
RequestHelper.usersMentions(searchUsers.text),
);
await service.httpGet();
@ -116,7 +116,7 @@ class MentionsState extends CoreProvier {
mentionedUsers.clear();
users.clear();
searchUsers = '';
searchUsers.text = '';
textFieldController.text = '';
showUsersForMentionsLayout = false;

View File

@ -15,7 +15,7 @@ class NotificationTimeState extends CoreProvier {
bool isAnytime = false;
bool fromFav = false;
late void Function() onTimeChanged = (){};
late void Function() onTimeChanged = () {};
Future<void> getTime() async {
appState = AppState.busy;
@ -53,15 +53,22 @@ class NotificationTimeState extends CoreProvier {
await service.put();
if (service.isSuccess) {
onTimeChanged();
Future.delayed(
Duration.zero,
() {
if (fromFav) {
Navigator.of(context).pop();
Navigator.of(context).pop();
Navigator.of(context).pop();
} else {
Navigator.of(context).pop();
}
},
);
if (fromFav) {
Navigator.of(context).pop();
Navigator.of(context).pop();
Navigator.of(context).pop();
} else {
Navigator.of(context).pop();
}
ActionSheetUtils.showAlert(AlertData(message: "تغییرات شما با موفقیت اعمال شد.",aLertType: ALertType.success));
ActionSheetUtils.showAlert(AlertData(
message: "تغییرات شما با موفقیت اعمال شد.",
aLertType: ALertType.success));
appState = AppState.idle;
return;

View File

@ -1,6 +1,7 @@
// ignore_for_file: use_build_context_synchronously
// ignore_for_file: use_build_context_synchronously, deprecated_member_use
import 'package:better_player/better_player.dart';
import 'package:chewie/chewie.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/models/view/app_bar_data.dart';
import 'package:didvan/services/media/media.dart';
import 'package:didvan/views/podcasts/studio_details/studio_details_state.dart';
@ -11,6 +12,7 @@ import 'package:didvan/views/widgets/state_handlers/state_handler.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:didvan/routes/routes.dart';
import 'package:video_player/video_player.dart';
class StudioDetails extends StatefulWidget {
final Map<String, dynamic> pageData;
@ -23,18 +25,17 @@ class StudioDetails extends StatefulWidget {
class _StudioDetailsState extends State<StudioDetails> {
int _currentlyPlayingId = 0;
late BetterPlayerController _betterPlayerController;
late VideoPlayerController _videoPlayerController;
late final ChewieController _chewieController = ChewieController(
videoPlayerController: _videoPlayerController,
autoPlay: true,
looping: true,
aspectRatio: 16 / 9,
materialProgressColors: ChewieProgressColors(
playedColor: Theme.of(context).colorScheme.title,
handleColor: Theme.of(context).colorScheme.title));
@override
void initState() {
_betterPlayerController = BetterPlayerController(
const BetterPlayerConfiguration(
aspectRatio: 16 / 9,
showPlaceholderUntilPlay: true,
autoDispose: false,
fullScreenAspectRatio: 16 / 9,
),
);
final state = context.read<StudioDetailsState>();
state.args = widget.pageData['args'];
@ -115,7 +116,12 @@ class _StudioDetailsState extends State<StudioDetails> {
height: d.size.height - d.padding.top - 56,
child: Column(
children: [
BetterPlayer(controller: _betterPlayerController),
AspectRatio(
aspectRatio: 16 / 9,
child: Chewie(
controller: _chewieController,
),
),
Expanded(
child: StudioDetailsWidget(
onMarkChanged: (id, value) => widget
@ -135,29 +141,17 @@ class _StudioDetailsState extends State<StudioDetails> {
}
Future<void> _handleVideoPlayback(state) async {
final betterPlayerDataSource = BetterPlayerDataSource(
BetterPlayerDataSourceType.network,
_videoPlayerController = VideoPlayerController.network(
state.studio.link,
videoFormat: BetterPlayerVideoFormat.hls,
);
await _betterPlayerController.clearCache();
await _betterPlayerController.setupDataSource(betterPlayerDataSource);
_betterPlayerController.setBetterPlayerControlsConfiguration(
BetterPlayerControlsConfiguration(
enablePlaybackSpeed: false,
enableSubtitles: false,
enableAudioTracks: false,
progressBarPlayedColor: Theme.of(context).colorScheme.secondary,
progressBarHandleColor: Theme.of(context).colorScheme.secondary,
),
);
)..initialize().then((value) async {});
_currentlyPlayingId = state.studio.id;
}
@override
void dispose() {
_betterPlayerController.pause();
_betterPlayerController.dispose();
_videoPlayerController.pause();
_videoPlayerController.dispose();
_chewieController.dispose();
super.dispose();
}
}

View File

@ -1,3 +1,5 @@
// ignore_for_file: deprecated_member_use
import 'dart:ui' as ui;
import 'package:didvan/models/view/app_bar_data.dart';

View File

@ -126,7 +126,7 @@ class StudioDetailsState extends CoreProvier {
// MediaService.resetAudioPlayer();
update();
appState = AppState.idle;
rethrow;
// rethrow;
}
}
@ -148,7 +148,7 @@ class StudioDetailsState extends CoreProvier {
);
if (nextStudio != null && !_positionListenerActivated) {
_positionListenerActivated = true;
MediaService.audioPlayer.currentPosition.listen((event) {
MediaService.audioPlayer.positionStream.listen((event) {
if (MediaService.audioPlayerTag?.contains('message') == true) {
return;
}

View File

@ -1,3 +1,5 @@
// ignore_for_file: deprecated_member_use
import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';

View File

@ -1,15 +1,10 @@
import 'package:day_night_time_picker/lib/constants.dart';
import 'package:day_night_time_picker/lib/daynight_timepicker.dart';
import 'package:day_night_time_picker/lib/state/time.dart';
import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/constants/assets.dart';
import 'package:didvan/models/view/action_sheet_data.dart';
import 'package:didvan/models/view/app_bar_data.dart';
import 'package:didvan/providers/theme.dart';
import 'package:didvan/utils/action_sheet.dart';
import 'package:didvan/utils/date_time.dart';
import 'package:didvan/views/profile/general_settings/settings_state.dart';
import 'package:didvan/views/widgets/menu_item.dart';
import 'package:didvan/views/widgets/didvan/card.dart';
@ -40,9 +35,6 @@ class _GeneralSettingsState extends State<GeneralSettings> {
return 'کوچک';
}
int _intervalStart = 0;
int _intervalEnd = 24;
@override
void initState() {
super.initState();
@ -230,91 +222,6 @@ class _GeneralSettingsState extends State<GeneralSettings> {
);
}
Future<void> _pickTimeRange(BuildContext context) async {
final state = context.read<GeneralSettingsState>();
_intervalStart = state.notificationTimeRange[0];
_intervalEnd = state.notificationTimeRange[1];
ActionSheetUtils.showBottomSheet(
data: ActionSheetData(
content: Row(
children: [
const SizedBox(width: 8),
Expanded(child: _timeFieldBuilder(context, 0)),
const SizedBox(width: 8),
const DidvanText('-'),
const SizedBox(width: 8),
Expanded(child: _timeFieldBuilder(context, 1)),
const SizedBox(width: 8),
],
),
title: 'زمان دریافت اعلان',
titleIcon: DidvanIcons.notification_regular,
onConfirmed: () {
state.notificationTimeRange = [_intervalStart, _intervalEnd];
},
),
);
}
Widget _timeFieldBuilder(BuildContext context, int index) {
final GeneralSettingsState state = context.read<GeneralSettingsState>();
return ChangeNotifierProvider.value(
value: state,
child: StatefulBuilder(
builder: (context, setState) => GestureDetector(
onTap: () async {
await _openTimePicker(context, index);
setState(() {});
},
child: Container(
alignment: Alignment.center,
padding: const EdgeInsets.all(24),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.splash,
borderRadius: DesignConfig.mediumBorderRadius,
border: Border.all(
color: Theme.of(context).colorScheme.border,
),
),
child: DidvanText(DateTimeUtils.normalizeTimeDuration(
Duration(minutes: index == 0 ? _intervalStart : _intervalEnd),
)),
),
),
),
);
}
Future<void> _openTimePicker(BuildContext context, int index) async {
await Navigator.of(context).push(
showPicker(
okText: 'تایید',
cancelText: 'بازگشت',
accentColor: Theme.of(context).colorScheme.primary,
okStyle: Theme.of(context).textTheme.bodyMedium!,
cancelStyle: Theme.of(context).textTheme.bodyMedium!,
unselectedColor: Theme.of(context).colorScheme.text,
blurredBackground: true,
disableMinute: true,
hourLabel: ':',
minuteLabel: '',
is24HrFormat: true,
iosStylePicker: true,
minuteInterval: TimePickerInterval.FIFTEEN,
context: context,
value: Time(hour: 0, minute: 0),
themeData: Theme.of(context),
onChange: (time) {
if (index == 0) {
_intervalStart = time.hour;
return;
}
_intervalEnd = time.hour;
},
),
);
}
Widget _themeItem(
BuildContext context, GeneralSettingsState state, String brightness) {
final bool isDarkTheme = brightness == 'dark';

View File

@ -1,7 +1,6 @@
import 'dart:async';
import 'dart:math';
import 'package:assets_audio_player/assets_audio_player.dart';
import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
@ -21,6 +20,7 @@ import 'package:didvan/views/widgets/ink_wrapper.dart';
import 'package:didvan/views/widgets/item_title.dart';
import 'package:didvan/views/widgets/skeleton_image.dart';
import 'package:flutter/material.dart';
import 'package:just_audio/just_audio.dart';
import 'package:provider/provider.dart';
class AudioPlayerWidget extends StatelessWidget {
@ -59,10 +59,55 @@ class AudioPlayerWidget extends StatelessWidget {
const SizedBox(height: 16),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: AudioSlider(
tag: 'podcast-${podcast.id}',
showTimer: true,
duration: podcast.duration,
child: Row(
children: [
StreamBuilder<double>(
stream: MediaService.audioPlayer.speedStream,
builder: (context, snapshot) {
if (!snapshot.hasData) {
return const SizedBox();
}
return Column(
children: [
PopupMenuButton(
child: Container(
width: 46,
alignment: Alignment.center,
margin: const EdgeInsets.fromLTRB(12, 0, 0, 46),
padding: const EdgeInsets.only(top: 2),
decoration: BoxDecoration(
borderRadius: DesignConfig.mediumBorderRadius,
border: Border.all(
color:
Theme.of(context).colorScheme.title)),
child: DidvanText(
'${snapshot.data!.toString().replaceAll('.0', '')}X'),
),
onSelected: (value) async {
await MediaService.audioPlayer.setSpeed(value);
},
itemBuilder: (BuildContext context) =>
<PopupMenuEntry>[
popUpSpeed(value: 0.5),
popUpSpeed(value: 0.75),
popUpSpeed(value: 1.0),
popUpSpeed(value: 1.25),
popUpSpeed(value: 1.5),
popUpSpeed(value: 2.0),
],
),
],
);
}),
Expanded(
child: AudioSlider(
tag: 'podcast-${podcast.id}',
showTimer: true,
duration: podcast.duration,
),
),
],
),
),
Row(
@ -108,9 +153,9 @@ class AudioPlayerWidget extends StatelessWidget {
onPressed: () {
MediaService.audioPlayer.seek(
Duration(
seconds: MediaService.audioPlayer.currentPosition
.value.inSeconds +
30,
seconds:
MediaService.audioPlayer.position.inSeconds +
30,
),
);
},
@ -126,14 +171,14 @@ class AudioPlayerWidget extends StatelessWidget {
),
Expanded(
child: Center(
child: StreamBuilder<PlayingAudio?>(
stream: MediaService.audioPlayer.onReadyToPlay,
child: StreamBuilder<PlayerState>(
stream: MediaService.audioPlayer.playerStateStream,
builder: (context, snapshot) {
if (snapshot.data == null) {
return const CircularProgressIndicator();
}
return StreamBuilder<bool>(
stream: MediaService.audioPlayer.isPlaying,
stream: MediaService.audioPlayer.playingStream,
builder: (context, snapshot) {
return _PlayPouseAnimatedIcon(
audioSource: podcast.link,
@ -158,8 +203,7 @@ class AudioPlayerWidget extends StatelessWidget {
Duration(
seconds: max(
0,
MediaService.audioPlayer.currentPosition.value
.inSeconds -
MediaService.audioPlayer.position.inSeconds -
10,
),
),
@ -196,6 +240,16 @@ class AudioPlayerWidget extends StatelessWidget {
);
}
PopupMenuItem<dynamic> popUpSpeed({required double value}) {
return PopupMenuItem(
value: value,
height: 32,
child: DidvanText(
'${value}X',
),
);
}
Future<void> _showSleepTimer(StudioDetailsState state, update) async {
int timerValue = 10;
final controller = FixedExtentScrollController();
@ -271,8 +325,7 @@ class AudioPlayerWidget extends StatelessWidget {
title: 'پایان پادکست',
onPressed: () async {
state.timerValue = MediaService.duration!.inMinutes -
MediaService
.audioPlayer.currentPosition.value.inMinutes;
MediaService.audioPlayer.position.inMinutes;
await controller.animateTo(
state.timerValue * 10,
duration: DesignConfig.lowAnimationDuration,
@ -351,7 +404,7 @@ class __PlayPouseAnimatedIconState extends State<_PlayPouseAnimatedIcon>
}
void _handleAnimation() {
if (MediaService.audioPlayer.isPlaying.value) {
if (MediaService.audioPlayer.playing) {
_animationController.forward();
} else {
_animationController.reverse();

View File

@ -26,33 +26,39 @@ class AudioSlider extends StatelessWidget {
child: Directionality(
textDirection: TextDirection.ltr,
child: StreamBuilder<Duration>(
stream:
_isPlaying && MediaService.audioPlayer.currentPosition.hasValue
? MediaService.audioPlayer.currentPosition
: null,
builder: (context, snapshot) => ProgressBar(
thumbColor: Theme.of(context).colorScheme.title,
progressBarColor: DesignConfig.isDark
? Theme.of(context).colorScheme.title
: Theme.of(context).colorScheme.primary,
baseBarColor: Theme.of(context).colorScheme.border,
bufferedBarColor: Theme.of(context).colorScheme.splash,
total: Duration(
seconds: duration ?? MediaService.duration?.inSeconds ?? 0),
progress: snapshot.data ?? Duration.zero,
thumbRadius: disableThumb ? 0 : 6,
barHeight: 3,
timeLabelTextStyle: TextStyle(
fontSize: showTimer ? null : 0,
height: showTimer ? 3 : 0,
color: Theme.of(context).colorScheme.text,
fontFamily: DesignConfig.fontFamily.replaceAll(
'-FA',
'',
),
),
onSeek: (value) => _onSeek(value.inMilliseconds),
),
stream: _isPlaying ? MediaService.audioPlayer.positionStream : null,
builder: (context, snapshot) {
return Row(
children: [
Expanded(
child: ProgressBar(
thumbColor: Theme.of(context).colorScheme.title,
progressBarColor: DesignConfig.isDark
? Theme.of(context).colorScheme.title
: Theme.of(context).colorScheme.primary,
baseBarColor: Theme.of(context).colorScheme.border,
bufferedBarColor: Theme.of(context).colorScheme.splash,
total: Duration(
seconds:
duration ?? MediaService.duration?.inSeconds ?? 0),
progress: snapshot.data ?? Duration.zero,
thumbRadius: disableThumb ? 0 : 6,
barHeight: 3,
timeLabelTextStyle: TextStyle(
fontSize: showTimer ? null : 0,
height: showTimer ? 3 : 0,
color: Theme.of(context).colorScheme.text,
fontFamily: DesignConfig.fontFamily.replaceAll(
'-FA',
'',
),
),
onSeek: (value) => _onSeek(value.inMilliseconds),
),
),
],
);
},
),
),
);

View File

@ -1,7 +1,5 @@
import 'package:assets_audio_player/assets_audio_player.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:expandable_bottom_sheet/expandable_bottom_sheet.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:provider/provider.dart';
@ -39,7 +37,7 @@ class _PlayerNavBarState extends State<PlayerNavBar> {
@override
Widget build(BuildContext context) {
return StreamBuilder<bool>(
stream: MediaService.audioPlayer.isPlaying,
stream: MediaService.audioPlayer.playingStream,
builder: (context, isPlaying) => GestureDetector(
onTap: () => (MediaService.currentPodcast == null &&
(MediaService.audioPlayerTag ?? '')

View File

@ -1,26 +1,8 @@
import 'package:assets_audio_player/assets_audio_player.dart';
import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/models/enums.dart';
import 'package:didvan/models/requests/radar.dart';
import 'package:didvan/routes/routes.dart';
import 'package:didvan/services/media/media.dart';
import 'package:didvan/utils/action_sheet.dart';
import 'package:didvan/views/podcasts/studio_details/studio_details_state.dart';
import 'package:didvan/views/podcasts/studio_details/widgets/studio_details_widget.dart';
import 'package:didvan/views/podcasts/podcasts_state.dart';
import 'package:didvan/views/widgets/audio/audio_player_widget.dart';
import 'package:didvan/views/widgets/audio/audio_slider.dart';
import 'package:didvan/views/widgets/didvan/icon_button.dart';
import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:didvan/views/widgets/skeleton_image.dart';
import 'package:expandable_bottom_sheet/expandable_bottom_sheet.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:provider/provider.dart';
import '../audio/player_navbar.dart';
@ -36,7 +18,9 @@ class DidvanBNB extends StatelessWidget {
Widget build(BuildContext context) {
return Stack(
children: [
const PlayerNavBar(inHome: true,),
const PlayerNavBar(
inHome: true,
),
Positioned(
bottom: 0,
left: 0,
@ -96,7 +80,6 @@ class DidvanBNB extends StatelessWidget {
}
}
class _NavBarItem extends StatelessWidget {
final VoidCallback onTap;
final bool isSelected;

View File

@ -1,26 +1,6 @@
import 'package:assets_audio_player/assets_audio_player.dart';
import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/models/enums.dart';
import 'package:didvan/models/requests/radar.dart';
import 'package:didvan/models/view/app_bar_data.dart';
import 'package:didvan/routes/routes.dart';
import 'package:didvan/services/media/media.dart';
import 'package:didvan/utils/action_sheet.dart';
import 'package:didvan/views/widgets/audio/audio_player_widget.dart';
import 'package:didvan/views/widgets/audio/audio_slider.dart';
import 'package:didvan/views/podcasts/podcasts_state.dart';
import 'package:didvan/views/podcasts/studio_details/studio_details_state.dart';
import 'package:didvan/views/podcasts/studio_details/widgets/studio_details_widget.dart';
import 'package:didvan/views/widgets/didvan/app_bar.dart';
import 'package:didvan/views/widgets/didvan/icon_button.dart';
import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:didvan/views/widgets/skeleton_image.dart';
import 'package:expandable_bottom_sheet/expandable_bottom_sheet.dart';
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:provider/provider.dart';
import '../audio/player_navbar.dart';
@ -87,7 +67,7 @@ class _DidvanScaffoldState extends State<DidvanScaffold> {
child: SizedBox(
height: MediaQuery.of(context).size.height -
statusBarHeight -
systemNavigationBarHeight ,
systemNavigationBarHeight,
child: Stack(
children: [
CustomScrollView(
@ -145,7 +125,7 @@ class _DidvanScaffoldState extends State<DidvanScaffold> {
12,
),
),
if(!widget.hidePlayer)
if (!widget.hidePlayer)
const SliverPadding(padding: EdgeInsets.only(bottom: 90))
],
),

View File

@ -1,3 +1,5 @@
// ignore_for_file: prefer_typing_uninitialized_variables, library_private_types_in_public_api
import 'package:flutter/material.dart';
class NotificationDynamicDialog extends StatefulWidget {
@ -5,7 +7,8 @@ class NotificationDynamicDialog extends StatefulWidget {
final body;
const NotificationDynamicDialog({super.key, this.title, this.body});
@override
_NotificationDynamicDialogState createState() => _NotificationDynamicDialogState();
_NotificationDynamicDialogState createState() =>
_NotificationDynamicDialogState();
}
class _NotificationDynamicDialogState extends State<NotificationDynamicDialog> {
@ -27,4 +30,3 @@ class _NotificationDynamicDialogState extends State<NotificationDynamicDialog> {
);
}
}

View File

@ -5,10 +5,10 @@ packages:
dependency: transitive
description:
name: _flutterfire_internals
sha256: "37a42d06068e2fe3deddb2da079a8c4d105f241225ba27b7122b37e9865fd8f7"
sha256: b1595874fbc8f7a50da90f5d8f327bb0bfd6a95dc906c390efe991540c3b54aa
url: "https://pub.dev"
source: hosted
version: "1.3.35"
version: "1.3.40"
android_intent_plus:
dependency: "direct main"
description:
@ -41,22 +41,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.5.0"
assets_audio_player:
dependency: "direct main"
description:
name: assets_audio_player
sha256: "9a87062cf39be0730ba8bb31ed4d148ca4e892e0ae607113f346d3c9a8da5df0"
url: "https://pub.dev"
source: hosted
version: "3.1.1"
assets_audio_player_web:
dependency: transitive
description:
name: assets_audio_player_web
sha256: "24cf82e72c7e7f9292d67e1b52d7945a182d9695ce8f903f60e5c6b379cbcaac"
url: "https://pub.dev"
source: hosted
version: "3.1.1"
async:
dependency: transitive
description:
@ -65,6 +49,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.11.0"
audio_session:
dependency: transitive
description:
name: audio_session
sha256: "343e83bc7809fbda2591a49e525d6b63213ade10c76f15813be9aed6657b3261"
url: "https://pub.dev"
source: hosted
version: "0.1.21"
audio_video_progress_bar:
dependency: "direct main"
description:
@ -73,62 +65,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.3"
audioplayers:
dependency: "direct main"
description:
name: audioplayers
sha256: "752039d6aa752597c98ec212e9759519061759e402e7da59a511f39d43aa07d2"
url: "https://pub.dev"
source: hosted
version: "6.0.0"
audioplayers_android:
dependency: transitive
description:
name: audioplayers_android
sha256: de576b890befe27175c2f511ba8b742bec83765fa97c3ce4282bba46212f58e4
url: "https://pub.dev"
source: hosted
version: "5.0.0"
audioplayers_darwin:
dependency: transitive
description:
name: audioplayers_darwin
sha256: e507887f3ff18d8e5a10a668d7bedc28206b12e10b98347797257c6ae1019c3b
url: "https://pub.dev"
source: hosted
version: "6.0.0"
audioplayers_linux:
dependency: transitive
description:
name: audioplayers_linux
sha256: "3d3d244c90436115417f170426ce768856d8fe4dfc5ed66a049d2890acfa82f9"
url: "https://pub.dev"
source: hosted
version: "4.0.0"
audioplayers_platform_interface:
dependency: transitive
description:
name: audioplayers_platform_interface
sha256: "6834dd48dfb7bc6c2404998ebdd161f79cd3774a7e6779e1348d54a3bfdcfaa5"
url: "https://pub.dev"
source: hosted
version: "7.0.0"
audioplayers_web:
dependency: transitive
description:
name: audioplayers_web
sha256: db8fc420dadf80da18e2286c18e746fb4c3b2c5adbf0c963299dde046828886d
url: "https://pub.dev"
source: hosted
version: "5.0.0"
audioplayers_windows:
dependency: transitive
description:
name: audioplayers_windows
sha256: "8605762dddba992138d476f6a0c3afd9df30ac5b96039929063eceed416795c2"
url: "https://pub.dev"
source: hosted
version: "4.0.0"
awesome_notifications:
dependency: "direct main"
description:
@ -137,23 +73,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.8.2"
awesome_notifications_core:
dependency: "direct main"
description:
name: awesome_notifications_core
sha256: "38c9f9d2618c0c2abe0cea267dc161aa8c4a0a239ca2263400900b9610f33e6f"
url: "https://pub.dev"
source: hosted
version: "0.9.3"
better_player:
dependency: "direct main"
description:
path: "."
ref: HEAD
resolved-ref: "91a9625524cdff448e0a9deb5047bcf20cc8dcf1"
url: "https://github.com/tintran-dev/betterplayer.git"
source: git
version: "0.0.83"
boolean_selector:
dependency: transitive
description:
@ -218,6 +137,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.3.1"
chewie:
dependency: "direct main"
description:
name: chewie
sha256: "2243e41e79e865d426d9dd9c1a9624aa33c4ad11de2d0cd680f826e2cd30e879"
url: "https://pub.dev"
source: hosted
version: "1.8.3"
clock:
dependency: transitive
description:
@ -354,78 +281,54 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.9.3+1"
firebase_auth:
dependency: "direct main"
description:
name: firebase_auth
sha256: cfc2d970829202eca09e2896f0a5aa7c87302817ecc0bdfa954f026046bf10ba
url: "https://pub.dev"
source: hosted
version: "4.20.0"
firebase_auth_platform_interface:
dependency: transitive
description:
name: firebase_auth_platform_interface
sha256: a0270e1db3b2098a14cb2a2342b3cd2e7e458e0c391b1f64f6f78b14296ec093
url: "https://pub.dev"
source: hosted
version: "7.3.0"
firebase_auth_web:
dependency: transitive
description:
name: firebase_auth_web
sha256: "64e067e763c6378b7e774e872f0f59f6812885e43020e25cde08f42e9459837b"
url: "https://pub.dev"
source: hosted
version: "5.12.0"
firebase_core:
dependency: "direct main"
description:
name: firebase_core
sha256: "26de145bb9688a90962faec6f838247377b0b0d32cc0abecd9a4e43525fc856c"
sha256: "3187f4f8e49968573fd7403011dca67ba95aae419bc0d8131500fae160d94f92"
url: "https://pub.dev"
source: hosted
version: "2.32.0"
version: "3.3.0"
firebase_core_platform_interface:
dependency: transitive
description:
name: firebase_core_platform_interface
sha256: "1003a5a03a61fc9a22ef49f37cbcb9e46c86313a7b2e7029b9390cf8c6fc32cb"
sha256: "3c3a1e92d6f4916c32deea79c4a7587aa0e9dbbe5889c7a16afcf005a485ee02"
url: "https://pub.dev"
source: hosted
version: "5.1.0"
version: "5.2.0"
firebase_core_web:
dependency: transitive
description:
name: firebase_core_web
sha256: "6643fe3dbd021e6ccfb751f7882b39df355708afbdeb4130fc50f9305a9d1a3d"
sha256: e8d1e22de72cb21cdcfc5eed7acddab3e99cd83f3b317f54f7a96c32f25fd11e
url: "https://pub.dev"
source: hosted
version: "2.17.2"
version: "2.17.4"
firebase_messaging:
dependency: "direct main"
description:
name: firebase_messaging
sha256: a1662cc95d9750a324ad9df349b873360af6f11414902021f130c68ec02267c4
sha256: "1b0a4f9ecbaf9007771bac152afad738ddfacc4b8431a7591c00829480d99553"
url: "https://pub.dev"
source: hosted
version: "14.9.4"
version: "15.0.4"
firebase_messaging_platform_interface:
dependency: transitive
description:
name: firebase_messaging_platform_interface
sha256: "87c4a922cb6f811cfb7a889bdbb3622702443c52a0271636cbc90d813ceac147"
sha256: c5a6443e66ae064fe186901d740ee7ce648ca2a6fd0484b8c5e963849ac0fc28
url: "https://pub.dev"
source: hosted
version: "4.5.37"
version: "4.5.42"
firebase_messaging_web:
dependency: transitive
description:
name: firebase_messaging_web
sha256: "0d34dca01a7b103ed7f20138bffbb28eb0e61a677bf9e78a028a932e2c7322d5"
sha256: "232ef63b986467ae5b5577a09c2502b26e2e2aebab5b85e6c966a5ca9b038b89"
url: "https://pub.dev"
source: hosted
version: "3.8.7"
version: "3.8.12"
fl_chart:
dependency: "direct main"
description:
@ -463,30 +366,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.3"
flutter_local_notifications:
dependency: "direct main"
description:
name: flutter_local_notifications
sha256: ced76d337f54de33d7d9f06092137b4ac2da5079e00cee8a11a1794ffc7c61c6
url: "https://pub.dev"
source: hosted
version: "17.2.1"
flutter_local_notifications_linux:
dependency: transitive
description:
name: flutter_local_notifications_linux
sha256: "33f741ef47b5f63cc7f78fe75eeeac7e19f171ff3c3df054d84c1e38bedb6a03"
url: "https://pub.dev"
source: hosted
version: "4.0.0+1"
flutter_local_notifications_platform_interface:
dependency: transitive
description:
name: flutter_local_notifications_platform_interface
sha256: "85f8d07fe708c1bdcf45037f2c0109753b26ae077e9d9e899d55971711a4ea66"
url: "https://pub.dev"
source: hosted
version: "7.2.0"
flutter_localizations:
dependency: "direct main"
description: flutter
@ -582,22 +461,6 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_widget_from_html_core:
dependency: transitive
description:
name: flutter_widget_from_html_core
sha256: e8f4f8b461a140ffb7c71f938bc76efc758893e7468843d9dbf70cb0b9e900cb
url: "https://pub.dev"
source: hosted
version: "0.8.5+3"
fwfh_text_style:
dependency: transitive
description:
name: fwfh_text_style
sha256: "5f8b587fd223a6bf14aad3d3da5e7ced0628becbd0768f8e7ae25ff6b9f3d2ec"
url: "https://pub.dev"
source: hosted
version: "2.23.8"
get:
dependency: "direct main"
description:
@ -734,6 +597,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.6.7"
just_audio:
dependency: "direct main"
description:
name: just_audio
sha256: ee50602364ba83fa6308f5512dd560c713ec3e1f2bc75f0db43618f0d82ef71a
url: "https://pub.dev"
source: hosted
version: "0.9.39"
just_audio_platform_interface:
dependency: transitive
description:
name: just_audio_platform_interface
sha256: "0243828cce503c8366cc2090cefb2b3c871aa8ed2f520670d76fd47aa1ab2790"
url: "https://pub.dev"
source: hosted
version: "4.3.0"
just_audio_web:
dependency: transitive
description:
name: just_audio_web
sha256: "0edb481ad4aa1ff38f8c40f1a3576013c3420bf6669b686fe661627d49bc606c"
url: "https://pub.dev"
source: hosted
version: "0.4.11"
leak_tracker:
dependency: transitive
description:
@ -822,6 +709,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.0"
package_info_plus:
dependency: transitive
description:
name: package_info_plus
sha256: a75164ade98cb7d24cfd0a13c6408927c6b217fa60dee5a7ff5c116a58f28918
url: "https://pub.dev"
source: hosted
version: "8.0.2"
package_info_plus_platform_interface:
dependency: transitive
description:
name: package_info_plus_platform_interface
sha256: ac1f4a4847f1ade8e6a87d1f39f5d7c67490738642e2542f559ec38c37489a66
url: "https://pub.dev"
source: hosted
version: "3.0.1"
path:
dependency: transitive
description:
@ -1147,14 +1050,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.6.1"
timezone:
dependency: transitive
description:
name: timezone
sha256: a6ccda4a69a442098b602c44e61a1e2b4bf6f5516e875bbf0f427d5df14745d5
url: "https://pub.dev"
source: hosted
version: "0.9.3"
toggle_switch:
dependency: "direct main"
description:
@ -1291,14 +1186,46 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.4"
visibility_detector:
dependency: transitive
video_player:
dependency: "direct main"
description:
name: visibility_detector
sha256: "15c54a459ec2c17b4705450483f3d5a2858e733aee893dcee9d75fd04814940d"
name: video_player
sha256: e30df0d226c4ef82e2c150ebf6834b3522cf3f654d8e2f9419d376cdc071425d
url: "https://pub.dev"
source: hosted
version: "0.3.3"
version: "2.9.1"
video_player_android:
dependency: transitive
description:
name: video_player_android
sha256: "134e1ad410d67e18a19486ed9512c72dfc6d8ffb284d0e8f2e99e903d1ba8fa3"
url: "https://pub.dev"
source: hosted
version: "2.4.14"
video_player_avfoundation:
dependency: transitive
description:
name: video_player_avfoundation
sha256: d1e9a824f2b324000dc8fb2dcb2a3285b6c1c7c487521c63306cc5b394f68a7c
url: "https://pub.dev"
source: hosted
version: "2.6.1"
video_player_platform_interface:
dependency: transitive
description:
name: video_player_platform_interface
sha256: "236454725fafcacf98f0f39af0d7c7ab2ce84762e3b63f2cbb3ef9a7e0550bc6"
url: "https://pub.dev"
source: hosted
version: "6.2.2"
video_player_web:
dependency: transitive
description:
name: video_player_web
sha256: "6dcdd298136523eaf7dfc31abaf0dfba9aa8a8dbc96670e87e9d42b6f2caf774"
url: "https://pub.dev"
source: hosted
version: "2.3.2"
vm_service:
dependency: transitive
description:
@ -1307,46 +1234,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "13.0.0"
wakelock:
wakelock_plus:
dependency: transitive
description:
name: wakelock
sha256: "769ecf42eb2d07128407b50cb93d7c10bd2ee48f0276ef0119db1d25cc2f87db"
name: wakelock_plus
sha256: bf4ee6f17a2fa373ed3753ad0e602b7603f8c75af006d5b9bdade263928c0484
url: "https://pub.dev"
source: hosted
version: "0.6.2"
wakelock_macos:
version: "1.2.8"
wakelock_plus_platform_interface:
dependency: transitive
description:
name: wakelock_macos
sha256: "047c6be2f88cb6b76d02553bca5a3a3b95323b15d30867eca53a19a0a319d4cd"
name: wakelock_plus_platform_interface
sha256: "422d1cdbb448079a8a62a5a770b69baa489f8f7ca21aef47800c726d404f9d16"
url: "https://pub.dev"
source: hosted
version: "0.4.0"
wakelock_platform_interface:
dependency: transitive
description:
name: wakelock_platform_interface
sha256: "1f4aeb81fb592b863da83d2d0f7b8196067451e4df91046c26b54a403f9de621"
url: "https://pub.dev"
source: hosted
version: "0.3.0"
wakelock_web:
dependency: transitive
description:
name: wakelock_web
sha256: "1b256b811ee3f0834888efddfe03da8d18d0819317f20f6193e2922b41a501b5"
url: "https://pub.dev"
source: hosted
version: "0.4.0"
wakelock_windows:
dependency: transitive
description:
name: wakelock_windows
sha256: "857f77b3fe6ae82dd045455baa626bc4b93cb9bb6c86bf3f27c182167c3a5567"
url: "https://pub.dev"
source: hosted
version: "0.2.1"
version: "1.2.1"
web:
dependency: transitive
description:
@ -1391,10 +1294,10 @@ packages:
dependency: transitive
description:
name: win32
sha256: a6f0236dbda0f63aa9a25ad1ff9a9d8a4eaaa5012da0dc59d21afdb1dc361ca4
sha256: "0eaf06e3446824099858367950a813472af675116bf63f008a4c2a75ae13e9cb"
url: "https://pub.dev"
source: hosted
version: "3.1.4"
version: "5.5.0"
xdg_directories:
dependency: transitive
description:

View File

@ -61,15 +61,15 @@ dependencies:
url_launcher: ^6.0.18
audio_video_progress_bar: ^2.0.0
image_cropper: ^1.5.0
firebase_messaging: ^14.1.3
firebase_core: ^2.3.0
firebase_core: ^3.1.0
firebase_messaging: ^15.0.1
webview_flutter: ^4.2.0
expandable_bottom_sheet: ^1.1.1+1
permission_handler: ^11.0.0
better_player:
git:
url: https://github.com/tintran-dev/betterplayer.git
assets_audio_player: ^3.1.1
# better_player:
# git:
# url: https://github.com/tintran-dev/betterplayer.git
# assets_audio_player: ^3.1.1
fl_chart: ^0.63.0
collection: ^1.17.2
animated_custom_dropdown: ^3.0.0
@ -78,14 +78,15 @@ dependencies:
http: any
http_parser: any
cached_network_image_platform_interface: any
flutter_local_notifications: ^17.1.2
awesome_notifications_core: ^0.9.0
awesome_notifications: any
awesome_notifications: ^0.8.2
home_widget: ^0.5.0
android_intent_plus: ^5.0.0
get: ^4.6.6
firebase_auth: ^4.19.6
audioplayers: ^6.0.0
# firebase_auth: ^4.19.6
just_audio: ^0.9.39
video_player: ^2.8.7
chewie: ^1.8.3
# onesignal_flutter: ^3.5.0
dev_dependencies:
flutter_test: