登录页面,反馈首页
@ -7,6 +7,9 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
1BCF943F2DBB62FB008AEBE9 /* FacebookBasics in Frameworks */ = {isa = PBXBuildFile; productRef = 1BCF943E2DBB62FB008AEBE9 /* FacebookBasics */; };
|
||||
1BCF94412DBB62FB008AEBE9 /* FacebookCore in Frameworks */ = {isa = PBXBuildFile; productRef = 1BCF94402DBB62FB008AEBE9 /* FacebookCore */; };
|
||||
1BCF94432DBB62FB008AEBE9 /* FacebookLogin in Frameworks */ = {isa = PBXBuildFile; productRef = 1BCF94422DBB62FB008AEBE9 /* FacebookLogin */; };
|
||||
510C67DE404B0A4C9F4E89C3 /* Pods_Thimra.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EF2D7FDB1FE86E5CD9908162 /* Pods_Thimra.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
@ -43,7 +46,10 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
1BCF94432DBB62FB008AEBE9 /* FacebookLogin in Frameworks */,
|
||||
510C67DE404B0A4C9F4E89C3 /* Pods_Thimra.framework in Frameworks */,
|
||||
1BCF94412DBB62FB008AEBE9 /* FacebookCore in Frameworks */,
|
||||
1BCF943F2DBB62FB008AEBE9 /* FacebookBasics in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -134,6 +140,9 @@
|
||||
);
|
||||
mainGroup = 1DBC40502DA4EDFC0093FCB0;
|
||||
minimizedProjectReferenceProxies = 1;
|
||||
packageReferences = (
|
||||
1BCF943D2DBB62FB008AEBE9 /* XCRemoteSwiftPackageReference "facebook-ios-sdk" */,
|
||||
);
|
||||
preferredProjectObjectVersion = 77;
|
||||
productRefGroup = 1DBC405A2DA4EDFC0093FCB0 /* Products */;
|
||||
projectDirPath = "";
|
||||
@ -434,6 +443,35 @@
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
|
||||
/* Begin XCRemoteSwiftPackageReference section */
|
||||
1BCF943D2DBB62FB008AEBE9 /* XCRemoteSwiftPackageReference "facebook-ios-sdk" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/facebook/facebook-ios-sdk";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 14.1.0;
|
||||
};
|
||||
};
|
||||
/* End XCRemoteSwiftPackageReference section */
|
||||
|
||||
/* Begin XCSwiftPackageProductDependency section */
|
||||
1BCF943E2DBB62FB008AEBE9 /* FacebookBasics */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 1BCF943D2DBB62FB008AEBE9 /* XCRemoteSwiftPackageReference "facebook-ios-sdk" */;
|
||||
productName = FacebookBasics;
|
||||
};
|
||||
1BCF94402DBB62FB008AEBE9 /* FacebookCore */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 1BCF943D2DBB62FB008AEBE9 /* XCRemoteSwiftPackageReference "facebook-ios-sdk" */;
|
||||
productName = FacebookCore;
|
||||
};
|
||||
1BCF94422DBB62FB008AEBE9 /* FacebookLogin */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 1BCF943D2DBB62FB008AEBE9 /* XCRemoteSwiftPackageReference "facebook-ios-sdk" */;
|
||||
productName = FacebookLogin;
|
||||
};
|
||||
/* End XCSwiftPackageProductDependency section */
|
||||
};
|
||||
rootObject = 1DBC40512DA4EDFC0093FCB0 /* Project object */;
|
||||
}
|
||||
|
15
Thimra.xcworkspace/xcshareddata/swiftpm/Package.resolved
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"originHash" : "ca3cf5f8f83d297b47d2cb0edff3e06f294951e2e06fa55cfc82831103499b2a",
|
||||
"pins" : [
|
||||
{
|
||||
"identity" : "facebook-ios-sdk",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/facebook/facebook-ios-sdk",
|
||||
"state" : {
|
||||
"revision" : "c19607d535864533523d1f437c84035e5fb101cf",
|
||||
"version" : "14.1.0"
|
||||
}
|
||||
}
|
||||
],
|
||||
"version" : 3
|
||||
}
|
28
Thimra/AppDelegate/AppDelegate+OpenApp.swift
Normal file
@ -0,0 +1,28 @@
|
||||
//
|
||||
// AppDelegate+OpenApp.swift
|
||||
// Thimra
|
||||
//
|
||||
// Created by 佳尔 on 2025/4/25.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
|
||||
|
||||
extension SceneDelegate {
|
||||
|
||||
///URL打开APP
|
||||
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
|
||||
|
||||
}
|
||||
|
||||
///UniversalLink 打开app
|
||||
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
|
||||
guard let webpageURL = userActivity.webpageURL else { return }
|
||||
|
||||
guard let query = webpageURL.query else { return }
|
||||
|
||||
spLog(message: query)
|
||||
}
|
||||
|
||||
}
|
@ -23,14 +23,14 @@ class SPViewController: UIViewController, JYPageChildContollerProtocol {
|
||||
private(set) var isViewDidLoad = false
|
||||
private(set) var isDidAppear = false
|
||||
|
||||
private(set) lazy var _bgImageView: UIImageView = {
|
||||
private(set) lazy var bgImageView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "main_bg_image_01"))
|
||||
imageView.isUserInteractionEnabled = true
|
||||
return imageView;
|
||||
}()
|
||||
|
||||
///头部渐变色
|
||||
private lazy var toGradientView: SPGradientView = {
|
||||
private lazy var topGradientView: SPGradientView = {
|
||||
let view = SPGradientView()
|
||||
view.colors = [UIColor.color290D0F().cgColor, UIColor.color230E11().cgColor, UIColor.color181115().cgColor, UIColor.color121317(alpha: 0).cgColor]
|
||||
view.startPoint = .init(x: 0.5, y: 0)
|
||||
@ -44,8 +44,19 @@ class SPViewController: UIViewController, JYPageChildContollerProtocol {
|
||||
self.isViewDidLoad = true
|
||||
self.edgesForExtendedLayout = []
|
||||
|
||||
view.addSubview(topGradientView)
|
||||
view.addSubview(bgImageView)
|
||||
|
||||
setBgImageView()
|
||||
topGradientView.snp.makeConstraints { make in
|
||||
make.left.right.top.equalToSuperview()
|
||||
make.height.equalTo(kSPStatusbarHeight + 420)
|
||||
}
|
||||
|
||||
bgImageView.snp.makeConstraints { make in
|
||||
make.left.right.top.equalToSuperview()
|
||||
}
|
||||
|
||||
setBackgroundView()
|
||||
|
||||
if let navi = navigationController {
|
||||
if navi.visibleViewController == self {
|
||||
@ -56,15 +67,11 @@ class SPViewController: UIViewController, JYPageChildContollerProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
func setBgImageView() {
|
||||
self.view.backgroundColor = .backgroundColor()
|
||||
|
||||
self.view.addSubview(toGradientView)
|
||||
|
||||
toGradientView.snp.makeConstraints { make in
|
||||
make.left.right.top.equalToSuperview()
|
||||
make.height.equalTo(kSPStatusbarHeight + 420)
|
||||
}
|
||||
func setBackgroundView(isShowGradient: Bool = true, bgImage: UIImage? = UIImage(named: "main_bg_image_01"), backgroundColor: UIColor = UIColor.backgroundColor()) {
|
||||
topGradientView.isHidden = !isShowGradient
|
||||
bgImageView.isHidden = isShowGradient
|
||||
bgImageView.image = bgImage
|
||||
view.backgroundColor = backgroundColor
|
||||
}
|
||||
|
||||
override func viewDidAppear(_ animated: Bool) {
|
||||
|
23
Thimra/Base/Extension/Dictionary+SPAdd.swift
Normal file
@ -0,0 +1,23 @@
|
||||
//
|
||||
// Dictionary+SPAdd.swift
|
||||
// Thimra
|
||||
//
|
||||
// Created by 佳尔 on 2025/4/25.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
extension Dictionary {
|
||||
|
||||
func toJsonString() -> String? {
|
||||
do {
|
||||
let data = try JSONSerialization.data(withJSONObject: self)
|
||||
let jsonStr = String(data: data, encoding: .utf8)
|
||||
return jsonStr
|
||||
} catch {
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
}
|
@ -20,7 +20,7 @@ extension String: SmartCodable {
|
||||
|
||||
static func timeZone() -> String {
|
||||
let timeZone = NSTimeZone.local as NSTimeZone
|
||||
let timeZoneAbbreviation = timeZone.name.length() > 0 ? timeZone.name : "Unknown"
|
||||
// let timeZoneAbbreviation = timeZone.name.length() > 0 ? timeZone.name : "Unknown"
|
||||
let timeZoneSecondsFromGMT = timeZone.secondsFromGMT / 3600
|
||||
return String(format: "GMT+0%d:00", timeZoneSecondsFromGMT)
|
||||
}
|
||||
|
@ -192,5 +192,17 @@ extension UIColor {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,11 +20,13 @@ let SPBaseURL = "https://api-thimratv.thimratv.com"
|
||||
let SPURLPathPrefix = "/0a2c5b02"
|
||||
|
||||
let SPWebBaseURL = "https://www.thimratv.com"
|
||||
let SPCampaignWebURL = "https://campaign.thimratv.com"
|
||||
#else
|
||||
let SPBaseURL = "https://api-thimratv.thimratv.com"
|
||||
let SPURLPathPrefix = "/0a2c5b02"
|
||||
|
||||
let SPWebBaseURL = "https://www.thimratv.com"
|
||||
let SPCampaignWebURL = "https://campaign.thimratv.com"
|
||||
#endif
|
||||
|
||||
|
||||
@ -41,5 +43,8 @@ let SPPersoInforDisclosureWebUrl = SPWebBaseURL + "/persoInfor_disclosure"
|
||||
///全国青少年互联网文明公约
|
||||
let SPCivizatioConventionWebUrl = SPWebBaseURL + "/civizatio_convention"
|
||||
|
||||
///反馈首页
|
||||
let SPFeedBackHomeWebUrl = SPCampaignWebURL + "/pages/leave/index"
|
||||
|
||||
|
||||
|
||||
|
@ -13,7 +13,7 @@ class SPWebView: WKWebView {
|
||||
weak var delegate: SPWebViewDelegate?
|
||||
|
||||
private(set) var scriptMessageHandlerArray: [SPWebViewMessageName] = [
|
||||
WebMessageGetUserInfo,
|
||||
WebMessageAPP,
|
||||
]
|
||||
|
||||
|
||||
|
@ -10,8 +10,8 @@ import WebKit
|
||||
|
||||
typealias SPWebViewMessageName = String
|
||||
|
||||
///获取用户信息
|
||||
let WebMessageGetUserInfo: SPWebViewMessageName = "getUserInfo"
|
||||
///APP交互
|
||||
let WebMessageAPP: SPWebViewMessageName = "js2app"
|
||||
|
||||
|
||||
extension SPWebViewController {
|
||||
|
@ -29,17 +29,15 @@ class SPWebViewController: SPViewController {
|
||||
super.viewDidLoad()
|
||||
// self.edgesForExtendedLayout = .top
|
||||
configNavigationBack()
|
||||
|
||||
|
||||
setBackgroundView(isShowGradient: false, bgImage: nil)
|
||||
|
||||
_setupUI()
|
||||
|
||||
if let url = urlStr {
|
||||
self.load(urlString: url)
|
||||
}
|
||||
}
|
||||
|
||||
override func setBgImageView() {
|
||||
self.view.backgroundColor = .backgroundColor()
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
@ -79,7 +77,37 @@ extension SPWebViewController: SPWebViewDelegate {
|
||||
spLog(message: error)
|
||||
}
|
||||
|
||||
func webViewDidFinishLoad(_ webView: SPWebView) {
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in
|
||||
self?.receiveDataFromNative()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
|
||||
_webViewUserContentController(didReceive: message)
|
||||
}
|
||||
}
|
||||
|
||||
extension SPWebViewController {
|
||||
|
||||
func receiveDataFromNative() {
|
||||
let dic = [
|
||||
"token" : SPLoginManager.manager.token?.token ?? "",
|
||||
"time_zone" : String.timeZone(),
|
||||
"lang" : SPLocalizedManager.shared.currentLocalizedKey,
|
||||
"type" : "ios",
|
||||
"theme" : "theme_1",
|
||||
]
|
||||
|
||||
if let json = dic.toJsonString() {
|
||||
let js = "receiveDataFromNative(\(json))"
|
||||
self.webView.evaluateJavaScript(js) { _, error in
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ class SPAllShortViewController: SPViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
self.view.backgroundColor = .clear
|
||||
setBackgroundView(isShowGradient: false, bgImage: nil, backgroundColor: .clear)
|
||||
|
||||
requestCategoryList()
|
||||
requestDataArr(page: 1, completer: nil)
|
||||
@ -122,19 +122,10 @@ class SPAllShortViewController: SPViewController {
|
||||
override func viewDidLayoutSubviews() {
|
||||
super.viewDidLayoutSubviews()
|
||||
|
||||
let widht: CGFloat = 100
|
||||
let height = self.tagView.tagHeight
|
||||
let x = self.tagView.width - widht
|
||||
let y = self.tagView.height - height
|
||||
|
||||
// openGradientLayer.frame = CGRect(x: x, y: y, width: widht, height: height)
|
||||
openGradientLayer.frame = self.tagView.bounds
|
||||
}
|
||||
|
||||
override func setBgImageView() {
|
||||
|
||||
}
|
||||
|
||||
override func handleHeaderRefresh(_ completer: (() -> Void)?) {
|
||||
requestDataArr(page: 1) { [weak self] in
|
||||
self?.collectionView.sp_endHeaderRefreshing()
|
||||
|
149
Thimra/Class/Login/Controller/SPLoginViewController.swift
Normal file
@ -0,0 +1,149 @@
|
||||
//
|
||||
// SPLoginViewController.swift
|
||||
// Thimra
|
||||
//
|
||||
// Created by 佳尔 on 2025/4/25.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class SPLoginViewController: SPViewController {
|
||||
|
||||
private lazy var logoImageView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "login_logo_icon_01"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var nameImageView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "login_logo_icon_02"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var stackView: UIStackView = {
|
||||
let stackView = UIStackView(arrangedSubviews: [faceBookButton, appleButton])
|
||||
stackView.axis = .vertical
|
||||
stackView.spacing = 18
|
||||
return stackView
|
||||
}()
|
||||
|
||||
private lazy var faceBookButton: UIButton = {
|
||||
let button = createButton(title: "Login with Facebook", titleColor: .colorFFFFFF(), icon: UIImage(named: "facebook_icon_01"), background: .color0866FF())
|
||||
return button
|
||||
}()
|
||||
|
||||
private lazy var appleButton: UIButton = {
|
||||
let button = createButton(title: "Login with Apple", titleColor: .color333333(), icon: UIImage(named: "apple_icon_01"), background: .colorFFFFFF())
|
||||
return button
|
||||
}()
|
||||
|
||||
private lazy var agreementLabel: YYLabel = {
|
||||
let agreementStr = "kLoginAgreementText".localized
|
||||
let userAgreementStr = "User Agreement".localized
|
||||
let privacyPolicy = "Privacy Policy".localized
|
||||
let range1 = agreementStr.ocString().range(of: userAgreementStr)
|
||||
let range2 = agreementStr.ocString().range(of: privacyPolicy)
|
||||
|
||||
let text = NSMutableAttributedString(string: agreementStr)
|
||||
text.font = .fontMedium(ofSize: 10)
|
||||
text.color = .colorB0B0B3()
|
||||
|
||||
text.setTextHighlight(range1, color: .colorFFFFFF(), backgroundColor: nil) { [weak self] _, _, _, _ in
|
||||
guard let self = self else { return }
|
||||
let vc = SPWebViewController()
|
||||
vc.urlStr = SPUserAgreementWebUrl
|
||||
self.navigationController?.pushViewController(vc, animated: true)
|
||||
}
|
||||
|
||||
text.setTextHighlight(range2, color: .colorFFFFFF(), backgroundColor: nil) { [weak self] _, _, _, _ in
|
||||
guard let self = self else { return }
|
||||
let vc = SPWebViewController()
|
||||
vc.urlStr = SPPrivacyPolicyWebUrl
|
||||
self.navigationController?.pushViewController(vc, animated: true)
|
||||
}
|
||||
|
||||
let textContainer = YYTextContainer(size: CGSize(width: kSPScreenWidth - 150, height: 100))
|
||||
|
||||
let layout = YYTextLayout(container: textContainer, text: text)
|
||||
|
||||
let label = YYLabel()
|
||||
label.textLayout = layout
|
||||
label.textAlignment = .center
|
||||
label.numberOfLines = 0
|
||||
return label
|
||||
}()
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
self.edgesForExtendedLayout = .top
|
||||
setBackgroundView(isShowGradient: false)
|
||||
|
||||
configNavigationBack()
|
||||
|
||||
_setupUI()
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
self.navigationController?.setNavigationBarHidden(false, animated: true)
|
||||
|
||||
setNavigationNormalStyle(backgroundColor: .clear, isTranslucent: true)
|
||||
}
|
||||
|
||||
|
||||
private func createButton(title: String, titleColor: UIColor, icon: UIImage?, background: UIColor) -> UIButton {
|
||||
let button = JXButton(type: .custom)
|
||||
button.setBackgroundImage(UIImage(color: background), for: .normal)
|
||||
button.setTitle(title, for: .normal)
|
||||
button.setTitleColor(titleColor, for: .normal)
|
||||
button.jx_font = .fontMedium(ofSize: 14)
|
||||
button.space = 12
|
||||
button.setImage(icon, for: .normal)
|
||||
button.layer.cornerRadius = 8
|
||||
button.layer.masksToBounds = true
|
||||
button.snp.makeConstraints { make in
|
||||
make.height.equalTo(48)
|
||||
}
|
||||
return button
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
extension SPLoginViewController {
|
||||
|
||||
private func _setupUI() {
|
||||
view.addSubview(logoImageView)
|
||||
view.addSubview(nameImageView)
|
||||
view.addSubview(stackView)
|
||||
view.addSubview(agreementLabel)
|
||||
// view.addSubview(faceBookButton)
|
||||
|
||||
logoImageView.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalToSuperview().offset(kSPStatusbarHeight + kSPMainW(120))
|
||||
}
|
||||
|
||||
nameImageView.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalTo(logoImageView.snp.bottom).offset(24)
|
||||
}
|
||||
|
||||
stackView.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(37)
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalTo(nameImageView.snp.bottom).offset(40)
|
||||
}
|
||||
|
||||
let size = agreementLabel.textLayout?.textBoundingSize ?? .zero
|
||||
|
||||
agreementLabel.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.size.equalTo(size)
|
||||
// make.right.lessThanOrEqualToSuperview().offset(-50)
|
||||
make.bottom.equalToSuperview().offset(-(kSPTabbarSafeBottomMargin + 20))
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -38,7 +38,7 @@ class SPAboutUsViewController: SPViewController {
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
self.title = "About Us".localized
|
||||
|
||||
setBackgroundView(isShowGradient: false, bgImage: nil)
|
||||
_setupUI()
|
||||
}
|
||||
|
||||
@ -47,10 +47,6 @@ class SPAboutUsViewController: SPViewController {
|
||||
self.navigationController?.setNavigationBarHidden(false, animated: true)
|
||||
setNavigationNormalStyle()
|
||||
}
|
||||
|
||||
override func setBgImageView() {
|
||||
self.view.backgroundColor = .backgroundColor()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@ class SPMineViewController: SPViewController {
|
||||
private lazy var dataArr: [SPMineItem] = {
|
||||
let arr = [
|
||||
// SPMineItem(type: .language, iconImage: UIImage(named: "language_icon_01"), title: "Language".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: "Privacy Policy".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: "About Us".localized),
|
||||
@ -40,7 +41,7 @@ class SPMineViewController: SPViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
setBackgroundView(isShowGradient: false)
|
||||
requestData()
|
||||
|
||||
_setupUI()
|
||||
@ -102,22 +103,27 @@ extension SPMineViewController: UITableViewDelegate, UITableViewDataSource {
|
||||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
let item = dataArr[indexPath.row]
|
||||
switch item.type {
|
||||
case .privacyPolicy:
|
||||
let vc = SPWebViewController()
|
||||
vc.urlStr = SPPrivacyPolicyWebUrl
|
||||
self.navigationController?.pushViewController(vc, animated: true)
|
||||
|
||||
case .userAgreement:
|
||||
let vc = SPWebViewController()
|
||||
vc.urlStr = SPUserAgreementWebUrl
|
||||
self.navigationController?.pushViewController(vc, animated: true)
|
||||
|
||||
case .aboutUs:
|
||||
let vc = SPAboutUsViewController()
|
||||
self.navigationController?.pushViewController(vc, animated: true)
|
||||
|
||||
default:
|
||||
break
|
||||
case .privacyPolicy:
|
||||
let vc = SPWebViewController()
|
||||
vc.urlStr = SPPrivacyPolicyWebUrl
|
||||
self.navigationController?.pushViewController(vc, animated: true)
|
||||
|
||||
case .userAgreement:
|
||||
let vc = SPWebViewController()
|
||||
vc.urlStr = SPUserAgreementWebUrl
|
||||
self.navigationController?.pushViewController(vc, animated: true)
|
||||
|
||||
case .aboutUs:
|
||||
let vc = SPAboutUsViewController()
|
||||
self.navigationController?.pushViewController(vc, animated: true)
|
||||
|
||||
case .feedBack:
|
||||
let vc = SPWebViewController()
|
||||
vc.urlStr = SPFeedBackHomeWebUrl
|
||||
self.navigationController?.pushViewController(vc, animated: true)
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,8 @@ struct SPMineItem {
|
||||
case informationSharing
|
||||
///收集个人信息明示清单
|
||||
case persoInforDisclosure
|
||||
///反馈
|
||||
case feedBack
|
||||
}
|
||||
|
||||
|
||||
|
@ -122,8 +122,11 @@ class SPMineHeaderView: UIView {
|
||||
}
|
||||
|
||||
@objc private func handleLoginButton() {
|
||||
let vc = SPLoginViewController()
|
||||
let nav = SPNavigationController(rootViewController: vc)
|
||||
nav.modalPresentationStyle = .fullScreen
|
||||
|
||||
|
||||
self.viewController?.present(nav, animated: true)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -46,14 +46,13 @@ class SPCollectListViewController: SPMyListChildViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
setBackgroundView(isShowGradient: false, bgImage: nil, backgroundColor: .clear)
|
||||
|
||||
requestDataList(page: 1, completer: nil)
|
||||
|
||||
_setupUI()
|
||||
}
|
||||
|
||||
override func setBgImageView() { }
|
||||
|
||||
|
||||
override func handleHeaderRefresh(_ completer: (() -> Void)?) {
|
||||
|
@ -48,11 +48,11 @@ class SPPlayHistoryViewController: SPMyListChildViewController {
|
||||
|
||||
|
||||
requestDataList(page: 1, completer: nil)
|
||||
setBackgroundView(isShowGradient: false, bgImage: nil, backgroundColor: .clear)
|
||||
|
||||
_setupUI()
|
||||
}
|
||||
|
||||
override func setBgImageView() { }
|
||||
|
||||
|
||||
override func handleHeaderRefresh(_ completer: (() -> Void)?) {
|
||||
|
70
Thimra/Libs/Login/SPLoginManager+Apple.swift
Normal file
@ -0,0 +1,70 @@
|
||||
//
|
||||
// SPLoginManager+Apple.swift
|
||||
// Thimra
|
||||
//
|
||||
// Created by 佳尔 on 2025/4/25.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import AuthenticationServices
|
||||
|
||||
|
||||
extension SPLoginManager {
|
||||
|
||||
///苹果登录
|
||||
func appleSignLogin(completer: ((_ model: SPThirdSignModel?) -> Void)?) {
|
||||
// self.signAppleHandle = completer
|
||||
|
||||
let appleIDProvider = ASAuthorizationAppleIDProvider()
|
||||
let request = appleIDProvider.createRequest()
|
||||
request.requestedScopes = [.fullName, .email]
|
||||
|
||||
let authorizationController = ASAuthorizationController(authorizationRequests: [request])
|
||||
authorizationController.delegate = self
|
||||
authorizationController.presentationContextProvider = self
|
||||
authorizationController.performRequests()
|
||||
}
|
||||
}
|
||||
|
||||
//MARK:-------------- ASAuthorizationControllerDelegate --------------
|
||||
extension SPLoginManager: ASAuthorizationControllerDelegate {
|
||||
|
||||
func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
|
||||
if let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential {
|
||||
|
||||
let userIdentifier = appleIDCredential.user
|
||||
let fullName = appleIDCredential.fullName
|
||||
let email = appleIDCredential.email
|
||||
|
||||
let model = SPThirdSignModel()
|
||||
model.userID = userIdentifier
|
||||
model.givenName = fullName?.givenName
|
||||
model.familyName = fullName?.familyName
|
||||
model.name = fullName?.nickname
|
||||
model.email = email
|
||||
|
||||
spLog(message: userIdentifier)
|
||||
spLog(message: fullName)
|
||||
spLog(message: email)
|
||||
|
||||
// if let signAppleHandle = signAppleHandle {
|
||||
// signAppleHandle(model)
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
|
||||
// if let signAppleHandle = signAppleHandle {
|
||||
// signAppleHandle(nil)
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension SPLoginManager: ASAuthorizationControllerPresentationContextProviding {
|
||||
|
||||
func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
|
||||
return SPAPPTool.getKeyWindow()!
|
||||
}
|
||||
|
||||
}
|
15
Thimra/Libs/Login/SPLoginManager+Facebook.swift
Normal file
@ -0,0 +1,15 @@
|
||||
//
|
||||
// SPLoginManager+Facebook.swift
|
||||
// Thimra
|
||||
//
|
||||
// Created by 佳尔 on 2025/4/25.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
//https://developers.facebook.com/docs/facebook-login/ios?checkpoint_src=any
|
||||
extension SPLoginManager {
|
||||
|
||||
|
||||
|
||||
}
|
@ -9,6 +9,12 @@ import UIKit
|
||||
|
||||
class SPLoginManager: NSObject {
|
||||
|
||||
enum LoginType: Int {
|
||||
case apple
|
||||
case faceBook
|
||||
|
||||
}
|
||||
|
||||
static let manager = SPLoginManager()
|
||||
|
||||
private(set) var token: SPTokenModel?
|
||||
@ -27,6 +33,19 @@ class SPLoginManager: NSObject {
|
||||
UserDefaults.jx_setObject(token, forKey: kSPLoginTokenDefaultsKey)
|
||||
}
|
||||
|
||||
///第三方登录
|
||||
func thirdLogin(type: LoginType, presentingViewController: UIViewController) {
|
||||
|
||||
switch type {
|
||||
case .apple:
|
||||
appleSignLogin { model in
|
||||
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
24
Thimra/Libs/Login/SPThirdSignModel.swift
Normal file
@ -0,0 +1,24 @@
|
||||
//
|
||||
// SPThirdSignModel.swift
|
||||
// Thimra
|
||||
//
|
||||
// Created by 佳尔 on 2025/4/25.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class SPThirdSignModel: NSObject {
|
||||
|
||||
var token: String?
|
||||
|
||||
var userID: String?
|
||||
var email: String?
|
||||
var name: String?
|
||||
//姓
|
||||
var familyName: String?
|
||||
//名
|
||||
var givenName: String?
|
||||
|
||||
var avatar: String?
|
||||
|
||||
}
|
22
Thimra/Source/Assets.xcassets/icon/apple_icon_01.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Vector@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Vector@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
Thimra/Source/Assets.xcassets/icon/apple_icon_01.imageset/Vector@2x.png
vendored
Normal file
After Width: | Height: | Size: 692 B |
BIN
Thimra/Source/Assets.xcassets/icon/apple_icon_01.imageset/Vector@3x.png
vendored
Normal file
After Width: | Height: | Size: 1008 B |
22
Thimra/Source/Assets.xcassets/icon/facebook_icon_01.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Vector@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Vector@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
Thimra/Source/Assets.xcassets/icon/facebook_icon_01.imageset/Vector@2x.png
vendored
Normal file
After Width: | Height: | Size: 637 B |
BIN
Thimra/Source/Assets.xcassets/icon/facebook_icon_01.imageset/Vector@3x.png
vendored
Normal file
After Width: | Height: | Size: 871 B |
22
Thimra/Source/Assets.xcassets/icon/feed_back_icon_01.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Frame@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Frame@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
Thimra/Source/Assets.xcassets/icon/feed_back_icon_01.imageset/Frame@2x.png
vendored
Normal file
After Width: | Height: | Size: 915 B |
BIN
Thimra/Source/Assets.xcassets/icon/feed_back_icon_01.imageset/Frame@3x.png
vendored
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
Thimra/Source/Assets.xcassets/icon/login_logo_icon_01.imageset/APP图标 2@2x.png
vendored
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
Thimra/Source/Assets.xcassets/icon/login_logo_icon_01.imageset/APP图标 2@3x.png
vendored
Normal file
After Width: | Height: | Size: 46 KiB |
22
Thimra/Source/Assets.xcassets/icon/login_logo_icon_01.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "APP图标 2@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "APP图标 2@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
22
Thimra/Source/Assets.xcassets/icon/login_logo_icon_02.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Thimra@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Thimra@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
Thimra/Source/Assets.xcassets/icon/login_logo_icon_02.imageset/Thimra@2x.png
vendored
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
Thimra/Source/Assets.xcassets/icon/login_logo_icon_02.imageset/Thimra@3x.png
vendored
Normal file
After Width: | Height: | Size: 6.4 KiB |
@ -5,12 +5,12 @@
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "bg@2x.png",
|
||||
"filename" : "背景@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "bg@3x.png",
|
||||
"filename" : "背景@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 268 KiB |
Before Width: | Height: | Size: 416 KiB |
BIN
Thimra/Source/Assets.xcassets/image/main_bg_image_01.imageset/背景@2x.png
vendored
Normal file
After Width: | Height: | Size: 702 KiB |
BIN
Thimra/Source/Assets.xcassets/image/main_bg_image_01.imageset/背景@3x.png
vendored
Normal file
After Width: | Height: | Size: 1.3 MiB |
@ -20,6 +20,7 @@
|
||||
"Episodes" = "Episodes";
|
||||
"Save" = "Save";
|
||||
"Added" = "Added";
|
||||
"FeedBack" = "FeedBack";
|
||||
"Language" = "Language";
|
||||
"Privacy Policy" = "Privacy Policy";
|
||||
"User Agreement" = "User Agreement";
|
||||
@ -52,3 +53,7 @@
|
||||
"Log in" = "Log in";
|
||||
|
||||
|
||||
|
||||
"kLoginAgreementText" = "By continuing, you agree to the User Agreement and Privacy Policy";
|
||||
|
||||
|
||||
|