Quellcode durchsuchen

1.完成壁纸功能
2.完成新人引导页

云天逵 vor 1 Jahr
Ursprung
Commit
bbcf1d4aea

+ 36 - 0
android/build.gradle

@@ -7,6 +7,42 @@ allprojects {
 
 rootProject.buildDir = "../build"
 subprojects {
+
+    /**************************
+     * https://github.com/flutter/flutter/issues/153281
+     * 受影响插件:image_gallery_saver
+     * **************/
+//==========================================================================================
+    afterEvaluate { project ->
+        if (project.extensions.findByName("android") != null) {
+            Integer pluginCompileSdk = project.android.compileSdk
+            if (pluginCompileSdk != null && pluginCompileSdk < 31) {
+                project.logger.error(
+                        "Warning: Overriding compileSdk version in Flutter plugin: "
+                                + project.name
+                                + " from "
+                                + pluginCompileSdk
+                                + " to 31 (to work around https://issuetracker.google.com/issues/199180389)."
+                                + "\nIf there is not a new version of " + project.name + ", consider filing an issue against "
+                                + project.name
+                                + " to increase their compileSdk to the latest (otherwise try updating to the latest version)."
+                )
+                project.android {
+                    compileSdk flutter.compileSdkVersion
+                }
+            }
+            if (project.hasProperty('android')) {
+                project.android {
+                    if (namespace == null) {
+                        namespace project.group
+                    }
+                }
+            }
+
+
+        }
+    }
+    //==========================================================================================
     project.buildDir = "${rootProject.buildDir}/${project.name}"
 }
 subprojects {

+ 2 - 0
android/gradle.properties

@@ -1,3 +1,5 @@
 org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError
 android.useAndroidX=true
 android.enableJetifier=true
+#image_gallery_saver??????????
+kotlin.jvm.target.validation.mode=warning

BIN
assets/anim/anim_intro_first.zip


BIN
assets/anim/anim_intro_second.zip


BIN
assets/anim/anim_splash.zip


BIN
assets/images/icon_private_close.webp


+ 2 - 2
assets/string/base/string.xml

@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
-    <string name="app_name">clean</string>
-    <string name="clean_pro">CleanPro</string>
+    <string name="app_name">CleanPro</string>
+
 </resources>

+ 6 - 0
lib/data/api/atmob_api.dart

@@ -5,6 +5,7 @@ import 'package:clean/data/api/response/order_pay_response.dart';
 import 'package:clean/data/api/response/order_status_response.dart';
 import 'package:clean/data/api/response/store_index_response.dart';
 import 'package:clean/data/api/response/user_info_response.dart';
+import 'package:clean/data/api/response/wallpaper_list_response.dart';
 import 'package:dio/dio.dart';
 import 'package:retrofit/error_logger.dart';
 import 'package:retrofit/http.dart';
@@ -39,6 +40,11 @@ abstract class AtmobApi {
   @POST("/project/clean/v1/member/subscription/resume")
   Future<BaseResponse> resume(
       @Body() SubscriptionResumeRequest request);
+
+  @POST("/project/clean/v1/clean/wallpaper/list")
+  Future<BaseResponse<WallpaperListResponse>> wallpaperList(
+      @Body() BaseRequest request);
+
 }
 
 final atmobApi = AtmobApi(defaultDio, baseUrl: Constants.baseUrl);

+ 18 - 0
lib/data/api/response/wallpaper_list_response.dart

@@ -0,0 +1,18 @@
+import 'package:clean/data/bean/wallpapers_bean.dart';
+import 'package:json_annotation/json_annotation.dart';
+
+
+part 'wallpaper_list_response.g.dart';
+
+@JsonSerializable()
+class WallpaperListResponse {
+  @JsonKey(name: 'wallpapers')
+  List<WallpapersBean>? wallpapers;
+
+  WallpaperListResponse(
+      this.wallpapers);
+
+
+  factory WallpaperListResponse.fromJson(Map<String, dynamic> json) =>
+      _$WallpaperListResponseFromJson(json);
+}

+ 20 - 0
lib/data/bean/wallpapers_bean.dart

@@ -0,0 +1,20 @@
+import 'package:json_annotation/json_annotation.dart';
+
+part 'wallpapers_bean.g.dart';
+
+@JsonSerializable()
+class WallpapersBean {
+  @JsonKey(name: 'imageUrl')
+  String? imageUrl;
+
+  @JsonKey(name: 'thumbUrl')
+  String? thumbUrl;
+
+  WallpapersBean({
+    required this.imageUrl,
+    this.thumbUrl,
+  });
+
+  factory WallpapersBean.fromJson(Map<String, dynamic> json) =>
+      _$WallpapersBeanFromJson(json);
+}

+ 17 - 0
lib/data/consts/constants.dart

@@ -23,6 +23,8 @@ class Constants {
   static const String userAgreement =
       "https://cdn.supercleaner.club/static/cleanpro/clean_pro_terms.html";
 
+  static const String isPolicyGranted = 'isPolicyGranted';
+  static const String isIntro = 'isIntroduction';
   static String baseUrl = getBaseUrl();
 
   static const String appDefaultChannel = "Android";
@@ -72,3 +74,18 @@ void setFirstOpenPhotoPreview(bool firstTime) {
   KVUtil.putBool(Constants.firstOpenPhotoPreview, firstTime);
 }
 
+bool isFirstIntro() {
+  return KVUtil.getBool(Constants.isIntro, true);
+}
+void setFirstIntro(bool firstTime) {
+  KVUtil.putBool(Constants.isIntro, firstTime);
+}
+
+bool isAgreePrivacyPolicy() {
+  return KVUtil.getBool(Constants.isPolicyGranted, false);
+}
+void setPrivacyPolicy(bool isAgree) {
+  KVUtil.putBool(Constants.isPolicyGranted, isAgree);
+}
+
+

+ 28 - 0
lib/data/repositories/wallpaper_repositories.dart

@@ -0,0 +1,28 @@
+import 'package:clean/base/base_request.dart';
+import 'package:clean/data/api/atmob_api.dart';
+import 'package:clean/data/api/response/wallpaper_list_response.dart';
+import 'package:clean/data/bean/wallpapers_bean.dart';
+import 'package:clean/utils/http_handler.dart';
+import 'package:get/get.dart';
+
+class WallpaperRepository {
+  WallpaperRepository._();
+
+  Rxn<WallpaperListResponse> get wallpaper => _wallpaper;
+  final Rxn<WallpaperListResponse> _wallpaper = Rxn<WallpaperListResponse>();
+  final RxList<WallpapersBean> _wallpapersList = RxList<WallpapersBean>();
+  RxList<WallpapersBean> get wallpapersList => _wallpapersList;
+
+  Future<WallpaperListResponse> wallpaperList() {
+    return atmobApi
+        .wallpaperList(BaseRequest())
+        .then(HttpHandler.handle(false))
+        .then((data) {
+      _wallpaper.value = data;
+      _wallpapersList.value = data.wallpapers ?? [];
+      return data;
+    });
+  }
+}
+
+final WallpaperRepository wallpaperRepository = WallpaperRepository._();

+ 132 - 0
lib/dialog/wallpaper_detail_dialog.dart

@@ -0,0 +1,132 @@
+import 'package:cached_network_image/cached_network_image.dart';
+import 'package:clean/data/bean/wallpapers_bean.dart';
+import 'package:clean/resource/assets.gen.dart';
+import 'package:clean/resource/colors.gen.dart';
+import 'package:clean/utils/toast_util.dart';
+import 'package:flutter/Material.dart';
+import 'package:flutter_cache_manager/flutter_cache_manager.dart';
+import 'package:flutter_screenutil/flutter_screenutil.dart';
+import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
+import 'package:image_gallery_saver/image_gallery_saver.dart';
+
+const tag = 'wallpaperDetailDialog';
+
+void wallpaperDetailDialog(
+    {WallpapersBean? wallpapersBean}) {
+  SmartDialog.show(
+      tag: tag,
+      backType: SmartBackType.normal,
+      clickMaskDismiss: false,
+      maskColor: ColorName.black,
+      builder: (_) {
+        return Container(
+            height: double.infinity,
+            width: double.infinity,
+            child: Container(
+              child: Stack(
+                children: [
+                  Container(
+                      child: SafeArea(
+                          child: Column(
+                    crossAxisAlignment: CrossAxisAlignment.center,
+                    children: [
+                      _titleCard(),
+                      Container(
+                          width: 322.w,
+                          height: 572.h,
+                          decoration: ShapeDecoration(
+                            shape: RoundedRectangleBorder(
+                              borderRadius: BorderRadius.circular(20.r),
+                            ),
+                          ),
+                          child: AspectRatio(
+                            aspectRatio: 9 / 16, // 设置9:16的宽高比
+
+                            child: ClipRRect(
+                              borderRadius: BorderRadius.circular(16.r),
+                              child: CachedNetworkImage(
+                                imageUrl: wallpapersBean?.thumbUrl ?? "",
+                                fit: BoxFit.cover,
+                                placeholder: (context, url) =>
+                                    CircularProgressIndicator(),
+                                // 加载时显示一个指示器
+                                errorWidget: (context, url, error) =>
+                                    Icon(Icons.error),
+                              ),
+                            ),
+                          )),
+                      Spacer(
+                        flex: 1,
+                      ),
+                      GestureDetector(
+                          onTap: () {
+                            downloadWallpaper(wallpapersBean?.imageUrl);
+                          },
+                          child: Container(
+                            width: 328.w,
+                            height: 48.h,
+                            decoration: ShapeDecoration(
+                              color: Color(0xFF0279FB),
+                              shape: RoundedRectangleBorder(
+                                borderRadius: BorderRadius.circular(10.r),
+                              ),
+                            ),
+                            child: Center(
+                              child: Text(
+                                'Download',
+                                style: TextStyle(
+                                  color: Colors.white,
+                                  fontSize: 16,
+                                  fontFamily: 'Source Han Sans CN',
+                                  fontWeight: FontWeight.w500,
+                                ),
+                              ),
+                            ),
+                          )),
+                      Spacer(
+                        flex: 1,
+                      ),
+                    ],
+                  ))),
+                  IgnorePointer(
+                    child: Assets.images.bgHome.image(
+                      width: 360.w,
+                      height: 234.h,
+                    ),
+                  ),
+                ],
+              ),
+            ));
+      });
+}
+
+void downloadWallpaper(String? imageUrl) async {
+  try {
+    ToastUtil.show("Downloading...");
+    final saveFile = await DefaultCacheManager().getSingleFile(imageUrl ?? "");
+
+    await ImageGallerySaver.saveFile(saveFile.path);
+    ToastUtil.show("Download success");
+  } catch (e) {
+    ToastUtil.show("Download failed");
+  }
+}
+
+Widget _titleCard() {
+  return Container(
+    alignment: Alignment.centerLeft,
+    padding: EdgeInsets.only(left: 16.w, top: 14.h, right: 16.w, bottom: 20.h),
+    child: Column(
+      crossAxisAlignment: CrossAxisAlignment.start,
+      children: [
+        GestureDetector(
+          onTap: () => SmartDialog.dismiss(tag: tag),
+          child: Assets.images.iconBackArrow.image(
+            width: 28.w,
+            height: 28.h,
+          ),
+        ),
+      ],
+    ),
+  );
+}

+ 1 - 1
lib/main.dart

@@ -60,7 +60,7 @@ class MyApp extends StatelessWidget {
       child: GetMaterialApp(
         onGenerateTitle: (_) => StringName.appName,
         getPages: AppPage.pages,
-        initialRoute: RoutePath.mainTab,
+        initialRoute: RoutePath.splash,
         initialBinding: AppBinding(),
         theme: ThemeData(
           useMaterial3: true,

+ 1 - 1
lib/module/home/home_view.dart

@@ -62,7 +62,7 @@ class HomePage extends BaseView<HomeController> {
         mainAxisAlignment: MainAxisAlignment.spaceBetween,
         children: [
           Text(
-            StringName.cleanPro,
+            StringName.appName,
             style: TextStyle(
               color: Colors.white,
               fontSize: 24.sp,

+ 5 - 1
lib/module/more/more_view.dart

@@ -1,5 +1,6 @@
 import 'package:clean/base/base_view.dart';
 import 'package:clean/module/more/more_controller.dart';
+import 'package:clean/module/wallpaper/wallpaper_view.dart';
 import 'package:clean/router/app_pages.dart';
 import 'package:clean/utils/expand.dart';
 import 'package:flutter/Material.dart';
@@ -12,6 +13,7 @@ import '../../resource/assets.gen.dart';
 class MorePage extends BaseView<MoreController> {
   const MorePage({super.key});
 
+
   @override
   Widget buildBody(BuildContext context) {
     return SafeArea(
@@ -75,7 +77,9 @@ class MorePage extends BaseView<MoreController> {
                         Assets.images.iconMoreWallpaperBg.image(),
                         Assets.images.iconMoreWallpaper
                             .image(height: 72.w, width: 72.w),
-                        onTap: () {}),
+                        onTap: () {
+                          WallPaperPage.start();
+                        }),
                     SizedBox(height: 14.h),
                     _buildCustomCard(
                       "Settings",

+ 72 - 0
lib/module/splash/intro/intro_controller.dart

@@ -0,0 +1,72 @@
+import 'dart:async';
+
+import 'package:clean/base/base_controller.dart';
+import 'package:clean/data/consts/constants.dart';
+import 'package:clean/resource/assets.gen.dart';
+import 'package:clean/router/app_pages.dart';
+import 'package:flutter/Material.dart';
+import 'package:get/get.dart';
+
+class IntroController extends BaseController {
+  Rx<PageController> pageController = PageController().obs;
+  var currentPage = 0.obs;
+
+  final List<PageBean> pageList = [
+    PageBean("One tap smart cleaning", Assets.anim.animIntroFirst),
+    PageBean(
+        "AI algorithm for duplicates \n detected", Assets.anim.animIntroSecond),
+  ];
+
+  Timer? _autoPageTimer;
+
+  @override
+  void onInit() {
+    super.onInit();
+  }
+
+  @override
+  void onReady() {
+    super.onReady();
+    _autoPageTimer = Timer.periodic(const Duration(seconds: 3), (timer) {
+      swiperIntro();
+    });
+  }
+
+  @override
+  void onClose() {
+    super.onClose();
+    _autoPageTimer?.cancel();
+  }
+
+  void swiperIntro() {
+    if (currentPage.value == pageList.length - 1) {
+      // 进入主页或其他操作
+
+      Timer(const Duration(milliseconds: 500), () {
+        Get.offNamed(RoutePath.mainTab);
+        setFirstIntro(false);
+      });
+    } else {
+      // 跳转到下一页
+      pageController.value.nextPage(
+        duration: const Duration(milliseconds: 500),
+        curve: Curves.easeInOut,
+      );
+      currentPage.value++;
+    }
+  }
+
+  void nextButton() {
+    Timer(const Duration(milliseconds: 500), () {
+      Get.offNamed(RoutePath.mainTab);
+      setFirstIntro(false);
+    });
+  }
+}
+
+class PageBean {
+  String title;
+  String animUrl;
+
+  PageBean(this.title, this.animUrl);
+}

+ 136 - 0
lib/module/splash/intro/intro_view.dart

@@ -0,0 +1,136 @@
+import 'package:clean/base/base_page.dart';
+import 'package:clean/module/splash/intro/intro_controller.dart';
+import 'package:clean/resource/assets.gen.dart';
+import 'package:clean/resource/colors.gen.dart';
+import 'package:clean/router/app_pages.dart';
+import 'package:flutter/Material.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter_screenutil/flutter_screenutil.dart';
+import 'package:get/get.dart';
+import 'package:get/get_core/src/get_main.dart';
+import 'package:lottie/lottie.dart';
+
+class IntroPage extends BasePage<IntroController> {
+  IntroPage({Key? key}) : super(key: key);
+
+  static void start() {
+    Get.offNamed(RoutePath.intro);
+  }
+
+  @override
+  bool immersive() {
+    return true;
+  }
+
+  @override
+  bool statusBarDarkFont() {
+    return false;
+  }
+
+  @override
+  Widget buildBody(BuildContext context) {
+    return Stack(children: [
+      Container(
+        width: double.infinity,
+        height: double.infinity,
+        child: SafeArea(
+            child: Container(
+                child: Column(
+          children: [
+            Flexible(
+              child: PageView(
+                controller: controller.pageController.value,
+                onPageChanged: (index) {
+                  controller.currentPage.value = index;
+                },
+                children: List.generate(controller.pageList.length, (index) {
+                  return buildPage(controller.pageList[index]);
+                }),
+              ),
+            ),
+            buildIndicator(),
+            SizedBox(height: 15.h),
+            GestureDetector(
+              child: Container(
+                width: 316.w,
+                height: 48.h,
+                alignment: Alignment.center,
+                decoration: ShapeDecoration(
+                  color: Color(0xFF0279FB),
+                  shape: RoundedRectangleBorder(
+                    borderRadius: BorderRadius.circular(24.r),
+                  ),
+                ),
+
+                child: Text(
+                  'CONTINUE',
+                  style: TextStyle(
+                    color: Colors.white,
+                    fontSize: 16.sp,
+                    fontWeight: FontWeight.w500,
+                  ),
+                ),
+              ),
+            ),
+
+            SizedBox(height: 76.h),
+          ],
+        ))),
+      ),
+      IgnorePointer(
+        child: Assets.images.bgPhotoSelectedPreviewFinish.image(
+          width: 360.w,
+          height: 335.h,
+        ),
+      ),
+    ]);
+  }
+
+  Widget buildIndicator() {
+    return Obx(() {
+      return Row(
+        mainAxisAlignment: MainAxisAlignment.center,
+        children: List.generate(controller.pageList.length, (index) {
+          return AnimatedContainer(
+            duration: const Duration(milliseconds: 500),
+            margin: EdgeInsets.symmetric(horizontal: 5.h),
+            height: 10,
+            width: controller.currentPage.value == index ? 10.w : 10.w,
+            // width: controller.currentPage.value == index ? 20.w : 10.w, 选中为长方形
+            decoration: BoxDecoration(
+              color: controller.currentPage.value == index
+                  ? ColorName.white
+                  : ColorName.white.withValues(alpha: 0.25),
+              borderRadius: BorderRadius.circular(5.r),
+            ),
+          );
+        }),
+      );
+    });
+  }
+
+  Widget buildPage(PageBean pageBean) {
+    return Column(
+      crossAxisAlignment: CrossAxisAlignment.center,
+      mainAxisAlignment: MainAxisAlignment.center,
+      children: [
+        Text(
+          pageBean.title,
+          textAlign: TextAlign.center,
+          style: TextStyle(
+            color: Colors.white,
+            fontSize: 24,
+            fontWeight: FontWeight.w500,
+            height: 1.25,
+          ),
+        ),
+        Lottie.asset(
+          pageBean.animUrl,
+          width: 360.w,
+          height: 329.w,
+          repeat: true,
+        ),
+      ],
+    );
+  }
+}

+ 42 - 0
lib/module/splash/splash_controller.dart

@@ -0,0 +1,42 @@
+import 'package:clean/base/base_controller.dart';
+import 'package:clean/data/consts/constants.dart';
+import 'package:clean/dialog/privacy_dialog.dart';
+import 'package:clean/module/main/main_view.dart';
+import 'package:clean/module/splash/intro/intro_view.dart';
+import 'package:flutter/Material.dart';
+import 'package:get/get.dart';
+
+class SplashController extends BaseController {
+  Animation<double>? animation;
+
+  @override
+  void onInit() {
+    super.onInit();
+  }
+
+  @override
+  void onReady() {
+    print('SplashController onReady');
+    super.onReady();
+    final isAgreePrivacy = isAgreePrivacyPolicy();
+    if (isAgreePrivacy) {
+      Future.delayed(const Duration(seconds: 3), () {
+        MainTabPage.start();
+      });
+    } else {
+      if (isFirstIntro()) {
+        Future.delayed(const Duration(seconds: 3), () {
+          IntroPage.start();
+        });
+      } else {
+        MainTabPage.start();
+      }
+    }
+  }
+
+  @override
+  void onClose() {
+    print('SplashController onClose');
+    super.onClose();
+  }
+}

+ 141 - 0
lib/module/splash/splash_view.dart

@@ -0,0 +1,141 @@
+import 'package:clean/base/base_page.dart';
+import 'package:clean/module/main/main_view.dart';
+import 'package:clean/module/splash/splash_controller.dart';
+import 'package:clean/resource/assets.gen.dart';
+import 'package:clean/resource/string.gen.dart';
+import 'package:flutter/Material.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/src/widgets/framework.dart';
+import 'package:flutter_screenutil/flutter_screenutil.dart';
+import 'package:get/get_core/src/get_main.dart';
+import 'package:lottie/lottie.dart';
+
+class SplashPage extends BasePage<SplashController> {
+  const SplashPage({super.key});
+
+  @override
+  bool immersive() {
+    return true;
+  }
+
+  @override
+  bool statusBarDarkFont() {
+    return false;
+  }
+
+  @override
+  Widget buildBody(BuildContext context) {
+    return Stack(children: [
+      Container(
+        width: double.infinity,
+        height: double.infinity,
+        child: SafeArea(
+            child: Container(
+
+          child: Column(
+            crossAxisAlignment: CrossAxisAlignment.center,
+            mainAxisAlignment: MainAxisAlignment.center,
+            children: [
+              SizedBox(
+                  child: Lottie.asset(
+                Assets.anim.animSplash,
+                controller: controller.animation,
+                width: 150.w,
+                height: 150.w,
+                repeat: true,
+              )),
+              Text(
+                StringName.appName,
+                textAlign: TextAlign.center,
+                style: TextStyle(
+                  color: Colors.white,
+                  fontSize: 24.sp,
+                  fontWeight: FontWeight.w900,
+                ),
+              ),
+            ],
+          ),
+        )),
+      ),
+      IgnorePointer(
+        child: Assets.images.bgPhotoSelectedPreviewFinish.image(
+          width: 360.w,
+          height: 335.h,
+        ),
+      ),
+    ]);
+  }
+
+// Widget _finishCleanCard() {
+//   return Container(
+//     width: 360.w,
+//     child: Column(
+//       mainAxisAlignment: MainAxisAlignment.start,
+//       children: [
+//         Spacer(
+//           flex: 3,
+//         ),
+//         Text(
+//           'Great!',
+//           textAlign: TextAlign.center,
+//           style: TextStyle(
+//             color: Colors.white,
+//             fontSize: 32.sp,
+//             fontWeight: FontWeight.w700,
+//           ),
+//         ),
+//         SizedBox(height: 14.h),
+//         Text(
+//           "You've completed 1 photo review",
+//           textAlign: TextAlign.center,
+//           style: TextStyle(
+//             color: Colors.white.withValues(alpha: 0.8),
+//             fontSize: 16.sp,
+//             fontWeight: FontWeight.w400,
+//           ),
+//         ),
+//         SizedBox(height: 47.h),
+//         // Assets.images.iconPhotoSelectedPreviewFireworks.image(
+//         //   width: 158.w,
+//         //   height: 158.h,
+//         // ),
+//
+//         SizedBox(
+//             child: Lottie.asset(
+//           Assets.anim.animPhotoSelectedPreviewFireworks,
+//           width: 158.w,
+//           height: 158.w,
+//           repeat: false,
+//         )),
+//
+//         Spacer(
+//           flex: 5,
+//         ),
+//       ],
+//     ),
+//   );
+// }
+
+// Stack(children: [
+// Container(
+// child: SafeArea(
+// child: Column(
+// children: [
+// SizedBox(
+// child: Lottie.asset(
+// Assets.anim.animPhotoSelectedPreviewFireworks,
+// width: 150.w,
+// height: 150.w,
+// repeat: true,
+// )),
+// ],
+// )),
+// ),
+// IgnorePointer(
+// child: Assets.images.bgPhotoSelectedPreviewFinish.image(
+// width: 360.w,
+// height: 335.h,
+// ),
+// ),
+// ]);
+}

+ 36 - 0
lib/module/wallpaper/wallpaper_controller.dart

@@ -0,0 +1,36 @@
+import 'package:clean/base/base_controller.dart';
+import 'package:clean/data/api/response/wallpaper_list_response.dart';
+import 'package:clean/data/bean/wallpapers_bean.dart';
+import 'package:clean/data/repositories/wallpaper_repositories.dart';
+import 'package:clean/dialog/wallpaper_detail_dialog.dart';
+import 'package:clean/router/app_pages.dart';
+import 'package:get/get.dart';
+
+class WallPaperController extends BaseController {
+  RxList<WallpapersBean> get wallpapersList =>
+      wallpaperRepository.wallpapersList;
+
+  @override
+  void onInit() {
+    super.onInit();
+    wallpaperRepository.wallpaperList();
+  }
+
+  @override
+  void onReady() {
+    super.onReady();
+  }
+
+  @override
+  void onClose() {
+    super.onClose();
+  }
+
+  clickBack() {
+    Get.back();
+  }
+
+  clickWallpaper(WallpapersBean? wallpapersBean) {
+    wallpaperDetailDialog(wallpapersBean: wallpapersBean);
+  }
+}

+ 142 - 0
lib/module/wallpaper/wallpaper_view.dart

@@ -0,0 +1,142 @@
+import 'package:cached_network_image/cached_network_image.dart';
+import 'package:clean/base/base_page.dart';
+import 'package:clean/module/wallpaper/wallpaper_controller.dart';
+import 'package:clean/resource/assets.gen.dart';
+import 'package:clean/router/app_pages.dart';
+import 'package:flutter/Material.dart';
+import 'package:flutter/src/widgets/framework.dart';
+import 'package:flutter_screenutil/flutter_screenutil.dart';
+import 'package:get/get.dart';
+
+class WallPaperPage extends BasePage<WallPaperController> {
+  const WallPaperPage({Key? key}) : super(key: key);
+
+  static void start() {
+    Get.toNamed(RoutePath.wallpaper);
+  }
+
+  @override
+  bool immersive() {
+    // TODO: implement immersive
+    return true;
+  }
+
+  @override
+  bool statusBarDarkFont() {
+    return false;
+  }
+
+  @override
+  @override
+  Widget buildBody(BuildContext context) {
+    return Stack(
+      children: [
+        PopScope(
+          canPop: false,
+          onPopInvokedWithResult: (didPop, result) {
+            if (didPop) {
+              return;
+            }
+            controller.clickBack();
+          },
+          child: SafeArea(
+            child: SizedBox(
+              width: double.infinity,
+              height: double.infinity,
+              child: Column(
+                children: [
+                  _titleCard(),
+                  Expanded(
+                    child: SingleChildScrollView(
+                      child: Column(
+                        crossAxisAlignment: CrossAxisAlignment.start,
+                        children: [
+                          Container(
+                            padding: EdgeInsets.symmetric(horizontal: 16.w),
+                            child: Text(
+                              "Wallpaper",
+                              style: TextStyle(
+                                color: Colors.white,
+                                fontSize: 24.sp,
+                                fontWeight: FontWeight.w700,
+                              ),
+                            ),
+                          ),
+                          SizedBox(height: 6.h),
+                          Container(
+                            padding: EdgeInsets.symmetric(horizontal: 16.w),
+                            child: Obx(() {
+                              return GridView.builder(
+                                gridDelegate:
+                                    SliverGridDelegateWithFixedCrossAxisCount(
+                                  crossAxisCount: 2,
+                                  childAspectRatio: 9 / 16,
+                                  crossAxisSpacing: 16.w,
+                                  mainAxisSpacing: 16.w,
+                                ),
+                                itemCount: controller.wallpapersList.length,
+                                physics: NeverScrollableScrollPhysics(),
+                                shrinkWrap: true,
+                                itemBuilder: (context, index) {
+                                  return GestureDetector(
+                                      onTap: () {
+                                        controller.clickWallpaper(
+                                            controller.wallpapersList[index]);
+                                      },
+                                      child: ClipRRect(
+                                        borderRadius:
+                                            BorderRadius.circular(12.r),
+                                        child: CachedNetworkImage(
+                                          width: 156.w,
+                                          height: 277.w,
+                                          imageUrl: controller
+                                                  .wallpapersList[index]
+                                                  .thumbUrl ??
+                                              "",
+                                          fit: BoxFit.cover,
+                                        ),
+                                      ));
+                                },
+                              );
+                            }),
+                          ),
+                          SizedBox(height: 16.h),
+                        ],
+                      ),
+                    ),
+                  ),
+                ],
+              ),
+            ),
+          ),
+        ),
+        IgnorePointer(
+          child: Assets.images.bgHome.image(
+            width: 360.w,
+            height: 234.h,
+          ),
+        )
+      ],
+    );
+  }
+
+  Widget _titleCard() {
+    return Container(
+      alignment: Alignment.centerLeft,
+      padding:
+          EdgeInsets.only(left: 16.w, top: 14.h, right: 16.w, bottom: 20.h),
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          GestureDetector(
+            onTap: () => controller.clickBack(),
+            child: Assets.images.iconBackArrow.image(
+              width: 28.w,
+              height: 28.h,
+            ),
+          ),
+        ],
+      ),
+    );
+  }
+}

+ 19 - 1
lib/router/app_pages.dart

@@ -20,9 +20,15 @@ import 'package:clean/module/setting/setting_controller.dart';
 import 'package:clean/module/setting/setting_view.dart';
 import 'package:clean/module/similar_photo/similar_photo_controller.dart';
 import 'package:clean/module/similar_photo/similar_photo_view.dart';
+import 'package:clean/module/splash/intro/intro_controller.dart';
+import 'package:clean/module/splash/intro/intro_view.dart';
 import 'package:clean/module/store/store_controller.dart';
 import 'package:clean/module/store/store_view.dart';
-import 'package:flutter/cupertino.dart';
+import 'package:clean/module/splash/splash_controller.dart';
+import 'package:clean/module/splash/splash_view.dart';
+import 'package:clean/module/wallpaper/wallpaper_controller.dart';
+import 'package:clean/module/wallpaper/wallpaper_view.dart';
+
 import 'package:get/get.dart';
 
 import '../module/browser/browser_controller.dart';
@@ -38,6 +44,7 @@ abstract class AppPage {
 }
 
 abstract class RoutePath {
+
   static const browser = '/browser';
   static const mainTab = '/mainTab';
   static const privacy = '/privacy';
@@ -52,6 +59,9 @@ abstract class RoutePath {
   static const setting = '/setting';
   static const analysis = '/analysis';
   static const photoSelectedPreview = '/photoSelectedPreview';
+  static const splash = '/splash';
+  static const wallpaper = '/wallpaper';
+  static const intro = '/intro';
 }
 
 class AppBinding extends Bindings {
@@ -73,12 +83,17 @@ class AppBinding extends Bindings {
     lazyPut(() => SettingController());
     lazyPut(() => AnalysisController());
     lazyPut(() => PhotoSelectedPreviewController());
+    lazyPut(()=>SplashController());
+    lazyPut(()=>WallPaperController());
+    lazyPut(()=>IntroController());
   }
 
   void lazyPut<S>(InstanceBuilderCallback<S> builder) {
     Get.lazyPut(builder, fenix: true);
   }
 
+
+
 }
 
 final generalPages = [
@@ -96,4 +111,7 @@ final generalPages = [
   GetPage(name: RoutePath.photoSelectedPreview, page: () => PhotoSelectedPreviewPage()),
   GetPage(name: RoutePath.setting, page: () => SettingPage()),
   GetPage(name: RoutePath.analysis, page: () => AnalysisPage()),
+  GetPage(name: RoutePath.splash, page: () => SplashPage()),
+  GetPage(name: RoutePath.wallpaper, page: () => WallPaperPage()),
+  GetPage(name: RoutePath.intro, page: () => IntroPage()),
 ];

+ 7 - 1
pubspec.yaml

@@ -47,6 +47,11 @@ dependencies:
   # 包信息
   package_info_plus: ^8.1.1
 
+  #网络图片
+  cached_network_image: ^3.4.1
+  # 文件缓存
+  flutter_cache_manager: ^3.4.1
+
   # 隐私追踪
   app_tracking_transparency: ^2.0.5
 
@@ -56,7 +61,8 @@ dependencies:
   #本地化
   flutter_localizations:
     sdk: flutter
-
+  # 图片保存
+  image_gallery_saver: ^2.0.3
   # 圆形进度条
   syncfusion_flutter_charts: ^28.1.38
   # 卡片滑动