mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-30 03:44:18 +00:00
Various improvements
This commit is contained in:
parent
c6acd92aed
commit
29b24d9d57
@ -15299,3 +15299,58 @@ Error: %8$@";
|
||||
|
||||
"Camera.LiveStream.Change" = "change";
|
||||
"Camera.LiveStream.StartLiveStream" = "Start Live Stream";
|
||||
|
||||
"Camera.LiveStream.End" = "End";
|
||||
"Camera.LiveStream.End.Title" = "End Live Stream";
|
||||
"Camera.LiveStream.End.Text" = "Are you sure you want to end this live stream?";
|
||||
"Camera.LiveStream.End.End" = "End";
|
||||
"Camera.LiveStream.End.Leave" = "Leave";
|
||||
|
||||
"Message.RepeatAt" = "%1$@ at %2$@";
|
||||
"Message.RepeatPeriod.Daily" = "daily";
|
||||
"Message.RepeatPeriod.Weekly" = "weekly";
|
||||
"Message.RepeatPeriod.Biweekly" = "biweekly";
|
||||
"Message.RepeatPeriod.Monthly" = "monthly";
|
||||
"Message.RepeatPeriod.3Months" = "every 3 months";
|
||||
"Message.RepeatPeriod.6Months" = "every 6 months";
|
||||
"Message.RepeatPeriod.Yearly" = "yearly";
|
||||
"Message.Approximate" = "appx. %@";
|
||||
|
||||
"LiveStreamSettings.Title" = "Live Settings";
|
||||
"LiveStreamSettings.TitleEdit" = "Live Stream";
|
||||
"LiveStreamSettings.StartLiveAs" = "START LIVE AS";
|
||||
"LiveStreamSettings.WhoCanView" = "WHO CAN VIEW THIS LIVE";
|
||||
"LiveStreamSettings.WhoCanViewInfo" = "[Select people]() who won't see your live.";
|
||||
"LiveStreamSettings.ConnectStream" = "Connect Stream";
|
||||
"LiveStreamSettings.ConnectStreamInfo" = "Stream with a different app.";
|
||||
"LiveStreamSettings.AllowComments" = "Allow Comments";
|
||||
"LiveStreamSettings.AllowScreenshots" = "Allow Screenshots";
|
||||
"LiveStreamSettings.PricePerComment" = "PRICE PER COMMENT";
|
||||
"LiveStreamSettings.PricePerCommentInfo" = "The price a viewer must pay to send a comment.";
|
||||
"LiveStreamSettings.PricePerComment.Free" = "Free";
|
||||
"LiveStreamSettings.PricePerComment.Stars_1" = "%@ Star";
|
||||
"LiveStreamSettings.PricePerComment.Stars_any" = "%@ Stars";
|
||||
"LiveStreamSettings.SaveSettings" = "Save Settings";
|
||||
|
||||
"AddContact.Title" = "New Contact";
|
||||
"AddContact.PhoneNumber.IsContact"= "This phone number is already in your contacts. [View >]()";
|
||||
"AddContact.PhoneNumber.Registered"= "This phone number is on Telegram.";
|
||||
"AddContact.PhoneNumber.NotRegistered"= "This phone number is not on Telegram. [Invite >]()";
|
||||
"AddContact.SyncToPhone" = "Sync Contact to Phone";
|
||||
"AddContact.NotePlaceholder" = "Add notes only visible to you";
|
||||
"AddContact.AddQR" = "Add via QR Code";
|
||||
|
||||
"ScheduleMessage.Time" = "Time";
|
||||
"ScheduleMessage.Repeat" = "Repeat";
|
||||
"ScheduleMessage.RepeatPeriod.Never" = "Never";
|
||||
"ScheduleMessage.RepeatPeriod.Daily" = "Daily";
|
||||
"ScheduleMessage.RepeatPeriod.Weekly" = "Weekly";
|
||||
"ScheduleMessage.RepeatPeriod.Biweekly" = "Biweekly";
|
||||
"ScheduleMessage.RepeatPeriod.Monthly" = "Monthly";
|
||||
"ScheduleMessage.RepeatPeriod.3Months" = "Every 3 Months";
|
||||
"ScheduleMessage.RepeatPeriod.6Months" = "Every 6 Months";
|
||||
"ScheduleMessage.RepeatPeriod.Yearly" = "Yearly";
|
||||
|
||||
"ScheduleMessage.PremiumRequired.Title" = "Premium Required";
|
||||
"ScheduleMessage.PremiumRequired.Text" = "Subscribe to **Telegram Premium** to schedule repeating messages.";
|
||||
"ScheduleMessage.PremiumRequired.Add" = "Add";
|
||||
|
||||
@ -2575,6 +2575,11 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.setupLoginEmail.id).startStandalone()
|
||||
}
|
||||
})
|
||||
if let layout = strongSelf.validLayout, layout.metrics.isTablet {
|
||||
controller.navigationPresentation = .standaloneFlatModal
|
||||
} else {
|
||||
controller.navigationPresentation = .flatModal
|
||||
}
|
||||
navigationController.pushViewController(controller)
|
||||
}
|
||||
})
|
||||
|
||||
@ -75,6 +75,12 @@ struct CameraState: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
enum StreamingMode {
|
||||
case none
|
||||
case camera
|
||||
case rtmp
|
||||
}
|
||||
|
||||
let mode: CameraMode
|
||||
let position: Camera.Position
|
||||
let flashMode: Camera.FlashMode
|
||||
@ -87,7 +93,7 @@ struct CameraState: Equatable {
|
||||
let isCollageEnabled: Bool
|
||||
let collageGrid: Camera.CollageGrid
|
||||
let collageProgress: Float
|
||||
let isStreaming: Bool
|
||||
let isStreaming: StreamingMode
|
||||
let isWaitingForStream: Bool
|
||||
|
||||
func updatedMode(_ mode: CameraMode) -> CameraState {
|
||||
@ -134,7 +140,7 @@ struct CameraState: Equatable {
|
||||
return CameraState(mode: self.mode, position: self.position, flashMode: self.flashMode, flashModeDidChange: self.flashModeDidChange, flashTint: self.flashTint, flashTintSize: self.flashTintSize, recording: self.recording, duration: self.duration, isDualCameraEnabled: self.isDualCameraEnabled, isCollageEnabled: self.isCollageEnabled, collageGrid: self.collageGrid, collageProgress: collageProgress, isStreaming: self.isStreaming, isWaitingForStream: self.isWaitingForStream)
|
||||
}
|
||||
|
||||
func updatedIsStreaming(_ isStreaming: Bool) -> CameraState {
|
||||
func updatedIsStreaming(_ isStreaming: StreamingMode) -> CameraState {
|
||||
return CameraState(mode: self.mode, position: self.position, flashMode: self.flashMode, flashModeDidChange: self.flashModeDidChange, flashTint: self.flashTint, flashTintSize: self.flashTintSize, recording: self.recording, duration: self.duration, isDualCameraEnabled: self.isDualCameraEnabled, isCollageEnabled: self.isCollageEnabled, collageGrid: self.collageGrid, collageProgress: self.collageProgress, isStreaming: isStreaming, isWaitingForStream: self.isWaitingForStream)
|
||||
}
|
||||
|
||||
@ -1133,7 +1139,7 @@ private final class CameraScreenComponent: CombinedComponent {
|
||||
}
|
||||
self.liveStreamStory = story
|
||||
|
||||
controller?.updateCameraState({ $0.updatedIsStreaming(true).updatedIsWaitingForStream(false) }, transition: .spring(duration: 0.4))
|
||||
controller?.updateCameraState({ $0.updatedIsStreaming(rtmp ? .rtmp : .camera).updatedIsWaitingForStream(false) }, transition: .spring(duration: 0.4))
|
||||
self.updated(transition: .immediate)
|
||||
})
|
||||
}
|
||||
@ -1155,9 +1161,9 @@ private final class CameraScreenComponent: CombinedComponent {
|
||||
return
|
||||
}
|
||||
for item in state.items.reversed() {
|
||||
if case let .item(item) = item, case .liveStream = item.media {
|
||||
if case let .item(item) = item, case let .liveStream(liveStream) = item.media {
|
||||
self.liveStreamStory = item
|
||||
controller?.updateCameraState({ $0.updatedIsStreaming(true) }, transition: .spring(duration: 0.4))
|
||||
controller?.updateCameraState({ $0.updatedIsStreaming(liveStream.kind == .rtmp ? .rtmp : .camera) }, transition: .spring(duration: 0.4))
|
||||
self.updated(transition: .immediate)
|
||||
return
|
||||
}
|
||||
@ -1180,17 +1186,17 @@ private final class CameraScreenComponent: CombinedComponent {
|
||||
let alertController = textAlertController(
|
||||
context: self.context,
|
||||
forceTheme: defaultDarkColorPresentationTheme,
|
||||
title: "End Live Stream",
|
||||
text: "Are you sure you want to end this live stream?",
|
||||
title: presentationData.strings.Camera_LiveStream_End_Title,
|
||||
text: presentationData.strings.Camera_LiveStream_End_Text,
|
||||
actions: [
|
||||
TextAlertAction(type: .destructiveAction, title: "End", action: { [weak self, weak controller] in
|
||||
TextAlertAction(type: .destructiveAction, title: presentationData.strings.Camera_LiveStream_End_End, action: { [weak self, weak controller] in
|
||||
guard let self, let controller else {
|
||||
return
|
||||
}
|
||||
let _ = self.liveStreamCall?.leave(terminateIfPossible: true).startStandalone()
|
||||
controller.requestDismiss(animated: true)
|
||||
}),
|
||||
TextAlertAction(type: .genericAction, title: "Leave", action: { [weak controller] in
|
||||
TextAlertAction(type: .genericAction, title: presentationData.strings.Camera_LiveStream_End_Leave, action: { [weak controller] in
|
||||
guard let controller else {
|
||||
return
|
||||
}
|
||||
@ -1206,11 +1212,11 @@ private final class CameraScreenComponent: CombinedComponent {
|
||||
let alertController = textAlertController(
|
||||
context: self.context,
|
||||
forceTheme: defaultDarkColorPresentationTheme,
|
||||
title: "End Live Stream",
|
||||
text: "Are you sure you want to end this live stream?",
|
||||
title: presentationData.strings.Camera_LiveStream_End_Title,
|
||||
text: presentationData.strings.Camera_LiveStream_End_Text,
|
||||
actions: [
|
||||
TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: {}),
|
||||
TextAlertAction(type: .destructiveAction, title: "End", action: { [weak self, weak controller] in
|
||||
TextAlertAction(type: .destructiveAction, title: presentationData.strings.Camera_LiveStream_End_End, action: { [weak self, weak controller] in
|
||||
guard let self, let controller else {
|
||||
return
|
||||
}
|
||||
@ -1435,7 +1441,7 @@ private final class CameraScreenComponent: CombinedComponent {
|
||||
case .video:
|
||||
shutterState = .video
|
||||
case .live:
|
||||
shutterState = .live(active: component.cameraState.isStreaming, progress: component.cameraState.isWaitingForStream)
|
||||
shutterState = .live(active: component.cameraState.isStreaming != .none, progress: component.cameraState.isWaitingForStream)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1560,7 +1566,7 @@ private final class CameraScreenComponent: CombinedComponent {
|
||||
)
|
||||
}
|
||||
|
||||
if component.cameraState.mode == .live, component.cameraState.isStreaming {
|
||||
if component.cameraState.mode == .live, component.cameraState.isStreaming != .none {
|
||||
let liveStream = liveStream.update(
|
||||
component: CameraLiveStreamComponent(
|
||||
context: component.context,
|
||||
@ -1607,7 +1613,7 @@ private final class CameraScreenComponent: CombinedComponent {
|
||||
let topControlVerticalInset: CGFloat = 12.0
|
||||
let topButtonSpacing: CGFloat = 15.0
|
||||
|
||||
if component.cameraState.mode == .live && !component.cameraState.isStreaming {
|
||||
if component.cameraState.mode == .live && component.cameraState.isStreaming == .none {
|
||||
let streamAsButton = streamAsButton.update(
|
||||
component: PlainButtonComponent(
|
||||
content: AnyComponent(
|
||||
@ -1647,7 +1653,7 @@ private final class CameraScreenComponent: CombinedComponent {
|
||||
}
|
||||
|
||||
if case .none = component.cameraState.recording, !state.isTransitioning {
|
||||
if !state.displayingCollageSelection && !component.cameraState.isStreaming {
|
||||
if !state.displayingCollageSelection && component.cameraState.isStreaming == .none {
|
||||
let cancelButton = cancelButton.update(
|
||||
component: CameraButton(
|
||||
content: AnyComponentWithIdentity(
|
||||
@ -1728,22 +1734,23 @@ private final class CameraScreenComponent: CombinedComponent {
|
||||
}
|
||||
|
||||
if hasAllRequiredAccess {
|
||||
let isStreaming = component.cameraState.mode == .live && component.cameraState.isStreaming
|
||||
let isStreaming = component.cameraState.mode == .live && component.cameraState.isStreaming != .none
|
||||
var endStreamButtonWidth: CGFloat = 56.0
|
||||
if isStreaming {
|
||||
let endStreamButton = endStreamButton.update(
|
||||
component: GlassBarButtonComponent(
|
||||
size: CGSize(width: 56.0, height: 40.0),
|
||||
size: nil,
|
||||
backgroundColor: UIColor.black.withAlphaComponent(0.5),
|
||||
isDark: true,
|
||||
state: .glass,
|
||||
component: AnyComponentWithIdentity(id: "label", component: AnyComponent(Text(text: "End", font: Font.semibold(17.0), color: .white))),
|
||||
component: AnyComponentWithIdentity(id: "label", component: AnyComponent(Text(text: environment.strings.Camera_LiveStream_End, font: Font.semibold(17.0), color: .white))),
|
||||
action: { [weak state] _ in
|
||||
if let state {
|
||||
state.endLiveStream()
|
||||
}
|
||||
}
|
||||
),
|
||||
availableSize: CGSize(width: 40.0, height: 40.0),
|
||||
availableSize: CGSize(width: 120.0, height: 40.0),
|
||||
transition: .immediate
|
||||
)
|
||||
context.add(endStreamButton
|
||||
@ -1751,12 +1758,13 @@ private final class CameraScreenComponent: CombinedComponent {
|
||||
.appear(.default(scale: true))
|
||||
.disappear(.default(scale: true))
|
||||
)
|
||||
endStreamButtonWidth = endStreamButton.size.width
|
||||
}
|
||||
|
||||
let rightMostButtonWidth: CGFloat
|
||||
if component.cameraState.mode == .live {
|
||||
if component.cameraState.isStreaming {
|
||||
rightMostButtonWidth = -25.0
|
||||
if component.cameraState.isStreaming != .none {
|
||||
rightMostButtonWidth = -25.0 + (endStreamButtonWidth - 56.0) * 2.0
|
||||
} else {
|
||||
rightMostButtonWidth = -55.0
|
||||
}
|
||||
@ -1824,7 +1832,7 @@ private final class CameraScreenComponent: CombinedComponent {
|
||||
|
||||
if !isSticker && !isAvatar && !isTablet {
|
||||
var nextButtonX = availableSize.width - topControlSideInset - rightMostButtonWidth / 2.0 - 100.0
|
||||
if Camera.isDualCameraSupported(forRoundVideo: false) && !component.cameraState.isCollageEnabled {
|
||||
if Camera.isDualCameraSupported(forRoundVideo: false) && !component.cameraState.isCollageEnabled && component.cameraState.isStreaming == .none {
|
||||
let dualButton = dualButton.update(
|
||||
component: CameraButton(
|
||||
content: AnyComponentWithIdentity(
|
||||
@ -1856,7 +1864,35 @@ private final class CameraScreenComponent: CombinedComponent {
|
||||
}
|
||||
|
||||
if component.cameraState.mode == .live {
|
||||
|
||||
if component.cameraState.isStreaming == .camera {
|
||||
let flipButton = flipButton.update(
|
||||
component: CameraButton(
|
||||
content: AnyComponentWithIdentity(
|
||||
id: "flip",
|
||||
component: AnyComponent(
|
||||
FlipButtonContentComponent(
|
||||
action: animateFlipAction,
|
||||
maskFrame: .zero,
|
||||
tintColor: controlsTintColor
|
||||
)
|
||||
)
|
||||
),
|
||||
minSize: CGSize(width: 44.0, height: 44.0),
|
||||
action: { [weak state] in
|
||||
if let state {
|
||||
state.togglePosition(animateFlipAction)
|
||||
}
|
||||
}
|
||||
),
|
||||
availableSize: availableSize,
|
||||
transition: context.transition
|
||||
)
|
||||
context.add(flipButton
|
||||
.position(CGPoint(x: nextButtonX, y: max(environment.statusBarHeight + 5.0, environment.safeInsets.top + topControlVerticalInset) + flipButton.size.height / 2.0 - 4.0))
|
||||
.appear(.default(scale: true))
|
||||
.disappear(.default(scale: true))
|
||||
)
|
||||
}
|
||||
} else {
|
||||
let collageButton = collageButton.update(
|
||||
component: CameraButton(
|
||||
@ -2026,7 +2062,7 @@ private final class CameraScreenComponent: CombinedComponent {
|
||||
}
|
||||
}
|
||||
|
||||
if !isSticker, case .none = component.cameraState.recording, !component.cameraState.isStreaming && !state.isTransitioning && hasAllRequiredAccess && component.cameraState.collageProgress < 1.0 - .ulpOfOne {
|
||||
if !isSticker, case .none = component.cameraState.recording, component.cameraState.isStreaming == .none && !state.isTransitioning && hasAllRequiredAccess && component.cameraState.collageProgress < 1.0 - .ulpOfOne {
|
||||
let availableModeControlSize: CGSize
|
||||
if isTablet {
|
||||
availableModeControlSize = CGSize(width: panelWidth, height: 120.0)
|
||||
@ -2474,7 +2510,7 @@ public class CameraScreenImpl: ViewController, CameraScreen {
|
||||
isCollageEnabled: false,
|
||||
collageGrid: collageGrids[6],
|
||||
collageProgress: 0.0,
|
||||
isStreaming: false,
|
||||
isStreaming: .none,
|
||||
isWaitingForStream: false
|
||||
)
|
||||
|
||||
@ -2900,7 +2936,7 @@ public class CameraScreenImpl: ViewController, CameraScreen {
|
||||
case .began:
|
||||
break
|
||||
case .changed:
|
||||
if case .none = self.cameraState.recording, !self.cameraState.isStreaming && !self.cameraState.isWaitingForStream {
|
||||
if case .none = self.cameraState.recording, self.cameraState.isStreaming == .none && !self.cameraState.isWaitingForStream {
|
||||
if case .compact = layout.metrics.widthClass {
|
||||
switch controller.mode {
|
||||
case .story:
|
||||
|
||||
@ -96,7 +96,6 @@ public func stringForMessageTimestampStatus(accountPeerId: PeerId, message: Mess
|
||||
}
|
||||
|
||||
if let repeatPeriod = message.scheduleRepeatPeriod {
|
||||
//TODO:localize
|
||||
let repeatString: String
|
||||
switch repeatPeriod {
|
||||
case 60:
|
||||
@ -104,27 +103,27 @@ public func stringForMessageTimestampStatus(accountPeerId: PeerId, message: Mess
|
||||
case 300:
|
||||
repeatString = "5 min"
|
||||
case 86400:
|
||||
repeatString = "daily"
|
||||
repeatString = strings.Message_RepeatPeriod_Daily
|
||||
case 7 * 86400:
|
||||
repeatString = "weekly"
|
||||
repeatString = strings.Message_RepeatPeriod_Weekly
|
||||
case 14 * 86400:
|
||||
repeatString = "biweekly"
|
||||
repeatString = strings.Message_RepeatPeriod_Biweekly
|
||||
case 30 * 86400:
|
||||
repeatString = "monthly"
|
||||
repeatString = strings.Message_RepeatPeriod_Monthly
|
||||
case 91 * 86400:
|
||||
repeatString = "every 3 months"
|
||||
repeatString = strings.Message_RepeatPeriod_3Months
|
||||
case 182 * 86400:
|
||||
repeatString = "every 6 months"
|
||||
repeatString = strings.Message_RepeatPeriod_6Months
|
||||
case 365 * 86400:
|
||||
repeatString = "yearly"
|
||||
repeatString = strings.Message_RepeatPeriod_Yearly
|
||||
default:
|
||||
repeatString = ""
|
||||
repeatString = "\(repeatPeriod)s"
|
||||
}
|
||||
dateText = "\(repeatString) at \(dateText)"
|
||||
dateText = strings.Message_RepeatAt(repeatString, dateText).string
|
||||
}
|
||||
|
||||
if message.id.namespace == Namespaces.Message.ScheduledCloud, let _ = message.pendingProcessingAttribute {
|
||||
return "appx. \(dateText)"
|
||||
return strings.Message_Approximate(dateText).string
|
||||
}
|
||||
|
||||
if displayFullDate {
|
||||
|
||||
@ -159,6 +159,8 @@ private final class ChatScheduleTimeSheetContentComponent: Component {
|
||||
self.component = component
|
||||
self.state = state
|
||||
|
||||
let strings = environment.strings
|
||||
|
||||
let sideInset: CGFloat = 39.0
|
||||
|
||||
var contentHeight: CGFloat = 0.0
|
||||
@ -201,9 +203,9 @@ private final class ChatScheduleTimeSheetContentComponent: Component {
|
||||
let title: String
|
||||
switch component.mode {
|
||||
case .scheduledMessages:
|
||||
title = environment.strings.Conversation_ScheduleMessage_Title
|
||||
title = strings.Conversation_ScheduleMessage_Title
|
||||
case .reminders:
|
||||
title = environment.strings.Conversation_SetReminder_Title
|
||||
title = strings.Conversation_SetReminder_Title
|
||||
}
|
||||
let titleSize = self.title.update(
|
||||
transition: transition,
|
||||
@ -232,7 +234,7 @@ private final class ChatScheduleTimeSheetContentComponent: Component {
|
||||
} else {
|
||||
datePicker = DatePickerNode(
|
||||
theme: DatePickerTheme(theme: environment.theme),
|
||||
strings: environment.strings,
|
||||
strings: strings,
|
||||
dateTimeFormat: environment.dateTimeFormat,
|
||||
hasValueRow: false
|
||||
)
|
||||
@ -295,7 +297,7 @@ private final class ChatScheduleTimeSheetContentComponent: Component {
|
||||
let timeTitleSize = self.timeTitle.update(
|
||||
transition: transition,
|
||||
component: AnyComponent(
|
||||
Text(text: "Time", font: Font.regular(17.0), color: environment.theme.actionSheet.primaryTextColor)
|
||||
Text(text: strings.ScheduleMessage_Time, font: Font.regular(17.0), color: environment.theme.actionSheet.primaryTextColor)
|
||||
),
|
||||
environment: {},
|
||||
containerSize: availableSize
|
||||
@ -364,7 +366,7 @@ private final class ChatScheduleTimeSheetContentComponent: Component {
|
||||
let repeatTitleSize = self.repeatTitle.update(
|
||||
transition: transition,
|
||||
component: AnyComponent(
|
||||
Text(text: "Repeat", font: Font.regular(17.0), color: environment.theme.actionSheet.primaryTextColor)
|
||||
Text(text: strings.ScheduleMessage_Repeat, font: Font.regular(17.0), color: environment.theme.actionSheet.primaryTextColor)
|
||||
),
|
||||
environment: {},
|
||||
containerSize: availableSize
|
||||
@ -380,29 +382,25 @@ private final class ChatScheduleTimeSheetContentComponent: Component {
|
||||
let repeatString: String
|
||||
if let repeatPeriod = self.repeatPeriod {
|
||||
switch repeatPeriod {
|
||||
case 60:
|
||||
repeatString = "Every Minute"
|
||||
case 300:
|
||||
repeatString = "Every 5 Minutes"
|
||||
case 86400:
|
||||
repeatString = "Daily"
|
||||
repeatString = strings.ScheduleMessage_RepeatPeriod_Daily
|
||||
case 7 * 86400:
|
||||
repeatString = "Weekly"
|
||||
repeatString = strings.ScheduleMessage_RepeatPeriod_Weekly
|
||||
case 14 * 86400:
|
||||
repeatString = "Biweekly"
|
||||
repeatString = strings.ScheduleMessage_RepeatPeriod_Biweekly
|
||||
case 30 * 86400:
|
||||
repeatString = "Monthly"
|
||||
repeatString = strings.ScheduleMessage_RepeatPeriod_Monthly
|
||||
case 91 * 86400:
|
||||
repeatString = "Every 3 Months"
|
||||
repeatString = strings.ScheduleMessage_RepeatPeriod_3Months
|
||||
case 182 * 86400:
|
||||
repeatString = "Every 6 Months"
|
||||
repeatString = strings.ScheduleMessage_RepeatPeriod_6Months
|
||||
case 365 * 86400:
|
||||
repeatString = "Yearly"
|
||||
repeatString = strings.ScheduleMessage_RepeatPeriod_Yearly
|
||||
default:
|
||||
repeatString = "\(repeatPeriod)"
|
||||
repeatString = "\(repeatPeriod)s"
|
||||
}
|
||||
} else {
|
||||
repeatString = "Never"
|
||||
repeatString = strings.ScheduleMessage_RepeatPeriod_Never
|
||||
}
|
||||
|
||||
let repeatValueSize = self.repeatValue.update(
|
||||
@ -448,19 +446,19 @@ private final class ChatScheduleTimeSheetContentComponent: Component {
|
||||
switch component.mode {
|
||||
case .scheduledMessages:
|
||||
if calendar.isDateInToday(date) {
|
||||
buttonTitle = environment.strings.Conversation_ScheduleMessage_SendToday(time).string
|
||||
buttonTitle = strings.Conversation_ScheduleMessage_SendToday(time).string
|
||||
} else if calendar.isDateInTomorrow(date) {
|
||||
buttonTitle = environment.strings.Conversation_ScheduleMessage_SendTomorrow(time).string
|
||||
buttonTitle = strings.Conversation_ScheduleMessage_SendTomorrow(time).string
|
||||
} else {
|
||||
buttonTitle = environment.strings.Conversation_ScheduleMessage_SendOn(self.dateFormatter.string(from: date), time).string
|
||||
buttonTitle = strings.Conversation_ScheduleMessage_SendOn(self.dateFormatter.string(from: date), time).string
|
||||
}
|
||||
case .reminders:
|
||||
if calendar.isDateInToday(date) {
|
||||
buttonTitle = environment.strings.Conversation_SetReminder_RemindToday(time).string
|
||||
buttonTitle = strings.Conversation_SetReminder_RemindToday(time).string
|
||||
} else if calendar.isDateInTomorrow(date) {
|
||||
buttonTitle = environment.strings.Conversation_SetReminder_RemindTomorrow(time).string
|
||||
buttonTitle = strings.Conversation_SetReminder_RemindTomorrow(time).string
|
||||
} else {
|
||||
buttonTitle = environment.strings.Conversation_SetReminder_RemindOn(self.dateFormatter.string(from: date), time).string
|
||||
buttonTitle = strings.Conversation_SetReminder_RemindOn(self.dateFormatter.string(from: date), time).string
|
||||
}
|
||||
}
|
||||
|
||||
@ -517,7 +515,7 @@ private final class ChatScheduleTimeSheetContentComponent: Component {
|
||||
pressedColor: environment.theme.list.itemCheckColors.fillColor.withMultipliedAlpha(0.8),
|
||||
),
|
||||
content: AnyComponentWithIdentity(id: AnyHashable(0 as Int), component: AnyComponent(
|
||||
Text(text: environment.strings.Conversation_ScheduleMessage_SendWhenOnline, font: Font.semibold(17.0), color: environment.theme.list.itemCheckColors.fillColor)
|
||||
Text(text: strings.Conversation_ScheduleMessage_SendWhenOnline, font: Font.semibold(17.0), color: environment.theme.list.itemCheckColors.fillColor)
|
||||
)),
|
||||
isEnabled: true,
|
||||
displaysProgress: false,
|
||||
@ -608,6 +606,7 @@ private final class ChatScheduleTimeSheetContentComponent: Component {
|
||||
sourceFrame: repeatValueFrame,
|
||||
component: AnyComponent(RepeatMenuComponent(
|
||||
theme: environment.theme,
|
||||
strings: strings,
|
||||
value: self.repeatPeriod,
|
||||
valueUpdated: { [weak self] value in
|
||||
guard let self, let component = self.component, let environment = self.environment else {
|
||||
@ -620,9 +619,9 @@ private final class ChatScheduleTimeSheetContentComponent: Component {
|
||||
let toastController = UndoOverlayController(
|
||||
presentationData: component.context.sharedContext.currentPresentationData.with { $0 },
|
||||
content: .premiumPaywall(
|
||||
title: "Premium Required",
|
||||
text: "Subscribe to **Telegram Premium** to schedule repeating messages.",
|
||||
customUndoText: "Add",
|
||||
title: strings.ScheduleMessage_PremiumRequired_Title,
|
||||
text: strings.ScheduleMessage_PremiumRequired_Text,
|
||||
customUndoText: strings.ScheduleMessage_PremiumRequired_Add,
|
||||
timeout: nil,
|
||||
linkAction: nil
|
||||
),
|
||||
@ -1169,15 +1168,18 @@ private final class MenuComponent: Component {
|
||||
|
||||
private final class RepeatMenuComponent: Component {
|
||||
let theme: PresentationTheme
|
||||
let strings: PresentationStrings
|
||||
let value: Int32?
|
||||
let valueUpdated: (Int32?) -> Void
|
||||
|
||||
init(
|
||||
theme: PresentationTheme,
|
||||
strings: PresentationStrings,
|
||||
value: Int32?,
|
||||
valueUpdated: @escaping (Int32?) -> Void
|
||||
) {
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
self.value = value
|
||||
self.valueUpdated = valueUpdated
|
||||
}
|
||||
@ -1186,6 +1188,9 @@ private final class RepeatMenuComponent: Component {
|
||||
if lhs.theme !== rhs.theme {
|
||||
return false
|
||||
}
|
||||
if lhs.strings !== rhs.strings {
|
||||
return false
|
||||
}
|
||||
if lhs.value != rhs.value {
|
||||
return false
|
||||
}
|
||||
@ -1240,7 +1245,7 @@ private final class RepeatMenuComponent: Component {
|
||||
component: AnyComponent(
|
||||
PlainButtonComponent(
|
||||
content: AnyComponent(
|
||||
Text(text: "Never", font: Font.regular(17.0), color: textColor)
|
||||
Text(text: component.strings.ScheduleMessage_RepeatPeriod_Never, font: Font.regular(17.0), color: textColor)
|
||||
),
|
||||
action: { [weak self] in
|
||||
guard let self else {
|
||||
@ -1278,26 +1283,22 @@ private final class RepeatMenuComponent: Component {
|
||||
|
||||
let repeatString: String
|
||||
switch value {
|
||||
case 60:
|
||||
repeatString = "Every Minute"
|
||||
case 300:
|
||||
repeatString = "Every 5 Minutes"
|
||||
case 86400:
|
||||
repeatString = "Daily"
|
||||
repeatString = component.strings.ScheduleMessage_RepeatPeriod_Daily
|
||||
case 7 * 86400:
|
||||
repeatString = "Weekly"
|
||||
repeatString = component.strings.ScheduleMessage_RepeatPeriod_Weekly
|
||||
case 14 * 86400:
|
||||
repeatString = "Biweekly"
|
||||
repeatString = component.strings.ScheduleMessage_RepeatPeriod_Biweekly
|
||||
case 30 * 86400:
|
||||
repeatString = "Monthly"
|
||||
repeatString = component.strings.ScheduleMessage_RepeatPeriod_Monthly
|
||||
case 91 * 86400:
|
||||
repeatString = "Every 3 Months"
|
||||
repeatString = component.strings.ScheduleMessage_RepeatPeriod_3Months
|
||||
case 182 * 86400:
|
||||
repeatString = "Every 6 Months"
|
||||
repeatString = component.strings.ScheduleMessage_RepeatPeriod_6Months
|
||||
case 365 * 86400:
|
||||
repeatString = "Yearly"
|
||||
repeatString = component.strings.ScheduleMessage_RepeatPeriod_Yearly
|
||||
default:
|
||||
repeatString = "\(value)"
|
||||
repeatString = "\(value)s"
|
||||
}
|
||||
|
||||
let itemSize = itemView.update(
|
||||
|
||||
@ -253,6 +253,7 @@ final class NewContactScreenComponent: Component {
|
||||
self.environment = environment
|
||||
|
||||
let theme = environment.theme
|
||||
let strings = environment.strings
|
||||
|
||||
var initialCountryCode: Int32?
|
||||
var updateFocusTag: Any?
|
||||
@ -326,7 +327,7 @@ final class NewContactScreenComponent: Component {
|
||||
theme: theme,
|
||||
initialText: component.initialData.firstName ?? "",
|
||||
resetText: nil,
|
||||
placeholder: "First Name",
|
||||
placeholder: strings.UserInfo_FirstNamePlaceholder,
|
||||
autocapitalizationType: .sentences,
|
||||
autocorrectionType: .default,
|
||||
returnKeyType: .next,
|
||||
@ -347,7 +348,7 @@ final class NewContactScreenComponent: Component {
|
||||
theme: theme,
|
||||
initialText: component.initialData.lastName ?? "",
|
||||
resetText: nil,
|
||||
placeholder: "Last Name",
|
||||
placeholder: strings.UserInfo_LastNamePlaceholder,
|
||||
autocapitalizationType: .sentences,
|
||||
autocorrectionType: .default,
|
||||
returnKeyType: .next,
|
||||
@ -437,7 +438,7 @@ final class NewContactScreenComponent: Component {
|
||||
style: .glass,
|
||||
title: AnyComponent(VStack([
|
||||
AnyComponentWithIdentity(id: "title", component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: "mobile", font: Font.regular(14.0), textColor: theme.list.itemPrimaryTextColor))))),
|
||||
AnyComponentWithIdentity(id: "value", component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: environment.strings.ContactInfo_PhoneNumberHidden, font: Font.regular(17.0), textColor: theme.list.itemAccentColor)))))
|
||||
AnyComponentWithIdentity(id: "value", component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: strings.ContactInfo_PhoneNumberHidden, font: Font.regular(17.0), textColor: theme.list.itemAccentColor)))))
|
||||
], alignment: .left, spacing: 4.0)),
|
||||
contentInsets: UIEdgeInsets(top: 15.0, left: 0.0, bottom: 15.0, right: 0.0),
|
||||
accessory: nil,
|
||||
@ -445,7 +446,7 @@ final class NewContactScreenComponent: Component {
|
||||
)))
|
||||
)
|
||||
phoneFooterComponent = AnyComponent(MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(string: environment.strings.AddContact_ContactWillBeSharedAfterMutual(peer.compactDisplayTitle).string, font: Font.regular(13.0), textColor: environment.theme.list.freeTextColor)),
|
||||
text: .plain(NSAttributedString(string: strings.AddContact_ContactWillBeSharedAfterMutual(peer.compactDisplayTitle).string, font: Font.regular(13.0), textColor: environment.theme.list.freeTextColor)),
|
||||
maximumNumberOfLines: 0
|
||||
))
|
||||
}
|
||||
@ -454,14 +455,14 @@ final class NewContactScreenComponent: Component {
|
||||
ListItemComponentAdaptor(
|
||||
itemGenerator: PhoneInputItem(
|
||||
theme: theme,
|
||||
strings: environment.strings,
|
||||
strings: strings,
|
||||
value: (initialCountryCode, nil, ""),
|
||||
accessory: phoneAccesory,
|
||||
selectCountryCode: { [weak self] in
|
||||
guard let self, let environment = self.environment, let controller = environment.controller() else {
|
||||
return
|
||||
}
|
||||
let countryController = AuthorizationSequenceCountrySelectionController(strings: environment.strings, theme: environment.theme, glass: true)
|
||||
let countryController = AuthorizationSequenceCountrySelectionController(strings: strings, theme: environment.theme, glass: true)
|
||||
countryController.completeWithCountryCode = { [weak self] code, name in
|
||||
guard let self else {
|
||||
return
|
||||
@ -550,12 +551,12 @@ final class NewContactScreenComponent: Component {
|
||||
phoneFooterRawText = ""
|
||||
case let .peer(_, isContact):
|
||||
if isContact {
|
||||
phoneFooterRawText = "This phone number is already in your contacts. [View >]()"
|
||||
phoneFooterRawText = strings.AddContact_PhoneNumber_IsContact
|
||||
} else {
|
||||
phoneFooterRawText = "This phone number is on Telegram."
|
||||
phoneFooterRawText = strings.AddContact_PhoneNumber_Registered
|
||||
}
|
||||
case .notFound:
|
||||
phoneFooterRawText = "This phone number is not on Telegram. [Invite >]()"
|
||||
phoneFooterRawText = strings.AddContact_PhoneNumber_NotRegistered
|
||||
}
|
||||
let phoneFooterText = NSMutableAttributedString(attributedString: parseMarkdownIntoAttributedString(phoneFooterRawText, attributes: footerAttributes))
|
||||
if let range = phoneFooterText.string.range(of: ">"), let chevronImage = self.cachedChevronImage?.0 {
|
||||
@ -625,7 +626,7 @@ final class NewContactScreenComponent: Component {
|
||||
style: .glass,
|
||||
title: AnyComponent(MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(
|
||||
string: "Sync Contact to Phone",
|
||||
string: strings.AddContact_SyncToPhone,
|
||||
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
|
||||
textColor: theme.list.itemPrimaryTextColor
|
||||
)),
|
||||
@ -649,7 +650,7 @@ final class NewContactScreenComponent: Component {
|
||||
style: .glass,
|
||||
title: AnyComponent(MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(
|
||||
string: environment.strings.AddContact_SharedContactException,
|
||||
string: strings.AddContact_SharedContactException,
|
||||
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
|
||||
textColor: theme.list.itemPrimaryTextColor
|
||||
)),
|
||||
@ -666,7 +667,7 @@ final class NewContactScreenComponent: Component {
|
||||
)))
|
||||
)
|
||||
optionsFooterComponent = AnyComponent(MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(string: environment.strings.AddContact_SharedContactExceptionInfo(peer.compactDisplayTitle).string, font: Font.regular(13.0), textColor: environment.theme.list.freeTextColor)),
|
||||
text: .plain(NSAttributedString(string: strings.AddContact_SharedContactExceptionInfo(peer.compactDisplayTitle).string, font: Font.regular(13.0), textColor: environment.theme.list.freeTextColor)),
|
||||
maximumNumberOfLines: 0
|
||||
))
|
||||
}
|
||||
@ -714,8 +715,8 @@ final class NewContactScreenComponent: Component {
|
||||
context: component.context,
|
||||
style: .glass,
|
||||
theme: theme,
|
||||
strings: environment.strings,
|
||||
placeholder: NSAttributedString(string: "Add notes only visible to you", font: Font.regular(17.0), textColor: theme.list.itemPlaceholderTextColor),
|
||||
strings: strings,
|
||||
placeholder: NSAttributedString(string: strings.AddContact_NotePlaceholder, font: Font.regular(17.0), textColor: theme.list.itemPlaceholderTextColor),
|
||||
characterLimit: characterLimit,
|
||||
emptyLineHandling: .allowed,
|
||||
returnKeyAction: nil,
|
||||
@ -771,7 +772,7 @@ final class NewContactScreenComponent: Component {
|
||||
title: AnyComponent(VStack([
|
||||
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(
|
||||
string: "Add via QR Code",
|
||||
string: strings.AddContact_AddQR,
|
||||
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
|
||||
textColor: theme.list.itemAccentColor
|
||||
)),
|
||||
@ -867,7 +868,7 @@ final class NewContactScreenComponent: Component {
|
||||
MultilineTextComponent(
|
||||
text: .plain(
|
||||
NSAttributedString(
|
||||
string: "New Contact",
|
||||
string: strings.AddContact_Title,
|
||||
font: Font.semibold(17.0),
|
||||
textColor: environment.theme.rootController.navigationBar.primaryTextColor
|
||||
)
|
||||
|
||||
@ -12,7 +12,7 @@ public final class GlassBarButtonComponent: Component {
|
||||
case tintedGlass
|
||||
}
|
||||
|
||||
public let size: CGSize
|
||||
public let size: CGSize?
|
||||
public let backgroundColor: UIColor
|
||||
public let isDark: Bool
|
||||
public let state: DisplayState?
|
||||
@ -21,7 +21,7 @@ public final class GlassBarButtonComponent: Component {
|
||||
public let action: ((UIView) -> Void)?
|
||||
|
||||
public init(
|
||||
size: CGSize,
|
||||
size: CGSize?,
|
||||
backgroundColor: UIColor,
|
||||
isDark: Bool,
|
||||
state: DisplayState? = nil,
|
||||
@ -149,9 +149,17 @@ public final class GlassBarButtonComponent: Component {
|
||||
transition: componentTransition,
|
||||
component: component.component.component,
|
||||
environment: {},
|
||||
containerSize: component.size
|
||||
containerSize: component.size ?? availableSize
|
||||
)
|
||||
let componentFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((component.size.width - componentSize.width) / 2.0), y: floorToScreenPixels((component.size.height - componentSize.height) / 2.0)), size: componentSize)
|
||||
|
||||
let containerSize: CGSize
|
||||
if let size = component.size {
|
||||
containerSize = size
|
||||
} else {
|
||||
containerSize = CGSize(width: componentSize.width + 25.0, height: max(availableSize.height, componentSize.height + 19.0))
|
||||
}
|
||||
|
||||
let componentFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((containerSize.width - componentSize.width) / 2.0), y: floorToScreenPixels((containerSize.height - componentSize.height) / 2.0)), size: componentSize)
|
||||
if let view = componentView.view {
|
||||
if view.superview == nil {
|
||||
self.containerView.addSubview(view)
|
||||
@ -175,11 +183,11 @@ public final class GlassBarButtonComponent: Component {
|
||||
genericAlpha = 0.0
|
||||
}
|
||||
|
||||
let cornerRadius = component.size.height * 0.5
|
||||
self.genericBackgroundView.update(size: component.size, cornerRadius: cornerRadius, isDark: component.isDark, tintColor: .init(kind: .custom, color: component.backgroundColor), transition: transition)
|
||||
self.glassBackgroundView.update(size: component.size, cornerRadius: cornerRadius, isDark: component.isDark, tintColor: .init(kind: effectiveState == .tintedGlass ? .custom : .panel , color: component.backgroundColor.withMultipliedAlpha(effectiveState == .tintedGlass ? 1.0 : 0.7)), transition: transition)
|
||||
let cornerRadius = containerSize.height * 0.5
|
||||
self.genericBackgroundView.update(size: containerSize, cornerRadius: cornerRadius, isDark: component.isDark, tintColor: .init(kind: .custom, color: component.backgroundColor), transition: transition)
|
||||
self.glassBackgroundView.update(size: containerSize, cornerRadius: cornerRadius, isDark: component.isDark, tintColor: .init(kind: effectiveState == .tintedGlass ? .custom : .panel , color: component.backgroundColor.withMultipliedAlpha(effectiveState == .tintedGlass ? 1.0 : 0.7)), transition: transition)
|
||||
|
||||
let bounds = CGRect(origin: .zero, size: component.size)
|
||||
let bounds = CGRect(origin: .zero, size: containerSize)
|
||||
transition.setFrame(view: self.containerView, frame: bounds)
|
||||
|
||||
transition.setAlpha(view: self.genericContainerView, alpha: genericAlpha)
|
||||
@ -191,7 +199,7 @@ public final class GlassBarButtonComponent: Component {
|
||||
transition.setFrame(view: self.genericBackgroundView, frame: bounds)
|
||||
transition.setFrame(view: self.glassBackgroundView, frame: bounds)
|
||||
|
||||
return component.size
|
||||
return containerSize
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -239,6 +239,7 @@ final class LiveStreamSettingsScreenComponent: Component {
|
||||
|
||||
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
|
||||
let theme = environment.theme.withModalBlocksBackground()
|
||||
let strings = environment.strings
|
||||
|
||||
guard let screenState = component.stateContext.stateValue else {
|
||||
return CGSize()
|
||||
@ -318,7 +319,7 @@ final class LiveStreamSettingsScreenComponent: Component {
|
||||
|
||||
let streamAsSectionHeader = AnyComponent(MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(
|
||||
string: "START LIVE AS",
|
||||
string: strings.LiveStreamSettings_StartLiveAs,
|
||||
font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize),
|
||||
textColor: theme.list.freeTextColor
|
||||
)),
|
||||
@ -587,7 +588,7 @@ final class LiveStreamSettingsScreenComponent: Component {
|
||||
|
||||
let privacySectionHeader = AnyComponent(MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(
|
||||
string: "WHO CAN VIEW THIS LIVE",
|
||||
string: strings.LiveStreamSettings_WhoCanView,
|
||||
font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize),
|
||||
textColor: theme.list.freeTextColor
|
||||
)),
|
||||
@ -596,7 +597,7 @@ final class LiveStreamSettingsScreenComponent: Component {
|
||||
|
||||
let privacySectionFooter = AnyComponent(MultilineTextComponent(
|
||||
text: .markdown(
|
||||
text: "[Select people]() who won't see your live.",
|
||||
text: strings.LiveStreamSettings_WhoCanViewInfo,
|
||||
attributes: MarkdownAttributes(
|
||||
body: MarkdownAttributeSet(font: footerTextFont, textColor: footerTextColor),
|
||||
bold: MarkdownAttributeSet(font: footerBoldTextFont, textColor: footerTextColor),
|
||||
@ -666,13 +667,12 @@ final class LiveStreamSettingsScreenComponent: Component {
|
||||
})
|
||||
}
|
||||
|
||||
//TODO:localize
|
||||
if !screenState.isEdit || (screenState.call != nil && screenState.isEdit && screenState.callIsStream) {
|
||||
let externalStreamSectionItems = [AnyComponentWithIdentity(id: 0, component: AnyComponent(
|
||||
ListActionItemComponent(
|
||||
theme: theme,
|
||||
style: .glass,
|
||||
title: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: "Connect Stream", font: Font.regular(presentationData.listsFontSize.baseDisplaySize), textColor: theme.list.itemPrimaryTextColor)))),
|
||||
title: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: strings.LiveStreamSettings_ConnectStream, font: Font.regular(presentationData.listsFontSize.baseDisplaySize), textColor: theme.list.itemPrimaryTextColor)))),
|
||||
action: { [weak self] _ in
|
||||
guard let self else {
|
||||
return
|
||||
@ -682,7 +682,7 @@ final class LiveStreamSettingsScreenComponent: Component {
|
||||
)
|
||||
))]
|
||||
let externalStreamFooterComponent = AnyComponent(MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(string: "Stream with a different app.", font: footerTextFont, textColor: footerTextColor)),
|
||||
text: .plain(NSAttributedString(string: strings.LiveStreamSettings_ConnectStreamInfo, font: footerTextFont, textColor: footerTextColor)),
|
||||
maximumNumberOfLines: 0
|
||||
))
|
||||
|
||||
@ -710,15 +710,13 @@ final class LiveStreamSettingsScreenComponent: Component {
|
||||
contentHeight += sectionSpacing
|
||||
}
|
||||
|
||||
|
||||
//TODO:localize
|
||||
var settingsSectionItems: [AnyComponentWithIdentity<Empty>] = []
|
||||
settingsSectionItems.append(AnyComponentWithIdentity(id: "comments", component: AnyComponent(ListActionItemComponent(
|
||||
theme: theme,
|
||||
style: .glass,
|
||||
title: AnyComponent(MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(
|
||||
string: "Allow Comments",
|
||||
string: strings.LiveStreamSettings_AllowComments,
|
||||
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
|
||||
textColor: theme.list.itemPrimaryTextColor
|
||||
)),
|
||||
@ -735,13 +733,12 @@ final class LiveStreamSettingsScreenComponent: Component {
|
||||
))))
|
||||
|
||||
if !(screenState.call != nil && screenState.isEdit) {
|
||||
//TODO:localize
|
||||
settingsSectionItems.append(AnyComponentWithIdentity(id: "screenshots", component: AnyComponent(ListActionItemComponent(
|
||||
theme: theme,
|
||||
style: .glass,
|
||||
title: AnyComponent(MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(
|
||||
string: "Allow Screenshots",
|
||||
string: strings.LiveStreamSettings_AllowScreenshots,
|
||||
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
|
||||
textColor: theme.list.itemPrimaryTextColor
|
||||
)),
|
||||
@ -789,7 +786,7 @@ final class LiveStreamSettingsScreenComponent: Component {
|
||||
minValue: 0,
|
||||
lowerBoundTitle: "0",
|
||||
upperBoundTitle: "\(presentationStringsFormattedNumber(Int32(clamping: screenState.maxPaidMessageStars), environment.dateTimeFormat.groupingSeparator))",
|
||||
title: screenState.paidMessageStars == 0 ? "Free" : "\(screenState.paidMessageStars) Stars",
|
||||
title: screenState.paidMessageStars == 0 ? strings.LiveStreamSettings_PricePerComment_Free : strings.LiveStreamSettings_PricePerComment_Stars(Int32(clamping: screenState.paidMessageStars)),
|
||||
valueUpdated: { [weak self] value in
|
||||
guard let self, let component = self.component else {
|
||||
return
|
||||
@ -805,7 +802,7 @@ final class LiveStreamSettingsScreenComponent: Component {
|
||||
if screenState.allowComments {
|
||||
let paidMessageSectionHeader = AnyComponent(MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(
|
||||
string: "PRICE PER COMMENT",
|
||||
string: strings.LiveStreamSettings_PricePerComment,
|
||||
font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize),
|
||||
textColor: theme.list.freeTextColor
|
||||
)),
|
||||
@ -813,7 +810,7 @@ final class LiveStreamSettingsScreenComponent: Component {
|
||||
))
|
||||
|
||||
let paidMessageSectionFooterComponent = AnyComponent(MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(string: "The price a viewer must pay to send a comment.", font: footerTextFont, textColor: footerTextColor)),
|
||||
text: .plain(NSAttributedString(string: strings.LiveStreamSettings_PricePerCommentInfo, font: footerTextFont, textColor: footerTextColor)),
|
||||
maximumNumberOfLines: 0
|
||||
))
|
||||
|
||||
@ -856,7 +853,7 @@ final class LiveStreamSettingsScreenComponent: Component {
|
||||
transition.setFrame(view: self.bottomEdgeEffectView, frame: bottomEdgeEffectFrame)
|
||||
self.bottomEdgeEffectView.update(content: theme.list.blocksBackgroundColor, blur: true, alpha: 1.0, rect: bottomEdgeEffectFrame, edge: .bottom, edgeSize: edgeEffectFrame.height, transition: transition)
|
||||
|
||||
let title: String = screenState.isEdit ? "Live Stream" : "Live Settings"
|
||||
let title: String = screenState.isEdit ? strings.LiveStreamSettings_TitleEdit : strings.LiveStreamSettings_Title
|
||||
let titleSize = self.title.update(
|
||||
transition: transition,
|
||||
component: AnyComponent(
|
||||
@ -961,7 +958,7 @@ final class LiveStreamSettingsScreenComponent: Component {
|
||||
content: AnyComponentWithIdentity(
|
||||
id: "label",
|
||||
component: AnyComponent(ButtonTextContentComponent(
|
||||
text: "Save Settings",
|
||||
text: strings.LiveStreamSettings_SaveSettings,
|
||||
badge: 0,
|
||||
textColor: theme.list.itemCheckColors.foregroundColor,
|
||||
badgeBackground: theme.list.itemCheckColors.foregroundColor,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user