Compare commits

..

6 Commits
main ... 1.0.0

Author SHA1 Message Date
zeng
c6f05b73a1 修复静音没有声音bug 2025-04-27 17:07:22 +08:00
zeng
f87d98c703 搜索bug修复 2025-04-27 16:47:00 +08:00
zeng
24b57a88f6 删除非必要代码 2025-04-27 16:43:01 +08:00
zeng
17068cb7e4 删除facebook库 2025-04-27 15:26:38 +08:00
zeng
6e9f640f95 1.0发布修改 2025-04-27 15:24:34 +08:00
zeng
8bb7aac8d1 1.0版本修改 2025-04-27 13:49:13 +08:00
724 changed files with 2074 additions and 17140 deletions

3
.gitignore vendored
View File

@ -66,7 +66,7 @@ xcuserdata/
## Playgrounds ## Playgrounds
timeline.xctimeline timeline.xctimeline
*.xcworkspace playground.xcworkspace
# Swift Package Manager # Swift Package Manager
# #
@ -89,7 +89,6 @@ timeline.xctimeline
# 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

View File

@ -1,41 +0,0 @@
Thimra 开发者账号信息
认证人 :陈佳
认证设备 Mac min
设备型号 MU9D3CH/A
序列号 TVJJ97WWHH
手机号码 190 7319 2960
企业邮箱 thimra@thimratv.com 密码9oldpGT_y0qR
D-U-N-S457012112
公司主体 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

View File

@ -0,0 +1,449 @@
// !$*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 */;
}

View File

@ -2,7 +2,7 @@
<Workspace <Workspace
version = "1.0"> version = "1.0">
<FileRef <FileRef
location = "group:ThimraTV.xcodeproj"> location = "group:MoviaBox.xcodeproj">
</FileRef> </FileRef>
<FileRef <FileRef
location = "group:Pods/Pods.xcodeproj"> location = "group:Pods/Pods.xcodeproj">

View File

@ -1,6 +1,6 @@
// //
// AppDelegate+Config.swift // AppDelegate+Config.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/8. // Created by on 2025/4/8.
// //
@ -17,8 +17,6 @@ extension AppDelegate {
SPToast.config() SPToast.config()
SPHUD.config() SPHUD.config()
UIBarButtonItem.appearance().sp_setTitleTextAttributes()
} }
@ -72,6 +70,8 @@ extension AppDelegate {
if #available(iOS 15.0, *) { if #available(iOS 15.0, *) {
tabBar.scrollEdgeAppearance = appearance tabBar.scrollEdgeAppearance = appearance
} }
} }
} }

View File

@ -0,0 +1,28 @@
//
// AppDelegate+OpenApp.swift
// MoviaBox
//
// Created by on 2025/4/25.
//
import UIKit
extension SceneDelegate {
///URLAPP
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)
}
}

View File

@ -1,6 +1,6 @@
// //
// AppDelegate.swift // AppDelegate.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/8. // Created by on 2025/4/8.
// //
@ -13,24 +13,18 @@ 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
// SPLoginManager.manager.requestVisitorLogin(completer: nil) SPNetworkReachabilityManager.manager.startMonitoring()
SPLoginManager.manager.updateUserInfo(completer: nil)
///
registerAPNS()
return true return true
} }
@ -52,8 +46,7 @@ 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)
} }
} }

View File

@ -0,0 +1,55 @@
//
// 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.
}
}

View File

@ -1,6 +1,6 @@
// //
// SPNavigationController.swift // SPNavigationController.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/8. // Created by on 2025/4/8.
// //

View File

@ -1,12 +1,11 @@
// //
// SPTabBarController.swift // SPTabBarController.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/8. // Created by on 2025/4/8.
// //
import UIKit import UIKit
import WebKit
class SPTabBarController: UITabBarController { class SPTabBarController: UITabBarController {
@ -14,18 +13,15 @@ class SPTabBarController: UITabBarController {
super.viewDidLoad() super.viewDidLoad()
self.view.backgroundColor = .backgroundColor() self.view.backgroundColor = .backgroundColor()
let nav1 = createNavigationController(viewController: SPHomeViewController(), title: "movia_home".localized, image: UIImage(named: "tabbar_icon_01"), selectedImage: UIImage(named: "tabbar_icon_01_selected")) let nav1 = createNavigationController(viewController: SPHomeViewController(), title: "Home".localized, image: UIImage(named: "tabbar_icon_01"), selectedImage: UIImage(named: "tabbar_icon_01_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 nav2 = createNavigationController(viewController: SPExplorePageController(), title: "For You".localized, image: UIImage(named: "tabbar_icon_02"), selectedImage: UIImage(named: "tabbar_icon_02_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: SPMyListViewController(), title: "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]
} }
@ -61,21 +57,6 @@ 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 {

View File

@ -1,6 +1,6 @@
// //
// SPViewController.swift // SPViewController.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/8. // Created by on 2025/4/8.
// //
@ -22,7 +22,6 @@ 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"))
@ -30,12 +29,6 @@ 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()
@ -84,7 +77,6 @@ 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) {
@ -127,24 +119,6 @@ class SPViewController: UIViewController, JYPageChildContollerProtocol {
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()
}
} }
extension UIViewController { extension UIViewController {
@ -204,7 +178,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 {

View File

@ -1,6 +1,6 @@
// //
// SPDefine.swift // SPDefine.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/8. // Created by on 2025/4/8.
// //

View File

@ -0,0 +1,14 @@
//
// SPUserDefaultsKey.swift
// MoviaBox
//
// Created by on 2025/4/9.
//
import UIKit
///
let kSPLoginTokenDefaultsKey = "kSPLoginTokenDefaultsKey"
///
let kSPHomeSearchHistoryDefaultsKey = "kSPHomeSearchHistoryDefaultsKey"

View File

@ -1,6 +1,6 @@
// //
// CGMutablePath+SPAdd.swift // CGMutablePath+SPAdd.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/14. // Created by on 2025/4/14.
// //

View File

@ -1,6 +1,6 @@
// //
// Dictionary+SPAdd.swift // Dictionary+SPAdd.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/25. // Created by on 2025/4/25.
// //

View File

@ -1,6 +1,6 @@
// //
// Int+SPAdd.swift // Int+SPAdd.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/17. // Created by on 2025/4/17.
// //

View File

@ -1,6 +1,6 @@
// //
// String+SPAdd.swift // String+SPAdd.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/8. // Created by on 2025/4/8.
// //
@ -25,31 +25,6 @@ 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 {

View File

@ -0,0 +1,228 @@
//
// 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)
}
}

View File

@ -1,6 +1,6 @@
// //
// UIDevice+SPAdd.swift // UIDevice+SPAdd.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/8. // Created by on 2025/4/8.
// //

View File

@ -1,6 +1,6 @@
// //
// UIFont+SPAdd.swift // UIFont+SPAdd.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/8. // Created by on 2025/4/8.
// //
@ -9,18 +9,6 @@ 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)
} }
@ -40,9 +28,4 @@ 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)
}
} }

View File

@ -1,18 +1,16 @@
// //
// UIImageView+SPAdd.swift // UIImageView+SPAdd.swift
// ThimraTV // MoviaBox
// //
// 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):

View File

@ -1,6 +1,6 @@
// //
// UINavigationBar+SPAdd.swift // UINavigationBar+SPAdd.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/8. // Created by on 2025/4/8.
// //

View File

@ -1,6 +1,6 @@
// //
// UINavigationController+SPAdd.swift // UINavigationController+SPAdd.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/8. // Created by on 2025/4/8.
// //

View File

@ -1,6 +1,6 @@
// //
// UIScrollView+SPRefresh.swift // UIScrollView+SPRefresh.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/19. // Created by on 2025/4/19.
// //

View File

@ -1,6 +1,6 @@
// //
// UIStackView+SPAdd.swift // UIStackView+SPAdd.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/14. // Created by on 2025/4/14.
// //

View File

@ -1,6 +1,6 @@
// //
// UIView+SPAdd.swift // UIView+SPAdd.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/9. // Created by on 2025/4/9.
// //
@ -109,30 +109,3 @@ 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)
}
}
}

View File

@ -1,6 +1,6 @@
// //
// SPListModel.swift // SPListModel.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/9. // Created by on 2025/4/9.
// //

View File

@ -1,6 +1,6 @@
// //
// SPModel.swift // SPModel.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/8. // Created by on 2025/4/8.
// //

View File

@ -1,6 +1,6 @@
// //
// SPHomeAPI.swift // SPHomeAPI.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/8. // Created by on 2025/4/8.
// //
@ -37,12 +37,13 @@ class SPHomeAPI: NSObject {
/// ///
static func requestHomeModuleData(completer: ((_ model: SPHomeModuleModel?) -> Void)?) { static func requestHomeModuleData(completer: ((_ model: SPHomeModuleModel?) -> Void)?) {
var param = SPNetworkParameters(path: "/homeModuleData") let param = SPNetworkParameters(path: "/homeBannerAndNineSquare")
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)
} }
} }
/// ///

View File

@ -0,0 +1,23 @@
//
// 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)
}
}
}

View File

@ -1,6 +1,6 @@
// //
// SPVideoAPI.swift // SPVideoAPI.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/10. // Created by on 2025/4/10.
// //
@ -10,22 +10,17 @@ import UIKit
class SPVideoAPI: NSObject { class SPVideoAPI: NSObject {
/// ///
static func requestVideoDetail(videoId: String?, shortPlayId: String, activityId: String? = nil, completer: ((_ model: SPVideoDetailModel?) -> Void)?) { static func requestVideoDetail(videoId: String?, shortPlayId: String, 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)
@ -33,46 +28,13 @@ class SPVideoAPI: NSObject {
} }
/// ///
static func requestCreateVideoPlayHistory(videoId: String?, shortPlayId: String) { static func requestRequestVideoPlayHistory(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 = [
"video_id" : videoId ?? "0",
"short_play_id" : shortPlayId
]
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<String>) in
}
}
///
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 = [ param.parameters = [
"video_id" : videoId, "video_id" : videoId,
"short_play_id" : shortPlayId, "short_play_id" : shortPlayId
"play_seconds" : seconds
] ]
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<String>) in SPNetwork.request(parameters: param) { (response: SPNetworkResponse<String>) in
@ -166,17 +128,6 @@ 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 {

View File

@ -1,6 +1,6 @@
// //
// SPApi.swift // SPApi.swift
// ThimraTV // MoviaBox
// //
// 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" : kSPAPPBundleIdentifier, "app-name" : "",
"system-type" : "ios", "system-type" : "ios",
"idfa" : JXUUID.idfa(), "idfa" : JXUUID.idfa(),
"model" : UIDevice.sp_machineModelName(), "model" : UIDevice.sp_machineModelName(),

View File

@ -1,6 +1,6 @@
// //
// SPCryptService.swift // SPCryptService.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/10. // Created by on 2025/4/10.
// //

View File

@ -1,6 +1,6 @@
// //
// SPNetwork.swift // SPNetwork.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/8. // Created by on 2025/4/8.
// //
@ -76,21 +76,12 @@ 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: "movia_error".localized) SPToast.show(text: "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 { token in self.requestToken(completer: nil)
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" {
@ -137,7 +128,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: "movia_error".localized) SPToast.show(text: "Error".localized)
} }
completion?(res) completion?(res)
} }
@ -146,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: "movia_network_toast_01".localized) SPToast.show(text: "Error".localized)
} }
completion?(res) completion?(res)
break break
@ -171,7 +162,7 @@ class SPNetwork: NSObject {
} else { } else {
var response = SPNetworkResponse<T>() var response = SPNetworkResponse<T>()
response.code = -1 response.code = -1
response.msg = "movia_error".localized response.msg = "Error".localized
return response return response
} }
} }

View File

@ -1,6 +1,6 @@
// //
// SPNetworkReachabilityManager.swift // SPNetworkReachabilityManager.swift
// ThimraTV // MoviaBox
// //
// Created by Overseas on 2025/4/19. // Created by Overseas on 2025/4/19.
// //
@ -54,24 +54,16 @@ class SPNetworkReachabilityManager {
if path.status == .satisfied { if path.status == .satisfied {
if self.isReachable == false { if self.isReachable == false {
print("++++++有网") print("++++++有网")
self.isReachable = true NotificationCenter.default.post(name: SPNetworkReachabilityManager.reachabilityDidChangeNotification, object: nil)
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("++++++无网")
self.isReachable = false NotificationCenter.default.post(name: SPNetworkReachabilityManager.reachabilityDidChangeNotification, object: nil)
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) {

View File

@ -1,6 +1,6 @@
// //
// SPURLPath.swift // SPURLPath.swift
// ThimraTV // MoviaBox
// //
// 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 = "/93f03506" let SPURLPathPrefix = "/0a2c5b02"
let SPWebBaseURL = "https://www.thimratv.com" let SPWebBaseURL = "https://www.thimratv.com"
let SPCampaignWebURL = "https://campaign.moviatv.com" let SPCampaignWebURL = "https://campaign.thimratv.com"
#else #else
let SPBaseURL = "https://api-thimratv.thimratv.com" let SPBaseURL = "https://api-thimratv.thimratv.com"
let SPURLPathPrefix = "/93f03506" let SPURLPathPrefix = "/0a2c5b02"
let SPWebBaseURL = "https://www.thimratv.com" let SPWebBaseURL = "https://www.thimratv.com"
let SPCampaignWebURL = "https://campaign.moviatv.com" let SPCampaignWebURL = "https://campaign.thimratv.com"
#endif #endif
@ -42,8 +42,6 @@ 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"
@ -51,7 +49,5 @@ 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"

View File

@ -1,6 +1,6 @@
// //
// SPCollectionView.swift // SPCollectionView.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/9. // Created by on 2025/4/9.
// //

View File

@ -1,6 +1,6 @@
// //
// SPCollectionViewCell.swift // SPCollectionViewCell.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/9. // Created by on 2025/4/9.
// //

View File

@ -1,6 +1,6 @@
// //
// SPGradientView.swift // SPGradientView.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/14. // Created by on 2025/4/14.
// //

View File

@ -1,6 +1,6 @@
// //
// SPImageView.swift // SPImageView.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/9. // Created by on 2025/4/9.
// //

View File

@ -1,6 +1,6 @@
// //
// SPScrollView.swift // SPScrollView.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/17. // Created by on 2025/4/17.
// //

View File

@ -1,6 +1,6 @@
// //
// SPTableView.swift // SPTableView.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/14. // Created by on 2025/4/14.
// //
@ -13,8 +13,7 @@ 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 = .colorFFFFFF(alpha: 0.1) // separatorColor = .lineColor()
separatorInset = .init(top: 0, left: 16, bottom: 0, right: 16)
self.backgroundColor = .clear self.backgroundColor = .clear
self.contentInsetAdjustmentBehavior = .never self.contentInsetAdjustmentBehavior = .never

View File

@ -1,6 +1,6 @@
// //
// SPTableViewCell.swift // SPTableViewCell.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/14. // Created by on 2025/4/14.
// //

View File

@ -1,6 +1,6 @@
// //
// SPTextField.swift // SPTextField.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/17. // Created by on 2025/4/17.
// //

View File

@ -0,0 +1,55 @@
//
// 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
}
}
}
}
}

View File

@ -1,6 +1,6 @@
// //
// SPWebView.swift // SPWebView.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/14. // Created by on 2025/4/14.
// //

View File

@ -1,6 +1,6 @@
// //
// SPWebViewController+ScriptMessage.swift // SPWebViewController+ScriptMessage.swift
// ThimraTV // MoviaBox
// //
// Created by Overseas on 2025/4/24. // Created by Overseas on 2025/4/24.
// //
@ -45,64 +45,12 @@ extension SPWebViewController {
} else if name == WebMessageOpenPhotoPicker { } else if name == WebMessageOpenPhotoPicker {
let vc = SPImagePickerManager.createImagePicker(delegate: self) let vc = SPImagePickerManager.createImagePicker(delegate: self)
self.present(vc, animated: true) self.present(vc, animated: true)
} else if name == WebMessageAPP {
guard let body = message.body as? [String : Any] else { return }
guard let model = SPWebMessageModel.deserialize(from: body) else { return }
let type = model.type
let data = model.data
if type == "login" {//
SPLoginManager.manager.openLoginVC()
} else if type == "open_notify" {//
openNotify()
} else if type == "watch_video" { //
let vc = SPPlayerDetailViewController()
vc.shortPlayId = data?.short_play_id
vc.activityId = data?.activity_id
self.navigationController?.pushViewController(vc, animated: true)
} else {
guard let urlStr = data?.link else { return }
guard let url = URL(string: urlStr) else { return }
if UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url)
}
}
} }
} }
} }
extension SPWebViewController {
///
func openNotify() {
UNUserNotificationCenter.current().getNotificationSettings { settings in
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
if settings.authorizationStatus != .authorized {//
SPAPPTool.openApnsSetting()
} else {//
SPRewardsAPI.requestUploadOpenNotify { [weak self] finish in
if finish {
self?.reload()
}
}
}
}
}
}
}
//MARK: -------------- TZImagePickerControllerDelegate -------------- //MARK: -------------- TZImagePickerControllerDelegate --------------
extension SPWebViewController: TZImagePickerControllerDelegate { extension SPWebViewController: TZImagePickerControllerDelegate {

View File

@ -1,6 +1,6 @@
// //
// SPWebViewController.swift // SPWebViewController.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/14. // Created by on 2025/4/14.
// //
@ -12,9 +12,6 @@ class SPWebViewController: SPViewController {
var urlStr: String? var urlStr: String?
///
var autoTitle = true
private(set) lazy var webView: SPWebView = { private(set) lazy var webView: SPWebView = {
let controller = WKUserContentController() let controller = WKUserContentController()
@ -31,7 +28,7 @@ class SPWebViewController: SPViewController {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
// self.edgesForExtendedLayout = .top // self.edgesForExtendedLayout = .top
// configNavigationBack() configNavigationBack()
setBackgroundView(isShowGradient: false, bgImage: nil) setBackgroundView(isShowGradient: false, bgImage: nil)
@ -52,15 +49,11 @@ class SPWebViewController: SPViewController {
let str: String = urlString let str: String = urlString
guard let url = URL(string: str) else { return } guard let url = URL(string: str) else { return }
let request = URLRequest(url: url, timeoutInterval: 30) let request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 30)
self.webView.load(request) self.webView.load(request)
} }
func reload() {
self.webView.reload()
}
} }
extension SPWebViewController { extension SPWebViewController {
@ -77,9 +70,7 @@ extension SPWebViewController {
extension SPWebViewController: SPWebViewDelegate { extension SPWebViewController: SPWebViewDelegate {
func webView(webView: SPWebView, didChangeTitle title: String) { func webView(webView: SPWebView, didChangeTitle title: String) {
if autoTitle { self.title = title
self.title = title
}
} }
func webView(_ webView: SPWebView, didFailLoadWithError error: any Error) { func webView(_ webView: SPWebView, didFailLoadWithError error: any Error) {
@ -87,7 +78,7 @@ extension SPWebViewController: SPWebViewDelegate {
} }
func webViewDidFinishLoad(_ webView: SPWebView) { func webViewDidFinishLoad(_ webView: SPWebView) {
spLog(message: "网页加载完成")
} }

View File

@ -1,6 +1,6 @@
// //
// SPAllShortViewController.swift // SPAllShortViewController.swift
// ThimraTV // MoviaBox
// //
// Created by Overseas on 2025/4/23. // Created by Overseas on 2025/4/23.
// //
@ -13,7 +13,7 @@ class SPAllShortViewController: SPViewController {
private lazy var allCategoryModel: SPCategoryModel = { private lazy var allCategoryModel: SPCategoryModel = {
let model = SPCategoryModel() let model = SPCategoryModel()
model.id = "0" model.id = "0"
model.name = "movia_all".localized model.name = "All".localized
return model return model
}() }()
private lazy var categoryArr: [SPCategoryModel] = [self.allCategoryModel] private lazy var categoryArr: [SPCategoryModel] = [self.allCategoryModel]
@ -98,7 +98,6 @@ class SPAllShortViewController: SPViewController {
let collectionView = SPCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout) let collectionView = SPCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout)
collectionView.delegate = self collectionView.delegate = self
collectionView.dataSource = self collectionView.dataSource = self
collectionView.showNormalEmpty()
collectionView.contentInset = .init(top: 10, left: 0, bottom: 10, right: 0) collectionView.contentInset = .init(top: 10, left: 0, bottom: 10, right: 0)
collectionView.sp_addRefreshHeader(insetTop: collectionView.contentInset.top) { [weak self] in collectionView.sp_addRefreshHeader(insetTop: collectionView.contentInset.top) { [weak self] in
self?.handleHeaderRefresh(nil) self?.handleHeaderRefresh(nil)
@ -163,8 +162,7 @@ extension SPAllShortViewController {
tagView.snp.makeConstraints { make in tagView.snp.makeConstraints { make in
make.left.right.equalToSuperview() make.left.right.equalToSuperview()
// make.top.equalToSuperview().offset(kSPStatusbarHeight + 40 + 12) make.top.equalToSuperview().offset(kSPStatusbarHeight + 40 + 12)
make.top.equalToSuperview().offset(kSPNavBarHeight + 12)
make.height.lessThanOrEqualTo(tagMaxHeight) make.height.lessThanOrEqualTo(tagMaxHeight)
} }

View File

@ -1,6 +1,6 @@
// //
// SPExplorePageController.swift // SPExplorePageController.swift
// ThimraTV // MoviaBox
// //
// Created by Overseas on 2025/4/21. // Created by Overseas on 2025/4/21.
// //
@ -11,7 +11,7 @@ import UIKit
class SPExplorePageController: SPViewController { class SPExplorePageController: SPViewController {
private lazy var titles: [String] = { private lazy var titles: [String] = {
let arr = ["movia_shorts".localized, "movia_all".localized] let arr = ["Shorts".localized, "All".localized]
return arr return arr
}() }()
@ -69,7 +69,6 @@ class SPExplorePageController: SPViewController {
return pageView return pageView
}() }()
private lazy var menuBgView: UIView = { private lazy var menuBgView: UIView = {
let view = UIView() let view = UIView()
view.addEffectView(style: .light) view.addEffectView(style: .light)
@ -78,21 +77,11 @@ class SPExplorePageController: SPViewController {
return view return view
}() }()
deinit {
NotificationCenter.default.removeObserver(self)
}
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(reachabilityDidChangeNotification), name: SPNetworkReachabilityManager.reachabilityDidChangeNotification, object: nil)
if SPNetworkReachabilityManager.manager.isReachable != true {
setEmptyView()
} else {
_setupUI()
}
_setupUI()
} }
@ -101,34 +90,6 @@ class SPExplorePageController: SPViewController {
self.navigationController?.setNavigationBarHidden(true, animated: true) self.navigationController?.setNavigationBarHidden(true, animated: true)
} }
}
extension SPExplorePageController {
///
private func setEmptyView() {
if SPNetworkReachabilityManager.manager.isReachable != true {
self.addNoNetworkEmptyView { [weak self] in
self?.updateEmptyState()
}
}
}
@objc private func reachabilityDidChangeNotification() {
updateEmptyState()
}
private func updateEmptyState() {
if self.pageView.view.superview != nil { return }
if SPNetworkReachabilityManager.manager.isReachable == true {
self._setupUI()
self.removeNoNetworkEmptyView()
}
}
} }
extension SPExplorePageController { extension SPExplorePageController {

View File

@ -1,6 +1,6 @@
// //
// SPExploreViewController.swift // SPExploreViewController.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/9. // Created by on 2025/4/9.
// //
@ -36,7 +36,7 @@ extension SPExploreViewController: SPPlayerListViewControllerDelegate {
guard let pagination = self.pagination else { return } guard let pagination = self.pagination else { return }
guard let page = self.pagination?.current_page else { return } guard let page = self.pagination?.current_page else { return }
let pageSize = pagination.page_size ?? 0 let pageSize = pagination.page_size ?? 0
if pagination.total_size ?? 0 <= pageSize * page { if pagination.page_total ?? 0 <= pageSize * page {
return return
} }
self.requestDataArr(page: page + 1) self.requestDataArr(page: page + 1)

View File

@ -1,6 +1,6 @@
// //
// SPCategoryModel.swift // SPCategoryModel.swift
// ThimraTV // MoviaBox
// //
// Created by Overseas on 2025/4/23. // Created by Overseas on 2025/4/23.
// //

View File

@ -1,6 +1,6 @@
// //
// SPAllShortCell.swift // SPAllShortCell.swift
// ThimraTV // MoviaBox
// //
// Created by Overseas on 2025/4/23. // Created by Overseas on 2025/4/23.
// //

View File

@ -1,6 +1,6 @@
// //
// SPExplorePlayerCell.swift // SPExplorePlayerCell.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/17. // Created by on 2025/4/17.
// //

View File

@ -1,6 +1,6 @@
// //
// SPExplorePlayerControlView.swift // SPExplorePlayerControlView.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/17. // Created by on 2025/4/17.
// //
@ -52,7 +52,7 @@ class SPExplorePlayerControlView: SPPlayerControlView {
private lazy var allEpisodeButton: UIButton = { private lazy var allEpisodeButton: UIButton = {
let button = JXButton(type: .custom) let button = JXButton(type: .custom)
button.setTitle("movia_full_episodes".localized, for: .normal) button.setTitle("Full Episodes".localized, for: .normal)
button.setTitleColor(.colorEC3324(), for: .normal) button.setTitleColor(.colorEC3324(), for: .normal)
button.setImage(UIImage(named: "arrow_right_icon_01"), for: .normal) button.setImage(UIImage(named: "arrow_right_icon_01"), for: .normal)
button.jx_font = .fontMedium(ofSize: 12) button.jx_font = .fontMedium(ofSize: 12)
@ -74,9 +74,8 @@ class SPExplorePlayerControlView: SPPlayerControlView {
} }
private func updateEpisodeLabel() { private func updateEpisodeLabel() {
// let totalEpisode = String(format: "movia_text_episcode_ios".localized, "\(self.shortModel?.episode_total ?? 0)") let totalEpisode = String(format: "EP%@".localized, "\(self.shortModel?.episode_total ?? 0)")
let totalEpisode = "\(self.shortModel?.episode_total ?? 0)" let currentEpisode = String(format: "EP%@".localized, self.videoInfo?.episode ?? "0")
let currentEpisode = String(format: "movia_text_episcode_ios".localized, self.videoInfo?.episode ?? "0")
let episodeStr = "\(currentEpisode)/\(totalEpisode)" let episodeStr = "\(currentEpisode)/\(totalEpisode)"
let range = NSRange(location: episodeStr.length() - totalEpisode.length(), length: totalEpisode.length()) let range = NSRange(location: episodeStr.length() - totalEpisode.length(), length: totalEpisode.length())
@ -98,9 +97,6 @@ extension SPExplorePlayerControlView {
self.viewController?.navigationController?.pushViewController(vc, animated: true) self.viewController?.navigationController?.pushViewController(vc, animated: true)
} }
override func handleEpisodeButton() {
self.handleAllEpisodeButton()
}
} }

View File

@ -1,6 +1,6 @@
// //
// SPVideoPlayerInfoView.swift // SPVideoPlayerInfoView.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/17. // Created by on 2025/4/17.
// //

View File

@ -0,0 +1,24 @@
//
// 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() { }
}

View File

@ -1,6 +1,6 @@
// //
// SPHomePageController.swift // SPHomePageController.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/8. // Created by on 2025/4/8.
// //
@ -14,16 +14,15 @@ class SPHomePageController: SPViewController {
/// ///
private var isRequesting = false private var isRequesting = false
private lazy var categoryArr: [SPHomeCategoryModel] = [] private lazy var categoryArr: [SPHomeCategoryModel] = {
// { let arr = [
// let arr = [ SPHomeCategoryModel(category_name: "Hot Picks".localized, category_id: nil, viewController: SPHomeViewController()),
// SPHomeCategoryModel(category_name: "Hot Picks".localized, category_id: nil, viewController: SPHomeViewController()), SPHomeCategoryModel(category_name: "Top 10".localized, category_id: nil, viewController: nil),
// SPHomeCategoryModel(category_name: "Top 10".localized, category_id: nil, viewController: nil), SPHomeCategoryModel(category_name: "Fresh Drops".localized, category_id: nil, viewController: nil),
// SPHomeCategoryModel(category_name: "Fresh Drops".localized, category_id: nil, viewController: nil), SPHomeCategoryModel(category_name: "Free".localized, category_id: nil, viewController: nil),
// SPHomeCategoryModel(category_name: "Free".localized, category_id: nil, viewController: nil), ]
// ] return arr
// return arr }()
// }()
private lazy var searchButton: SPHomeSearchButton = { private lazy var searchButton: SPHomeSearchButton = {
let button = SPHomeSearchButton() let button = SPHomeSearchButton()
@ -124,7 +123,7 @@ extension SPHomePageController: JYPageControllerDelegate, JYPageControllerDataSo
func childController(atIndex index: Int) -> any JYPageChildContollerProtocol { func childController(atIndex index: Int) -> any JYPageChildContollerProtocol {
let vc = SPHomeViewController() let vc = SPHomeViewController()
// vc.topMargins = 15 vc.topMargins = 15
return vc return vc
} }

View File

@ -1,22 +1,19 @@
// //
// SPHomeViewController.swift // SPHomeViewController.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/8. // Created by on 2025/4/8.
// //
import UIKit import UIKit
class SPHomeViewController: SPViewController { class SPHomeViewController: SPHomeChildController {
private lazy var viewModel: SPHomeViewModel = SPHomeViewModel() private lazy var viewModel: SPHomeViewModel = SPHomeViewModel()
private lazy var page = 1
private lazy var dataArr: [SPShortModel] = []
private lazy var requestGroup = DispatchGroup()
private var isSetupUI = false
//MARK: UI //MARK: UI
private lazy var logoImageView: UIImageView = { private lazy var logoImageView: UIImageView = {
@ -32,24 +29,6 @@ class SPHomeViewController: SPViewController {
return button return button
}() }()
private lazy var allButton: UIButton = {
let button = UIButton(type: .custom)
button.setImage(UIImage(named: "all_icon_01"), for: .normal)
button.setContentHuggingPriority(.required, for: .horizontal)
button.setContentCompressionResistancePriority(.required, for: .horizontal)
button.addTarget(self, action: #selector(handleAllButton), for: .touchUpInside)
return button
}()
private lazy var rewardButton: UIButton = {
let button = UIButton(type: .custom)
button.setImage(UIImage(named: "reward_icon_01"), for: .normal)
button.setContentHuggingPriority(.required, for: .horizontal)
button.setContentCompressionResistancePriority(.required, for: .horizontal)
button.addTarget(self, action: #selector(handleRewardButton), for: .touchUpInside)
return button
}()
private lazy var layout: UICollectionViewFlowLayout = { private lazy var layout: UICollectionViewFlowLayout = {
let width = floor((kSPScreenWidth - 32 - 13) / 2) let width = floor((kSPScreenWidth - 32 - 13) / 2)
let height = 221 / 165 * width + 44 let height = 221 / 165 * width + 44
@ -78,28 +57,15 @@ class SPHomeViewController: SPViewController {
return collectionView return collectionView
}() }()
private var headerView: SPHomeHeaderView?
private lazy var playHistoricalView: SPHomePlayHistoricalView = {
let view = SPHomePlayHistoricalView()
view.isHidden = true
return view
}()
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(reachabilityDidChangeNotification), name: SPNetworkReachabilityManager.reachabilityDidChangeNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(reachabilityDidChangeNotification), name: SPNetworkReachabilityManager.reachabilityDidChangeNotification, object: nil)
updateAllData(completer: nil)
if SPNetworkReachabilityManager.manager.isReachable == true { _setupUI()
updateAllData(completer: nil)
_setupUI()
} else {
setEmptyView()
}
} }
@ -108,20 +74,6 @@ class SPHomeViewController: SPViewController {
self.navigationController?.setNavigationBarHidden(true, animated: true) self.navigationController?.setNavigationBarHidden(true, animated: true)
} }
override func viewDidAppear(_ animated: Bool) {
if hasViewDidAppear {
requestPlayHistory()
}
super.viewDidAppear(animated)
self.headerView?.isDidAppear = self.isDidAppear
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
self.headerView?.isDidAppear = self.isDidAppear
}
override func handleHeaderRefresh(_ completer: (() -> Void)?) { override func handleHeaderRefresh(_ completer: (() -> Void)?) {
updateAllData { [weak self] in updateAllData { [weak self] in
@ -130,7 +82,7 @@ class SPHomeViewController: SPViewController {
} }
override func handleFooterRefresh(_ completer: (() -> Void)?) { override func handleFooterRefresh(_ completer: (() -> Void)?) {
requestListDataArr(page: self.viewModel.page + 1) { [weak self] in requestListDataArr(page: self.page + 1) { [weak self] in
self?.collectionView.sp_endFooterRefreshing() self?.collectionView.sp_endFooterRefreshing()
} }
} }
@ -138,19 +90,12 @@ class SPHomeViewController: SPViewController {
} }
extension SPHomeViewController { extension SPHomeViewController {
private func _setupUI() { private func _setupUI() {
if isSetupUI { return }
isSetupUI = true
// view.addSubview(logoImageView) // view.addSubview(logoImageView)
view.addSubview(searchButton) view.addSubview(searchButton)
view.addSubview(allButton)
view.addSubview(rewardButton)
view.addSubview(self.collectionView) view.addSubview(self.collectionView)
view.addSubview(playHistoricalView)
// logoImageView.snp.makeConstraints { make in // logoImageView.snp.makeConstraints { make in
// make.left.equalToSuperview().offset(16) // make.left.equalToSuperview().offset(16)
@ -160,20 +105,8 @@ extension SPHomeViewController {
searchButton.snp.makeConstraints { make in searchButton.snp.makeConstraints { make in
// make.left.equalTo(logoImageView.snp.right).offset(6) // make.left.equalTo(logoImageView.snp.right).offset(6)
make.left.equalToSuperview().offset(16) make.left.equalToSuperview().offset(16)
// make.right.equalToSuperview().offset(-16)
make.right.equalTo(allButton.snp.left).offset(-4)
make.top.equalToSuperview().offset(kSPStatusbarHeight + 10)
}
allButton.snp.makeConstraints { make in
make.centerY.equalTo(searchButton)
// make.right.equalToSuperview().offset(-16)
make.right.equalTo(rewardButton.snp.left).offset(-1)
}
rewardButton.snp.makeConstraints { make in
make.centerY.equalTo(searchButton)
make.right.equalToSuperview().offset(-16) make.right.equalToSuperview().offset(-16)
make.top.equalToSuperview().offset(kSPStatusbarHeight + 10)
} }
self.collectionView.snp.makeConstraints { make in self.collectionView.snp.makeConstraints { make in
@ -181,12 +114,6 @@ extension SPHomeViewController {
// make.top.equalToSuperview().offset(kSPStatusbarHeight + 66) // make.top.equalToSuperview().offset(kSPStatusbarHeight + 66)
make.top.equalTo(searchButton.snp.bottom).offset(34) make.top.equalTo(searchButton.snp.bottom).offset(34)
} }
playHistoricalView.snp.makeConstraints { make in
make.left.equalToSuperview().offset(16)
make.centerX.equalToSuperview()
make.bottom.equalToSuperview().offset(-4)
}
} }
} }
@ -196,45 +123,11 @@ extension SPHomeViewController {
self.navigationController?.pushViewController(vc, animated: true) self.navigationController?.pushViewController(vc, animated: true)
} }
///
private func setEmptyView() {
if SPNetworkReachabilityManager.manager.isReachable != true {
self.addNoNetworkEmptyView { [weak self] in
guard let self = self else { return }
self.updateEmptyState()
if self.viewModel.isEmptyData, SPNetworkReachabilityManager.manager.isReachable == true {
self.updateAllData(completer: nil)
}
}
}
}
@objc private func reachabilityDidChangeNotification() { @objc private func reachabilityDidChangeNotification() {
updateEmptyState() if SPNetworkReachabilityManager.manager.isReachable == true, self.viewModel.moduleModel == nil {
updateAllData(completer: nil)
if viewModel.isEmptyData, SPNetworkReachabilityManager.manager.isReachable == true {
self.updateAllData(completer: nil)
} }
} }
///
private func updateEmptyState() {
if SPNetworkReachabilityManager.manager.isReachable == true {
self._setupUI()
self.removeNoNetworkEmptyView()
}
}
@objc private func handleAllButton() {
let vc = SPAllViewController()
self.navigationController?.pushViewController(vc, animated: true)
}
@objc private func handleRewardButton() {
let vc = SPRewardsViewController()
self.navigationController?.pushViewController(vc, animated: true)
}
} }
@ -243,26 +136,25 @@ extension SPHomeViewController: UICollectionViewDelegate, UICollectionViewDataSo
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = SPHomeShortCell.dequeueReusableCell(collectionView: collectionView, indexPath: indexPath) let cell = SPHomeShortCell.dequeueReusableCell(collectionView: collectionView, indexPath: indexPath)
cell.model = viewModel.dataArr[indexPath.row] cell.model = dataArr[indexPath.row]
return cell return cell
} }
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return viewModel.dataArr.count return dataArr.count
} }
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
if let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "headerView", for: indexPath) as? SPHomeHeaderView { if let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "headerView", for: indexPath) as? SPHomeHeaderView {
headerView.viewModel = self.viewModel headerView.viewModel = self.viewModel
self.headerView = headerView
return headerView return headerView
} }
return UICollectionReusableView() return UICollectionReusableView()
} }
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let model = viewModel.dataArr[indexPath.row] let model = self.dataArr[indexPath.row]
let vc = SPPlayerDetailViewController() let vc = SPPlayerDetailViewController()
vc.shortPlayId = model.short_play_id vc.shortPlayId = model.short_play_id
@ -275,35 +167,14 @@ extension SPHomeViewController: UICollectionViewDelegate, UICollectionViewDataSo
extension SPHomeViewController { extension SPHomeViewController {
private func updateAllData(completer: (() -> Void)?) { private func updateAllData(completer: (() -> Void)?) {
self.requestGroup.enter() requestModuleData()
requestModuleData { [weak self] in requestPlayHistory()
self?.requestGroup.leave() requestListDataArr(page: 1) {
}
self.requestGroup.enter()
requestPlayHistory { [weak self] in
self?.requestGroup.leave()
}
self.requestGroup.enter()
requestListDataArr(page: 1) { [weak self] in
self?.requestGroup.leave()
}
self.requestGroup.enter()
requestCategoryShortList(id: "3") { [weak self] in
self?.requestGroup.leave()
}
// self.requestGroup.enter()
// requestCategoryShortList(id: "1") { [weak self] in
// self?.requestGroup.leave()
// }
self.requestGroup.notify(queue: DispatchQueue.main) {
completer?() completer?()
} }
} }
/// banner private func requestModuleData() {
private func requestModuleData(completer: (() -> Void)? = nil) {
SPHomeAPI.requestHomeModuleData { [weak self] model in SPHomeAPI.requestHomeModuleData { [weak self] model in
guard let self = self else { return } guard let self = self else { return }
if let model = model { if let model = model {
@ -312,49 +183,18 @@ extension SPHomeViewController {
self.layout.headerReferenceSize = CGSize(width: kSPScreenWidth, height: SPHomeHeaderView.contentHeight(viewModel: self.viewModel)) self.layout.headerReferenceSize = CGSize(width: kSPScreenWidth, height: SPHomeHeaderView.contentHeight(viewModel: self.viewModel))
self.collectionView.reloadData() self.collectionView.reloadData()
} }
self.updateEmptyState()
completer?()
}
}
///ID= 3
///ID=1
private func requestCategoryShortList(id: String, completer: (() -> Void)?) {
SPVideoAPI.requestCategoryShortList(page: 1, id: id) { [weak self] listModel in
guard let self = self else { return }
if let list = listModel?.list {
if id == "3" {
self.viewModel.categoryDataArr1 = list
} else {
self.viewModel.categoryDataArr2 = list
}
self.layout.headerReferenceSize = CGSize(width: kSPScreenWidth, height: SPHomeHeaderView.contentHeight(viewModel: self.viewModel))
self.collectionView.reloadData()
}
self.updateEmptyState()
completer?()
} }
} }
/// ///
private func requestPlayHistory(completer: (() -> Void)? = nil) { private func requestPlayHistory() {
SPVideoAPI.requestPlayHistoryList(page: 1) { [weak self] listModel in SPVideoAPI.requestPlayHistoryList(page: 1) { [weak self] listModel in
guard let self = self else { return } guard let self = self else { return }
if let list = listModel?.list { if let list = listModel?.list {
self.viewModel.playHistoryArr = list self.viewModel.playHistoryArr = list
self.layout.headerReferenceSize = CGSize(width: kSPScreenWidth, height: SPHomeHeaderView.contentHeight(viewModel: self.viewModel)) self.layout.headerReferenceSize = CGSize(width: kSPScreenWidth, height: SPHomeHeaderView.contentHeight(viewModel: self.viewModel))
self.collectionView.reloadData() self.collectionView.reloadData()
if let model = listModel?.list?.first {
self.playHistoricalView.model = model
self.playHistoricalView.isHidden = false
}
} }
self.updateEmptyState()
completer?()
} }
} }
@ -365,18 +205,15 @@ extension SPHomeViewController {
if let list = listModel?.list { if let list = listModel?.list {
if page == 1 { if page == 1 {
self.viewModel.dataArr.removeAll() self.dataArr.removeAll()
} }
self.viewModel.dataArr += list self.dataArr += list
self.collectionView.reloadData() self.collectionView.reloadData()
self.viewModel.page = page self.page = page
} }
self.updateEmptyState()
completer?() completer?()
} }
} }
} }

View File

@ -1,6 +1,6 @@
// //
// SPSearchViewController.swift // SPSearchViewController.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/17. // Created by on 2025/4/17.
// //
@ -60,8 +60,6 @@ class SPSearchViewController: SPViewController {
searchInputView.textField.becomeFirstResponder() searchInputView.textField.becomeFirstResponder()
setBackgroundView(isShowGradient: false, bgImage: nil)
_setupUI() _setupUI()
} }

View File

@ -1,6 +1,6 @@
// //
// SPHomeCategoryModel.swift // SPHomeCategoryModel.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/8. // Created by on 2025/4/8.
// //

View File

@ -1,6 +1,6 @@
// //
// SPHomeModuleModel.swift // SPHomeModuleModel.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/14. // Created by on 2025/4/14.
// //

View File

@ -1,6 +1,6 @@
// //
// SPHomeTopModel.swift // SPHomeTopModel.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/14. // Created by on 2025/4/14.
// //

View File

@ -1,6 +1,6 @@
// //
// SPHomeBannerCell.swift // SPHomeBannerCell.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/14. // Created by on 2025/4/14.
// //

View File

@ -1,6 +1,6 @@
// //
// SPHomeDataItemView.swift // SPHomeDataItemView.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/14. // Created by on 2025/4/14.
// //
@ -30,7 +30,7 @@ class SPHomeDataItemView: UIView {
private(set) lazy var titleLabel: UILabel = { private(set) lazy var titleLabel: UILabel = {
let label = UILabel() let label = UILabel()
label.font = .fontMedium(ofSize: 18) label.font = .fontWeight(ofSize: 18, weight: 400)
label.textColor = .colorFFFFFF() label.textColor = .colorFFFFFF()
return label return label
}() }()
@ -42,7 +42,7 @@ class SPHomeDataItemView: UIView {
private lazy var moreButton: UIButton = { private lazy var moreButton: UIButton = {
let button = UIButton(type: .custom) let button = UIButton(type: .custom)
button.setTitle("movia_more".localized, for: .normal) button.setTitle("More".localized, for: .normal)
button.setTitleColor(.colorF564B6(), for: .normal) button.setTitleColor(.colorF564B6(), for: .normal)
button.titleLabel?.font = .fontLight(ofSize: 12) button.titleLabel?.font = .fontLight(ofSize: 12)
return button return button

View File

@ -0,0 +1,65 @@
//
// 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)
}
}
}

View File

@ -1,6 +1,6 @@
// //
// SPHomeExploreView.swift // SPHomeExploreView.swift
// ThimraTV // MoviaBox
// //
// Created by Overseas on 2025/4/22. // Created by Overseas on 2025/4/22.
// //
@ -62,7 +62,7 @@ class SPHomeExploreView: SPHomeDataItemView {
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
titleLabel.text = "movia_explore_for_you".localized titleLabel.text = "Explore For You".localized
iconImageView.image = UIImage(named: "mark_icon_01") iconImageView.image = UIImage(named: "mark_icon_01")
_setupUI() _setupUI()

View File

@ -1,6 +1,6 @@
// //
// SPHomeHeaderView.swift // SPHomeHeaderView.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/14. // Created by on 2025/4/14.
// //
@ -13,17 +13,10 @@ class SPHomeHeaderView: UICollectionReusableView {
didSet { didSet {
let moduleModel = viewModel?.moduleModel let moduleModel = viewModel?.moduleModel
let bannerModel = self.viewModel?.moduleModel?.bannerData?.first
setBannerBgImage(model: bannerModel)
stackView.removeAllArrangedSubview() stackView.removeAllArrangedSubview()
stackView.addArrangedSubview(bannerView)
if let bannerData = moduleModel?.bannerData, bannerData.count > 0 { bannerView.reloadData()
stackView.addArrangedSubview(bannerView)
bannerView.reloadData()
}
if let historyList = viewModel?.playHistoryArr, historyList.count > 0 { if let historyList = viewModel?.playHistoryArr, historyList.count > 0 {
stackView.addArrangedSubview(playHistoryView) stackView.addArrangedSubview(playHistoryView)
@ -36,22 +29,8 @@ class SPHomeHeaderView: UICollectionReusableView {
exploreView.dataArr = list exploreView.dataArr = list
} }
if let list = viewModel?.categoryDataArr1, list.count > 0 { // stackView.addArrangedSubview(trendingView)
stackView.addArrangedSubview(categoryVideoView1) // trendingView.dataArr = moduleModel?.bannerData
categoryVideoView1.dataArr = list
}
if let list = moduleModel?.hotData, list.count > 0 {
stackView.addArrangedSubview(trendingView)
trendingView.dataArr = list
}
if let list = viewModel?.categoryDataArr2, list.count > 0 {
stackView.addArrangedSubview(categoryVideoView2)
categoryVideoView2.dataArr = list
}
// //
// stackView.addArrangedSubview(hotView) // stackView.addArrangedSubview(hotView)
// hotView.dataArr = moduleModel?.bannerData // hotView.dataArr = moduleModel?.bannerData
@ -59,18 +38,7 @@ class SPHomeHeaderView: UICollectionReusableView {
// stackView.addArrangedSubview(shortsForYouView) // stackView.addArrangedSubview(shortsForYouView)
// shortsForYouView.dataArr = moduleModel?.bannerData // shortsForYouView.dataArr = moduleModel?.bannerData
if (viewModel?.dataArr.count ?? 0) > 0 { stackView.addArrangedSubview(titleView)
stackView.addArrangedSubview(titleView)
}
}
}
private var currentBannerModel: SPShortModel?
var isDidAppear: Bool = false {
didSet {
self.categoryVideoView1.isDidAppear = isDidAppear
self.categoryVideoView2.isDidAppear = isDidAppear
} }
} }
@ -82,20 +50,13 @@ class SPHomeHeaderView: UICollectionReusableView {
return view return view
}() }()
private lazy var bannerBgImageView: SPFadeEdgeImageView = {
let imageView = SPFadeEdgeImageView()
imageView.contentMode = .scaleAspectFill
imageView.layer.masksToBounds = true
return imageView
}()
private lazy var bannerView: ZKCycleScrollView = { private lazy var bannerView: ZKCycleScrollView = {
let view = ZKCycleScrollView(frame: .zero, shouldInfiniteLoop: true) let view = ZKCycleScrollView(frame: .zero, shouldInfiniteLoop: true)
view.itemSize = .init(width: 234, height: Self.bannerHeight()) view.itemSize = .init(width: 234, height: Self.bannerHeight())
view.itemAlpha = true view.itemAlpha = true
view.itemZoomScale = 0.85 view.itemZoomScale = 0.9
view.rotationAngle = 12 view.itemSpacing = 10
view.itemSpacing = 15 view.rotationAngle = 5
view.delegate = self view.delegate = self
view.dataSource = self view.dataSource = self
view.hidesPageControl = true view.hidesPageControl = true
@ -118,20 +79,6 @@ class SPHomeHeaderView: UICollectionReusableView {
return view return view
}() }()
///
private lazy var categoryVideoView1: SPHomeCategoryVideoView = {
let view = SPHomeCategoryVideoView()
view.image = UIImage(named: "category_bg_image_01")
return view
}()
///
private lazy var categoryVideoView2: SPHomeCategoryVideoView = {
let view = SPHomeCategoryVideoView()
view.image = UIImage(named: "category_bg_image_02")
return view
}()
private lazy var trendingView: SPHomeTrendingView = { private lazy var trendingView: SPHomeTrendingView = {
let view = SPHomeTrendingView() let view = SPHomeTrendingView()
return view return view
@ -149,8 +96,7 @@ class SPHomeHeaderView: UICollectionReusableView {
private lazy var titleView: SPHomeDataItemView = { private lazy var titleView: SPHomeDataItemView = {
let view = SPHomeDataItemView() let view = SPHomeDataItemView()
view.titleLabel.text = "movia_more_for_you".localized view.titleLabel.text = "More for you!".localized
view.iconImageView.image = UIImage(named: "mark_icon_02")
return view return view
}() }()
@ -163,44 +109,16 @@ class SPHomeHeaderView: UICollectionReusableView {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
private func setBannerBgImage(model: SPShortModel?) {
self.currentBannerModel = model
if let image = model?.blurImage {
self.bannerBgImageView.image = image
return
}
self.bannerBgImageView.sp_setImage(url: model?.image_url) { [weak self] image, url in
guard let self = self else { return }
if model == self.currentBannerModel {
if model?.blurImage == nil {
model?.blurImage = image?.applyBlur()
}
self.bannerBgImageView.image = model?.blurImage
}
}
}
} }
extension SPHomeHeaderView { extension SPHomeHeaderView {
private func _setupUI() { private func _setupUI() {
addSubview(bannerBgImageView)
addSubview(stackView) addSubview(stackView)
stackView.snp.makeConstraints { make in stackView.snp.makeConstraints { make in
make.edges.equalToSuperview() make.edges.equalToSuperview()
} }
bannerBgImageView.snp.makeConstraints { make in
// make.top.equalTo(20)
make.top.equalToSuperview()
make.centerX.equalToSuperview()
make.width.equalTo(kSPScreenWidth)
make.height.equalTo(Self.bannerHeight())
}
} }
} }
@ -244,12 +162,6 @@ extension SPHomeHeaderView: ZKCycleScrollViewDelegate, ZKCycleScrollViewDataSour
return self.viewModel?.moduleModel?.bannerData?.count ?? 0 return self.viewModel?.moduleModel?.bannerData?.count ?? 0
} }
func cycleScrollView(_ cycleScrollView: ZKCycleScrollView, didScrollFromIndex fromIndex: Int, toIndex: Int) {
let model = self.viewModel?.moduleModel?.bannerData?[toIndex]
setBannerBgImage(model: model)
}
func cycleScrollView(_ cycleScrollView: ZKCycleScrollView, didSelectItemAt index: Int) { func cycleScrollView(_ cycleScrollView: ZKCycleScrollView, didSelectItemAt index: Int) {
let model = self.viewModel?.moduleModel?.bannerData?[index] let model = self.viewModel?.moduleModel?.bannerData?[index]
@ -263,52 +175,21 @@ extension SPHomeHeaderView: ZKCycleScrollViewDelegate, ZKCycleScrollViewDataSour
extension SPHomeHeaderView { extension SPHomeHeaderView {
static func contentHeight(viewModel: SPHomeViewModel) -> CGFloat { static func contentHeight(viewModel: SPHomeViewModel) -> CGFloat {
var height: CGFloat = 0 var height = bannerHeight()
let moduleModel = viewModel.moduleModel let moduleModel = viewModel.moduleModel
if let bannerData = moduleModel?.bannerData, bannerData.count > 0 {
height = height + bannerHeight()
}
/// ///
if let historyList = viewModel.playHistoryArr, historyList.count > 0 { if let historyList = viewModel.playHistoryArr, historyList.count > 0 {
if height > 0 { height = height + SPHomePlayHistoryView.contentHeight(dataArr: historyList) + 25
height = height + 25
}
height = height + SPHomePlayHistoryView.contentHeight(dataArr: historyList)
} }
/// ///
if let list = moduleModel?.nineSquare?.list, list.count > 0 { if let list = moduleModel?.nineSquare?.list, list.count > 0 {
if height > 0 { height = height + SPHomeExploreView.contentHeight(dataArr: list) + 25
height = height + 25
}
height = height + SPHomeExploreView.contentHeight(dataArr: list)
}
///
if viewModel.categoryDataArr1.count > 0 {
if height > 0 {
height = height + 25
}
height = height + SPHomeCategoryVideoView.contentHeight()
}
///
if viewModel.categoryDataArr2.count > 0 {
if height > 0 {
height = height + 25
}
height = height + SPHomeCategoryVideoView.contentHeight()
}
if let list = moduleModel?.hotData, list.count > 0 {
if height > 0 {
height = height + 25
}
height = height + SPHomeTrendingView.contentHeight(dataArr: list)
} }
// height = height + SPHomeTrendingView.contentHeight(dataArr: moduleModel?.bannerData ?? []) + 25
// //
// //
// height = height + SPHomeHotView.contentHeight(dataArr: moduleModel?.bannerData ?? []) + 25 // height = height + SPHomeHotView.contentHeight(dataArr: moduleModel?.bannerData ?? []) + 25

View File

@ -1,6 +1,6 @@
// //
// SPHomeHotCell.swift // SPHomeHotCell.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/14. // Created by on 2025/4/14.
// //

View File

@ -1,6 +1,6 @@
// //
// SPHomeHotSearchCell.swift // SPHomeHotSearchCell.swift
// ThimraTV // MoviaBox
// //
// Created by Overseas on 2025/4/22. // Created by Overseas on 2025/4/22.
// //

View File

@ -1,6 +1,6 @@
// //
// SPHomeHotSearchView.swift // SPHomeHotSearchView.swift
// ThimraTV // MoviaBox
// //
// Created by Overseas on 2025/4/22. // Created by Overseas on 2025/4/22.
// //
@ -25,7 +25,7 @@ class SPHomeHotSearchView: UIView {
let label = UILabel() let label = UILabel()
label.font = .fontMedium(ofSize: 16) label.font = .fontMedium(ofSize: 16)
label.textColor = .colorFFFFFF() label.textColor = .colorFFFFFF()
label.text = "movia_top_search".localized label.text = "Top Search".localized
return label return label
}() }()

View File

@ -1,6 +1,6 @@
// //
// SPHomeHotView.swift // SPHomeHotView.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/14. // Created by on 2025/4/14.
// //
@ -46,7 +46,7 @@ class SPHomeHotView: SPHomeDataItemView {
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
self.titleLabel.text = "movia_editors_hotlist".localized self.titleLabel.text = "Editor's Hotlist".localized
_setupUI() _setupUI()
} }

View File

@ -1,6 +1,6 @@
// //
// SPHomePlayHistoryCell.swift // SPHomePlayHistoryCell.swift
// ThimraTV // MoviaBox
// //
// Created by Overseas on 2025/4/22. // Created by Overseas on 2025/4/22.
// //
@ -18,7 +18,7 @@ class SPHomePlayHistoryCell: SPCollectionViewCell {
// model?.episode_total // model?.episode_total
let episode_total = "\(model?.episode_total ?? 0)" let episode_total = "\(model?.episode_total ?? 0)"
let episode = String(format: "movia_text_episcode_ios".localized, "\(model?.current_episode ?? "0")") + "/\(episode_total)" let episode = String(format: "EP.%@/%@", "\(model?.current_episode ?? "0")", episode_total)
let episodeString = NSMutableAttributedString(string: episode) let episodeString = NSMutableAttributedString(string: episode)
episodeString.color = .colorFF5100() episodeString.color = .colorFF5100()

View File

@ -1,6 +1,6 @@
// //
// SPHomePlayHistoryView.swift // SPHomePlayHistoryView.swift
// ThimraTV // MoviaBox
// //
// Created by Overseas on 2025/4/22. // Created by Overseas on 2025/4/22.
// //
@ -42,7 +42,7 @@ class SPHomePlayHistoryView: SPHomeDataItemView {
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
self.titleLabel.text = "movia_continue_watching".localized self.titleLabel.text = "Continue watching".localized
_setupUI() _setupUI()

View File

@ -1,6 +1,6 @@
// //
// SPHomeSearchButton.swift // SPHomeSearchButton.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/17. // Created by on 2025/4/17.
// //
@ -23,7 +23,7 @@ class SPHomeSearchButton: UIControl {
let label = UILabel() let label = UILabel()
label.font = .fontRegular(ofSize: 12) label.font = .fontRegular(ofSize: 12)
label.textColor = .colorFFFFFF(alpha: 0.52) label.textColor = .colorFFFFFF(alpha: 0.52)
label.text = "movia_search_tips".localized label.text = "Love Me Like You Do It".localized
return label return label
}() }()

View File

@ -1,6 +1,6 @@
// //
// SPHomeSearchHistoryView.swift // SPHomeSearchHistoryView.swift
// ThimraTV // MoviaBox
// //
// Created by Overseas on 2025/4/22. // Created by Overseas on 2025/4/22.
// //
@ -30,7 +30,7 @@ class SPHomeSearchHistoryView: UIView {
let label = UILabel() let label = UILabel()
label.font = .fontBold(ofSize: 16) label.font = .fontBold(ofSize: 16)
label.textColor = .colorE7F5FF() label.textColor = .colorE7F5FF()
label.text = "movia_Historical_search".localized label.text = "Historical search".localized
return label return label
}() }()

View File

@ -1,6 +1,6 @@
// //
// SPHomeShortCell.swift // SPHomeShortCell.swift
// ThimraTV // MoviaBox
// //
// Created by Overseas on 2025/4/22. // Created by Overseas on 2025/4/22.
// //
@ -13,18 +13,6 @@ class SPHomeShortCell: SPCollectionViewCell {
didSet { didSet {
coverImageView.sp_setImage(url: model?.image_url) coverImageView.sp_setImage(url: model?.image_url)
titleLabel.text = model?.name titleLabel.text = model?.name
if model?.tag_type == .hot {
markView.isHidden = false
markView.colors = [UIColor.color3E23DE(alpha: 0.17).cgColor, UIColor.color4629F1(alpha: 0.74).cgColor, UIColor.color3D1DFF().cgColor]
markLabel.text = "HOT"
} else if model?.tag_type == .new {
markView.isHidden = false
markView.colors = [UIColor.colorDE2326(alpha: 0.17).cgColor, UIColor.colorF1298A(alpha: 0.74).cgColor, UIColor.colorFF1DE8().cgColor]
markLabel.text = "NEW"
} else {
markView.isHidden = true
}
} }
} }
@ -33,22 +21,6 @@ class SPHomeShortCell: SPCollectionViewCell {
return imageView return imageView
}() }()
private lazy var markView: SPGradientView = {
let view = SPGradientView()
view.locations = [0, 0.3, 1]
view.startPoint = .init(x: 0, y: 0.7)
view.endPoint = .init(x: 1, y: 0.5)
view.addRadius(topLeft: 0, topRight: 4, bottomLeft: 12, bottomRight: 0)
return view
}()
private lazy var markLabel: UILabel = {
let label = UILabel()
label.font = .fontBold(ofSize: 12)
label.textColor = .colorFFFFFF()
return label
}()
private lazy var titleLabel: UILabel = { private lazy var titleLabel: UILabel = {
let label = UILabel() let label = UILabel()
label.font = .fontMedium(ofSize: 12) label.font = .fontMedium(ofSize: 12)
@ -75,8 +47,6 @@ class SPHomeShortCell: SPCollectionViewCell {
extension SPHomeShortCell { extension SPHomeShortCell {
private func _setupUI() { private func _setupUI() {
contentView.addSubview(coverImageView) contentView.addSubview(coverImageView)
coverImageView.addSubview(markView)
markView.addSubview(markLabel)
contentView.addSubview(titleLabel) contentView.addSubview(titleLabel)
coverImageView.snp.makeConstraints { make in coverImageView.snp.makeConstraints { make in
@ -84,17 +54,6 @@ extension SPHomeShortCell {
make.bottom.equalToSuperview().offset(-44) make.bottom.equalToSuperview().offset(-44)
} }
markView.snp.makeConstraints { make in
make.top.equalToSuperview().offset(6)
make.right.equalToSuperview().offset(-6)
make.width.equalTo(46)
make.height.equalTo(18)
}
markLabel.snp.makeConstraints { make in
make.center.equalToSuperview()
}
titleLabel.snp.makeConstraints { make in titleLabel.snp.makeConstraints { make in
make.left.equalToSuperview().offset(8) make.left.equalToSuperview().offset(8)
make.right.lessThanOrEqualToSuperview().offset(-8) make.right.lessThanOrEqualToSuperview().offset(-8)

View File

@ -1,6 +1,6 @@
// //
// SPHomeShortsForYouCell.swift // SPHomeShortsForYouCell.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/14. // Created by on 2025/4/14.
// //

View File

@ -1,6 +1,6 @@
// //
// SPHomeShortsForYouView.swift // SPHomeShortsForYouView.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/14. // Created by on 2025/4/14.
// //
@ -43,7 +43,7 @@ class SPHomeShortsForYouView: SPHomeDataItemView {
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
self.titleLabel.text = "movia_shorts_for_you".localized self.titleLabel.text = "Shorts for You".localized
_setupUI() _setupUI()
} }

View File

@ -0,0 +1,91 @@
//
// 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()
}
}
}

View File

@ -1,50 +1,53 @@
// //
// SPHomeTrendingView.swift // SPHomeTrendingView.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/14. // Created by on 2025/4/14.
// //
import UIKit import UIKit
class SPHomeTrendingView: UIView { class SPHomeTrendingView: SPHomeDataItemView {
private static func itemSize() -> CGSize { private static func itemSize() -> CGSize {
let width = floor((kSPScreenWidth - 15 * 2 - 12 * 2) / 3)
let imageScale: CGFloat = 153 / 107
let height = width * imageScale + 38
return CGSize(width: 224, height: 106) return CGSize(width: width, height: height)
} }
class func contentHeight(dataArr: [SPShortModel]) -> CGFloat { override class func contentHeight(dataArr: [SPShortModel]) -> CGFloat {
return 388
var height = self.contentToTop
var lineCount = dataArr.count / 3
if dataArr.count % 3 > 0 {
lineCount += 1
}
let contentHeight = itemSize().height * CGFloat(lineCount) + 12 * CGFloat(lineCount - 1)
if contentHeight > 0 {
height += contentHeight
} else {
height += 1
}
return height
} }
var dataArr: [SPShortModel]? { override var dataArr: [SPShortModel]? {
didSet { didSet {
self.collectionView.reloadData() self.collectionView.reloadData()
} }
} }
//MARK: UI
private lazy var bgView: UIImageView = {
let view = UIImageView(image: UIImage(named: "category_bg_image_03"))
return view
}()
private lazy var titleLabel: UILabel = {
let label = UILabel()
label.font = .fontMedium(ofSize: 18)
label.textColor = .colorFFC234()
return label
}()
private lazy var collectionViewLayout: UICollectionViewFlowLayout = { private lazy var collectionViewLayout: UICollectionViewFlowLayout = {
let layout = UICollectionViewFlowLayout() let layout = UICollectionViewFlowLayout()
layout.minimumLineSpacing = 12 layout.minimumLineSpacing = 12
layout.minimumInteritemSpacing = 12 layout.minimumInteritemSpacing = 12
layout.itemSize = Self.itemSize() layout.itemSize = Self.itemSize()
layout.sectionInset = UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16) layout.sectionInset = UIEdgeInsets(top: 0, left: 15, bottom: 0, right: 15)
layout.scrollDirection = .horizontal
return layout return layout
}() }()
@ -52,9 +55,7 @@ class SPHomeTrendingView: UIView {
let collectionView = SPCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout) let collectionView = SPCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout)
collectionView.delegate = self collectionView.delegate = self
collectionView.dataSource = self collectionView.dataSource = self
// collectionView.isScrollEnabled = false collectionView.isScrollEnabled = false
collectionView.showsVerticalScrollIndicator = false
collectionView.showsHorizontalScrollIndicator = false
SPHomeTrendingCell.registerCell(collectionView: collectionView) SPHomeTrendingCell.registerCell(collectionView: collectionView)
return collectionView return collectionView
}() }()
@ -62,7 +63,8 @@ class SPHomeTrendingView: UIView {
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
self.titleLabel.text = "movia_trending_now".localized
self.titleLabel.text = "Trending Now".localized
_setupUI() _setupUI()
} }
@ -75,23 +77,10 @@ class SPHomeTrendingView: UIView {
extension SPHomeTrendingView { extension SPHomeTrendingView {
private func _setupUI() { private func _setupUI() {
addSubview(bgView) contentView.addSubview(collectionView)
addSubview(titleLabel)
addSubview(collectionView)
titleLabel.snp.makeConstraints { make in
make.left.equalToSuperview().offset(16)
make.top.equalToSuperview().offset(14)
}
bgView.snp.makeConstraints { make in
make.left.equalToSuperview()
make.top.equalToSuperview()
}
collectionView.snp.makeConstraints { make in collectionView.snp.makeConstraints { make in
make.left.right.bottom.equalToSuperview() make.edges.equalToSuperview()
make.top.equalToSuperview().offset(46)
} }
} }
@ -101,17 +90,12 @@ extension SPHomeTrendingView {
extension SPHomeTrendingView: UICollectionViewDataSource, UICollectionViewDelegate { extension SPHomeTrendingView: UICollectionViewDataSource, UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = SPHomeTrendingCell.dequeueReusableCell(collectionView: collectionView, indexPath: indexPath) let cell = SPHomeTrendingCell.dequeueReusableCell(collectionView: collectionView, indexPath: indexPath)
cell.row = indexPath.row
cell.model = dataArr?[indexPath.row] cell.model = dataArr?[indexPath.row]
return cell return cell
} }
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
var count = self.dataArr?.count ?? 0 return dataArr?.count ?? 0
if count > 9 {
count = 9
}
return count
} }
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

View File

@ -1,6 +1,6 @@
// //
// SPHomeZoomBannerCell.swift // SPHomeZoomBannerCell.swift
// ThimraTV // MoviaBox
// //
// Created by Overseas on 2025/4/22. // Created by Overseas on 2025/4/22.
// //
@ -13,11 +13,6 @@ class SPHomeZoomBannerCell: ZKCycleScrollViewCell {
didSet { didSet {
coverImageView.sp_setImage(url: model?.image_url) coverImageView.sp_setImage(url: model?.image_url)
titleLabel.text = model?.name titleLabel.text = model?.name
if model?.tag_type == .new {
iconImageView.isHidden = false
} else {
iconImageView.isHidden = true
}
} }
} }
@ -83,7 +78,7 @@ extension SPHomeZoomBannerCell {
titleLabel.snp.makeConstraints { make in titleLabel.snp.makeConstraints { make in
make.left.equalToSuperview().offset(15) make.left.equalToSuperview().offset(15)
make.right.lessThanOrEqualToSuperview().offset(-40) make.right.lessThanOrEqualToSuperview().offset(-15)
make.centerY.equalToSuperview() make.centerY.equalToSuperview()
} }
} }

View File

@ -1,6 +1,6 @@
// //
// SPSearchAssociativeCell.swift // SPSearchAssociativeCell.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/18. // Created by on 2025/4/18.
// //

View File

@ -1,6 +1,6 @@
// //
// SPSearchAssociativeView.swift // SPSearchAssociativeView.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/18. // Created by on 2025/4/18.
// //
@ -24,7 +24,6 @@ class SPSearchAssociativeView: UIView {
tableView.separatorInset = .init(top: 0, left: 16, bottom: 0, right: 16) tableView.separatorInset = .init(top: 0, left: 16, bottom: 0, right: 16)
tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: kSPTabbarSafeBottomMargin, right: 0) tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: kSPTabbarSafeBottomMargin, right: 0)
tableView.keyboardDismissMode = .onDrag tableView.keyboardDismissMode = .onDrag
tableView.showNormalEmpty(image: UIImage(named: "empty_image_03"))
SPSearchAssociativeCell.registerCell(tableView: tableView) SPSearchAssociativeCell.registerCell(tableView: tableView)
return tableView return tableView
}() }()

View File

@ -1,6 +1,6 @@
// //
// SPSearchHomeView.swift // SPSearchHomeView.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/17. // Created by on 2025/4/17.
// //

View File

@ -1,6 +1,6 @@
// //
// SPSearchInputView.swift // SPSearchInputView.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/17. // Created by on 2025/4/17.
// //

View File

@ -1,6 +1,6 @@
// //
// SPSearchResultCell.swift // SPSearchResultCell.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/18. // Created by on 2025/4/18.
// //

View File

@ -1,6 +1,6 @@
// //
// SPSearchResultView.swift // SPSearchResultView.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/18. // Created by on 2025/4/18.
// //

View File

@ -0,0 +1,19 @@
//
// SPHomeViewModel.swift
// MoviaBox
//
// Created by Overseas on 2025/4/22.
//
import UIKit
class SPHomeViewModel: NSObject {
var moduleModel: SPHomeModuleModel?
///
var playHistoryArr: [SPShortModel]?
}

View File

@ -1,6 +1,6 @@
// //
// SPSearchViewModel.swift // SPSearchViewModel.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/18. // Created by on 2025/4/18.
// //

View File

@ -1,6 +1,6 @@
// //
// SPLoginViewController.swift // SPLoginViewController.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/25. // Created by on 2025/4/25.
// //
@ -11,45 +11,40 @@ class SPLoginViewController: SPViewController {
private lazy var logoImageView: UIImageView = { private lazy var logoImageView: UIImageView = {
let imageView = UIImageView(image: UIImage(named: "login_logo_icon_01")) let imageView = UIImageView(image: UIImage(named: "login_logo_icon_01"))
imageView.layer.cornerRadius = 10
imageView.layer.masksToBounds = true
return imageView return imageView
}() }()
// private lazy var nameImageView: UIImageView = { private lazy var nameImageView: UIImageView = {
// let imageView = UIImageView(image: UIImage(named: "login_logo_icon_02")) let imageView = UIImageView(image: UIImage(named: "login_logo_icon_02"))
// return imageView return imageView
// }() }()
private lazy var stackView: UIStackView = { private lazy var stackView: UIStackView = {
let stackView = UIStackView(arrangedSubviews: [faceBookButton, appleButton]) let stackView = UIStackView(arrangedSubviews: [faceBookButton, appleButton])
stackView.axis = .vertical stackView.axis = .vertical
stackView.spacing = 20 stackView.spacing = 18
return stackView return stackView
}() }()
private lazy var faceBookButton: UIButton = { private lazy var faceBookButton: UIButton = {
let button = createButton(title: "movia_login_title_facebook".localized, titleColor: .colorFFFFFF(), icon: UIImage(named: "facebook_icon_01"), background: .color0866FF()) let button = createButton(title: "Login with Facebook", titleColor: .colorFFFFFF(), icon: UIImage(named: "facebook_icon_01"), background: .color0866FF())
button.addTarget(self, action: #selector(handleFaceBookButton), for: .touchUpInside)
return button return button
}() }()
private lazy var appleButton: UIButton = { private lazy var appleButton: UIButton = {
let button = createButton(title: "movia_login_title_apple".localized, titleColor: .color333333(), icon: UIImage(named: "apple_icon_01"), background: .colorFFFFFF()) let button = createButton(title: "Login with Apple", titleColor: .color333333(), icon: UIImage(named: "apple_icon_01"), background: .colorFFFFFF())
button.addTarget(self, action: #selector(handleAppleButton), for: .touchUpInside)
return button return button
}() }()
private lazy var agreementLabel: YYLabel = { private lazy var agreementLabel: YYLabel = {
let userAgreementStr = "movia_profile_User_Agreement".localized let agreementStr = "kLoginAgreementText".localized
let privacyPolicy = "movia_profile_Privacy_Policy".localized let userAgreementStr = "User Agreement".localized
let agreementStr = String(format: "movia_login_agreement_tip".localized, userAgreementStr, privacyPolicy) let privacyPolicy = "Privacy Policy".localized
let range1 = agreementStr.ocString().range(of: userAgreementStr) let range1 = agreementStr.ocString().range(of: userAgreementStr)
let range2 = agreementStr.ocString().range(of: privacyPolicy) let range2 = agreementStr.ocString().range(of: privacyPolicy)
let text = NSMutableAttributedString(string: agreementStr) let text = NSMutableAttributedString(string: agreementStr)
text.font = .fontMedium(ofSize: 12) text.font = .fontMedium(ofSize: 10)
text.color = .colorB0B0B3() text.color = .colorB0B0B3()
text.setTextHighlight(range1, color: .colorFFFFFF(), backgroundColor: nil) { [weak self] _, _, _, _ in text.setTextHighlight(range1, color: .colorFFFFFF(), backgroundColor: nil) { [weak self] _, _, _, _ in
@ -100,7 +95,7 @@ class SPLoginViewController: SPViewController {
button.setBackgroundImage(UIImage(color: background), for: .normal) button.setBackgroundImage(UIImage(color: background), for: .normal)
button.setTitle(title, for: .normal) button.setTitle(title, for: .normal)
button.setTitleColor(titleColor, for: .normal) button.setTitleColor(titleColor, for: .normal)
button.jx_font = .fontMedium(ofSize: 16) button.jx_font = .fontMedium(ofSize: 14)
button.space = 12 button.space = 12
button.setImage(icon, for: .normal) button.setImage(icon, for: .normal)
button.layer.cornerRadius = 8 button.layer.cornerRadius = 8
@ -114,32 +109,11 @@ class SPLoginViewController: SPViewController {
} }
extension SPLoginViewController {
@objc private func handleFaceBookButton() {
thirdLogin(type: .faceBook)
}
@objc private func handleAppleButton() {
thirdLogin(type: .apple)
}
private func thirdLogin(type: SPLoginManager.LoginType) {
SPHUD.show()
SPLoginManager.manager.thirdLogin(type: type, presentingViewController: self) { [weak self] isFinish in
SPHUD.dismiss()
guard let self = self else { return }
if isFinish {
self.dismiss(animated: true)
}
}
}
}
extension SPLoginViewController { extension SPLoginViewController {
private func _setupUI() { private func _setupUI() {
view.addSubview(logoImageView) view.addSubview(logoImageView)
// view.addSubview(nameImageView) view.addSubview(nameImageView)
view.addSubview(stackView) view.addSubview(stackView)
view.addSubview(agreementLabel) view.addSubview(agreementLabel)
// view.addSubview(faceBookButton) // view.addSubview(faceBookButton)
@ -147,18 +121,17 @@ extension SPLoginViewController {
logoImageView.snp.makeConstraints { make in logoImageView.snp.makeConstraints { make in
make.centerX.equalToSuperview() make.centerX.equalToSuperview()
make.top.equalToSuperview().offset(kSPStatusbarHeight + kSPMainW(120)) make.top.equalToSuperview().offset(kSPStatusbarHeight + kSPMainW(120))
make.width.height.equalTo(120)
} }
// nameImageView.snp.makeConstraints { make in nameImageView.snp.makeConstraints { make in
// make.centerX.equalToSuperview() make.centerX.equalToSuperview()
// make.top.equalTo(logoImageView.snp.bottom).offset(24) make.top.equalTo(logoImageView.snp.bottom).offset(24)
// } }
stackView.snp.makeConstraints { make in stackView.snp.makeConstraints { make in
make.left.equalToSuperview().offset(37) make.left.equalToSuperview().offset(37)
make.centerX.equalToSuperview() make.centerX.equalToSuperview()
make.top.equalTo(logoImageView.snp.bottom).offset(80) make.top.equalTo(nameImageView.snp.bottom).offset(40)
} }
let size = agreementLabel.textLayout?.textBoundingSize ?? .zero let size = agreementLabel.textLayout?.textBoundingSize ?? .zero

View File

@ -1,6 +1,6 @@
// //
// SPAboutUsViewController.swift // SPAboutUsViewController.swift
// ThimraTV // MoviaBox
// //
// Created by Overseas on 2025/4/19. // Created by Overseas on 2025/4/19.
// //
@ -11,12 +11,12 @@ class SPAboutUsViewController: SPViewController {
private lazy var dataArr: [SPMineItem] = { private lazy var dataArr: [SPMineItem] = {
let arr = [ let arr = [
SPMineItem(type: .userAgreement, title: "movia_profile_User_Agreement".localized), SPMineItem(type: .userAgreement, title: "User Agreement".localized),
SPMineItem(type: .privacyPolicy, title: "movia_profile_Privacy_Policy".localized), SPMineItem(type: .privacyPolicy, title: "Privacy Policy".localized),
SPMineItem(type: .informationProtection, title: "movia_child_protection_text".localized), SPMineItem(type: .informationProtection, title: "Child Personal Information Protection Rules".localized),
SPMineItem(type: .civizatioConvention, title: "movia_civizatio_convention_text".localized), SPMineItem(type: .civizatioConvention, title: "Youth Civilization Convention".localized),
SPMineItem(type: .informationSharing, title: "movia_information_sharing_text".localized), SPMineItem(type: .informationSharing, title: "List of Third-Party Sharing of Personal Information".localized),
SPMineItem(type: .persoInforDisclosure, title: "movia_persoInfor_disclosure_text".localized), SPMineItem(type: .persoInforDisclosure, title: "Explicit List of Personal Information Collection".localized),
] ]
return arr return arr
}() }()
@ -37,7 +37,7 @@ class SPAboutUsViewController: SPViewController {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
self.title = "movia_profile_About_Us".localized self.title = "About Us".localized
setBackgroundView(isShowGradient: false, bgImage: nil) setBackgroundView(isShowGradient: false, bgImage: nil)
_setupUI() _setupUI()
} }

View File

@ -1,6 +1,6 @@
// //
// SPFeedbackViewController.swift // SPFeedbackViewController.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/25. // Created by on 2025/4/25.
// //

View File

@ -1,6 +1,6 @@
// //
// SPMineViewController.swift // SPMineViewController.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/10. // Created by on 2025/4/10.
// //
@ -11,12 +11,11 @@ class SPMineViewController: SPViewController {
private lazy var dataArr: [SPMineItem] = { private lazy var dataArr: [SPMineItem] = {
let arr = [ let arr = [
SPMineItem(type: .language, iconImage: UIImage(named: "language_icon_01"), title: "movia_profile_Language".localized), // SPMineItem(type: .language, iconImage: UIImage(named: "language_icon_01"), title: "Language".localized),
SPMineItem(type: .feedBack, iconImage: UIImage(named: "feed_back_icon_01"), title: "movia_profile_Feedback".localized), SPMineItem(type: .feedBack, iconImage: UIImage(named: "feed_back_icon_01"), title: "FeedBack".localized),
SPMineItem(type: .privacyPolicy, iconImage: UIImage(named: "privacy_policy_icon_01"), title: "movia_profile_Privacy_Policy".localized), SPMineItem(type: .privacyPolicy, iconImage: UIImage(named: "privacy_policy_icon_01"), title: "Privacy Policy".localized),
SPMineItem(type: .userAgreement, iconImage: UIImage(named: "user_agreement_icon_01"), title: "movia_profile_User_Agreement".localized), SPMineItem(type: .userAgreement, iconImage: UIImage(named: "user_agreement_icon_01"), title: "User Agreement".localized),
SPMineItem(type: .aboutUs, iconImage: UIImage(named: "about_us_icon_01"), title: "movia_profile_About_Us".localized), SPMineItem(type: .aboutUs, iconImage: UIImage(named: "about_us_icon_01"), title: "About Us".localized),
SPMineItem(type: .settings, iconImage: UIImage(named: "settings_icon_01"), title: "movia_profile_Setting".localized),
] ]
return arr return arr
}() }()
@ -24,12 +23,10 @@ class SPMineViewController: SPViewController {
/// ///
private var isHaveEntered = false private var isHaveEntered = false
weak var vipAlertView: SPVipAlertView?
//MARK: UI  //MARK: UI 
private lazy var headerView: SPMineHeaderView = { private lazy var headerView: SPMineHeaderView = {
let view = SPMineHeaderView() let view = SPMineHeaderView()
view.frame = CGRect(x: 0, y: 0, width: kSPScreenWidth, height: view.contentHeight) view.frame = CGRect(x: 0, y: 0, width: kSPScreenWidth, height: view.contentHeight)
view.userInfo = SPLoginManager.manager.userInfo
return view return view
}() }()
@ -38,9 +35,6 @@ class SPMineViewController: SPViewController {
tableView.delegate = self tableView.delegate = self
tableView.dataSource = self tableView.dataSource = self
tableView.rowHeight = 50 tableView.rowHeight = 50
tableView.sp_addRefreshHeader(insetTop: 0) { [weak self] in
self?.handleHeaderRefresh(nil)
}
SPMineCell.registerCell(tableView: tableView) SPMineCell.registerCell(tableView: tableView)
return tableView return tableView
}() }()
@ -48,7 +42,6 @@ class SPMineViewController: SPViewController {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
setBackgroundView(isShowGradient: false) setBackgroundView(isShowGradient: false)
requestData() requestData()
_setupUI() _setupUI()
@ -61,16 +54,11 @@ class SPMineViewController: SPViewController {
override func viewDidAppear(_ animated: Bool) { override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated) super.viewDidAppear(animated)
self.headerView.userInfo = SPLoginManager.manager.userInfo
if isHaveEntered { if isHaveEntered {
requestData() requestData()
} }
isHaveEntered = true isHaveEntered = true
///VIP
showVipAlert()
} }
private func updateHeaderView() { private func updateHeaderView() {
@ -82,31 +70,6 @@ class SPMineViewController: SPViewController {
} }
override func handleHeaderRefresh(_ completer: (() -> Void)?) {
requestData { [weak self] in
self?.tableView.sp_endHeaderRefreshing()
}
}
}
extension SPMineViewController {
private func showVipAlert() {
guard SPLoginManager.manager.userInfo?.is_vip != true else { return }
guard SPVipAlertView.isShowAlert else { return }
SPWalletAPI.requestPayTemplate { model in
guard let list = model?.list_sub_vip, list.count > 0 else { return }
if !self.isDidAppear { return }
if self.vipAlertView != nil { return }
let alert = SPVipAlertView(dataArr: list).show(in: SPAPPTool.getKeyWindow())
alert.buyFinishHandle = { [weak self] in
guard let self = self else { return }
self.requestUserInfo()
}
self.vipAlertView = alert
}
}
} }
@ -158,15 +121,6 @@ extension SPMineViewController: UITableViewDelegate, UITableViewDataSource {
let vc = SPFeedbackViewController() let vc = SPFeedbackViewController()
self.navigationController?.pushViewController(vc, animated: true) self.navigationController?.pushViewController(vc, animated: true)
case .settings:
let vc = SPSettingsViewController()
self.navigationController?.pushViewController(vc, animated: true)
case .language:
let vc = SPLanguageViewController()
self.navigationController?.pushViewController(vc, animated: true)
default: default:
break break
} }
@ -175,29 +129,29 @@ extension SPMineViewController: UITableViewDelegate, UITableViewDataSource {
extension SPMineViewController { extension SPMineViewController {
private func requestData(completer: (() -> Void)? = nil) { private func requestData() {
requestUserInfo() requestUserInfo()
requestPlayHistoryList { requestPlayHistoryList()
completer?()
}
} }
/// ///
private func requestUserInfo() { private func requestUserInfo() {
SPLoginManager.manager.updateUserInfo { [weak self] in SPUserAPI.requestUserInfo { [weak self] userInfo in
self?.headerView.userInfo = SPLoginManager.manager.userInfo guard let self = self else { return }
if let userInfo = userInfo {
self.headerView.userInfo = userInfo
}
} }
} }
/// ///
private func requestPlayHistoryList(completer: (() -> Void)? = nil) { private func requestPlayHistoryList() {
SPVideoAPI.requestPlayHistoryList(page: 1, pageSize: 10) { [weak self] listModel in SPVideoAPI.requestPlayHistoryList(page: 1, pageSize: 3) { [weak self] listModel in
guard let self = self else { return } guard let self = self else { return }
if let list = listModel?.list { if let list = listModel?.list {
self.headerView.playHistoryArr = list self.headerView.playHistoryArr = list
self.updateHeaderView() self.updateHeaderView()
} }
completer?()
} }
} }

View File

@ -1,6 +1,6 @@
// //
// SPMineItem.swift // SPMineItem.swift
// ThimraTV // MoviaBox
// //
// Created by on 2025/4/17. // Created by on 2025/4/17.
// //
@ -31,25 +31,12 @@ struct SPMineItem {
case persoInforDisclosure case persoInforDisclosure
/// ///
case feedBack case feedBack
///
case settings
///
case consumptionRecords
///
case rewardCoins
///
case clearCache
///
case deleteAccount
///退
case logout
} }
var type: ItemType? var type: ItemType?
var iconImage: UIImage? var iconImage: UIImage?
var title: String? var title: String?
var subtitle: String?
} }

View File

@ -1,6 +1,6 @@
// //
// SPAboutUsCell.swift // SPAboutUsCell.swift
// ThimraTV // MoviaBox
// //
// Created by Overseas on 2025/4/23. // Created by Overseas on 2025/4/23.
// //
@ -44,7 +44,6 @@ extension SPAboutUsCell {
titleLabel.snp.makeConstraints { make in titleLabel.snp.makeConstraints { make in
make.centerY.equalToSuperview() make.centerY.equalToSuperview()
make.left.equalToSuperview().offset(16) make.left.equalToSuperview().offset(16)
make.right.lessThanOrEqualToSuperview().offset(-80)
} }
} }

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