feat(review): 集成iOS应用内评分功能

- 新增iOS原生模块AppStoreReviewManager,封装StoreKit评分请求
- 实现appStoreReviewService服务层,管理评分请求时间间隔(14天)
- 在关键用户操作后触发评分请求:完成挑战、记录服药、记录体重、记录饮水
- 优化通知设置页面UI,改进设置项布局和视觉层次
- 调整用药卡片样式,优化状态显示和文字大小
- 新增配置检查脚本check-app-review-setup.sh
- 修改喝水提醒默认状态为关闭

评分请求策略:
- 仅iOS 14.0+支持
- 自动控制请求频率,避免过度打扰用户
- 延迟1秒执行,不阻塞主业务流程
- 所有评分请求均做错误处理,确保不影响核心功能
This commit is contained in:
richarjiang
2025-11-24 10:06:18 +08:00
parent 8cbf6be50a
commit c1c9f22111
15 changed files with 823 additions and 335 deletions

View File

@@ -0,0 +1,20 @@
//
// AppStoreReviewManager.m
// OutLive
//
// Objective-C Swift React Native
//
#import <React/RCTBridgeModule.h>
@interface RCT_EXTERN_MODULE(AppStoreReviewManager, NSObject)
//
RCT_EXTERN_METHOD(requestReview:(RCTPromiseResolveBlock)resolver
rejecter:(RCTPromiseRejectBlock)rejecter)
//
RCT_EXTERN_METHOD(canRequestReview:(RCTPromiseResolveBlock)resolver
rejecter:(RCTPromiseRejectBlock)rejecter)
@end

View File

@@ -0,0 +1,85 @@
//
// AppStoreReviewManager.swift
// OutLive
//
// iOS
// 使 StoreKit SKStoreReviewController
//
import Foundation
import StoreKit
import React
@objc(AppStoreReviewManager)
class AppStoreReviewManager: NSObject {
@objc
static func moduleName() -> String! {
return "AppStoreReviewManager"
}
///
/// JavaScript
/// iOS
@objc
func requestReview(
_ resolver: @escaping RCTPromiseResolveBlock,
rejecter: @escaping RCTPromiseRejectBlock
) {
DispatchQueue.main.async {
// iOS SKStoreReviewController iOS 14.0+
if #available(iOS 14.0, *) {
//
if let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene {
//
SKStoreReviewController.requestReview(in: scene)
resolver([
"success": true,
"message": "Review request sent successfully"
])
} else {
rejecter(
"NO_SCENE",
"Unable to find active window scene",
nil
)
}
} else {
// iOS 14
rejecter(
"VERSION_NOT_SUPPORTED",
"SKStoreReviewController requires iOS 14.0 or later",
nil
)
}
}
}
///
/// iOS JS
@objc
func canRequestReview(
_ resolver: @escaping RCTPromiseResolveBlock,
rejecter: @escaping RCTPromiseRejectBlock
) {
// iOS 14.0+
if #available(iOS 14.0, *) {
resolver([
"canRequest": true,
"systemVersion": UIDevice.current.systemVersion
])
} else {
resolver([
"canRequest": false,
"systemVersion": UIDevice.current.systemVersion,
"reason": "Requires iOS 14.0 or later"
])
}
}
@objc
static func requiresMainQueueSetup() -> Bool {
return true
}
}