Commit 763e6cee authored by yqz's avatar yqz

学英语

parent 29992f2f
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "image@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
"scale" : "2x" "scale" : "2x"
}, },
{ {
"filename" : "dengluye@3x.png", "filename" : "Log_in_bg@3x.png",
"idiom" : "universal", "idiom" : "universal",
"scale" : "3x" "scale" : "3x"
} }
......
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "10000h+@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Welcome to SpeakEasy Learning@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "icon_send_off@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
...@@ -5,12 +5,11 @@ ...@@ -5,12 +5,11 @@
"scale" : "1x" "scale" : "1x"
}, },
{ {
"filename" : "Send@2x.png",
"idiom" : "universal", "idiom" : "universal",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"filename" : "Send@3x.png", "filename" : "icon_send_on@3x.png",
"idiom" : "universal", "idiom" : "universal",
"scale" : "3x" "scale" : "3x"
} }
......
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "bg_blue_home@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "button_guide_on@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "button_guide_on@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "button_no@3x(1).png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "button_no@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
"scale" : "1x" "scale" : "1x"
}, },
{ {
"filename" : "Google@2x 1@2x(1).png",
"idiom" : "universal", "idiom" : "universal",
"scale" : "2x" "scale" : "2x"
}, },
......
...@@ -18,7 +18,7 @@ extension AppDelegate { ...@@ -18,7 +18,7 @@ extension AppDelegate {
_ = SpeakCache.cache _ = SpeakCache.cache
SpeakDayEveryManager.manager.loadData(Date().toStr() ?? "") SpeakDayEveryManager.manager.loadData(Date().toStr() ?? "")
_ = SpeakLeassonData.data.leassionData _ = SpeakLeassonData.data.leassionData
// _ = SpeakVideoPlayer.share SpeakAIVideoPlayManager.share.loadVideo()
IAPViewModel.share.fetchProducts { product in // 初始化内购 IAPViewModel.share.fetchProducts { product in // 初始化内购
Print("内购列表\(product?.count ?? 0)") Print("内购列表\(product?.count ?? 0)")
} }
......
...@@ -89,7 +89,7 @@ func copyMatchingProperties<T, U>(from source: T, to destination: inout U) { ...@@ -89,7 +89,7 @@ func copyMatchingProperties<T, U>(from source: T, to destination: inout U) {
} }
func updateUserInformation() -> Void { func updateUserInformation(_ complate:((Bool)->Void)? = nil) -> Void {
if SpeakElePublicManager.share.userInfo.isLogin() { if SpeakElePublicManager.share.userInfo.isLogin() {
let name = SpeakElePublicManager.share.userInfo.userName ?? "" let name = SpeakElePublicManager.share.userInfo.userName ?? ""
let lanaguage = SpeakElePublicManager.share.userInfo.nativeLanguage ?? "" let lanaguage = SpeakElePublicManager.share.userInfo.nativeLanguage ?? ""
...@@ -104,7 +104,7 @@ func updateUserInformation() -> Void { ...@@ -104,7 +104,7 @@ func updateUserInformation() -> Void {
"targetLevel": level, "targetLevel": level,
"targetLanguage":en "targetLanguage":en
]) { su in ]) { su in
complate?(su)
} }
} }
} }
......
...@@ -37,6 +37,13 @@ extension UIColor { ...@@ -37,6 +37,13 @@ extension UIColor {
public func generate(_ size:CGSize = CGSize(width: 1, height: 1), public func generate(_ size:CGSize = CGSize(width: 1, height: 1),
_ cornerRadius:CGFloat = 0) -> UIImage? { _ cornerRadius:CGFloat = 0) -> UIImage? {
var size = size;
if size.width <= 0 {
size.width = 1
}
if size.height <= 0 {
size.height = 1
}
let rect = CGRect(origin: .zero, size: size) let rect = CGRect(origin: .zero, size: size)
UIGraphicsBeginImageContextWithOptions(size, false, 0.0) UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
guard let context = UIGraphicsGetCurrentContext() else { return nil } guard let context = UIGraphicsGetCurrentContext() else { return nil }
......
...@@ -51,6 +51,12 @@ class SpeakEleHomeViewCtr: SpeakEleBaseViewCtr, UIPopoverPresentationControllerD ...@@ -51,6 +51,12 @@ class SpeakEleHomeViewCtr: SpeakEleBaseViewCtr, UIPopoverPresentationControllerD
SpeakElePublicManager.share.userInfo.targetLanguage = "🇪🇸 Español" SpeakElePublicManager.share.userInfo.targetLanguage = "🇪🇸 Español"
self?.SpeakEnglistShow.setImage(UIImage(named: "sp-home-Es"), for: .normal) self?.SpeakEnglistShow.setImage(UIImage(named: "sp-home-Es"), for: .normal)
} }
updateUserInformation {[weak self] su in
if su {
self?.viewModel.fetchSesson()
self?.viewModel.fetchUserInfo()
}
}
} }
} }
return tip return tip
...@@ -101,7 +107,7 @@ class SpeakEleHomeViewCtr: SpeakEleBaseViewCtr, UIPopoverPresentationControllerD ...@@ -101,7 +107,7 @@ class SpeakEleHomeViewCtr: SpeakEleBaseViewCtr, UIPopoverPresentationControllerD
/// 改变学习的语言 /// 改变学习的语言
@IBAction func SpeakChangeLangu(_ sender: Any) { @IBAction func SpeakChangeLangu(_ sender: Any) {
if !IAPViewModel.share.isSubscribed { if IAPViewModel.share.isSubscribed {
self.view.bringSubviewToFront(tipView) self.view.bringSubviewToFront(tipView)
tipView.selectIdx = SpeakElePublicManager.share.userInfo.targetLanguage == "🇬🇧 English" ? 0 : 1 tipView.selectIdx = SpeakElePublicManager.share.userInfo.targetLanguage == "🇬🇧 English" ? 0 : 1
tipView.show() tipView.show()
...@@ -146,7 +152,6 @@ class SpeakEleHomeViewCtr: SpeakEleBaseViewCtr, UIPopoverPresentationControllerD ...@@ -146,7 +152,6 @@ class SpeakEleHomeViewCtr: SpeakEleBaseViewCtr, UIPopoverPresentationControllerD
override func viewWillAppear(_ animated: Bool) { override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated) super.viewWillAppear(animated)
SpeakPermission.requestNotificationPermission()
titleView.isHidden = true titleView.isHidden = true
setAISer() setAISer()
viewModel.fetchSesson() viewModel.fetchSesson()
...@@ -156,13 +161,22 @@ class SpeakEleHomeViewCtr: SpeakEleBaseViewCtr, UIPopoverPresentationControllerD ...@@ -156,13 +161,22 @@ class SpeakEleHomeViewCtr: SpeakEleBaseViewCtr, UIPopoverPresentationControllerD
self?.SpeakDataUpdate() self?.SpeakDataUpdate()
} }
} }
SpeakAIVideoPlayManager.share.loadVideo()
if SpeakElePublicManager.share.userInfo.targetLanguage == "🇬🇧 English" { if SpeakElePublicManager.share.userInfo.targetLanguage == "🇬🇧 English" {
self.SpeakEnglistShow.setImage(UIImage(named: "sp-home-En"), for: .normal) self.SpeakEnglistShow.setImage(UIImage(named: "sp-home-En"), for: .normal)
}else{ }else{
self.SpeakEnglistShow.setImage(UIImage(named: "sp-home-Es"), for: .normal) self.SpeakEnglistShow.setImage(UIImage(named: "sp-home-Es"), for: .normal)
} }
/// 新用户直接进课程
if SpeakElePublicManager.share.userInfo.newUser ?? true {
SpeakElePublicManager.share.userInfo.newUser = false
let vc = SpeakNewUserViewCtr()
vc.isReStart = true
vc.isMute = false
vc.view.callblack = { [weak self] tip in
self?.TipsSign(tip as? Bool ?? false)
}
self.navigationController?.pushViewController(vc, animated: true)
}
} }
} }
...@@ -173,14 +187,15 @@ extension SpeakEleHomeViewCtr { ...@@ -173,14 +187,15 @@ extension SpeakEleHomeViewCtr {
for (v) in self.lessonDataSource { for (v) in self.lessonDataSource {
if v.isLocked == false { if v.isLocked == false {
lessonId = v.lessonId ?? 0 lessonId = v.lessonId ?? 0
}else{
break
} }
} }
for (i,v) in lessonViews.enumerated() { for (i,v) in lessonViews.enumerated() {
let data = lessonDataSource[safe: i] let data = lessonDataSource[safe: i]
v.data = data v.data = data
v.SpeakLessionStart.isHidden = !(data?.lessonId == lessonId) v.SpeakLessionStart.isHidden = !(data?.lessonId == lessonId)
if data?.lessonId == lessonId {
offsetY = v.y - 70.0
}
} }
} }
...@@ -293,8 +308,6 @@ extension SpeakEleHomeViewCtr { ...@@ -293,8 +308,6 @@ extension SpeakEleHomeViewCtr {
for (v) in self.lessonDataSource { for (v) in self.lessonDataSource {
if v.isLocked == false { if v.isLocked == false {
lessonId = v.lessonId ?? 0 lessonId = v.lessonId ?? 0
}else{
break
} }
} }
for i in 1...6 { for i in 1...6 {
......
...@@ -126,8 +126,11 @@ ...@@ -126,8 +126,11 @@
</userDefinedRuntimeAttributes> </userDefinedRuntimeAttributes>
</view> </view>
<view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="REb-HE-Vml"> <view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="REb-HE-Vml">
<rect key="frame" x="24" y="119" width="345" height="79"/> <rect key="frame" x="24" y="103" width="345" height="79"/>
<subviews> <subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="icon_bg_blue_home" translatesAutoresizingMaskIntoConstraints="NO" id="7aS-Wk-Ktd">
<rect key="frame" x="0.0" y="0.0" width="345" height="79"/>
</imageView>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="sp-home-headerivar" translatesAutoresizingMaskIntoConstraints="NO" id="pAk-N9-Dv6"> <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="sp-home-headerivar" translatesAutoresizingMaskIntoConstraints="NO" id="pAk-N9-Dv6">
<rect key="frame" x="16" y="16" width="48" height="48"/> <rect key="frame" x="16" y="16" width="48" height="48"/>
<constraints> <constraints>
...@@ -147,7 +150,7 @@ ...@@ -147,7 +150,7 @@
</userDefinedRuntimeAttributes> </userDefinedRuntimeAttributes>
</imageView> </imageView>
<stackView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="245" verticalHuggingPriority="245" horizontalCompressionResistancePriority="745" verticalCompressionResistancePriority="745" axis="vertical" alignment="top" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="EgX-1V-LiS"> <stackView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="245" verticalHuggingPriority="245" horizontalCompressionResistancePriority="745" verticalCompressionResistancePriority="745" axis="vertical" alignment="top" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="EgX-1V-LiS">
<rect key="frame" x="80" y="15.666666666666657" width="126" height="49"/> <rect key="frame" x="80" y="15.666666666666671" width="126" height="49"/>
<subviews> <subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Amelia" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="GO5-4q-Wtk"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Amelia" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="GO5-4q-Wtk">
<rect key="frame" x="0.0" y="0.0" width="59.333333333333336" height="24"/> <rect key="frame" x="0.0" y="0.0" width="59.333333333333336" height="24"/>
...@@ -156,7 +159,7 @@ ...@@ -156,7 +159,7 @@
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Lde-SU-5MS"> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Lde-SU-5MS">
<rect key="frame" x="0.0" y="29" width="126" height="20"/> <rect key="frame" x="0.0" y="28.999999999999986" width="126" height="20"/>
<constraints> <constraints>
<constraint firstAttribute="height" constant="20" id="iK8-oc-A1D"/> <constraint firstAttribute="height" constant="20" id="iK8-oc-A1D"/>
</constraints> </constraints>
...@@ -181,7 +184,7 @@ ...@@ -181,7 +184,7 @@
</subviews> </subviews>
</stackView> </stackView>
<button opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="255" verticalHuggingPriority="255" horizontalCompressionResistancePriority="755" verticalCompressionResistancePriority="755" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="tji-S9-nFP"> <button opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="255" verticalHuggingPriority="255" horizontalCompressionResistancePriority="755" verticalCompressionResistancePriority="755" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="tji-S9-nFP">
<rect key="frame" x="240" y="23.666666666666657" width="87" height="32"/> <rect key="frame" x="240" y="23.666666666666671" width="87" height="32"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints> <constraints>
<constraint firstAttribute="width" constant="87" id="ayL-fl-zR2"/> <constraint firstAttribute="width" constant="87" id="ayL-fl-zR2"/>
...@@ -200,15 +203,19 @@ ...@@ -200,15 +203,19 @@
</userDefinedRuntimeAttributes> </userDefinedRuntimeAttributes>
</button> </button>
</subviews> </subviews>
<color key="backgroundColor" red="0.22352941176470587" green="0.50196078431372548" blue="0.96470588235294119" alpha="1" colorSpace="calibratedRGB"/> <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints> <constraints>
<constraint firstAttribute="trailing" secondItem="tji-S9-nFP" secondAttribute="trailing" constant="18" id="12u-v5-UR0"/> <constraint firstAttribute="trailing" secondItem="tji-S9-nFP" secondAttribute="trailing" constant="18" id="12u-v5-UR0"/>
<constraint firstItem="pAk-N9-Dv6" firstAttribute="top" secondItem="REb-HE-Vml" secondAttribute="top" constant="16" id="3rQ-4P-EMq"/> <constraint firstItem="pAk-N9-Dv6" firstAttribute="top" secondItem="REb-HE-Vml" secondAttribute="top" constant="16" id="3rQ-4P-EMq"/>
<constraint firstItem="tji-S9-nFP" firstAttribute="centerY" secondItem="REb-HE-Vml" secondAttribute="centerY" id="Al5-9M-UVy"/> <constraint firstItem="tji-S9-nFP" firstAttribute="centerY" secondItem="REb-HE-Vml" secondAttribute="centerY" id="Al5-9M-UVy"/>
<constraint firstAttribute="bottom" secondItem="7aS-Wk-Ktd" secondAttribute="bottom" id="KMU-9T-dgH"/>
<constraint firstItem="EgX-1V-LiS" firstAttribute="centerY" secondItem="pAk-N9-Dv6" secondAttribute="centerY" id="MOK-MF-8ZK"/> <constraint firstItem="EgX-1V-LiS" firstAttribute="centerY" secondItem="pAk-N9-Dv6" secondAttribute="centerY" id="MOK-MF-8ZK"/>
<constraint firstItem="EgX-1V-LiS" firstAttribute="leading" secondItem="pAk-N9-Dv6" secondAttribute="trailing" constant="16" id="Ndk-uL-Uhq"/> <constraint firstItem="EgX-1V-LiS" firstAttribute="leading" secondItem="pAk-N9-Dv6" secondAttribute="trailing" constant="16" id="Ndk-uL-Uhq"/>
<constraint firstItem="pAk-N9-Dv6" firstAttribute="leading" secondItem="REb-HE-Vml" secondAttribute="leading" constant="16" id="OLG-nC-Uwh"/> <constraint firstItem="pAk-N9-Dv6" firstAttribute="leading" secondItem="REb-HE-Vml" secondAttribute="leading" constant="16" id="OLG-nC-Uwh"/>
<constraint firstItem="7aS-Wk-Ktd" firstAttribute="top" secondItem="REb-HE-Vml" secondAttribute="top" id="PFT-M8-wBt"/>
<constraint firstAttribute="trailing" secondItem="7aS-Wk-Ktd" secondAttribute="trailing" id="TzI-w3-0wo"/>
<constraint firstAttribute="bottom" secondItem="pAk-N9-Dv6" secondAttribute="bottom" constant="15" id="ha2-7J-HlX"/> <constraint firstAttribute="bottom" secondItem="pAk-N9-Dv6" secondAttribute="bottom" constant="15" id="ha2-7J-HlX"/>
<constraint firstItem="7aS-Wk-Ktd" firstAttribute="leading" secondItem="REb-HE-Vml" secondAttribute="leading" id="oPp-t1-H2p"/>
</constraints> </constraints>
<userDefinedRuntimeAttributes> <userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="corners"> <userDefinedRuntimeAttribute type="number" keyPath="corners">
...@@ -221,7 +228,7 @@ ...@@ -221,7 +228,7 @@
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints> <constraints>
<constraint firstItem="REb-HE-Vml" firstAttribute="leading" secondItem="rqH-oW-agY" secondAttribute="leading" constant="24" id="Cvh-VK-8kb"/> <constraint firstItem="REb-HE-Vml" firstAttribute="leading" secondItem="rqH-oW-agY" secondAttribute="leading" constant="24" id="Cvh-VK-8kb"/>
<constraint firstItem="REb-HE-Vml" firstAttribute="top" secondItem="KYz-Od-c9d" secondAttribute="bottom" constant="26" id="FHQ-WP-3fM"/> <constraint firstItem="REb-HE-Vml" firstAttribute="top" secondItem="KYz-Od-c9d" secondAttribute="bottom" constant="10" id="FHQ-WP-3fM"/>
<constraint firstItem="KYz-Od-c9d" firstAttribute="top" secondItem="Ia2-3z-Nib" secondAttribute="top" constant="61" id="ISI-vx-5CZ"/> <constraint firstItem="KYz-Od-c9d" firstAttribute="top" secondItem="Ia2-3z-Nib" secondAttribute="top" constant="61" id="ISI-vx-5CZ"/>
<constraint firstAttribute="trailing" secondItem="KYz-Od-c9d" secondAttribute="trailing" constant="24" id="KEg-YG-8N8"/> <constraint firstAttribute="trailing" secondItem="KYz-Od-c9d" secondAttribute="trailing" constant="24" id="KEg-YG-8N8"/>
<constraint firstItem="KYz-Od-c9d" firstAttribute="leading" secondItem="Ia2-3z-Nib" secondAttribute="leading" constant="24" id="Kv8-Bt-b6l"/> <constraint firstItem="KYz-Od-c9d" firstAttribute="leading" secondItem="Ia2-3z-Nib" secondAttribute="leading" constant="24" id="Kv8-Bt-b6l"/>
...@@ -231,6 +238,7 @@ ...@@ -231,6 +238,7 @@
</view> </view>
</objects> </objects>
<resources> <resources>
<image name="icon_bg_blue_home" width="354" height="82"/>
<image name="sp-home-En" width="28" height="28"/> <image name="sp-home-En" width="28" height="28"/>
<image name="sp-home-book" width="20.333333969116211" height="20"/> <image name="sp-home-book" width="20.333333969116211" height="20"/>
<image name="sp-home-clock" width="20" height="20"/> <image name="sp-home-clock" width="20" height="20"/>
......
...@@ -77,6 +77,7 @@ class SpeakChangeStuLanguesView: UIView { ...@@ -77,6 +77,7 @@ class SpeakChangeStuLanguesView: UIView {
@IBAction func TOIjkjdklsf(_ sender: UIButton) { @IBAction func TOIjkjdklsf(_ sender: UIButton) {
if !sender.isSelected { if !sender.isSelected {
SpeakCache.cache.SaveModel(cache: SpeakPracticeLesLocalModel(lesson: [] ,select: 0), state: .PracticeCache, name: "Lesson")
if let call = callblack { if let call = callblack {
call( sender == SpeakChangeBtns.first ? 0 : 1) call( sender == SpeakChangeBtns.first ? 0 : 1)
} }
......
...@@ -82,8 +82,8 @@ class SpeakEleLessionView: UIView { ...@@ -82,8 +82,8 @@ class SpeakEleLessionView: UIView {
} }
private func setupUI() { private func setupUI() {
self.addSubview(backView) self.addSubview(backView)
backView.addSubview(button) backView.addSubview(button)
self.addSubview(nameLb) self.addSubview(nameLb)
...@@ -103,7 +103,7 @@ class SpeakEleLessionView: UIView { ...@@ -103,7 +103,7 @@ class SpeakEleLessionView: UIView {
} }
SpeakLessionStart.snp.makeConstraints { make in SpeakLessionStart.snp.makeConstraints { make in
make.bottom.equalTo(self.snp.top) make.bottom.equalTo(self.button.snp.top).offset(5.adapterH())
make.centerX.equalToSuperview() make.centerX.equalToSuperview()
} }
......
...@@ -15,7 +15,7 @@ class SpeakElePracticeReviewViewCtr: SpeakEleBaseViewCtr { ...@@ -15,7 +15,7 @@ class SpeakElePracticeReviewViewCtr: SpeakEleBaseViewCtr {
@IBOutlet var SpeakItemBtns: [UIButton]! @IBOutlet var SpeakItemBtns: [UIButton]!
private let viewModel = SpeakPracticeNetViewModel() private let viewModel = SpeakPracticeNetViewModel()
private let collectViewModel = SpeakEleProfileNetViewModel()
private var startStudyT:Date = Date() private var startStudyT:Date = Date()
@IBOutlet weak var SpeakTipsRight: UIView! @IBOutlet weak var SpeakTipsRight: UIView!
@IBOutlet weak var SpeakTipsLeft: UIView! @IBOutlet weak var SpeakTipsLeft: UIView!
...@@ -52,6 +52,17 @@ class SpeakElePracticeReviewViewCtr: SpeakEleBaseViewCtr { ...@@ -52,6 +52,17 @@ class SpeakElePracticeReviewViewCtr: SpeakEleBaseViewCtr {
UserDefaults.standard.setValue(true, forKey: UnsafeRawUserDefaultsKey.UnsafePracticeTipsShow.rawValue) UserDefaults.standard.setValue(true, forKey: UnsafeRawUserDefaultsKey.UnsafePracticeTipsShow.rawValue)
} }
} }
override func PopViewCtr() {
let name = SpeakElePublicManager.share.userInfo.targetLanguage ?? ""
let saveData = self.datasource.map { bt in
var temp = bt
temp.isFront = nil
return temp
}
SpeakCache.cache.SaveModel(cache: saveData, state: .PracticeCache, name: name)
super.PopViewCtr()
}
@objc private func tipsHide(_ res:UIGestureRecognizer) -> Void { @objc private func tipsHide(_ res:UIGestureRecognizer) -> Void {
let view = res.view let view = res.view
...@@ -127,6 +138,17 @@ class SpeakElePracticeReviewViewCtr: SpeakEleBaseViewCtr { ...@@ -127,6 +138,17 @@ class SpeakElePracticeReviewViewCtr: SpeakEleBaseViewCtr {
extension SpeakElePracticeReviewViewCtr : UICollectionViewDelegate,UICollectionViewDataSource , UICollectionViewDelegateFlowLayout{ extension SpeakElePracticeReviewViewCtr : UICollectionViewDelegate,UICollectionViewDataSource , UICollectionViewDelegateFlowLayout{
private func setFavaret(_ fw:Bool , indexPath:IndexPath) -> Void {
let d = self.datasource[indexPath.row].wordId
collectViewModel.collect(param: ["businessId":d,
"type":2,
"isCollect":fw]) {[weak self] su, data in
self?.datasource[indexPath.row].isCollected = su ? fw : !fw
let cell = self?.SpeakCollectionV.cellForItem(at: indexPath) as? SpeakPracticeReviewCell
cell?.data = self?.datasource[indexPath.row]
}
}
private func StrangeFamilar(state:SpeakPracticeReviewCell.SpeakPracticeReviewState) -> Void { private func StrangeFamilar(state:SpeakPracticeReviewCell.SpeakPracticeReviewState) -> Void {
let cell = SpeakCollectionV.cellForItem(at: IndexPath(row: currentIdx, section: 0)) let cell = SpeakCollectionV.cellForItem(at: IndexPath(row: currentIdx, section: 0))
...@@ -199,7 +221,7 @@ extension SpeakElePracticeReviewViewCtr : UICollectionViewDelegate,UICollectionV ...@@ -199,7 +221,7 @@ extension SpeakElePracticeReviewViewCtr : UICollectionViewDelegate,UICollectionV
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: SpeakPracticeReviewCell.id, for: indexPath) as! SpeakPracticeReviewCell let cell = collectionView.dequeueReusableCell(withReuseIdentifier: SpeakPracticeReviewCell.id, for: indexPath) as! SpeakPracticeReviewCell
cell.isHidden = (indexPath.row < currentIdx ? true : false) cell.isHidden = (indexPath.row < currentIdx ? true : false)
cell.data = datasource[indexPath.row] cell.data = datasource[indexPath.row]
cell.clipsToBounds = true // cell.clipsToBounds = true
cell.SpeakCallblack = { [weak self] state in cell.SpeakCallblack = { [weak self] state in
self?.StrangeFamilar(state: state) self?.StrangeFamilar(state: state)
} }
...@@ -214,6 +236,8 @@ extension SpeakElePracticeReviewViewCtr : UICollectionViewDelegate,UICollectionV ...@@ -214,6 +236,8 @@ extension SpeakElePracticeReviewViewCtr : UICollectionViewDelegate,UICollectionV
}else{ }else{
self?.SpeakItemBtns.forEach({$0.isSelected = false}) self?.SpeakItemBtns.forEach({$0.isSelected = false})
} }
}else if let fav = state as? Bool {
self?.setFavaret( fav,indexPath: indexPath)
} }
} }
return cell return cell
......
...@@ -19,6 +19,7 @@ class SpeakElePracticeViewCtr: SpeakEleBaseViewCtr { ...@@ -19,6 +19,7 @@ class SpeakElePracticeViewCtr: SpeakEleBaseViewCtr {
/// 课程 /// 课程
private var Session:[SpeakPracticeLessonModel] = [] private var Session:[SpeakPracticeLessonModel] = []
private var currentLess:SpeakPracticeLessonModel? private var currentLess:SpeakPracticeLessonModel?
private var selectIdx:Int = -1
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
...@@ -41,6 +42,12 @@ class SpeakElePracticeViewCtr: SpeakEleBaseViewCtr { ...@@ -41,6 +42,12 @@ class SpeakElePracticeViewCtr: SpeakEleBaseViewCtr {
learnedW.view.callblack = { [weak self] data in learnedW.view.callblack = { [weak self] data in
if let da = data as? SpeakPracticeLessonModel { if let da = data as? SpeakPracticeLessonModel {
if self?.currentLess?.lessonId != da.lessonId { if self?.currentLess?.lessonId != da.lessonId {
for (i,v) in (self?.Session ?? []).enumerated() {
if v.lessonId == da.lessonId {
self?.selectIdx = i
break
}
}
self?.currentLess = da self?.currentLess = da
self?.SpeakselectSession() self?.SpeakselectSession()
} }
...@@ -51,7 +58,11 @@ class SpeakElePracticeViewCtr: SpeakEleBaseViewCtr { ...@@ -51,7 +58,11 @@ class SpeakElePracticeViewCtr: SpeakEleBaseViewCtr {
@IBAction func SpeakReviewTaps(_ sender: Any) { @IBAction func SpeakReviewTaps(_ sender: Any) {
if self.currentLess != nil { if self.currentLess != nil {
let review = SpeakElePracticeReviewViewCtr() let review = SpeakElePracticeReviewViewCtr()
review.datasource = dataSource review.datasource = dataSource.map({ bd in
var temp = bd
temp.isFront = nil
return temp
})
review.leassion = self.currentLess?.lessonId ?? 0 review.leassion = self.currentLess?.lessonId ?? 0
self.parent?.navigationController?.pushViewController(review, animated: true) self.parent?.navigationController?.pushViewController(review, animated: true)
} }
...@@ -60,20 +71,33 @@ class SpeakElePracticeViewCtr: SpeakEleBaseViewCtr { ...@@ -60,20 +71,33 @@ class SpeakElePracticeViewCtr: SpeakEleBaseViewCtr {
override func viewWillAppear(_ animated: Bool) { override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated) super.viewWillAppear(animated)
titleView.isHidden = true titleView.isHidden = true
let model:SpeakPracticeLesLocalModel? = SpeakCache.cache.LoadMode(state: .PracticeCache, name: "Lesson")
self.Session = model?.lesson ?? []
self.selectIdx = model?.select ?? 0
if self.selectIdx >= 0 && self.selectIdx < (model?.lesson?.count ?? 0) && (model?.lesson?.count ?? 0) > 0 {
self.currentLess = self.Session[self.selectIdx]
}
let name = SpeakElePublicManager.share.userInfo.targetLanguage ?? "" let name = SpeakElePublicManager.share.userInfo.targetLanguage ?? ""
let data:[SpeakPracticeWordModel] = SpeakCache.cache.LoadMode(state: .MessageCache, name: name) ?? [] let data:[SpeakPracticeWordModel] = SpeakCache.cache.LoadMode(state: .PracticeCache, name: name) ?? []
if data.count <= 0 { if self.Session.count <= 0 {
self.getLeasion() self.getLeasion()
}else{ }else{
SpeakSectionL.text = currentLess?.lessonName
if data.count != self.dataSource.count { if data.count != self.dataSource.count {
self.dataSource = data self.dataSource = data
setPage(current: 1)
self.SpeakCollection.reloadData() self.SpeakCollection.reloadData()
}else{
for (i,var v) in self.dataSource.enumerated() {
if let cell = SpeakCollection.cellForItem(at: IndexPath(row: i, section: 0)) as? SpeakElePracticeViewCell {
v.isCollected = data[i].isCollected
cell.data = v
}
}
} }
} }
} }
private var dataSource:[SpeakPracticeWordModel] = [] private var dataSource:[SpeakPracticeWordModel] = []
} }
extension SpeakElePracticeViewCtr :UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout { extension SpeakElePracticeViewCtr :UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout {
...@@ -93,7 +117,7 @@ extension SpeakElePracticeViewCtr :UICollectionViewDelegate,UICollectionViewData ...@@ -93,7 +117,7 @@ extension SpeakElePracticeViewCtr :UICollectionViewDelegate,UICollectionViewData
viewModel.learnedLesson {[weak self] (success, data:[SpeakPracticeLessonModel]?) in viewModel.learnedLesson {[weak self] (success, data:[SpeakPracticeLessonModel]?) in
if success { if success {
self?.Session = data ?? [] self?.Session = data ?? []
self?.currentLess = data?.first self?.currentLess = data?[safe:self?.selectIdx ?? 0]
self?.SpeakselectSession() self?.SpeakselectSession()
} }
} }
...@@ -104,10 +128,14 @@ extension SpeakElePracticeViewCtr :UICollectionViewDelegate,UICollectionViewData ...@@ -104,10 +128,14 @@ extension SpeakElePracticeViewCtr :UICollectionViewDelegate,UICollectionViewData
viewModel.leassionWord(param: ["lessonId":self.currentLess?.lessonId ?? ""]) {[weak self] (su, data:[SpeakPracticeWordModel]? ) in viewModel.leassionWord(param: ["lessonId":self.currentLess?.lessonId ?? ""]) {[weak self] (su, data:[SpeakPracticeWordModel]? ) in
if su { if su {
self?.dataSource = data ?? [] self?.dataSource = data ?? []
let point = self?.SpeakCollection.contentOffset ?? CGPoint()
let name = SpeakElePublicManager.share.userInfo.targetLanguage ?? "" let name = SpeakElePublicManager.share.userInfo.targetLanguage ?? ""
SpeakCache.cache.SaveModel(cache: self?.dataSource, state: .PracticeCache, name: name) SpeakCache.cache.SaveModel(cache: self?.dataSource, state: .PracticeCache, name: name)
self?.setPage(current: ( Int(round(point.x/(self?.SpeakCollection.width ?? 1))) + 1) )
let model = SpeakPracticeLesLocalModel(lesson: self?.Session, select: self?.selectIdx)
SpeakCache.cache.SaveModel(cache: model, state: .PracticeCache, name: "Lesson")
self?.setPage(current: 1 )
self?.SpeakCollection.reloadData() self?.SpeakCollection.reloadData()
} }
} }
...@@ -125,10 +153,9 @@ extension SpeakElePracticeViewCtr :UICollectionViewDelegate,UICollectionViewData ...@@ -125,10 +153,9 @@ extension SpeakElePracticeViewCtr :UICollectionViewDelegate,UICollectionViewData
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: SpeakElePracticeViewCell.id, for: indexPath) as! SpeakElePracticeViewCell let cell = collectionView.dequeueReusableCell(withReuseIdentifier: SpeakElePracticeViewCell.id, for: indexPath) as! SpeakElePracticeViewCell
var data = self.dataSource[indexPath.row] var data = self.dataSource[indexPath.row]
cell.data = data cell.data = data
cell.SpeakPracticeNormal.SpeakPracticeIcon.image = UIImage(named: "sp-Practicebg-\(((data.wordId ?? 0)%14)+1)")
cell.callblack = {[weak self] fw in cell.callblack = {[weak self] fw in
if let i = fw as? Int { if let i = fw as? String {
data.isFront = (i == 1 ? true : false) data.isFront = (i == "1" ? true : false)
self?.dataSource[indexPath.row] = data self?.dataSource[indexPath.row] = data
}else{ }else{
self?.setFavaret( (fw as? Bool ?? false) ,indexPath: indexPath) self?.setFavaret( (fw as? Bool ?? false) ,indexPath: indexPath)
......
...@@ -7,6 +7,12 @@ ...@@ -7,6 +7,12 @@
import UIKit import UIKit
struct SpeakPracticeLesLocalModel : Codable {
var lesson:[SpeakPracticeLessonModel]?
var select:Int?
}
struct SpeakPracticeLessonModel: Codable { struct SpeakPracticeLessonModel: Codable {
var lessonId : Int? var lessonId : Int?
var lessonName : String? var lessonName : String?
......
...@@ -40,6 +40,7 @@ class SpeakElePracticeViewCell: UICollectionViewCell { ...@@ -40,6 +40,7 @@ class SpeakElePracticeViewCell: UICollectionViewCell {
}else if !isShow{ }else if !isShow{
self.HideDescp() self.HideDescp()
} }
SpeakPracticeNormal.SpeakPracticeIcon.image = UIImage(named: "sp-Practicebg-\(((data?.wordId ?? 0)%14)+1)")
} }
} }
...@@ -84,7 +85,6 @@ class SpeakElePracticeViewCell: UICollectionViewCell { ...@@ -84,7 +85,6 @@ class SpeakElePracticeViewCell: UICollectionViewCell {
call(fw) call(fw)
} }
} }
} }
override func layoutSubviews() { override func layoutSubviews() {
...@@ -107,7 +107,7 @@ class SpeakElePracticeViewCell: UICollectionViewCell { ...@@ -107,7 +107,7 @@ class SpeakElePracticeViewCell: UICollectionViewCell {
completion: { [weak self] _ in completion: { [weak self] _ in
self?.isShowingFront.toggle() self?.isShowingFront.toggle()
guard let call = self?.callblack else { return } guard let call = self?.callblack else { return }
call( (self?.isShowingFront ?? true ? 1 : 0) ) call( (self?.isShowingFront ?? true ? "1" : "0") )
} }
) )
} }
......
...@@ -15,8 +15,14 @@ class SpeakPracticeReviewCell: UICollectionViewCell { ...@@ -15,8 +15,14 @@ class SpeakPracticeReviewCell: UICollectionViewCell {
@IBOutlet var SpeakRightTips: UIView! @IBOutlet var SpeakRightTips: UIView!
@IBOutlet weak var SpeakRightLabel: UILabel! @IBOutlet weak var SpeakRightLabel: UILabel!
private let viewmodel = SpeakPracticeNetViewModel()
static let id = "SpeakPracticeReviewCell" static let id = "SpeakPracticeReviewCell"
private let leftMax:Double = -70
private let rightMax:Double = 70
var isShowingFront = true
var wordDetail:SpeakPracticeWordDetailModel?
enum SpeakPracticeReviewState { enum SpeakPracticeReviewState {
case left case left
case right case right
...@@ -26,20 +32,51 @@ class SpeakPracticeReviewCell: UICollectionViewCell { ...@@ -26,20 +32,51 @@ class SpeakPracticeReviewCell: UICollectionViewCell {
private var beginP = CGPoint() private var beginP = CGPoint()
var SpeakCallblack: ((_ state:SpeakPracticeReviewState)-> Void)? var SpeakCallblack: ((_ state:SpeakPracticeReviewState)-> Void)?
private var isShow:Bool{
set {}
get {
return IAPViewModel.share.isSubscribed || SpeakDayEveryManager.manager.SpeakDayData.PracticeFreeNum ?? 0 > 0
}
}
var data:SpeakPracticeWordModel? { var data:SpeakPracticeWordModel? {
didSet{ didSet{
isShowingFront = data?.isFront ?? true
UIView.transition(with: isShowingFront ? Word : back , duration: 0, options: [.transitionFlipFromRight]) { }
Word.SpeakPracticeWord.text = data?.word Word.SpeakPracticeWord.text = data?.word
Word.setLabel(data?.markStatus == 1 ? 1 : (data?.markStatus == 2 ? 2 : 0 ) ) Word.setLabel(data?.markStatus == 1 ? 1 : (data?.markStatus == 2 ? 2 : 0 ) )
Word.SpeakPracticeIcon.image = UIImage(named: "sp-Practicebg-\(((data?.wordId ?? 0)%14)+1)") Word.SpeakPracticeIcon.image = UIImage(named: "sp-Practicebg-\(((data?.wordId ?? 0)%14)+1)")
Word.clipsToBounds = true Word.clipsToBounds = true
Word.corners = 16 Word.corners = 16
Word.backgroundColor = .clear Word.backgroundColor = .clear
Word.SpeakPracticeFavorites.isSelected = data?.isCollected ?? false
back.SpeakPracticeBackWord.text = data?.word
back.SpeakPracticeBackFavorites.isSelected = data?.isCollected ?? false
Word.isHidden = !isShowingFront
back.isHidden = isShowingFront
back.corners = 16
wordDetail = SpeakWordTranslateData.data.WordTranslate?[data?.wordId ?? 0]
if let translation = wordDetail?.translation {
translationFunc()
}else{
translationHide()
}
} }
} }
override func awakeFromNib() { override func awakeFromNib() {
super.awakeFromNib() super.awakeFromNib()
self.gesture(target: self, class: UIPanGestureRecognizer.self, selector: #selector(panGesture(_:))) self.gesture(target: self, class: UIPanGestureRecognizer.self, selector: #selector(panGesture(_:)))
self.gesture(target: self, class: UITapGestureRecognizer.self, selector: #selector(FlipTaps))
back.snp.makeConstraints { make in
make.left.right.bottom.top.equalToSuperview()
}
Word.snp.makeConstraints { make in Word.snp.makeConstraints { make in
make.left.right.bottom.top.equalToSuperview() make.left.right.bottom.top.equalToSuperview()
} }
...@@ -53,10 +90,71 @@ class SpeakPracticeReviewCell: UICollectionViewCell { ...@@ -53,10 +90,71 @@ class SpeakPracticeReviewCell: UICollectionViewCell {
super.layoutSubviews() super.layoutSubviews()
contentView.bringSubviewToFront(SpeakLeftTips) contentView.bringSubviewToFront(SpeakLeftTips)
contentView.bringSubviewToFront(SpeakRightTips) contentView.bringSubviewToFront(SpeakRightTips)
self.layoutIfNeeded()
back.shadow(cornerRadius: 16, shadowColor: .init(hex: 0x000000), offset: CGSize(width: 0, height: 0), opacity: 0.06, radius: 4)
} }
private let leftMax:Double = -70 private lazy var Word: SpeakPracticeWordView = {
private let rightMax:Double = 70 let w = SpeakPracticeWordView()
contentView.addSubview(w)
w.callblack = { [weak self] fw in
if let call = self?.callblack {
call(fw)
}
}
return w
}()
private lazy var back: SpeakPracticeBackView = {
let b = SpeakPracticeBackView.xib()
b.callblack = { [weak self] fw in
if let call = self?.callblack {
call(fw)
}
}
contentView.addSubview(b)
return b
}()
deinit {
SpeakCallblack = nil
}
}
extension SpeakPracticeReviewCell {
private func netwokng() -> Void {
viewmodel.cardTranslate(param: ["word":data?.word ?? ""]) {[weak self] (success, data:SpeakPracticeWordDetailModel?) in
if success {
self?.wordDetail = data
SpeakWordTranslateData.data.WordTranslate?[self?.data?.wordId ?? 0] = data
SpeakDayEveryManager.manager.SpeakDayData.PracticeFreeNum! -= 1
SpeakDayEveryManager.manager.update()
self?.translationHide()
}
}
}
@objc private func FlipTaps() -> Void {
if wordDetail == nil && isShow == true {
self.netwokng()
}else if wordDetail == nil {
self.translationHide()
}
UIView.transition(
from: isShowingFront ? Word : back,
to: isShowingFront ? back : Word,
duration: 12/60.0,
options: [.transitionFlipFromRight, .showHideTransitionViews],
completion: { [weak self] _ in
self?.isShowingFront.toggle()
guard let call = self?.callblack else { return }
// call( (self?.isShowingFront ?? true ? 1 : 0) )
}
)
}
@objc private func panGesture(_ recognizer:UIGestureRecognizer) -> Void { @objc private func panGesture(_ recognizer:UIGestureRecognizer) -> Void {
let p = recognizer.location(in: self) let p = recognizer.location(in: self)
...@@ -99,13 +197,19 @@ class SpeakPracticeReviewCell: UICollectionViewCell { ...@@ -99,13 +197,19 @@ class SpeakPracticeReviewCell: UICollectionViewCell {
} }
} }
private lazy var Word: SpeakPracticeWordView = {
let w = SpeakPracticeWordView()
contentView.addSubview(w)
return w
}()
deinit { private func translationFunc() -> Void {
SpeakCallblack = nil back.SpeakPracticeBackWord1.text = wordDetail?.translation
back.SpeakPracticeBackUnlock.isHidden = true
let anto = "Antonym:".attributed().color(.init(hex: 0x3980F6)).build()
let Example = "Example sentence:".attributed().color(.init(hex: 0x3980F6)).build()
let att = "Synonyms:".attributed().color(.init(hex: 0x3980F6)).build().combined(with: [wordDetail?.synonyms,"\n\n",anto,wordDetail?.antonym,"\n\n" ,Example,wordDetail?.example])
back.SpeakPracticeBackDesc.attributedText = att
}
private func translationHide() -> Void {
back.SpeakPracticeBackWord1.text = wordDetail?.translation
back.SpeakPracticeBackUnlock.isHidden = false
back.SpeakPracticeBackDesc.attributedText = "".attributed().build()
} }
} }
...@@ -216,7 +216,7 @@ extension SpeakEleProfileViewCtr { ...@@ -216,7 +216,7 @@ extension SpeakEleProfileViewCtr {
SpeakElePublicManager.share.PublicData.state = .start SpeakElePublicManager.share.PublicData.state = .start
let nav = SpeakEleBaseNavigationCtr(rootViewController: SpeakEleLoginGuideCtr()) let nav = SpeakEleBaseNavigationCtr(rootViewController: SpeakEleLoginGuideCtr())
SpWindow.switchToController(nav) SpWindow.rootViewController = (nav)
} }
} }
...@@ -63,7 +63,7 @@ class SpeakProfileMoreViewCtr: SpeakEleBaseViewCtr { ...@@ -63,7 +63,7 @@ class SpeakProfileMoreViewCtr: SpeakEleBaseViewCtr {
get{ get{
if state == .TargetLanguage { if state == .TargetLanguage {
var iap = ["🇬🇧 English"] var iap = ["🇬🇧 English"]
if !IAPViewModel.share.isSubscribed { if IAPViewModel.share.isSubscribed {
iap.append("🇪🇸 Español") iap.append("🇪🇸 Español")
} }
return iap return iap
......
...@@ -39,6 +39,9 @@ class SpeakEleProgressViewCtr: SpeakEleBaseViewCtr { ...@@ -39,6 +39,9 @@ class SpeakEleProgressViewCtr: SpeakEleBaseViewCtr {
if let cell = self?.SpeakTableView.cellForRow(at: IndexPath(row: 1, section: 0)) as? SpeakProgressStudyCell { if let cell = self?.SpeakTableView.cellForRow(at: IndexPath(row: 1, section: 0)) as? SpeakProgressStudyCell {
cell.data = self?.dayStudy ?? [] cell.data = self?.dayStudy ?? []
} }
if let cell = self?.SpeakTableView.cellForRow(at: IndexPath(row: 0, section: 0)) as? SpeakProgressSignCell {
cell.signList = speakSignListViewModel.share.signList
}
} }
} }
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
// //
import UIKit import UIKit
import AVFAudio
class SpeakEleCallAIViewCtr: SpeakEleBaseViewCtr { class SpeakEleCallAIViewCtr: SpeakEleBaseViewCtr {
...@@ -57,7 +58,6 @@ class SpeakEleCallAIViewCtr: SpeakEleBaseViewCtr { ...@@ -57,7 +58,6 @@ class SpeakEleCallAIViewCtr: SpeakEleBaseViewCtr {
} }
} }
private var studyTime = 0 private var studyTime = 0
private var offset:Int = 0 { private var offset:Int = 0 {
didSet{ didSet{
...@@ -75,7 +75,6 @@ class SpeakEleCallAIViewCtr: SpeakEleBaseViewCtr { ...@@ -75,7 +75,6 @@ class SpeakEleCallAIViewCtr: SpeakEleBaseViewCtr {
SpeakAskContentV.isHidden = true SpeakAskContentV.isHidden = true
SpeakEleLoadingView.isHidden = true SpeakEleLoadingView.isHidden = true
SpeakLastMsg.isHidden = true SpeakLastMsg.isHidden = true
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
SpeakDisplayV.gesture(target: self, class: UITapGestureRecognizer.self, selector: #selector(SpeakDisplayTaps)) SpeakDisplayV.gesture(target: self, class: UITapGestureRecognizer.self, selector: #selector(SpeakDisplayTaps))
SpeakAskAgainV.gesture(target: self, class: UITapGestureRecognizer.self, selector: #selector(SpeakAskAgain)) SpeakAskAgainV.gesture(target: self, class: UITapGestureRecognizer.self, selector: #selector(SpeakAskAgain))
...@@ -100,6 +99,7 @@ class SpeakEleCallAIViewCtr: SpeakEleBaseViewCtr { ...@@ -100,6 +99,7 @@ class SpeakEleCallAIViewCtr: SpeakEleBaseViewCtr {
SpeakCache.cache.saveData(data: d, fileName: "\(save.recordId ?? 0)") SpeakCache.cache.saveData(data: d, fileName: "\(save.recordId ?? 0)")
} }
} }
self?.SpeakLastMsgDescp.text = audio.contentList?.last?.content ?? ""
DispatchQueue.main.async { DispatchQueue.main.async {
if Audioplay.count > 0 { if Audioplay.count > 0 {
AudioPlayerManager.shared.setupAudioPlayer(with: Audioplay.first! ,isMuted: self?.isMate ?? false) AudioPlayerManager.shared.setupAudioPlayer(with: Audioplay.first! ,isMuted: self?.isMate ?? false)
...@@ -118,21 +118,16 @@ class SpeakEleCallAIViewCtr: SpeakEleBaseViewCtr { ...@@ -118,21 +118,16 @@ class SpeakEleCallAIViewCtr: SpeakEleBaseViewCtr {
self?.startTime = 0 self?.startTime = 0
} }
if let ai = SpeakAIVideoPlayManager.share.SpeakAI.SpeakPlayerLayer , let dsts = SpeakAIVideoPlayManager.share
let bg = SpeakAIVideoPlayManager.share.backgoundAI.SpeakPlayerLayer{ dsts.removeFromSuperview()
ai.videoGravity = .resizeAspectFill self.SpeakAISer.addSubview(dsts)
self.SpeakAISer.layer.addSublayer(ai)
self.SpeakAISer.layer.addSublayer(bg)
bg.videoGravity = .resizeAspectFill
SpeakAIVideoPlayManager.share.PlayBg()
}
} }
override func viewDidLayoutSubviews() { override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews() super.viewDidLayoutSubviews()
self.view.layoutIfNeeded() self.view.layoutIfNeeded()
SpeakAIVideoPlayManager.share.SpeakAI.SpeakPlayerLayer?.frame = SpeakAISer.bounds SpeakAIVideoPlayManager.share.frame = SpeakAISer.bounds
SpeakAIVideoPlayManager.share.backgoundAI.SpeakPlayerLayer?.frame = SpeakAISer.bounds
} }
override func SpeakUpdate() { override func SpeakUpdate() {
...@@ -151,7 +146,7 @@ class SpeakEleCallAIViewCtr: SpeakEleBaseViewCtr { ...@@ -151,7 +146,7 @@ class SpeakEleCallAIViewCtr: SpeakEleBaseViewCtr {
} }
if isRecord { if isRecord {
self.startTime += 1 self.startTime += 1
if self.startTime > 5 { if self.startTime > 2 {
isRecord = false isRecord = false
if self.SpeakText.count > 0 { if self.SpeakText.count > 0 {
var talk = SpeakDialogueModel() var talk = SpeakDialogueModel()
...@@ -175,16 +170,20 @@ class SpeakEleCallAIViewCtr: SpeakEleBaseViewCtr { ...@@ -175,16 +170,20 @@ class SpeakEleCallAIViewCtr: SpeakEleBaseViewCtr {
titleView.isHidden = true titleView.isHidden = true
SpeakSoundBtn.isSelected = isMate SpeakSoundBtn.isSelected = isMate
let aiser = viewModel.AIser() let aiser = viewModel.AIser()
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
let idx = SpeakElePublicManager.share.PublicData.AIerIndex let idx = SpeakElePublicManager.share.PublicData.AIerIndex
let icon = "img_" + (aiser[safe: idx]?.name.lowercased() ?? "") let icon = "img_" + (aiser[safe: idx]?.name.lowercased() ?? "")
self.SpeakCallIcon.image = UIImage(named: icon) self.SpeakCallIcon.image = UIImage(named: icon)
SpeakName.text = aiser[safe: idx]?.name SpeakName.text = aiser[safe: idx]?.name
do{
let audioSession = AVAudioSession.sharedInstance()
try audioSession.setCategory(.playback)
try audioSession.setActive(true)
}catch{ }
DispatchQueue.main.asyncAfter(deadline: .now() + 3) { DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
self.display.isPaused = false self.display.isPaused = false
self.dataSource = self.netViewModel.dialogLeassAsk self.dataSource = self.netViewModel.dialogLeassAsk
// if self.netViewModel.isSpeech { self.Ask()
self.Ask()
// }
} }
} }
...@@ -194,7 +193,7 @@ class SpeakEleCallAIViewCtr: SpeakEleBaseViewCtr { ...@@ -194,7 +193,7 @@ class SpeakEleCallAIViewCtr: SpeakEleBaseViewCtr {
SpeakCallIcon.isHidden = true SpeakCallIcon.isHidden = true
SpeakAskWaitL.isHidden = true SpeakAskWaitL.isHidden = true
SpeakAISer.isHidden = false SpeakAISer.isHidden = false
SpeakAIVideoPlayManager.share.PlayBg()
if netViewModel.isSpeech { if netViewModel.isSpeech {
SpeakAskT.isHidden = false SpeakAskT.isHidden = false
} }
...@@ -241,8 +240,8 @@ class SpeakEleCallAIViewCtr: SpeakEleBaseViewCtr { ...@@ -241,8 +240,8 @@ class SpeakEleCallAIViewCtr: SpeakEleBaseViewCtr {
} }
} }
override func viewDidDisappear(_ animated: Bool) { override func viewWillDisappear(_ animated: Bool) {
super.viewDidDisappear(animated) super.viewWillDisappear(animated)
display.isPaused = true display.isPaused = true
display.invalidate() display.invalidate()
AudioPlayerManager.shared.stop() AudioPlayerManager.shared.stop()
......
...@@ -30,6 +30,8 @@ class SpeakEleGeneratePlanViewCtr: SpeakEleBaseViewCtr, UIScrollViewDelegate { ...@@ -30,6 +30,8 @@ class SpeakEleGeneratePlanViewCtr: SpeakEleBaseViewCtr, UIScrollViewDelegate {
private var offset:Int = 0 private var offset:Int = 0
private var selectIdx:CGFloat = -1
private var SpeakPlanChilds:[SpeakEleGeneratePlanView] = [ private var SpeakPlanChilds:[SpeakEleGeneratePlanView] = [
SpeakEleGeneratePlanView(string: "Creating diverse topics"), SpeakEleGeneratePlanView(string: "Creating diverse topics"),
SpeakEleGeneratePlanView(string: "Preparing interactive dialogues"), SpeakEleGeneratePlanView(string: "Preparing interactive dialogues"),
...@@ -39,12 +41,11 @@ class SpeakEleGeneratePlanViewCtr: SpeakEleBaseViewCtr, UIScrollViewDelegate { ...@@ -39,12 +41,11 @@ class SpeakEleGeneratePlanViewCtr: SpeakEleBaseViewCtr, UIScrollViewDelegate {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
SpeakPlanChilds.forEach { plan in SpeakPlanChilds.forEach { plan in
SpeakStackView.addArrangedSubview(plan) SpeakStackView.addArrangedSubview(plan)
} }
timer.fire()
} }
override func viewWillAppear(_ animated: Bool) { override func viewWillAppear(_ animated: Bool) {
...@@ -128,8 +129,8 @@ class SpeakEleGeneratePlanViewCtr: SpeakEleBaseViewCtr, UIScrollViewDelegate { ...@@ -128,8 +129,8 @@ class SpeakEleGeneratePlanViewCtr: SpeakEleBaseViewCtr, UIScrollViewDelegate {
child2.startRotation() child2.startRotation()
child2.offset = offset-200 child2.offset = offset-200
break break
default:
default:
let child = SpeakPlanChilds[2] let child = SpeakPlanChilds[2]
child.stop() child.stop()
child.offset = 100 child.offset = 100
...@@ -151,6 +152,12 @@ class SpeakEleGeneratePlanViewCtr: SpeakEleBaseViewCtr, UIScrollViewDelegate { ...@@ -151,6 +152,12 @@ class SpeakEleGeneratePlanViewCtr: SpeakEleBaseViewCtr, UIScrollViewDelegate {
} }
} }
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if timer.isValid {
timer.invalidate()
}
}
private lazy var pagectrol: UIView = { private lazy var pagectrol: UIView = {
let p = UIView() let p = UIView()
p.corners = 3 p.corners = 3
...@@ -174,4 +181,22 @@ class SpeakEleGeneratePlanViewCtr: SpeakEleBaseViewCtr, UIScrollViewDelegate { ...@@ -174,4 +181,22 @@ class SpeakEleGeneratePlanViewCtr: SpeakEleBaseViewCtr, UIScrollViewDelegate {
let offset = scrollView.contentOffset.x let offset = scrollView.contentOffset.x
setPages(Int(offset / scrollView.width) ) setPages(Int(offset / scrollView.width) )
} }
private lazy var timer: Timer = {
let tim = Timer(timeInterval: 3, repeats: true) {[weak self] tm in
Print("timer 1111111111")
self?.selectIdx += 1
if (self?.selectIdx ?? 3) < 3 {
UIView.animate(withDuration: 0.8) {
self?.SpeakScroll.contentOffset = CGPoint(x: (self?.SpeakScroll.width ?? 0.0) * (self?.selectIdx ?? 0), y: 0)
} completion: { su in
self?.setPages(Int(self?.selectIdx ?? 0))
}
}else{
tm.invalidate()
}
}
RunLoop.main.add(tim, forMode: .common)
return tim
}()
} }
...@@ -27,6 +27,7 @@ class SpeakEleGeneratePlanView: UIView { ...@@ -27,6 +27,7 @@ class SpeakEleGeneratePlanView: UIView {
}else if self.state == .start { }else if self.state == .start {
self.info.isHidden = false self.info.isHidden = false
self.SpeakOffsetL.text = "\(self.offset)%" self.SpeakOffsetL.text = "\(self.offset)%"
self.SpeakL.textColor = .init(hex: 0x000000,alpha: 0.54)
self.ProgressV.snp.remakeConstraints({ make in self.ProgressV.snp.remakeConstraints({ make in
make.left.right.bottom.equalToSuperview() make.left.right.bottom.equalToSuperview()
make.top.equalTo(self.SpeakL.snp.bottom).offset(10) make.top.equalTo(self.SpeakL.snp.bottom).offset(10)
...@@ -36,6 +37,7 @@ class SpeakEleGeneratePlanView: UIView { ...@@ -36,6 +37,7 @@ class SpeakEleGeneratePlanView: UIView {
self.animationLayer.frame = CGRectMake(0, 0, self.ProgressV.width * (CGFloat(self.offset) / 100.0), self.ProgressV.height) self.animationLayer.frame = CGRectMake(0, 0, self.ProgressV.width * (CGFloat(self.offset) / 100.0), self.ProgressV.height)
} }
}else{ }else{
self.SpeakL.textColor = .init(hex: 0x000000,alpha: 0.9)
self.SpeakOffsetL.isHidden = true self.SpeakOffsetL.isHidden = true
self.ProgressV.snp.remakeConstraints({ make in self.ProgressV.snp.remakeConstraints({ make in
make.height.equalTo(12) make.height.equalTo(12)
...@@ -83,7 +85,7 @@ class SpeakEleGeneratePlanView: UIView { ...@@ -83,7 +85,7 @@ class SpeakEleGeneratePlanView: UIView {
private lazy var SpeakL: UILabel = { private lazy var SpeakL: UILabel = {
let l = UILabel() let l = UILabel()
l.font = UIFont.montserrat(.semiBold,size: 18) l.font = UIFont.montserrat(.semiBold,size: 18)
l.textColor = .init(hex: 0x000000 ,alpha: 0.9) l.textColor = .init(hex: 0x000000 ,alpha: 0.54)
l.text = Plan l.text = Plan
l.numberOfLines = 0 l.numberOfLines = 0
addSubview(l) addSubview(l)
......
...@@ -52,7 +52,7 @@ class SpeakEleGuideViewCtr: SpeakEleBaseViewCtr ,UIScrollViewDelegate { ...@@ -52,7 +52,7 @@ class SpeakEleGuideViewCtr: SpeakEleBaseViewCtr ,UIScrollViewDelegate {
super.viewDidLayoutSubviews() super.viewDidLayoutSubviews()
self.view.layoutIfNeeded() self.view.layoutIfNeeded()
SpeakTrustContentVs.forEach { trust in SpeakTrustContentVs.forEach { trust in
trust.shadow(cornerRadius: 12, shadowColor: .init(hex: 0x49D9F9,alpha: 0.1), offset: CGSizeMake(0, 4), opacity: 1, radius: 2) trust.shadow(cornerRadius: 12, shadowColor: .init(hex: 0x49D9F9,alpha: 0.1), offset: CGSizeMake(0, 0), opacity: 1, radius: 3)
} }
} }
......
...@@ -18,6 +18,9 @@ class SpeakEleQAViewCtr: SpeakEleBaseViewCtr { ...@@ -18,6 +18,9 @@ class SpeakEleQAViewCtr: SpeakEleBaseViewCtr {
@IBOutlet weak var contiuneBtn: SpeakEleButton! @IBOutlet weak var contiuneBtn: SpeakEleButton!
@IBOutlet weak var SpeakTopVideoView: UIView! @IBOutlet weak var SpeakTopVideoView: UIView!
@IBOutlet weak var SpeakBottomTool: UIView!
@IBOutlet weak var ContiueContentV: UIView!
private var offsets = 0 private var offsets = 0
...@@ -32,7 +35,14 @@ class SpeakEleQAViewCtr: SpeakEleBaseViewCtr { ...@@ -32,7 +35,14 @@ class SpeakEleQAViewCtr: SpeakEleBaseViewCtr {
private var isCountiue:Int = -1 { private var isCountiue:Int = -1 {
didSet { didSet {
contiuneBtn.isEnabled = !(isCountiue == -1) let enable = !(isCountiue == -1)
if !enable {
contiuneBtn.setBackgroundImage(UIImage(named: "icon-button_no(1)"), for: .normal)
contiuneBtn.setBackgroundImage(UIImage(named: "button_guide_on-Heigiose"), for: .highlighted)
}else{
contiuneBtn.setBackgroundImage(UIImage(named: "icon-button_guide_on"), for: .normal)
contiuneBtn.setBackgroundImage(UIImage(named: "icon-button_no-hight"), for: .highlighted)
}
SpeakTableView.reloadData() SpeakTableView.reloadData()
} }
} }
...@@ -40,6 +50,7 @@ class SpeakEleQAViewCtr: SpeakEleBaseViewCtr { ...@@ -40,6 +50,7 @@ class SpeakEleQAViewCtr: SpeakEleBaseViewCtr {
private var step = 0 { private var step = 0 {
didSet{ didSet{
contiuneBtn.isHidden = step < 3 contiuneBtn.isHidden = step < 3
ContiueContentV.isHidden = contiuneBtn.isHidden
InputBoxContent.isHidden = !(step < 3) InputBoxContent.isHidden = !(step < 3)
SpeakInputBox.isUserInteractionEnabled = (step == 2) SpeakInputBox.isUserInteractionEnabled = (step == 2)
} }
...@@ -84,6 +95,7 @@ class SpeakEleQAViewCtr: SpeakEleBaseViewCtr { ...@@ -84,6 +95,7 @@ class SpeakEleQAViewCtr: SpeakEleBaseViewCtr {
override func viewWillAppear(_ animated: Bool) { override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated) super.viewWillAppear(animated)
titleView.isHidden = true titleView.isHidden = true
isCountiue = -1
GetLostMessage() GetLostMessage()
} }
...@@ -98,6 +110,9 @@ class SpeakEleQAViewCtr: SpeakEleBaseViewCtr { ...@@ -98,6 +110,9 @@ class SpeakEleQAViewCtr: SpeakEleBaseViewCtr {
} }
@IBAction func contineTaps(_ sender: Any) { @IBAction func contineTaps(_ sender: Any) {
if self.isCountiue < 0 {
return
}
if let last = viewModel.anwer.last { if let last = viewModel.anwer.last {
if last.speakMsg == "" { if last.speakMsg == "" {
let language = moreItem[safe:self.isCountiue] ?? "" let language = moreItem[safe:self.isCountiue] ?? ""
...@@ -175,7 +190,7 @@ class SpeakEleQAViewCtr: SpeakEleBaseViewCtr { ...@@ -175,7 +190,7 @@ class SpeakEleQAViewCtr: SpeakEleBaseViewCtr {
display.isPaused = true display.isPaused = true
offsets = 0 offsets = 0
} }
if msg.messageType == .name && msg.speakMsg.isEmpty{ if msg.messageType == .name && msg.speakMsg.isEmpty {
}else{ }else{
viewModel.anwer.append(msg) viewModel.anwer.append(msg)
...@@ -204,6 +219,7 @@ class SpeakEleQAViewCtr: SpeakEleBaseViewCtr { ...@@ -204,6 +219,7 @@ class SpeakEleQAViewCtr: SpeakEleBaseViewCtr {
}else if msg.messageType == .finish { }else if msg.messageType == .finish {
self.isCountiue = 0 self.isCountiue = 0
self.contiuneBtn.setTitle("Start", for: .normal) self.contiuneBtn.setTitle("Start", for: .normal)
SpeakPermission.requestNotificationPermission()
} }
return return
} }
...@@ -270,8 +286,22 @@ extension SpeakEleQAViewCtr { ...@@ -270,8 +286,22 @@ extension SpeakEleQAViewCtr {
} }
private func update() -> Void { private func update() -> Void {
let v = Float(self.viewModel.anwer.count) / Float(self.viewModel.questionArrys.count) var pro = 0
self.SpeakProgres.value = v for v in self.viewModel.anwer {
if (v.role == .speakUser && v.speakMsg.count > 0){
pro += 1
}
}
if let last = self.viewModel.anwer.last {
if (last.role == .speakUser && last.speakMsg.count <= 0) || last.messageType == .name || last.messageType == .finish{
SpeakBottomTool.isHidden = false
}else{
SpeakBottomTool.isHidden = true
}
}else{
SpeakBottomTool.isHidden = true
}
self.SpeakProgres.value = Float(pro) / 9.0
self.SpeakTableView.reloadData() self.SpeakTableView.reloadData()
self.view.layoutIfNeeded() self.view.layoutIfNeeded()
if self.viewModel.anwer.count > 0 { if self.viewModel.anwer.count > 0 {
...@@ -343,7 +373,8 @@ extension SpeakEleQAViewCtr : UITableViewDelegate,UITableViewDataSource { ...@@ -343,7 +373,8 @@ extension SpeakEleQAViewCtr : UITableViewDelegate,UITableViewDataSource {
} }
self?.selectSets = NSMutableSet(array: self?.selectSets.filter({($0 as! Int) < (self?.max ?? 0) }) ?? []) self?.selectSets = NSMutableSet(array: self?.selectSets.filter({($0 as! Int) < (self?.max ?? 0) }) ?? [])
} }
self?.contiuneBtn.isEnabled = (self?.selectSets.count ?? 0 > 0) // self?.contiuneBtn.isEnabled = (self?.selectSets.count ?? 0 > 0)
self?.isCountiue = (self?.selectSets.count ?? 0 > 0) ? 1 : -1
self?.SpeakTableView.reloadData() self?.SpeakTableView.reloadData()
} }
return cell return cell
......
...@@ -11,7 +11,9 @@ ...@@ -11,7 +11,9 @@
<objects> <objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="SpeakEleQAViewCtr" customModule="SpeakEasyLearnEnglish" customModuleProvider="target"> <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="SpeakEleQAViewCtr" customModule="SpeakEasyLearnEnglish" customModuleProvider="target">
<connections> <connections>
<outlet property="ContiueContentV" destination="ciK-R0-acp" id="uo5-cp-Ze1"/>
<outlet property="InputBoxContent" destination="uS5-tZ-Obr" id="E0N-dl-Lnr"/> <outlet property="InputBoxContent" destination="uS5-tZ-Obr" id="E0N-dl-Lnr"/>
<outlet property="SpeakBottomTool" destination="ly6-as-jqg" id="eoy-1H-eBq"/>
<outlet property="SpeakContentV" destination="lhO-rO-ci0" id="VH2-3v-YWq"/> <outlet property="SpeakContentV" destination="lhO-rO-ci0" id="VH2-3v-YWq"/>
<outlet property="SpeakInputBox" destination="n0s-ld-qq8" id="UMQ-9p-FAo"/> <outlet property="SpeakInputBox" destination="n0s-ld-qq8" id="UMQ-9p-FAo"/>
<outlet property="SpeakProgres" destination="ZV3-Si-Hef" id="ZBs-da-fiI"/> <outlet property="SpeakProgres" destination="ZV3-Si-Hef" id="ZBs-da-fiI"/>
...@@ -91,6 +93,7 @@ ...@@ -91,6 +93,7 @@
</constraints> </constraints>
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
<state key="normal" image="sp-guide-Send"/> <state key="normal" image="sp-guide-Send"/>
<state key="highlighted" image="sp-guide-Send-Hight"/>
<connections> <connections>
<action selector="SpeakSendMsg:" destination="-1" eventType="touchUpInside" id="pSi-TS-fMS"/> <action selector="SpeakSendMsg:" destination="-1" eventType="touchUpInside" id="pSi-TS-fMS"/>
</connections> </connections>
...@@ -100,28 +103,40 @@ ...@@ -100,28 +103,40 @@
<constraint firstAttribute="height" constant="48" id="by7-wH-3pT"/> <constraint firstAttribute="height" constant="48" id="by7-wH-3pT"/>
</constraints> </constraints>
</stackView> </stackView>
<button opaque="NO" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="jZV-J1-egY" customClass="SpeakEleButton" customModule="SpeakEasyLearnEnglish" customModuleProvider="target"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ciK-R0-acp">
<rect key="frame" x="24" y="16.666666666666629" width="345" height="48"/> <rect key="frame" x="24" y="12.666666666666629" width="345" height="52"/>
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> <subviews>
<state key="normal" title="Continue"/> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="jZV-J1-egY">
<connections> <rect key="frame" x="0.0" y="18" width="345" height="34"/>
<action selector="contineTaps:" destination="-1" eventType="touchUpInside" id="ehk-ya-RMw"/> <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</connections> <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
</button> <state key="normal" title="Continue"/>
<connections>
<action selector="contineTaps:" destination="-1" eventType="touchUpInside" id="ehk-ya-RMw"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstAttribute="bottom" secondItem="jZV-J1-egY" secondAttribute="bottom" id="6zT-87-MWy"/>
<constraint firstAttribute="height" constant="52" id="Igt-nt-xnN"/>
<constraint firstAttribute="trailing" secondItem="jZV-J1-egY" secondAttribute="trailing" id="Rxu-VC-zEZ"/>
<constraint firstItem="jZV-J1-egY" firstAttribute="leading" secondItem="ciK-R0-acp" secondAttribute="leading" id="iBs-uC-t0b"/>
</constraints>
</view>
</subviews> </subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor"/> <color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints> <constraints>
<constraint firstItem="jZV-J1-egY" firstAttribute="top" secondItem="uS5-tZ-Obr" secondAttribute="top" id="0bt-xh-P70"/>
<constraint firstAttribute="trailing" secondItem="uS5-tZ-Obr" secondAttribute="trailing" constant="24" id="6cX-0K-4lq"/> <constraint firstAttribute="trailing" secondItem="uS5-tZ-Obr" secondAttribute="trailing" constant="24" id="6cX-0K-4lq"/>
<constraint firstItem="uS5-tZ-Obr" firstAttribute="top" secondItem="Pk3-rK-Odt" secondAttribute="bottom" constant="16" id="D3H-sA-sez"/> <constraint firstItem="uS5-tZ-Obr" firstAttribute="top" secondItem="Pk3-rK-Odt" secondAttribute="bottom" constant="16" id="D3H-sA-sez"/>
<constraint firstItem="jZV-J1-egY" firstAttribute="leading" secondItem="uS5-tZ-Obr" secondAttribute="leading" id="EWW-4z-5I0"/> <constraint firstItem="uS5-tZ-Obr" firstAttribute="trailing" secondItem="ciK-R0-acp" secondAttribute="trailing" id="N01-8f-ISZ"/>
<constraint firstItem="jZV-J1-egY" firstAttribute="bottom" secondItem="uS5-tZ-Obr" secondAttribute="bottom" id="QZd-ZE-Nd6"/> <constraint firstItem="uS5-tZ-Obr" firstAttribute="bottom" secondItem="ciK-R0-acp" secondAttribute="bottom" id="PRP-oR-LAN"/>
<constraint firstItem="Pk3-rK-Odt" firstAttribute="top" secondItem="ly6-as-jqg" secondAttribute="top" id="R6c-cV-kgx"/> <constraint firstItem="Pk3-rK-Odt" firstAttribute="top" secondItem="ly6-as-jqg" secondAttribute="top" id="R6c-cV-kgx"/>
<constraint firstItem="uS5-tZ-Obr" firstAttribute="leading" secondItem="ly6-as-jqg" secondAttribute="leading" constant="24" id="eRl-ls-UHL"/> <constraint firstItem="uS5-tZ-Obr" firstAttribute="leading" secondItem="ly6-as-jqg" secondAttribute="leading" constant="24" id="eRl-ls-UHL"/>
<constraint firstAttribute="bottom" secondItem="uS5-tZ-Obr" secondAttribute="bottom" constant="16" id="h5H-Xb-zyy"/> <constraint firstAttribute="bottom" secondItem="uS5-tZ-Obr" secondAttribute="bottom" constant="16" id="h5H-Xb-zyy"/>
<constraint firstItem="Pk3-rK-Odt" firstAttribute="leading" secondItem="ly6-as-jqg" secondAttribute="leading" id="jeu-9r-eGu"/> <constraint firstItem="Pk3-rK-Odt" firstAttribute="leading" secondItem="ly6-as-jqg" secondAttribute="leading" id="jeu-9r-eGu"/>
<constraint firstItem="uS5-tZ-Obr" firstAttribute="leading" secondItem="ciK-R0-acp" secondAttribute="leading" id="nkB-GL-DBD"/>
<constraint firstAttribute="trailing" secondItem="Pk3-rK-Odt" secondAttribute="trailing" id="oWt-sh-GoR"/> <constraint firstAttribute="trailing" secondItem="Pk3-rK-Odt" secondAttribute="trailing" id="oWt-sh-GoR"/>
<constraint firstItem="jZV-J1-egY" firstAttribute="trailing" secondItem="uS5-tZ-Obr" secondAttribute="trailing" id="rlN-TL-UlX"/>
</constraints> </constraints>
</view> </view>
</subviews> </subviews>
...@@ -156,11 +171,12 @@ ...@@ -156,11 +171,12 @@
</objects> </objects>
<resources> <resources>
<image name="sp-guide-Send" width="48" height="48"/> <image name="sp-guide-Send" width="48" height="48"/>
<image name="sp-guide-Send-Hight" width="48" height="48"/>
<systemColor name="systemBackgroundColor"> <systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor> </systemColor>
<systemColor name="systemGrayColor"> <systemColor name="systemGrayColor">
<color red="0.55686274509803924" green="0.55686274509803924" blue="0.57647058823529407" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color red="0.5568627451" green="0.5568627451" blue="0.57647058819999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor> </systemColor>
</resources> </resources>
</document> </document>
...@@ -51,12 +51,13 @@ class SpeakEleMutabSelectBoxViewCell: SpeakEleQABaseViewCell { ...@@ -51,12 +51,13 @@ class SpeakEleMutabSelectBoxViewCell: SpeakEleQABaseViewCell {
btn.corners = 8 btn.corners = 8
btn.borderWidth = 1 btn.borderWidth = 1
btn.borderColor = .init(hex: 0x6B71E3) btn.borderColor = .init(hex: 0x6B71E3)
btn.contentEdgeInsets = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
btn.addTarget(self, action: #selector(btnTaps(_:)), for: .touchUpInside) btn.addTarget(self, action: #selector(btnTaps(_:)), for: .touchUpInside)
contentV.addSubview(btn) contentV.addSubview(btn)
items.append(btn) items.append(btn)
btn.tag = i btn.tag = i
let size = str.size(withFont: UIFont.montserrat(.regular,size: 16)) let size = str.size(withFont: UIFont.montserrat(.regular,size: 16))
let width = size.width + 10.0 let width = size.width + 10.0 + 16
if ((offsetX + width + content.right) > contentV.width) { if ((offsetX + width + content.right) > contentV.width) {
offsetX = content.left offsetX = content.left
...@@ -104,8 +105,7 @@ class SpeakEleMutabSelectBoxViewCell: SpeakEleQABaseViewCell { ...@@ -104,8 +105,7 @@ class SpeakEleMutabSelectBoxViewCell: SpeakEleQABaseViewCell {
make.left.right.bottom.top.equalToSuperview().inset(UIEdgeInsets(top: -10, left: -10, bottom: -10, right: -10)) make.left.right.bottom.top.equalToSuperview().inset(UIEdgeInsets(top: -10, left: -10, bottom: -10, right: -10))
} }
contentV.snp.makeConstraints { make in contentV.snp.makeConstraints { make in
make.right.top.bottom.equalToSuperview().inset(UIEdgeInsets(top: 2, left: 0, bottom: 16, right: (marginLR))) make.right.top.left.bottom.equalToSuperview().inset(UIEdgeInsets(top: 2, left: 40, bottom: 16, right: (marginLR)))
make.width.equalTo(Dev.screenW * 0.6 )
} }
} }
......
...@@ -103,8 +103,8 @@ class SpeakEleSelectBoxViewCell: SpeakEleQABaseViewCell { ...@@ -103,8 +103,8 @@ class SpeakEleSelectBoxViewCell: SpeakEleQABaseViewCell {
make.left.right.bottom.top.equalToSuperview().inset(UIEdgeInsets(top: -10, left: -10, bottom: -10, right: -10)) make.left.right.bottom.top.equalToSuperview().inset(UIEdgeInsets(top: -10, left: -10, bottom: -10, right: -10))
} }
contentV.snp.makeConstraints { make in contentV.snp.makeConstraints { make in
make.right.top.bottom.equalToSuperview().inset(UIEdgeInsets(top: 2, left: 0, bottom: 16, right: (marginLR))) make.right.left.top.bottom.equalToSuperview().inset(UIEdgeInsets(top: 2, left: 40, bottom: 16, right: (marginLR)))
make.width.equalTo(Dev.screenW * 0.6 ) // make.width.equalTo(338)
} }
} }
......
...@@ -13,12 +13,11 @@ class SpeakReviewViewModel: NSObject { ...@@ -13,12 +13,11 @@ class SpeakReviewViewModel: NSObject {
set {} set {}
get { get {
return [ return [
SpeakReviewModel(image: "img_1", name: "Lily Parker", country: "United States", descption: "Fragmented English practice is convenient! App drills work—greetings feel natural."), SpeakReviewModel(image: "img_1", name: "Lily Parker", country: "United States", descption: "Fragmented English practice fits my schedule! The app’s scenario drills work—after 2 weeks, greeting foreign interns feels natural, no pauses."),
SpeakReviewModel(image: "img_2", name: "Mia Davies", country: "United Kingdom", descption: "Café work: it helps practice ordering—customers praise fluency. "), SpeakReviewModel(image: "img_2", name: "Mia Davies", country: "United Kingdom", descption: "Working at the café lets me practice English easily! Daily chats with customers help, and a British customer said, “Your English is fluent—I can’t tell it’s not first!”"),
SpeakReviewModel(image: "img_3", name: "Chloe Wang", country: "Australia", descption: "Chats with foreign friend Detailed grammar feedback helps. ")
SpeakReviewModel(image: "img_3", name: "Chloe Wang", country: "Australia", descption: "Chatting weekly with friend Emma boosts my English! She gives great grammar feedback, and now I catch errors—my writing’s much more accurate.")
] ]
} }
} }
...@@ -27,11 +26,11 @@ class SpeakReviewViewModel: NSObject { ...@@ -27,11 +26,11 @@ class SpeakReviewViewModel: NSObject {
set{ } set{ }
get{ get{
return [ return [
SpeakReviewModel(image: "img_4", name: "James Scott", country: "", descption: "Business trips: plane listening with accents helps clients—English feels authentic."), SpeakReviewModel(image: "img_4", name: "James Scott", country: "", descption: "Practicing English on business planes helps! I learn accents, and a Sydney client said, “Your English is authentic—like you lived here!” It boosted rapport."),
SpeakReviewModel(image: "img_5", name: "Nora Hayes", country: "", descption: "App boosts vocabulary—English literature reading easier."), SpeakReviewModel(image: "img_5", name: "Nora Hayes", country: "", descption: "This English app helps my vocabulary! I once struggled with English lit, but now 500+ words later, I get tricky descriptions in Pride and Prejudice."),
SpeakReviewModel(image: "img_6", name: "Thomas Bennett", country: "", descption: "AI chat lets me speak—gentle corrections ease call nerves.")] SpeakReviewModel(image: "img_6", name: "Thomas Bennett", country: "", descption: "I used to panic about English calls! Now AI chat practice helps—after a month, I chatted with NY office smoothly, no fluster, even joked.")]
} }
} }
......
...@@ -37,6 +37,8 @@ class SpeakEleIAPViewCtr: SpeakEleBaseViewCtr { ...@@ -37,6 +37,8 @@ class SpeakEleIAPViewCtr: SpeakEleBaseViewCtr {
@IBOutlet weak var SpeakPayBut: SpeakEleButton! @IBOutlet weak var SpeakPayBut: SpeakEleButton!
@IBOutlet weak var SpeakBotDescription: UILabel! @IBOutlet weak var SpeakBotDescription: UILabel!
@IBOutlet weak var SpeakContentBg: UIView!
var Products:[SKProduct?] = [] var Products:[SKProduct?] = []
private let viewModel = IAPViewModel.share private let viewModel = IAPViewModel.share
...@@ -91,8 +93,10 @@ class SpeakEleIAPViewCtr: SpeakEleBaseViewCtr { ...@@ -91,8 +93,10 @@ class SpeakEleIAPViewCtr: SpeakEleBaseViewCtr {
override func viewDidLayoutSubviews() { override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews() super.viewDidLayoutSubviews()
self.view.layoutIfNeeded()
SpeakEasyV.shadow(cornerRadius: 16,shadowColor: .init(hex: 0x000000,alpha: 1),opacity: 0.06,radius: 2) SpeakEasyV.shadow(cornerRadius: 16,shadowColor: .init(hex: 0x000000,alpha: 1),opacity: 0.06,radius: 2)
SpeakPayContentV.shadow(cornerRadius: 8,shadowColor: .init(hex: 0x000000,alpha: 1),opacity: 0.06,radius: 2) SpeakPayContentV.shadow(cornerRadius: 8,shadowColor: .init(hex: 0x000000,alpha: 1),opacity: 0.06,radius: 2)
SpeakContentBg.gradient(colors: [.init(hex: 0xFFFFFF,alpha: 0),.init(hex: 0xFFFFFF,alpha: 0.76) ,.white],direction: .topToBottom)
} }
@IBAction func SpeakCloseTaps(_ sender: Any) { @IBAction func SpeakCloseTaps(_ sender: Any) {
......
...@@ -11,7 +11,7 @@ class SpeakEleLaunchViewCtr: SpeakEleBaseViewCtr { ...@@ -11,7 +11,7 @@ class SpeakEleLaunchViewCtr: SpeakEleBaseViewCtr {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
DispatchQueue.main.asyncAfter(deadline: .now() + 1) { DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
self.ToPages() self.ToPages()
} }
} }
...@@ -26,7 +26,7 @@ class SpeakEleLaunchViewCtr: SpeakEleBaseViewCtr { ...@@ -26,7 +26,7 @@ class SpeakEleLaunchViewCtr: SpeakEleBaseViewCtr {
SpWindow.switchToController(nav) SpWindow.switchToController(nav)
}else{ }else{
let nav = SpeakEleBaseNavigationCtr(rootViewController: SpeakEleLoginGuideCtr()) let nav = SpeakEleBaseNavigationCtr(rootViewController: SpeakEleLoginGuideCtr())
SpWindow.switchToController(nav) SpWindow.rootViewController = nav
} }
break break
case .subscribe: case .subscribe:
......
...@@ -26,10 +26,17 @@ class SpeakEleFLoginViewCtr: SpeakEleBaseViewCtr { ...@@ -26,10 +26,17 @@ class SpeakEleFLoginViewCtr: SpeakEleBaseViewCtr {
super.viewWillAppear(animated) super.viewWillAppear(animated)
titleView.isHidden = true titleView.isHidden = true
self.view.layoutIfNeeded() self.view.layoutIfNeeded()
var idx = 0
LoginBtns.forEach { btn in LoginBtns.forEach { btn in
btn.setBackgroundImage(UIColor.white.generate(btn.size,20), for: .normal) if idx == 0 {
btn.setBackgroundImage(UIColor.init(hex: 0x191919).generate(btn.size,20), for: .highlighted) btn.setBackgroundImage(UIColor.black.generate(btn.size,20), for: .normal)
btn.setBackgroundImage(UIColor.black.generate(btn.size,20), for: .highlighted)
}else{
btn.setBackgroundImage(UIColor.white.generate(btn.size,20), for: .normal)
btn.setBackgroundImage(UIColor.init(hex: 0x191919).generate(btn.size,20), for: .highlighted)
}
btn.clipsToBounds = false btn.clipsToBounds = false
idx += 1
} }
} }
...@@ -37,7 +44,7 @@ class SpeakEleFLoginViewCtr: SpeakEleBaseViewCtr { ...@@ -37,7 +44,7 @@ class SpeakEleFLoginViewCtr: SpeakEleBaseViewCtr {
super.viewDidLayoutSubviews() super.viewDidLayoutSubviews()
self.view.layoutIfNeeded() self.view.layoutIfNeeded()
LoginBtns.forEach { btn in LoginBtns.forEach { btn in
btn.shadow(cornerRadius: 20,shadowColor: .init(hex: 0x000000),offset: CGSize(width: 0, height: 2) ,opacity: 0.06,radius: 2) btn.shadow(cornerRadius: 20,shadowColor: .init(hex: 0x000000,alpha: 0.06),offset: CGSize(width: 0, height: 2) ,opacity: 1,radius: 5)
} }
} }
...@@ -93,8 +100,8 @@ class SpeakEleFLoginViewCtr: SpeakEleBaseViewCtr { ...@@ -93,8 +100,8 @@ class SpeakEleFLoginViewCtr: SpeakEleBaseViewCtr {
private func ToHome() -> Void { private func ToHome() -> Void {
updateUserInformation() updateUserInformation()
let nav = SpeakEleBaseNavigationCtr(rootViewController: SpeakEleTabbarViewCtr()) let nav = SpeakEleBaseNavigationCtr(rootViewController: SpeakEleTabbarViewCtr())
SpWindow.switchToController(nav) SpWindow.switchToController(nav)
} }
} }
...@@ -66,7 +66,7 @@ ...@@ -66,7 +66,7 @@
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="XM7-aG-cye"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="XM7-aG-cye">
<rect key="frame" x="0.0" y="0.0" width="272" height="60"/> <rect key="frame" x="0.0" y="0.0" width="272" height="60"/>
<subviews> <subviews>
<textField opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="248" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="gaoleyang@linkingplay.com" placeholder="E-mail address" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="e0z-Rl-Mp2"> <textField opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="248" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="E-mail address" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="e0z-Rl-Mp2">
<rect key="frame" x="16" y="19" width="240" height="22"/> <rect key="frame" x="16" y="19" width="240" height="22"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/> <fontDescription key="fontDescription" type="system" pointSize="16"/>
......
...@@ -12,6 +12,21 @@ class SpeakEleLoginGuideCtr: SpeakEleBaseViewCtr { ...@@ -12,6 +12,21 @@ class SpeakEleLoginGuideCtr: SpeakEleBaseViewCtr {
@IBOutlet weak var SpeakDescLabel: UILabel! @IBOutlet weak var SpeakDescLabel: UILabel!
@IBOutlet weak var TopIcon: UIImageView!
@IBOutlet weak var ShowTopImg: UIImageView!
@IBOutlet weak var ShowAniM1: UIImageView!
@IBOutlet weak var ShowAniM2: UIImageView!
@IBOutlet weak var ShowButtons: UIStackView!
@IBOutlet weak var centerBottonConst: NSLayoutConstraint!
@IBOutlet weak var TopWidthConst: NSLayoutConstraint!
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
} }
...@@ -19,6 +34,49 @@ class SpeakEleLoginGuideCtr: SpeakEleBaseViewCtr { ...@@ -19,6 +34,49 @@ class SpeakEleLoginGuideCtr: SpeakEleBaseViewCtr {
override func viewWillAppear(_ animated: Bool) { override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated) super.viewWillAppear(animated)
setDescription() setDescription()
self.startAni()
}
private func startAni() -> Void {
self.TopIcon.alpha = 1
ShowButtons.alpha = 0
ShowTopImg.alpha = 0
ShowAniM1.alpha = 1
self.ShowAniM1.isHidden = true
ShowAniM2.alpha = 0
TopWidthConst.constant = 302 * 2.0
ShowAniM2.alpha = 0
self.ShowButtons.alpha = 0
centerBottonConst.constant = 150
self.view.layoutIfNeeded()
DispatchQueue.main.async {
self.view.setNeedsDisplay()
UIView.animate(withDuration: 0.5) {
self.TopIcon.alpha = 0.0
} completion: { su in
if su {
self.ShowAniM1.isHidden = false
UIView.animate(withDuration: 0.6) {
self.ShowAniM1.alpha = 1
self.TopWidthConst.constant = 302 * 1.2
self.view.layoutIfNeeded()
} completion: { su in
if su {
UIView.animate(withDuration: 0.6) {
self.ShowAniM2.alpha = 1
self.ShowButtons.alpha = 1
self.TopWidthConst.constant = 302
self.centerBottonConst.constant = 80
self.view.layoutIfNeeded()
} completion: { su in
}
}
}
}
}
}
} }
override func viewDidLayoutSubviews() { override func viewDidLayoutSubviews() {
......
...@@ -11,7 +11,14 @@ ...@@ -11,7 +11,14 @@
<objects> <objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="SpeakEleLoginGuideCtr" customModule="SpeakEasyLearnEnglish" customModuleProvider="target"> <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="SpeakEleLoginGuideCtr" customModule="SpeakEasyLearnEnglish" customModuleProvider="target">
<connections> <connections>
<outlet property="ShowAniM1" destination="2Pj-ZL-FxO" id="BhB-kV-Thj"/>
<outlet property="ShowAniM2" destination="egF-1p-Cl5" id="Quz-kT-fdN"/>
<outlet property="ShowButtons" destination="veF-PY-V1F" id="PkJ-jw-li3"/>
<outlet property="ShowTopImg" destination="eyD-Iy-5pN" id="P19-KE-Kwa"/>
<outlet property="SpeakDescLabel" destination="jGO-Du-a3k" id="mxV-nA-Nwk"/> <outlet property="SpeakDescLabel" destination="jGO-Du-a3k" id="mxV-nA-Nwk"/>
<outlet property="TopIcon" destination="w7f-wU-Eto" id="rmc-Eq-U2D"/>
<outlet property="TopWidthConst" destination="aW6-vK-ZDa" id="O88-s0-sRq"/>
<outlet property="centerBottonConst" destination="NuM-ib-dld" id="cRg-ks-kKG"/>
<outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/> <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
</connections> </connections>
</placeholder> </placeholder>
...@@ -20,10 +27,13 @@ ...@@ -20,10 +27,13 @@
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/> <rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="dengluye-login" translatesAutoresizingMaskIntoConstraints="NO" id="eyD-Iy-5pN"> <imageView clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.0" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="BBBBBBBBBGo.png" translatesAutoresizingMaskIntoConstraints="NO" id="w7f-wU-Eto">
<rect key="frame" x="0.0" y="0.0" width="393" height="465"/> <rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
</imageView> </imageView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="equalSpacing" spacing="16" translatesAutoresizingMaskIntoConstraints="NO" id="veF-PY-V1F"> <imageView clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.0" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="dengluye-login" translatesAutoresizingMaskIntoConstraints="NO" id="eyD-Iy-5pN">
<rect key="frame" x="0.0" y="0.0" width="393" height="402"/>
</imageView>
<stackView opaque="NO" alpha="0.0" contentMode="scaleToFill" axis="vertical" distribution="equalSpacing" spacing="16" translatesAutoresizingMaskIntoConstraints="NO" id="veF-PY-V1F">
<rect key="frame" x="24" y="589.66666666666663" width="345" height="170.33333333333337"/> <rect key="frame" x="24" y="589.66666666666663" width="345" height="170.33333333333337"/>
<subviews> <subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="equalSpacing" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="pwZ-Zv-JRo"> <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="equalSpacing" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="pwZ-Zv-JRo">
...@@ -89,22 +99,44 @@ ...@@ -89,22 +99,44 @@
</label> </label>
</subviews> </subviews>
</stackView> </stackView>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="sp-10000h+" translatesAutoresizingMaskIntoConstraints="NO" id="2Pj-ZL-FxO">
<rect key="frame" x="45.666666666666657" y="279" width="302" height="130"/>
<constraints>
<constraint firstAttribute="width" secondItem="2Pj-ZL-FxO" secondAttribute="height" multiplier="302:130" id="Axm-4a-6Mu"/>
<constraint firstAttribute="width" constant="302" id="aW6-vK-ZDa"/>
</constraints>
</imageView>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="sp-SpeakEasyLearning" translatesAutoresizingMaskIntoConstraints="NO" id="egF-1p-Cl5">
<rect key="frame" x="24" y="509" width="345" height="67"/>
</imageView>
</subviews> </subviews>
<viewLayoutGuide key="safeArea" id="fnl-2z-Ty3"/> <viewLayoutGuide key="safeArea" id="fnl-2z-Ty3"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/> <color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints> <constraints>
<constraint firstItem="veF-PY-V1F" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" constant="24" id="0oh-4u-Nzo"/> <constraint firstItem="veF-PY-V1F" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" constant="24" id="0oh-4u-Nzo"/>
<constraint firstItem="w7f-wU-Eto" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" id="2Fe-GS-bKr"/>
<constraint firstItem="egF-1p-Cl5" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" constant="24" id="8nd-bH-4Et"/>
<constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="veF-PY-V1F" secondAttribute="trailing" constant="24" id="9ao-KJ-und"/> <constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="veF-PY-V1F" secondAttribute="trailing" constant="24" id="9ao-KJ-und"/>
<constraint firstItem="eyD-Iy-5pN" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" id="9vZ-ko-bjl"/> <constraint firstItem="eyD-Iy-5pN" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" id="9vZ-ko-bjl"/>
<constraint firstItem="w7f-wU-Eto" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" id="BXz-Rl-pBh"/>
<constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="egF-1p-Cl5" secondAttribute="trailing" constant="24" id="Bv4-yp-t6a"/>
<constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="w7f-wU-Eto" secondAttribute="trailing" id="Cz8-3M-tyJ"/>
<constraint firstItem="fnl-2z-Ty3" firstAttribute="bottom" secondItem="veF-PY-V1F" secondAttribute="bottom" constant="24" id="NIU-Ch-1i2"/> <constraint firstItem="fnl-2z-Ty3" firstAttribute="bottom" secondItem="veF-PY-V1F" secondAttribute="bottom" constant="24" id="NIU-Ch-1i2"/>
<constraint firstItem="egF-1p-Cl5" firstAttribute="bottom" secondItem="i5M-Pr-FkT" secondAttribute="centerY" constant="150" id="NuM-ib-dld"/>
<constraint firstItem="egF-1p-Cl5" firstAttribute="top" secondItem="2Pj-ZL-FxO" secondAttribute="bottom" constant="100" id="X1n-a6-Ev3"/>
<constraint firstItem="2Pj-ZL-FxO" firstAttribute="centerX" secondItem="i5M-Pr-FkT" secondAttribute="centerX" id="aJ5-Rk-qcu"/>
<constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="eyD-Iy-5pN" secondAttribute="trailing" id="bbE-PY-j4r"/> <constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="eyD-Iy-5pN" secondAttribute="trailing" id="bbE-PY-j4r"/>
<constraint firstAttribute="bottom" secondItem="w7f-wU-Eto" secondAttribute="bottom" id="clw-Ck-R1b"/>
<constraint firstItem="eyD-Iy-5pN" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" id="sGi-Ff-y6I"/> <constraint firstItem="eyD-Iy-5pN" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" id="sGi-Ff-y6I"/>
</constraints> </constraints>
<point key="canvasLocation" x="131" y="-12"/> <point key="canvasLocation" x="130.53435114503816" y="-12.67605633802817"/>
</view> </view>
</objects> </objects>
<resources> <resources>
<image name="dengluye-login" width="402" height="465"/> <image name="BBBBBBBBBGo.png" width="402" height="874"/>
<image name="dengluye-login" width="402" height="402"/>
<image name="sp-10000h+" width="302" height="130"/>
<image name="sp-SpeakEasyLearning" width="318.66665649414062" height="67"/>
<systemColor name="systemBackgroundColor"> <systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor> </systemColor>
......
...@@ -82,7 +82,7 @@ ...@@ -82,7 +82,7 @@
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="xbG-3d-KMi"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="xbG-3d-KMi">
<rect key="frame" x="0.0" y="0.0" width="272" height="60"/> <rect key="frame" x="0.0" y="0.0" width="272" height="60"/>
<subviews> <subviews>
<textField opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="248" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="yuanzhongqing@linkingplay.com" placeholder="E-mail address" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="M4R-vQ-irk"> <textField opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="248" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="E-mail address" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="M4R-vQ-irk">
<rect key="frame" x="16" y="19" width="240" height="22"/> <rect key="frame" x="16" y="19" width="240" height="22"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/> <fontDescription key="fontDescription" type="system" pointSize="16"/>
...@@ -141,7 +141,7 @@ ...@@ -141,7 +141,7 @@
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="khn-vx-1Kx"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="khn-vx-1Kx">
<rect key="frame" x="0.0" y="142" width="272" height="60"/> <rect key="frame" x="0.0" y="142" width="272" height="60"/>
<subviews> <subviews>
<textField opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="248" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="666666" placeholder="Password" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="RcT-ZC-XJJ"> <textField opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="248" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="Password" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="RcT-ZC-XJJ">
<rect key="frame" x="16" y="19" width="190" height="22"/> <rect key="frame" x="16" y="19" width="190" height="22"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/> <fontDescription key="fontDescription" type="system" pointSize="16"/>
......
...@@ -33,7 +33,8 @@ struct UserMode:Codable { ...@@ -33,7 +33,8 @@ struct UserMode:Codable {
var maxContinuousSignDays:Int? var maxContinuousSignDays:Int?
/// 当前签到 /// 当前签到
var currentContinuousSignDays:Int? var currentContinuousSignDays:Int?
/// 是否新用户
var newUser:Bool?
func isLogin() -> Bool { func isLogin() -> Bool {
return (self.token?.count ?? 0 > 0) return (self.token?.count ?? 0 > 0)
...@@ -55,7 +56,8 @@ struct UserMode:Codable { ...@@ -55,7 +56,8 @@ struct UserMode:Codable {
"learnedNative": \UserMode.learnedNative, "learnedNative": \UserMode.learnedNative,
"snowNum": \UserMode.snowNum, "snowNum": \UserMode.snowNum,
"maxContinuousSignDays": \UserMode.maxContinuousSignDays, "maxContinuousSignDays": \UserMode.maxContinuousSignDays,
"currentContinuousSignDays":\UserMode.currentContinuousSignDays "currentContinuousSignDays":\UserMode.currentContinuousSignDays,
"newUser":\UserMode.newUser
] ]
mutating func assign(from source: UserMode?) { mutating func assign(from source: UserMode?) {
...@@ -73,18 +75,6 @@ struct UserMode:Codable { ...@@ -73,18 +75,6 @@ struct UserMode:Codable {
break break
} }
} }
// let mirror = Mirror(reflecting: source)
// for child in mirror.children {
// if let key = child.label {
// // 使用键路径动态设置值
// if let value = child.value as? Int, let intKey = UserMode.keyPathMap[key] as? WritableKeyPath<UserMode, Int?> {
// self[keyPath: intKey] = value
// } else if let value = child.value as? String , let intKey = UserMode.keyPathMap[key] as? WritableKeyPath<UserMode, String?>{
// self[keyPath: intKey] = value
// }
// }
// }
} }
} }
...@@ -33,6 +33,7 @@ class SpeakDialogueViewCtr: SpeakEleBaseViewCtr { ...@@ -33,6 +33,7 @@ class SpeakDialogueViewCtr: SpeakEleBaseViewCtr {
var isReStart = false var isReStart = false
var isMute = false var isMute = false
private var Translates = NSMutableSet() private var Translates = NSMutableSet()
let viewModel = SpeakDialogueViewModel() let viewModel = SpeakDialogueViewModel()
var dataLesssion:SpeakLessonDescpModel? var dataLesssion:SpeakLessonDescpModel?
...@@ -94,6 +95,7 @@ class SpeakDialogueViewCtr: SpeakEleBaseViewCtr { ...@@ -94,6 +95,7 @@ class SpeakDialogueViewCtr: SpeakEleBaseViewCtr {
self.dataSource = viewModel.dialogLeassAsk self.dataSource = viewModel.dialogLeassAsk
self.SpeakLeassonTableView.reloadData() self.SpeakLeassonTableView.reloadData()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) { DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
self.tipsAnimateFinish()
self.scrollTop() self.scrollTop()
} }
} }
...@@ -111,6 +113,10 @@ class SpeakDialogueViewCtr: SpeakEleBaseViewCtr { ...@@ -111,6 +113,10 @@ class SpeakDialogueViewCtr: SpeakEleBaseViewCtr {
vc.show() vc.show()
} }
} }
SpeakVideoPPPPPP.addSubview(SpeakAIVideoPlayManager.share)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
SpeakAIVideoPlayManager.share.PlayBg()
}
} }
override func setup() { override func setup() {
...@@ -126,21 +132,12 @@ class SpeakDialogueViewCtr: SpeakEleBaseViewCtr { ...@@ -126,21 +132,12 @@ class SpeakDialogueViewCtr: SpeakEleBaseViewCtr {
SpeakLeassonTableView.register(UINib(nibName: SpeakDialogLoadingCell.id, bundle: nil), forCellReuseIdentifier: SpeakDialogLoadingCell.id) SpeakLeassonTableView.register(UINib(nibName: SpeakDialogLoadingCell.id, bundle: nil), forCellReuseIdentifier: SpeakDialogLoadingCell.id)
SpeakLeassonTableView.register(UINib(nibName: SpeakDialogAIReviewCell.id, bundle: nil), forCellReuseIdentifier: SpeakDialogAIReviewCell.id) SpeakLeassonTableView.register(UINib(nibName: SpeakDialogAIReviewCell.id, bundle: nil), forCellReuseIdentifier: SpeakDialogAIReviewCell.id)
SpeakLeassonTableView.register(UINib(nibName: SpeakDialogQuReviewCell.id, bundle: nil), forCellReuseIdentifier: SpeakDialogQuReviewCell.id) SpeakLeassonTableView.register(UINib(nibName: SpeakDialogQuReviewCell.id, bundle: nil), forCellReuseIdentifier: SpeakDialogQuReviewCell.id)
if let ai = SpeakAIVideoPlayManager.share.SpeakAI.SpeakPlayerLayer ,
let bg = SpeakAIVideoPlayManager.share.backgoundAI.SpeakPlayerLayer {
self.SpeakVideoPPPPPP.layer.addSublayer(ai)
ai.videoGravity = .resizeAspectFill
self.SpeakVideoPPPPPP.layer.addSublayer(bg)
bg.videoGravity = .resizeAspectFill
SpeakAIVideoPlayManager.share.PlayBg()
}
} }
override func viewDidLayoutSubviews() { override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews() super.viewDidLayoutSubviews()
SpeakContentView.cornerRect(radius: 16, [.topLeft,.topRight]) SpeakContentView.cornerRect(radius: 16, [.topLeft,.topRight])
SpeakAIVideoPlayManager.share.SpeakAI.SpeakPlayerLayer?.frame = self.SpeakVideoPPPPPP.bounds SpeakAIVideoPlayManager.share.frame = self.SpeakVideoPPPPPP.bounds
SpeakAIVideoPlayManager.share.backgoundAI.SpeakPlayerLayer?.frame = self.SpeakVideoPPPPPP.bounds
} }
@IBAction func SpeakFavatorTaps(_ sender: UIButton) { @IBAction func SpeakFavatorTaps(_ sender: UIButton) {
...@@ -150,7 +147,13 @@ class SpeakDialogueViewCtr: SpeakEleBaseViewCtr { ...@@ -150,7 +147,13 @@ class SpeakDialogueViewCtr: SpeakEleBaseViewCtr {
@IBAction func SoundTapCloseTaps(_ sender: UIButton) { @IBAction func SoundTapCloseTaps(_ sender: UIButton) {
sender.isSelected = !sender.isSelected sender.isSelected = !sender.isSelected
isMute = sender.isSelected
AudioPlayerManager.shared.setVolume(sender.isSelected ? 0 : 1) AudioPlayerManager.shared.setVolume(sender.isSelected ? 0 : 1)
for (i,_) in self.dataSource.enumerated() {
if let cell = self.SpeakLeassonTableView.cellForRow(at: IndexPath(row: i, section: 0)) as? SpeakDialogAIerCell {
cell.isMute = isMute
}
}
} }
...@@ -163,14 +166,16 @@ class SpeakDialogueViewCtr: SpeakEleBaseViewCtr { ...@@ -163,14 +166,16 @@ class SpeakDialogueViewCtr: SpeakEleBaseViewCtr {
b == true{ b == true{
self?.didddd.isPaused = true self?.didddd.isPaused = true
self?.didddd.invalidate() self?.didddd.invalidate()
self?.display.isPaused = true
self?.display.invalidate() self?.display.invalidate()
//FIXME: test SpeakAIVideoPlayManager.share.removeFromSuperview()
SpeakDayEveryManager.manager.SpeakDayData.studyFreeTm = 600 //self?.studyTm SpeakDayEveryManager.manager.SpeakDayData.studyFreeTm = self?.studyTm
SpeakDayEveryManager.manager.SpeakDayData.studytime = self?.studyTime SpeakDayEveryManager.manager.SpeakDayData.studytime = self?.studyTime
SpeakDayEveryManager.manager.update() SpeakDayEveryManager.manager.update()
if let call = self?.view.callblack { if let call = self?.view.callblack {
call(self?.isSing) call(self?.isSing)
} }
AudioPlayerManager.shared.stop()
self?.navigationController?.popViewController(animated: true) self?.navigationController?.popViewController(animated: true)
} }
} }
...@@ -219,6 +224,7 @@ class SpeakDialogueViewCtr: SpeakEleBaseViewCtr { ...@@ -219,6 +224,7 @@ class SpeakDialogueViewCtr: SpeakEleBaseViewCtr {
self?.isMute = isMate self?.isMute = isMate
self?.dataSource = self?.viewModel.dialogLeassAsk ?? [] self?.dataSource = self?.viewModel.dialogLeassAsk ?? []
self?.scrollTop() self?.scrollTop()
self?.tipsAnimateFinish()
} }
} }
self?.navigationController?.pushViewController(call, animated: true) self?.navigationController?.pushViewController(call, animated: true)
...@@ -236,16 +242,9 @@ class SpeakDialogueViewCtr: SpeakEleBaseViewCtr { ...@@ -236,16 +242,9 @@ class SpeakDialogueViewCtr: SpeakEleBaseViewCtr {
return input return input
}() }()
override func viewWillDisappear(_ animated: Bool) { override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated) super.viewWillDisappear(animated)
} SpeakAIVideoPlayManager.share.stop()
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
self.display.isPaused = true
self.didddd.isPaused = true
AudioPlayerManager.shared.stop()
} }
private lazy var didddd: CADisplayLink = { private lazy var didddd: CADisplayLink = {
...@@ -277,7 +276,7 @@ extension SpeakDialogueViewCtr { ...@@ -277,7 +276,7 @@ extension SpeakDialogueViewCtr {
private func tipsAnimateFinish() { private func tipsAnimateFinish() {
self.view.layoutIfNeeded() self.view.layoutIfNeeded()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
if let last = self.dataSource.last, if let last = self.dataSource.last,
last.AniState == .loading, last.AniState == .loading,
last.role == .AI { last.role == .AI {
......
...@@ -120,7 +120,7 @@ class SpeakDialogueViewModel: NSObject { ...@@ -120,7 +120,7 @@ class SpeakDialogueViewModel: NSObject {
let idx = SpeakElePublicManager.share.PublicData.AIerIndex let idx = SpeakElePublicManager.share.PublicData.AIerIndex
let airs = SpeakHomeViewModel().AIser()[safe: idx] let airs = SpeakHomeViewModel().AIser()[safe: idx]
let vodioID = airs?.voiceId let vodioID = airs?.voiceId
net.SpeakAILeasson(param: ["lessonId":lessonId,"isReStart":isReStart ,"userAnswer":userAnswer, "isSub":/*IAPViewModel.share.isSubscribed*/true ,"voiceId":vodioID]) {[weak self] ( su ,data:SpeakdialogueTalkModel?) in net.SpeakAILeasson(param: ["lessonId":lessonId,"isReStart":isReStart ,"userAnswer":userAnswer, "isSub":IAPViewModel.share.isSubscribed ,"voiceId":vodioID]) {[weak self] ( su ,data:SpeakdialogueTalkModel?) in
if su { if su {
self?.isSpeech = true self?.isSpeech = true
if var setD = data, if var setD = data,
......
//
// SpeakAutoLayout.swift
// SpeakEasyLearnEnglish
//
// Created by edy on 2025/9/3.
//
import UIKit
class SpeakAutoLayout: NSLayoutConstraint {
static private let standardHeight: CGFloat = 874
override func awakeFromNib() {
super.awakeFromNib()
updateConstant()
}
private func updateConstant() {
let screenHeight = UIScreen.main.bounds.height
guard SpeakAutoLayout.standardHeight.isFinite && screenHeight.isFinite else {
self.constant = 0
return
}
let calculatedConstant = (screenHeight / SpeakAutoLayout.standardHeight) * self.constant
if calculatedConstant.isFinite {
self.constant = calculatedConstant
} else {
self.constant = 0
}
}
}
...@@ -7,48 +7,73 @@ ...@@ -7,48 +7,73 @@
import UIKit import UIKit
class SpeakAIVideoPlayManager: NSObject { class SpeakAIVideoPlayManager: UIView {
static let share = SpeakAIVideoPlayManager() static let share = SpeakAIVideoPlayManager()
var backgoundAI = SpeakVideoPlayer() private var backgoundAI = SpeakVideoPlayer()
var SpeakAI = SpeakVideoPlayer() private var SpeakAI = SpeakVideoPlayer()
private override init() { private override init(frame: CGRect) {
super.init() super.init(frame: frame)
self.loadVideo()
NotificationCenter.default.addObserver(self, selector: #selector(Foreground), name: UIApplication.willEnterForegroundNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(Foreground), name: UIApplication.willEnterForegroundNotification, object: nil)
SpeakAI.PlayFinish = { [weak self] in SpeakAI.PlayFinish = { [weak self] in
self?.PlayBg() self?.PlayBg()
} }
} }
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc private func Foreground() -> Void { @objc private func Foreground() -> Void {
PlayBg() PlayBg()
} }
func loadVideo() -> Void { func loadVideo() -> Void {
self.layer.sublayers?.forEach({$0.removeFromSuperlayer()})
backgoundAI.loadVideo(state: .none) backgoundAI.loadVideo(state: .none)
SpeakAI.loadVideo(state: .runloop) SpeakAI.loadVideo(state: .runloop)
if let bg = backgoundAI.SpeakPlayerLayer,
let ai = SpeakAI.SpeakPlayerLayer{
self.layer.insertSublayer(bg, at: 10)
self.layer.insertSublayer(ai, at: 15)
Print("添加AI动画成功")
}
} }
func PlaySpeak(_ duration:Double) -> Void { func PlaySpeak(_ duration:Double) -> Void {
SpeakAI.SpeakPlayerLayer?.zPosition = 1 SpeakAI.SpeakPlayerLayer?.zPosition = 15
backgoundAI.stop()
backgoundAI.SpeakPlayerLayer?.zPosition = 0 backgoundAI.SpeakPlayerLayer?.zPosition = 10
backgoundAI.play()
let vduration = SpeakAI.duration let vduration = SpeakAI.duration
let count = ceil(duration / vduration) let count = ceil(duration / vduration)
let rate = (count*vduration)/duration + 0.03 let rate = (count*vduration)/duration + 0.03
SpeakAI.videoPlayer(rate, playCount: Int(count)) SpeakAI.videoPlayer(rate, playCount: Int(count))
} }
func PlayBg() -> Void { func PlayBg() -> Void {
SpeakAI.SpeakPlayerLayer?.zPosition = 0 SpeakAI.SpeakPlayerLayer?.zPosition = 10
SpeakAI.play()
backgoundAI.SpeakPlayerLayer?.zPosition = 15
backgoundAI.play()
}
override func layoutSubviews() {
super.layoutSubviews()
self.layoutIfNeeded()
SpeakAI.SpeakPlayerLayer?.frame = self.bounds
backgoundAI.SpeakPlayerLayer?.frame = self.bounds
}
func stop() -> Void {
SpeakAI.stop() SpeakAI.stop()
backgoundAI.videoPlayer() backgoundAI.stop()
backgoundAI.SpeakPlayerLayer?.zPosition = 1
} }
} }
...@@ -18,17 +18,16 @@ class SpeakVideoPlayer { ...@@ -18,17 +18,16 @@ class SpeakVideoPlayer {
var SpeakPlayer:AVPlayer? var SpeakPlayer:AVPlayer?
var SpeakPlayerLayer:AVPlayerLayer? var SpeakPlayerLayer:AVPlayerLayer?
var SpeakPlayCount:Int = 0 private var SpeakPlayCount:Int = 0
var SpeakCurrentPlay:Int = 0 private var SpeakCurrentPlay:Int = 0
var duration:Double = 1 var duration:Double = 1
var PlayFinish:(()->Void)? var PlayFinish:(()->Void)?
open func videoPlayer(_ rate:Double = 1 , playCount:Int = 0) -> Void { open func videoPlayer(_ rate:Double = 1 , playCount:Int = 0) -> Void {
self.stop()
SpeakPlayCount = playCount SpeakPlayCount = playCount
SpeakCurrentPlay = 0 SpeakCurrentPlay = 0
SpeakPlayer?.play()
DispatchQueue.main.asyncAfter(deadline: .now()+0.1) { DispatchQueue.main.asyncAfter(deadline: .now()+0.1) {
self.play()
self.SpeakPlayer?.rate = Float(rate) self.SpeakPlayer?.rate = Float(rate)
} }
} }
...@@ -47,21 +46,16 @@ class SpeakVideoPlayer { ...@@ -47,21 +46,16 @@ class SpeakVideoPlayer {
} }
} }
// 初始化多个视频播放器
private func setupPlayers(videoURL: URL) { private func setupPlayers(videoURL: URL) {
let asset = AVAsset(url: videoURL)
let playerItem = AVPlayerItem(url: videoURL) let playerItem = AVPlayerItem(asset: asset)
let player = AVPlayer(playerItem: playerItem) let player = AVPlayer(playerItem: playerItem)
self.SpeakPlayer = player self.SpeakPlayer = player
let playerLayer = AVPlayerLayer(player: player) let playerLayer = AVPlayerLayer(player: self.SpeakPlayer)
playerLayer.videoGravity = .resizeAspectFill playerLayer.videoGravity = .resizeAspectFill
playerLayer.shouldRasterize = true playerLayer.shouldRasterize = true
playerLayer.rasterizationScale = UIScreen.main.nativeScale playerLayer.rasterizationScale = UIScreen.main.nativeScale
self.SpeakPlayerLayer = playerLayer self.SpeakPlayerLayer = playerLayer
playerItem.preferredPeakBitRate = 1
let asset = AVAsset(url: videoURL)
asset.loadValuesAsynchronously(forKeys: ["duration"]) { [weak self] in asset.loadValuesAsynchronously(forKeys: ["duration"]) { [weak self] in
DispatchQueue.main.async { DispatchQueue.main.async {
var error: NSError? var error: NSError?
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment