Compare commits
70 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
c96a1cdc5b | ||
|
e5261c3fc8 | ||
|
9adad48800 | ||
|
d3a1aa1beb | ||
|
81bb16598a | ||
|
509aa81f8a | ||
|
84689e7ade | ||
|
eea76fabfc | ||
|
e18a1652ca | ||
|
11cd8628aa | ||
|
d6e314a97f | ||
|
4f402efabf | ||
|
6e970b4a73 | ||
|
8ebd677a1e | ||
|
fbc2d11d48 | ||
|
7a2faa9fe0 | ||
|
ef0b3b1ab8 | ||
|
cb70d63465 | ||
|
9f3242cb26 | ||
|
18789cb6ec | ||
|
e3d7ffe773 | ||
|
948b44e913 | ||
|
bfb189cad0 | ||
|
b3ff8fb010 | ||
|
6a6a19b4a8 | ||
|
5c1b2c7ffb | ||
|
81f6dee213 | ||
|
6149f994bd | ||
|
c772c16e29 | ||
|
6107b37720 | ||
|
74ad92fe57 | ||
|
d859febdc8 | ||
|
1dd0094b1b | ||
|
ff3f5a8f51 | ||
|
607bcafb32 | ||
|
a94e3a8fd7 | ||
|
b4b867b7d4 | ||
|
e4d88bae10 | ||
|
fb601875ef | ||
|
5f3deeb52d | ||
|
fa0db110b6 | ||
|
e8b2c4668f | ||
|
34beab7b6b | ||
|
e0e727573a | ||
|
b78bd95996 | ||
|
94e047a0e9 | ||
|
2bbfb16139 | ||
|
5814d4f434 | ||
|
c73ae42733 | ||
|
b710eb9ac1 | ||
|
e4e92ee9bf | ||
|
65a0753c20 | ||
|
b5b55119f6 | ||
|
53dff92edf | ||
|
9a50ca2fdc | ||
|
9a26c4ac7f | ||
|
538c5a5a86 | ||
|
73078a1acf | ||
|
d5a6e44f49 | ||
|
05e80f50e2 | ||
|
c3944c5342 | ||
|
490dc77b1e | ||
|
1807584f6d | ||
|
153c8ac080 | ||
|
4345d8e3dd | ||
|
f75e05808a | ||
|
5ad8ef6ce0 | ||
|
351d7d8262 | ||
|
c845ecb41d | ||
|
d7a2582c86 |
3
.gitignore
vendored
@ -66,7 +66,7 @@ xcuserdata/
|
|||||||
|
|
||||||
## Playgrounds
|
## Playgrounds
|
||||||
timeline.xctimeline
|
timeline.xctimeline
|
||||||
playground.xcworkspace
|
*.xcworkspace
|
||||||
|
|
||||||
# Swift Package Manager
|
# Swift Package Manager
|
||||||
#
|
#
|
||||||
@ -89,6 +89,7 @@ playground.xcworkspace
|
|||||||
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
||||||
#
|
#
|
||||||
Pods/
|
Pods/
|
||||||
|
Podfile.lock
|
||||||
#
|
#
|
||||||
# Add this line if you want to avoid checking in source code from the Xcode workspace
|
# Add this line if you want to avoid checking in source code from the Xcode workspace
|
||||||
# *.xcworkspace
|
# *.xcworkspace
|
||||||
|
41
Apple账号资料.txt
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
Thimra 开发者账号信息
|
||||||
|
认证人 :陈佳
|
||||||
|
认证设备 :Mac min
|
||||||
|
设备型号 :MU9D3CH/A
|
||||||
|
序列号 :TVJJ97WWHH
|
||||||
|
手机号码 :190 7319 2960
|
||||||
|
|
||||||
|
企业邮箱 :thimra@thimratv.com 密码:9oldpGT_y0qR
|
||||||
|
D-U-N-S:457012112
|
||||||
|
公司主体 :Changsha Jiaer Network Technology Co., Ltd.
|
||||||
|
公司地址 :Room 15006, Xijing Commercial Plaza, No. 383 Jinxing Middle Road
|
||||||
|
官网 :https://www.thimratv.com
|
||||||
|
appleId :cs.jiaer.developer@icloud.com
|
||||||
|
密码 :Discover2024
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
账户持有人:
|
||||||
|
Hong Kong Qin Jiu Media Culture Co., Limited
|
||||||
|
银行账号:
|
||||||
|
9558851001034420709
|
||||||
|
复制
|
||||||
|
币种:
|
||||||
|
USD
|
||||||
|
费率:
|
||||||
|
0.7%
|
||||||
|
银行名称:
|
||||||
|
Industrial And Commercial Bank Of China Shanghai Pilot Free Trade Zone Branch Xinling Road Sub-Branch
|
||||||
|
Swift Code:
|
||||||
|
ICBKCNBJSHI
|
||||||
|
CNAPS代码
|
||||||
|
102290019237
|
||||||
|
银行所在国家/地区:
|
||||||
|
China
|
||||||
|
银行地址:
|
||||||
|
NO.118 Xinling Rd Shanghai Branch
|
||||||
|
|
||||||
|
|
||||||
|
沙盒账号:
|
||||||
|
jiaer@test.com
|
||||||
|
Cje12345
|
@ -1,449 +0,0 @@
|
|||||||
// !$*UTF8*$!
|
|
||||||
{
|
|
||||||
archiveVersion = 1;
|
|
||||||
classes = {
|
|
||||||
};
|
|
||||||
objectVersion = 77;
|
|
||||||
objects = {
|
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
|
||||||
91D08C5AEAE459A3B8EA48C6 /* Pods_MoviaBox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A81436A54285C9EE97EEBC50 /* Pods_MoviaBox.framework */; };
|
|
||||||
/* End PBXBuildFile section */
|
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
|
||||||
109EB01BE447EE135493CA38 /* Pods-MoviaBox.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MoviaBox.release.xcconfig"; path = "Target Support Files/Pods-MoviaBox/Pods-MoviaBox.release.xcconfig"; sourceTree = "<group>"; };
|
|
||||||
1DBC40592DA4EDFC0093FCB0 /* MoviaBox.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MoviaBox.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
||||||
1F666DE0B12C863F26BE5027 /* Pods-MoviaBox.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MoviaBox.debug.xcconfig"; path = "Target Support Files/Pods-MoviaBox/Pods-MoviaBox.debug.xcconfig"; sourceTree = "<group>"; };
|
|
||||||
A81436A54285C9EE97EEBC50 /* Pods_MoviaBox.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MoviaBox.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
||||||
F7763FEFB6BEB1A75D6FBA0A /* Pods-Thimra.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Thimra.debug.xcconfig"; path = "Target Support Files/Pods-Thimra/Pods-Thimra.debug.xcconfig"; sourceTree = "<group>"; };
|
|
||||||
FEA583158A7C05D8D7C5A9FC /* Pods-Thimra.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Thimra.release.xcconfig"; path = "Target Support Files/Pods-Thimra/Pods-Thimra.release.xcconfig"; sourceTree = "<group>"; };
|
|
||||||
/* End PBXFileReference section */
|
|
||||||
|
|
||||||
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
|
||||||
1DBC41052DA4F98D0093FCB0 /* Exceptions for "MoviaBox" folder in "MoviaBox" target */ = {
|
|
||||||
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
|
||||||
membershipExceptions = (
|
|
||||||
Source/Info.plist,
|
|
||||||
);
|
|
||||||
target = 1DBC40582DA4EDFC0093FCB0 /* MoviaBox */;
|
|
||||||
};
|
|
||||||
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
|
||||||
|
|
||||||
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
|
||||||
1DBC40FB2DA4F98D0093FCB0 /* MoviaBox */ = {
|
|
||||||
isa = PBXFileSystemSynchronizedRootGroup;
|
|
||||||
exceptions = (
|
|
||||||
1DBC41052DA4F98D0093FCB0 /* Exceptions for "MoviaBox" folder in "MoviaBox" target */,
|
|
||||||
);
|
|
||||||
path = MoviaBox;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
/* End PBXFileSystemSynchronizedRootGroup section */
|
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
|
||||||
1DBC40562DA4EDFC0093FCB0 /* Frameworks */ = {
|
|
||||||
isa = PBXFrameworksBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
91D08C5AEAE459A3B8EA48C6 /* Pods_MoviaBox.framework in Frameworks */,
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
/* End PBXFrameworksBuildPhase section */
|
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
|
||||||
0061C3496D158807460301A9 /* Pods */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
F7763FEFB6BEB1A75D6FBA0A /* Pods-Thimra.debug.xcconfig */,
|
|
||||||
FEA583158A7C05D8D7C5A9FC /* Pods-Thimra.release.xcconfig */,
|
|
||||||
1F666DE0B12C863F26BE5027 /* Pods-MoviaBox.debug.xcconfig */,
|
|
||||||
109EB01BE447EE135493CA38 /* Pods-MoviaBox.release.xcconfig */,
|
|
||||||
);
|
|
||||||
path = Pods;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
1DBC40502DA4EDFC0093FCB0 = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
1DBC40FB2DA4F98D0093FCB0 /* MoviaBox */,
|
|
||||||
1DBC405A2DA4EDFC0093FCB0 /* Products */,
|
|
||||||
0061C3496D158807460301A9 /* Pods */,
|
|
||||||
B6C9E282BAC4C4B3E926A853 /* Frameworks */,
|
|
||||||
);
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
1DBC405A2DA4EDFC0093FCB0 /* Products */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
1DBC40592DA4EDFC0093FCB0 /* MoviaBox.app */,
|
|
||||||
);
|
|
||||||
name = Products;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
B6C9E282BAC4C4B3E926A853 /* Frameworks */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
A81436A54285C9EE97EEBC50 /* Pods_MoviaBox.framework */,
|
|
||||||
);
|
|
||||||
name = Frameworks;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
/* End PBXGroup section */
|
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
|
||||||
1DBC40582DA4EDFC0093FCB0 /* MoviaBox */ = {
|
|
||||||
isa = PBXNativeTarget;
|
|
||||||
buildConfigurationList = 1DBC40822DA4EE010093FCB0 /* Build configuration list for PBXNativeTarget "MoviaBox" */;
|
|
||||||
buildPhases = (
|
|
||||||
801A3E3FF53193556BBE9EBF /* [CP] Check Pods Manifest.lock */,
|
|
||||||
1DBC40552DA4EDFC0093FCB0 /* Sources */,
|
|
||||||
1DBC40562DA4EDFC0093FCB0 /* Frameworks */,
|
|
||||||
1DBC40572DA4EDFC0093FCB0 /* Resources */,
|
|
||||||
4E1CBF3F1205E28DFCF11722 /* [CP] Embed Pods Frameworks */,
|
|
||||||
);
|
|
||||||
buildRules = (
|
|
||||||
);
|
|
||||||
dependencies = (
|
|
||||||
);
|
|
||||||
fileSystemSynchronizedGroups = (
|
|
||||||
1DBC40FB2DA4F98D0093FCB0 /* MoviaBox */,
|
|
||||||
);
|
|
||||||
name = MoviaBox;
|
|
||||||
productName = ShortPlay;
|
|
||||||
productReference = 1DBC40592DA4EDFC0093FCB0 /* MoviaBox.app */;
|
|
||||||
productType = "com.apple.product-type.application";
|
|
||||||
};
|
|
||||||
/* End PBXNativeTarget section */
|
|
||||||
|
|
||||||
/* Begin PBXProject section */
|
|
||||||
1DBC40512DA4EDFC0093FCB0 /* Project object */ = {
|
|
||||||
isa = PBXProject;
|
|
||||||
attributes = {
|
|
||||||
BuildIndependentTargetsInParallel = 1;
|
|
||||||
LastSwiftUpdateCheck = 1620;
|
|
||||||
LastUpgradeCheck = 1620;
|
|
||||||
TargetAttributes = {
|
|
||||||
1DBC40582DA4EDFC0093FCB0 = {
|
|
||||||
CreatedOnToolsVersion = 16.2;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
buildConfigurationList = 1DBC40542DA4EDFC0093FCB0 /* Build configuration list for PBXProject "MoviaBox" */;
|
|
||||||
developmentRegion = en;
|
|
||||||
hasScannedForEncodings = 0;
|
|
||||||
knownRegions = (
|
|
||||||
en,
|
|
||||||
Base,
|
|
||||||
);
|
|
||||||
mainGroup = 1DBC40502DA4EDFC0093FCB0;
|
|
||||||
minimizedProjectReferenceProxies = 1;
|
|
||||||
packageReferences = (
|
|
||||||
);
|
|
||||||
preferredProjectObjectVersion = 77;
|
|
||||||
productRefGroup = 1DBC405A2DA4EDFC0093FCB0 /* Products */;
|
|
||||||
projectDirPath = "";
|
|
||||||
projectRoot = "";
|
|
||||||
targets = (
|
|
||||||
1DBC40582DA4EDFC0093FCB0 /* MoviaBox */,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
/* End PBXProject section */
|
|
||||||
|
|
||||||
/* Begin PBXResourcesBuildPhase section */
|
|
||||||
1DBC40572DA4EDFC0093FCB0 /* Resources */ = {
|
|
||||||
isa = PBXResourcesBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
/* End PBXResourcesBuildPhase section */
|
|
||||||
|
|
||||||
/* Begin PBXShellScriptBuildPhase section */
|
|
||||||
4E1CBF3F1205E28DFCF11722 /* [CP] Embed Pods Frameworks */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputFileListPaths = (
|
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-MoviaBox/Pods-MoviaBox-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
|
||||||
);
|
|
||||||
name = "[CP] Embed Pods Frameworks";
|
|
||||||
outputFileListPaths = (
|
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-MoviaBox/Pods-MoviaBox-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-MoviaBox/Pods-MoviaBox-frameworks.sh\"\n";
|
|
||||||
showEnvVarsInLog = 0;
|
|
||||||
};
|
|
||||||
801A3E3FF53193556BBE9EBF /* [CP] Check Pods Manifest.lock */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputFileListPaths = (
|
|
||||||
);
|
|
||||||
inputPaths = (
|
|
||||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
|
||||||
"${PODS_ROOT}/Manifest.lock",
|
|
||||||
);
|
|
||||||
name = "[CP] Check Pods Manifest.lock";
|
|
||||||
outputFileListPaths = (
|
|
||||||
);
|
|
||||||
outputPaths = (
|
|
||||||
"$(DERIVED_FILE_DIR)/Pods-MoviaBox-checkManifestLockResult.txt",
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
|
||||||
showEnvVarsInLog = 0;
|
|
||||||
};
|
|
||||||
/* End PBXShellScriptBuildPhase section */
|
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
|
||||||
1DBC40552DA4EDFC0093FCB0 /* Sources */ = {
|
|
||||||
isa = PBXSourcesBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
/* End PBXSourcesBuildPhase section */
|
|
||||||
|
|
||||||
/* Begin XCBuildConfiguration section */
|
|
||||||
1DBC40832DA4EE010093FCB0 /* Debug */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
baseConfigurationReference = 1F666DE0B12C863F26BE5027 /* Pods-MoviaBox.debug.xcconfig */;
|
|
||||||
buildSettings = {
|
|
||||||
ARCHS = "$(ARCHS_STANDARD)";
|
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
|
||||||
CODE_SIGN_STYLE = Automatic;
|
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
|
||||||
DEVELOPMENT_TEAM = TWDZ3MP9DV;
|
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
|
||||||
INFOPLIST_FILE = MoviaBox/Source/Info.plist;
|
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = MoviaBox;
|
|
||||||
INFOPLIST_KEY_NSCameraUsageDescription = "The APP needs to access your album to provide screenshots for feedback.";
|
|
||||||
INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "The APP needs to access your album to provide screenshots for feedback.";
|
|
||||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
|
||||||
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
|
|
||||||
INFOPLIST_KEY_UIMainStoryboardFile = "";
|
|
||||||
INFOPLIST_KEY_UIStatusBarHidden = NO;
|
|
||||||
INFOPLIST_KEY_UIStatusBarStyle = UIStatusBarStyleLightContent;
|
|
||||||
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
|
|
||||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
|
|
||||||
INFOPLIST_KEY_UIUserInterfaceStyle = Light;
|
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
|
||||||
"$(inherited)",
|
|
||||||
"@executable_path/Frameworks",
|
|
||||||
);
|
|
||||||
MARKETING_VERSION = 1.0;
|
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.thimratv.app;
|
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
|
||||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
|
||||||
SUPPORTS_MACCATALYST = NO;
|
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "MoviaBox/Source/MoviaBox-Bridging-Header.h";
|
|
||||||
SWIFT_VERSION = 5.0;
|
|
||||||
TARGETED_DEVICE_FAMILY = 1;
|
|
||||||
VALID_ARCHS = "arm64 arm64e armv7s x86_64";
|
|
||||||
};
|
|
||||||
name = Debug;
|
|
||||||
};
|
|
||||||
1DBC40842DA4EE010093FCB0 /* Release */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
baseConfigurationReference = 109EB01BE447EE135493CA38 /* Pods-MoviaBox.release.xcconfig */;
|
|
||||||
buildSettings = {
|
|
||||||
ARCHS = "$(ARCHS_STANDARD)";
|
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
|
||||||
CODE_SIGN_STYLE = Automatic;
|
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
|
||||||
DEVELOPMENT_TEAM = TWDZ3MP9DV;
|
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
|
||||||
INFOPLIST_FILE = MoviaBox/Source/Info.plist;
|
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = MoviaBox;
|
|
||||||
INFOPLIST_KEY_NSCameraUsageDescription = "The APP needs to access your album to provide screenshots for feedback.";
|
|
||||||
INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "The APP needs to access your album to provide screenshots for feedback.";
|
|
||||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
|
||||||
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
|
|
||||||
INFOPLIST_KEY_UIMainStoryboardFile = "";
|
|
||||||
INFOPLIST_KEY_UIStatusBarHidden = NO;
|
|
||||||
INFOPLIST_KEY_UIStatusBarStyle = UIStatusBarStyleLightContent;
|
|
||||||
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
|
|
||||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
|
|
||||||
INFOPLIST_KEY_UIUserInterfaceStyle = Light;
|
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
|
||||||
"$(inherited)",
|
|
||||||
"@executable_path/Frameworks",
|
|
||||||
);
|
|
||||||
MARKETING_VERSION = 1.0;
|
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.thimratv.app;
|
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
|
||||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
|
||||||
SUPPORTS_MACCATALYST = NO;
|
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "MoviaBox/Source/MoviaBox-Bridging-Header.h";
|
|
||||||
SWIFT_VERSION = 5.0;
|
|
||||||
TARGETED_DEVICE_FAMILY = 1;
|
|
||||||
VALID_ARCHS = "arm64 arm64e armv7s x86_64";
|
|
||||||
};
|
|
||||||
name = Release;
|
|
||||||
};
|
|
||||||
1DBC40852DA4EE010093FCB0 /* Debug */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
buildSettings = {
|
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
|
||||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
|
||||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
|
||||||
CLANG_ENABLE_MODULES = YES;
|
|
||||||
CLANG_ENABLE_OBJC_ARC = YES;
|
|
||||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
|
||||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
|
||||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
|
||||||
CLANG_WARN_COMMA = YES;
|
|
||||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
|
||||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
|
||||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
|
||||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
|
||||||
CLANG_WARN_EMPTY_BODY = YES;
|
|
||||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
|
||||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
|
||||||
CLANG_WARN_INT_CONVERSION = YES;
|
|
||||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
|
||||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
|
||||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
|
||||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
|
||||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
|
||||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
|
||||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
|
||||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
|
||||||
COPY_PHASE_STRIP = NO;
|
|
||||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
|
||||||
ENABLE_TESTABILITY = YES;
|
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
|
||||||
GCC_DYNAMIC_NO_PIC = NO;
|
|
||||||
GCC_NO_COMMON_BLOCKS = YES;
|
|
||||||
GCC_OPTIMIZATION_LEVEL = 0;
|
|
||||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
|
||||||
"DEBUG=1",
|
|
||||||
"$(inherited)",
|
|
||||||
);
|
|
||||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
|
||||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
|
||||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 18.2;
|
|
||||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
|
||||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
|
||||||
MTL_FAST_MATH = YES;
|
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
|
||||||
SDKROOT = iphoneos;
|
|
||||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
|
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
|
||||||
};
|
|
||||||
name = Debug;
|
|
||||||
};
|
|
||||||
1DBC40862DA4EE010093FCB0 /* Release */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
buildSettings = {
|
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
|
||||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
|
||||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
|
||||||
CLANG_ENABLE_MODULES = YES;
|
|
||||||
CLANG_ENABLE_OBJC_ARC = YES;
|
|
||||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
|
||||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
|
||||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
|
||||||
CLANG_WARN_COMMA = YES;
|
|
||||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
|
||||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
|
||||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
|
||||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
|
||||||
CLANG_WARN_EMPTY_BODY = YES;
|
|
||||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
|
||||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
|
||||||
CLANG_WARN_INT_CONVERSION = YES;
|
|
||||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
|
||||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
|
||||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
|
||||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
|
||||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
|
||||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
|
||||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
|
||||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
|
||||||
COPY_PHASE_STRIP = NO;
|
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
|
||||||
ENABLE_NS_ASSERTIONS = NO;
|
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
|
||||||
GCC_NO_COMMON_BLOCKS = YES;
|
|
||||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
|
||||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
|
||||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 18.2;
|
|
||||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
|
||||||
MTL_FAST_MATH = YES;
|
|
||||||
SDKROOT = iphoneos;
|
|
||||||
SWIFT_COMPILATION_MODE = wholemodule;
|
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
|
||||||
VALIDATE_PRODUCT = YES;
|
|
||||||
};
|
|
||||||
name = Release;
|
|
||||||
};
|
|
||||||
/* End XCBuildConfiguration section */
|
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
|
||||||
1DBC40542DA4EDFC0093FCB0 /* Build configuration list for PBXProject "MoviaBox" */ = {
|
|
||||||
isa = XCConfigurationList;
|
|
||||||
buildConfigurations = (
|
|
||||||
1DBC40852DA4EE010093FCB0 /* Debug */,
|
|
||||||
1DBC40862DA4EE010093FCB0 /* Release */,
|
|
||||||
);
|
|
||||||
defaultConfigurationIsVisible = 0;
|
|
||||||
defaultConfigurationName = Release;
|
|
||||||
};
|
|
||||||
1DBC40822DA4EE010093FCB0 /* Build configuration list for PBXNativeTarget "MoviaBox" */ = {
|
|
||||||
isa = XCConfigurationList;
|
|
||||||
buildConfigurations = (
|
|
||||||
1DBC40832DA4EE010093FCB0 /* Debug */,
|
|
||||||
1DBC40842DA4EE010093FCB0 /* Release */,
|
|
||||||
);
|
|
||||||
defaultConfigurationIsVisible = 0;
|
|
||||||
defaultConfigurationName = Release;
|
|
||||||
};
|
|
||||||
/* End XCConfigurationList section */
|
|
||||||
};
|
|
||||||
rootObject = 1DBC40512DA4EDFC0093FCB0 /* Project object */;
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
//
|
|
||||||
// AppDelegate+OpenApp.swift
|
|
||||||
// MoviaBox
|
|
||||||
//
|
|
||||||
// Created by 佳尔 on 2025/4/25.
|
|
||||||
//
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
extension SceneDelegate {
|
|
||||||
|
|
||||||
///URL打开APP
|
|
||||||
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
///UniversalLink 打开app
|
|
||||||
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
|
|
||||||
guard let webpageURL = userActivity.webpageURL else { return }
|
|
||||||
|
|
||||||
guard let query = webpageURL.query else { return }
|
|
||||||
|
|
||||||
spLog(message: query)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
//
|
|
||||||
// SceneDelegate.swift
|
|
||||||
// MoviaBox
|
|
||||||
//
|
|
||||||
// Created by 曾觉新 on 2025/4/8.
|
|
||||||
//
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
|
||||||
|
|
||||||
var window: UIWindow?
|
|
||||||
|
|
||||||
|
|
||||||
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
|
|
||||||
guard let windowScene = (scene as? UIWindowScene) else { return }
|
|
||||||
let tabBarController = SPTabBarController()
|
|
||||||
SPAPPTool.mainTabBarController = tabBarController
|
|
||||||
|
|
||||||
window = UIWindow(windowScene: windowScene)
|
|
||||||
window?.rootViewController = tabBarController
|
|
||||||
window?.makeKeyAndVisible()
|
|
||||||
}
|
|
||||||
|
|
||||||
func sceneDidDisconnect(_ scene: UIScene) {
|
|
||||||
// Called as the scene is being released by the system.
|
|
||||||
// This occurs shortly after the scene enters the background, or when its session is discarded.
|
|
||||||
// Release any resources associated with this scene that can be re-created the next time the scene connects.
|
|
||||||
// The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
|
|
||||||
}
|
|
||||||
|
|
||||||
func sceneDidBecomeActive(_ scene: UIScene) {
|
|
||||||
// Called when the scene has moved from an inactive state to an active state.
|
|
||||||
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
|
|
||||||
}
|
|
||||||
|
|
||||||
func sceneWillResignActive(_ scene: UIScene) {
|
|
||||||
// Called when the scene will move from an active state to an inactive state.
|
|
||||||
// This may occur due to temporary interruptions (ex. an incoming phone call).
|
|
||||||
}
|
|
||||||
|
|
||||||
func sceneWillEnterForeground(_ scene: UIScene) {
|
|
||||||
// Called as the scene transitions from the background to the foreground.
|
|
||||||
// Use this method to undo the changes made on entering the background.
|
|
||||||
}
|
|
||||||
|
|
||||||
func sceneDidEnterBackground(_ scene: UIScene) {
|
|
||||||
// Called as the scene transitions from the foreground to the background.
|
|
||||||
// Use this method to save data, release shared resources, and store enough scene-specific state information
|
|
||||||
// to restore the scene back to its current state.
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
|||||||
//
|
|
||||||
// SPUserDefaultsKey.swift
|
|
||||||
// MoviaBox
|
|
||||||
//
|
|
||||||
// Created by 曾觉新 on 2025/4/9.
|
|
||||||
//
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
///登录的用户信息
|
|
||||||
let kSPLoginTokenDefaultsKey = "kSPLoginTokenDefaultsKey"
|
|
||||||
|
|
||||||
///首页搜索记录
|
|
||||||
let kSPHomeSearchHistoryDefaultsKey = "kSPHomeSearchHistoryDefaultsKey"
|
|
@ -1,228 +0,0 @@
|
|||||||
//
|
|
||||||
// UIColor+SPAdd.swift
|
|
||||||
// MoviaBox
|
|
||||||
//
|
|
||||||
// Created by 曾觉新 on 2025/4/8.
|
|
||||||
//
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
extension UIColor {
|
|
||||||
|
|
||||||
static func color(hex: UInt32, alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return UIColor(rgb: hex, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func backgroundColor() -> UIColor {
|
|
||||||
return color121317()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static func themeColor() -> UIColor {
|
|
||||||
return .color121317()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static func placeholderColor() -> UIColor {
|
|
||||||
return .colorFFFFFF(alpha: 0.6)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension UIColor {
|
|
||||||
static func colorFFFFFF(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0xFFFFFF, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func color000000(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0x000000, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func colorFF0089(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0xFF0089, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func color7F7F80(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0x7F7F80, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func colorD2D2D2(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0xD2D2D2, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func colorBF6BFF(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0xBF6BFF, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func color121418(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0x121418, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func colorF564B6(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0xF564B6, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func colorF56490(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0xF56490, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func color9D9D9D(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0x9D9D9D, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func color545454(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0x545454, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func colorD568D2(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0xD568D2, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func color8A899F(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0x8A899F, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func color888888(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0x888888, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func color201A1A(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0x201A1A, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func color828284(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0x828284, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func color121317(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0x121317, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func color290D0F(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0x290D0F, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func color230E11(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0x230E11, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func color181115(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0x181115, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func colorFF5100(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0xFF5100, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func colorAFAFAF(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0xAFAFAF, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func colorA8A5AA(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0xA8A5AA, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func colorD9D9D9(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0xD9D9D9, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func colorEAF7FF(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0xEAF7FF, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func colorFF4B5A(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0xFF4B5A, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func color1E1F2C(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0x1E1F2C, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func colorE7F5FF(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0xE7F5FF, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func colorAFB8BF(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0xAFB8BF, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func colorFF0000(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0xFF0000, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func color1C1A1C(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0x1C1A1C, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func color621C14(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0x621C14, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func color5A5C67(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0x5A5C67, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func color3D4556(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0x3D4556, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func color1C1C1E(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0x1C1C1E, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func colorEC3324(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0xEC3324, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func colorCCCCCC(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0xCCCCCC, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func color6D7A8F(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0x6D7A8F, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func color8B6C6C(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0x8B6C6C, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func color58484B(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0x58484B, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func colorE6334B(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0xE6334B, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func color0866FF(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0x0866FF, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func color333333(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0x333333, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func colorB0B0B3(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0xB0B0B3, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func colorBBB9B3(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0xBBB9B3, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func colorFFD791(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0xFFD791, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func color262014(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0x262014, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func colorA69B89(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0xA69B89, alpha: alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func colorFFD28F(alpha: CGFloat = 1) -> UIColor {
|
|
||||||
return color(hex: 0xFFD28F, alpha: alpha)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
|||||||
//
|
|
||||||
// SPUserAPI.swift
|
|
||||||
// MoviaBox
|
|
||||||
//
|
|
||||||
// Created by 曾觉新 on 2025/4/18.
|
|
||||||
//
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
class SPUserAPI: NSObject {
|
|
||||||
|
|
||||||
|
|
||||||
static func requestUserInfo(completer: ((_ userInfo: SPUserInfo?) -> Void)?) {
|
|
||||||
|
|
||||||
var param = SPNetworkParameters(path: "/customer/info")
|
|
||||||
param.method = .get
|
|
||||||
|
|
||||||
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<SPUserInfo>) in
|
|
||||||
completer?(response.data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
//
|
|
||||||
// SPCampaignWebViewController.swift
|
|
||||||
// MoviaBox
|
|
||||||
//
|
|
||||||
// Created by 佳尔 on 2025/4/25.
|
|
||||||
//
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
class SPCampaignWebViewController: SPWebViewController {
|
|
||||||
|
|
||||||
var id: String?
|
|
||||||
|
|
||||||
override func viewDidLoad() {
|
|
||||||
super.viewDidLoad()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override func webViewDidFinishLoad(_ webView: SPWebView) {
|
|
||||||
super.webViewDidFinishLoad(webView)
|
|
||||||
receiveDataFromNative()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
extension SPCampaignWebViewController {
|
|
||||||
///设置登录信息
|
|
||||||
func receiveDataFromNative() {
|
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in
|
|
||||||
guard let self = self else { return }
|
|
||||||
var dic = [
|
|
||||||
"token" : SPLoginManager.manager.token?.token ?? "",
|
|
||||||
"time_zone" : String.timeZone(),
|
|
||||||
"lang" : SPLocalizedManager.shared.currentLocalizedKey,
|
|
||||||
"type" : "ios",
|
|
||||||
"theme" : "theme_1",
|
|
||||||
]
|
|
||||||
if let id = id {
|
|
||||||
dic["id"] = id
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if let json = dic.toJsonString() {
|
|
||||||
let js = "receiveDataFromNative(\(json))"
|
|
||||||
self.webView.evaluateJavaScript(js) { _, error in
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
|||||||
//
|
|
||||||
// SPHomeChildController.swift
|
|
||||||
// MoviaBox
|
|
||||||
//
|
|
||||||
// Created by 曾觉新 on 2025/4/14.
|
|
||||||
//
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
class SPHomeChildController: SPViewController {
|
|
||||||
|
|
||||||
var topMargins: CGFloat = 10
|
|
||||||
|
|
||||||
override func viewDidLoad() {
|
|
||||||
super.viewDidLoad()
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// override func setBgImageView() { }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
//
|
|
||||||
// SPHomeExploreCell.swift
|
|
||||||
// MoviaBox
|
|
||||||
//
|
|
||||||
// Created by Overseas on 2025/4/22.
|
|
||||||
//
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
class SPHomeExploreCell: SPCollectionViewCell {
|
|
||||||
|
|
||||||
var model: SPShortModel? {
|
|
||||||
didSet {
|
|
||||||
coverImageView.sp_setImage(url: model?.image_url)
|
|
||||||
titleLabel.text = model?.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//MARK: UI属性
|
|
||||||
private lazy var coverImageView: SPImageView = {
|
|
||||||
let imageView = SPImageView()
|
|
||||||
imageView.layer.cornerRadius = 4
|
|
||||||
imageView.layer.masksToBounds = true
|
|
||||||
return imageView
|
|
||||||
}()
|
|
||||||
|
|
||||||
private lazy var titleLabel: UILabel = {
|
|
||||||
let label = UILabel()
|
|
||||||
label.font = .fontRegular(ofSize: 12)
|
|
||||||
label.textColor = .colorFFFFFF()
|
|
||||||
label.numberOfLines = 2
|
|
||||||
return label
|
|
||||||
}()
|
|
||||||
|
|
||||||
override init(frame: CGRect) {
|
|
||||||
super.init(frame: frame)
|
|
||||||
|
|
||||||
_setupUI()
|
|
||||||
}
|
|
||||||
|
|
||||||
@MainActor required init?(coder: NSCoder) {
|
|
||||||
fatalError("init(coder:) has not been implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
extension SPHomeExploreCell {
|
|
||||||
|
|
||||||
private func _setupUI() {
|
|
||||||
contentView.addSubview(coverImageView)
|
|
||||||
contentView.addSubview(titleLabel)
|
|
||||||
|
|
||||||
coverImageView.snp.makeConstraints { make in
|
|
||||||
make.left.right.top.equalToSuperview()
|
|
||||||
make.bottom.equalToSuperview().offset(-36)
|
|
||||||
}
|
|
||||||
|
|
||||||
titleLabel.snp.makeConstraints { make in
|
|
||||||
make.left.equalToSuperview()
|
|
||||||
make.right.lessThanOrEqualToSuperview()
|
|
||||||
make.top.equalTo(coverImageView.snp.bottom).offset(8)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,91 +0,0 @@
|
|||||||
//
|
|
||||||
// SPHomeTrendingCell.swift
|
|
||||||
// MoviaBox
|
|
||||||
//
|
|
||||||
// Created by 曾觉新 on 2025/4/14.
|
|
||||||
//
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
class SPHomeTrendingCell: SPCollectionViewCell {
|
|
||||||
|
|
||||||
var model: SPShortModel? {
|
|
||||||
didSet {
|
|
||||||
coverImageView.sp_setImage(url: model?.image_url)
|
|
||||||
titleLabel.text = model?.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private lazy var coverImageView: SPImageView = {
|
|
||||||
let imageView = SPImageView()
|
|
||||||
imageView.layer.cornerRadius = 10
|
|
||||||
imageView.layer.masksToBounds = true
|
|
||||||
return imageView
|
|
||||||
}()
|
|
||||||
|
|
||||||
private lazy var titleLabel: UILabel = {
|
|
||||||
let label = UILabel()
|
|
||||||
label.font = .fontLight(ofSize: 13)
|
|
||||||
label.textColor = .colorFFFFFF(alpha: 0.9)
|
|
||||||
label.numberOfLines = 2
|
|
||||||
return label
|
|
||||||
}()
|
|
||||||
|
|
||||||
private lazy var hotBgView: SPGradientView = {
|
|
||||||
let view = SPGradientView()
|
|
||||||
view.colors = [UIColor.colorF56490().cgColor, UIColor.colorBF6BFF().cgColor]
|
|
||||||
view.startPoint = .init(x: 0.5, y: 0)
|
|
||||||
view.endPoint = .init(x: 0.5, y: 1)
|
|
||||||
view.locations = [0, 1]
|
|
||||||
view.addRadius(topLeft: 0, topRight: 0, bottomLeft: 0, bottomRight: 6)
|
|
||||||
return view
|
|
||||||
}()
|
|
||||||
|
|
||||||
private lazy var hotIconImageView: UIImageView = {
|
|
||||||
let imageView = UIImageView(image: UIImage(named: "hot_icon_01"))
|
|
||||||
return imageView
|
|
||||||
}()
|
|
||||||
|
|
||||||
override init(frame: CGRect) {
|
|
||||||
super.init(frame: frame)
|
|
||||||
|
|
||||||
_setupUI()
|
|
||||||
}
|
|
||||||
|
|
||||||
@MainActor required init?(coder: NSCoder) {
|
|
||||||
fatalError("init(coder:) has not been implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
extension SPHomeTrendingCell {
|
|
||||||
|
|
||||||
private func _setupUI() {
|
|
||||||
contentView.addSubview(coverImageView)
|
|
||||||
contentView.addSubview(titleLabel)
|
|
||||||
coverImageView.addSubview(hotBgView)
|
|
||||||
hotBgView.addSubview(hotIconImageView)
|
|
||||||
|
|
||||||
coverImageView.snp.makeConstraints { make in
|
|
||||||
make.left.right.top.equalToSuperview()
|
|
||||||
make.bottom.equalToSuperview().offset(-38)
|
|
||||||
}
|
|
||||||
|
|
||||||
titleLabel.snp.makeConstraints { make in
|
|
||||||
make.left.equalToSuperview()
|
|
||||||
make.right.lessThanOrEqualToSuperview()
|
|
||||||
make.top.equalTo(coverImageView.snp.bottom).offset(5)
|
|
||||||
}
|
|
||||||
|
|
||||||
hotBgView.snp.makeConstraints { make in
|
|
||||||
make.left.top.equalToSuperview()
|
|
||||||
make.width.equalTo(22)
|
|
||||||
make.height.equalTo(16)
|
|
||||||
}
|
|
||||||
|
|
||||||
hotIconImageView.snp.makeConstraints { make in
|
|
||||||
make.center.equalToSuperview()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
//
|
|
||||||
// SPHomeViewModel.swift
|
|
||||||
// MoviaBox
|
|
||||||
//
|
|
||||||
// Created by Overseas on 2025/4/22.
|
|
||||||
//
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
class SPHomeViewModel: NSObject {
|
|
||||||
|
|
||||||
var moduleModel: SPHomeModuleModel?
|
|
||||||
|
|
||||||
///历史记录
|
|
||||||
var playHistoryArr: [SPShortModel]?
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,203 +0,0 @@
|
|||||||
//
|
|
||||||
// SPPlayerDetailViewController.swift
|
|
||||||
// MoviaBox
|
|
||||||
//
|
|
||||||
// Created by 曾觉新 on 2025/4/10.
|
|
||||||
//
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
class SPPlayerDetailViewController: SPPlayerListViewController {
|
|
||||||
|
|
||||||
override var PlayerCellClass: SPPlayerListCell.Type {
|
|
||||||
return SPPlayerDetailCell.self
|
|
||||||
}
|
|
||||||
|
|
||||||
override var contentSize: CGSize {
|
|
||||||
return CGSize(width: kSPScreenWidth, height: kSPScreenHeight - kSPTabbarSafeBottomMargin - 35)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var videoId: String?
|
|
||||||
var shortPlayId: String?
|
|
||||||
var playHistoryModel: SPShortModel?
|
|
||||||
|
|
||||||
private var detailModel: SPVideoDetailModel?
|
|
||||||
|
|
||||||
//MARK: UI属性
|
|
||||||
///选集视图
|
|
||||||
private weak var episodeView: SPEpisodeView?
|
|
||||||
|
|
||||||
private lazy var backButton: UIButton = {
|
|
||||||
let button = UIButton(type: .custom)
|
|
||||||
button.setImage(UIImage(named: "arrow_left_icon_01"), for: .normal)
|
|
||||||
button.addTarget(self, action: #selector(handleBack), for: .touchUpInside)
|
|
||||||
return button
|
|
||||||
}()
|
|
||||||
|
|
||||||
private lazy var titleLabel: UILabel = {
|
|
||||||
let label = UILabel()
|
|
||||||
label.font = .fontBold(ofSize: 18)
|
|
||||||
label.textColor = .colorFFFFFF()
|
|
||||||
return label
|
|
||||||
}()
|
|
||||||
|
|
||||||
private lazy var episodeLabel: UILabel = {
|
|
||||||
let label = UILabel()
|
|
||||||
label.font = .fontMedium(ofSize: 18)
|
|
||||||
label.textColor = .colorFFFFFF(alpha: 0.4)
|
|
||||||
return label
|
|
||||||
}()
|
|
||||||
|
|
||||||
private lazy var bottomView: UIView = {
|
|
||||||
let view = UIView()
|
|
||||||
view.backgroundColor = .color1C1C1E()
|
|
||||||
return view
|
|
||||||
}()
|
|
||||||
|
|
||||||
override func viewDidLoad() {
|
|
||||||
super.viewDidLoad()
|
|
||||||
self.autoNextEpisode = true
|
|
||||||
self.dataSource = self
|
|
||||||
self.delegate = self
|
|
||||||
|
|
||||||
requestDetailData()
|
|
||||||
|
|
||||||
_addAction()
|
|
||||||
|
|
||||||
_setupUI()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override func viewWillAppear(_ animated: Bool) {
|
|
||||||
super.viewWillAppear(animated)
|
|
||||||
self.navigationController?.setNavigationBarHidden(true, animated: true)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override func play() {
|
|
||||||
super.play()
|
|
||||||
if let _ = self.detailModel,
|
|
||||||
let videoInfo = self.viewModel.currentPlayer?.videoInfo
|
|
||||||
{
|
|
||||||
SPVideoAPI.requestRequestVideoPlayHistory(videoId: videoInfo.short_play_video_id ?? "", shortPlayId: videoInfo.short_play_id ?? "")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
extension SPPlayerDetailViewController {
|
|
||||||
|
|
||||||
private func _setupUI() {
|
|
||||||
view.addSubview(backButton)
|
|
||||||
view.addSubview(titleLabel)
|
|
||||||
view.addSubview(episodeLabel)
|
|
||||||
view.addSubview(bottomView)
|
|
||||||
|
|
||||||
backButton.snp.makeConstraints { make in
|
|
||||||
make.left.equalToSuperview().offset(5)
|
|
||||||
make.top.equalToSuperview().offset(5 + kSPStatusbarHeight)
|
|
||||||
make.width.height.equalTo(37)
|
|
||||||
}
|
|
||||||
|
|
||||||
titleLabel.snp.makeConstraints { make in
|
|
||||||
make.left.equalTo(backButton.snp.right)
|
|
||||||
make.centerY.equalTo(backButton)
|
|
||||||
// make.right.equalToSuperview().offset(-15)
|
|
||||||
make.width.lessThanOrEqualTo(kSPScreenWidth - 130)
|
|
||||||
}
|
|
||||||
|
|
||||||
episodeLabel.snp.makeConstraints { make in
|
|
||||||
make.centerY.equalTo(titleLabel)
|
|
||||||
make.left.equalTo(titleLabel.snp.right).offset(16)
|
|
||||||
}
|
|
||||||
|
|
||||||
bottomView.snp.makeConstraints { make in
|
|
||||||
make.left.right.bottom.equalToSuperview()
|
|
||||||
make.top.equalTo(self.collectionView.snp.bottom)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func _addAction() {
|
|
||||||
self.viewModel.handleEpisode = { [weak self] in
|
|
||||||
self?.onEpisode()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension SPPlayerDetailViewController {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private func onEpisode() {
|
|
||||||
let view = SPEpisodeView()
|
|
||||||
view.dataArr = detailModel?.episodeList ?? []
|
|
||||||
view.shortModel = detailModel?.shortPlayInfo
|
|
||||||
view.currentIndex = self.currentIndexPath.row
|
|
||||||
view.didSelectedIndex = { [weak self] (index) in
|
|
||||||
self?.scrollToItem(indexPath: IndexPath(row: index, section: 0), animated: false)
|
|
||||||
}
|
|
||||||
view.present(in: nil)
|
|
||||||
self.episodeView = view
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//MARK: -------------- SPPlayerListViewControllerDataSource --------------
|
|
||||||
extension SPPlayerDetailViewController: SPPlayerListViewControllerDataSource, SPPlayerListViewControllerDelegate {
|
|
||||||
func sp_playerListViewController(_ viewController: SPPlayerListViewController, _ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath, oldCell: UICollectionViewCell) -> UICollectionViewCell {
|
|
||||||
if let cell = oldCell as? SPPlayerDetailCell {
|
|
||||||
cell.shortModel = detailModel?.shortPlayInfo
|
|
||||||
cell.videoInfo = detailModel?.episodeList?[indexPath.row]
|
|
||||||
cell.isLoop = false
|
|
||||||
}
|
|
||||||
return oldCell
|
|
||||||
}
|
|
||||||
|
|
||||||
func sp_playerListViewController(_ viewController: SPPlayerListViewController, _ collectionView: UICollectionView, numberOfItemsInSection section: Int, oldNumber: Int) -> Int {
|
|
||||||
return detailModel?.episodeList?.count ?? 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func sp_playerListViewController(_ viewController: SPPlayerListViewController, didChangeIndexPathForVisible indexPath: IndexPath) {
|
|
||||||
self.episodeView?.currentIndex = indexPath.row
|
|
||||||
let videoInfo = detailModel?.episodeList?[indexPath.row]
|
|
||||||
|
|
||||||
// titleLabel.text = String(format: "kPlayerDetailTitleString".localized, "\(videoInfo?.episode ?? "0")", self.detailModel?.shortPlayInfo?.name ?? "")
|
|
||||||
titleLabel.text = detailModel?.shortPlayInfo?.name
|
|
||||||
episodeLabel.text = "\(videoInfo?.episode ?? "0")/\(detailModel?.shortPlayInfo?.episode_total ?? 0)"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extension SPPlayerDetailViewController {
|
|
||||||
|
|
||||||
private func requestDetailData() {
|
|
||||||
guard let shortPlayId = self.shortPlayId else { return }
|
|
||||||
|
|
||||||
SPVideoAPI.requestVideoDetail(videoId: videoId, shortPlayId: shortPlayId) { [weak self] model in
|
|
||||||
guard let self = self else { return }
|
|
||||||
if let model = model {
|
|
||||||
self.detailModel = model
|
|
||||||
self.reloadData { [weak self] in
|
|
||||||
guard let self = self else { return }
|
|
||||||
|
|
||||||
if let playHistoryModel = self.playHistoryModel {
|
|
||||||
var row: Int?
|
|
||||||
self.detailModel?.episodeList?.enumerated().forEach({
|
|
||||||
if $1.episode == playHistoryModel.current_episode {
|
|
||||||
row = $0
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if let row = row {
|
|
||||||
self.scrollToItem(indexPath: IndexPath(row: row, section: 0), animated: false)
|
|
||||||
}
|
|
||||||
self.playHistoryModel = nil
|
|
||||||
} else {
|
|
||||||
self.play()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
//
|
|
||||||
// SPPlayerDetailCell.swift
|
|
||||||
// MoviaBox
|
|
||||||
//
|
|
||||||
// Created by 曾觉新 on 2025/4/10.
|
|
||||||
//
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
class SPPlayerDetailCell: SPPlayerListCell {
|
|
||||||
|
|
||||||
override var PlayerControlViewClass: SPPlayerControlView.Type {
|
|
||||||
return SPPlayerDetailControlView.self
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override init(frame: CGRect) {
|
|
||||||
super.init(frame: frame)
|
|
||||||
}
|
|
||||||
|
|
||||||
@MainActor required init?(coder: NSCoder) {
|
|
||||||
fatalError("init(coder:) has not been implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,91 +0,0 @@
|
|||||||
//
|
|
||||||
// SPEmptyState.swift
|
|
||||||
// MoviaBox
|
|
||||||
//
|
|
||||||
// Created by Overseas on 2025/4/19.
|
|
||||||
//
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
import EmptyStateKit
|
|
||||||
|
|
||||||
struct SPEmptyParameters {
|
|
||||||
// var title: String = "暂无内容"
|
|
||||||
// var titleFont: UIFont = UIFont.text_md
|
|
||||||
// var titleColor: UIColor = UIColor.system_text_secondary_300
|
|
||||||
var image: UIImage? = UIImage(named: "empty_image_01")
|
|
||||||
// var buttonTitle: String?
|
|
||||||
}
|
|
||||||
|
|
||||||
enum SPEmptyState {
|
|
||||||
case normail(parameters: SPEmptyParameters)
|
|
||||||
}
|
|
||||||
|
|
||||||
extension SPEmptyState: CustomState {
|
|
||||||
|
|
||||||
var image: UIImage? {
|
|
||||||
switch self {
|
|
||||||
case .normail(let parameters):
|
|
||||||
return parameters.image
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var title: String? {
|
|
||||||
switch self {
|
|
||||||
case .normail(let parameters):
|
|
||||||
return nil
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// var titleButton: String? {
|
|
||||||
// switch self {
|
|
||||||
// case .normail(let parameters):
|
|
||||||
// return parameters.buttonTitle
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
extension SPEmptyState {
|
|
||||||
var format: EmptyStateFormat {
|
|
||||||
|
|
||||||
var format = EmptyStateFormat()
|
|
||||||
format.backgroundColor = .clear
|
|
||||||
format.imageSize = self.image?.size ?? .zero
|
|
||||||
// format.verticalMargin = -10
|
|
||||||
//
|
|
||||||
// format.buttonWidth = 107
|
|
||||||
// format.buttonTopMargin = 10
|
|
||||||
// format.buttonColor = .system_fill_primary_100
|
|
||||||
// format.buttonAttributes = [
|
|
||||||
// .font: UIFont.text_md,
|
|
||||||
// .foregroundColor: UIColor.system_text_secondary_500
|
|
||||||
// ]
|
|
||||||
//
|
|
||||||
// switch self {
|
|
||||||
// case .normail(let p):
|
|
||||||
// format.titleAttributes = [
|
|
||||||
// .font: p.titleFont,
|
|
||||||
// .foregroundColor: p.titleColor
|
|
||||||
// ]
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// case .login(let p):
|
|
||||||
// format.titleAttributes = [
|
|
||||||
// .font: p.titleFont,
|
|
||||||
// .foregroundColor: p.titleColor
|
|
||||||
// ]
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return format
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,61 +0,0 @@
|
|||||||
//
|
|
||||||
// SPLoginManager.swift
|
|
||||||
// MoviaBox
|
|
||||||
//
|
|
||||||
// Created by 曾觉新 on 2025/4/8.
|
|
||||||
//
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
class SPLoginManager: NSObject {
|
|
||||||
|
|
||||||
enum LoginType: Int {
|
|
||||||
case apple
|
|
||||||
case faceBook
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static let manager = SPLoginManager()
|
|
||||||
|
|
||||||
private(set) var token: SPTokenModel?
|
|
||||||
|
|
||||||
///是否正在刷新token
|
|
||||||
private(set) var isRefreshingToken = false
|
|
||||||
|
|
||||||
override init() {
|
|
||||||
super.init()
|
|
||||||
token = UserDefaults.jx_object(forKey: kSPLoginTokenDefaultsKey, class: SPTokenModel.self) as? SPTokenModel
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func setLoginToken(token: SPTokenModel?) {
|
|
||||||
self.token = token
|
|
||||||
UserDefaults.jx_setObject(token, forKey: kSPLoginTokenDefaultsKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
///第三方登录
|
|
||||||
func thirdLogin(type: LoginType, presentingViewController: UIViewController) {
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
extension SPLoginManager {
|
|
||||||
///游客登录
|
|
||||||
func requestVisitorLogin(completer: (() -> Void)?) {
|
|
||||||
if isRefreshingToken {
|
|
||||||
completer?()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
isRefreshingToken = true
|
|
||||||
|
|
||||||
SPNetwork.requestToken { [weak self] token in
|
|
||||||
guard let self = self else { return }
|
|
||||||
self.isRefreshingToken = false
|
|
||||||
completer?()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
//
|
|
||||||
// SPThirdSignModel.swift
|
|
||||||
// MoviaBox
|
|
||||||
//
|
|
||||||
// Created by 佳尔 on 2025/4/25.
|
|
||||||
//
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
class SPThirdSignModel: NSObject {
|
|
||||||
|
|
||||||
var token: String?
|
|
||||||
|
|
||||||
var userID: String?
|
|
||||||
var email: String?
|
|
||||||
var name: String?
|
|
||||||
//姓
|
|
||||||
var familyName: String?
|
|
||||||
//名
|
|
||||||
var givenName: String?
|
|
||||||
|
|
||||||
var avatar: String?
|
|
||||||
|
|
||||||
}
|
|
@ -1,61 +0,0 @@
|
|||||||
//
|
|
||||||
// SPLocalizedManager.swift
|
|
||||||
// MoviaBox
|
|
||||||
//
|
|
||||||
// Created by 曾觉新 on 2025/4/8.
|
|
||||||
//
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
class SPLocalizedManager: NSObject {
|
|
||||||
static let shared = SPLocalizedManager()
|
|
||||||
|
|
||||||
private let userDefaultsKey = "AppLocalized"
|
|
||||||
|
|
||||||
// 获取当前语言代码(如果用户未手动设置,则返回系统语言)
|
|
||||||
var currentLocalizedKey: String {
|
|
||||||
get {
|
|
||||||
// return UserDefaults.standard.string(forKey: userDefaultsKey) ?? Locale.preferredLanguages.first ?? "en"
|
|
||||||
return "en"
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
UserDefaults.standard.set(newValue, forKey: userDefaultsKey)
|
|
||||||
UserDefaults.standard.synchronize()
|
|
||||||
NotificationCenter.default.post(name: SPLocalizedManager.localizedDidChange, object: nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 判断是否跟随系统
|
|
||||||
var isFollowingSystem: Bool {
|
|
||||||
return UserDefaults.standard.string(forKey: userDefaultsKey) == nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 还原为系统默认语言
|
|
||||||
func resetToSystemLanguage() {
|
|
||||||
UserDefaults.standard.removeObject(forKey: userDefaultsKey)
|
|
||||||
UserDefaults.standard.synchronize()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取本地化字符串
|
|
||||||
func localizedString(forKey key: String, tableName: String? = nil) -> String {
|
|
||||||
if let selectedLanguage = UserDefaults.standard.string(forKey: userDefaultsKey),
|
|
||||||
let bundlePath = Bundle.main.path(forResource: selectedLanguage, ofType: "lproj"),
|
|
||||||
let bundle = Bundle(path: bundlePath) {
|
|
||||||
return bundle.localizedString(forKey: key, value: nil, table: tableName)
|
|
||||||
} else {
|
|
||||||
return NSLocalizedString(key, tableName: tableName, bundle: .main, value: "", comment: "")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension SPLocalizedManager {
|
|
||||||
|
|
||||||
static let localizedDidChange = Notification.Name(rawValue: "SPLocalizedManager.localizedDidChange")
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
extension String {
|
|
||||||
var localized: String {
|
|
||||||
return SPLocalizedManager.shared.localizedString(forKey: self)
|
|
||||||
}
|
|
||||||
}
|
|
Before Width: | Height: | Size: 140 KiB |
Before Width: | Height: | Size: 1.0 MiB |
Before Width: | Height: | Size: 2.3 MiB |
Before Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 533 B |
Before Width: | Height: | Size: 931 B |
Before Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 31 KiB |
@ -1,27 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>ITSAppUsesNonExemptEncryption</key>
|
|
||||||
<false/>
|
|
||||||
<key>UIApplicationSceneManifest</key>
|
|
||||||
<dict>
|
|
||||||
<key>UIApplicationSupportsMultipleScenes</key>
|
|
||||||
<false/>
|
|
||||||
<key>UISceneConfigurations</key>
|
|
||||||
<dict>
|
|
||||||
<key>UIWindowSceneSessionRoleApplication</key>
|
|
||||||
<array>
|
|
||||||
<dict>
|
|
||||||
<key>UISceneConfigurationName</key>
|
|
||||||
<string>Default Configuration</string>
|
|
||||||
<key>UISceneDelegateClassName</key>
|
|
||||||
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
|
|
||||||
</dict>
|
|
||||||
</array>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
|
||||||
<false/>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
@ -1,57 +0,0 @@
|
|||||||
/*
|
|
||||||
Localizable.strings
|
|
||||||
MoviaBox
|
|
||||||
|
|
||||||
Created by 曾觉新 on 2025/4/8.
|
|
||||||
英语
|
|
||||||
*/
|
|
||||||
|
|
||||||
"Home" = "Home";
|
|
||||||
"For You" = "For You";
|
|
||||||
"Error" = "Error";
|
|
||||||
"Profile" = "Profile";
|
|
||||||
"Hot Picks" = "Hot Picks";
|
|
||||||
"Top 10" = "Top 10";
|
|
||||||
"Fresh Drops" = "Fresh Drops";
|
|
||||||
"Free" = "Free";
|
|
||||||
"Trending Now" = "Trending Now";
|
|
||||||
"Editor's Hotlist" = "Editor's Hotlist";
|
|
||||||
"Shorts for You" = "Shorts for You";
|
|
||||||
"Episodes" = "Episodes";
|
|
||||||
"Save" = "Save";
|
|
||||||
"Added" = "Added";
|
|
||||||
"FeedBack" = "FeedBack";
|
|
||||||
"Language" = "Language";
|
|
||||||
"Privacy Policy" = "Privacy Policy";
|
|
||||||
"User Agreement" = "User Agreement";
|
|
||||||
"About Us" = "About Us";
|
|
||||||
"My list" = "My list";
|
|
||||||
"Watch list" = "Watch list";
|
|
||||||
"Recently viewed" = "Recently viewed";
|
|
||||||
"Cancel" = "Cancel";
|
|
||||||
"Select All" = "Select All";
|
|
||||||
"Delet (%@)" = "Delet (%@)";
|
|
||||||
"Love Me Like You Do It" = "Love Me Like You Do It";
|
|
||||||
"Explore For You" = "Explore For You";
|
|
||||||
"Continue watching" = "Continue watching";
|
|
||||||
"More for you!" = "More for you!";
|
|
||||||
"More" = "More";
|
|
||||||
"Historical search" = "Historical search";
|
|
||||||
"Top Search" = "Top Search";
|
|
||||||
"EP%@" = "EP%@";
|
|
||||||
"Full Episodes" = "Full Episodes";
|
|
||||||
"All" = "All";
|
|
||||||
"Shorts" = "Shorts";
|
|
||||||
"EP.%@" = "EP.%@";
|
|
||||||
"Copy" = "Copy";
|
|
||||||
"Succeed" = "Succeed";
|
|
||||||
"Watch History" = "Watch History";
|
|
||||||
"Child Personal Information Protection Rules" = "Child Personal Information Protection Rules";
|
|
||||||
"Youth Civilization Convention" = "Youth Civilization Convention";
|
|
||||||
"List of Third-Party Sharing of Personal Information" = "List of Third-Party Sharing of Personal Information";
|
|
||||||
"Explicit List of Personal Information Collection" = "Explicit List of Personal Information Collection";
|
|
||||||
|
|
||||||
|
|
||||||
"kLoginAgreementText" = "By continuing, you agree to the User Agreement and Privacy Policy";
|
|
||||||
|
|
||||||
|
|
10
Podfile
@ -1,6 +1,6 @@
|
|||||||
# Uncomment the next line to define a global platform for your project
|
# Uncomment the next line to define a global platform for your project
|
||||||
source 'https://github.com/CocoaPods/Specs.git'
|
source 'https://github.com/CocoaPods/Specs.git'
|
||||||
platform :ios, '15.6'
|
platform :ios, '15.0'
|
||||||
|
|
||||||
post_install do |installer|
|
post_install do |installer|
|
||||||
installer.pods_project.targets.each do |target|
|
installer.pods_project.targets.each do |target|
|
||||||
@ -12,7 +12,7 @@ post_install do |installer|
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
target 'MoviaBox' do
|
target 'ThimraTV' do
|
||||||
# Comment the next line if you don't want to use dynamic frameworks
|
# Comment the next line if you don't want to use dynamic frameworks
|
||||||
use_frameworks!
|
use_frameworks!
|
||||||
|
|
||||||
@ -26,9 +26,13 @@ target 'MoviaBox' do
|
|||||||
pod 'KTVHTTPCache' #视频缓存
|
pod 'KTVHTTPCache' #视频缓存
|
||||||
pod 'HWPanModal' #底部弹出控制器
|
pod 'HWPanModal' #底部弹出控制器
|
||||||
pod 'Kingfisher' #图片加载
|
pod 'Kingfisher' #图片加载
|
||||||
pod 'EmptyStateKit' #空数据页面
|
# pod 'KingfisherWebP'
|
||||||
|
pod 'EmptyDataSet-Swift' #空数据页面
|
||||||
pod 'ReachabilitySwift' #网络状态监控
|
pod 'ReachabilitySwift' #网络状态监控
|
||||||
pod 'WMZPageController' #分页控制器
|
pod 'WMZPageController' #分页控制器
|
||||||
pod 'SVProgressHUD' #HUD
|
pod 'SVProgressHUD' #HUD
|
||||||
pod 'TZImagePickerController' #相册
|
pod 'TZImagePickerController' #相册
|
||||||
|
pod 'Adjust' # Adjust
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
31
Podfile.lock
@ -1,7 +1,12 @@
|
|||||||
PODS:
|
PODS:
|
||||||
|
- Adjust (5.4.0):
|
||||||
|
- Adjust/Adjust (= 5.4.0)
|
||||||
|
- Adjust/Adjust (5.4.0):
|
||||||
|
- AdjustSignature (= 3.35.2)
|
||||||
|
- AdjustSignature (3.35.2)
|
||||||
- Alamofire (5.10.2)
|
- Alamofire (5.10.2)
|
||||||
- CocoaAsyncSocket (7.6.5)
|
- CocoaAsyncSocket (7.6.5)
|
||||||
- EmptyStateKit (1.1.0)
|
- EmptyDataSet-Swift (5.0.0)
|
||||||
- HWPanModal (0.9.9)
|
- HWPanModal (0.9.9)
|
||||||
- Kingfisher (8.3.2)
|
- Kingfisher (8.3.2)
|
||||||
- KTVHTTPCache (3.0.2):
|
- KTVHTTPCache (3.0.2):
|
||||||
@ -12,7 +17,9 @@ PODS:
|
|||||||
- Moya/Core (15.0.0):
|
- Moya/Core (15.0.0):
|
||||||
- Alamofire (~> 5.0)
|
- Alamofire (~> 5.0)
|
||||||
- ReachabilitySwift (5.2.4)
|
- ReachabilitySwift (5.2.4)
|
||||||
- SmartCodable (4.3.9)
|
- SmartCodable (5.0.9):
|
||||||
|
- SmartCodable/Core (= 5.0.9)
|
||||||
|
- SmartCodable/Core (5.0.9)
|
||||||
- SnapKit (5.7.1)
|
- SnapKit (5.7.1)
|
||||||
- SVProgressHUD (2.3.1):
|
- SVProgressHUD (2.3.1):
|
||||||
- SVProgressHUD/Core (= 2.3.1)
|
- SVProgressHUD/Core (= 2.3.1)
|
||||||
@ -32,7 +39,8 @@ PODS:
|
|||||||
- ZFPlayer/Core (4.1.4)
|
- ZFPlayer/Core (4.1.4)
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- EmptyStateKit
|
- Adjust
|
||||||
|
- EmptyDataSet-Swift
|
||||||
- HWPanModal
|
- HWPanModal
|
||||||
- Kingfisher
|
- Kingfisher
|
||||||
- KTVHTTPCache
|
- KTVHTTPCache
|
||||||
@ -50,13 +58,13 @@ DEPENDENCIES:
|
|||||||
|
|
||||||
SPEC REPOS:
|
SPEC REPOS:
|
||||||
https://github.com/CocoaPods/Specs.git:
|
https://github.com/CocoaPods/Specs.git:
|
||||||
- Kingfisher
|
- Adjust
|
||||||
- ZFPlayer
|
- AdjustSignature
|
||||||
trunk:
|
|
||||||
- Alamofire
|
- Alamofire
|
||||||
- CocoaAsyncSocket
|
- CocoaAsyncSocket
|
||||||
- EmptyStateKit
|
- EmptyDataSet-Swift
|
||||||
- HWPanModal
|
- HWPanModal
|
||||||
|
- Kingfisher
|
||||||
- KTVHTTPCache
|
- KTVHTTPCache
|
||||||
- MJRefresh
|
- MJRefresh
|
||||||
- Moya
|
- Moya
|
||||||
@ -68,18 +76,21 @@ SPEC REPOS:
|
|||||||
- TZImagePickerController
|
- TZImagePickerController
|
||||||
- WMZPageController
|
- WMZPageController
|
||||||
- YYKit
|
- YYKit
|
||||||
|
- ZFPlayer
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
|
Adjust: a5f881d0cbfe9a6df979b076dc7116fe19ece797
|
||||||
|
AdjustSignature: 23b9e5d4adcadffc303bb6b410fde617dd88504f
|
||||||
Alamofire: 7193b3b92c74a07f85569e1a6c4f4237291e7496
|
Alamofire: 7193b3b92c74a07f85569e1a6c4f4237291e7496
|
||||||
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
|
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
|
||||||
EmptyStateKit: dc41e9ce5c6089f67a49d063bce73ade9f2ba73f
|
EmptyDataSet-Swift: eb382c0c87a2d9c678077385a595cec52da38171
|
||||||
HWPanModal: b57a6717d3cdcd666bff44f9dd2a5be9f4d6f5d2
|
HWPanModal: b57a6717d3cdcd666bff44f9dd2a5be9f4d6f5d2
|
||||||
Kingfisher: 0621d0ac0c78fecb19f6dc5303bde2b52abaf2f5
|
Kingfisher: 0621d0ac0c78fecb19f6dc5303bde2b52abaf2f5
|
||||||
KTVHTTPCache: 5711692cdf9a5ecfe829b1e16577deb3ffe3dc86
|
KTVHTTPCache: 5711692cdf9a5ecfe829b1e16577deb3ffe3dc86
|
||||||
MJRefresh: ff9e531227924c84ce459338414550a05d2aea78
|
MJRefresh: ff9e531227924c84ce459338414550a05d2aea78
|
||||||
Moya: 138f0573e53411fb3dc17016add0b748dfbd78ee
|
Moya: 138f0573e53411fb3dc17016add0b748dfbd78ee
|
||||||
ReachabilitySwift: 32793e867593cfc1177f5d16491e3a197d2fccda
|
ReachabilitySwift: 32793e867593cfc1177f5d16491e3a197d2fccda
|
||||||
SmartCodable: efc682e18fb5eac77f4c0497e37c79590710c192
|
SmartCodable: 68b3598438181a938eed8ee5623e58ef3e3ea443
|
||||||
SnapKit: d612e99e678a2d3b95bf60b0705ed0a35c03484a
|
SnapKit: d612e99e678a2d3b95bf60b0705ed0a35c03484a
|
||||||
SVProgressHUD: 4837c74bdfe2e51e8821c397825996a8d7de6e22
|
SVProgressHUD: 4837c74bdfe2e51e8821c397825996a8d7de6e22
|
||||||
Toast: 1f5ea13423a1e6674c4abdac5be53587ae481c4e
|
Toast: 1f5ea13423a1e6674c4abdac5be53587ae481c4e
|
||||||
@ -88,6 +99,6 @@ SPEC CHECKSUMS:
|
|||||||
YYKit: 7cda43304a8dc3696c449041e2cb3107b4e236e7
|
YYKit: 7cda43304a8dc3696c449041e2cb3107b4e236e7
|
||||||
ZFPlayer: 5cf39e8d9f0c2394a014b0db4767b5b5a6bffe13
|
ZFPlayer: 5cf39e8d9f0c2394a014b0db4767b5b5a6bffe13
|
||||||
|
|
||||||
PODFILE CHECKSUM: a4a45c34f6f8f83641e2b23364c97c871ca84221
|
PODFILE CHECKSUM: 25e7f44d27dd18aad94fde84cae1f0c157c60341
|
||||||
|
|
||||||
COCOAPODS: 1.16.2
|
COCOAPODS: 1.16.2
|
||||||
|
2128
ThimraTV.xcodeproj/project.pbxproj
Normal file
78
ThimraTV.xcodeproj/xcshareddata/xcschemes/ThimraTV.xcscheme
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1620"
|
||||||
|
version = "1.7">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES"
|
||||||
|
buildArchitectures = "Automatic">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "1DBC40582DA4EDFC0093FCB0"
|
||||||
|
BuildableName = "ThimraTV.app"
|
||||||
|
BlueprintName = "ThimraTV"
|
||||||
|
ReferencedContainer = "container:ThimraTV.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
shouldAutocreateTestPlan = "YES">
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "1DBC40582DA4EDFC0093FCB0"
|
||||||
|
BuildableName = "ThimraTV.app"
|
||||||
|
BlueprintName = "ThimraTV"
|
||||||
|
ReferencedContainer = "container:ThimraTV.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "1DBC40582DA4EDFC0093FCB0"
|
||||||
|
BuildableName = "ThimraTV.app"
|
||||||
|
BlueprintName = "ThimraTV"
|
||||||
|
ReferencedContainer = "container:ThimraTV.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
@ -2,7 +2,7 @@
|
|||||||
<Workspace
|
<Workspace
|
||||||
version = "1.0">
|
version = "1.0">
|
||||||
<FileRef
|
<FileRef
|
||||||
location = "group:MoviaBox.xcodeproj">
|
location = "group:ThimraTV.xcodeproj">
|
||||||
</FileRef>
|
</FileRef>
|
||||||
<FileRef
|
<FileRef
|
||||||
location = "group:Pods/Pods.xcodeproj">
|
location = "group:Pods/Pods.xcodeproj">
|
133
ThimraTV/AppDelegate/AppDelegate+APNS.swift
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
//
|
||||||
|
// AppDelegate+APNS.swift
|
||||||
|
// ThimraTV
|
||||||
|
//
|
||||||
|
// Created by 佳尔 on 2025/4/30.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import FirebaseMessaging
|
||||||
|
import FirebaseCore
|
||||||
|
|
||||||
|
extension AppDelegate {
|
||||||
|
///是否展示过通知提示
|
||||||
|
static var haveBeenShownAPNS = false
|
||||||
|
|
||||||
|
func registerAPNS() {
|
||||||
|
FirebaseApp.configure()
|
||||||
|
Messaging.messaging().delegate = self
|
||||||
|
|
||||||
|
let center = UNUserNotificationCenter.current()
|
||||||
|
center.delegate = self
|
||||||
|
|
||||||
|
center.requestAuthorization(options: [.badge, .sound, .alert]) { grant, error in
|
||||||
|
if !grant {
|
||||||
|
if let date = UserDefaults.standard.object(forKey: kSPApnsAlertDefaultsKey) as? Date {
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||||
|
#if DEBUG
|
||||||
|
self.showApnsAlert()
|
||||||
|
#else
|
||||||
|
if !date.sp_isToday {
|
||||||
|
self.showApnsAlert()
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Self.haveBeenShownAPNS = true
|
||||||
|
SPAPPTool.sceneDelegate?.retryHandleOpenAppMessage()
|
||||||
|
}
|
||||||
|
UserDefaults.standard.set(Date(), forKey: kSPApnsAlertDefaultsKey)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Self.haveBeenShownAPNS = true
|
||||||
|
SPAPPTool.sceneDelegate?.retryHandleOpenAppMessage()
|
||||||
|
}
|
||||||
|
self.uploadNoticeStatus()
|
||||||
|
}
|
||||||
|
UIApplication.shared.registerForRemoteNotifications()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func showApnsAlert() {
|
||||||
|
let view = SPApnsAlertView()
|
||||||
|
view.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
///更新通知状态
|
||||||
|
func uploadNoticeStatus() {
|
||||||
|
UNUserNotificationCenter.current().getNotificationSettings { settings in
|
||||||
|
if settings.authorizationStatus == .authorized {
|
||||||
|
SPRewardsAPI.requestUploadNoticeStatus(status: true)
|
||||||
|
} else if settings.authorizationStatus == .denied {
|
||||||
|
SPRewardsAPI.requestUploadNoticeStatus(status: false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension AppDelegate: UNUserNotificationCenterDelegate {
|
||||||
|
|
||||||
|
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
|
||||||
|
Messaging.messaging().apnsToken = deviceToken
|
||||||
|
}
|
||||||
|
///APP处于前台是接收通知消息
|
||||||
|
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
|
||||||
|
completionHandler([.badge, .banner])
|
||||||
|
}
|
||||||
|
|
||||||
|
///点击通知消息进入app
|
||||||
|
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
|
||||||
|
if #available(iOS 16.0, *) {
|
||||||
|
UNUserNotificationCenter.current().setBadgeCount(0)
|
||||||
|
} else {
|
||||||
|
UIApplication.shared.applicationIconBadgeNumber = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let userInfo: [String : Any] = response.notification.request.content.userInfo as? [String : Any] else {
|
||||||
|
completionHandler()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let model = SPOpenAppModel.deserialize(from: userInfo) else {
|
||||||
|
completionHandler()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
SPStatAPI.requestStatApns(messageId: model.message_id ?? "", title: response.notification.request.content.title)
|
||||||
|
|
||||||
|
|
||||||
|
if model.path == .videoDetail, let shortPlayId = model.short_play_id {
|
||||||
|
let vc = SPPlayerDetailViewController()
|
||||||
|
vc.shortPlayId = shortPlayId
|
||||||
|
SPAPPTool.topViewController()?.navigationController?.pushViewController(vc, animated: true)
|
||||||
|
|
||||||
|
} else if model.path == .promotion {
|
||||||
|
SPAPPTool.mainTabBarController?.selectedReward()
|
||||||
|
|
||||||
|
} else if model.path == .feedback {
|
||||||
|
let vc = SPCampaignWebViewController()
|
||||||
|
vc.urlStr = SPFeedBackListWebUrl
|
||||||
|
SPAPPTool.topViewController()?.navigationController?.pushViewController(vc, animated: true)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
completionHandler()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//MARK: -------------- MessagingDelegate --------------
|
||||||
|
extension AppDelegate: MessagingDelegate {
|
||||||
|
|
||||||
|
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
|
||||||
|
if let token = fcmToken {
|
||||||
|
SPApnsAPI.requestUploadDeviceToken(token: token)
|
||||||
|
}
|
||||||
|
|
||||||
|
let dataDict: [String: String] = ["token": fcmToken ?? ""]
|
||||||
|
NotificationCenter.default.post(
|
||||||
|
name: Notification.Name("FCMToken"),
|
||||||
|
object: nil,
|
||||||
|
userInfo: dataDict
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// AppDelegate+Config.swift
|
// AppDelegate+Config.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/8.
|
// Created by 曾觉新 on 2025/4/8.
|
||||||
//
|
//
|
||||||
@ -17,6 +17,8 @@ extension AppDelegate {
|
|||||||
SPToast.config()
|
SPToast.config()
|
||||||
|
|
||||||
SPHUD.config()
|
SPHUD.config()
|
||||||
|
|
||||||
|
UIBarButtonItem.appearance().sp_setTitleTextAttributes()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -70,8 +72,6 @@ extension AppDelegate {
|
|||||||
if #available(iOS 15.0, *) {
|
if #available(iOS 15.0, *) {
|
||||||
tabBar.scrollEdgeAppearance = appearance
|
tabBar.scrollEdgeAppearance = appearance
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
122
ThimraTV/AppDelegate/AppDelegate+OpenApp.swift
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
//
|
||||||
|
// AppDelegate+OpenApp.swift
|
||||||
|
// ThimraTV
|
||||||
|
//
|
||||||
|
// Created by 佳尔 on 2025/4/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
#if canImport(FacebookCore)
|
||||||
|
import FacebookCore
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
extension SceneDelegate {
|
||||||
|
|
||||||
|
///URL打开APP
|
||||||
|
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
|
||||||
|
guard let url = URLContexts.first?.url else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var result = false
|
||||||
|
|
||||||
|
#if canImport(FacebookCore)
|
||||||
|
result = ApplicationDelegate.shared.application(UIApplication.shared, open: url, sourceApplication: nil, annotation: [UIApplication.OpenURLOptionsKey.annotation])
|
||||||
|
#endif
|
||||||
|
if !result {
|
||||||
|
handleOpenAppMessage(webpageURL: url)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
///UniversalLink 打开app
|
||||||
|
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
|
||||||
|
guard let webpageURL = userActivity.webpageURL else { return }
|
||||||
|
|
||||||
|
handleOpenAppMessage(webpageURL: webpageURL)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extension SceneDelegate {
|
||||||
|
static var hasOpenMessage = false
|
||||||
|
///是否需要重试
|
||||||
|
static var isNeedRetry = false
|
||||||
|
|
||||||
|
private static var webpageURL: URL?
|
||||||
|
|
||||||
|
func handleOpenAppMessage(webpageURL: URL?) {
|
||||||
|
guard SPNetworkReachabilityManager.manager.isReachable == true, AppDelegate.haveBeenShownAPNS, SPAPPTool.isAppOpen else {
|
||||||
|
if let webpageURL = webpageURL {
|
||||||
|
SceneDelegate.webpageURL = webpageURL
|
||||||
|
}
|
||||||
|
Self.isNeedRetry = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Self.isNeedRetry = false
|
||||||
|
SceneDelegate.webpageURL = nil
|
||||||
|
|
||||||
|
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||||
|
self._handleOpenAppMessage(webpageURL: webpageURL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///重试
|
||||||
|
func retryHandleOpenAppMessage() {
|
||||||
|
guard Self.isNeedRetry else { return }
|
||||||
|
handleOpenAppMessage(webpageURL: SceneDelegate.webpageURL)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func _handleOpenAppMessage(webpageURL: URL?) {
|
||||||
|
if !SPAPPTool.isAppOpen { return }
|
||||||
|
|
||||||
|
if Self.hasOpenMessage { return }
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
|
||||||
|
Self.hasOpenMessage = false
|
||||||
|
}
|
||||||
|
|
||||||
|
Self.hasOpenMessage = true
|
||||||
|
|
||||||
|
//统计用URL
|
||||||
|
var statUrlStr: String?
|
||||||
|
var data: [String : Any]?
|
||||||
|
|
||||||
|
if let pasteStr = UIPasteboard.general.string, pasteStr.contains("movia") {
|
||||||
|
UIPasteboard.general.string = nil
|
||||||
|
let tempArr = pasteStr.components(separatedBy: "?")
|
||||||
|
let query = tempArr.last
|
||||||
|
|
||||||
|
let tempData = query?.urlQuryToDictionary()
|
||||||
|
if tempData?["short_play_id"] != nil {
|
||||||
|
data = tempData
|
||||||
|
statUrlStr = pasteStr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if data == nil {
|
||||||
|
data = webpageURL?.query?.urlQuryToDictionary()
|
||||||
|
statUrlStr = webpageURL?.absoluteString
|
||||||
|
}
|
||||||
|
|
||||||
|
if let urlStr = statUrlStr {//上报结果
|
||||||
|
SPStatAPI.requestStatW2a(data: urlStr)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
guard let data = data else { return }
|
||||||
|
guard let model = SPOpenAppModel.deserialize(from: data) else { return }
|
||||||
|
guard let shortPlayId = model.short_play_id, shortPlayId.count > 0 else { return }
|
||||||
|
|
||||||
|
|
||||||
|
let vc = SPPlayerDetailViewController()
|
||||||
|
vc.shortPlayId = shortPlayId
|
||||||
|
SPAPPTool.topViewController()?.navigationController?.pushViewController(vc, animated: true)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
33
ThimraTV/AppDelegate/AppDelegate+Thirdparty.swift
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
//
|
||||||
|
// AppDelegate+Thirdparty.swift
|
||||||
|
// ThimraTV
|
||||||
|
//
|
||||||
|
// Created by 佳尔 on 2025/5/7.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import AdjustSdk
|
||||||
|
#if canImport(FacebookCore)
|
||||||
|
import FacebookCore
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extension AppDelegate {
|
||||||
|
|
||||||
|
func registThirdparty(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) {
|
||||||
|
//Facebook
|
||||||
|
#if canImport(FacebookCore)
|
||||||
|
ApplicationDelegate.shared.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
registAdjust()
|
||||||
|
///设置刷新控件的语言
|
||||||
|
MJRefreshConfig.default.languageCode = SPLocalizedManager.shared.mjLocalizedKey
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private func registAdjust() {
|
||||||
|
let config = ADJConfig(appToken: "7z38v0rvceww", environment: ADJEnvironmentProduction)
|
||||||
|
Adjust.initSdk(config)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// AppDelegate.swift
|
// AppDelegate.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/8.
|
// Created by 曾觉新 on 2025/4/8.
|
||||||
//
|
//
|
||||||
@ -13,18 +13,24 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||||||
|
|
||||||
|
|
||||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||||
|
SPAPPTool.appDelegate = self
|
||||||
|
|
||||||
|
self.registThirdparty(application, didFinishLaunchingWithOptions: launchOptions)
|
||||||
|
|
||||||
self.appConfig()
|
self.appConfig()
|
||||||
|
|
||||||
SPLoginManager.manager.requestVisitorLogin(completer: nil)
|
|
||||||
///开启网络监控
|
///开启网络监控
|
||||||
// SPNetworkReachabilityManager.manager.startMonitoring()
|
SPNetworkReachabilityManager.manager.startMonitoring()
|
||||||
|
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(reachabilityDidChangeNotification), name: SPNetworkReachabilityManager.reachabilityDidChangeNotification, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(reachabilityDidChangeNotification), name: SPNetworkReachabilityManager.reachabilityDidChangeNotification, object: nil)
|
||||||
|
|
||||||
|
let _ = JXIAPManager.manager
|
||||||
|
|
||||||
SPNetworkReachabilityManager.manager.startMonitoring()
|
// SPLoginManager.manager.requestVisitorLogin(completer: nil)
|
||||||
|
SPLoginManager.manager.updateUserInfo(completer: nil)
|
||||||
|
///注册消息通知
|
||||||
|
registerAPNS()
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -46,7 +52,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||||||
|
|
||||||
@objc private func reachabilityDidChangeNotification() {
|
@objc private func reachabilityDidChangeNotification() {
|
||||||
if SPNetworkReachabilityManager.manager.isReachable == true {
|
if SPNetworkReachabilityManager.manager.isReachable == true {
|
||||||
SPLoginManager.manager.requestVisitorLogin(completer: nil)
|
// SPLoginManager.manager.requestVisitorLogin(completer: nil)
|
||||||
|
SPLoginManager.manager.updateUserInfo(completer: nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
172
ThimraTV/AppDelegate/SceneDelegate.swift
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
//
|
||||||
|
// SceneDelegate.swift
|
||||||
|
// ThimraTV
|
||||||
|
//
|
||||||
|
// Created by 曾觉新 on 2025/4/8.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||||
|
|
||||||
|
var window: UIWindow?
|
||||||
|
|
||||||
|
private var timer: Timer?
|
||||||
|
|
||||||
|
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
|
||||||
|
guard let windowScene = (scene as? UIWindowScene) else { return }
|
||||||
|
SPAPPTool.sceneDelegate = self
|
||||||
|
SPAPPTool.windowScene = windowScene
|
||||||
|
|
||||||
|
///监听语言切换
|
||||||
|
NotificationCenter.default.addObserver(self, selector: #selector(localizedDidChange), name: SPLocalizedManager.localizedDidChange, object: nil)
|
||||||
|
///监听网路变化
|
||||||
|
NotificationCenter.default.addObserver(self, selector: #selector(reachabilityDidChangeNotification), name: SPNetworkReachabilityManager.reachabilityDidChangeNotification, object: nil)
|
||||||
|
///监听登录状态
|
||||||
|
// NotificationCenter.default.addObserver(self, selector: #selector(loginStateDidChangeNotification), name: SPLoginManager.loginStateDidChangeNotification, object: nil)
|
||||||
|
|
||||||
|
if let webpageURL = connectionOptions.userActivities.first?.webpageURL {
|
||||||
|
self.handleOpenAppMessage(webpageURL: webpageURL)
|
||||||
|
} else if let url = connectionOptions.urlContexts.first?.url {
|
||||||
|
self.handleOpenAppMessage(webpageURL: url)
|
||||||
|
}
|
||||||
|
|
||||||
|
window = UIWindow(windowScene: windowScene)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
startApp()
|
||||||
|
|
||||||
|
//在线状态统计
|
||||||
|
timer = Timer.scheduledTimer(timeInterval: 60 * 10, target: self, selector: #selector(handleOnLine), userInfo: nil, repeats: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func sceneDidDisconnect(_ scene: UIScene) {
|
||||||
|
// Called as the scene is being released by the system.
|
||||||
|
// This occurs shortly after the scene enters the background, or when its session is discarded.
|
||||||
|
// Release any resources associated with this scene that can be re-created the next time the scene connects.
|
||||||
|
// The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
|
||||||
|
}
|
||||||
|
|
||||||
|
func sceneDidBecomeActive(_ scene: UIScene) {
|
||||||
|
// Called when the scene has moved from an inactive state to an active state.
|
||||||
|
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
|
||||||
|
SPStatAPI.requestEnterApp()
|
||||||
|
handleOnLine()
|
||||||
|
}
|
||||||
|
|
||||||
|
func sceneWillResignActive(_ scene: UIScene) {
|
||||||
|
// Called when the scene will move from an active state to an inactive state.
|
||||||
|
// This may occur due to temporary interruptions (ex. an incoming phone call).
|
||||||
|
|
||||||
|
SPStatAPI.requestLeaveApp()
|
||||||
|
}
|
||||||
|
|
||||||
|
func sceneWillEnterForeground(_ scene: UIScene) {
|
||||||
|
// Called as the scene transitions from the background to the foreground.
|
||||||
|
// Use this method to undo the changes made on entering the background.
|
||||||
|
SPAPPTool.appDelegate?.uploadNoticeStatus()
|
||||||
|
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||||
|
self.handleOpenAppMessage(webpageURL: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func sceneDidEnterBackground(_ scene: UIScene) {
|
||||||
|
// Called as the scene transitions from the foreground to the background.
|
||||||
|
// Use this method to save data, release shared resources, and store enough scene-specific state information
|
||||||
|
// to restore the scene back to its current state.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SceneDelegate {
|
||||||
|
|
||||||
|
private func startApp() {
|
||||||
|
let localizedManager = SPLocalizedManager.shared
|
||||||
|
|
||||||
|
///设置语言与当前的数据语言不同步时,需要重新获取语言后展示页面
|
||||||
|
if localizedManager.localizedDataLocalizedKey != localizedManager.currentLocalizedKey, let lanuchVC = SPAPPTool.getLanuchViewController() {
|
||||||
|
window?.rootViewController = lanuchVC
|
||||||
|
window?.makeKeyAndVisible()
|
||||||
|
|
||||||
|
SPLocalizedManager.shared.updateLocalizedData { [weak self] finish in
|
||||||
|
guard let self = self else { return }
|
||||||
|
self.setRootVC()
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
SPLocalizedManager.shared.updateLocalizedData(completer: nil)
|
||||||
|
|
||||||
|
setRootVC()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///统计在线状态
|
||||||
|
@objc private func handleOnLine() {
|
||||||
|
SPStatAPI.requestStatOnLine()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setRootVC() {
|
||||||
|
let hasOpenApp = UserDefaults.standard.object(forKey: kSPHasBeenOpenedAPPDefaultsKey) as? Bool
|
||||||
|
///引导页
|
||||||
|
let guideVc = SPGuideViewController()
|
||||||
|
|
||||||
|
|
||||||
|
if hasOpenApp != true && guideVc.lanuchVC != nil {
|
||||||
|
SPAPPTool.isAppOpen = false
|
||||||
|
guideVc.openAppBlock = {
|
||||||
|
self.handleOpenApp()
|
||||||
|
}
|
||||||
|
window?.rootViewController = guideVc
|
||||||
|
window?.makeKeyAndVisible()
|
||||||
|
|
||||||
|
} else {
|
||||||
|
SPAPPTool.isAppOpen = true
|
||||||
|
setTabBarController()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setTabBarController() {
|
||||||
|
let tabBarController = SPTabBarController()
|
||||||
|
SPAPPTool.mainTabBarController = tabBarController
|
||||||
|
|
||||||
|
window?.rootViewController = tabBarController
|
||||||
|
window?.makeKeyAndVisible()
|
||||||
|
}
|
||||||
|
|
||||||
|
///打开app
|
||||||
|
@objc private func handleOpenApp() {
|
||||||
|
setTabBarController()
|
||||||
|
|
||||||
|
retryHandleOpenAppMessage()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SceneDelegate {
|
||||||
|
///语言切换
|
||||||
|
@objc private func localizedDidChange() {
|
||||||
|
MJRefreshConfig.default.languageCode = SPLocalizedManager.shared.mjLocalizedKey
|
||||||
|
|
||||||
|
setTabBarController()
|
||||||
|
}
|
||||||
|
|
||||||
|
///监听网络变化
|
||||||
|
@objc private func reachabilityDidChangeNotification() {
|
||||||
|
retryHandleOpenAppMessage()
|
||||||
|
|
||||||
|
let localizedData = SPLocalizedManager.shared.localizedData ?? [:]
|
||||||
|
|
||||||
|
if SPNetworkReachabilityManager.manager.isReachable == true {
|
||||||
|
handleOnLine()
|
||||||
|
|
||||||
|
///缺少语言数据,重新获取语言数据
|
||||||
|
if localizedData.isEmpty {
|
||||||
|
self.startApp()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// SPNavigationController.swift
|
// SPNavigationController.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/8.
|
// Created by 曾觉新 on 2025/4/8.
|
||||||
//
|
//
|
@ -1,27 +1,31 @@
|
|||||||
//
|
//
|
||||||
// SPTabBarController.swift
|
// SPTabBarController.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/8.
|
// Created by 曾觉新 on 2025/4/8.
|
||||||
//
|
//
|
||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
|
import WebKit
|
||||||
|
|
||||||
class SPTabBarController: UITabBarController {
|
class SPTabBarController: UITabBarController {
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
self.view.backgroundColor = .backgroundColor()
|
self.view.backgroundColor = .backgroundColor()
|
||||||
|
|
||||||
let nav1 = createNavigationController(viewController: SPHomeViewController(), title: "Home".localized, image: UIImage(named: "tabbar_icon_01"), selectedImage: UIImage(named: "tabbar_icon_01_selected"))
|
let nav1 = createNavigationController(viewController: SPHomeViewController(), title: "movia_home".localized, image: UIImage(named: "tabbar_icon_01"), selectedImage: UIImage(named: "tabbar_icon_01_selected"))
|
||||||
|
|
||||||
let nav2 = createNavigationController(viewController: SPExplorePageController(), title: "For You".localized, image: UIImage(named: "tabbar_icon_02"), selectedImage: UIImage(named: "tabbar_icon_02_selected"))
|
let nav2 = createNavigationController(viewController: SPExplorePageController(), title: "movia_for_you".localized, image: UIImage(named: "tabbar_icon_02"), selectedImage: UIImage(named: "tabbar_icon_02_selected"))
|
||||||
|
|
||||||
let nav4 = createNavigationController(viewController: SPMyListViewController(), title: "My list".localized, image: UIImage(named: "tabbar_icon_04"), selectedImage: UIImage(named: "tabbar_icon_04_selected"))
|
let nav3 = createNavigationController(viewController: SPMyListViewController(), title: "movia_my_list".localized, image: UIImage(named: "tabbar_icon_04"), selectedImage: UIImage(named: "tabbar_icon_04_selected"))
|
||||||
|
|
||||||
|
let nav4 = createNavigationController(viewController: SPRewardsViewController(), title: "movia_rewards".localized, image: UIImage(named: "tabbar_icon_04"), selectedImage: UIImage(named: "tabbar_icon_04_selected"))
|
||||||
|
|
||||||
let nav5 = createNavigationController(viewController: SPMineViewController(), title: "Profile".localized, image: UIImage(named: "tabbar_icon_05"), selectedImage: UIImage(named: "tabbar_icon_05_selected"))
|
let nav5 = createNavigationController(viewController: SPMineViewController(), title: "movia_profile".localized, image: UIImage(named: "tabbar_icon_05"), selectedImage: UIImage(named: "tabbar_icon_05_selected"))
|
||||||
|
|
||||||
|
self.viewControllers = [nav1, nav2, nav3, nav4, nav5]
|
||||||
|
|
||||||
self.viewControllers = [nav1, nav2, nav4, nav5]
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,6 +61,21 @@ extension SPTabBarController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///选择活动页面
|
||||||
|
func selectedReward() {
|
||||||
|
var index: Int?
|
||||||
|
self.viewControllers?.enumerated().forEach({
|
||||||
|
guard let nav = $1 as? UINavigationController else { return }
|
||||||
|
if let _ = nav.viewControllers.first as? SPRewardsViewController {
|
||||||
|
index = $0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if let index = index {
|
||||||
|
self.selectedIndex = index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension SPTabBarController {
|
extension SPTabBarController {
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// SPViewController.swift
|
// SPViewController.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/8.
|
// Created by 曾觉新 on 2025/4/8.
|
||||||
//
|
//
|
||||||
@ -22,6 +22,7 @@ class SPViewController: UIViewController, JYPageChildContollerProtocol {
|
|||||||
|
|
||||||
private(set) var isViewDidLoad = false
|
private(set) var isViewDidLoad = false
|
||||||
private(set) var isDidAppear = false
|
private(set) var isDidAppear = false
|
||||||
|
private(set) var hasViewDidAppear = false
|
||||||
|
|
||||||
private(set) lazy var bgImageView: UIImageView = {
|
private(set) lazy var bgImageView: UIImageView = {
|
||||||
let imageView = UIImageView(image: UIImage(named: "main_bg_image_01"))
|
let imageView = UIImageView(image: UIImage(named: "main_bg_image_01"))
|
||||||
@ -29,6 +30,12 @@ class SPViewController: UIViewController, JYPageChildContollerProtocol {
|
|||||||
return imageView;
|
return imageView;
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
///无网空页面
|
||||||
|
private(set) lazy var noNetworkEmptyView: SPNoNetworkEmptyView = {
|
||||||
|
let view = SPNoNetworkEmptyView()
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
///头部渐变色
|
///头部渐变色
|
||||||
private lazy var topGradientView: SPGradientView = {
|
private lazy var topGradientView: SPGradientView = {
|
||||||
let view = SPGradientView()
|
let view = SPGradientView()
|
||||||
@ -77,6 +84,7 @@ class SPViewController: UIViewController, JYPageChildContollerProtocol {
|
|||||||
override func viewDidAppear(_ animated: Bool) {
|
override func viewDidAppear(_ animated: Bool) {
|
||||||
super.viewDidAppear(animated)
|
super.viewDidAppear(animated)
|
||||||
isDidAppear = true
|
isDidAppear = true
|
||||||
|
hasViewDidAppear = true
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewWillDisappear(_ animated: Bool) {
|
override func viewWillDisappear(_ animated: Bool) {
|
||||||
@ -118,6 +126,24 @@ class SPViewController: UIViewController, JYPageChildContollerProtocol {
|
|||||||
func handleHeaderRefresh(_ completer: (() -> Void)?) {}
|
func handleHeaderRefresh(_ completer: (() -> Void)?) {}
|
||||||
|
|
||||||
func handleFooterRefresh(_ completer: (() -> Void)?) {}
|
func handleFooterRefresh(_ completer: (() -> Void)?) {}
|
||||||
|
|
||||||
|
///添加无网空页面
|
||||||
|
func addNoNetworkEmptyView(clickButton: (() -> Void)?) {
|
||||||
|
noNetworkEmptyView.clickButton = {
|
||||||
|
clickButton?()
|
||||||
|
}
|
||||||
|
view.addSubview(noNetworkEmptyView)
|
||||||
|
|
||||||
|
noNetworkEmptyView.snp.makeConstraints { make in
|
||||||
|
make.centerX.equalToSuperview()
|
||||||
|
make.centerY.equalToSuperview().offset(-50)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///删除无网空页面
|
||||||
|
func removeNoNetworkEmptyView() {
|
||||||
|
noNetworkEmptyView.removeFromSuperview()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,7 +204,7 @@ extension UIViewController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///设置当行标题样式
|
///设置标题样式
|
||||||
func setNavigationTitleStyle(color: UIColor? = nil, font: UIFont? = nil) {
|
func setNavigationTitleStyle(color: UIColor? = nil, font: UIFont? = nil) {
|
||||||
guard let nav = navigationController else { return }
|
guard let nav = navigationController else { return }
|
||||||
if nav.visibleViewController == self {
|
if nav.visibleViewController == self {
|
11
ThimraTV/Base/Define/SPAPPKey.swift
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
//
|
||||||
|
// SPAPPKey.swift
|
||||||
|
// ThimraTV
|
||||||
|
//
|
||||||
|
// Created by 佳尔 on 2025/4/30.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
let kSPAppleAppId = "6745007239"
|
||||||
|
let kSPAppleDownloadPath = "https://apps.apple.com/app/id6670203263"
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// SPDefine.swift
|
// SPDefine.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/8.
|
// Created by 曾觉新 on 2025/4/8.
|
||||||
//
|
//
|
28
ThimraTV/Base/Define/SPUserDefaultsKey.swift
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// SPUserDefaultsKey.swift
|
||||||
|
// ThimraTV
|
||||||
|
//
|
||||||
|
// Created by 曾觉新 on 2025/4/9.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
///是否开启过APP
|
||||||
|
let kSPHasBeenOpenedAPPDefaultsKey = "kSPHasBeenOpenedAPPDefaultsKey"
|
||||||
|
|
||||||
|
///登录的用户信息
|
||||||
|
let kSPLoginTokenDefaultsKey = "kSPLoginTokenDefaultsKey"
|
||||||
|
///登录的用户信息
|
||||||
|
let kSPLoginUserInfoDefaultsKey = "kSPLoginUserInfoDefaultsKey"
|
||||||
|
|
||||||
|
///首页搜索记录
|
||||||
|
let kSPHomeSearchHistoryDefaultsKey = "kSPHomeSearchHistoryDefaultsKey"
|
||||||
|
|
||||||
|
///待恢复数据
|
||||||
|
let kSPWaitRestoreIAPDefaultsKey = "kSPWaitRestoreIAPDefaultsKey"
|
||||||
|
|
||||||
|
///推送提示
|
||||||
|
let kSPApnsAlertDefaultsKey = "kSPApnsAlertDefaultsKey"
|
||||||
|
|
||||||
|
///vip弹窗时间
|
||||||
|
let kSPVipAlertDateDefaultsKey = "kSPVipAlertDateDefaultsKey"
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// CGMutablePath+SPAdd.swift
|
// CGMutablePath+SPAdd.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/14.
|
// Created by 曾觉新 on 2025/4/14.
|
||||||
//
|
//
|
39
ThimraTV/Base/Extension/Date+SPAdd.swift
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
//
|
||||||
|
// Date+SPAdd.swift
|
||||||
|
// ThimraTV
|
||||||
|
//
|
||||||
|
// Created by 佳尔 on 2025/5/6.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
extension Date {
|
||||||
|
///格式化时间 yyyy-MM-dd HH-mm-ss
|
||||||
|
func format(dateFormat: String) -> String {
|
||||||
|
let formatter = DateFormatter()
|
||||||
|
formatter.dateFormat = dateFormat
|
||||||
|
return formatter.string(from: self)
|
||||||
|
}
|
||||||
|
|
||||||
|
func dateDifference(date: Date) -> Int {
|
||||||
|
let dateComponents = Calendar.current.dateComponents([.day], from: self, to: date)
|
||||||
|
return dateComponents.day ?? 0
|
||||||
|
}
|
||||||
|
|
||||||
|
///是否是今天
|
||||||
|
var sp_isToday: Bool {
|
||||||
|
get {
|
||||||
|
return Calendar.current.isDateInToday(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
///是否是昨天
|
||||||
|
var sp_isYesterday: Bool {
|
||||||
|
return Calendar.current.isDateInYesterday(self)
|
||||||
|
}
|
||||||
|
///是否是明天
|
||||||
|
var sp_isTomorrow: Bool {
|
||||||
|
return Calendar.current.isDateInTomorrow(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// Dictionary+SPAdd.swift
|
// Dictionary+SPAdd.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 佳尔 on 2025/4/25.
|
// Created by 佳尔 on 2025/4/25.
|
||||||
//
|
//
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// Int+SPAdd.swift
|
// Int+SPAdd.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/17.
|
// Created by 曾觉新 on 2025/4/17.
|
||||||
//
|
//
|
25
ThimraTV/Base/Extension/NSNumber+SPAdd.swift
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
//
|
||||||
|
// NSNumber+SPAdd.swift
|
||||||
|
// ThimraTV
|
||||||
|
//
|
||||||
|
// Created by 佳尔 on 2025/5/16.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
extension NSNumber {
|
||||||
|
|
||||||
|
func toString(maximumFractionDigits: Int = 10, minimumFractionDigits: Int? = nil, roundingMode: NumberFormatter.RoundingMode? = nil) -> String {
|
||||||
|
let formatter = NumberFormatter()
|
||||||
|
formatter.minimumIntegerDigits = 1
|
||||||
|
formatter.maximumFractionDigits = maximumFractionDigits
|
||||||
|
if let minimumFractionDigits = minimumFractionDigits {
|
||||||
|
formatter.minimumFractionDigits = minimumFractionDigits
|
||||||
|
}
|
||||||
|
if let roundingMode = roundingMode {
|
||||||
|
formatter.roundingMode = roundingMode
|
||||||
|
}
|
||||||
|
formatter.numberStyle = .none
|
||||||
|
return formatter.string(from: self) ?? "0"
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// String+SPAdd.swift
|
// String+SPAdd.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/8.
|
// Created by 曾觉新 on 2025/4/8.
|
||||||
//
|
//
|
||||||
@ -25,6 +25,31 @@ extension String: SmartCodable {
|
|||||||
return String(format: "GMT+0%d:00", timeZoneSecondsFromGMT)
|
return String(format: "GMT+0%d:00", timeZoneSecondsFromGMT)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///设置首字母大写
|
||||||
|
func capitalizingFirstLetter() -> String {
|
||||||
|
guard let first = self.first else { return self }
|
||||||
|
return first.uppercased() + self.dropFirst()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension String {
|
||||||
|
///将url中的参数转换成字典
|
||||||
|
func urlQuryToDictionary() -> [String : Any] {
|
||||||
|
let array = self.components(separatedBy: "&")
|
||||||
|
var tempDic: [String : Any] = [:]
|
||||||
|
|
||||||
|
array.forEach {
|
||||||
|
if let strRange = $0.range(of: "=") {
|
||||||
|
var key: String = String($0.prefix(upTo: strRange.upperBound))
|
||||||
|
key.removeLast()
|
||||||
|
var value: String = String($0.suffix(from: strRange.upperBound))
|
||||||
|
value = value.removingPercentEncoding ?? value
|
||||||
|
tempDic[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tempDic
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension String {
|
extension String {
|
36
ThimraTV/Base/Extension/UIBarButtonItem+SPAdd.swift
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
//
|
||||||
|
// UIBarButtonItem+SPAdd.swift
|
||||||
|
// ThimraTV
|
||||||
|
//
|
||||||
|
// Created by 佳尔 on 2025/4/29.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
extension UIBarButtonItem {
|
||||||
|
|
||||||
|
static let sp_normalTitleFont = UIFont.fontRegular(ofSize: 14)
|
||||||
|
static var sp_normalTitleColor: UIColor {
|
||||||
|
get {
|
||||||
|
return UIColor.colorFFFFFF(alpha: 0.5)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
默认标题样式
|
||||||
|
*/
|
||||||
|
static var sp_normalTitleTextAttributes: [NSAttributedString.Key : Any] {
|
||||||
|
get {
|
||||||
|
return [
|
||||||
|
NSAttributedString.Key.font : sp_normalTitleFont,
|
||||||
|
NSAttributedString.Key.foregroundColor : sp_normalTitleColor
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func sp_setTitleTextAttributes(normalAttributes: [NSAttributedString.Key : Any] = UIBarButtonItem.sp_normalTitleTextAttributes) {
|
||||||
|
self.setTitleTextAttributes(normalAttributes, for: .normal)
|
||||||
|
self.setTitleTextAttributes(normalAttributes, for: .highlighted)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
560
ThimraTV/Base/Extension/UIColor+SPAdd.swift
Normal file
@ -0,0 +1,560 @@
|
|||||||
|
//
|
||||||
|
// UIColor+SPAdd.swift
|
||||||
|
// ThimraTV
|
||||||
|
//
|
||||||
|
// Created by 曾觉新 on 2025/4/8.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
extension UIColor {
|
||||||
|
|
||||||
|
static func color(hex: UInt32, alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return UIColor(rgb: hex, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func backgroundColor() -> UIColor {
|
||||||
|
return color121317()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static func themeColor() -> UIColor {
|
||||||
|
return .color121317()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static func placeholderColor() -> UIColor {
|
||||||
|
return .colorFFFFFF(alpha: 0.6)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension UIColor {
|
||||||
|
static func colorFFFFFF(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFFFFFF, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color000000(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x000000, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFF0089(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFF0089, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color7F7F80(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x7F7F80, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorD2D2D2(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xD2D2D2, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorBF6BFF(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xBF6BFF, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color121418(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x121418, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorF564B6(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xF564B6, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorF56490(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xF56490, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color9D9D9D(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x9D9D9D, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color545454(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x545454, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorD568D2(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xD568D2, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color8A899F(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x8A899F, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color888888(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x888888, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color201A1A(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x201A1A, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color828284(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x828284, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color121317(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x121317, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color290D0F(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x290D0F, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color230E11(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x230E11, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color181115(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x181115, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFF5100(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFF5100, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorAFAFAF(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xAFAFAF, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorA8A5AA(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xA8A5AA, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorD9D9D9(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xD9D9D9, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorEAF7FF(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xEAF7FF, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFF4B5A(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFF4B5A, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color1E1F2C(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x1E1F2C, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorE7F5FF(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xE7F5FF, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorAFB8BF(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xAFB8BF, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFF0000(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFF0000, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color1C1A1C(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x1C1A1C, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color621C14(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x621C14, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color5A5C67(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x5A5C67, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color3D4556(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x3D4556, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color1C1C1E(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x1C1C1E, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorEC3324(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xEC3324, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorCCCCCC(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xCCCCCC, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color6D7A8F(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x6D7A8F, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color8B6C6C(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x8B6C6C, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color58484B(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x58484B, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorE6334B(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xE6334B, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color0866FF(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x0866FF, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color333333(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x333333, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorB0B0B3(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xB0B0B3, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorBBB9B3(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xBBB9B3, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFFD791(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFFD791, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color262014(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x262014, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorA69B89(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xA69B89, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFFD28F(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFFD28F, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFFFFC8(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFFFFC8, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorF76359(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xF76359, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFFD5B2(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFFD5B2, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color321704(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x321704, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorF2A3A3(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xF2A3A3, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFEE095(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFEE095, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color0D0807(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x0D0807, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorF2C879(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xF2C879, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color202531(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x202531, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFDE9A6(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFDE9A6, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFFBD39(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFFBD39, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFFAC38(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFFAC38, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color2B2826(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x2B2826, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color100F0B(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x100F0B, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFEE3B5(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFEE3B5, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFCCE7D(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFCCE7D, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color2AAED3(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x2AAED3, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color9CD5E5(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x9CD5E5, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFAFCFE(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFAFCFE, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorCED6FA(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xCED6FA, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color0588DB(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x0588DB, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorA9E1F2(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xA9E1F2, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorF2F4F4(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xF2F4F4, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorC8E1E8(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xC8E1E8, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color6B3308(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x6B3308, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFFB559(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFFB559, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color9F5300(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x9F5300, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color0D4E64(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x0D4E64, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color020926(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x020926, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorEF7301(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xEF7301, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFFCF93(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFFCF93, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFFF0DE(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFFF0DE, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFF1A35(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFF1A35, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFF569C(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFF569C, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFF8E33(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFF8E33, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorB2B2B2(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xB2B2B2, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color8B8B8B(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x8B8B8B, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color272A30(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x272A30, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFF1F1F(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFF1F1F, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFF3232(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFF3232, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color362020(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x362020, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color7A7F96(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x7A7F96, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color967A7A(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x967A7A, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorA8B8C3(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xA8B8C3, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color321F1F(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x321F1F, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFF473D(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFF473D, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color622100(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x622100, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFFC555(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFFC555, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFFC591(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFFC591, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorBC7616(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xBC7616, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color9C9896(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x9C9896, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorCC9251(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xCC9251, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorCA8D3B(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xCA8D3B, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorA36C2D(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xA36C2D, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color412D11(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x412D11, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorD0C0AA(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xD0C0AA, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorF6D8A0(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xF6D8A0, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorDF9F46(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xDF9F46, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color684B2A(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x684B2A, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color9E692C(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x9E692C, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorBE9D70(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xBE9D70, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorF8F1E2(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xF8F1E2, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorEBD5A3(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xEBD5A3, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorAD7433(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xAD7433, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFFC234(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFFC234, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFFDD00(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFFDD00, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color3E23DE(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x3E23DE, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color4629F1(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x4629F1, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color3D1DFF(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x3D1DFF, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorDE2326(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xDE2326, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorF1298A(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xF1298A, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFF1DE8(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFF1DE8, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorD93845(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xD93845, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFF5528(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFF5528, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFF9924(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFF9924, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFFF1D9(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFFF1D9, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color005786(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x005786, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFED095(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFED095, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFFE49E(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFFE49E, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorE9BB68(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xE9BB68, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorFFE18D(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xFFE18D, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorDDA754(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0xDDA754, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func color94550E(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return color(hex: 0x94550E, alpha: alpha)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// UIDevice+SPAdd.swift
|
// UIDevice+SPAdd.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/8.
|
// Created by 曾觉新 on 2025/4/8.
|
||||||
//
|
//
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// UIFont+SPAdd.swift
|
// UIFont+SPAdd.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/8.
|
// Created by 曾觉新 on 2025/4/8.
|
||||||
//
|
//
|
||||||
@ -9,6 +9,18 @@ import UIKit
|
|||||||
|
|
||||||
extension UIFont {
|
extension UIFont {
|
||||||
|
|
||||||
|
static func regularFontName() -> String {
|
||||||
|
return ".AppleSystemUIFont"
|
||||||
|
}
|
||||||
|
|
||||||
|
static func mediumFontName() -> String {
|
||||||
|
return ".AppleSystemUIFontMedium"
|
||||||
|
}
|
||||||
|
|
||||||
|
static func boldFontName() -> String {
|
||||||
|
return ".AppleSystemUIFontBold"
|
||||||
|
}
|
||||||
|
|
||||||
static func fontRegular(ofSize: CGFloat) -> UIFont {
|
static func fontRegular(ofSize: CGFloat) -> UIFont {
|
||||||
return .systemFont(ofSize: ofSize, weight: .regular)
|
return .systemFont(ofSize: ofSize, weight: .regular)
|
||||||
}
|
}
|
||||||
@ -28,4 +40,9 @@ extension UIFont {
|
|||||||
static func fontWeight(ofSize: CGFloat, weight: CGFloat) -> UIFont {
|
static func fontWeight(ofSize: CGFloat, weight: CGFloat) -> UIFont {
|
||||||
return .systemFont(ofSize: ofSize, weight: UIFont.Weight(weight))
|
return .systemFont(ofSize: ofSize, weight: UIFont.Weight(weight))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static func fontInterExtraBold(ofSize: CGFloat) -> UIFont {
|
||||||
|
|
||||||
|
return .init(name: "Inter-ExtraBold", size: ofSize) ?? fontBold(ofSize: ofSize)
|
||||||
|
}
|
||||||
}
|
}
|
32
ThimraTV/Base/Extension/UIImage+SPAdd.swift
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
//
|
||||||
|
// UIImage+SPAdd.swift
|
||||||
|
// ThimraTV
|
||||||
|
//
|
||||||
|
// Created by 长沙佳儿 on 2025/6/18.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
extension UIImage {
|
||||||
|
|
||||||
|
///添加模糊效果
|
||||||
|
func applyBlur() -> UIImage? {
|
||||||
|
let radius = 50.0
|
||||||
|
guard let inputCIImage = CIImage(image: self) else { return nil }
|
||||||
|
|
||||||
|
let filter = CIFilter(name: "CIGaussianBlur")
|
||||||
|
filter?.setValue(inputCIImage, forKey: kCIInputImageKey)
|
||||||
|
filter?.setValue(radius, forKey: kCIInputRadiusKey)
|
||||||
|
|
||||||
|
guard let outputCIImage = filter?.outputImage else { return nil }
|
||||||
|
|
||||||
|
// 必须裁剪模糊后的图像
|
||||||
|
let croppedImage = outputCIImage.cropped(to: inputCIImage.extent)
|
||||||
|
|
||||||
|
let context = CIContext(options: nil)
|
||||||
|
guard let cgImage = context.createCGImage(croppedImage, from: croppedImage.extent) else { return nil }
|
||||||
|
|
||||||
|
return UIImage(cgImage: cgImage)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,16 +1,18 @@
|
|||||||
//
|
//
|
||||||
// UIImageView+SPAdd.swift
|
// UIImageView+SPAdd.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/8.
|
// Created by 曾觉新 on 2025/4/8.
|
||||||
//
|
//
|
||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
import Kingfisher
|
import Kingfisher
|
||||||
|
//import KingfisherWebP
|
||||||
|
|
||||||
extension UIImageView {
|
extension UIImageView {
|
||||||
func sp_setImage(url: String?, placeholder: UIImage? = nil, completer: ((_ image: UIImage?, _ url: URL?) -> Void)? = nil) {
|
func sp_setImage(url: String?, placeholder: UIImage? = nil, completer: ((_ image: UIImage?, _ url: URL?) -> Void)? = nil) {
|
||||||
|
|
||||||
|
// self.kf.setImage(with: URL(string: url ?? ""), placeholder: placeholder, options: [.processor(WebPProcessor.default)]) { result in
|
||||||
self.kf.setImage(with: URL(string: url ?? ""), placeholder: placeholder, options: nil) { result in
|
self.kf.setImage(with: URL(string: url ?? ""), placeholder: placeholder, options: nil) { result in
|
||||||
switch result {
|
switch result {
|
||||||
case .success(let value):
|
case .success(let value):
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// UINavigationBar+SPAdd.swift
|
// UINavigationBar+SPAdd.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/8.
|
// Created by 曾觉新 on 2025/4/8.
|
||||||
//
|
//
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// UINavigationController+SPAdd.swift
|
// UINavigationController+SPAdd.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/8.
|
// Created by 曾觉新 on 2025/4/8.
|
||||||
//
|
//
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// UIScrollView+SPRefresh.swift
|
// UIScrollView+SPRefresh.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/19.
|
// Created by 曾觉新 on 2025/4/19.
|
||||||
//
|
//
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// UIStackView+SPAdd.swift
|
// UIStackView+SPAdd.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/14.
|
// Created by 曾觉新 on 2025/4/14.
|
||||||
//
|
//
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// UIView+SPAdd.swift
|
// UIView+SPAdd.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/9.
|
// Created by 曾觉新 on 2025/4/9.
|
||||||
//
|
//
|
||||||
@ -109,3 +109,30 @@ extension UIView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//MARK: -------------- 添加点击事件 --------------
|
||||||
|
extension UIView {
|
||||||
|
|
||||||
|
private var sp_tapGestureBlock: ((_ view: UIView) -> Void)? {
|
||||||
|
get {
|
||||||
|
return objc_getAssociatedObject(self,&AssociatedKeys.sp_tapGesture) as? ((_ view: UIView) -> Void)
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
objc_setAssociatedObject(self,&AssociatedKeys.sp_tapGesture, newValue, .OBJC_ASSOCIATION_COPY)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func sp_addTapGestureRecognizer(_ block: ((_ view: UIView) -> Void)?) {
|
||||||
|
if sp_tapGestureBlock == nil {
|
||||||
|
let tap = UITapGestureRecognizer(target: self, action: #selector(handleTapGestureRecognizer(tap:)))
|
||||||
|
self.addGestureRecognizer(tap)
|
||||||
|
}
|
||||||
|
self.sp_tapGestureBlock = block
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func handleTapGestureRecognizer(tap: UITapGestureRecognizer) {
|
||||||
|
if tap.state == .recognized {
|
||||||
|
self.sp_tapGestureBlock?(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// SPListModel.swift
|
// SPListModel.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/9.
|
// Created by 曾觉新 on 2025/4/9.
|
||||||
//
|
//
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// SPModel.swift
|
// SPModel.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/8.
|
// Created by 曾觉新 on 2025/4/8.
|
||||||
//
|
//
|
25
ThimraTV/Base/Model/SPOpenAppModel.swift
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
//
|
||||||
|
// SPOpenAppModel.swift
|
||||||
|
// ThimraTV
|
||||||
|
//
|
||||||
|
// Created by 佳尔 on 2025/5/8.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import SmartCodable
|
||||||
|
|
||||||
|
class SPOpenAppModel: SPModel, SmartCodable {
|
||||||
|
|
||||||
|
enum Path: String, SmartCaseDefaultable {
|
||||||
|
case videoDetail = "detail"
|
||||||
|
///反馈列表
|
||||||
|
case feedback = "feedback"
|
||||||
|
///活动
|
||||||
|
case promotion = "promotion"
|
||||||
|
}
|
||||||
|
|
||||||
|
var id: String?
|
||||||
|
var message_id: String?
|
||||||
|
var short_play_id: String?
|
||||||
|
var path: Path?
|
||||||
|
}
|
21
ThimraTV/Base/Networking/API/SPApnsAPI.swift
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
//
|
||||||
|
// SPApnsAPI.swift
|
||||||
|
// ThimraTV
|
||||||
|
//
|
||||||
|
// Created by 佳尔 on 2025/4/30.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class SPApnsAPI: NSObject {
|
||||||
|
static func requestUploadDeviceToken(token: String) {
|
||||||
|
var param = SPNetworkParameters(path: "/customer/firebaseToken")
|
||||||
|
param.parameters = ["fcm_token": token]
|
||||||
|
param.isToast = false
|
||||||
|
|
||||||
|
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<String>) in
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// SPHomeAPI.swift
|
// SPHomeAPI.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/8.
|
// Created by 曾觉新 on 2025/4/8.
|
||||||
//
|
//
|
||||||
@ -37,13 +37,12 @@ class SPHomeAPI: NSObject {
|
|||||||
|
|
||||||
///首页模块接口
|
///首页模块接口
|
||||||
static func requestHomeModuleData(completer: ((_ model: SPHomeModuleModel?) -> Void)?) {
|
static func requestHomeModuleData(completer: ((_ model: SPHomeModuleModel?) -> Void)?) {
|
||||||
let param = SPNetworkParameters(path: "/homeBannerAndNineSquare")
|
var param = SPNetworkParameters(path: "/homeModuleData")
|
||||||
// param.method = .get
|
param.method = .get
|
||||||
|
|
||||||
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<SPHomeModuleModel>) in
|
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<SPHomeModuleModel>) in
|
||||||
completer?(response.data)
|
completer?(response.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///首页列表数据
|
///首页列表数据
|
39
ThimraTV/Base/Networking/API/SPRewardsAPI.swift
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
//
|
||||||
|
// SPRewardsAPI.swift
|
||||||
|
// ThimraTV
|
||||||
|
//
|
||||||
|
// Created by 佳尔 on 2025/4/28.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class SPRewardsAPI: NSObject {
|
||||||
|
///开启通知领金币
|
||||||
|
static func requestUploadOpenNotify(completer: ((_ finish: Bool) -> Void)?) {
|
||||||
|
|
||||||
|
let param = SPNetworkParameters(path: "/openNotify")
|
||||||
|
|
||||||
|
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<String>) in
|
||||||
|
if response.code == SPNetworkCodeSucceed {
|
||||||
|
completer?(true)
|
||||||
|
} else {
|
||||||
|
completer?(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///上传通知状态
|
||||||
|
static func requestUploadNoticeStatus(status: Bool) {
|
||||||
|
var param = SPNetworkParameters(path: "/customer/uploadNoticeStatus")
|
||||||
|
param.isLoding = false
|
||||||
|
param.isToast = false
|
||||||
|
param.parameters = [
|
||||||
|
"is_open_notice" : status ? 1 : 0
|
||||||
|
]
|
||||||
|
|
||||||
|
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<String>) in
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
38
ThimraTV/Base/Networking/API/SPSettingAPI.swift
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
//
|
||||||
|
// SPSettingAPI.swift
|
||||||
|
// ThimraTV
|
||||||
|
//
|
||||||
|
// Created by 佳尔 on 2025/5/10.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class SPSettingAPI: NSObject {
|
||||||
|
|
||||||
|
///获取语言列表
|
||||||
|
static func requestLanguageList(completer: ((_ list: [SPLanguageModel]?) -> Void)?) {
|
||||||
|
|
||||||
|
var param = SPNetworkParameters(path: "/languges")
|
||||||
|
param.method = .get
|
||||||
|
|
||||||
|
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<SPListModel<SPLanguageModel>>) in
|
||||||
|
completer?(response.data?.list)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///获取语言数据
|
||||||
|
static func requestLocalizedData(key: String, completer: ((_ model: SPLocalizedModel?) -> Void)?) {
|
||||||
|
var param = SPNetworkParameters(path: "/translates")
|
||||||
|
param.method = .get
|
||||||
|
param.parameters = [
|
||||||
|
"lang_key" : key
|
||||||
|
]
|
||||||
|
|
||||||
|
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<SPLocalizedModel>) in
|
||||||
|
completer?(response.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
75
ThimraTV/Base/Networking/API/SPStatAPI.swift
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
//
|
||||||
|
// SPStatAPI.swift
|
||||||
|
// ThimraTV
|
||||||
|
//
|
||||||
|
// Created by 佳尔 on 2025/5/8.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
///统计
|
||||||
|
class SPStatAPI: NSObject {
|
||||||
|
|
||||||
|
///进入APP
|
||||||
|
static func requestEnterApp() {
|
||||||
|
|
||||||
|
var param = SPNetworkParameters(path: "/customer/enterTheApp")
|
||||||
|
param.isToast = false
|
||||||
|
param.isLoding = false
|
||||||
|
|
||||||
|
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<String>) in
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///离开APP
|
||||||
|
static func requestLeaveApp() {
|
||||||
|
var param = SPNetworkParameters(path: "/customer/leaveApp")
|
||||||
|
param.isToast = false
|
||||||
|
param.isLoding = false
|
||||||
|
|
||||||
|
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<String>) in
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///在线状态统计
|
||||||
|
static func requestStatOnLine() {
|
||||||
|
var param = SPNetworkParameters(path: "/customer/onLine")
|
||||||
|
param.isToast = false
|
||||||
|
param.isLoding = false
|
||||||
|
|
||||||
|
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<String>) in
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///统计w2a点击
|
||||||
|
static func requestStatW2a(data: String) {
|
||||||
|
var param = SPNetworkParameters(path: "/w2aSelfAttribution")
|
||||||
|
param.isToast = false
|
||||||
|
param.isLoding = false
|
||||||
|
param.parameters = [
|
||||||
|
"data" : data
|
||||||
|
]
|
||||||
|
|
||||||
|
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<String>) in
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///统计点击推送消息
|
||||||
|
static func requestStatApns(messageId: String, title: String) {
|
||||||
|
var param = SPNetworkParameters(path: "/message/sendReport")
|
||||||
|
param.isToast = false
|
||||||
|
param.isLoding = false
|
||||||
|
param.parameters = [
|
||||||
|
"message_id" : messageId,
|
||||||
|
"title" : title
|
||||||
|
]
|
||||||
|
|
||||||
|
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<String>) in
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
60
ThimraTV/Base/Networking/API/SPUserAPI.swift
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
//
|
||||||
|
// SPUserAPI.swift
|
||||||
|
// ThimraTV
|
||||||
|
//
|
||||||
|
// Created by 曾觉新 on 2025/4/18.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class SPUserAPI: NSObject {
|
||||||
|
|
||||||
|
///获取用户信息
|
||||||
|
static func requestUserInfo(completer: ((_ userInfo: SPUserInfo?) -> Void)?) {
|
||||||
|
|
||||||
|
var param = SPNetworkParameters(path: "/customer/info")
|
||||||
|
param.method = .get
|
||||||
|
|
||||||
|
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<SPUserInfo>) in
|
||||||
|
completer?(response.data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///第三方用户登录
|
||||||
|
static func requestThirdLogin(model: SPThirdSignModel, completer: ((_ token: SPTokenModel?) -> Void)?) {
|
||||||
|
|
||||||
|
var param = SPNetworkParameters(path: "/customer/login")
|
||||||
|
param.parameters = model.toDictionary()
|
||||||
|
|
||||||
|
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<SPTokenModel>) in
|
||||||
|
completer?(response.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
///退出登录
|
||||||
|
static func requestSignout(completer: ((_ token: SPTokenModel?) -> Void)?) {
|
||||||
|
var param = SPNetworkParameters(path: "/customer/signout")
|
||||||
|
param.isLoding = true
|
||||||
|
|
||||||
|
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<SPTokenModel>) in
|
||||||
|
completer?(response.data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///注销账户
|
||||||
|
static func requestLogoff(completer: ((_ isFinish: Bool) -> Void)?) {
|
||||||
|
var param = SPNetworkParameters(path: "/customer/logoff")
|
||||||
|
param.isLoding = true
|
||||||
|
|
||||||
|
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<String>) in
|
||||||
|
if response.code == SPNetworkCodeSucceed {
|
||||||
|
completer?(true)
|
||||||
|
} else {
|
||||||
|
completer?(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// SPVideoAPI.swift
|
// SPVideoAPI.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/10.
|
// Created by 曾觉新 on 2025/4/10.
|
||||||
//
|
//
|
||||||
@ -10,17 +10,22 @@ import UIKit
|
|||||||
class SPVideoAPI: NSObject {
|
class SPVideoAPI: NSObject {
|
||||||
|
|
||||||
///获取视频详情
|
///获取视频详情
|
||||||
static func requestVideoDetail(videoId: String?, shortPlayId: String, completer: ((_ model: SPVideoDetailModel?) -> Void)?) {
|
static func requestVideoDetail(videoId: String?, shortPlayId: String, activityId: String? = nil, completer: ((_ model: SPVideoDetailModel?) -> Void)?) {
|
||||||
var parameters: [String : Any] = [
|
var parameters: [String : Any] = [
|
||||||
"short_play_id" : shortPlayId
|
"short_play_id" : shortPlayId
|
||||||
]
|
]
|
||||||
|
|
||||||
if let videoId = videoId {
|
// if let videoId = videoId {
|
||||||
parameters["video_id"] = videoId
|
// }
|
||||||
|
parameters["video_id"] = "0"
|
||||||
|
if let activityId = activityId {
|
||||||
|
parameters["activity_id"] = activityId
|
||||||
}
|
}
|
||||||
|
|
||||||
var param = SPNetworkParameters(path: "/getVideoDetails")
|
var param = SPNetworkParameters(path: "/getVideoDetails")
|
||||||
param.method = .get
|
param.method = .get
|
||||||
param.parameters = parameters
|
param.parameters = parameters
|
||||||
|
param.isLoding = true
|
||||||
|
|
||||||
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<SPVideoDetailModel>) in
|
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<SPVideoDetailModel>) in
|
||||||
completer?(response.data)
|
completer?(response.data)
|
||||||
@ -28,12 +33,12 @@ class SPVideoAPI: NSObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
///创建播放记录
|
///创建播放记录
|
||||||
static func requestRequestVideoPlayHistory(videoId: String, shortPlayId: String) {
|
static func requestCreateVideoPlayHistory(videoId: String?, shortPlayId: String) {
|
||||||
var param = SPNetworkParameters(path: "/createHistory")
|
var param = SPNetworkParameters(path: "/createHistory")
|
||||||
param.isLoding = false
|
param.isLoding = false
|
||||||
param.isToast = false
|
param.isToast = false
|
||||||
param.parameters = [
|
param.parameters = [
|
||||||
"video_id" : videoId,
|
"video_id" : videoId ?? "0",
|
||||||
"short_play_id" : shortPlayId
|
"short_play_id" : shortPlayId
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -42,6 +47,39 @@ class SPVideoAPI: NSObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///视频观看结束
|
||||||
|
static func requestViewingFinish(shortPlayId: String, videoId: String, activityId: String) {
|
||||||
|
var param = SPNetworkParameters(path: "/activeAfterWatchingVideo")
|
||||||
|
param.isLoding = false
|
||||||
|
param.isToast = false
|
||||||
|
param.parameters = [
|
||||||
|
"short_play_video_id" : videoId,
|
||||||
|
"short_play_id" : shortPlayId,
|
||||||
|
"activity_id" : activityId
|
||||||
|
]
|
||||||
|
|
||||||
|
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<String>) in
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///上报播放时长
|
||||||
|
static func requestUploadPlayTime(shortPlayId: String, videoId: String, seconds: Int) {
|
||||||
|
|
||||||
|
var param = SPNetworkParameters(path: "/uploadHistorySeconds")
|
||||||
|
param.isLoding = false
|
||||||
|
param.isToast = false
|
||||||
|
param.parameters = [
|
||||||
|
"video_id" : videoId,
|
||||||
|
"short_play_id" : shortPlayId,
|
||||||
|
"play_seconds" : seconds
|
||||||
|
]
|
||||||
|
|
||||||
|
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<String>) in
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///收藏短剧
|
///收藏短剧
|
||||||
static func requestCollectShort(isCollect: Bool, shortPlayId: String, videoId: String?, success: (() -> Void)?, failure: (() -> Void)? = nil) {
|
static func requestCollectShort(isCollect: Bool, shortPlayId: String, videoId: String?, success: (() -> Void)?, failure: (() -> Void)? = nil) {
|
||||||
let path: String
|
let path: String
|
||||||
@ -114,7 +152,7 @@ class SPVideoAPI: NSObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///获取分类短剧
|
///获取分类短剧
|
||||||
static func requestCategoryShortList(page: Int, id: String, completer: ((_ listModel: SPListModel<SPShortModel>?) -> Void)?) {
|
static func requestCategoryShortList(page: Int, id: String, completer: ((_ listModel: SPListModel<SPShortModel>?) -> Void)?) {
|
||||||
var param = SPNetworkParameters(path: "/videoList")
|
var param = SPNetworkParameters(path: "/videoList")
|
||||||
param.method = .get
|
param.method = .get
|
||||||
@ -128,6 +166,17 @@ class SPVideoAPI: NSObject {
|
|||||||
completer?(response.data)
|
completer?(response.data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///视频推荐
|
||||||
|
static func requestPlayerDetailsRecommand(completer: ((_ list: [SPShortModel]?) -> Void)?) {
|
||||||
|
|
||||||
|
var param = SPNetworkParameters(path: "/getDetailsRecommand")
|
||||||
|
param.method = .get
|
||||||
|
|
||||||
|
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<SPListModel<SPShortModel>>) in
|
||||||
|
completer?(response.data?.list)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension SPVideoAPI {
|
extension SPVideoAPI {
|
125
ThimraTV/Base/Networking/API/SPWalletAPI.swift
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
//
|
||||||
|
// SPWalletAPI.swift
|
||||||
|
// ThimraTV
|
||||||
|
//
|
||||||
|
// Created by 佳尔 on 2025/4/28.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class SPWalletAPI: NSObject {
|
||||||
|
enum BuyType: String {
|
||||||
|
case coins = "coins"
|
||||||
|
case vip = "vip"
|
||||||
|
}
|
||||||
|
|
||||||
|
///获取支付模版
|
||||||
|
static func requestPayTemplate(completer: ((_ model: SPPayTemplateModel?) -> Void)?) {
|
||||||
|
var param = SPNetworkParameters(path: "/paySettingsV3")
|
||||||
|
param.method = .get
|
||||||
|
|
||||||
|
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<SPPayTemplateModel>) in
|
||||||
|
completer?(response.data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///创建内购订单
|
||||||
|
static func requestCreateOrder(payId: String, shortPlayId: String, videoId: String, completer: ((_ orderModel: SPIAPOrderModel?) -> Void)?) {
|
||||||
|
var param = SPNetworkParameters(path: "/createOrder")
|
||||||
|
param.isToast = false
|
||||||
|
param.parameters = [
|
||||||
|
"payment_channel" : "apple",
|
||||||
|
"short_play_id" : shortPlayId,
|
||||||
|
"video_id" : videoId,
|
||||||
|
"pay_setting_id" : payId
|
||||||
|
]
|
||||||
|
|
||||||
|
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<SPIAPOrderModel>) in
|
||||||
|
if let message = response.data?.message, message.count > 0 {
|
||||||
|
if response.data?.code == 30007 {
|
||||||
|
SPToast.show(text: "movia_member_toast_01".localized)
|
||||||
|
} else {
|
||||||
|
SPToast.show(text: message)
|
||||||
|
}
|
||||||
|
|
||||||
|
completer?(nil)
|
||||||
|
} else {
|
||||||
|
completer?(response.data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///校验内购
|
||||||
|
static func requestVerifyOrder(orderCode: String, payId: String, productId: String, purchaseToken: String, completer: ((_ model: SPIAPVerifyModel?) -> Void)?) {
|
||||||
|
var param = SPNetworkParameters(path: "/applePaid")
|
||||||
|
param.parameters = [
|
||||||
|
"order_code" : orderCode,
|
||||||
|
"pay_setting_id" : payId,
|
||||||
|
"pkg_name" : kSPAPPBundleIdentifier,
|
||||||
|
"transaction_id" : productId,
|
||||||
|
"purchases_token" : purchaseToken
|
||||||
|
]
|
||||||
|
|
||||||
|
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<SPIAPVerifyModel>) in
|
||||||
|
completer?(response.data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///赠币记录
|
||||||
|
static func reuqestSendCoinRecord(page: Int, completer: ((_ listModel: SPListModel<SPRewardCoinsRecordModel>?) -> Void)?) {
|
||||||
|
|
||||||
|
var param = SPNetworkParameters(path: "/sendCoinList")
|
||||||
|
param.parameters = [
|
||||||
|
"page_size" : 20,
|
||||||
|
"current_page" : page
|
||||||
|
]
|
||||||
|
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<SPListModel<SPRewardCoinsRecordModel>>) in
|
||||||
|
completer?(response.data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///充值记录
|
||||||
|
static func requestRechargeRecord(buyType: BuyType, page: Int, completer: ((_ listModel: SPListModel<SPRechargeRecordModel>?) -> Void)?) {
|
||||||
|
var param = SPNetworkParameters(path: "/getCustomerOrder")
|
||||||
|
param.method = .get
|
||||||
|
param.parameters = [
|
||||||
|
"page_size" : 20,
|
||||||
|
"current_page" : page,
|
||||||
|
"buy_type" : buyType.rawValue
|
||||||
|
]
|
||||||
|
|
||||||
|
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<SPListModel<SPRechargeRecordModel>>) in
|
||||||
|
completer?(response.data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///消费购买记录
|
||||||
|
static func requestBuyRecords(page: Int, completer: ((_ listModel: SPListModel<SPBuyRecordsModel>?) -> Void)?) {
|
||||||
|
var param = SPNetworkParameters(path: "/getCustomerBuyRecords")
|
||||||
|
param.method = .get
|
||||||
|
param.parameters = [
|
||||||
|
"page_size" : 20,
|
||||||
|
"current_page" : page,
|
||||||
|
]
|
||||||
|
|
||||||
|
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<SPListModel<SPBuyRecordsModel>>) in
|
||||||
|
completer?(response.data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///金币解锁视频
|
||||||
|
static func requestCoinUnlockVideo(shortPlayId: String, videoId: String, completer: ((_ model: SPVideoUnlockModel?) -> Void)?) {
|
||||||
|
|
||||||
|
var param = SPNetworkParameters(path: "/buy_video")
|
||||||
|
param.isLoding = true
|
||||||
|
param.parameters = [
|
||||||
|
"short_play_id" : shortPlayId,
|
||||||
|
"video_id" : videoId,
|
||||||
|
]
|
||||||
|
|
||||||
|
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<SPVideoUnlockModel>) in
|
||||||
|
completer?(response.data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// SPApi.swift
|
// SPApi.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/8.
|
// Created by 曾觉新 on 2025/4/8.
|
||||||
//
|
//
|
||||||
@ -87,7 +87,7 @@ extension SPApi: TargetType {
|
|||||||
// "device-id" : JXUUID.systemUUID(), //设备id
|
// "device-id" : JXUUID.systemUUID(), //设备id
|
||||||
"device-id" : JXUUID.uuid(), //设备id
|
"device-id" : JXUUID.uuid(), //设备id
|
||||||
"brand" : "apple", //品牌
|
"brand" : "apple", //品牌
|
||||||
"app-name" : "",
|
"app-name" : kSPAPPBundleIdentifier,
|
||||||
"system-type" : "ios",
|
"system-type" : "ios",
|
||||||
"idfa" : JXUUID.idfa(),
|
"idfa" : JXUUID.idfa(),
|
||||||
"model" : UIDevice.sp_machineModelName(),
|
"model" : UIDevice.sp_machineModelName(),
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// SPCryptService.swift
|
// SPCryptService.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/10.
|
// Created by 曾觉新 on 2025/4/10.
|
||||||
//
|
//
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// SPNetwork.swift
|
// SPNetwork.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/8.
|
// Created by 曾觉新 on 2025/4/8.
|
||||||
//
|
//
|
||||||
@ -76,12 +76,21 @@ class SPNetwork: NSObject {
|
|||||||
var res = SPNetworkResponse<T>()
|
var res = SPNetworkResponse<T>()
|
||||||
res.code = -1
|
res.code = -1
|
||||||
if parameters.isToast {
|
if parameters.isToast {
|
||||||
SPToast.show(text: "Error".localized)
|
SPToast.show(text: "movia_error".localized)
|
||||||
}
|
}
|
||||||
completion?(res)
|
completion?(res)
|
||||||
} else {
|
} else {
|
||||||
|
if code == 402, parameters.isToast {
|
||||||
|
SPToast.show(text: "movia_network_toast_02".localized)
|
||||||
|
}
|
||||||
///重新获取token
|
///重新获取token
|
||||||
self.requestToken(completer: nil)
|
self.requestToken { token in
|
||||||
|
if token != nil {
|
||||||
|
SPLoginManager.manager.updateUserInfo(completer: nil)
|
||||||
|
SPStatAPI.requestEnterApp()
|
||||||
|
SPStatAPI.requestStatOnLine()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///将请求失败数据重新请求
|
///将请求失败数据重新请求
|
||||||
if let tokenOperation = self.tokenOperation, parameters.path != "/customer/register" {
|
if let tokenOperation = self.tokenOperation, parameters.path != "/customer/register" {
|
||||||
@ -128,7 +137,7 @@ class SPNetwork: NSObject {
|
|||||||
var res = SPNetworkResponse<T>()
|
var res = SPNetworkResponse<T>()
|
||||||
res.code = -1
|
res.code = -1
|
||||||
if parameters.isToast {
|
if parameters.isToast {
|
||||||
SPToast.show(text: "Error".localized)
|
SPToast.show(text: "movia_error".localized)
|
||||||
}
|
}
|
||||||
completion?(res)
|
completion?(res)
|
||||||
}
|
}
|
||||||
@ -137,7 +146,7 @@ class SPNetwork: NSObject {
|
|||||||
var res = SPNetworkResponse<T>()
|
var res = SPNetworkResponse<T>()
|
||||||
res.code = -1
|
res.code = -1
|
||||||
if parameters.isToast {
|
if parameters.isToast {
|
||||||
SPToast.show(text: "Error".localized)
|
SPToast.show(text: "movia_network_toast_01".localized)
|
||||||
}
|
}
|
||||||
completion?(res)
|
completion?(res)
|
||||||
break
|
break
|
||||||
@ -162,7 +171,7 @@ class SPNetwork: NSObject {
|
|||||||
} else {
|
} else {
|
||||||
var response = SPNetworkResponse<T>()
|
var response = SPNetworkResponse<T>()
|
||||||
response.code = -1
|
response.code = -1
|
||||||
response.msg = "Error".localized
|
response.msg = "movia_error".localized
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// SPNetworkReachabilityManager.swift
|
// SPNetworkReachabilityManager.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by Overseas on 2025/4/19.
|
// Created by Overseas on 2025/4/19.
|
||||||
//
|
//
|
||||||
@ -54,16 +54,24 @@ class SPNetworkReachabilityManager {
|
|||||||
if path.status == .satisfied {
|
if path.status == .satisfied {
|
||||||
if self.isReachable == false {
|
if self.isReachable == false {
|
||||||
print("++++++有网")
|
print("++++++有网")
|
||||||
NotificationCenter.default.post(name: SPNetworkReachabilityManager.reachabilityDidChangeNotification, object: nil)
|
self.isReachable = true
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
NotificationCenter.default.post(name: SPNetworkReachabilityManager.reachabilityDidChangeNotification, object: nil)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.isReachable = true
|
||||||
}
|
}
|
||||||
self.isReachable = true
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if self.isReachable == true {
|
if self.isReachable == true {
|
||||||
print("++++++无网")
|
print("++++++无网")
|
||||||
NotificationCenter.default.post(name: SPNetworkReachabilityManager.reachabilityDidChangeNotification, object: nil)
|
self.isReachable = false
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
NotificationCenter.default.post(name: SPNetworkReachabilityManager.reachabilityDidChangeNotification, object: nil)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.isReachable = false
|
||||||
}
|
}
|
||||||
self.isReachable = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if path.usesInterfaceType(.wifi) {
|
// if path.usesInterfaceType(.wifi) {
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// SPURLPath.swift
|
// SPURLPath.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/8.
|
// Created by 曾觉新 on 2025/4/8.
|
||||||
//
|
//
|
||||||
@ -17,16 +17,16 @@ import UIKit
|
|||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
let SPBaseURL = "https://api-thimratv.thimratv.com"
|
let SPBaseURL = "https://api-thimratv.thimratv.com"
|
||||||
let SPURLPathPrefix = "/0a2c5b02"
|
let SPURLPathPrefix = "/93f03506"
|
||||||
|
|
||||||
let SPWebBaseURL = "https://www.thimratv.com"
|
let SPWebBaseURL = "https://www.thimratv.com"
|
||||||
let SPCampaignWebURL = "https://campaign.thimratv.com"
|
let SPCampaignWebURL = "https://campaign.moviatv.com"
|
||||||
#else
|
#else
|
||||||
let SPBaseURL = "https://api-thimratv.thimratv.com"
|
let SPBaseURL = "https://api-thimratv.thimratv.com"
|
||||||
let SPURLPathPrefix = "/0a2c5b02"
|
let SPURLPathPrefix = "/93f03506"
|
||||||
|
|
||||||
let SPWebBaseURL = "https://www.thimratv.com"
|
let SPWebBaseURL = "https://www.thimratv.com"
|
||||||
let SPCampaignWebURL = "https://campaign.thimratv.com"
|
let SPCampaignWebURL = "https://campaign.moviatv.com"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -42,6 +42,8 @@ let SPInformationSharingWebUrl = SPWebBaseURL + "/information_sharing"
|
|||||||
let SPPersoInforDisclosureWebUrl = SPWebBaseURL + "/persoInfor_disclosure"
|
let SPPersoInforDisclosureWebUrl = SPWebBaseURL + "/persoInfor_disclosure"
|
||||||
///全国青少年互联网文明公约
|
///全国青少年互联网文明公约
|
||||||
let SPCivizatioConventionWebUrl = SPWebBaseURL + "/civizatio_convention"
|
let SPCivizatioConventionWebUrl = SPWebBaseURL + "/civizatio_convention"
|
||||||
|
///会员服务协议
|
||||||
|
let SPMemberShipAgreement = SPWebBaseURL + "/member_ship_agreement"
|
||||||
|
|
||||||
///反馈首页
|
///反馈首页
|
||||||
let SPFeedBackHomeWebUrl = SPCampaignWebURL + "/pages/leave/index"
|
let SPFeedBackHomeWebUrl = SPCampaignWebURL + "/pages/leave/index"
|
||||||
@ -49,5 +51,7 @@ let SPFeedBackHomeWebUrl = SPCampaignWebURL + "/pages/leave/index"
|
|||||||
let SPFeedBackListWebUrl = SPCampaignWebURL + "/pages/leave/list"
|
let SPFeedBackListWebUrl = SPCampaignWebURL + "/pages/leave/list"
|
||||||
///反馈详情
|
///反馈详情
|
||||||
let SPFeedBackDetailWebUrl = SPCampaignWebURL + "/pages/leave/detail"
|
let SPFeedBackDetailWebUrl = SPCampaignWebURL + "/pages/leave/detail"
|
||||||
|
///活动页面
|
||||||
|
let SPRewardsWebUrl = SPCampaignWebURL + "/pages/reward/theme2"
|
||||||
|
|
||||||
|
|
163
ThimraTV/Base/View/SPApnsAlertView.swift
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
//
|
||||||
|
// SPApnsAlertView.swift
|
||||||
|
// ThimraTV
|
||||||
|
//
|
||||||
|
// Created by 佳尔 on 2025/5/9.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class SPApnsAlertView: UIView {
|
||||||
|
|
||||||
|
//MARK: UI属性
|
||||||
|
private lazy var contentView: UIView = {
|
||||||
|
let view = UIView()
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var bgView: UIView = {
|
||||||
|
let imageView = UIImageView(image: UIImage(named: "alert_bg_image_01"))
|
||||||
|
imageView.isUserInteractionEnabled = true
|
||||||
|
return imageView
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var iconImageView: UIImageView = {
|
||||||
|
let imageView = UIImageView(image: UIImage(named: "message_icon_01"))
|
||||||
|
return imageView
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var titleLabel: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.font = .fontMedium(ofSize: 20)
|
||||||
|
label.textColor = .colorFFFFFF()
|
||||||
|
label.text = "movia_open_notification".localized
|
||||||
|
label.textAlignment = .center
|
||||||
|
label.numberOfLines = 0
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var textLabel: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.textColor = .colorA8B8C3()
|
||||||
|
label.font = .fontRegular(ofSize: 14)
|
||||||
|
label.text = "movia_open_notification_info".localized
|
||||||
|
label.textAlignment = .center
|
||||||
|
label.numberOfLines = 0
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var laterButton: UIButton = {
|
||||||
|
let button = UIButton(type: .custom)
|
||||||
|
button.setTitle("movia_open_notification_later".localized, for: .normal)
|
||||||
|
button.titleLabel?.font = .fontMedium(ofSize: 16)
|
||||||
|
button.setTitleColor(.colorFF3232(), for: .normal)
|
||||||
|
button.addTarget(self, action: #selector(handleLaterButton), for: .touchUpInside)
|
||||||
|
return button
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var allowButton: UIButton = {
|
||||||
|
let button = UIButton(type: .custom)
|
||||||
|
button.setTitle("movia_allow".localized, for: .normal)
|
||||||
|
button.titleLabel?.font = .fontMedium(ofSize: 16)
|
||||||
|
button.setTitleColor(.colorFFFFFF(), for: .normal)
|
||||||
|
button.layer.cornerRadius = 21
|
||||||
|
button.layer.masksToBounds = true
|
||||||
|
button.backgroundColor = .colorFF3232()
|
||||||
|
button.addTarget(self, action: #selector(handleAllowButton), for: .touchUpInside)
|
||||||
|
return button
|
||||||
|
}()
|
||||||
|
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
super.init(frame: frame)
|
||||||
|
backgroundColor = .color000000(alpha: 0.8)
|
||||||
|
|
||||||
|
_setupUI()
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func show() {
|
||||||
|
guard let view = SPAPPTool.getKeyWindow() else { return }
|
||||||
|
|
||||||
|
view.addSubview(self)
|
||||||
|
|
||||||
|
self.snp.makeConstraints { make in
|
||||||
|
make.edges.equalToSuperview()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func handleLaterButton() {
|
||||||
|
self.removeFromSuperview()
|
||||||
|
AppDelegate.haveBeenShownAPNS = true
|
||||||
|
SPAPPTool.sceneDelegate?.retryHandleOpenAppMessage()
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func handleAllowButton() {
|
||||||
|
AppDelegate.haveBeenShownAPNS = true
|
||||||
|
self.removeFromSuperview()
|
||||||
|
SPAPPTool.openApnsSetting()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SPApnsAlertView {
|
||||||
|
private func _setupUI() {
|
||||||
|
addSubview(contentView)
|
||||||
|
contentView.addSubview(bgView)
|
||||||
|
bgView.addSubview(iconImageView)
|
||||||
|
bgView.addSubview(titleLabel)
|
||||||
|
bgView.addSubview(textLabel)
|
||||||
|
bgView.addSubview(laterButton)
|
||||||
|
bgView.addSubview(allowButton)
|
||||||
|
|
||||||
|
|
||||||
|
contentView.snp.makeConstraints { make in
|
||||||
|
make.centerX.equalToSuperview()
|
||||||
|
make.centerY.equalToSuperview()
|
||||||
|
make.left.equalToSuperview().offset(26)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bgView.snp.makeConstraints { make in
|
||||||
|
make.left.right.top.equalToSuperview()
|
||||||
|
// make.height.equalTo(284)
|
||||||
|
make.bottom.equalToSuperview()
|
||||||
|
}
|
||||||
|
|
||||||
|
iconImageView.snp.makeConstraints { make in
|
||||||
|
make.centerX.equalToSuperview()
|
||||||
|
make.top.equalToSuperview().offset(9)
|
||||||
|
}
|
||||||
|
|
||||||
|
titleLabel.snp.makeConstraints { make in
|
||||||
|
make.centerX.equalToSuperview()
|
||||||
|
make.top.equalTo(iconImageView.snp.bottom).offset(15)
|
||||||
|
make.right.lessThanOrEqualToSuperview().offset(-30)
|
||||||
|
}
|
||||||
|
|
||||||
|
textLabel.snp.makeConstraints { make in
|
||||||
|
make.centerX.equalToSuperview()
|
||||||
|
make.top.equalTo(titleLabel.snp.bottom).offset(19)
|
||||||
|
make.right.lessThanOrEqualToSuperview().offset(-30)
|
||||||
|
}
|
||||||
|
|
||||||
|
laterButton.snp.makeConstraints { make in
|
||||||
|
make.left.equalToSuperview().offset(33)
|
||||||
|
make.top.equalTo(textLabel.snp.bottom).offset(28)
|
||||||
|
make.height.equalTo(42)
|
||||||
|
}
|
||||||
|
|
||||||
|
allowButton.snp.makeConstraints { make in
|
||||||
|
make.right.equalToSuperview().offset(-33)
|
||||||
|
make.left.equalTo(laterButton.snp.right).offset(13)
|
||||||
|
make.width.height.top.equalTo(laterButton)
|
||||||
|
make.bottom.equalToSuperview().offset(-32)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// SPCollectionView.swift
|
// SPCollectionView.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/9.
|
// Created by 曾觉新 on 2025/4/9.
|
||||||
//
|
//
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// SPCollectionViewCell.swift
|
// SPCollectionViewCell.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/9.
|
// Created by 曾觉新 on 2025/4/9.
|
||||||
//
|
//
|
53
ThimraTV/Base/View/SPFadeEdgeImageView.swift
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
//
|
||||||
|
// SPFadeEdgeImageView.swift
|
||||||
|
// ThimraTV
|
||||||
|
//
|
||||||
|
// Created by 佳尔 on 2025/4/28.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class SPFadeEdgeImageView: UIImageView {
|
||||||
|
|
||||||
|
|
||||||
|
private var blurredImage: UIImage?
|
||||||
|
|
||||||
|
override func layoutSubviews() {
|
||||||
|
super.layoutSubviews()
|
||||||
|
|
||||||
|
applyCircularFade()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 给当前视图添加一个圆形渐隐遮罩
|
||||||
|
func applyCircularFade(radius: CGFloat? = nil) {
|
||||||
|
let maskLayer = CALayer()
|
||||||
|
maskLayer.frame = bounds
|
||||||
|
|
||||||
|
// 渲染一个径向渐变图像
|
||||||
|
UIGraphicsBeginImageContextWithOptions(bounds.size, false, 0)
|
||||||
|
guard let ctx = UIGraphicsGetCurrentContext() else { return }
|
||||||
|
|
||||||
|
let center = CGPoint(x: bounds.midX, y: bounds.midY)
|
||||||
|
let maxRadius = radius ?? min(bounds.width, bounds.height) / 2
|
||||||
|
|
||||||
|
let colorSpace = CGColorSpaceCreateDeviceGray()
|
||||||
|
let colors: [CGFloat] = [1, 1, 0, 0] // 中心透明度1,边缘透明度0
|
||||||
|
let locations: [CGFloat] = [0, 1]
|
||||||
|
|
||||||
|
if let gradient = CGGradient(colorSpace: colorSpace, colorComponents: colors, locations: locations, count: 2) {
|
||||||
|
ctx.drawRadialGradient(
|
||||||
|
gradient,
|
||||||
|
startCenter: center, startRadius: 0,
|
||||||
|
endCenter: center, endRadius: maxRadius,
|
||||||
|
options: .drawsAfterEndLocation
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
let maskImage = UIGraphicsGetImageFromCurrentImageContext()?.cgImage
|
||||||
|
UIGraphicsEndImageContext()
|
||||||
|
|
||||||
|
maskLayer.contents = maskImage
|
||||||
|
self.layer.mask = maskLayer
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
53
ThimraTV/Base/View/SPGradientLabel.swift
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
//
|
||||||
|
// SPGradientLabel.swift
|
||||||
|
// ThimraTV
|
||||||
|
//
|
||||||
|
// Created by 佳尔 on 2025/4/27.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class SPGradientLabel: UILabel {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private(set) var gradientLayer: CAGradientLayer = {
|
||||||
|
// 创建渐变层
|
||||||
|
let gradient = CAGradientLayer()
|
||||||
|
gradient.colors = [
|
||||||
|
UIColor.red.cgColor,
|
||||||
|
UIColor.blue.cgColor
|
||||||
|
]
|
||||||
|
gradient.startPoint = CGPoint(x: 0.5, y: 0)
|
||||||
|
gradient.endPoint = CGPoint(x: 0.5, y: 1)
|
||||||
|
gradient.locations = [0, 1]
|
||||||
|
return gradient
|
||||||
|
}()
|
||||||
|
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
super.init(frame: frame)
|
||||||
|
layer.addSublayer(gradientLayer)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override func layoutSubviews() {
|
||||||
|
super.layoutSubviews()
|
||||||
|
|
||||||
|
gradientLayer.frame = bounds
|
||||||
|
|
||||||
|
// 创建一个文字图层
|
||||||
|
let textLayer = CATextLayer()
|
||||||
|
textLayer.string = attributedText ?? NSAttributedString(string: text ?? "")
|
||||||
|
textLayer.frame = bounds
|
||||||
|
textLayer.alignmentMode = .center
|
||||||
|
textLayer.contentsScale = UIScreen.main.scale
|
||||||
|
|
||||||
|
gradientLayer.mask = textLayer
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// SPGradientView.swift
|
// SPGradientView.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/14.
|
// Created by 曾觉新 on 2025/4/14.
|
||||||
//
|
//
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// SPImageView.swift
|
// SPImageView.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/9.
|
// Created by 曾觉新 on 2025/4/9.
|
||||||
//
|
//
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// SPScrollView.swift
|
// SPScrollView.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/17.
|
// Created by 曾觉新 on 2025/4/17.
|
||||||
//
|
//
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// SPTableView.swift
|
// SPTableView.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/14.
|
// Created by 曾觉新 on 2025/4/14.
|
||||||
//
|
//
|
||||||
@ -13,7 +13,8 @@ class SPTableView: UITableView {
|
|||||||
|
|
||||||
override init(frame: CGRect, style: UITableView.Style) {
|
override init(frame: CGRect, style: UITableView.Style) {
|
||||||
super.init(frame: frame, style: style)
|
super.init(frame: frame, style: style)
|
||||||
// separatorColor = .lineColor()
|
separatorColor = .colorFFFFFF(alpha: 0.1)
|
||||||
|
separatorInset = .init(top: 0, left: 16, bottom: 0, right: 16)
|
||||||
self.backgroundColor = .clear
|
self.backgroundColor = .clear
|
||||||
self.contentInsetAdjustmentBehavior = .never
|
self.contentInsetAdjustmentBehavior = .never
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// SPTableViewCell.swift
|
// SPTableViewCell.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/14.
|
// Created by 曾觉新 on 2025/4/14.
|
||||||
//
|
//
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// SPTextField.swift
|
// SPTextField.swift
|
||||||
// MoviaBox
|
// ThimraTV
|
||||||
//
|
//
|
||||||
// Created by 曾觉新 on 2025/4/17.
|
// Created by 曾觉新 on 2025/4/17.
|
||||||
//
|
//
|