1
@ -79,6 +79,14 @@
|
||||
039810D02ED54D370006E317 /* NRHomeCategoryTagView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039810CF2ED54D370006E317 /* NRHomeCategoryTagView.swift */; };
|
||||
039810D22ED54F190006E317 /* NRHomeNovelListTextCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039810D12ED54F190006E317 /* NRHomeNovelListTextCell.swift */; };
|
||||
67DC33BD353DB9F2D4C0FFE8 /* Pods_ReaderHive.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43E8F76284854E8FD006C875 /* Pods_ReaderHive.framework */; };
|
||||
85606A902EEBA8F3005D989D /* NRCoinsPackConfirmView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85606A8F2EEBA8F3005D989D /* NRCoinsPackConfirmView.swift */; };
|
||||
85606A922EEBB336005D989D /* NRCoinsPackConfirmItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85606A912EEBB336005D989D /* NRCoinsPackConfirmItemView.swift */; };
|
||||
85606A942EEBB3FE005D989D /* NRCoinsPackConfirmTitleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85606A932EEBB3FE005D989D /* NRCoinsPackConfirmTitleView.swift */; };
|
||||
85606A962EEBB733005D989D /* NRCoinsPackConfirmTipView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85606A952EEBB733005D989D /* NRCoinsPackConfirmTipView.swift */; };
|
||||
85606A982EEBC11D005D989D /* Date+NRAdd.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85606A972EEBC119005D989D /* Date+NRAdd.swift */; };
|
||||
85606A9A2EEBC26F005D989D /* NRCoinsPackViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85606A992EEBC26F005D989D /* NRCoinsPackViewController.swift */; };
|
||||
85606A9C2EEBE243005D989D /* NRCoinsPackHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85606A9B2EEBE243005D989D /* NRCoinsPackHeaderView.swift */; };
|
||||
85606A9F2EEBE95A005D989D /* NRDashedLineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85606A9E2EEBE95A005D989D /* NRDashedLineView.swift */; };
|
||||
F34348AF2ED5B85300AA7E70 /* NRExploreViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F34348AE2ED5B85300AA7E70 /* NRExploreViewController.swift */; };
|
||||
F34348B12ED5B9A400AA7E70 /* NRExploreNovelViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F34348B02ED5B9A400AA7E70 /* NRExploreNovelViewController.swift */; };
|
||||
F34348B32ED5BB6100AA7E70 /* NRExploreNovelMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F34348B22ED5BB6100AA7E70 /* NRExploreNovelMenuView.swift */; };
|
||||
@ -293,6 +301,14 @@
|
||||
33A96151B23BA2ED4F2CCF56 /* Pods-ReaderHive.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ReaderHive.release.xcconfig"; path = "Target Support Files/Pods-ReaderHive/Pods-ReaderHive.release.xcconfig"; sourceTree = "<group>"; };
|
||||
43E8F76284854E8FD006C875 /* Pods_ReaderHive.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ReaderHive.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
455BEF77457E224E14EB6CCA /* Pods-NovelReader.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NovelReader.release.xcconfig"; path = "Target Support Files/Pods-NovelReader/Pods-NovelReader.release.xcconfig"; sourceTree = "<group>"; };
|
||||
85606A8F2EEBA8F3005D989D /* NRCoinsPackConfirmView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRCoinsPackConfirmView.swift; sourceTree = "<group>"; };
|
||||
85606A912EEBB336005D989D /* NRCoinsPackConfirmItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRCoinsPackConfirmItemView.swift; sourceTree = "<group>"; };
|
||||
85606A932EEBB3FE005D989D /* NRCoinsPackConfirmTitleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRCoinsPackConfirmTitleView.swift; sourceTree = "<group>"; };
|
||||
85606A952EEBB733005D989D /* NRCoinsPackConfirmTipView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRCoinsPackConfirmTipView.swift; sourceTree = "<group>"; };
|
||||
85606A972EEBC119005D989D /* Date+NRAdd.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Date+NRAdd.swift"; sourceTree = "<group>"; };
|
||||
85606A992EEBC26F005D989D /* NRCoinsPackViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRCoinsPackViewController.swift; sourceTree = "<group>"; };
|
||||
85606A9B2EEBE243005D989D /* NRCoinsPackHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRCoinsPackHeaderView.swift; sourceTree = "<group>"; };
|
||||
85606A9E2EEBE95A005D989D /* NRDashedLineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRDashedLineView.swift; sourceTree = "<group>"; };
|
||||
C3BEE224CB3F55939653D26D /* Pods-NovelReader.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NovelReader.debug.xcconfig"; path = "Target Support Files/Pods-NovelReader/Pods-NovelReader.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
F34348AE2ED5B85300AA7E70 /* NRExploreViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRExploreViewController.swift; sourceTree = "<group>"; };
|
||||
F34348B02ED5B9A400AA7E70 /* NRExploreNovelViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRExploreNovelViewController.swift; sourceTree = "<group>"; };
|
||||
@ -631,6 +647,7 @@
|
||||
0398106E2ED053630006E317 /* Extension */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
85606A972EEBC119005D989D /* Date+NRAdd.swift */,
|
||||
F3B859602EE9126A0095A9CC /* Dictionary+NRAdd.swift */,
|
||||
F34990B62EDE78680039E939 /* UIScrollView+Refresh.swift */,
|
||||
F34348E62ED7F91500AA7E70 /* NSNumber+NRAdd.swift */,
|
||||
@ -737,6 +754,7 @@
|
||||
F343490F2ED9A77A00AA7E70 /* NRPanModalContentView.swift */,
|
||||
F34349112EDA84F100AA7E70 /* NRProgressView.swift */,
|
||||
F34990FA2EE121490039E939 /* NRLabel.swift */,
|
||||
85606A9E2EEBE95A005D989D /* NRDashedLineView.swift */,
|
||||
);
|
||||
path = View;
|
||||
sourceTree = "<group>";
|
||||
@ -1068,6 +1086,11 @@
|
||||
F3B859852EE972F70095A9CC /* NRConsumptionRecordsCell.xib */,
|
||||
F3B8598C2EEA51FE0095A9CC /* NRRewardCoinsCell.swift */,
|
||||
F3B859942EEA64430095A9CC /* NROrderRecordsCell.swift */,
|
||||
85606A8F2EEBA8F3005D989D /* NRCoinsPackConfirmView.swift */,
|
||||
85606A912EEBB336005D989D /* NRCoinsPackConfirmItemView.swift */,
|
||||
85606A932EEBB3FE005D989D /* NRCoinsPackConfirmTitleView.swift */,
|
||||
85606A952EEBB733005D989D /* NRCoinsPackConfirmTipView.swift */,
|
||||
85606A9B2EEBE243005D989D /* NRCoinsPackHeaderView.swift */,
|
||||
);
|
||||
path = V;
|
||||
sourceTree = "<group>";
|
||||
@ -1092,6 +1115,7 @@
|
||||
F3B859882EE97E1F0095A9CC /* NRRewardCoinsViewController.swift */,
|
||||
F3B8598E2EEA5B1C0095A9CC /* NROrderRecordsPageViewController.swift */,
|
||||
F3B859902EEA627F0095A9CC /* NROrderRecordsViewController.swift */,
|
||||
85606A992EEBC26F005D989D /* NRCoinsPackViewController.swift */,
|
||||
);
|
||||
path = VC;
|
||||
sourceTree = "<group>";
|
||||
@ -1226,14 +1250,10 @@
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-ReaderHive/Pods-ReaderHive-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-ReaderHive/Pods-ReaderHive-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ReaderHive/Pods-ReaderHive-frameworks.sh\"\n";
|
||||
@ -1275,6 +1295,8 @@
|
||||
F34348DB2ED6F80A00AA7E70 /* NRNovelReaderViewController.swift in Sources */,
|
||||
F34990B92EDEB1620039E939 /* NRHomeNovelModuleItem.swift in Sources */,
|
||||
F34349032ED943C300AA7E70 /* NRReadParser.swift in Sources */,
|
||||
85606A982EEBC11D005D989D /* Date+NRAdd.swift in Sources */,
|
||||
85606A922EEBB336005D989D /* NRCoinsPackConfirmItemView.swift in Sources */,
|
||||
0398106A2ED0505D0006E317 /* NRNetworkReachableManager.swift in Sources */,
|
||||
F34348C32ED6A20700AA7E70 /* NRExploreNovelContentViewController.swift in Sources */,
|
||||
F34991292EE285660039E939 /* NRShowRecommendPop.swift in Sources */,
|
||||
@ -1329,6 +1351,7 @@
|
||||
03980F882ED009EB0006E317 /* SceneDelegate.swift in Sources */,
|
||||
F34991232EE26EAC0039E939 /* NRAlert.swift in Sources */,
|
||||
F34348B72ED5C75800AA7E70 /* NRTableViewCell.swift in Sources */,
|
||||
85606A9C2EEBE243005D989D /* NRCoinsPackHeaderView.swift in Sources */,
|
||||
F34349102ED9A77A00AA7E70 /* NRPanModalContentView.swift in Sources */,
|
||||
F3B859892EE97E1F0095A9CC /* NRRewardCoinsViewController.swift in Sources */,
|
||||
039810CE2ED47A130006E317 /* CGMutablePath+NRRoundedCorner.swift in Sources */,
|
||||
@ -1359,6 +1382,7 @@
|
||||
0398109B2ED0692A0006E317 /* NRImageView.swift in Sources */,
|
||||
0398108A2ED0582F0006E317 /* NRDeviceId.swift in Sources */,
|
||||
F3B859812EE9716E0095A9CC /* NRBuyRecordsModel.swift in Sources */,
|
||||
85606A9A2EEBC26F005D989D /* NRCoinsPackViewController.swift in Sources */,
|
||||
F3B859952EEA64430095A9CC /* NROrderRecordsCell.swift in Sources */,
|
||||
0373D9542ED58AF00017DCC7 /* NRSearchInputView.swift in Sources */,
|
||||
F34348EB2ED82B4100AA7E70 /* NRNovelReadSet.swift in Sources */,
|
||||
@ -1375,6 +1399,7 @@
|
||||
039810622ED04F250006E317 /* NRNetwork.swift in Sources */,
|
||||
039810782ED054740006E317 /* NRHud.swift in Sources */,
|
||||
F34991032EE160F00039E939 /* NRUserAPI.swift in Sources */,
|
||||
85606A9F2EEBE95A005D989D /* NRDashedLineView.swift in Sources */,
|
||||
039810C42ED459440006E317 /* NRHomeNovelHotTagView.swift in Sources */,
|
||||
F34991122EE170E20039E939 /* NRWebView.swift in Sources */,
|
||||
F3B859402EE6787E0095A9CC /* NRLocalizedManager.swift in Sources */,
|
||||
@ -1416,11 +1441,13 @@
|
||||
F3B8598D2EEA51FE0095A9CC /* NRRewardCoinsCell.swift in Sources */,
|
||||
F34990F52EE0346B0039E939 /* NRNovelReadBaseViewController.swift in Sources */,
|
||||
039810642ED04F480006E317 /* NRTargetType.swift in Sources */,
|
||||
85606A962EEBB733005D989D /* NRCoinsPackConfirmTipView.swift in Sources */,
|
||||
F3B8595D2EE907710095A9CC /* NRIAPVerifyModel.swift in Sources */,
|
||||
F343491E2EDAD0AA00AA7E70 /* NRReadTheme.swift in Sources */,
|
||||
F3B8597D2EE9627B0095A9CC /* NRWalletHeaderView.swift in Sources */,
|
||||
039810872ED057260006E317 /* NRUserDefaultsKey.swift in Sources */,
|
||||
F34349222EDD227A00AA7E70 /* NRReadSettingSpacingView.swift in Sources */,
|
||||
85606A902EEBA8F3005D989D /* NRCoinsPackConfirmView.swift in Sources */,
|
||||
F34990F32EE02FD60039E939 /* NRNovelReadFinishViewController.swift in Sources */,
|
||||
F34348F92ED855AA00AA7E70 /* NRNovelReadContentViewController.swift in Sources */,
|
||||
039810A42ED072380006E317 /* NRHomeNovelListViewController.swift in Sources */,
|
||||
@ -1434,6 +1461,7 @@
|
||||
F3B859772EE95B220095A9CC /* NRMeVipView.swift in Sources */,
|
||||
F3B8594E2EE905A70095A9CC /* NRStoreAPI.swift in Sources */,
|
||||
0373D94F2ED58A1E0017DCC7 /* NRSearchViewController.swift in Sources */,
|
||||
85606A942EEBB3FE005D989D /* NRCoinsPackConfirmTitleView.swift in Sources */,
|
||||
0398108E2ED060020006E317 /* UIFont+NRAdd.swift in Sources */,
|
||||
F34348D32ED6E0F400AA7E70 /* NRMyListViewController.swift in Sources */,
|
||||
0398105C2ED047FE0006E317 /* NRTabBarController.swift in Sources */,
|
||||
@ -1481,7 +1509,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
DEVELOPMENT_TEAM = 9JR2Y32ZU3;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = ReaderHive/Source/Info.plist;
|
||||
@ -1520,11 +1548,9 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 9JR2Y32ZU3;
|
||||
DEVELOPMENT_TEAM = 9JR2Y32ZU3;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = ReaderHive/Source/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = ReaderHive;
|
||||
@ -1543,7 +1569,6 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lssj.ReaderHive;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = readerdev;
|
||||
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
|
||||
31
ReaderHive/Base/Extension/Date+NRAdd.swift
Normal file
@ -0,0 +1,31 @@
|
||||
//
|
||||
// Date.swift
|
||||
// ReaderHive
|
||||
//
|
||||
// Created by 澜声世纪 on 2025/12/12.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
extension Date {
|
||||
|
||||
///相差天数
|
||||
func nr_differenceDay(_ date: Date) -> Int {
|
||||
let dateComponents = Calendar.current.dateComponents([.day], from: self, to: date)
|
||||
return dateComponents.day ?? 0
|
||||
}
|
||||
|
||||
func nr_formatString(_ dateFormat: String) -> String {
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateFormat = dateFormat
|
||||
return formatter.string(from: self)
|
||||
}
|
||||
|
||||
///是否是今天
|
||||
var nr_isToday: Bool {
|
||||
get {
|
||||
return Calendar.current.isDateInToday(self)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -13,6 +13,7 @@ extension UIView {
|
||||
fileprivate struct AssociatedKeys {
|
||||
static var nr_roundedCorner: Int?
|
||||
static var nr_effect: Int?
|
||||
static var nr_border: Int?
|
||||
}
|
||||
|
||||
@objc public static func fa_Awake() {
|
||||
@ -24,6 +25,8 @@ extension UIView {
|
||||
|
||||
_updateRoundedCorner()
|
||||
|
||||
_updateBorder()
|
||||
|
||||
if let effectView = effectView, effectView.frame != self.bounds {
|
||||
effectView.frame = self.bounds
|
||||
}
|
||||
@ -66,6 +69,35 @@ extension UIView {
|
||||
|
||||
}
|
||||
|
||||
//MARK: -------------- 渐变边框 --------------
|
||||
extension UIView {
|
||||
private var borderImage: UIImage? {
|
||||
get {
|
||||
return objc_getAssociatedObject(self, &AssociatedKeys.nr_border) as? UIImage
|
||||
}
|
||||
set {
|
||||
objc_setAssociatedObject(self, &AssociatedKeys.nr_border, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
|
||||
}
|
||||
}
|
||||
|
||||
func nr_setBorder(_ image: UIImage?) {
|
||||
borderImage = image
|
||||
if let _ = image {
|
||||
_updateBorder()
|
||||
} else {
|
||||
layer.borderColor = nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private func _updateBorder() {
|
||||
guard let image = borderImage else { return }
|
||||
let size = self.bounds.size
|
||||
layer.borderColor = UIColor(patternImage: image.nr_resized(to: size)).cgColor
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//MARK: -------------- 模糊效果 --------------
|
||||
extension UIView {
|
||||
private var effectView: UIVisualEffectView? {
|
||||
|
||||
46
ReaderHive/Base/View/NRDashedLineView.swift
Normal file
@ -0,0 +1,46 @@
|
||||
//
|
||||
// NRDashedLineView.swift
|
||||
// ReaderHive
|
||||
//
|
||||
// Created by 澜声世纪 on 2025/12/12.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class NRDashedLineView: UIView {
|
||||
|
||||
var isHorizontal: Bool = true // 控制是横向还是纵向绘制
|
||||
|
||||
var lineWidth: CGFloat = 1.0
|
||||
|
||||
var lineColor: UIColor = .black.withAlphaComponent(0.25)
|
||||
|
||||
override func draw(_ rect: CGRect) {
|
||||
super.draw(rect)
|
||||
|
||||
// 获取当前的上下文
|
||||
guard let context = UIGraphicsGetCurrentContext() else { return }
|
||||
|
||||
// 设置线条颜色和宽度
|
||||
context.setStrokeColor(UIColor.red.cgColor)
|
||||
context.setLineWidth(lineWidth)
|
||||
|
||||
// 设置虚线样式
|
||||
context.setLineDash(phase: 0, lengths: [2, 2]) // 长度为6的线段和间隔为3的空白
|
||||
|
||||
// 根据方向绘制路径
|
||||
if isHorizontal {
|
||||
// 横向绘制
|
||||
context.move(to: CGPoint(x: 0, y: self.bounds.midY))
|
||||
context.addLine(to: CGPoint(x: self.bounds.width, y: self.bounds.midY))
|
||||
} else {
|
||||
// 纵向绘制
|
||||
context.move(to: CGPoint(x: self.bounds.midX, y: 0))
|
||||
context.addLine(to: CGPoint(x: self.bounds.midX, y: self.bounds.height))
|
||||
}
|
||||
|
||||
// 绘制路径
|
||||
context.strokePath()
|
||||
}
|
||||
|
||||
}
|
||||
@ -13,11 +13,14 @@ class NRLabel: UILabel {
|
||||
var textStartPoint: CGPoint?
|
||||
var textEndPoint: CGPoint?
|
||||
|
||||
var textColorImage: UIImage?
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
let size = self.bounds.size
|
||||
if let text = self.text, text.count > 0, let colors = self.textColors, let startPoint = self.textStartPoint, let endPoine = self.textEndPoint {
|
||||
if let image = self.textColorImage {
|
||||
self.textColor = UIColor(patternImage: image.nr_resized(to: size))
|
||||
} else if let text = self.text, text.count > 0, let colors = self.textColors, let startPoint = self.textStartPoint, let endPoine = self.textEndPoint {
|
||||
self.textColor = UIColor(patternImage: UIImage.nr_getGradientImage(size: size, colors: colors, startPoint: startPoint, endPoint: endPoine))
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ class NRPanModalContentView: HWPanModalContentView {
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
self.backgroundColor = .F_8_F_8_F_8
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
@ -43,7 +43,7 @@ class NRPanModalContentView: HWPanModalContentView {
|
||||
|
||||
override func backgroundConfig() -> HWBackgroundConfig {
|
||||
let config = HWBackgroundConfig()
|
||||
config.backgroundAlpha = 0.0
|
||||
config.backgroundAlpha = 0.5
|
||||
return config
|
||||
}
|
||||
|
||||
|
||||
@ -87,7 +87,7 @@ extension NRExploreNovelMenuView: NRWaterfallMutiSectionDelegate {
|
||||
|
||||
func heightForRowAtIndexPath(collectionView collection: UICollectionView, layout: NRWaterfallFlowLayout, indexPath: IndexPath, itemWidth: CGFloat) -> CGFloat {
|
||||
let item = self.viewModel?.menuDataArr[indexPath.row]
|
||||
let textHeight = item?.title?.size(.font(ofSize: 10, weight: .regular), .init(width: 60, height: 100)).height ?? 0
|
||||
let textHeight = item?.title?.size(.font(ofSize: 10, weight: .regular), .init(width: 60 - 4, height: 100)).height ?? 0
|
||||
return textHeight + 44
|
||||
}
|
||||
|
||||
|
||||
@ -39,7 +39,7 @@ class NRHomeNovelListViewController: NRViewController {
|
||||
return view
|
||||
}()
|
||||
|
||||
deinit {
|
||||
@MainActor deinit {
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
}
|
||||
|
||||
|
||||
@ -49,7 +49,7 @@ class NRHomeNovelViewController: NRViewController {
|
||||
return vc
|
||||
}()
|
||||
|
||||
deinit {
|
||||
@MainActor deinit {
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
}
|
||||
|
||||
|
||||
@ -7,11 +7,31 @@
|
||||
|
||||
import UIKit
|
||||
import SnapKit
|
||||
import YYCategories
|
||||
|
||||
class NRMeHeaderView: UITableViewHeaderFooterView {
|
||||
|
||||
// var contentHeight: CGFloat = 200
|
||||
|
||||
var userInfo: NRUserInfo? {
|
||||
didSet {
|
||||
avatarImageView.nr_setImage(userInfo?.avator)
|
||||
nickLabel.text = userInfo?.getNickName()
|
||||
idLabel.text = "ID:\(userInfo?.customer_id ?? "")"
|
||||
|
||||
coinsView.userInfo = userInfo
|
||||
|
||||
|
||||
stackView.nr_removeAllArrangedSubview()
|
||||
stackView.addArrangedSubview(coinsView)
|
||||
if userInfo?.is_vip == true {
|
||||
vipView.userInfo = userInfo
|
||||
stackView.addArrangedSubview(vipView)
|
||||
}
|
||||
stackView.addArrangedSubview(coinsPackView)
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var avatarImageView: UIImageView = {
|
||||
let imageView = NRImageView()
|
||||
imageView.layer.cornerRadius = 30
|
||||
@ -66,6 +86,11 @@ class NRMeHeaderView: UITableViewHeaderFooterView {
|
||||
|
||||
private lazy var coinsPackView: NRMeCoinsPackView = {
|
||||
let view = NRMeCoinsPackView()
|
||||
view.addGestureRecognizer(UITapGestureRecognizer(actionBlock: { [weak self] _ in
|
||||
guard let self = self else { return }
|
||||
let vc = NRCoinsPackViewController()
|
||||
self.viewController?.navigationController?.pushViewController(vc, animated: true)
|
||||
}))
|
||||
return view
|
||||
}()
|
||||
|
||||
@ -74,20 +99,10 @@ class NRMeHeaderView: UITableViewHeaderFooterView {
|
||||
return view
|
||||
}()
|
||||
|
||||
deinit {
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
}
|
||||
|
||||
override init(reuseIdentifier: String?) {
|
||||
super.init(reuseIdentifier: reuseIdentifier)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(userInfoUpdateNotification), name: NRLoginManager.userInfoUpdateNotification, object: nil)
|
||||
nr_setupUI()
|
||||
|
||||
userInfoUpdateNotification()
|
||||
|
||||
stackView.addArrangedSubview(coinsView)
|
||||
stackView.addArrangedSubview(vipView)
|
||||
stackView.addArrangedSubview(coinsPackView)
|
||||
}
|
||||
|
||||
|
||||
@ -95,15 +110,6 @@ class NRMeHeaderView: UITableViewHeaderFooterView {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
@objc private func userInfoUpdateNotification() {
|
||||
guard let userInfo = NRLoginManager.manager.userInfo else { return }
|
||||
|
||||
avatarImageView.nr_setImage(userInfo.avator)
|
||||
nickLabel.text = userInfo.family_name?.isEmpty != false ? "Visitor".localized : userInfo.family_name
|
||||
idLabel.text = "ID:\(userInfo.customer_id ?? "")"
|
||||
|
||||
coinsView.userInfo = userInfo
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -10,6 +10,16 @@ import SnapKit
|
||||
|
||||
class NRMeVipView: UIView {
|
||||
|
||||
var userInfo: NRUserInfo? {
|
||||
didSet {
|
||||
// titleLabel.text = "Weekly VIP".localized
|
||||
titleLabel.text = "VIP".localized
|
||||
|
||||
let date = Date(timeIntervalSince1970: userInfo?.vip_end_time ?? 0)
|
||||
timeLabel.text = "Expiration Time".localized + ":\(date.nr_formatString("yyyy-MM-dd"))"
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var contentView: UIView = {
|
||||
let view = UIView()
|
||||
view.backgroundColor = .F_2_EFEE
|
||||
@ -45,8 +55,7 @@ class NRMeVipView: UIView {
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
titleLabel.text = "Weekly VIP".localized
|
||||
timeLabel.text = "Expiration Time:2023-11-23"
|
||||
|
||||
|
||||
nr_setupUI()
|
||||
}
|
||||
|
||||
@ -32,9 +32,13 @@ class NRMeViewController: NRViewController {
|
||||
return tableView
|
||||
}()
|
||||
|
||||
@MainActor deinit {
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(userInfoUpdateNotification), name: NRLoginManager.userInfoUpdateNotification, object: nil)
|
||||
nr_setupUI()
|
||||
|
||||
}
|
||||
@ -53,6 +57,10 @@ class NRMeViewController: NRViewController {
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func userInfoUpdateNotification() {
|
||||
self.tableView.reloadData()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension NRMeViewController {
|
||||
@ -83,6 +91,7 @@ extension NRMeViewController: UITableViewDelegate, UITableViewDataSource {
|
||||
|
||||
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
|
||||
let view = tableView.dequeueReusableHeaderFooterView(withIdentifier: "header") as? NRMeHeaderView
|
||||
view?.userInfo = NRLoginManager.manager.userInfo
|
||||
return view
|
||||
}
|
||||
|
||||
|
||||
@ -66,7 +66,7 @@ class NRNovelDetailViewController: NRViewController {
|
||||
return recommandVC.collectionView
|
||||
}
|
||||
|
||||
deinit {
|
||||
@MainActor deinit {
|
||||
recommandListView.removeObserver(self, forKeyPath: "contentSize")
|
||||
}
|
||||
|
||||
|
||||
@ -26,7 +26,7 @@ class NRNovelReadContentViewController: NRNovelReadBaseViewController {
|
||||
return view
|
||||
}()
|
||||
|
||||
deinit {
|
||||
@MainActor deinit {
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
}
|
||||
|
||||
|
||||
@ -72,7 +72,7 @@ class NRNovelReaderViewController: NRViewController {
|
||||
return view
|
||||
}()
|
||||
|
||||
deinit {
|
||||
@MainActor deinit {
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
}
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
import UIKit
|
||||
import SmartCodable
|
||||
import StoreKit
|
||||
internal import StoreKit
|
||||
|
||||
class NRPayDateModel: NSObject, SmartCodable {
|
||||
|
||||
|
||||
41
ReaderHive/Class/Store/V/NRCoinsPackConfirmItemView.swift
Normal file
@ -0,0 +1,41 @@
|
||||
//
|
||||
// NRCoinsPackConfirmItemView.swift
|
||||
// ReaderHive
|
||||
//
|
||||
// Created by 澜声世纪 on 2025/12/12.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SnapKit
|
||||
|
||||
class NRCoinsPackConfirmItemView: UIView {
|
||||
|
||||
lazy var titleLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 18, weight: .bold)
|
||||
label.adjustsFontSizeToFitWidth = true
|
||||
label.textColor = .black
|
||||
label.textAlignment = .center
|
||||
return label
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
backgroundColor = .F_2_EFEE
|
||||
layer.cornerRadius = 8
|
||||
layer.masksToBounds = true
|
||||
|
||||
addSubview(titleLabel)
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.right.lessThanOrEqualToSuperview().offset(-16)
|
||||
make.top.equalToSuperview().offset(16)
|
||||
}
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
}
|
||||
126
ReaderHive/Class/Store/V/NRCoinsPackConfirmTipView.swift
Normal file
@ -0,0 +1,126 @@
|
||||
//
|
||||
// NRCoinsPackConfirmTipView.swift
|
||||
// ReaderHive
|
||||
//
|
||||
// Created by 澜声世纪 on 2025/12/12.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SnapKit
|
||||
|
||||
class NRCoinsPackConfirmTipView: NRCoinsPackConfirmItemView {
|
||||
|
||||
var list: [String]? {
|
||||
didSet {
|
||||
|
||||
self.stackView.nr_removeAllArrangedSubview()
|
||||
|
||||
list?.forEach {
|
||||
let view = NRCoinsPackConfirmTipView.ItemView()
|
||||
view.text = $0
|
||||
self.stackView.addArrangedSubview(view)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private lazy var lineView: UIView = {
|
||||
let view = UIView()
|
||||
view.backgroundColor = .white
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var stackView: UIStackView = {
|
||||
let view = UIStackView()
|
||||
view.axis = .vertical
|
||||
view.spacing = 24
|
||||
return view
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
self.titleLabel.text = "coins_pack_confirm_tip_title".localized
|
||||
|
||||
nr_setupUI()
|
||||
}
|
||||
|
||||
@MainActor required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
|
||||
extension NRCoinsPackConfirmTipView {
|
||||
|
||||
private func nr_setupUI() {
|
||||
addSubview(lineView)
|
||||
addSubview(stackView)
|
||||
|
||||
lineView.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(12)
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalTo(titleLabel.snp.bottom).offset(16)
|
||||
make.height.equalTo(1)
|
||||
}
|
||||
|
||||
stackView.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(16)
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalTo(lineView.snp.bottom).offset(16)
|
||||
make.bottom.equalToSuperview().offset(-16)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
extension NRCoinsPackConfirmTipView {
|
||||
|
||||
class ItemView: UIView {
|
||||
var text: String? {
|
||||
didSet {
|
||||
textLabel.text = text
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var iconImageView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "coins_icon_01"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var textLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 14, weight: .regular)
|
||||
label.textColor = .black
|
||||
label.numberOfLines = 0
|
||||
return label
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
addSubview(iconImageView)
|
||||
addSubview(textLabel)
|
||||
|
||||
iconImageView.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview()
|
||||
make.top.equalToSuperview()
|
||||
}
|
||||
|
||||
textLabel.snp.makeConstraints { make in
|
||||
make.left.equalTo(iconImageView.snp.right).offset(12)
|
||||
make.right.lessThanOrEqualToSuperview()
|
||||
make.top.equalToSuperview()
|
||||
make.bottom.equalToSuperview()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
75
ReaderHive/Class/Store/V/NRCoinsPackConfirmTitleView.swift
Normal file
@ -0,0 +1,75 @@
|
||||
//
|
||||
// NRCoinsPackConfirmTitleView.swift
|
||||
// ReaderHive
|
||||
//
|
||||
// Created by 澜声世纪 on 2025/12/12.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SnapKit
|
||||
|
||||
class NRCoinsPackConfirmTitleView: NRCoinsPackConfirmItemView {
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
titleLabel.text = "Bonus You Get".localized
|
||||
|
||||
let view1 = getItemView(image: UIImage(named: "gift_icon_02"), text: "Weekly Refill Package".localized)
|
||||
let view2 = getItemView(image: UIImage(named: "calendar_icon_01"), text: "Daily Bonuses".localized)
|
||||
|
||||
addSubview(view1)
|
||||
addSubview(view2)
|
||||
|
||||
view1.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(12)
|
||||
make.top.equalTo(titleLabel.snp.bottom).offset(8)
|
||||
make.height.equalTo(83)
|
||||
make.bottom.equalToSuperview().offset(-16)
|
||||
}
|
||||
|
||||
view2.snp.makeConstraints { make in
|
||||
make.left.equalTo(view1.snp.right).offset(12)
|
||||
make.right.equalToSuperview().offset(-12)
|
||||
make.width.height.top.equalTo(view1)
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
private func getItemView(image: UIImage?, text: String) -> UIView {
|
||||
let view = UIView()
|
||||
view.backgroundColor = .white
|
||||
view.layer.cornerRadius = 8
|
||||
view.layer.masksToBounds = true
|
||||
|
||||
let imageView = UIImageView(image: image)
|
||||
imageView.setContentHuggingPriority(.required, for: .horizontal)
|
||||
imageView.setContentCompressionResistancePriority(.required, for: .horizontal)
|
||||
|
||||
let label = UILabel()
|
||||
label.numberOfLines = 0
|
||||
label.font = .font(ofSize: 12, weight: .init(800))
|
||||
label.textColor = .black
|
||||
label.text = text
|
||||
|
||||
|
||||
view.addSubview(imageView)
|
||||
view.addSubview(label)
|
||||
|
||||
imageView.snp.makeConstraints { make in
|
||||
make.centerY.equalToSuperview()
|
||||
make.left.equalToSuperview().offset(8)
|
||||
}
|
||||
|
||||
label.snp.makeConstraints { make in
|
||||
make.centerY.equalToSuperview()
|
||||
make.left.equalTo(imageView.snp.right).offset(8)
|
||||
make.right.lessThanOrEqualToSuperview().offset(-8)
|
||||
}
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
}
|
||||
202
ReaderHive/Class/Store/V/NRCoinsPackConfirmView.swift
Normal file
@ -0,0 +1,202 @@
|
||||
//
|
||||
// NRCoinsPackConfirmView.swift
|
||||
// ReaderHive
|
||||
//
|
||||
// Created by 澜声世纪 on 2025/12/12.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SnapKit
|
||||
import HWPanModal
|
||||
internal import StoreKit
|
||||
|
||||
class NRCoinsPackConfirmView: NRPanModalContentView {
|
||||
|
||||
|
||||
var buyFinishHandle: (() -> Void)?
|
||||
|
||||
var shortPlayId: String?
|
||||
var videoId: String?
|
||||
|
||||
var model: NRPayItem? {
|
||||
didSet {
|
||||
tipView.list = model?.ext_info?.sub_coins_txt_list
|
||||
|
||||
var price = model?.price ?? ""
|
||||
if model?.discount_type == 1, let introductoryPrice = model?.introductionaryOffer {
|
||||
price = introductoryPrice.price.stringValue
|
||||
} else if model?.discount_type == 2, let discount = model?.promotionalOffers?.first {
|
||||
price = discount.price.stringValue
|
||||
}
|
||||
|
||||
priceLabel.text = "\(model?.currency ?? "")\(price)/\(model?.getTimeString() ?? "")"
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var bgView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "bg_image_01"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var titleLabel: NRLabel = {
|
||||
let label = NRLabel()
|
||||
label.font = .font(ofSize: 24, weight: .bold)
|
||||
label.textColorImage = UIImage(named: "gradient_color_01")
|
||||
label.text = "What You Get".localized
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var closeButton: UIButton = {
|
||||
let button = UIButton(type: .custom, primaryAction: UIAction(handler: { [weak self] _ in
|
||||
guard let self = self else { return }
|
||||
Task {
|
||||
await self.dismiss(animated: true)
|
||||
}
|
||||
}))
|
||||
button.setImage(UIImage(named: "close_icon_02"), for: .normal)
|
||||
return button
|
||||
}()
|
||||
|
||||
private lazy var scrollView: NRScrollView = {
|
||||
let scrollView = NRScrollView()
|
||||
scrollView.addObserver(self, forKeyPath: "contentSize", context: nil)
|
||||
return scrollView
|
||||
}()
|
||||
|
||||
private lazy var titleView: NRCoinsPackConfirmTitleView = {
|
||||
let view = NRCoinsPackConfirmTitleView()
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var tipView: NRCoinsPackConfirmTipView = {
|
||||
let view = NRCoinsPackConfirmTipView()
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var priceLabel: UILabel = {
|
||||
let label = NRLabel()
|
||||
label.font = .font(ofSize: 18, weight: .bold)
|
||||
label.textColorImage = UIImage(named: "gradient_color_01")
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var buyButton: UIButton = {
|
||||
var configuration = UIButton.Configuration.plain()
|
||||
configuration.background.image = UIImage(named: "gradient_color_01")
|
||||
configuration.background.cornerRadius = 24
|
||||
configuration.attributedTitle = AttributedString("Continue".localized, attributes: AttributeContainer([
|
||||
.font : UIFont.font(ofSize: 14, weight: .bold),
|
||||
.foregroundColor : UIColor.white
|
||||
]))
|
||||
|
||||
let button = UIButton(configuration: configuration, primaryAction: UIAction(handler: { [weak self] _ in
|
||||
guard let self = self else { return }
|
||||
self.buyCoinsPack()
|
||||
}))
|
||||
|
||||
return button
|
||||
}()
|
||||
|
||||
@MainActor deinit {
|
||||
scrollView.removeObserver(self, forKeyPath: "contentSize")
|
||||
}
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
nr_setupUI()
|
||||
}
|
||||
|
||||
@MainActor required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
|
||||
if keyPath == "contentSize" {
|
||||
self.panModalSetNeedsLayoutUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
override func allowsTapBackgroundToDismiss() -> Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
override func longFormHeight() -> PanModalHeight {
|
||||
let height = 88 + scrollView.contentSize.height + 92 + 10
|
||||
return PanModalHeightMake(.content, height + UIScreen.safeBottom)
|
||||
}
|
||||
|
||||
private func buyCoinsPack() {
|
||||
guard let model = self.model else { return }
|
||||
NRIapManager.manager.start(model: model, shortPlayId: self.shortPlayId, videoId: self.videoId) { [weak self] finish in
|
||||
guard let self = self else { return }
|
||||
if finish {
|
||||
self.buyFinishHandle?()
|
||||
Task {
|
||||
await self.dismiss(animated: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension NRCoinsPackConfirmView {
|
||||
|
||||
private func nr_setupUI() {
|
||||
addSubview(bgView)
|
||||
addSubview(titleLabel)
|
||||
addSubview(closeButton)
|
||||
addSubview(scrollView)
|
||||
scrollView.addSubview(titleView)
|
||||
scrollView.addSubview(tipView)
|
||||
addSubview(buyButton)
|
||||
addSubview(priceLabel)
|
||||
|
||||
bgView.snp.makeConstraints { make in
|
||||
make.left.right.top.equalToSuperview()
|
||||
}
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalToSuperview().offset(52)
|
||||
}
|
||||
|
||||
closeButton.snp.makeConstraints { make in
|
||||
make.right.equalToSuperview().offset(-6)
|
||||
make.top.equalToSuperview().offset(6)
|
||||
make.width.height.equalTo(44)
|
||||
}
|
||||
|
||||
scrollView.snp.makeConstraints { make in
|
||||
make.left.right.equalToSuperview()
|
||||
make.top.equalToSuperview().offset(88)
|
||||
make.bottom.equalToSuperview().offset(-(92 + UIScreen.safeBottom + 10))
|
||||
}
|
||||
|
||||
titleView.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(16)
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalToSuperview()
|
||||
}
|
||||
|
||||
tipView.snp.makeConstraints { make in
|
||||
make.left.right.equalTo(titleView)
|
||||
make.top.equalTo(titleView.snp.bottom).offset(12)
|
||||
make.bottom.equalToSuperview()
|
||||
}
|
||||
|
||||
buyButton.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(16)
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalTo(scrollView.snp.bottom).offset(44)
|
||||
make.height.equalTo(48)
|
||||
}
|
||||
|
||||
priceLabel.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.centerY.equalTo(scrollView.snp.bottom).offset(22)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
159
ReaderHive/Class/Store/V/NRCoinsPackHeaderView.swift
Normal file
@ -0,0 +1,159 @@
|
||||
//
|
||||
// NRCoinsPackHeaderView.swift
|
||||
// ReaderHive
|
||||
//
|
||||
// Created by 澜声世纪 on 2025/12/12.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SnapKit
|
||||
|
||||
class NRCoinsPackHeaderView: UIView {
|
||||
|
||||
var clickClaimButton: (() -> Void)?
|
||||
|
||||
|
||||
private lazy var titleLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 16, weight: .semibold)
|
||||
label.textColor = ._714_A_1_B
|
||||
label.text = "Rewards Overview".localized
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var coinsView1: CoinsView = {
|
||||
let view = CoinsView()
|
||||
view.title = "Weekly Total".localized
|
||||
view.coins = 0
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var lineView1: NRDashedLineView = {
|
||||
let view = NRDashedLineView()
|
||||
view.isHorizontal = false
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var coinsView2: CoinsView = {
|
||||
let view = CoinsView()
|
||||
view.title = "Claimable Coins".localized
|
||||
view.coins = 0
|
||||
return view
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
nr_setupUI()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension NRCoinsPackHeaderView {
|
||||
|
||||
private func nr_setupUI() {
|
||||
addSubview(titleLabel)
|
||||
addSubview(coinsView1)
|
||||
addSubview(coinsView2)
|
||||
addSubview(lineView1)
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(16)
|
||||
make.top.equalToSuperview().offset(16)
|
||||
}
|
||||
|
||||
coinsView1.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(28)
|
||||
make.top.equalTo(titleLabel.snp.bottom).offset(23)
|
||||
}
|
||||
|
||||
lineView1.snp.makeConstraints { make in
|
||||
make.centerY.equalTo(coinsView1)
|
||||
make.left.equalTo(coinsView1.snp.right).offset(18)
|
||||
make.width.equalTo(1)
|
||||
make.height.equalTo(32)
|
||||
}
|
||||
|
||||
coinsView2.snp.makeConstraints { make in
|
||||
make.centerY.equalTo(lineView1)
|
||||
make.left.equalTo(lineView1.snp.right).offset(18)
|
||||
make.bottom.equalToSuperview()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
extension NRCoinsPackHeaderView {
|
||||
|
||||
class CoinsView: UIView {
|
||||
var title: String? {
|
||||
didSet {
|
||||
titleLabel.text = title
|
||||
}
|
||||
}
|
||||
|
||||
var coins: Int? {
|
||||
didSet {
|
||||
coinsLabel.text = "\(coins ?? 0)"
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var titleLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 12, weight: .bold)
|
||||
label.textColor = .black.withAlphaComponent(0.5)
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var iconImageView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "coins_icon_05"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var coinsLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 18, weight: .bold)
|
||||
label.textColor = .F_9710_D
|
||||
return label
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
addSubview(titleLabel)
|
||||
addSubview(iconImageView)
|
||||
addSubview(coinsLabel)
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview()
|
||||
make.top.equalToSuperview()
|
||||
make.right.lessThanOrEqualToSuperview()
|
||||
}
|
||||
|
||||
iconImageView.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview()
|
||||
make.top.equalTo(titleLabel.snp.bottom).offset(4)
|
||||
make.bottom.equalToSuperview()
|
||||
}
|
||||
|
||||
coinsLabel.snp.makeConstraints { make in
|
||||
make.centerY.equalTo(iconImageView)
|
||||
make.left.equalTo(iconImageView.snp.right).offset(4)
|
||||
make.right.lessThanOrEqualToSuperview()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@MainActor required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -66,7 +66,7 @@ class NRRewardCoinsCell: NRTableViewCell {
|
||||
|
||||
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
|
||||
nr_setupUI()
|
||||
}
|
||||
|
||||
@MainActor required init?(coder: NSCoder) {
|
||||
|
||||
@ -6,7 +6,148 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SnapKit
|
||||
|
||||
class NRStoreCoinsBigCell: NRStoreCoinsCell {
|
||||
|
||||
|
||||
override var model: NRPayItem? {
|
||||
didSet {
|
||||
let coins = model?.coins ?? 0
|
||||
let sendCoins = model?.send_coins ?? 0
|
||||
coinsView.setNeedsUpdateConfiguration()
|
||||
|
||||
priceLabel.text = (model?.currency ?? "") + (model?.price ?? "")
|
||||
|
||||
if sendCoins > 0 {
|
||||
sendCountLabel.isHidden = false
|
||||
ratioBgView.isHidden = false
|
||||
sendCountLabel.text = "+ \(sendCoins) " + "Bonus".localized
|
||||
|
||||
let ratio = String(format: "%.0f", CGFloat(sendCoins) / CGFloat(coins) * 100)
|
||||
ratioLabel.text = "+\(ratio)%"
|
||||
} else {
|
||||
sendCountLabel.isHidden = true
|
||||
ratioBgView.isHidden = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var bgView: UIView = {
|
||||
let view = NRGradientView()
|
||||
view.colors = [UIColor.F_3912_F.cgColor, UIColor.FF_5_C_5_C.cgColor]
|
||||
view.startPoint = .init(x: 0, y: 0.5)
|
||||
view.endPoint = .init(x: 1, y: 0.5)
|
||||
view.layer.cornerRadius = 8
|
||||
view.layer.masksToBounds = true
|
||||
view.layer.borderWidth = 1
|
||||
view.layer.borderColor = UIColor.black.withAlphaComponent(0.05).cgColor
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var coinsView: UIButton = {
|
||||
var configuration = UIButton.Configuration.plain()
|
||||
configuration.image = UIImage(named: "coins_icon_02")
|
||||
configuration.imagePadding = 4
|
||||
configuration.contentInsets = .zero
|
||||
|
||||
let button = UIButton(configuration: configuration)
|
||||
button.isUserInteractionEnabled = false
|
||||
button.configurationUpdateHandler = { [weak self] button in
|
||||
guard let self = self else { return }
|
||||
|
||||
button.configuration?.attributedTitle = AttributedString("\(self.model?.coins ?? 0)", attributes: AttributeContainer([
|
||||
.font : UIFont.font(ofSize: 18, weight: .bold),
|
||||
.foregroundColor : UIColor.white
|
||||
]))
|
||||
}
|
||||
|
||||
return button
|
||||
}()
|
||||
|
||||
private lazy var sendCountLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 12, weight: .regular)
|
||||
label.textColor = .white.withAlphaComponent(0.5)
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var priceLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.textAlignment = .center
|
||||
label.layer.cornerRadius = 4
|
||||
label.layer.masksToBounds = true
|
||||
label.backgroundColor = .white
|
||||
label.textColor = ._946_A_37
|
||||
label.font = .font(ofSize: 14, weight: .bold)
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var ratioBgView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "mark_bg_image_01"))
|
||||
imageView.nr_setRoundedCorner(topLeft: 0, topRight: 0, bottomLeft: 8, bottomRight: 0)
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var ratioLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 14, weight: .bold)
|
||||
label.textColor = ._946_A_37
|
||||
return label
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
nr_setupUI()
|
||||
}
|
||||
|
||||
@MainActor required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension NRStoreCoinsBigCell {
|
||||
|
||||
private func nr_setupUI() {
|
||||
contentView.addSubview(bgView)
|
||||
bgView.addSubview(coinsView)
|
||||
bgView.addSubview(sendCountLabel)
|
||||
bgView.addSubview(priceLabel)
|
||||
bgView.addSubview(ratioBgView)
|
||||
ratioBgView.addSubview(ratioLabel)
|
||||
|
||||
bgView.snp.makeConstraints { make in
|
||||
make.edges.equalToSuperview()
|
||||
}
|
||||
|
||||
coinsView.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalToSuperview().offset(16)
|
||||
}
|
||||
|
||||
sendCountLabel.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.centerY.equalToSuperview()
|
||||
}
|
||||
|
||||
priceLabel.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(6)
|
||||
make.centerX.equalToSuperview()
|
||||
make.bottom.equalToSuperview().offset(-6)
|
||||
make.height.equalTo(24)
|
||||
}
|
||||
|
||||
ratioBgView.snp.makeConstraints { make in
|
||||
make.right.top.equalToSuperview()
|
||||
make.height.equalTo(18)
|
||||
}
|
||||
|
||||
ratioLabel.snp.makeConstraints { make in
|
||||
make.center.equalToSuperview()
|
||||
make.left.equalToSuperview().offset(4)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -6,7 +6,208 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SnapKit
|
||||
internal import StoreKit
|
||||
import YYCategories
|
||||
|
||||
class NRStoreCoinsPackCell: NRStoreCoinsCell {
|
||||
|
||||
override var model: NRPayItem? {
|
||||
didSet {
|
||||
coinsLabel.text = "\(model?.ext_info?.max_total_coins ?? 0)"
|
||||
|
||||
if let text = model?.ext_info?.receive_coins_rate, !text.isEmpty {
|
||||
ratioLabel.text = text
|
||||
ratioBgView.isHidden = false
|
||||
} else {
|
||||
ratioBgView.isHidden = true
|
||||
}
|
||||
|
||||
priceView.setNeedsUpdateConfiguration()
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var bgView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "bg_image_06"))
|
||||
imageView.layer.cornerRadius = 12
|
||||
imageView.layer.masksToBounds = true
|
||||
imageView.layer.borderWidth = 1
|
||||
imageView.layer.borderColor = UIColor.black.withAlphaComponent(0.05).cgColor
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var bgIconImageView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "coins_icon_03"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var titleLabel: UILabel = {
|
||||
let label = NRLabel()
|
||||
label.font = .font(ofSize: 16, weight: .bold).withBoldItalic()
|
||||
label.textColors = [UIColor.BA_8_A_2_A.cgColor, UIColor._8_B_5801.cgColor]
|
||||
label.textStartPoint = .init(x: 0, y: 0.5)
|
||||
label.textEndPoint = .init(x: 1, y: 0.5)
|
||||
label.text = "Weekly Refill".localized
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var coinsIconView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "coins_icon_01"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var coinsLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 18, weight: .bold)
|
||||
label.textColor = ._8_B_5801
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var ratioBgView: UIView = {
|
||||
let view = UIView()
|
||||
view.backgroundColor = .black.withAlphaComponent(0.25)
|
||||
view.layer.cornerRadius = 9
|
||||
view.layer.masksToBounds = true
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var ratioLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 10, weight: .regular)
|
||||
label.textColor = .FFEFD_4
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var priceView: UIButton = {
|
||||
var config = UIButton.Configuration.plain()
|
||||
config.titleAlignment = .center
|
||||
config.titlePadding = 0
|
||||
config.contentInsets = .init(top: 0, leading: 10, bottom: 0, trailing: 10)
|
||||
|
||||
let button = NRGradientButton(configuration: config)
|
||||
button.isUserInteractionEnabled = false
|
||||
button.layer.masksToBounds = true
|
||||
button.layer.cornerRadius = 24
|
||||
button.layer.borderWidth = 1
|
||||
button.layer.borderColor = UIColor.black.withAlphaComponent(0.15).cgColor
|
||||
button.colors = [UIColor.white.cgColor, UIColor.FDE_9_CB.cgColor]
|
||||
button.startPoint = .init(x: 0, y: 0.5)
|
||||
button.endPoint = .init(x: 1, y: 0.5)
|
||||
button.configurationUpdateHandler = { [weak self] button in
|
||||
guard let self = self else { return }
|
||||
|
||||
let currency = self.model?.currency ?? ""
|
||||
let timeText = model?.getTimeString() ?? ""
|
||||
let oldPrice = self.model?.price ?? ""
|
||||
var discountPrice: String? = nil
|
||||
|
||||
if self.model?.discount_type == 1, let introductoryPrice = self.model?.introductionaryOffer {
|
||||
discountPrice = introductoryPrice.price.stringValue
|
||||
} else if self.model?.discount_type == 2, let discount = self.model?.promotionalOffers?.first {
|
||||
discountPrice = discount.price.stringValue
|
||||
}
|
||||
|
||||
if let discountPrice = discountPrice {
|
||||
|
||||
let priceString = AttributedString("\(currency)\(discountPrice)", attributes: AttributeContainer([
|
||||
.font : UIFont.font(ofSize: 18, weight: .bold),
|
||||
// .foregroundColor : UIColor._114_CEE
|
||||
]))
|
||||
|
||||
|
||||
// button.configuration?.attributedTitle = priceString
|
||||
//
|
||||
// var subtitle = AttributedString("\(currency)\(oldPrice)", attributes: AttributeContainer([
|
||||
// .font : UIFont.font(ofSize: 12, weight: .regular),
|
||||
// .foregroundColor : UIColor._636_F_7_B.withAlphaComponent(0.05),
|
||||
// .strikethroughStyle: NSUnderlineStyle.double.rawValue,
|
||||
// .strikethroughColor: UIColor._636_F_7_B.withAlphaComponent(0.05)
|
||||
// ]))
|
||||
//
|
||||
// button.configuration?.attributedSubtitle = subtitle
|
||||
|
||||
} else {
|
||||
|
||||
button.configuration?.attributedTitle = AttributedString("\(currency)\(oldPrice)", attributes: AttributeContainer([
|
||||
.font : UIFont.font(ofSize: 18, weight: .bold),
|
||||
.foregroundColor : UIColor._946_A_37
|
||||
]))
|
||||
|
||||
button.configuration?.attributedSubtitle = AttributedString("/\(timeText)", attributes: AttributeContainer([
|
||||
.font : UIFont.font(ofSize: 12, weight: .regular),
|
||||
.foregroundColor : UIColor.black.withAlphaComponent(0.5)
|
||||
]))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return button
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
nr_setupUI()
|
||||
}
|
||||
|
||||
@MainActor required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension NRStoreCoinsPackCell {
|
||||
|
||||
private func nr_setupUI() {
|
||||
contentView.addSubview(bgView)
|
||||
bgView.addSubview(bgIconImageView)
|
||||
bgView.addSubview(titleLabel)
|
||||
bgView.addSubview(coinsIconView)
|
||||
bgView.addSubview(coinsLabel)
|
||||
bgView.addSubview(ratioBgView)
|
||||
ratioBgView.addSubview(ratioLabel)
|
||||
bgView.addSubview(priceView)
|
||||
|
||||
bgView.snp.makeConstraints { make in
|
||||
make.edges.equalToSuperview()
|
||||
}
|
||||
|
||||
bgIconImageView.snp.makeConstraints { make in
|
||||
make.top.bottom.left.equalToSuperview()
|
||||
}
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(72)
|
||||
make.top.equalToSuperview().offset(19)
|
||||
}
|
||||
|
||||
coinsIconView.snp.makeConstraints { make in
|
||||
make.left.equalTo(titleLabel)
|
||||
make.bottom.equalToSuperview().offset(-21)
|
||||
}
|
||||
|
||||
coinsLabel.snp.makeConstraints { make in
|
||||
make.centerY.equalTo(coinsIconView)
|
||||
make.left.equalTo(coinsIconView.snp.right).offset(4)
|
||||
}
|
||||
|
||||
ratioBgView.snp.makeConstraints { make in
|
||||
make.centerY.equalTo(coinsIconView)
|
||||
make.left.equalTo(coinsLabel.snp.right).offset(4)
|
||||
make.height.equalTo(18)
|
||||
}
|
||||
|
||||
ratioLabel.snp.makeConstraints { make in
|
||||
make.center.equalToSuperview()
|
||||
make.left.equalToSuperview().offset(8)
|
||||
}
|
||||
|
||||
priceView.snp.makeConstraints { make in
|
||||
make.centerY.equalToSuperview()
|
||||
make.right.equalToSuperview().offset(-12)
|
||||
make.height.equalTo(48)
|
||||
make.width.greaterThanOrEqualTo(88)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -6,7 +6,141 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SnapKit
|
||||
|
||||
class NRStoreCoinsSmallCell: NRStoreCoinsCell {
|
||||
|
||||
override var model: NRPayItem? {
|
||||
didSet {
|
||||
let coins = model?.coins ?? 0
|
||||
let sendCoins = model?.send_coins ?? 0
|
||||
coinsView.setNeedsUpdateConfiguration()
|
||||
|
||||
priceLabel.text = (model?.currency ?? "") + (model?.price ?? "")
|
||||
|
||||
if sendCoins > 0 {
|
||||
sendCountLabel.isHidden = false
|
||||
ratioBgView.isHidden = false
|
||||
sendCountLabel.text = "+ \(sendCoins) " + "Bonus".localized
|
||||
|
||||
let ratio = String(format: "%.0f", CGFloat(sendCoins) / CGFloat(coins) * 100)
|
||||
ratioLabel.text = "+\(ratio)%"
|
||||
} else {
|
||||
sendCountLabel.isHidden = true
|
||||
ratioBgView.isHidden = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var bgView: UIView = {
|
||||
let view = UIImageView(image: UIImage(named: "bg_image_05"))
|
||||
view.nr_setBorder(UIImage(named: "gradient_color_01"))
|
||||
view.layer.borderWidth = 1
|
||||
view.layer.cornerRadius = 8
|
||||
view.layer.masksToBounds = true
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var coinsView: UIButton = {
|
||||
var configuration = UIButton.Configuration.plain()
|
||||
configuration.image = UIImage(named: "coins_icon_02")
|
||||
configuration.imagePadding = 4
|
||||
configuration.contentInsets = .zero
|
||||
|
||||
let button = UIButton(configuration: configuration)
|
||||
button.isUserInteractionEnabled = false
|
||||
button.configurationUpdateHandler = { [weak self] button in
|
||||
guard let self = self else { return }
|
||||
|
||||
button.configuration?.attributedTitle = AttributedString("\(self.model?.coins ?? 0)", attributes: AttributeContainer([
|
||||
.font : UIFont.font(ofSize: 18, weight: .bold),
|
||||
.foregroundColor : UIColor.F_9710_D
|
||||
]))
|
||||
}
|
||||
|
||||
return button
|
||||
}()
|
||||
|
||||
private lazy var sendCountLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 10, weight: .regular)
|
||||
label.textColor = .black.withAlphaComponent(0.5)
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var priceLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.textAlignment = .center
|
||||
label.layer.cornerRadius = 4
|
||||
label.layer.masksToBounds = true
|
||||
label.backgroundColor = .FFD_0_AE
|
||||
label.textColor = .F_9710_D
|
||||
label.font = .font(ofSize: 12, weight: .bold)
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var ratioBgView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "mark_bg_image_02"))
|
||||
imageView.nr_setRoundedCorner(topLeft: 0, topRight: 0, bottomLeft: 8, bottomRight: 0)
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var ratioLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 14, weight: .bold)
|
||||
label.textColor = .white
|
||||
return label
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
nr_setupUI()
|
||||
}
|
||||
|
||||
@MainActor required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension NRStoreCoinsSmallCell {
|
||||
private func nr_setupUI() {
|
||||
contentView.addSubview(bgView)
|
||||
bgView.addSubview(coinsView)
|
||||
bgView.addSubview(sendCountLabel)
|
||||
bgView.addSubview(priceLabel)
|
||||
bgView.addSubview(ratioBgView)
|
||||
ratioBgView.addSubview(ratioLabel)
|
||||
|
||||
bgView.snp.makeConstraints { make in
|
||||
make.edges.equalToSuperview()
|
||||
}
|
||||
|
||||
coinsView.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalToSuperview().offset(18)
|
||||
}
|
||||
|
||||
sendCountLabel.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.bottom.equalTo(priceLabel.snp.top).offset(-3)
|
||||
}
|
||||
|
||||
priceLabel.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(6)
|
||||
make.centerX.equalToSuperview()
|
||||
make.bottom.equalToSuperview().offset(-6)
|
||||
make.height.equalTo(24)
|
||||
}
|
||||
|
||||
ratioBgView.snp.makeConstraints { make in
|
||||
make.right.top.equalToSuperview()
|
||||
make.height.equalTo(18)
|
||||
}
|
||||
|
||||
ratioLabel.snp.makeConstraints { make in
|
||||
make.center.equalToSuperview()
|
||||
make.left.equalToSuperview().offset(4)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
|
||||
import UIKit
|
||||
import SnapKit
|
||||
import HWPanModal
|
||||
|
||||
class NRStoreCoinsView: UIView {
|
||||
|
||||
@ -27,7 +28,7 @@ class NRStoreCoinsView: UIView {
|
||||
|
||||
private lazy var collectionViewLayout: UICollectionViewCompositionalLayout = {
|
||||
let config = UICollectionViewCompositionalLayoutConfiguration()
|
||||
config.interSectionSpacing = 10
|
||||
config.interSectionSpacing = 12
|
||||
|
||||
let layout = UICollectionViewCompositionalLayout { [weak self] section, _ in
|
||||
guard let self = self else { return nil}
|
||||
@ -159,10 +160,10 @@ extension NRStoreCoinsView {
|
||||
let item = NSCollectionLayoutItem(layoutSize: .init(widthDimension: .fractionalWidth(0.5), heightDimension: .fractionalHeight(1)))
|
||||
|
||||
let group = NSCollectionLayoutGroup.horizontal(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .absolute(100)), subitems: [item])
|
||||
group.interItemSpacing = .fixed(1)
|
||||
group.interItemSpacing = .fixed(15)
|
||||
|
||||
let layoutSection = NSCollectionLayoutSection(group: group)
|
||||
layoutSection.interGroupSpacing = 10
|
||||
layoutSection.interGroupSpacing = 12
|
||||
layoutSection.contentInsets = .init(top: 0, leading: 16, bottom: 0, trailing: 16)
|
||||
return layoutSection
|
||||
}
|
||||
@ -170,11 +171,11 @@ extension NRStoreCoinsView {
|
||||
private func smallLayoutSection() -> NSCollectionLayoutSection {
|
||||
let item = NSCollectionLayoutItem(layoutSize: .init(widthDimension: .fractionalWidth(1 / 3), heightDimension: .fractionalHeight(1)))
|
||||
|
||||
let group = NSCollectionLayoutGroup.horizontal(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .absolute(121)), subitems: [item])
|
||||
group.interItemSpacing = .fixed(8)
|
||||
let group = NSCollectionLayoutGroup.horizontal(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .absolute(84)), subitems: [item])
|
||||
group.interItemSpacing = .fixed(15)
|
||||
|
||||
let layoutSection = NSCollectionLayoutSection(group: group)
|
||||
layoutSection.interGroupSpacing = 10
|
||||
layoutSection.interGroupSpacing = 12
|
||||
layoutSection.contentInsets = .init(top: 0, leading: 16, bottom: 0, trailing: 16)
|
||||
return layoutSection
|
||||
}
|
||||
@ -186,7 +187,7 @@ extension NRStoreCoinsView {
|
||||
|
||||
|
||||
let layoutSection = NSCollectionLayoutSection(group: group)
|
||||
layoutSection.interGroupSpacing = 10
|
||||
layoutSection.interGroupSpacing = 12
|
||||
layoutSection.contentInsets = .init(top: 0, leading: 16, bottom: 0, trailing: 16)
|
||||
return layoutSection
|
||||
}
|
||||
@ -225,23 +226,19 @@ extension NRStoreCoinsView: UICollectionViewDelegate, UICollectionViewDataSource
|
||||
collectionView.reloadData()
|
||||
|
||||
if model.buy_type == .subCoins {
|
||||
// let view = FACoinPackConfirmView()
|
||||
// view.shortPlayId = self.shortPlayId
|
||||
// view.videoId = self.videoId
|
||||
// view.model = model
|
||||
// view.buyFinishHandle = { [weak self] in
|
||||
// guard let self = self else { return }
|
||||
// NRLoginManager.manager.updateUserInfo()
|
||||
// self.buyFinishHandle?()
|
||||
// }
|
||||
// view.present(in: nil)
|
||||
let view = NRCoinsPackConfirmView()
|
||||
view.shortPlayId = self.shortPlayId
|
||||
view.videoId = self.videoId
|
||||
view.model = model
|
||||
view.buyFinishHandle = { [weak self] in
|
||||
guard let self = self else { return }
|
||||
self.buyFinishHandle?()
|
||||
}
|
||||
view.present(in: nil)
|
||||
} else {
|
||||
NRIapManager.manager.start(model: model, shortPlayId: self.shortPlayId, videoId: self.videoId) { [weak self] finish in
|
||||
guard let self = self else { return }
|
||||
if finish {
|
||||
Task {
|
||||
await NRLoginManager.manager.updateUserInfo()
|
||||
}
|
||||
self.buyFinishHandle?()
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,11 +6,189 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SnapKit
|
||||
import YYCategories
|
||||
|
||||
class NRStoreVipCell: UICollectionViewCell {
|
||||
var model: NRPayItem? {
|
||||
didSet {
|
||||
titleLabel.text = model?.brief
|
||||
desLabel.text = model?.nr_description
|
||||
|
||||
if let coins = model?.send_coins, coins > 0 {
|
||||
extraLabel.text = "+\(coins) \("Extra".localized)"
|
||||
extraBgView.isHidden = false
|
||||
} else {
|
||||
extraBgView.isHidden = true
|
||||
}
|
||||
|
||||
let currency = model?.currency ?? ""
|
||||
let oldPrice = model?.price ?? ""
|
||||
priceLabel.text = currency + oldPrice
|
||||
|
||||
switch model?.vip_type_key {
|
||||
case .week:
|
||||
bgView.image = UIImage(named: "vip_bg_image_week")
|
||||
bgIconView.image = UIImage(named: "vip_bg_icon_week")
|
||||
vipIconImageView.image = UIImage(named: "vip_icon_week")
|
||||
titleLabel.textColors = [UIColor._389_FEA.cgColor, UIColor._062_AAE.cgColor]
|
||||
priceLabel.textColor = ._062_AAE
|
||||
|
||||
case .month:
|
||||
bgView.image = UIImage(named: "vip_bg_image_month")
|
||||
bgIconView.image = UIImage(named: "vip_bg_icon_month")
|
||||
vipIconImageView.image = UIImage(named: "vip_icon_month")
|
||||
titleLabel.textColors = [UIColor._162_FAC.cgColor, UIColor._661794.cgColor]
|
||||
priceLabel.textColor = ._661794
|
||||
|
||||
case .quarter:
|
||||
bgView.image = UIImage(named: "vip_bg_image_quarter")
|
||||
bgIconView.image = UIImage(named: "vip_bg_icon_quarter")
|
||||
vipIconImageView.image = UIImage(named: "vip_icon_quarter")
|
||||
titleLabel.textColors = [UIColor.CE_1_E_79.cgColor, UIColor.B_92214.cgColor]
|
||||
priceLabel.textColor = .B_92214
|
||||
|
||||
case .year:
|
||||
bgView.image = UIImage(named: "vip_bg_image_year")
|
||||
bgIconView.image = UIImage(named: "vip_bg_icon_year")
|
||||
vipIconImageView.image = UIImage(named: "vip_icon_year")
|
||||
titleLabel.textColors = [UIColor.BA_8_A_2_A.cgColor, UIColor._8_B_5801.cgColor]
|
||||
priceLabel.textColor = ._8_B_5801
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var bgView: UIImageView = {
|
||||
let view = UIImageView()
|
||||
view.layer.cornerRadius = 12
|
||||
view.layer.masksToBounds = true
|
||||
view.layer.borderColor = UIColor.black.withAlphaComponent(0.05).cgColor
|
||||
view.layer.borderWidth = 1
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var bgIconView: UIImageView = {
|
||||
let view = UIImageView()
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var vipIconImageView: UIImageView = {
|
||||
let imageView = UIImageView()
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var titleLabel: NRLabel = {
|
||||
let label = NRLabel()
|
||||
label.font = .font(ofSize: 14, weight: .medium)
|
||||
label.textStartPoint = .init(x: 0, y: 0.5)
|
||||
label.textEndPoint = .init(x: 1, y: 0.5)
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var priceLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 20, weight: .bold).withBoldItalic()
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var desLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 12, weight: .regular)
|
||||
label.textColor = .black.withAlphaComponent(0.5)
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var extraBgView: UIView = {
|
||||
let view = UIView()
|
||||
view.backgroundColor = .white.withAlphaComponent(0.75)
|
||||
view.nr_setRoundedCorner(topLeft: 12, topRight: 0, bottomLeft: 0, bottomRight: 0)
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var extraLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 14, weight: .bold).withBoldItalic()
|
||||
label.textColor = ._9_C_6_A_45
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var extraIconView: UIView = {
|
||||
let view = UIImageView(image: UIImage(named: "coins_icon_04"))
|
||||
return view
|
||||
}()
|
||||
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
nr_setupUI()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
|
||||
extension NRStoreVipCell {
|
||||
|
||||
private func nr_setupUI() {
|
||||
contentView.addSubview(bgView)
|
||||
bgView.addSubview(bgIconView)
|
||||
bgView.addSubview(vipIconImageView)
|
||||
bgView.addSubview(titleLabel)
|
||||
bgView.addSubview(priceLabel)
|
||||
bgView.addSubview(desLabel)
|
||||
bgView.addSubview(extraBgView)
|
||||
extraBgView.addSubview(extraLabel)
|
||||
extraBgView.addSubview(extraIconView)
|
||||
|
||||
bgView.snp.makeConstraints { make in
|
||||
make.edges.equalToSuperview()
|
||||
}
|
||||
|
||||
bgIconView.snp.makeConstraints { make in
|
||||
make.centerY.equalToSuperview()
|
||||
make.right.equalToSuperview().offset(-12)
|
||||
}
|
||||
|
||||
vipIconImageView.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(12)
|
||||
make.top.equalToSuperview().offset(12)
|
||||
}
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.centerY.equalTo(vipIconImageView)
|
||||
make.left.equalTo(vipIconImageView.snp.right).offset(4)
|
||||
}
|
||||
|
||||
priceLabel.snp.makeConstraints { make in
|
||||
make.left.equalTo(vipIconImageView)
|
||||
make.centerY.equalToSuperview().offset(3)
|
||||
}
|
||||
|
||||
desLabel.snp.makeConstraints { make in
|
||||
make.left.equalTo(priceLabel)
|
||||
make.right.lessThanOrEqualToSuperview().offset(-12)
|
||||
make.bottom.equalToSuperview().offset(-12)
|
||||
}
|
||||
|
||||
extraBgView.snp.makeConstraints { make in
|
||||
make.right.bottom.equalToSuperview()
|
||||
make.height.equalTo(24)
|
||||
}
|
||||
|
||||
extraLabel.snp.makeConstraints { make in
|
||||
make.centerY.equalToSuperview()
|
||||
make.left.equalToSuperview().offset(12)
|
||||
}
|
||||
|
||||
extraIconView.snp.makeConstraints { make in
|
||||
make.centerY.equalToSuperview()
|
||||
make.left.equalTo(extraLabel.snp.right).offset(4)
|
||||
make.right.equalToSuperview().offset(-12)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,10 +31,10 @@ class NRStoreVipView: UIView {
|
||||
|
||||
let item = NSCollectionLayoutItem(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .fractionalHeight(1)))
|
||||
|
||||
let group = NSCollectionLayoutGroup.horizontal(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .absolute(110)), subitems: [item])
|
||||
let group = NSCollectionLayoutGroup.horizontal(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .absolute(96)), subitems: [item])
|
||||
|
||||
let layoutSection = NSCollectionLayoutSection(group: group)
|
||||
layoutSection.interGroupSpacing = 14
|
||||
layoutSection.interGroupSpacing = 12
|
||||
layoutSection.contentInsets = .init(top: 0, leading: 16, bottom: 0, trailing: 16)
|
||||
|
||||
|
||||
|
||||
70
ReaderHive/Class/Store/VC/NRCoinsPackViewController.swift
Normal file
@ -0,0 +1,70 @@
|
||||
//
|
||||
// NRCoinsPackViewController.swift
|
||||
// ReaderHive
|
||||
//
|
||||
// Created by 澜声世纪 on 2025/12/12.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SnapKit
|
||||
|
||||
class NRCoinsPackViewController: NRViewController {
|
||||
|
||||
|
||||
private lazy var bgIconImageView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "calendar_icon_02"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var scrollView: NRScrollView = {
|
||||
let scrollView = NRScrollView()
|
||||
return scrollView
|
||||
}()
|
||||
|
||||
private lazy var headerView: NRCoinsPackHeaderView = {
|
||||
let view = NRCoinsPackHeaderView()
|
||||
return view
|
||||
}()
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
self.title = "My Refills".localized
|
||||
configNavigationBack("arrow_left_icon_05")
|
||||
|
||||
nr_setupUI()
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
self.navigationController?.setNavigationBarHidden(false, animated: true)
|
||||
self.nr_setNavigationStyle(titleColor: UINavigationBar.titleBlackColor)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension NRCoinsPackViewController {
|
||||
|
||||
private func nr_setupUI() {
|
||||
view.addSubview(bgIconImageView)
|
||||
view.addSubview(scrollView)
|
||||
scrollView.addSubview(headerView)
|
||||
|
||||
|
||||
bgIconImageView.snp.makeConstraints { make in
|
||||
make.top.equalToSuperview().offset(UIScreen.navBarHeight)
|
||||
make.right.equalToSuperview().offset(-3)
|
||||
}
|
||||
|
||||
scrollView.snp.makeConstraints { make in
|
||||
make.right.left.bottom.equalToSuperview()
|
||||
make.top.equalToSuperview().offset(UIScreen.navBarHeight)
|
||||
}
|
||||
|
||||
headerView.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview()
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalToSuperview()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -11,6 +11,10 @@ import SnapKit
|
||||
class NRStoreViewController: NRViewController {
|
||||
|
||||
|
||||
private var payRequest: NRPayDataRequest = NRPayDataRequest()
|
||||
|
||||
private var payDataModel: NRPayDateModel? = NRIapManager.manager.payDateModel
|
||||
|
||||
private lazy var scrollView: NRScrollView = {
|
||||
let scrollView = NRScrollView()
|
||||
return scrollView
|
||||
@ -27,7 +31,7 @@ class NRStoreViewController: NRViewController {
|
||||
let view = NRStoreCoinsView()
|
||||
view.isShowTitle = true
|
||||
view.buyFinishHandle = { [weak self] in
|
||||
|
||||
self?.buyFinish()
|
||||
}
|
||||
return view
|
||||
}()
|
||||
@ -36,7 +40,7 @@ class NRStoreViewController: NRViewController {
|
||||
let view = NRStoreVipView()
|
||||
view.isShowTitle = true
|
||||
view.buyFinishHandle = { [weak self] in
|
||||
|
||||
self?.buyFinish()
|
||||
}
|
||||
return view
|
||||
}()
|
||||
@ -46,10 +50,13 @@ class NRStoreViewController: NRViewController {
|
||||
self.title = "Store".localized
|
||||
configNavigationBack("arrow_left_icon_05")
|
||||
|
||||
stackView.addArrangedSubview(coinsView)
|
||||
stackView.addArrangedSubview(vipView)
|
||||
|
||||
nr_setupUI()
|
||||
|
||||
restore(isLoding: false)
|
||||
|
||||
requestPayData()
|
||||
|
||||
updateLayout()
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
@ -58,6 +65,61 @@ class NRStoreViewController: NRViewController {
|
||||
self.nr_setNavigationStyle(titleColor: UINavigationBar.titleBlackColor)
|
||||
}
|
||||
|
||||
|
||||
private func buyFinish() {
|
||||
Task {
|
||||
await NRLoginManager.manager.updateUserInfo()
|
||||
}
|
||||
self.requestPayData()
|
||||
}
|
||||
|
||||
|
||||
@objc private func handleRestore() {
|
||||
restore(isLoding: true)
|
||||
}
|
||||
|
||||
func updateLayout() {
|
||||
self.stackView.nr_removeAllArrangedSubview()
|
||||
|
||||
guard let model = self.payDataModel else { return }
|
||||
|
||||
|
||||
if let sort = model.sort, sort.count > 0 {
|
||||
sort.forEach {
|
||||
if $0 == .vip {
|
||||
self.addVipView()
|
||||
} else if $0 == .coin {
|
||||
self.addCoinsView()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.addVipView()
|
||||
self.addCoinsView()
|
||||
}
|
||||
// self.stackView.addArrangedSubview(tipView)
|
||||
}
|
||||
|
||||
private func addCoinsView() {
|
||||
guard let model = self.payDataModel else { return }
|
||||
|
||||
var newList: [NRPayItem] = []
|
||||
|
||||
if let list = model.list_coins, list.count > 0 {
|
||||
newList = list
|
||||
}
|
||||
if newList.count > 0 {
|
||||
coinsView.setDataArr(newList)
|
||||
self.stackView.addArrangedSubview(coinsView)
|
||||
}
|
||||
}
|
||||
|
||||
private func addVipView() {
|
||||
guard let list = payDataModel?.list_sub_vip else { return }
|
||||
guard list.count > 0 else { return }
|
||||
|
||||
self.vipView.dataArr = list
|
||||
self.stackView.addArrangedSubview(self.vipView)
|
||||
}
|
||||
}
|
||||
|
||||
extension NRStoreViewController {
|
||||
@ -80,3 +142,31 @@ extension NRStoreViewController {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension NRStoreViewController {
|
||||
|
||||
private func requestPayData() {
|
||||
|
||||
payRequest.requestProducts { [weak self] model in
|
||||
guard let self = self else { return }
|
||||
guard let model = model else { return }
|
||||
self.payDataModel = model
|
||||
|
||||
self.updateLayout()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private func restore(isLoding: Bool) {
|
||||
|
||||
NRIapManager.manager.restore(isLoding: isLoding) { [weak self] isFinish, buyType in
|
||||
if isFinish {
|
||||
Task {
|
||||
await NRLoginManager.manager.updateUserInfo()
|
||||
}
|
||||
self?.buyFinish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@ class NRWalletViewController: NRViewController {
|
||||
return tableView
|
||||
}()
|
||||
|
||||
deinit {
|
||||
@MainActor deinit {
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
}
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import StoreKit
|
||||
internal import StoreKit
|
||||
|
||||
class NRIapManager {
|
||||
typealias CompletionHandler = ((_ finish: Bool) -> Void)
|
||||
@ -277,7 +277,7 @@ extension NRIapManager {
|
||||
func preloadingProducts() {
|
||||
JXIAPManager.manager.fetchReceipt { _ in
|
||||
self.payRequest = NRPayDataRequest()
|
||||
self.payRequest?.requestProducts(isLoding: false, isToast: false) { model in
|
||||
self.payRequest?.requestProducts(isLoding: false, isToast: false) { _ in
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import StoreKit
|
||||
internal import StoreKit
|
||||
|
||||
class NRPayDataRequest: NSObject {
|
||||
|
||||
|
||||
@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xAE",
|
||||
"green" : "0x2A",
|
||||
"red" : "0x06"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xAC",
|
||||
"green" : "0x2F",
|
||||
"red" : "0x16"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xEA",
|
||||
"green" : "0x9F",
|
||||
"red" : "0x38"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x94",
|
||||
"green" : "0x17",
|
||||
"red" : "0x66"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x1B",
|
||||
"green" : "0x4A",
|
||||
"red" : "0x71"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x01",
|
||||
"green" : "0x58",
|
||||
"red" : "0x8B"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x37",
|
||||
"green" : "0x6A",
|
||||
"red" : "0x94"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x45",
|
||||
"green" : "0x6A",
|
||||
"red" : "0x9C"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x14",
|
||||
"green" : "0x22",
|
||||
"red" : "0xB9"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x2A",
|
||||
"green" : "0x8A",
|
||||
"red" : "0xBA"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x79",
|
||||
"green" : "0x1E",
|
||||
"red" : "0xCE"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xCB",
|
||||
"green" : "0xE9",
|
||||
"red" : "0xFD"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x5C",
|
||||
"green" : "0x5C",
|
||||
"red" : "0xFF"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xAE",
|
||||
"green" : "0xD0",
|
||||
"red" : "0xFF"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
ReaderHive/Source/Assets.xcassets/Image/bg_image_05.imageset/Coin@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
ReaderHive/Source/Assets.xcassets/Image/bg_image_05.imageset/Coin@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 46 KiB |
22
ReaderHive/Source/Assets.xcassets/Image/bg_image_05.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Coin@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Coin@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
22
ReaderHive/Source/Assets.xcassets/Image/bg_image_06.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "金币包背景(商店页)@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "金币包背景(商店页)@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
ReaderHive/Source/Assets.xcassets/Image/bg_image_06.imageset/金币包背景(商店页)@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 103 KiB |
BIN
ReaderHive/Source/Assets.xcassets/Image/bg_image_06.imageset/金币包背景(商店页)@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 224 KiB |
22
ReaderHive/Source/Assets.xcassets/Image/calendar_icon_01.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Frame 2072750451@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Frame 2072750451@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
ReaderHive/Source/Assets.xcassets/Image/calendar_icon_01.imageset/Frame 2072750451@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
ReaderHive/Source/Assets.xcassets/Image/calendar_icon_01.imageset/Frame 2072750451@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
ReaderHive/Source/Assets.xcassets/Image/calendar_icon_02.imageset/Checkin@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 84 KiB |
BIN
ReaderHive/Source/Assets.xcassets/Image/calendar_icon_02.imageset/Checkin@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 184 KiB |
22
ReaderHive/Source/Assets.xcassets/Image/calendar_icon_02.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Checkin@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Checkin@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
22
ReaderHive/Source/Assets.xcassets/Image/close_icon_02.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Group 958@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Group 958@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
ReaderHive/Source/Assets.xcassets/Image/close_icon_02.imageset/Group 958@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 910 B |
BIN
ReaderHive/Source/Assets.xcassets/Image/close_icon_02.imageset/Group 958@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
22
ReaderHive/Source/Assets.xcassets/Image/coins_icon_02.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Rectangle 457@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Rectangle 457@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
ReaderHive/Source/Assets.xcassets/Image/coins_icon_02.imageset/Rectangle 457@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
ReaderHive/Source/Assets.xcassets/Image/coins_icon_02.imageset/Rectangle 457@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
22
ReaderHive/Source/Assets.xcassets/Image/coins_icon_03.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "金币+光@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "金币+光@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
ReaderHive/Source/Assets.xcassets/Image/coins_icon_03.imageset/金币+光@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 48 KiB |
BIN
ReaderHive/Source/Assets.xcassets/Image/coins_icon_03.imageset/金币+光@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 100 KiB |
BIN
ReaderHive/Source/Assets.xcassets/Image/coins_icon_04.imageset/Coins@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
ReaderHive/Source/Assets.xcassets/Image/coins_icon_04.imageset/Coins@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
22
ReaderHive/Source/Assets.xcassets/Image/coins_icon_04.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Coins@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Coins@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
ReaderHive/Source/Assets.xcassets/Image/coins_icon_05.imageset/Coins@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
ReaderHive/Source/Assets.xcassets/Image/coins_icon_05.imageset/Coins@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
22
ReaderHive/Source/Assets.xcassets/Image/coins_icon_05.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Coins@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Coins@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
22
ReaderHive/Source/Assets.xcassets/Image/gift_icon_02.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Frame@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Frame@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
ReaderHive/Source/Assets.xcassets/Image/gift_icon_02.imageset/Frame@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
ReaderHive/Source/Assets.xcassets/Image/gift_icon_02.imageset/Frame@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
ReaderHive/Source/Assets.xcassets/Image/gradient_color_01.imageset/Coin@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
ReaderHive/Source/Assets.xcassets/Image/gradient_color_01.imageset/Coin@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 66 KiB |
22
ReaderHive/Source/Assets.xcassets/Image/gradient_color_01.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Coin@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Coin@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
22
ReaderHive/Source/Assets.xcassets/Image/mark_bg_image_01.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "赠币@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "赠币@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
ReaderHive/Source/Assets.xcassets/Image/mark_bg_image_01.imageset/赠币@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
ReaderHive/Source/Assets.xcassets/Image/mark_bg_image_01.imageset/赠币@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
22
ReaderHive/Source/Assets.xcassets/Image/mark_bg_image_02.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "赠币@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "赠币@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
ReaderHive/Source/Assets.xcassets/Image/mark_bg_image_02.imageset/赠币@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
ReaderHive/Source/Assets.xcassets/Image/mark_bg_image_02.imageset/赠币@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 6.7 KiB |
22
ReaderHive/Source/Assets.xcassets/Image/vip_bg_icon_month.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "VIP Icon(月会员)@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "VIP Icon(月会员)@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
ReaderHive/Source/Assets.xcassets/Image/vip_bg_icon_month.imageset/VIP Icon(月会员)@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
ReaderHive/Source/Assets.xcassets/Image/vip_bg_icon_month.imageset/VIP Icon(月会员)@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 77 KiB |
22
ReaderHive/Source/Assets.xcassets/Image/vip_bg_icon_quarter.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "VIP Icon(季会员)@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "VIP Icon(季会员)@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
ReaderHive/Source/Assets.xcassets/Image/vip_bg_icon_quarter.imageset/VIP Icon(季会员)@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
ReaderHive/Source/Assets.xcassets/Image/vip_bg_icon_quarter.imageset/VIP Icon(季会员)@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 73 KiB |
22
ReaderHive/Source/Assets.xcassets/Image/vip_bg_icon_week.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "VIP Icon(周会员)@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "VIP Icon(周会员)@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
ReaderHive/Source/Assets.xcassets/Image/vip_bg_icon_week.imageset/VIP Icon(周会员)@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
ReaderHive/Source/Assets.xcassets/Image/vip_bg_icon_week.imageset/VIP Icon(周会员)@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 75 KiB |
22
ReaderHive/Source/Assets.xcassets/Image/vip_bg_icon_year.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "VIP Icon(年会员)@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "VIP Icon(年会员)@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
ReaderHive/Source/Assets.xcassets/Image/vip_bg_icon_year.imageset/VIP Icon(年会员)@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
ReaderHive/Source/Assets.xcassets/Image/vip_bg_icon_year.imageset/VIP Icon(年会员)@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 76 KiB |
22
ReaderHive/Source/Assets.xcassets/Image/vip_bg_image_month.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "月VIP卡片@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "月VIP卡片@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
ReaderHive/Source/Assets.xcassets/Image/vip_bg_image_month.imageset/月VIP卡片@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 156 KiB |