upgrade dependencies and gradle

main
htylight 2024-03-16 12:15:13 +08:00
parent 9d0a3eebf5
commit ecd1e8d052
18 changed files with 549 additions and 1000 deletions

View File

@ -1,3 +1,9 @@
plugins {
id "com.android.application"
id "kotlin-android"
id "dev.flutter.flutter-gradle-plugin"
}
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
@ -6,10 +12,10 @@ if (localPropertiesFile.exists()) {
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
//def flutterRoot = localProperties.getProperty('flutter.sdk')
//if (flutterRoot == null) {
// throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
//}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
@ -21,9 +27,9 @@ if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
//apply plugin: 'com.android.application'
//apply plugin: 'kotlin-android'
//apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
namespace "com.example.together_mobile"
@ -31,7 +37,7 @@ android {
// flutter_local_notifications needed:
// The 33 (Android 13) is minimal version to display a prompt to ask
// notification permission
compileSdkVersion 33
compileSdkVersion 34
ndkVersion flutter.ndkVersion
compileOptions {
@ -61,7 +67,7 @@ android {
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
// minSdkVersion flutter.minSdkVersion
// device_info_plugin requires a higher android sdk version
minSdkVersion 19
minSdkVersion 21
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
@ -83,8 +89,8 @@ flutter {
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
// flutter_local_notifications: solve the problem that enabling desugaring
// implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
// flutter_local_notifications: solve the problem that enabling desugaring
// may result in a Flutter app crashing on Android 12L and above
// Default but also flutter_local_notifications needs
implementation 'androidx.window:window:1.0.0'

View File

@ -1,20 +1,30 @@
buildscript {
ext.kotlin_version = '1.7.10'
repositories {
google()
mavenCentral()
}
// diminish warning of "Deprecated imperative apply of Flutter's Gradle plugins"
// https://docs.flutter.dev/release/breaking-changes/flutter-gradle-plugin-apply
dependencies {
classpath 'com.android.tools.build:gradle:7.4.2'
// flutter_local_notifications
// classpath 'com.android.tools.build:gradle:4.2.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
//buildscript {
// ext.kotlin_version = '1.7.10'
// repositories {
// google()
// mavenCentral()
// }
//
// dependencies {
// classpath 'com.android.tools.build:gradle:7.4.2'
// // flutter_local_notifications
// // classpath 'com.android.tools.build:gradle:4.2.2'
// classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// }
//}
allprojects {
repositories {
maven { url "https://jitpack.io" }
maven { url 'https://maven.aliyun.com/repository/releases' }
maven { url 'https://maven.aliyun.com/repository/jcenter' }
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://maven.aliyun.com/repository/central' }
maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
maven { url 'https://maven.aliyun.com/repository/public' }
google()
mavenCentral()
}

View File

@ -1,3 +1,7 @@
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
systemProp.https.proxyHost=127.0.0.1
systemProp.https.proxyPort=2340
systemProp.http.proxyHost=127.0.0.1
systemProp.http.proxyPort=2340

View File

@ -1,11 +1,35 @@
include ':app'
pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}()
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
def properties = new Properties()
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
assert localPropertiesFile.exists()
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
repositories {
maven { url "https://jitpack.io" }
maven { url 'https://maven.aliyun.com/repository/releases' }
maven { url 'https://maven.aliyun.com/repository/jcenter' }
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://maven.aliyun.com/repository/central' }
maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
maven { url 'https://maven.aliyun.com/repository/public' }
google()
mavenCentral()
gradlePluginPortal()
}
}
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "7.4.2" apply false
id "org.jetbrains.kotlin.android" version "1.7.10" apply false
}
include ":app"
// diminish warning of "Deprecated imperative apply of Flutter's Gradle plugins"
// https://docs.flutter.dev/release/breaking-changes/flutter-gradle-plugin-apply

View File

@ -46,8 +46,8 @@ var request = Dio(baseOptions)
}
},
onError: (DioException e, ErrorInterceptorHandler handler) {
// print('错误信息:' + e.response?.data);
// print('错误码: ${e.response?.statusCode}');
print('错误信息:' + e.response?.data);
print('错误码: ${e.response?.statusCode}');
handler.reject(e);
},
),

View File

@ -21,14 +21,14 @@ final chatRoute = GoRoute(
name: 'Message',
parentNavigatorKey: rootNavigatorKey,
builder: (context, state) {
int type = int.parse(state.queryParameters['type']!);
int type = int.parse(state.uri.queryParameters['type']!);
if (type == 0) {
return FriendMessageScreen(
friendId: state.queryParameters['friendId']!,
friendId: state.uri.queryParameters['friendId']!,
);
} else {
return GroupChatMessageScreen(
groupChatId: state.queryParameters['groupChatId']!,
groupChatId: state.uri.queryParameters['groupChatId']!,
);
}
},

View File

@ -28,8 +28,8 @@ final contactRoute = GoRoute(
path: '/contact',
name: 'Contact',
builder: (context, state) {
if (state.queryParameters.isNotEmpty) {
var deletedFriendId = state.queryParameters['deletedFriendId'];
if (state.uri.queryParameters.isNotEmpty) {
var deletedFriendId = state.uri.queryParameters['deletedFriendId'];
if (deletedFriendId != null) {
getIt.get<Contact>().removeFriend(deletedFriendId);
getIt.get<ContactAccountProfile>().removeFriend(deletedFriendId);
@ -53,7 +53,7 @@ final contactRoute = GoRoute(
parentNavigatorKey: rootNavigatorKey,
builder: (context, state) {
return AddFriendScreen(
accountProfile: state.queryParameters,
accountProfile: state.uri.queryParameters,
);
},
),
@ -79,7 +79,7 @@ final contactRoute = GoRoute(
parentNavigatorKey: rootNavigatorKey,
builder: (context, state) {
return ApplicantProfileScreen(
accountProfile: state.queryParameters,
accountProfile: state.uri.queryParameters,
);
},
),

View File

@ -33,7 +33,7 @@ final myProfileRoute = GoRoute(
return AvatarViewScreen(
isMyself: true,
avatarType: AvatarType.user,
avatar: state.queryParameters['avatar']!,
avatar: state.uri.queryParameters['avatar']!,
);
},
),
@ -70,7 +70,7 @@ final friendProfileRoute = GoRoute(
parentNavigatorKey: rootNavigatorKey,
builder: (context, state) {
return FriendProfileScreen(
friendId: state.queryParameters['friendId']!,
friendId: state.uri.queryParameters['friendId']!,
);
},
routes: [
@ -82,7 +82,7 @@ final friendProfileRoute = GoRoute(
return AvatarViewScreen(
isMyself: false,
avatarType: AvatarType.user,
avatar: state.queryParameters['avatar']!,
avatar: state.uri.queryParameters['avatar']!,
);
},
),
@ -92,7 +92,7 @@ final friendProfileRoute = GoRoute(
parentNavigatorKey: rootNavigatorKey,
builder: (context, state) {
return FriendSettingScreen(
friendId: state.queryParameters['friendId']!,
friendId: state.uri.queryParameters['friendId']!,
);
},
),
@ -105,7 +105,7 @@ final groupChatProfileRoute = GoRoute(
parentNavigatorKey: rootNavigatorKey,
builder: (context, state) {
return GroupChatProfileScreen(
groupChatId: state.queryParameters['groupChatId']!,
groupChatId: state.uri.queryParameters['groupChatId']!,
);
},
routes: [
@ -115,7 +115,7 @@ final groupChatProfileRoute = GoRoute(
parentNavigatorKey: rootNavigatorKey,
builder: (context, state) {
return GroupChatOutlineScreen(
groupChatId: state.queryParameters['groupChatId']!,
groupChatId: state.uri.queryParameters['groupChatId']!,
);
},
),
@ -125,7 +125,7 @@ final groupChatProfileRoute = GoRoute(
parentNavigatorKey: rootNavigatorKey,
builder: (context, state) {
return InviteGroupChatMemberScreen(
groupChatId: state.queryParameters['groupChatId']!,
groupChatId: state.uri.queryParameters['groupChatId']!,
);
},
),
@ -135,7 +135,7 @@ final groupChatProfileRoute = GoRoute(
parentNavigatorKey: rootNavigatorKey,
builder: (context, state) {
return ChangeGroupChatAvatarScreen(
groupChatId: state.queryParameters['groupChatId']!,
groupChatId: state.uri.queryParameters['groupChatId']!,
);
},
),
@ -145,8 +145,8 @@ final groupChatProfileRoute = GoRoute(
parentNavigatorKey: rootNavigatorKey,
builder: (context, state) {
return ChangeGroupChatNameScreen(
groupChatId: state.queryParameters['groupChatId']!,
name: state.queryParameters['name']!,
groupChatId: state.uri.queryParameters['groupChatId']!,
name: state.uri.queryParameters['name']!,
);
},
),
@ -156,8 +156,8 @@ final groupChatProfileRoute = GoRoute(
parentNavigatorKey: rootNavigatorKey,
builder: (context, state) {
return ChangeGroupChatIntroScreen(
groupChatId: state.queryParameters['groupChatId']!,
intro: state.queryParameters['intro']!,
groupChatId: state.uri.queryParameters['groupChatId']!,
intro: state.uri.queryParameters['intro']!,
);
},
),
@ -167,8 +167,8 @@ final groupChatProfileRoute = GoRoute(
parentNavigatorKey: rootNavigatorKey,
builder: (context, state) {
return ChangeGroupChatRemarkScreen(
groupChatId: state.queryParameters['groupChatId']!,
nameRemark: state.queryParameters['groupChatRemark']!,
groupChatId: state.uri.queryParameters['groupChatId']!,
nameRemark: state.uri.queryParameters['groupChatRemark']!,
);
},
),
@ -178,8 +178,8 @@ final groupChatProfileRoute = GoRoute(
parentNavigatorKey: rootNavigatorKey,
builder: (context, state) {
return ChangeMyRemarkScreen(
groupChatId: state.queryParameters['groupChatId']!,
myRemark: state.queryParameters['remarkInGroupChat']!,
groupChatId: state.uri.queryParameters['groupChatId']!,
myRemark: state.uri.queryParameters['remarkInGroupChat']!,
);
},
),

View File

@ -42,6 +42,8 @@ final GoRouter router = GoRouter(
getIt.get<UserAccount>().init(res['data']);
await HiveDatabase.init();
return '/chat';
} else {
return null;
}
}
return null;

View File

@ -5,10 +5,10 @@ import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:cherry_toast/cherry_toast.dart';
import 'package:image_picker/image_picker.dart';
import 'package:image_editor_plus/image_editor_plus.dart';
import 'package:image_editor_plus/utils.dart';
import 'package:image_editor_plus/options.dart' as iepo;
import 'package:together_mobile/common/constants.dart';
import 'package:together_mobile/models/contact_model.dart';
import 'package:together_mobile/models/route_state_model.dart';
@ -159,7 +159,7 @@ class _ChangeGroupChatAvatarScreenState
MaterialPageRoute(
builder: (context) => ImageCropper(
availableRatios: const [
AspectRatioOption(ratio: 1, title: '1:1')
iepo.AspectRatio(ratio: 1, title: '1:1')
],
image: imageData,
),

View File

@ -136,7 +136,7 @@ class _HomeScreenWithNavBarState extends State<HomeScreenWithNavBar>
AndroidFlutterLocalNotificationsPlugin>();
final bool? grantedNotificationPermission =
await androidImplementation?.requestPermission();
await androidImplementation?.requestNotificationsPermission();
setState(() {
_notificationsEnabled = grantedNotificationPermission ?? false;
});

View File

@ -5,10 +5,10 @@ import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:cherry_toast/cherry_toast.dart';
import 'package:image_picker/image_picker.dart';
import 'package:image_editor_plus/image_editor_plus.dart';
import 'package:image_editor_plus/utils.dart';
import 'package:image_editor_plus/options.dart' as iepo;
import 'package:together_mobile/common/constants.dart';
import 'package:together_mobile/models/route_state_model.dart';
import 'package:together_mobile/request/server.dart';
@ -139,7 +139,7 @@ class _ChangeMyAvatarScreenState extends State<ChangeMyAvatarScreen> {
MaterialPageRoute(
builder: (context) => ImageCropper(
availableRatios: const [
AspectRatioOption(ratio: 1, title: '1:1')
iepo.AspectRatio(ratio: 1, title: '1:1')
],
image: imageData,
),

View File

@ -1,514 +0,0 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// ignore_for_file: public_member_api_docs
import 'dart:async';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:video_player/video_player.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Image Picker Demo',
home: MyHomePage(title: 'Image Picker Example'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, this.title});
final String? title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<XFile>? _imageFileList;
void _setImageFileListFromFile(XFile? value) {
_imageFileList = value == null ? null : <XFile>[value];
}
dynamic _pickImageError;
bool _isVideo = false;
VideoPlayerController? _videoController;
VideoPlayerController? _toBeDisposed;
String? _retrieveDataError;
final ImagePicker _picker = ImagePicker();
final TextEditingController _maxWidthController = TextEditingController();
final TextEditingController _maxHeightController = TextEditingController();
final TextEditingController _qualityController = TextEditingController();
Future<void> _playVideo(XFile? file) async {
if (file != null && mounted) {
await _disposeVideoController();
late VideoPlayerController controller;
if (kIsWeb) {
controller = VideoPlayerController.network(file.path);
} else {
controller = VideoPlayerController.file(File(file.path));
}
_videoController = controller;
// In web, most browsers won't honor a programmatic call to .play
// if the video has a sound track (and is not muted).
// Mute the video so it auto-plays in web!
// This is not needed if the call to .play is the result of user
// interaction (clicking on a "play" button, for example).
const double volume = kIsWeb ? 0.0 : 1.0;
await controller.setVolume(volume);
await controller.initialize();
await controller.setLooping(true);
await controller.play();
setState(() {});
}
}
Future<void> _onImageButtonPressed(
ImageSource source, {
required BuildContext context,
bool isMultiImage = false,
}) async {
if (_videoController != null) {
await _videoController!.setVolume(0.0);
}
if (context.mounted) {
if (_isVideo) {
final XFile? file = await _picker.pickVideo(
source: source,
maxDuration: const Duration(seconds: 10),
);
await _playVideo(file);
} else if (isMultiImage) {
await _displayPickImageDialog(
context,
(double? maxWidth, double? maxHeight, int? quality) async {
try {
final List<XFile> pickedFileList = await _picker.pickMultiImage(
maxWidth: maxWidth,
maxHeight: maxHeight,
imageQuality: quality,
);
setState(() {
_imageFileList = pickedFileList;
});
} catch (e) {
setState(() {
_pickImageError = e;
});
}
},
);
} else {
await _displayPickImageDialog(
context,
(double? maxWidth, double? maxHeight, int? quality) async {
try {
// call to `pickImage` jump to the image pick page automatically
final XFile? pickedFile = await _picker.pickImage(
source: source,
maxWidth: maxWidth,
maxHeight: maxHeight,
imageQuality: quality,
);
setState(() {
_setImageFileListFromFile(pickedFile);
});
} catch (e) {
setState(() {
_pickImageError = e;
});
}
},
);
}
}
}
@override
void deactivate() {
if (_videoController != null) {
_videoController!.setVolume(0.0);
_videoController!.pause();
}
super.deactivate();
}
@override
void dispose() {
_disposeVideoController();
_maxWidthController.dispose();
_maxHeightController.dispose();
_qualityController.dispose();
super.dispose();
}
Future<void> _disposeVideoController() async {
if (_toBeDisposed != null) {
await _toBeDisposed!.dispose();
}
_toBeDisposed = _videoController;
_videoController = null;
}
Widget _previewVideo() {
final Text? retrieveError = _getRetrieveErrorWidget();
if (retrieveError != null) {
return retrieveError;
}
if (_videoController == null) {
return const Text(
'You have not yet picked a video',
textAlign: TextAlign.center,
);
}
return Padding(
padding: const EdgeInsets.all(10.0),
child: AspectRatioVideo(_videoController),
);
}
// Show the image(s) on the home page after the image(s) is(are) picked
Widget _previewImages() {
final Text? retrieveError = _getRetrieveErrorWidget();
if (retrieveError != null) {
return retrieveError;
}
if (_imageFileList != null) {
return Semantics(
label: 'image_picker_example_picked_images',
child: ListView.builder(
key: UniqueKey(),
itemBuilder: (BuildContext context, int index) {
// Why network for web?
// See https://pub.dev/packages/image_picker_for_web#limitations-on-the-web-platform
return Semantics(
label: 'image_picker_example_picked_image',
child: kIsWeb
? Image.network(_imageFileList![index].path)
: Image.file(
File(_imageFileList![index].path),
errorBuilder: (
BuildContext context,
Object error,
StackTrace? stackTrace,
) =>
const Center(
child: Text('This image type is not supported'),
),
),
);
},
itemCount: _imageFileList!.length,
),
);
} else if (_pickImageError != null) {
return Text(
'Pick image error: $_pickImageError',
textAlign: TextAlign.center,
);
} else {
return const Text(
'You have not yet picked an image.',
textAlign: TextAlign.center,
);
}
}
Widget _handlePreview() {
if (_isVideo) {
return _previewVideo();
} else {
return _previewImages();
}
}
Future<void> retrieveLostData() async {
final LostDataResponse response = await _picker.retrieveLostData();
if (response.isEmpty) {
return;
}
if (response.file != null) {
if (response.type == RetrieveType.video) {
_isVideo = true;
await _playVideo(response.file);
} else {
_isVideo = false;
setState(() {
if (response.files == null) {
_setImageFileListFromFile(response.file);
} else {
_imageFileList = response.files;
}
});
}
} else {
_retrieveDataError = response.exception!.code;
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title!),
),
body: Center(
child: !kIsWeb && defaultTargetPlatform == TargetPlatform.android
? FutureBuilder<void>(
future: retrieveLostData(),
builder: (
BuildContext context,
AsyncSnapshot<void> snapshot,
) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
return const Text(
'You have not yet picked an image.',
textAlign: TextAlign.center,
);
case ConnectionState.done:
// When finish picking image, which also means the future
//is done, this hanle will be executed.
return _handlePreview();
case ConnectionState.active:
if (snapshot.hasError) {
return Text(
'Pick image/video error: ${snapshot.error}}',
textAlign: TextAlign.center,
);
} else {
return const Text(
'You have not yet picked an image.',
textAlign: TextAlign.center,
);
}
}
},
)
: _handlePreview(),
),
floatingActionButton: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Semantics(
label: 'image_picker_example_from_gallery',
child: FloatingActionButton(
onPressed: () {
_isVideo = false;
_onImageButtonPressed(
ImageSource.gallery,
context: context,
);
},
heroTag: 'image0',
tooltip: 'Pick Image from gallery',
child: const Icon(Icons.photo),
),
),
Padding(
padding: const EdgeInsets.only(top: 16.0),
child: FloatingActionButton(
onPressed: () {
_isVideo = false;
_onImageButtonPressed(
ImageSource.gallery,
context: context,
isMultiImage: true,
);
},
heroTag: 'image1',
tooltip: 'Pick Multiple Image from gallery',
child: const Icon(Icons.photo_library),
),
),
Padding(
padding: const EdgeInsets.only(top: 16.0),
child: FloatingActionButton(
onPressed: () {
_isVideo = false;
_onImageButtonPressed(ImageSource.camera, context: context);
},
heroTag: 'image2',
tooltip: 'Take a Photo',
child: const Icon(Icons.camera_alt),
),
),
Padding(
padding: const EdgeInsets.only(top: 16.0),
child: FloatingActionButton(
backgroundColor: Colors.red,
onPressed: () {
_isVideo = true;
_onImageButtonPressed(ImageSource.gallery, context: context);
},
heroTag: 'video0',
tooltip: 'Pick Video from gallery',
child: const Icon(Icons.video_library),
),
),
Padding(
padding: const EdgeInsets.only(top: 16.0),
child: FloatingActionButton(
backgroundColor: Colors.red,
onPressed: () {
_isVideo = true;
_onImageButtonPressed(ImageSource.camera, context: context);
},
heroTag: 'video1',
tooltip: 'Take a Video',
child: const Icon(Icons.videocam),
),
),
],
),
);
}
Text? _getRetrieveErrorWidget() {
if (_retrieveDataError != null) {
final Text result = Text(_retrieveDataError!);
_retrieveDataError = null;
return result;
}
return null;
}
Future<void> _displayPickImageDialog(
BuildContext context,
OnPickImageCallback onPick,
) async {
return showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Add optional parameters'),
content: Column(
children: <Widget>[
TextField(
controller: _maxWidthController,
keyboardType:
const TextInputType.numberWithOptions(decimal: true),
decoration: const InputDecoration(
hintText: 'Enter maxWidth if desired'),
),
TextField(
controller: _maxHeightController,
keyboardType: const TextInputType.numberWithOptions(
decimal: true,
),
decoration: const InputDecoration(
hintText: 'Enter maxHeight if desired',
),
),
TextField(
controller: _qualityController,
keyboardType: TextInputType.number,
decoration: const InputDecoration(
hintText: 'Enter quality if desired',
),
),
],
),
actions: <Widget>[
TextButton(
child: const Text('CANCEL'),
onPressed: () {
Navigator.of(context).pop();
},
),
TextButton(
child: const Text('PICK'),
onPressed: () {
final double? width = _maxWidthController.text.isNotEmpty
? double.parse(_maxWidthController.text)
: null;
final double? height = _maxHeightController.text.isNotEmpty
? double.parse(_maxHeightController.text)
: null;
final int? quality = _qualityController.text.isNotEmpty
? int.parse(_qualityController.text)
: null;
onPick(width, height, quality);
Navigator.of(context).pop();
},
),
],
);
},
);
}
}
typedef OnPickImageCallback = void Function(
double? maxWidth,
double? maxHeight,
int? quality,
);
class AspectRatioVideo extends StatefulWidget {
const AspectRatioVideo(this.controller, {super.key});
final VideoPlayerController? controller;
@override
AspectRatioVideoState createState() => AspectRatioVideoState();
}
class AspectRatioVideoState extends State<AspectRatioVideo> {
VideoPlayerController? get controller => widget.controller;
bool initialized = false;
void _onVideoControllerUpdate() {
if (!mounted) {
return;
}
if (initialized != controller!.value.isInitialized) {
initialized = controller!.value.isInitialized;
setState(() {});
}
}
@override
void initState() {
super.initState();
controller!.addListener(_onVideoControllerUpdate);
}
@override
void dispose() {
controller!.removeListener(_onVideoControllerUpdate);
super.dispose();
}
@override
Widget build(BuildContext context) {
if (initialized) {
return Center(
child: AspectRatio(
aspectRatio: controller!.value.aspectRatio,
child: VideoPlayer(controller!),
),
);
} else {
return Container();
}
}
}

View File

@ -8,25 +8,23 @@ import Foundation
import device_info_plus
import fast_rsa
import file_selector_macos
import flutter_image_compress_macos
import flutter_local_notifications
import flutter_secure_storage_macos
import flutter_timezone
import image_editor_common
import path_provider_foundation
import shared_preferences_foundation
import sqflite
import video_player_avfoundation
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
FastRsaPlugin.register(with: registry.registrar(forPlugin: "FastRsaPlugin"))
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
FlutterImageCompressMacosPlugin.register(with: registry.registrar(forPlugin: "FlutterImageCompressMacosPlugin"))
FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
FlutterTimezonePlugin.register(with: registry.registrar(forPlugin: "FlutterTimezonePlugin"))
ImageEditorPlugin.register(with: registry.registrar(forPlugin: "ImageEditorPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
FVPVideoPlayerPlugin.register(with: registry.registrar(forPlugin: "FVPVideoPlayerPlugin"))
}

File diff suppressed because it is too large Load Diff

View File

@ -34,23 +34,23 @@ dependencies:
cached_network_image: ^3.2.3
cherry_toast: ^1.4.3
custom_pop_up_menu: ^1.2.4
device_info_plus: ^9.0.2
device_info_plus: ^9.1.2
dio: ^5.2.1+1
fast_rsa: ^3.5.7
flutter:
sdk: flutter
flutter_local_notifications: ^15.1.1
flutter_local_notifications: ^17.0.0
flutter_pickers: ^2.1.9
flutter_secure_storage: ^8.0.0
flutter_secure_storage: ^9.0.0
flutter_slidable: ^3.0.0
flutter_timezone: ^1.0.6
get_it: ^7.6.0
get_it_mixin: ^4.2.0
go_router: ^7.1.1
google_fonts: ^4.0.0
go_router: ^13.2.1
google_fonts: ^6.2.1
hive: ^2.2.3
hive_flutter: ^1.1.0
image_editor_plus: ^0.2.4
image_editor_plus: ^1.0.5
image_picker: ^1.0.0
logging: ^1.2.0
path_provider: ^2.0.15
@ -59,13 +59,12 @@ dependencies:
reorderables: ^0.6.0
shared_preferences: ^2.2.0
timezone: ^0.9.2
video_player: ^2.6.1
web_socket_channel: ^2.4.0
worker_manager: ^6.3.1
dev_dependencies:
build_runner: ^2.4.5
flutter_lints: ^2.0.0
flutter_lints: ^3.0.1
flutter_test:
sdk: flutter

View File

@ -9,6 +9,7 @@
#include <fast_rsa/fast_rsa_plugin.h>
#include <file_selector_windows/file_selector_windows.h>
#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
#include <permission_handler_windows/permission_handler_windows_plugin.h>
void RegisterPlugins(flutter::PluginRegistry* registry) {
FastRsaPluginRegisterWithRegistrar(
@ -17,4 +18,6 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
registry->GetRegistrarForPlugin("FileSelectorWindows"));
FlutterSecureStorageWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin"));
PermissionHandlerWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
}

View File

@ -6,6 +6,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
fast_rsa
file_selector_windows
flutter_secure_storage_windows
permission_handler_windows
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST