This commit is contained in:
澜声世纪 2025-12-12 15:01:30 +08:00
parent e14d8e2c6b
commit 211bf5f3df
124 changed files with 2494 additions and 76 deletions

View File

@ -79,6 +79,14 @@
039810D02ED54D370006E317 /* NRHomeCategoryTagView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039810CF2ED54D370006E317 /* NRHomeCategoryTagView.swift */; }; 039810D02ED54D370006E317 /* NRHomeCategoryTagView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039810CF2ED54D370006E317 /* NRHomeCategoryTagView.swift */; };
039810D22ED54F190006E317 /* NRHomeNovelListTextCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039810D12ED54F190006E317 /* NRHomeNovelListTextCell.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 */; }; 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 */; }; F34348AF2ED5B85300AA7E70 /* NRExploreViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F34348AE2ED5B85300AA7E70 /* NRExploreViewController.swift */; };
F34348B12ED5B9A400AA7E70 /* NRExploreNovelViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F34348B02ED5B9A400AA7E70 /* NRExploreNovelViewController.swift */; }; F34348B12ED5B9A400AA7E70 /* NRExploreNovelViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F34348B02ED5B9A400AA7E70 /* NRExploreNovelViewController.swift */; };
F34348B32ED5BB6100AA7E70 /* NRExploreNovelMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F34348B22ED5BB6100AA7E70 /* NRExploreNovelMenuView.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>"; }; 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; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; F34348B02ED5B9A400AA7E70 /* NRExploreNovelViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRExploreNovelViewController.swift; sourceTree = "<group>"; };
@ -631,6 +647,7 @@
0398106E2ED053630006E317 /* Extension */ = { 0398106E2ED053630006E317 /* Extension */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
85606A972EEBC119005D989D /* Date+NRAdd.swift */,
F3B859602EE9126A0095A9CC /* Dictionary+NRAdd.swift */, F3B859602EE9126A0095A9CC /* Dictionary+NRAdd.swift */,
F34990B62EDE78680039E939 /* UIScrollView+Refresh.swift */, F34990B62EDE78680039E939 /* UIScrollView+Refresh.swift */,
F34348E62ED7F91500AA7E70 /* NSNumber+NRAdd.swift */, F34348E62ED7F91500AA7E70 /* NSNumber+NRAdd.swift */,
@ -737,6 +754,7 @@
F343490F2ED9A77A00AA7E70 /* NRPanModalContentView.swift */, F343490F2ED9A77A00AA7E70 /* NRPanModalContentView.swift */,
F34349112EDA84F100AA7E70 /* NRProgressView.swift */, F34349112EDA84F100AA7E70 /* NRProgressView.swift */,
F34990FA2EE121490039E939 /* NRLabel.swift */, F34990FA2EE121490039E939 /* NRLabel.swift */,
85606A9E2EEBE95A005D989D /* NRDashedLineView.swift */,
); );
path = View; path = View;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1068,6 +1086,11 @@
F3B859852EE972F70095A9CC /* NRConsumptionRecordsCell.xib */, F3B859852EE972F70095A9CC /* NRConsumptionRecordsCell.xib */,
F3B8598C2EEA51FE0095A9CC /* NRRewardCoinsCell.swift */, F3B8598C2EEA51FE0095A9CC /* NRRewardCoinsCell.swift */,
F3B859942EEA64430095A9CC /* NROrderRecordsCell.swift */, F3B859942EEA64430095A9CC /* NROrderRecordsCell.swift */,
85606A8F2EEBA8F3005D989D /* NRCoinsPackConfirmView.swift */,
85606A912EEBB336005D989D /* NRCoinsPackConfirmItemView.swift */,
85606A932EEBB3FE005D989D /* NRCoinsPackConfirmTitleView.swift */,
85606A952EEBB733005D989D /* NRCoinsPackConfirmTipView.swift */,
85606A9B2EEBE243005D989D /* NRCoinsPackHeaderView.swift */,
); );
path = V; path = V;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1092,6 +1115,7 @@
F3B859882EE97E1F0095A9CC /* NRRewardCoinsViewController.swift */, F3B859882EE97E1F0095A9CC /* NRRewardCoinsViewController.swift */,
F3B8598E2EEA5B1C0095A9CC /* NROrderRecordsPageViewController.swift */, F3B8598E2EEA5B1C0095A9CC /* NROrderRecordsPageViewController.swift */,
F3B859902EEA627F0095A9CC /* NROrderRecordsViewController.swift */, F3B859902EEA627F0095A9CC /* NROrderRecordsViewController.swift */,
85606A992EEBC26F005D989D /* NRCoinsPackViewController.swift */,
); );
path = VC; path = VC;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1226,14 +1250,10 @@
inputFileListPaths = ( inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-ReaderHive/Pods-ReaderHive-frameworks-${CONFIGURATION}-input-files.xcfilelist", "${PODS_ROOT}/Target Support Files/Pods-ReaderHive/Pods-ReaderHive-frameworks-${CONFIGURATION}-input-files.xcfilelist",
); );
inputPaths = (
);
name = "[CP] Embed Pods Frameworks"; name = "[CP] Embed Pods Frameworks";
outputFileListPaths = ( outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-ReaderHive/Pods-ReaderHive-frameworks-${CONFIGURATION}-output-files.xcfilelist", "${PODS_ROOT}/Target Support Files/Pods-ReaderHive/Pods-ReaderHive-frameworks-${CONFIGURATION}-output-files.xcfilelist",
); );
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ReaderHive/Pods-ReaderHive-frameworks.sh\"\n"; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ReaderHive/Pods-ReaderHive-frameworks.sh\"\n";
@ -1275,6 +1295,8 @@
F34348DB2ED6F80A00AA7E70 /* NRNovelReaderViewController.swift in Sources */, F34348DB2ED6F80A00AA7E70 /* NRNovelReaderViewController.swift in Sources */,
F34990B92EDEB1620039E939 /* NRHomeNovelModuleItem.swift in Sources */, F34990B92EDEB1620039E939 /* NRHomeNovelModuleItem.swift in Sources */,
F34349032ED943C300AA7E70 /* NRReadParser.swift in Sources */, F34349032ED943C300AA7E70 /* NRReadParser.swift in Sources */,
85606A982EEBC11D005D989D /* Date+NRAdd.swift in Sources */,
85606A922EEBB336005D989D /* NRCoinsPackConfirmItemView.swift in Sources */,
0398106A2ED0505D0006E317 /* NRNetworkReachableManager.swift in Sources */, 0398106A2ED0505D0006E317 /* NRNetworkReachableManager.swift in Sources */,
F34348C32ED6A20700AA7E70 /* NRExploreNovelContentViewController.swift in Sources */, F34348C32ED6A20700AA7E70 /* NRExploreNovelContentViewController.swift in Sources */,
F34991292EE285660039E939 /* NRShowRecommendPop.swift in Sources */, F34991292EE285660039E939 /* NRShowRecommendPop.swift in Sources */,
@ -1329,6 +1351,7 @@
03980F882ED009EB0006E317 /* SceneDelegate.swift in Sources */, 03980F882ED009EB0006E317 /* SceneDelegate.swift in Sources */,
F34991232EE26EAC0039E939 /* NRAlert.swift in Sources */, F34991232EE26EAC0039E939 /* NRAlert.swift in Sources */,
F34348B72ED5C75800AA7E70 /* NRTableViewCell.swift in Sources */, F34348B72ED5C75800AA7E70 /* NRTableViewCell.swift in Sources */,
85606A9C2EEBE243005D989D /* NRCoinsPackHeaderView.swift in Sources */,
F34349102ED9A77A00AA7E70 /* NRPanModalContentView.swift in Sources */, F34349102ED9A77A00AA7E70 /* NRPanModalContentView.swift in Sources */,
F3B859892EE97E1F0095A9CC /* NRRewardCoinsViewController.swift in Sources */, F3B859892EE97E1F0095A9CC /* NRRewardCoinsViewController.swift in Sources */,
039810CE2ED47A130006E317 /* CGMutablePath+NRRoundedCorner.swift in Sources */, 039810CE2ED47A130006E317 /* CGMutablePath+NRRoundedCorner.swift in Sources */,
@ -1359,6 +1382,7 @@
0398109B2ED0692A0006E317 /* NRImageView.swift in Sources */, 0398109B2ED0692A0006E317 /* NRImageView.swift in Sources */,
0398108A2ED0582F0006E317 /* NRDeviceId.swift in Sources */, 0398108A2ED0582F0006E317 /* NRDeviceId.swift in Sources */,
F3B859812EE9716E0095A9CC /* NRBuyRecordsModel.swift in Sources */, F3B859812EE9716E0095A9CC /* NRBuyRecordsModel.swift in Sources */,
85606A9A2EEBC26F005D989D /* NRCoinsPackViewController.swift in Sources */,
F3B859952EEA64430095A9CC /* NROrderRecordsCell.swift in Sources */, F3B859952EEA64430095A9CC /* NROrderRecordsCell.swift in Sources */,
0373D9542ED58AF00017DCC7 /* NRSearchInputView.swift in Sources */, 0373D9542ED58AF00017DCC7 /* NRSearchInputView.swift in Sources */,
F34348EB2ED82B4100AA7E70 /* NRNovelReadSet.swift in Sources */, F34348EB2ED82B4100AA7E70 /* NRNovelReadSet.swift in Sources */,
@ -1375,6 +1399,7 @@
039810622ED04F250006E317 /* NRNetwork.swift in Sources */, 039810622ED04F250006E317 /* NRNetwork.swift in Sources */,
039810782ED054740006E317 /* NRHud.swift in Sources */, 039810782ED054740006E317 /* NRHud.swift in Sources */,
F34991032EE160F00039E939 /* NRUserAPI.swift in Sources */, F34991032EE160F00039E939 /* NRUserAPI.swift in Sources */,
85606A9F2EEBE95A005D989D /* NRDashedLineView.swift in Sources */,
039810C42ED459440006E317 /* NRHomeNovelHotTagView.swift in Sources */, 039810C42ED459440006E317 /* NRHomeNovelHotTagView.swift in Sources */,
F34991122EE170E20039E939 /* NRWebView.swift in Sources */, F34991122EE170E20039E939 /* NRWebView.swift in Sources */,
F3B859402EE6787E0095A9CC /* NRLocalizedManager.swift in Sources */, F3B859402EE6787E0095A9CC /* NRLocalizedManager.swift in Sources */,
@ -1416,11 +1441,13 @@
F3B8598D2EEA51FE0095A9CC /* NRRewardCoinsCell.swift in Sources */, F3B8598D2EEA51FE0095A9CC /* NRRewardCoinsCell.swift in Sources */,
F34990F52EE0346B0039E939 /* NRNovelReadBaseViewController.swift in Sources */, F34990F52EE0346B0039E939 /* NRNovelReadBaseViewController.swift in Sources */,
039810642ED04F480006E317 /* NRTargetType.swift in Sources */, 039810642ED04F480006E317 /* NRTargetType.swift in Sources */,
85606A962EEBB733005D989D /* NRCoinsPackConfirmTipView.swift in Sources */,
F3B8595D2EE907710095A9CC /* NRIAPVerifyModel.swift in Sources */, F3B8595D2EE907710095A9CC /* NRIAPVerifyModel.swift in Sources */,
F343491E2EDAD0AA00AA7E70 /* NRReadTheme.swift in Sources */, F343491E2EDAD0AA00AA7E70 /* NRReadTheme.swift in Sources */,
F3B8597D2EE9627B0095A9CC /* NRWalletHeaderView.swift in Sources */, F3B8597D2EE9627B0095A9CC /* NRWalletHeaderView.swift in Sources */,
039810872ED057260006E317 /* NRUserDefaultsKey.swift in Sources */, 039810872ED057260006E317 /* NRUserDefaultsKey.swift in Sources */,
F34349222EDD227A00AA7E70 /* NRReadSettingSpacingView.swift in Sources */, F34349222EDD227A00AA7E70 /* NRReadSettingSpacingView.swift in Sources */,
85606A902EEBA8F3005D989D /* NRCoinsPackConfirmView.swift in Sources */,
F34990F32EE02FD60039E939 /* NRNovelReadFinishViewController.swift in Sources */, F34990F32EE02FD60039E939 /* NRNovelReadFinishViewController.swift in Sources */,
F34348F92ED855AA00AA7E70 /* NRNovelReadContentViewController.swift in Sources */, F34348F92ED855AA00AA7E70 /* NRNovelReadContentViewController.swift in Sources */,
039810A42ED072380006E317 /* NRHomeNovelListViewController.swift in Sources */, 039810A42ED072380006E317 /* NRHomeNovelListViewController.swift in Sources */,
@ -1434,6 +1461,7 @@
F3B859772EE95B220095A9CC /* NRMeVipView.swift in Sources */, F3B859772EE95B220095A9CC /* NRMeVipView.swift in Sources */,
F3B8594E2EE905A70095A9CC /* NRStoreAPI.swift in Sources */, F3B8594E2EE905A70095A9CC /* NRStoreAPI.swift in Sources */,
0373D94F2ED58A1E0017DCC7 /* NRSearchViewController.swift in Sources */, 0373D94F2ED58A1E0017DCC7 /* NRSearchViewController.swift in Sources */,
85606A942EEBB3FE005D989D /* NRCoinsPackConfirmTitleView.swift in Sources */,
0398108E2ED060020006E317 /* UIFont+NRAdd.swift in Sources */, 0398108E2ED060020006E317 /* UIFont+NRAdd.swift in Sources */,
F34348D32ED6E0F400AA7E70 /* NRMyListViewController.swift in Sources */, F34348D32ED6E0F400AA7E70 /* NRMyListViewController.swift in Sources */,
0398105C2ED047FE0006E317 /* NRTabBarController.swift in Sources */, 0398105C2ED047FE0006E317 /* NRTabBarController.swift in Sources */,
@ -1481,7 +1509,7 @@
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = 9JR2Y32ZU3;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = ReaderHive/Source/Info.plist; INFOPLIST_FILE = ReaderHive/Source/Info.plist;
@ -1520,11 +1548,9 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic;
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = 9JR2Y32ZU3;
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 9JR2Y32ZU3;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = ReaderHive/Source/Info.plist; INFOPLIST_FILE = ReaderHive/Source/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = ReaderHive; INFOPLIST_KEY_CFBundleDisplayName = ReaderHive;
@ -1543,7 +1569,6 @@
PRODUCT_BUNDLE_IDENTIFIER = com.lssj.ReaderHive; PRODUCT_BUNDLE_IDENTIFIER = com.lssj.ReaderHive;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = readerdev;
STRING_CATALOG_GENERATE_SYMBOLS = YES; STRING_CATALOG_GENERATE_SYMBOLS = YES;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO; SUPPORTS_MACCATALYST = NO;

View 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)
}
}
}

View File

@ -13,6 +13,7 @@ extension UIView {
fileprivate struct AssociatedKeys { fileprivate struct AssociatedKeys {
static var nr_roundedCorner: Int? static var nr_roundedCorner: Int?
static var nr_effect: Int? static var nr_effect: Int?
static var nr_border: Int?
} }
@objc public static func fa_Awake() { @objc public static func fa_Awake() {
@ -24,6 +25,8 @@ extension UIView {
_updateRoundedCorner() _updateRoundedCorner()
_updateBorder()
if let effectView = effectView, effectView.frame != self.bounds { if let effectView = effectView, effectView.frame != self.bounds {
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: -------------- -------------- //MARK: -------------- --------------
extension UIView { extension UIView {
private var effectView: UIVisualEffectView? { private var effectView: UIVisualEffectView? {

View 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()
}
}

View File

@ -13,11 +13,14 @@ class NRLabel: UILabel {
var textStartPoint: CGPoint? var textStartPoint: CGPoint?
var textEndPoint: CGPoint? var textEndPoint: CGPoint?
var textColorImage: UIImage?
override func layoutSubviews() { override func layoutSubviews() {
super.layoutSubviews() super.layoutSubviews()
let size = self.bounds.size 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)) self.textColor = UIColor(patternImage: UIImage.nr_getGradientImage(size: size, colors: colors, startPoint: startPoint, endPoint: endPoine))
} }
} }

View File

@ -21,7 +21,7 @@ class NRPanModalContentView: HWPanModalContentView {
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
self.backgroundColor = .F_8_F_8_F_8
} }
required init?(coder: NSCoder) { required init?(coder: NSCoder) {
@ -43,7 +43,7 @@ class NRPanModalContentView: HWPanModalContentView {
override func backgroundConfig() -> HWBackgroundConfig { override func backgroundConfig() -> HWBackgroundConfig {
let config = HWBackgroundConfig() let config = HWBackgroundConfig()
config.backgroundAlpha = 0.0 config.backgroundAlpha = 0.5
return config return config
} }

View File

@ -87,7 +87,7 @@ extension NRExploreNovelMenuView: NRWaterfallMutiSectionDelegate {
func heightForRowAtIndexPath(collectionView collection: UICollectionView, layout: NRWaterfallFlowLayout, indexPath: IndexPath, itemWidth: CGFloat) -> CGFloat { func heightForRowAtIndexPath(collectionView collection: UICollectionView, layout: NRWaterfallFlowLayout, indexPath: IndexPath, itemWidth: CGFloat) -> CGFloat {
let item = self.viewModel?.menuDataArr[indexPath.row] 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 return textHeight + 44
} }

View File

@ -39,7 +39,7 @@ class NRHomeNovelListViewController: NRViewController {
return view return view
}() }()
deinit { @MainActor deinit {
NotificationCenter.default.removeObserver(self) NotificationCenter.default.removeObserver(self)
} }

View File

@ -49,7 +49,7 @@ class NRHomeNovelViewController: NRViewController {
return vc return vc
}() }()
deinit { @MainActor deinit {
NotificationCenter.default.removeObserver(self) NotificationCenter.default.removeObserver(self)
} }

View File

@ -7,11 +7,31 @@
import UIKit import UIKit
import SnapKit import SnapKit
import YYCategories
class NRMeHeaderView: UITableViewHeaderFooterView { class NRMeHeaderView: UITableViewHeaderFooterView {
// var contentHeight: CGFloat = 200 // 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 = { private lazy var avatarImageView: UIImageView = {
let imageView = NRImageView() let imageView = NRImageView()
imageView.layer.cornerRadius = 30 imageView.layer.cornerRadius = 30
@ -66,6 +86,11 @@ class NRMeHeaderView: UITableViewHeaderFooterView {
private lazy var coinsPackView: NRMeCoinsPackView = { private lazy var coinsPackView: NRMeCoinsPackView = {
let view = 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 return view
}() }()
@ -74,20 +99,10 @@ class NRMeHeaderView: UITableViewHeaderFooterView {
return view return view
}() }()
deinit {
NotificationCenter.default.removeObserver(self)
}
override init(reuseIdentifier: String?) { override init(reuseIdentifier: String?) {
super.init(reuseIdentifier: reuseIdentifier) super.init(reuseIdentifier: reuseIdentifier)
NotificationCenter.default.addObserver(self, selector: #selector(userInfoUpdateNotification), name: NRLoginManager.userInfoUpdateNotification, object: nil)
nr_setupUI() 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") 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
}
} }

View File

@ -10,6 +10,16 @@ import SnapKit
class NRMeVipView: UIView { 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 = { private lazy var contentView: UIView = {
let view = UIView() let view = UIView()
view.backgroundColor = .F_2_EFEE view.backgroundColor = .F_2_EFEE
@ -45,8 +55,7 @@ class NRMeVipView: UIView {
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
titleLabel.text = "Weekly VIP".localized
timeLabel.text = "Expiration Time2023-11-23"
nr_setupUI() nr_setupUI()
} }

View File

@ -32,9 +32,13 @@ class NRMeViewController: NRViewController {
return tableView return tableView
}() }()
@MainActor deinit {
NotificationCenter.default.removeObserver(self)
}
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(userInfoUpdateNotification), name: NRLoginManager.userInfoUpdateNotification, object: nil)
nr_setupUI() nr_setupUI()
} }
@ -53,6 +57,10 @@ class NRMeViewController: NRViewController {
} }
} }
@objc private func userInfoUpdateNotification() {
self.tableView.reloadData()
}
} }
extension NRMeViewController { extension NRMeViewController {
@ -83,6 +91,7 @@ extension NRMeViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let view = tableView.dequeueReusableHeaderFooterView(withIdentifier: "header") as? NRMeHeaderView let view = tableView.dequeueReusableHeaderFooterView(withIdentifier: "header") as? NRMeHeaderView
view?.userInfo = NRLoginManager.manager.userInfo
return view return view
} }

View File

@ -66,7 +66,7 @@ class NRNovelDetailViewController: NRViewController {
return recommandVC.collectionView return recommandVC.collectionView
} }
deinit { @MainActor deinit {
recommandListView.removeObserver(self, forKeyPath: "contentSize") recommandListView.removeObserver(self, forKeyPath: "contentSize")
} }

View File

@ -26,7 +26,7 @@ class NRNovelReadContentViewController: NRNovelReadBaseViewController {
return view return view
}() }()
deinit { @MainActor deinit {
NotificationCenter.default.removeObserver(self) NotificationCenter.default.removeObserver(self)
} }

View File

@ -72,7 +72,7 @@ class NRNovelReaderViewController: NRViewController {
return view return view
}() }()
deinit { @MainActor deinit {
NotificationCenter.default.removeObserver(self) NotificationCenter.default.removeObserver(self)
} }

View File

@ -7,7 +7,7 @@
import UIKit import UIKit
import SmartCodable import SmartCodable
import StoreKit internal import StoreKit
class NRPayDateModel: NSObject, SmartCodable { class NRPayDateModel: NSObject, SmartCodable {

View 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")
}
}

View 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")
}
}
}

View 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
}
}

View 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)
}
}
}

View 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")
}
}
}

View File

@ -66,7 +66,7 @@ class NRRewardCoinsCell: NRTableViewCell {
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier) super.init(style: style, reuseIdentifier: reuseIdentifier)
nr_setupUI()
} }
@MainActor required init?(coder: NSCoder) { @MainActor required init?(coder: NSCoder) {

View File

@ -6,7 +6,148 @@
// //
import UIKit import UIKit
import SnapKit
class NRStoreCoinsBigCell: NRStoreCoinsCell { 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)
}
}
} }

View File

@ -6,7 +6,208 @@
// //
import UIKit import UIKit
import SnapKit
internal import StoreKit
import YYCategories
class NRStoreCoinsPackCell: NRStoreCoinsCell { 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)
}
}
} }

View File

@ -6,7 +6,141 @@
// //
import UIKit import UIKit
import SnapKit
class NRStoreCoinsSmallCell: NRStoreCoinsCell { 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)
}
}
} }

View File

@ -7,6 +7,7 @@
import UIKit import UIKit
import SnapKit import SnapKit
import HWPanModal
class NRStoreCoinsView: UIView { class NRStoreCoinsView: UIView {
@ -27,7 +28,7 @@ class NRStoreCoinsView: UIView {
private lazy var collectionViewLayout: UICollectionViewCompositionalLayout = { private lazy var collectionViewLayout: UICollectionViewCompositionalLayout = {
let config = UICollectionViewCompositionalLayoutConfiguration() let config = UICollectionViewCompositionalLayoutConfiguration()
config.interSectionSpacing = 10 config.interSectionSpacing = 12
let layout = UICollectionViewCompositionalLayout { [weak self] section, _ in let layout = UICollectionViewCompositionalLayout { [weak self] section, _ in
guard let self = self else { return nil} 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 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]) 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) let layoutSection = NSCollectionLayoutSection(group: group)
layoutSection.interGroupSpacing = 10 layoutSection.interGroupSpacing = 12
layoutSection.contentInsets = .init(top: 0, leading: 16, bottom: 0, trailing: 16) layoutSection.contentInsets = .init(top: 0, leading: 16, bottom: 0, trailing: 16)
return layoutSection return layoutSection
} }
@ -170,11 +171,11 @@ extension NRStoreCoinsView {
private func smallLayoutSection() -> NSCollectionLayoutSection { private func smallLayoutSection() -> NSCollectionLayoutSection {
let item = NSCollectionLayoutItem(layoutSize: .init(widthDimension: .fractionalWidth(1 / 3), heightDimension: .fractionalHeight(1))) 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]) let group = NSCollectionLayoutGroup.horizontal(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .absolute(84)), subitems: [item])
group.interItemSpacing = .fixed(8) group.interItemSpacing = .fixed(15)
let layoutSection = NSCollectionLayoutSection(group: group) let layoutSection = NSCollectionLayoutSection(group: group)
layoutSection.interGroupSpacing = 10 layoutSection.interGroupSpacing = 12
layoutSection.contentInsets = .init(top: 0, leading: 16, bottom: 0, trailing: 16) layoutSection.contentInsets = .init(top: 0, leading: 16, bottom: 0, trailing: 16)
return layoutSection return layoutSection
} }
@ -186,7 +187,7 @@ extension NRStoreCoinsView {
let layoutSection = NSCollectionLayoutSection(group: group) let layoutSection = NSCollectionLayoutSection(group: group)
layoutSection.interGroupSpacing = 10 layoutSection.interGroupSpacing = 12
layoutSection.contentInsets = .init(top: 0, leading: 16, bottom: 0, trailing: 16) layoutSection.contentInsets = .init(top: 0, leading: 16, bottom: 0, trailing: 16)
return layoutSection return layoutSection
} }
@ -225,23 +226,19 @@ extension NRStoreCoinsView: UICollectionViewDelegate, UICollectionViewDataSource
collectionView.reloadData() collectionView.reloadData()
if model.buy_type == .subCoins { if model.buy_type == .subCoins {
// let view = FACoinPackConfirmView() let view = NRCoinsPackConfirmView()
// view.shortPlayId = self.shortPlayId view.shortPlayId = self.shortPlayId
// view.videoId = self.videoId view.videoId = self.videoId
// view.model = model view.model = model
// view.buyFinishHandle = { [weak self] in view.buyFinishHandle = { [weak self] in
// guard let self = self else { return } guard let self = self else { return }
// NRLoginManager.manager.updateUserInfo() self.buyFinishHandle?()
// self.buyFinishHandle?() }
// } view.present(in: nil)
// view.present(in: nil)
} else { } else {
NRIapManager.manager.start(model: model, shortPlayId: self.shortPlayId, videoId: self.videoId) { [weak self] finish in NRIapManager.manager.start(model: model, shortPlayId: self.shortPlayId, videoId: self.videoId) { [weak self] finish in
guard let self = self else { return } guard let self = self else { return }
if finish { if finish {
Task {
await NRLoginManager.manager.updateUserInfo()
}
self.buyFinishHandle?() self.buyFinishHandle?()
} }
} }

View File

@ -6,11 +6,189 @@
// //
import UIKit import UIKit
import SnapKit
import YYCategories
class NRStoreVipCell: UICollectionViewCell { class NRStoreVipCell: UICollectionViewCell {
var model: NRPayItem? { var model: NRPayItem? {
didSet { 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)
}
}
} }

View File

@ -31,10 +31,10 @@ class NRStoreVipView: UIView {
let item = NSCollectionLayoutItem(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .fractionalHeight(1))) 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) let layoutSection = NSCollectionLayoutSection(group: group)
layoutSection.interGroupSpacing = 14 layoutSection.interGroupSpacing = 12
layoutSection.contentInsets = .init(top: 0, leading: 16, bottom: 0, trailing: 16) layoutSection.contentInsets = .init(top: 0, leading: 16, bottom: 0, trailing: 16)

View 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()
}
}
}

View File

@ -11,6 +11,10 @@ import SnapKit
class NRStoreViewController: NRViewController { class NRStoreViewController: NRViewController {
private var payRequest: NRPayDataRequest = NRPayDataRequest()
private var payDataModel: NRPayDateModel? = NRIapManager.manager.payDateModel
private lazy var scrollView: NRScrollView = { private lazy var scrollView: NRScrollView = {
let scrollView = NRScrollView() let scrollView = NRScrollView()
return scrollView return scrollView
@ -27,7 +31,7 @@ class NRStoreViewController: NRViewController {
let view = NRStoreCoinsView() let view = NRStoreCoinsView()
view.isShowTitle = true view.isShowTitle = true
view.buyFinishHandle = { [weak self] in view.buyFinishHandle = { [weak self] in
self?.buyFinish()
} }
return view return view
}() }()
@ -36,7 +40,7 @@ class NRStoreViewController: NRViewController {
let view = NRStoreVipView() let view = NRStoreVipView()
view.isShowTitle = true view.isShowTitle = true
view.buyFinishHandle = { [weak self] in view.buyFinishHandle = { [weak self] in
self?.buyFinish()
} }
return view return view
}() }()
@ -46,10 +50,13 @@ class NRStoreViewController: NRViewController {
self.title = "Store".localized self.title = "Store".localized
configNavigationBack("arrow_left_icon_05") configNavigationBack("arrow_left_icon_05")
stackView.addArrangedSubview(coinsView)
stackView.addArrangedSubview(vipView)
nr_setupUI() nr_setupUI()
restore(isLoding: false)
requestPayData()
updateLayout()
} }
override func viewWillAppear(_ animated: Bool) { override func viewWillAppear(_ animated: Bool) {
@ -58,6 +65,61 @@ class NRStoreViewController: NRViewController {
self.nr_setNavigationStyle(titleColor: UINavigationBar.titleBlackColor) 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 { 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()
}
}
}
}

View File

@ -32,7 +32,7 @@ class NRWalletViewController: NRViewController {
return tableView return tableView
}() }()
deinit { @MainActor deinit {
NotificationCenter.default.removeObserver(self) NotificationCenter.default.removeObserver(self)
} }

View File

@ -6,7 +6,7 @@
// //
import UIKit import UIKit
import StoreKit internal import StoreKit
class NRIapManager { class NRIapManager {
typealias CompletionHandler = ((_ finish: Bool) -> Void) typealias CompletionHandler = ((_ finish: Bool) -> Void)
@ -277,8 +277,8 @@ extension NRIapManager {
func preloadingProducts() { func preloadingProducts() {
JXIAPManager.manager.fetchReceipt { _ in JXIAPManager.manager.fetchReceipt { _ in
self.payRequest = NRPayDataRequest() self.payRequest = NRPayDataRequest()
self.payRequest?.requestProducts(isLoding: false, isToast: false) { model in self.payRequest?.requestProducts(isLoding: false, isToast: false) { _ in
} }
} }
} }

View File

@ -6,7 +6,7 @@
// //
import UIKit import UIKit
import StoreKit internal import StoreKit
class NRPayDataRequest: NSObject { class NRPayDataRequest: NSObject {

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

View 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
}
}

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 KiB

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 KiB

View 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
}
}

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 910 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

View 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
}
}

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

View 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
}
}

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Some files were not shown because too many files have changed in this diff Show More