Commit e1763f450f76c1b2d42e765a581a39ed47b9e885

Authored by “张旭”
1 parent 756453e9

横屏选集

metaCode.xcodeproj/project.pbxproj
@@ -196,6 +196,7 @@ @@ -196,6 +196,7 @@
196 1965FA422AFB79EA00F0F435 /* CNLiveGoodsCategoryController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1965FA412AFB79EA00F0F435 /* CNLiveGoodsCategoryController.swift */; }; 196 1965FA422AFB79EA00F0F435 /* CNLiveGoodsCategoryController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1965FA412AFB79EA00F0F435 /* CNLiveGoodsCategoryController.swift */; };
197 1969E1AD2C92E98700E4185E /* CNHomeWebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1969E1AC2C92E98700E4185E /* CNHomeWebViewController.swift */; }; 197 1969E1AD2C92E98700E4185E /* CNHomeWebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1969E1AC2C92E98700E4185E /* CNHomeWebViewController.swift */; };
198 1969E1AF2C942F4400E4185E /* CNLivePhotoManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1969E1AE2C942F4400E4185E /* CNLivePhotoManager.swift */; }; 198 1969E1AF2C942F4400E4185E /* CNLivePhotoManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1969E1AE2C942F4400E4185E /* CNLivePhotoManager.swift */; };
  199 + 196A55F52D95432B00B06DB7 /* CNLiveVodLandscapeBeiSuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 196A55F42D95432B00B06DB7 /* CNLiveVodLandscapeBeiSuView.swift */; };
199 197325D22BB11C18002E41A3 /* DatabaseManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197325D12BB11C18002E41A3 /* DatabaseManager.swift */; }; 200 197325D22BB11C18002E41A3 /* DatabaseManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197325D12BB11C18002E41A3 /* DatabaseManager.swift */; };
200 1975636E2C5A2EB2004E0F42 /* CNLiveVitaeWorkDetailController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1975636D2C5A2EB2004E0F42 /* CNLiveVitaeWorkDetailController.swift */; }; 201 1975636E2C5A2EB2004E0F42 /* CNLiveVitaeWorkDetailController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1975636D2C5A2EB2004E0F42 /* CNLiveVitaeWorkDetailController.swift */; };
201 197563712C5A3151004E0F42 /* CNLiveVitaeWorkCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197563702C5A3151004E0F42 /* CNLiveVitaeWorkCell.swift */; }; 202 197563712C5A3151004E0F42 /* CNLiveVitaeWorkCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197563702C5A3151004E0F42 /* CNLiveVitaeWorkCell.swift */; };
@@ -595,6 +596,7 @@ @@ -595,6 +596,7 @@
595 1965FA412AFB79EA00F0F435 /* CNLiveGoodsCategoryController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CNLiveGoodsCategoryController.swift; sourceTree = "<group>"; }; 596 1965FA412AFB79EA00F0F435 /* CNLiveGoodsCategoryController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CNLiveGoodsCategoryController.swift; sourceTree = "<group>"; };
596 1969E1AC2C92E98700E4185E /* CNHomeWebViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CNHomeWebViewController.swift; sourceTree = "<group>"; }; 597 1969E1AC2C92E98700E4185E /* CNHomeWebViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CNHomeWebViewController.swift; sourceTree = "<group>"; };
597 1969E1AE2C942F4400E4185E /* CNLivePhotoManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CNLivePhotoManager.swift; sourceTree = "<group>"; }; 598 1969E1AE2C942F4400E4185E /* CNLivePhotoManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CNLivePhotoManager.swift; sourceTree = "<group>"; };
  599 + 196A55F42D95432B00B06DB7 /* CNLiveVodLandscapeBeiSuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CNLiveVodLandscapeBeiSuView.swift; sourceTree = "<group>"; };
598 197325D12BB11C18002E41A3 /* DatabaseManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseManager.swift; sourceTree = "<group>"; }; 600 197325D12BB11C18002E41A3 /* DatabaseManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseManager.swift; sourceTree = "<group>"; };
599 1975636D2C5A2EB2004E0F42 /* CNLiveVitaeWorkDetailController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CNLiveVitaeWorkDetailController.swift; sourceTree = "<group>"; }; 601 1975636D2C5A2EB2004E0F42 /* CNLiveVitaeWorkDetailController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CNLiveVitaeWorkDetailController.swift; sourceTree = "<group>"; };
600 197563702C5A3151004E0F42 /* CNLiveVitaeWorkCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CNLiveVitaeWorkCell.swift; sourceTree = "<group>"; }; 602 197563702C5A3151004E0F42 /* CNLiveVitaeWorkCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CNLiveVitaeWorkCell.swift; sourceTree = "<group>"; };
@@ -1381,6 +1383,7 @@ @@ -1381,6 +1383,7 @@
1381 195650C12D75435700818FC8 /* VodDetail */ = { 1383 195650C12D75435700818FC8 /* VodDetail */ = {
1382 isa = PBXGroup; 1384 isa = PBXGroup;
1383 children = ( 1385 children = (
  1386 + 196A55F32D9542EE00B06DB7 /* HengPing */,
1384 195650B42D7047C500818FC8 /* CNLiveZFPlayerControlView.swift */, 1387 195650B42D7047C500818FC8 /* CNLiveZFPlayerControlView.swift */,
1385 195650C22D7543A500818FC8 /* CNLiveVodIntroductionCell.swift */, 1388 195650C22D7543A500818FC8 /* CNLiveVodIntroductionCell.swift */,
1386 195650C62D769B2A00818FC8 /* CNLiveVodAlbumListCell.swift */, 1389 195650C62D769B2A00818FC8 /* CNLiveVodAlbumListCell.swift */,
@@ -1477,6 +1480,14 @@ @@ -1477,6 +1480,14 @@
1477 path = GoodsManager; 1480 path = GoodsManager;
1478 sourceTree = "<group>"; 1481 sourceTree = "<group>";
1479 }; 1482 };
  1483 + 196A55F32D9542EE00B06DB7 /* HengPing */ = {
  1484 + isa = PBXGroup;
  1485 + children = (
  1486 + 196A55F42D95432B00B06DB7 /* CNLiveVodLandscapeBeiSuView.swift */,
  1487 + );
  1488 + path = HengPing;
  1489 + sourceTree = "<group>";
  1490 + };
1480 197325D02BB11BFD002E41A3 /* DatabaseManager */ = { 1491 197325D02BB11BFD002E41A3 /* DatabaseManager */ = {
1481 isa = PBXGroup; 1492 isa = PBXGroup;
1482 children = ( 1493 children = (
@@ -2453,6 +2464,7 @@ @@ -2453,6 +2464,7 @@
2453 790B1FB62A41938F0074CF00 /* UIImage+CNLiveExtensions.swift in Sources */, 2464 790B1FB62A41938F0074CF00 /* UIImage+CNLiveExtensions.swift in Sources */,
2454 192ED4692C4F77370057244C /* CNLiveHangYeFirCell.swift in Sources */, 2465 192ED4692C4F77370057244C /* CNLiveHangYeFirCell.swift in Sources */,
2455 196211E12D66BCDE001925EC /* CNLiveHomeLanmuCell.swift in Sources */, 2466 196211E12D66BCDE001925EC /* CNLiveHomeLanmuCell.swift in Sources */,
  2467 + 196A55F52D95432B00B06DB7 /* CNLiveVodLandscapeBeiSuView.swift in Sources */,
2456 19C735C12BFDCEE900CACF4E /* CNLiveTotalHotListController.swift in Sources */, 2468 19C735C12BFDCEE900CACF4E /* CNLiveTotalHotListController.swift in Sources */,
2457 7939B0732B47F12F005AE981 /* CNLiveShortVideoViewController.swift in Sources */, 2469 7939B0732B47F12F005AE981 /* CNLiveShortVideoViewController.swift in Sources */,
2458 19BB1FEA2AEF7B4A0094D962 /* CNLiveShopConsoleCell.swift in Sources */, 2470 19BB1FEA2AEF7B4A0094D962 /* CNLiveShopConsoleCell.swift in Sources */,
metaCode/Classes/Main/HomePages/ViewModel/CNLiveHomePageViewModel.swift
@@ -81,6 +81,7 @@ class CNLiveHomePageViewModel:NSObject,URLSessionTaskDelegate{ @@ -81,6 +81,7 @@ class CNLiveHomePageViewModel:NSObject,URLSessionTaskDelegate{
81 81
82 task.resume() 82 task.resume()
83 } 83 }
  84 +
84 func urlSession(_ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse, newRequest request: URLRequest, completionHandler: @escaping (URLRequest?) -> Void) { 85 func urlSession(_ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse, newRequest request: URLRequest, completionHandler: @escaping (URLRequest?) -> Void) {
85 print("\(response.statusCode)") // 302 86 print("\(response.statusCode)") // 302
86 print("\(response.allHeaderFields["Location"] as? String ?? "无重定向地址")") // 重定向地址URL 87 print("\(response.allHeaderFields["Location"] as? String ?? "无重定向地址")") // 重定向地址URL
metaCode/Classes/Main/HuBiLieHomePage/Controller/CNLiveTVPlayerViewController.swift
@@ -492,6 +492,7 @@ class CNLiveTVPlayerViewController:UIViewController, UITableViewDataSource, UITa @@ -492,6 +492,7 @@ class CNLiveTVPlayerViewController:UIViewController, UITableViewDataSource, UITa
492 492
493 //播放url更换title 493 //播放url更换title
494 func playWithUrlAndTitle(url:String,title:String){ 494 func playWithUrlAndTitle(url:String,title:String){
  495 + self.player.currentPlayerManager.rate = 1.0
495 self.url = URL(string: url) 496 self.url = URL(string: url)
496 var urls = [URL]() 497 var urls = [URL]()
497 urls.append(self.url!) 498 urls.append(self.url!)
metaCode/Classes/Main/HuBiLieHomePage/View/VodDetail/CNLiveZFPlayerControlView.swift
@@ -13,11 +13,36 @@ class CNLiveZFPlayerControlView:ZFPlayerControlView{ @@ -13,11 +13,36 @@ class CNLiveZFPlayerControlView:ZFPlayerControlView{
13 let closeBtn = UIButton(type: .custom) 13 let closeBtn = UIButton(type: .custom)
14 closeBtn.setTitle("倍速", for: .normal) 14 closeBtn.setTitle("倍速", for: .normal)
15 closeBtn.setTitleColor(HexColor("#FFFFFF"), for: .normal) 15 closeBtn.setTitleColor(HexColor("#FFFFFF"), for: .normal)
16 - closeBtn.titleLabel?.font = Font_10 16 + closeBtn.titleLabel?.font = Font_12
17 closeBtn.addTarget(self, action: #selector(beiSuBtnAction), for: .touchUpInside) 17 closeBtn.addTarget(self, action: #selector(beiSuBtnAction), for: .touchUpInside)
18 closeBtn.backgroundColor = .clear 18 closeBtn.backgroundColor = .clear
19 return closeBtn 19 return closeBtn
20 }() 20 }()
  21 + lazy var gaoqingBtn: UIButton = {
  22 + let closeBtn = UIButton(type: .custom)
  23 + closeBtn.setTitle("高清", for: .normal)
  24 + closeBtn.setTitleColor(HexColor("#FFFFFF"), for: .normal)
  25 + closeBtn.titleLabel?.font = Font_12
  26 + closeBtn.addTarget(self, action: #selector(gaoqingBtnAction), for: .touchUpInside)
  27 + closeBtn.backgroundColor = .clear
  28 + return closeBtn
  29 + }()
  30 +
  31 + lazy var xuanjiBtn: UIButton = {
  32 + let closeBtn = UIButton(type: .custom)
  33 + closeBtn.setTitle("选集", for: .normal)
  34 + closeBtn.setTitleColor(HexColor("#FFFFFF"), for: .normal)
  35 + closeBtn.titleLabel?.font = Font_12
  36 + closeBtn.addTarget(self, action: #selector(xuanjiBtnAction), for: .touchUpInside)
  37 + closeBtn.backgroundColor = .clear
  38 + return closeBtn
  39 + }()
  40 +
  41 + lazy var beiSuBgView :CNLiveVodLandscapeBeiSuView = {
  42 + let bottomNavView = CNLiveVodLandscapeBeiSuView()
  43 + return bottomNavView
  44 + }()
  45 +
21 46
22 override init(frame: CGRect) { 47 override init(frame: CGRect) {
23 super.init(frame: frame) 48 super.init(frame: frame)
@@ -30,6 +55,39 @@ class CNLiveZFPlayerControlView:ZFPlayerControlView{ @@ -30,6 +55,39 @@ class CNLiveZFPlayerControlView:ZFPlayerControlView{
30 55
31 func initUI(){ 56 func initUI(){
32 self.landScapeControlView.bottomToolView.addSubview(self.beiSuBtn) 57 self.landScapeControlView.bottomToolView.addSubview(self.beiSuBtn)
  58 + beiSuBtn.snp.makeConstraints { make in
  59 + make.left.equalTo(self.landScapeControlView.totalTimeLabel.snp.right).offset(5)
  60 + make.centerY.equalTo(self.landScapeControlView.slider.snp.centerY)
  61 + make.width.equalTo(40)
  62 + make.height.equalTo(30)
  63 + }
  64 +
  65 + self.landScapeControlView.bottomToolView.addSubview(self.gaoqingBtn)
  66 + gaoqingBtn.snp.makeConstraints { make in
  67 + make.left.equalTo(self.beiSuBtn.snp.right)
  68 + make.centerY.equalTo(self.landScapeControlView.slider.snp.centerY)
  69 + make.width.equalTo(self.beiSuBtn.snp.width)
  70 + make.height.equalTo(self.beiSuBtn.snp.height)
  71 + }
  72 +
  73 + self.landScapeControlView.bottomToolView.addSubview(self.xuanjiBtn)
  74 + xuanjiBtn.snp.makeConstraints { make in
  75 + make.left.equalTo(self.gaoqingBtn.snp.right)
  76 + make.centerY.equalTo(self.landScapeControlView.slider.snp.centerY)
  77 + make.width.equalTo(self.beiSuBtn.snp.width)
  78 + make.height.equalTo(self.beiSuBtn.snp.height)
  79 + }
  80 +
  81 + self.addSubview(self.beiSuBgView)
  82 + beiSuBgView.snp.makeConstraints { make in
  83 + make.left.right.top.bottom.equalToSuperview()
  84 + }
  85 + self.beiSuBgView.isHidden = true
  86 + self.beiSuBgView.beiSuUpdateBlock = {[weak self] rate in
  87 + guard let self = self else { return }
  88 + self.player?.currentPlayerManager.rate = rate
  89 + self.beiSuBgView.isHidden = true
  90 + }
33 } 91 }
34 92
35 override func layoutSubviews() { 93 override func layoutSubviews() {
@@ -48,7 +106,7 @@ class CNLiveZFPlayerControlView:ZFPlayerControlView{ @@ -48,7 +106,7 @@ class CNLiveZFPlayerControlView:ZFPlayerControlView{
48 self.landScapeControlView.slider.frame = CGRect(x: min_x1, y: min_y1, width: min_w1, height: min_h1) 106 self.landScapeControlView.slider.frame = CGRect(x: min_x1, y: min_y1, width: min_w1, height: min_h1)
49 self.landScapeControlView.slider.centerY = self.landScapeControlView.playOrPauseBtn.centerY 107 self.landScapeControlView.slider.centerY = self.landScapeControlView.playOrPauseBtn.centerY
50 108
51 - self.beiSuBtn.frame = CGRect(x: self.landScapeControlView.totalTimeLabel.right + 10.0, y: 0, width: 40, height: min_h1) 109 + self.beiSuBtn.frame = CGRect(x: self.landScapeControlView.totalTimeLabel.right + 5.0, y: 0, width: 40, height: min_h1)
52 self.beiSuBtn.centerY = self.landScapeControlView.slider.centerY 110 self.beiSuBtn.centerY = self.landScapeControlView.slider.centerY
53 // print("totalTimeLabel:\n \(self.landScapeControlView.totalTimeLabel)") 111 // print("totalTimeLabel:\n \(self.landScapeControlView.totalTimeLabel)")
54 // print("slider:\n \(self.landScapeControlView.slider)") 112 // print("slider:\n \(self.landScapeControlView.slider)")
@@ -57,6 +115,16 @@ class CNLiveZFPlayerControlView:ZFPlayerControlView{ @@ -57,6 +115,16 @@ class CNLiveZFPlayerControlView:ZFPlayerControlView{
57 } 115 }
58 116
59 @objc func beiSuBtnAction(){ 117 @objc func beiSuBtnAction(){
60 - print("beiSuBtn") 118 + self.beiSuBgView.isHidden = false
  119 +
61 } 120 }
  121 +
  122 + @objc func gaoqingBtnAction(){
  123 + print("gaoqing")
  124 + }
  125 +
  126 + @objc func xuanjiBtnAction(){
  127 + print("xuanji")
  128 + }
  129 +
62 } 130 }
metaCode/Classes/Main/HuBiLieHomePage/View/VodDetail/HengPing/CNLiveVodLandscapeBeiSuView.swift 0 → 100644
  1 +//
  2 +// CNLiveVodLandscapeBeiSuView.swift
  3 +// metaCode
  4 +//
  5 +// Created by zx on 2025/3/27.
  6 +// 横屏倍速
  7 +
  8 +import Foundation
  9 +
  10 +typealias CNLiveVodLandscapeBeiSuUpdateBlock = (_ rate:Float)->Void
  11 +
  12 +class CNLiveVodLandscapeBeiSuView:UIView{
  13 +
  14 + var beiSuUpdateBlock:CNLiveVodLandscapeBeiSuUpdateBlock?
  15 + var currSeleIdx = 2//1.0
  16 + //MARK: - 懒加载
  17 + lazy var titleLabel: UILabel = {
  18 + let titleLbl = UILabel()
  19 + titleLbl.font = Font_14
  20 + titleLbl.textColor = HexColor("#FFFFFF")
  21 + titleLbl.text = "倍速"
  22 + return titleLbl
  23 + }()
  24 +
  25 + override init(frame: CGRect) {
  26 + super.init(frame: frame)
  27 + self.backgroundColor = HexColor("#000000", alpha: 0.7)
  28 + self.isUserInteractionEnabled = true
  29 + self.initUI()
  30 + self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tapAction)))
  31 + }
  32 +
  33 + required init?(coder: NSCoder) {
  34 + fatalError("init(coder:) has not been implemented")
  35 + }
  36 +
  37 + func initUI(){
  38 +
  39 + self.addSubview(self.titleLabel)
  40 + titleLabel.snp.makeConstraints { make in
  41 + make.top.equalToSuperview().offset(31)
  42 + make.centerX.equalToSuperview()
  43 + }
  44 +
  45 + var W:CGFloat = 65.0
  46 + var H:CGFloat = 65.0
  47 + let padding:CGFloat = 18.0
  48 + let leftPadding:CGFloat = (KSreenHeight-W*6-padding*5)*0.5
  49 + var title = "0.5x"
  50 + for i in 0..<6{
  51 + let expandBtn = UIButton.init(type: .custom)
  52 + expandBtn.frame = CGRect(x: leftPadding+CGFloat(i)*(W+padding), y: 0, width: W, height: H)
  53 + expandBtn.centerY = KSreenWidth*0.5
  54 + if i == 0{
  55 + title = "0.5x"
  56 + }else if i == 1{
  57 + title = "0.75x"
  58 + }else if i == 2{
  59 + title = "1.0x"
  60 +
  61 + }else if i == 3{
  62 + title = "1.25x"
  63 + }else if i == 4{
  64 + title = "1.5x"
  65 + }else if i == 5{
  66 + title = "2.0x"
  67 + }
  68 + if i == self.currSeleIdx{
  69 + expandBtn.backgroundColor = HexColor("#D3E4FF")
  70 + expandBtn.layer.borderWidth = 0.65
  71 + expandBtn.layer.borderColor = HexColor("#478BFF")?.cgColor
  72 + expandBtn.isSelected = true
  73 + }else{
  74 + expandBtn.backgroundColor = HexColor("#000000")
  75 + expandBtn.layer.borderWidth = 0
  76 + expandBtn.layer.borderColor = HexColor("#000000")?.cgColor
  77 + expandBtn.isSelected = false
  78 + }
  79 + expandBtn.setTitle(title, for: .normal)
  80 + expandBtn.setTitle(title, for: .selected)
  81 + expandBtn.setTitleColor(HexColor("#FFFFFF"), for: .normal)
  82 + expandBtn.setTitleColor(HexColor("#478BFF"), for: .selected)
  83 + expandBtn.titleLabel?.font = Font_18
  84 + expandBtn.layer.cornerRadius = 12
  85 + expandBtn.clipsToBounds = true
  86 + expandBtn.tag = 100+i
  87 + expandBtn.addTarget(self, action: #selector(beisuBtnAction), for: .touchUpInside)
  88 + self.addSubview(expandBtn)
  89 + }
  90 + }
  91 +
  92 + @objc func beisuBtnAction(btn:UIButton){
  93 + let btnTag = btn.tag
  94 + for obj in self.subviews{
  95 + if obj.tag >= 100{
  96 + if obj.tag == btnTag{
  97 + if let tmpBtn = obj as? UIButton{
  98 + tmpBtn.backgroundColor = HexColor("#D3E4FF")
  99 + tmpBtn.layer.borderWidth = 0.65
  100 + tmpBtn.layer.borderColor = HexColor("#478BFF")?.cgColor
  101 + tmpBtn.isSelected = true
  102 + }
  103 + }else{
  104 + if let tmpBtn = obj as? UIButton{
  105 + tmpBtn.backgroundColor = HexColor("#000000")
  106 + tmpBtn.layer.borderWidth = 0
  107 + tmpBtn.layer.borderColor = HexColor("#000000")?.cgColor
  108 + tmpBtn.isSelected = false
  109 + }
  110 + }
  111 + }
  112 + }
  113 +
  114 + let i = btn.tag-100
  115 + var rate:Float = 1.0
  116 + if i == 0{
  117 + rate = 0.5
  118 + }else if i == 1{
  119 + rate = 0.75
  120 + }else if i == 2{
  121 + rate = 1.0
  122 + }else if i == 3{
  123 + rate = 1.25
  124 + }else if i == 4{
  125 + rate = 1.5
  126 + }else if i == 5{
  127 + rate = 2.0
  128 + }
  129 + self.beiSuUpdateBlock?(rate)
  130 + }
  131 +
  132 + @objc func tapAction(){
  133 + self.isHidden = true
  134 + }
  135 +
  136 +}
  137 +