修改权限申请文案

This commit is contained in:
Fson 2024-08-19 13:53:06 +08:00
parent 4072fe7c8d
commit 4092c0b235
7 changed files with 226 additions and 221 deletions

View File

@ -399,7 +399,7 @@
CODE_SIGN_IDENTITY = "Apple Distribution"; CODE_SIGN_IDENTITY = "Apple Distribution";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 6; CURRENT_PROJECT_VERSION = 8;
DART_OBFUSCATION = true; DART_OBFUSCATION = true;
DEVELOPMENT_TEAM = TW3K3253KL; DEVELOPMENT_TEAM = TW3K3253KL;
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = TW3K3253KL; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = TW3K3253KL;
@ -545,7 +545,7 @@
CODE_SIGN_IDENTITY = "Apple Distribution"; CODE_SIGN_IDENTITY = "Apple Distribution";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 6; CURRENT_PROJECT_VERSION = 8;
DART_OBFUSCATION = true; DART_OBFUSCATION = true;
DEVELOPMENT_TEAM = TW3K3253KL; DEVELOPMENT_TEAM = TW3K3253KL;
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = TW3K3253KL; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = TW3K3253KL;
@ -581,7 +581,7 @@
CODE_SIGN_IDENTITY = "Apple Distribution"; CODE_SIGN_IDENTITY = "Apple Distribution";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 6; CURRENT_PROJECT_VERSION = 8;
DART_OBFUSCATION = true; DART_OBFUSCATION = true;
DEVELOPMENT_TEAM = TW3K3253KL; DEVELOPMENT_TEAM = TW3K3253KL;
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = TW3K3253KL; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = TW3K3253KL;

View File

@ -32,11 +32,11 @@
<true/> <true/>
</dict> </dict>
<key>NSCameraUsageDescription</key> <key>NSCameraUsageDescription</key>
<string>TThis enables you to take and upload photos to your private space. Please grant camera access.</string> <string>Visual Wallpaper needs access to your camera to take photos for creating custom wallpapers. The photos you take will only be used to make personalized wallpapers within the app.</string>
<key>NSPhotoLibraryAddUsageDescription</key> <key>NSPhotoLibraryAddUsageDescription</key>
<string>We need access to your photo album so you can save wallpapers from the app to your album.</string> <string>We need access to your photo album so you can save wallpapers from the app to your album.</string>
<key>NSPhotoLibraryUsageDescription</key> <key>NSPhotoLibraryUsageDescription</key>
<string>This enables you to upload photos and save wallpapers. Please grant photo library access.</string> <string>This enables you to upload photos and save wallpapers.</string>
<key>NSUserTrackingUsageDescription</key> <key>NSUserTrackingUsageDescription</key>
<string>We need your permission to access the advertising identifier to provide better ad services.</string> <string>We need your permission to access the advertising identifier to provide better ad services.</string>
<key>CFBundleURLTypes</key> <key>CFBundleURLTypes</key>

View File

@ -58,195 +58,197 @@ class _PinCodeVerificationScreenState extends State<PinCodeVerificationScreen> {
backgroundColor: Colors.black, backgroundColor: Colors.black,
key: scaffoldKey, key: scaffoldKey,
body: SafeArea( body: SafeArea(
child: Container( child: SingleChildScrollView(
margin: EdgeInsets.only(top: 94.w), child: Container(
height: MediaQuery.of(context).size.height, margin: EdgeInsets.only(top: 94.h),
width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height - MediaQuery.of(context).padding.top - kBottomNavigationBarHeight - 94.h,
child: Column( width: MediaQuery.of(context).size.width,
children: [ child: Column(
Row( children: [
mainAxisAlignment: MainAxisAlignment.center, Row(
children: [ mainAxisAlignment: MainAxisAlignment.center,
Column( children: [
crossAxisAlignment: CrossAxisAlignment.start, Column(
children: [ crossAxisAlignment: CrossAxisAlignment.start,
Text( children: [
'Please input a', Text(
style: TextStyle( 'Please input a',
fontWeight: FontWeight.w700, style: TextStyle(
fontSize: 28.sp, fontWeight: FontWeight.w700,
color: Colors.white, fontSize: 28.sp,
), color: Colors.white,
), ),
Text(
'password',
style: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 28.sp,
color: Colors.white,
),
)
],
),
Container(
clipBehavior: Clip.hardEdge,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15.r),
),
child: Image.asset(
Assets.imagesCustomLock,
width: 100.w,
height: 100.w,
),
),
],
),
SizedBox(height: 64.w),
Form(
key: formKey,
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 8,
horizontal: 30,
).w,
child: PinCodeTextField(
appContext: context,
pastedTextStyle: TextStyle(
color: Colors.green.shade600,
fontWeight: FontWeight.bold,
),
dialogConfig: DialogConfig(platform: PinCodePlatform.iOS),
length: 4,
obscureText: true,
obscuringCharacter: '*',
animationType: AnimationType.fade,
pinTheme: PinTheme(
activeColor: const Color(0xff262626),
selectedColor: const Color(0xff262626),
selectedFillColor: Colors.grey,
inactiveFillColor: const Color(0xff262626),
errorBorderColor: const Color(0xff262626),
inactiveColor: const Color(0xff262626),
shape: PinCodeFieldShape.box,
borderRadius: BorderRadius.circular(30.r),
fieldHeight: 58.w,
fieldWidth: 58.w,
activeFillColor: hasError
? const Color(0xff262626)
: const Color(0xff262626),
),
showCursor: false,
animationDuration: const Duration(milliseconds: 300),
textStyle: TextStyle(
fontSize: 32.sp,
fontWeight: FontWeight.w700,
color: Colors.white,
height: 2.0,
),
backgroundColor: Colors.transparent,
enableActiveFill: true,
errorAnimationController: errorController,
controller: textEditingController,
keyboardType: TextInputType.number,
boxShadows: const [
BoxShadow(
offset: Offset(0, 1),
color: Colors.black12,
blurRadius: 30,
), ),
Text(
'password',
style: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 28.sp,
color: Colors.white,
),
)
], ],
onCompleted: (v) {}, ),
onChanged: (value) { Container(
setState(() { clipBehavior: Clip.hardEdge,
currentText = value; decoration: BoxDecoration(
}); borderRadius: BorderRadius.circular(15.r),
}, ),
beforeTextPaste: (text) { child: Image.asset(
setState(() { Assets.imagesCustomLock,
currentText = text!; width: 100.w,
}); height: 100.w,
return true; ),
}, ),
)), ],
), ),
Visibility( SizedBox(height: 64.w),
visible: widget.checkPassword == "", Form(
child: Text( key: formKey,
"First input as password", child: Padding(
style: TextStyle( padding: const EdgeInsets.symmetric(
color: Colors.red, vertical: 8,
fontSize: 14.sp, horizontal: 30,
).w,
child: PinCodeTextField(
appContext: context,
pastedTextStyle: TextStyle(
color: Colors.green.shade600,
fontWeight: FontWeight.bold,
),
dialogConfig: DialogConfig(platform: PinCodePlatform.iOS),
length: 4,
obscureText: true,
obscuringCharacter: '*',
animationType: AnimationType.fade,
pinTheme: PinTheme(
activeColor: const Color(0xff262626),
selectedColor: const Color(0xff262626),
selectedFillColor: Colors.grey,
inactiveFillColor: const Color(0xff262626),
errorBorderColor: const Color(0xff262626),
inactiveColor: const Color(0xff262626),
shape: PinCodeFieldShape.box,
borderRadius: BorderRadius.circular(30.r),
fieldHeight: 58.w,
fieldWidth: 58.w,
activeFillColor: hasError
? const Color(0xff262626)
: const Color(0xff262626),
),
showCursor: false,
animationDuration: const Duration(milliseconds: 300),
textStyle: TextStyle(
fontSize: 32.sp,
fontWeight: FontWeight.w700,
color: Colors.white,
height: 2.0,
),
backgroundColor: Colors.transparent,
enableActiveFill: true,
errorAnimationController: errorController,
controller: textEditingController,
keyboardType: TextInputType.number,
boxShadows: const [
BoxShadow(
offset: Offset(0, 1),
color: Colors.black12,
blurRadius: 30,
),
],
onCompleted: (v) {},
onChanged: (value) {
setState(() {
currentText = value;
});
},
beforeTextPaste: (text) {
setState(() {
currentText = text!;
});
return true;
},
)),
),
Visibility(
visible: widget.checkPassword == "",
child: Text(
"First input as password",
style: TextStyle(
color: Colors.red,
fontSize: 14.sp,
),
), ),
), ),
), GestureDetector(
GestureDetector( onTap: () {
onTap: () { formKey.currentState?.validate();
formKey.currentState?.validate(); if (currentText.length == 4 && widget.checkPassword == "") {
if (currentText.length == 4 && widget.checkPassword == "") { UPCache.getInstance()
UPCache.getInstance() .setData("custom_password", currentText);
.setData("custom_password", currentText);
widget.callback();
} else if (currentText.length != 4 ||
currentText != widget.checkPassword) {
errorController.add(ErrorAnimationType
.shake); // Triggering error shake animation
setState(() {
hasError = true;
textEditingController.clear();
});
} else {
InterstitialAdManager().showAdIfReady(onTap: () {
widget.callback(); widget.callback();
} else if (currentText.length != 4 ||
currentText != widget.checkPassword) {
errorController.add(ErrorAnimationType
.shake); // Triggering error shake animation
setState(() { setState(() {
hasError = false; hasError = true;
textEditingController.clear();
}); });
}); } else {
} InterstitialAdManager().showAdIfReady(onTap: () {
}, widget.callback();
child: Container( setState(() {
margin: const EdgeInsets.symmetric( hasError = false;
vertical: 24, });
horizontal: 40, });
).w, }
padding: const EdgeInsets.symmetric( },
vertical: 17, child: Container(
).w, margin: const EdgeInsets.symmetric(
decoration: BoxDecoration( vertical: 24,
borderRadius: BorderRadius.circular(30.r), horizontal: 40,
gradient: const LinearGradient( ).w,
begin: Alignment.topRight, padding: const EdgeInsets.symmetric(
end: Alignment.bottomLeft, vertical: 17,
colors: [ ).w,
Color(0xffBEEF32), decoration: BoxDecoration(
Color(0xff2795E5), borderRadius: BorderRadius.circular(30.r),
Color(0xff8041FD), gradient: const LinearGradient(
], begin: Alignment.topRight,
end: Alignment.bottomLeft,
colors: [
Color(0xffBEEF32),
Color(0xff2795E5),
Color(0xff8041FD),
],
),
), ),
), child: Center(
child: Center( child: Text(
child: Text( "Confirm",
"Confirm", style: TextStyle(
style: TextStyle( color: Colors.white,
color: Colors.white, fontSize: 18.sp,
fontSize: 18.sp, fontWeight: FontWeight.bold),
fontWeight: FontWeight.bold), ),
), ),
), ),
), ),
), GestureDetector(
GestureDetector( child: Text(
child: Text( "Clear",
"Clear", style: TextStyle(
style: TextStyle( color: Colors.white,
color: Colors.white, fontSize: 18.sp,
fontSize: 18.sp, ),
), ),
onTap: () {
textEditingController.clear();
},
), ),
onTap: () { ],
textEditingController.clear(); ),
},
),
],
), ),
), ),
), ),

View File

@ -1,11 +1,18 @@
// Author: fengshengxiong
// Date: 2024/5/10
// Description:
import 'dart:io';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
import 'package:wallpaperx/common/components/dialog/remind_dialog.dart'; import 'package:wallpaperx/common/components/dialog/remind_dialog.dart';
import 'package:wallpaperx/global/app_config.dart';
class PermissionUtil { class PermissionUtil {
/// ///
/// [permissionList] /// [permissionList]
static Future<bool> checkPermission(List<Permission> permissionList) async { static Future<bool> checkPermission(List<Permission> permissionList, {bool showDialog = true}) async {
// //
List<Permission> newPermissionList = []; List<Permission> newPermissionList = [];
// //
@ -21,19 +28,19 @@ class PermissionUtil {
if (newPermissionList.isNotEmpty) { if (newPermissionList.isNotEmpty) {
PermissionStatus permissionStatus = await _requestPermission(newPermissionList); PermissionStatus permissionStatus = await _requestPermission(newPermissionList);
switch (permissionStatus) { switch (permissionStatus) {
// //
case PermissionStatus.denied: case PermissionStatus.denied:
showFailedDialog(newPermissionList); if (showDialog) _showFailedDialog(newPermissionList);
return false; return false;
// //
case PermissionStatus.granted: case PermissionStatus.granted:
case PermissionStatus.limited: case PermissionStatus.limited:
case PermissionStatus.provisional:
return true; return true;
// //
case PermissionStatus.provisional:
case PermissionStatus.restricted: case PermissionStatus.restricted:
case PermissionStatus.permanentlyDenied: case PermissionStatus.permanentlyDenied:
showFailedDialog(newPermissionList, isPermanentlyDenied: true); if (showDialog) _showFailedDialog(newPermissionList, isPermanentlyDenied: true);
break; break;
} }
} else { } else {
@ -55,58 +62,53 @@ class PermissionUtil {
return currentPermissionStatus; return currentPermissionStatus;
} }
///
static Future<bool> checkLocationAlways() async { static Future<bool> checkLocationAlways() async {
// //
// Android没有这一步 ios会先访问这个再访问其他的 // Android没有这一步 ios会先访问这个再访问其他的
PermissionStatus status = PermissionStatus.granted; PermissionStatus status1 = PermissionStatus.granted;
status = await _checkSinglePermission(Permission.locationWhenInUse); status1 = await _checkSinglePermission(Permission.locationWhenInUse);
// //
PermissionStatus status2 = PermissionStatus.denied; PermissionStatus status2 = PermissionStatus.denied;
// //
if (status.isGranted) { if (status1.isGranted) {
status2 = await _checkSinglePermission(Permission.locationAlways); status2 = await _checkSinglePermission(Permission.locationAlways);
} }
// //
if (status.isGranted && status2.isGranted) { if (status1.isGranted && status2.isGranted) {
return true; return true;
//
} else if (status.isDenied || status2.isDenied) {
showFailedDialog(
[Permission.locationWhenInUse, Permission.locationAlways]);
} else { } else {
showFailedDialog( //
[Permission.locationWhenInUse, Permission.locationAlways], _showFailedDialog([Permission.locationWhenInUse, Permission.locationAlways],
isPermanentlyDenied: true, isPermanentlyDenied: Platform.isIOS ? true : false,
); );
} }
return false; return false;
} }
///
static _checkSinglePermission(Permission permission) async { static _checkSinglePermission(Permission permission) async {
// //
PermissionStatus status = await permission.status; PermissionStatus status = await permission.status;
PermissionStatus currentPermissionStatus = PermissionStatus.granted; PermissionStatus currentPermissionStatus = PermissionStatus.granted;
// //
if (!status.isGranted) { if (!status.isGranted) {
currentPermissionStatus = await _requestPermission([permission]); currentPermissionStatus = await _requestPermission([permission]);
} }
// //
return currentPermissionStatus; return currentPermissionStatus;
} }
/// ///
static showFailedDialog(List<Permission> permissionList, {bool isPermanentlyDenied = false}) async { static _showFailedDialog(List<Permission> permissionList, {bool isPermanentlyDenied = false}) async {
Get.dialog( Get.dialog(
barrierDismissible: false, barrierDismissible: false,
RemindDialog( RemindDialog(
content: await _getInstructions(permissionList), content: await _getDescription(permissionList),
confirmText: isPermanentlyDenied ? 'Go Settings' : 'Confirm', confirmText: isPermanentlyDenied ? 'Go open' : 'Confirm',
confirmOnTap: () { confirmOnTap: () {
if (isPermanentlyDenied) { if (isPermanentlyDenied) {
openAppSettings(); openAppSettings();
@ -118,24 +120,26 @@ class PermissionUtil {
); );
} }
/// 使 ///
static Future<String> _getInstructions(List<Permission> permissionList) async { static Future<String> _getDescription(List<Permission> permissionList) async {
late Permission failedPermission; late Permission failedPermission;
//
for (Permission permission in permissionList) { for (Permission permission in permissionList) {
PermissionStatus status = await permission.status; if (!await permission.status.isGranted) {
//
if (!status.isGranted || !status.isLimited) {
failedPermission = permission; failedPermission = permission;
break; break;
} }
} }
String explain = '';
if (failedPermission == Permission.storage || failedPermission == Permission.photosAddOnly) { String description = '';
explain = 'We need access to your photo album so you can save wallpapers from the app to your album'; if (failedPermission == Permission.storage) {
description = '$appName needs access to your camera to take photos for creating custom wallpapers. The photos you take will only be used to make personalized wallpapers within the app.';
} else if (failedPermission == Permission.camera) {
description = 'This app can take photos and upload them to a private space.';
} else if (failedPermission == Permission.photos) {
description = 'This enables you to upload photos and save wallpapers.';
} else if (failedPermission == Permission.appTrackingTransparency) {
description = 'We need your permission to access the advertising identifier to provide better ad services.';
} }
return explain; return description;
} }
} }

View File

@ -4,7 +4,7 @@ const appName = 'Visual Wallpaper';
/// +3广 /// +3广
DateTime getGuaranteedDate () { DateTime getGuaranteedDate () {
DateTime? commitDate = DateUtils.getDateTime('2024-08-15 18:30:00'); DateTime? commitDate = DateUtils.getDateTime('2024-08-16 09:30:00');
if (commitDate != null) { if (commitDate != null) {
return commitDate.add(const Duration(days: 3)); return commitDate.add(const Duration(days: 3));
} else { } else {

View File

@ -1,7 +1,6 @@
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:flip_card/flip_card.dart'; import 'package:flip_card/flip_card.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';

View File

@ -2,7 +2,7 @@ name: wallpaperx
description: "A new Flutter project." description: "A new Flutter project."
publish_to: 'none' # Remove this line if you wish to publish to pub.dev publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 1.2.0+6 version: 1.2.0+8
environment: environment:
sdk: '>=3.4.1 <4.0.0' sdk: '>=3.4.1 <4.0.0'