Skip to content
4 changes: 2 additions & 2 deletions AgoraWidgets.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |spec|
spec.name = "AgoraWidgets"
spec.version = "2.8.100"
spec.version = "2.8.101"
spec.summary = "Agora widgets"
spec.description = "Agora native widgets"
spec.homepage = "https://docs.agora.io/en/agora-class/landing-page?platform=iOS"
Expand All @@ -18,7 +18,7 @@ Pod::Spec.new do |spec|
spec.dependency "AgoraUIBaseViews", ">=2.8.0"
spec.dependency "AgoraWidget", ">=2.8.0"
spec.dependency "AgoraLog", "1.0.2"
spec.dependency "Armin", ">=1.1.0"
spec.dependency "Armin", "~> 1.0"

spec.dependency "SwifterSwift"
spec.dependency "Masonry"
Expand Down
2 changes: 1 addition & 1 deletion AgoraWidgets_Local.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |spec|
spec.name = "AgoraWidgets"
spec.version = "2.8.100"
spec.version = "2.8.101"
spec.summary = "SDKs/AgoraWidgets."
spec.description = "Agora native widgets"
spec.homepage = "https://docs.agora.io/en/agora-class/landing-page?platform=iOS"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,19 @@ extension AgoraChatInputView: UITextFieldDelegate {
onClickSendMessage()
return true
}

func textField(_ textField: UITextField,
shouldChangeCharactersIn range: NSRange,
replacementString string: String) -> Bool {
guard let currentText = textField.text else {
return true
}

let newText = currentText.replacingCharacters(in: Range(range, in: currentText)!,
with: string)

return newText.count <= 300
}
}
// MARK: - Actions
private extension AgoraChatInputView {
Expand Down Expand Up @@ -234,4 +247,3 @@ extension AgoraChatInputView: AgoraUIContentContainer {
sendButton.layer.cornerRadius = config.cornerRadius
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ class AgoraChatAnnouncementView: UIView {
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

}

// MARK: - AgoraUIContentContainer
Expand Down Expand Up @@ -129,6 +128,7 @@ extension AgoraChatAnnouncementView: AgoraUIContentContainer {
make?.left.equalTo()(13)
make?.top.equalTo()(13)
make?.width.height().lessThanOrEqualTo()(self)?.offset()(-14)
make?.bottom.lessThanOrEqualTo()(self)?.offset()(-34)
}

deleteButton.mas_makeConstraints { make in
Expand Down Expand Up @@ -257,6 +257,11 @@ extension AgoraChatAnnouncementView: UITextViewDelegate {
return false
}

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}

func textViewDidEndEditing(_ textView: UITextView) {
inputTextView.resignFirstResponder()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,17 +199,35 @@ extension AgoraChatMessageView: UITableViewDelegate, UITableViewDataSource {
cell.messageImageView.size = size
cell.updateFrame()
} else {
let url = URL(string: model.imageRemoteUrl)
let urlString = model.imageRemoteUrl
let url = URL(string: urlString)
let brokenImage = UIConfig.agoraChat.picture.brokenImage

cell.messageImageView.sd_setImage(with: url,
placeholderImage: brokenImage) { [weak self] downloadImage, error, cacheType, url in
guard let `self` = self else {
return
}
cell.messageImageView.image = downloadImage
let size = cell.sizeWithImage(downloadImage)
cell.messageImageView.size = size
cell.updateFrame()

guard self.messageDataSource.count > indexPath.row else {
return
}

let type = self.messageDataSource[indexPath.row]

guard case .image(var model) = type else {
return
}

guard model.imageRemoteUrl == urlString else {
return
}

model.image = downloadImage

let new = AgoraChatMessageViewType.image(model)

self.messageDataSource[indexPath.row] = new

tableView.reloadRows(at: [indexPath],
with: .none)
Expand All @@ -229,11 +247,16 @@ extension AgoraChatMessageView: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView,
didSelectRowAt indexPath: IndexPath) {
let type = messageDataSource[indexPath.row]

guard case .image(let model) = type else {
return
}
setFullScreenImage(urlString: model.imageRemoteUrl,
localImage: model.image)

guard let image = model.image else {
return
}

setFullScreenImage(localImage: image)
}
}

Expand Down Expand Up @@ -289,23 +312,14 @@ private extension AgoraChatMessageView {
func updateNoticeMessageCell(cell: AgoraChatNoticeMessageCell,
notice: String) {
cell.noticeLabel.text = notice
}
}

func setFullScreenImage(urlString: String?,
localImage:UIImage?) {
func setFullScreenImage(localImage: UIImage) {
let topVc = UIViewController.agora_top_view_controller()

if let localImage = localImage {
topVc.view.bringSubviewToFront(fullScreenImageView)
fullScreenImageView.agora_visible = true
fullScreenImageView.image = localImage
} else if let url = URL(string: urlString) {
topVc.view.bringSubviewToFront(fullScreenImageView)
fullScreenImageView.agora_visible = true
fullScreenImageView.sd_setImage(with: url)
} else {
return
}
topVc.view.bringSubviewToFront(fullScreenImageView)
fullScreenImageView.agora_visible = true
fullScreenImageView.image = localImage
}

@objc func onClickCloseFullScreenImage() {
Expand Down
5 changes: 5 additions & 0 deletions SDKs/AgoraWidgets/Assets/others/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,11 @@ fcr_popup_quiz_my_answer = "My Answer";
fcr_popup_quiz_start_again = "restart";
fcr_popup_quiz_answer_time = "Time elapsed";

//slide
fcr_board_slide_retry = "course load failure, retry now";
fcr_board_slide_retry_failure = "course load failure, please load next page or reopen";


// poll
fcr_poll_title = "Poll";
fcr_poll_submit = "Submit";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ fcr_cloud_upload_file = "上传文件";
fcr_cloud_upload_pictures = "上传图片";
fcr_cloud_uploading = "上传中";

//slide
fcr_board_slide_retry = "课件加载失败,正在重试";
fcr_board_slide_retry_failure = "课件加载失败,请切换下一页或关闭课件后重试";

// AnswerSelector
fcr_popup_quiz = "答题器";
fcr_popup_quiz_post = "提交答案";
Expand Down
4 changes: 2 additions & 2 deletions SDKs/AgoraWidgets/CloudDrive/FcrCloudDriveServerAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class FcrCloudDriveServerAPI: AgoraWidgetServerAPI {
request(event: "cloud-drive-delete-file",
url: urlString,
method: .delete,
parameters: list) { json in
anyParameters: list) { json in
success(resourceUuid)
} failure: { error in
failure(error)
Expand Down Expand Up @@ -117,7 +117,7 @@ class FcrCloudDriveServerAPI: AgoraWidgetServerAPI {
request(event: "cloud-drive",
url: urlString,
method: .post,
parameters: parameters) { json in
anyParameters: parameters) { json in
if let data = (json["data"] as? [[String: Any]])?.first {
success(data)
} else {
Expand Down
12 changes: 4 additions & 8 deletions SDKs/AgoraWidgets/Common/AgoraWidgetServerAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public class AgoraWidgetServerAPI: NSObject {
url: String,
method: ArHttpMethod,
header: [String: String]? = nil,
parameters: Any? = nil,
anyParameters: Any,
success: JsonCompletion? = nil,
failure: FailureCompletion? = nil) {
var extra: [String: Any] = ["event": event]
Expand All @@ -94,9 +94,7 @@ public class AgoraWidgetServerAPI: NSObject {
extra["header"] = header.description
}

if let `parameters` = parameters {
extra["parameters"] = parameters
}
extra["parameters"] = anyParameters

self.armin.logTube?.log(info: "http request",
extra: extra.description)
Expand All @@ -114,10 +112,8 @@ public class AgoraWidgetServerAPI: NSObject {
}

// Parameters
if let params = parameters {
let jsonData = try? JSONSerialization.data(withJSONObject: params)
request.httpBody = jsonData
}
let jsonData = try? JSONSerialization.data(withJSONObject: anyParameters)
request.httpBody = jsonData

request.allHTTPHeaderFields = ["x-agora-token": token,
"x-agora-uid": userId,
Expand Down
39 changes: 36 additions & 3 deletions SDKs/AgoraWidgets/Whiteboard/FcrBoardWidget.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import AgoraWidget
import AgoraLog
import Photos
import Armin
import Whiteboard

@objcMembers public class FcrBoardWidget: AgoraNativeWidget {
// Views
Expand All @@ -28,6 +29,7 @@ import Armin

private var canJoin = false

private var retryTime = 0
// 教师角色加入房间成功时设置,学生角色监听grantedUsers变化设置
private var hasOperationPrivilege: Bool = false {
didSet {
Expand Down Expand Up @@ -57,6 +59,14 @@ import Armin
analyzeGrantedUsersFromRoomProperties()
}

func retry(slideId:String, slideIndex: Int){
self.retryTime += 1
self.boardRoom?.recoverSlide(slideId: slideId, slideIndex: slideIndex)
showToast("fcr_board_slide_retry".localized() + String(self.retryTime) + "/5",
type: .error)
}


public override func onWidgetRoomPropertiesDeleted(_ properties: [String : Any]?,
cause: [String : Any]?,
keyPaths: [String],
Expand Down Expand Up @@ -331,10 +341,10 @@ extension FcrBoardWidget {
let backgroundColor = UIConfig.netlessBoard.backgroundColor
let room = FcrBoardRoom(appId: config.boardAppId,
region: boardRegion,
backgroundColor: backgroundColor)
room.delegate = self
backgroundColor: backgroundColor,
logTube: self)

room.logTube = self
room.delegate = self

let ratio = view.ratio()

Expand Down Expand Up @@ -665,6 +675,29 @@ extension FcrBoardWidget: FcrBoardRoomDelegate {
break
}
}
func onSlideError(slideError: WhiteSlideErrorType, errorMessage: String, slideId: String, slideIndex: Int) {
if(slideError == WhiteSlideErrorType.resourceError || slideError == WhiteSlideErrorType.canvasCrash){
if(self.retryTime == 0){
self.retry(slideId: slideId, slideIndex: slideIndex)
}else if(self.retryTime < 5){
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
self.retry(slideId: slideId, slideIndex: slideIndex)
}
}else{
showToast("fcr_board_slide_retry_failure".localized(),
type: .error)
}
} else if(slideError == WhiteSlideErrorType.runtimeError){
self.boardRoom?.recoverSlide(slideId: slideId, slideIndex: slideIndex + 1)
} else if(slideError == WhiteSlideErrorType.runtimeWarn) {
let slideExtra = ["slideId": slideId,
"slideIndex": slideIndex.agDescription]
log(content: "slide page error",
extra: slideExtra.agDescription, type: .warning,
fromClass: WhiteSDK.self,
funcName: "onSlideError")
}
}
}

// MARK: - FcrBoardMainWindowDelegate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import Whiteboard
// Public
protocol FcrBoardRoomDelegate: NSObjectProtocol {
func onConnectionStateUpdated(state: FcrBoardRoomConnectionState)
func onSlideError(slideError: WhiteSlideErrorType, errorMessage: String, slideId: String, slideIndex: Int)
}

protocol FcrBoardMainWindowDelegate: FcrBoardAudioMixingDelegate {
Expand Down
20 changes: 17 additions & 3 deletions SDKs/AgoraWidgets/Whiteboard/Wrapper/FcrBoardRoom.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import Foundation
import Whiteboard

class FcrBoardRoom: NSObject {
class FcrBoardRoom: NSObject, WhiteSlideDelegate {
private weak var whiteRoom: WhiteRoom?
private let whiteView: WhiteBoardView
private let whiteSDK: WhiteSDK
Expand All @@ -24,7 +24,8 @@ class FcrBoardRoom: NSObject {

init(appId: String,
region: FcrBoardRegion,
backgroundColor: UIColor?) {
backgroundColor: UIColor?,
logTube: FcrBoardLogTube?) {
let listener = FcrBoardListener()

let whiteView = WhiteBoardView(frame: .zero,
Expand All @@ -37,6 +38,7 @@ class FcrBoardRoom: NSObject {
sdkConfig.region = region.netlessValue
sdkConfig.useMultiViews = true
sdkConfig.userCursor = true
sdkConfig.enableAppliancePlugin = true

let whiteSDK = WhiteSDK(whiteBoardView: whiteView,
config: sdkConfig,
Expand All @@ -46,9 +48,11 @@ class FcrBoardRoom: NSObject {
self.whiteView = whiteView
self.whiteSDK = whiteSDK
self.listener = listener
self.logTube = logTube

super.init()

whiteSDK.setSlideDelegate(self)
listener.roomNeedObserve = self

registerH5App()
Expand All @@ -73,12 +77,20 @@ class FcrBoardRoom: NSObject {
funcName: "init")
}


func onSlideError(_ slideError: WhiteSlideErrorType, errorMessage: String, slideId: String, slideIndex: Int) {
delegate?.onSlideError(slideError: slideError, errorMessage: errorMessage, slideId: slideId, slideIndex: slideIndex)
}

func recoverSlide(slideId:String, slideIndex:Int) {
self.whiteSDK.recoverSlide(slideId, slideIndex: slideIndex)
}

func join(config: FcrBoardRoomJoinConfig,
superView: UIView,
success: @escaping (FcrBoardMainWindow) -> Void,
failure: @escaping (Error) -> Void) {
hasLeft = false

joinConfig = config

superView.addSubview(whiteView)
Expand Down Expand Up @@ -163,6 +175,8 @@ private extension FcrBoardRoom {
delegate?.onConnectionStateUpdated(state: state)
}



func getWhiteRoomConfig() -> WhiteRoomConfig? {
guard let config = joinConfig else {
log(content: "join config nil",
Expand Down