diff --git a/assets/images/error.svg b/assets/images/error.svg
new file mode 100644
index 0000000..cf763e3
--- /dev/null
+++ b/assets/images/error.svg
@@ -0,0 +1,10 @@
+
diff --git a/lib/app/widgets/app.dart b/lib/app/widgets/app.dart
deleted file mode 100644
index e8c41bb..0000000
--- a/lib/app/widgets/app.dart
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright 2021 BBK Development. All rights reserved.
-// Use of this source code is governed by a GPL-style license that can be found
-// in the LICENSE file.
-
-import 'package:bottom_navy_bar/bottom_navy_bar.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_svg/svg.dart';
-import 'package:get/get.dart';
-import 'package:vmerge/controllers/controllers.dart';
-import 'package:vmerge/controllers/home_page_controller.dart';
-import 'package:vmerge/utilities/utilities.dart';
-import 'package:vmerge/views/views.dart';
-
-class App extends StatelessWidget {
- const App({super.key});
-
- @override
- Widget build(BuildContext context) {
- return GetMaterialApp(
- debugShowCheckedModeBanner: false,
- themeMode: ThemeMode.dark,
- darkTheme: appTheme,
- home: VSoundPageView(),
- );
- }
-}
-
-class VSoundPageView extends StatelessWidget {
- VSoundPageView({super.key}) {
- _bottomBarController = Get.put(BottomBarController());
- _editPageController = Get.put(EditPageController());
- _homePageController = Get.put(HomePageController());
- _morePageController = Get.put(MorePageController());
- }
- late final BottomBarController _bottomBarController;
- late final EditPageController _editPageController;
- late final HomePageController _homePageController;
- late final MorePageController _morePageController;
-
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- body: SizedBox.expand(
- child: PageView(
- controller: _bottomBarController.pageController,
- physics: const NeverScrollableScrollPhysics(),
- onPageChanged: (index) async {
- _bottomBarController.updateCurrentIndex(index);
- if (index == 1) {
- _editPageController.getAnimationController.duration =
- kEditPageInAnimationDuration;
- await _editPageController.getAnimationController.forward();
- if (_homePageController.getVideoList.length == 2) {
- _editPageController
- .updateAssets(_homePageController.getVideoList);
- }
- }
- if (index == 2) {
- _morePageController.getBeginList.clear();
- _morePageController.getEndList.clear();
- _morePageController.getAnimationController.duration =
- kMorePageInAnimationDuration;
- await _morePageController.getAnimationController.forward();
- }
- },
- children: [
- HomePage(),
- const EditPage(),
- MorePage(),
- ],
- ),
- ),
- bottomNavigationBar: Container(
- padding: const EdgeInsets.symmetric(horizontal: 14),
- color: kPrimaryColor,
- child: Obx(() {
- return BottomNavyBar(
- selectedIndex: _bottomBarController.currentIndex,
- onItemSelected: (index) async {
- if (_bottomBarController.currentIndex == 1 && index != 1) {
- _editPageController.getAnimationController.duration =
- kEditPageOutAnimationDuration;
- await _editPageController.getAnimationController.reverse();
- }
- if (_bottomBarController.currentIndex == 2 && index != 2) {
- _morePageController.getAnimationController.duration =
- kMorePageOutAnimationDuration;
- await _morePageController.getAnimationController.reverse();
- }
- _bottomBarController.updateCurrentIndex(index);
- _bottomBarController.pageController.jumpToPage(index);
- },
- backgroundColor: kPrimaryColor,
- items: [
- BottomNavyBarItem(
- activeColor: kPrimaryWhiteColor,
- inactiveColor: kPrimaryWhiteColor,
- title: const Text('Home', style: kSemiBoldTextStyle),
- textAlign: TextAlign.center,
- icon: SvgPicture.asset(kHomeIconPath),
- ),
- BottomNavyBarItem(
- activeColor: kPrimaryWhiteColor,
- inactiveColor: kPrimaryWhiteColor,
- title: const Text('Edit', style: kSemiBoldTextStyle),
- textAlign: TextAlign.center,
- icon: SvgPicture.asset(kCutIconPath),
- ),
- BottomNavyBarItem(
- activeColor: kPrimaryWhiteColor,
- inactiveColor: kPrimaryWhiteColor,
- title: const Text('More', style: kSemiBoldTextStyle),
- textAlign: TextAlign.center,
- icon: SvgPicture.asset(kMoreIconPath),
- ),
- ],
- );
- }),
- ),
- );
- }
-}
diff --git a/lib/bootstrap.dart b/lib/bootstrap.dart
index a40ffde..b3ac4ae 100644
--- a/lib/bootstrap.dart
+++ b/lib/bootstrap.dart
@@ -8,8 +8,14 @@ import 'dart:developer';
import 'package:bloc/bloc.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
+import 'package:get_it/get_it.dart';
+import 'package:launch_review_service/launch_review_service.dart';
+import 'package:url_launcher_service/url_launcher_service.dart';
+import 'package:vmerge/utilities/utilities.dart';
import 'package:wechat_assets_picker/wechat_assets_picker.dart';
+final getIt = GetIt.instance;
+
class AppBlocObserver extends BlocObserver {
const AppBlocObserver();
@@ -36,8 +42,24 @@ Future bootstrap(FutureOr Function() builder) async {
final widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
// FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark);
- await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
- await PhotoManager.clearFileCache();
+
+ await Future.wait(
+ [
+ SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]),
+ PhotoManager.clearFileCache(),
+ setup(),
+ ],
+ ).onError((error, stackTrace) => [log('$error', stackTrace: stackTrace)]);
runApp(await builder());
}
+
+Future setup() async {
+ getIt
+ ..registerLazySingleton(
+ () => const LaunchReviewService(androidAppId: kAndroidAppId),
+ )
+ ..registerLazySingleton(
+ () => const UrlLauncherService(),
+ );
+}
diff --git a/lib/components/animated_control_button.dart b/lib/components/animated_control_button.dart
new file mode 100644
index 0000000..68d54a4
--- /dev/null
+++ b/lib/components/animated_control_button.dart
@@ -0,0 +1,83 @@
+// Copyright 2023 BBK Development. All rights reserved.
+// Use of this source code is governed by a GPL-style license that can be found
+// in the LICENSE file.
+
+import 'package:flutter/material.dart';
+
+class AnimatedControlButtonController {
+ late void Function() forward;
+ late void Function() reverse;
+}
+
+class AnimatedControlButton extends StatefulWidget {
+ const AnimatedControlButton({
+ required this.controller,
+ this.onTap,
+ this.size = 32.0,
+ super.key,
+ });
+
+ final AnimatedControlButtonController controller;
+ final void Function()? onTap;
+ final double size;
+
+ @override
+ State createState() => _AnimatedControlButtonState();
+}
+
+class _AnimatedControlButtonState extends State
+ with TickerProviderStateMixin {
+ late final AnimationController controller;
+
+ @override
+ void initState() {
+ super.initState();
+ controller = AnimationController(
+ duration: const Duration(milliseconds: 500),
+ vsync: this,
+ );
+ initController();
+ }
+
+ @override
+ void dispose() {
+ controller.dispose();
+ super.dispose();
+ }
+
+ void initController() {
+ widget.controller.forward = () async {
+ if (mounted) {
+ await controller.forward();
+ }
+ };
+
+ widget.controller.reverse = () async {
+ if (mounted) {
+ await controller.reverse();
+ }
+ };
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return GestureDetector(
+ onTap: widget.onTap,
+ child: Container(
+ height: MediaQuery.of(context).size.width * 0.12,
+ width: MediaQuery.of(context).size.width * 0.12,
+ decoration: BoxDecoration(
+ shape: BoxShape.circle,
+ color: Theme.of(context).focusColor,
+ ),
+ child: Center(
+ child: AnimatedIcon(
+ icon: AnimatedIcons.play_pause,
+ progress: controller,
+ size: widget.size,
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/components/components.dart b/lib/components/components.dart
index 0dcbd9e..f76353b 100644
--- a/lib/components/components.dart
+++ b/lib/components/components.dart
@@ -2,7 +2,5 @@
// Use of this source code is governed by a GPL-style license that can be found
// in the LICENSE file.
-export 'save_modal_bottom_sheet.dart';
-export 'settings_modal_bottom_sheet.dart';
-export 'video_thumbnail.dart';
+export 'animated_control_button.dart';
export 'vmerge_app_bar.dart';
diff --git a/lib/components/save_modal_bottom_sheet.dart b/lib/components/save_modal_bottom_sheet.dart
deleted file mode 100644
index 9d5fa79..0000000
--- a/lib/components/save_modal_bottom_sheet.dart
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright 2021 BBK Development. All rights reserved.
-// Use of this source code is governed by a GPL-style license that can be found
-// in the LICENSE file.
-
-import 'package:flutter/material.dart';
-import 'package:flutter_svg/flutter_svg.dart';
-import 'package:get/get.dart';
-import 'package:vmerge/controllers/controllers.dart';
-import 'package:vmerge/utilities/utilities.dart';
-
-class SaveModalBottomSheet extends StatelessWidget {
- SaveModalBottomSheet({super.key}) {
- _editPageController = Get.find();
- }
-
- late final EditPageController _editPageController;
-
- @override
- Widget build(BuildContext context) {
- return Material(
- color: Colors.transparent,
- child: Container(
- padding: const EdgeInsets.symmetric(horizontal: 22),
- decoration: const BoxDecoration(
- color: kPrimaryColor,
- borderRadius: BorderRadius.only(
- topLeft: Radius.circular(22),
- topRight: Radius.circular(22),
- ),
- ),
- child: SafeArea(
- child: Column(
- mainAxisSize: MainAxisSize.min,
- children: [
- const SizedBox(height: 20),
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- const SizedBox(width: kIconSize),
- const Text(
- kSaveToAlbumText,
- style: kBoldTextStyle,
- ),
- InkWell(
- onTap: () {
- if (_editPageController.status == kSuccessText) {
- Get.back();
- }
- },
- overlayColor: MaterialStateProperty.all(Colors.transparent),
- highlightColor: Colors.transparent,
- child: Obx(
- () => _editPageController.status == kSuccessText
- ? SvgPicture.asset(
- kCloseIconPath,
- width: kIconSize,
- color: kPrimaryWhiteColor.withOpacity(1),
- )
- : const SizedBox(width: kIconSize),
- ),
- ),
- ],
- ),
- const SizedBox(height: 32),
- _buildTimeSlider(),
- const SizedBox(height: 32),
- Obx(
- () => Text(
- _editPageController.status,
- style: kMediumTextStyle,
- ),
- ),
- const SizedBox(height: 20),
- ],
- ),
- ),
- ),
- );
- }
-
- SizedBox _buildTimeSlider() {
- return SizedBox(
- height: 120,
- width: 120,
- child: Obx(
- () => Stack(
- fit: StackFit.expand,
- children: [
- CircularProgressIndicator(
- backgroundColor: kPrimaryWhiteColor.withOpacity(0.7),
- strokeWidth: 8,
- value: _editPageController.progressPercentage / 100,
- valueColor: const AlwaysStoppedAnimation(
- kPrimaryWhiteColor,
- ),
- ),
- Center(
- child: _editPageController.status == kSuccessText
- ? const Icon(
- Icons.check_rounded,
- color: kPrimaryWhiteColor,
- size: kIconSize,
- )
- : Text(
- '${_editPageController.progressPercentage.round()}%',
- textAlign: TextAlign.center,
- style: kBoldTextStyle.copyWith(color: kPrimaryWhiteColor),
- ),
- ),
- ],
- ),
- ),
- );
- }
-}
diff --git a/lib/controllers/bottom_bar_controller.dart b/lib/controllers/bottom_bar_controller.dart
deleted file mode 100644
index 346a452..0000000
--- a/lib/controllers/bottom_bar_controller.dart
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2021 BBK Development. All rights reserved.
-// Use of this source code is governed by a GPL-style license that can be found
-// in the LICENSE file.
-
-import 'package:flutter/material.dart';
-import 'package:get/get.dart';
-
-class BottomBarController extends GetxController {
- late final RxInt _currentIndex;
- late final PageController _pageController;
-
- int get currentIndex => _currentIndex.value;
- PageController get pageController => _pageController;
-
- @override
- void onInit() {
- super.onInit();
- _currentIndex = 0.obs;
- _pageController = PageController();
- }
-
- void updateCurrentIndex(int index) {
- _currentIndex.value = index;
- }
-}
diff --git a/lib/controllers/controllers.dart b/lib/controllers/controllers.dart
deleted file mode 100644
index 219a821..0000000
--- a/lib/controllers/controllers.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2021 BBK Development. All rights reserved.
-// Use of this source code is governed by a GPL-style license that can be found
-// in the LICENSE file.
-
-export 'bottom_bar_controller.dart';
-export 'edit_page_controller.dart';
-export 'more_page_controller.dart';
diff --git a/lib/controllers/edit_page_controller.dart b/lib/controllers/edit_page_controller.dart
deleted file mode 100644
index 62a5a43..0000000
--- a/lib/controllers/edit_page_controller.dart
+++ /dev/null
@@ -1,448 +0,0 @@
-// Copyright 2021 BBK Development. All rights reserved.
-// Use of this source code is governed by a GPL-style license that can be found
-// in the LICENSE file.
-
-import 'dart:io';
-
-import 'package:flutter/material.dart';
-import 'package:flutter_ffmpeg/flutter_ffmpeg.dart';
-import 'package:get/get.dart';
-import 'package:image_gallery_saver/image_gallery_saver.dart';
-import 'package:path/path.dart';
-import 'package:path_provider/path_provider.dart';
-import 'package:video_player/video_player.dart';
-import 'package:vmerge/components/components.dart';
-import 'package:vmerge/models/models.dart';
-import 'package:vmerge/utilities/utilities.dart';
-
-class EditPageController extends GetxController
- with GetSingleTickerProviderStateMixin {
- late final FlutterFFmpeg _flutterFFmpeg;
- late final FlutterFFmpegConfig _fFmpegConfig;
- late final VideoPlayerOptions _videoPlayerOptions;
- late final AnimationController _animationController;
- late final Animation _staggeredAnimation;
- late final RxDouble _speedValue;
- late final RxDouble _qualityValue;
- late final RxDouble _progressPercentage;
- late final RxList