This commit is contained in:
Isaac 2024-03-01 00:09:39 +04:00
parent c69ba2c089
commit 42b14666a2
28 changed files with 414 additions and 329 deletions

View File

@ -11390,3 +11390,190 @@ to respond to messages faster.";
"Story.Editor.DiscardText" = "If you go back now, you will lose any changes you made.";
"Premium.Business.Description" = "Turn your account to a business page with these additional features.";
"Attachment.Reply" = "Reply";
"ChatList.ItemMoreMessagesFormat_1" = "+1 MORE";
"ChatList.ItemMoreMessagesFormat_any" = "+%d MORE";
"ChatList.ItemMenuEdit" = "Edit";
"ChatList.ItemMenuDelete" = "Delete";
"ChatList.PeerTypeNonContact" = "non-contact";
"ChatListFilter.TagLabelNoTag" = "NO TAG";
"ChatListFilter.TagLabelPremiumExpired" = "PREMIUM EXPIRED";
"ChatListFilter.TagSectionTitle" = "FOLDER COLOR";
"ChatListFilter.TagSectionFooter" = "This color will be used for the folder's tag in the chat list";
"ChatListFilter.TagPremiumRequiredTooltipText" = "Subscribe to **Telegram Premium** to select folder color.";
"ChatListFilterList.ShowTags" = "Show Folder Tags";
"ChatListFilterList.ShowTagsFooter" = "Display folder names for each chat in the chat list.";
"PeerInfo.BusinessHours.DayOpen24h" = "open 24 hours";
"PeerInfo.BusinessHours.DayClosed" = "closed";
"PeerInfo.BusinessHours.StatusOpen" = "Open";
"PeerInfo.BusinessHours.StatusClosed" = "Closed";
"PeerInfo.BusinessHours.StatusOpensInMinutes_1" = "Opens in one minute";
"PeerInfo.BusinessHours.StatusOpensInMinutes_any" = "Opens in %d minutes";
"PeerInfo.BusinessHours.StatusOpensInHours_1" = "Opens in one hour";
"PeerInfo.BusinessHours.StatusOpensInHours_any" = "Opens in %d hours";
"PeerInfo.BusinessHours.StatusOpensOnDate" = "Opens %@";
"PeerInfo.BusinessHours.TimezoneSwitchMy" = "my time";
"PeerInfo.BusinessHours.TimezoneSwitchBusiness" = "local time";
"PeerInfo.BusinessHours.Label" = "business hours";
"PeerInfo.Location.Label" = "location";
"QuickReplies.EmptyState.Title" = "No Quick Replies";
"QuickReplies.EmptyState.Text" = "Set up shortcuts with rich text and media to respond to messages faster.";
"QuickReplies.EmptyState.AddButton" = "Add Quick Reply";
"Chat.CommandList.EditQuickReplies" = "Edit Quick Replies";
"Conversation.EditingQuickReplyPanelTitle" = "Edit Quick Reply";
"Chat.Placeholder.QuickReply" = "Add quick reply..";
"Chat.Placeholder.GreetingMessage" = "Add greeting message...";
"Chat.Placeholder.AwayMessage" = "Add away message...";
"Chat.QuickReplyMessageLimitReachedText_1" = "Limit of %d message reached";
"Chat.QuickReplyMessageLimitReachedText_any" = "Limit of %d messages reached";
"Chat.EmptyState.QuickReply.Title" = "New Quick Reply";
"Chat.EmptyState.QuickReply.Text1" = "· Enter a message below that will be sent in chats when you type \"**/%@\"**.";
"Chat.EmptyState.QuickReply.Text2" = "· You can access Quick Replies in any chat by typing \"/\" or using the Attachment menu.";
"EmptyState.GreetingMessage.Title" = "New Greeting Message";
"EmptyState.GreetingMessage.Text" = "Create greetings that will be automatically sent to new customers";
"EmptyState.AwayMessage.Title" = "New Away Message";
"EmptyState.AwayMessage.Text" = "Add messages that are automatically sent when you are off.";
"QuickReply.Title" = "Quick Replies";
"QuickReply.SelectedTitle_1" = "%d Selected";
"QuickReply.SelectedTitle_any" = "%d Selected";
"QuickReply.ShortcutPlaceholder" = "Shortcut";
"QuickReply.CreateShortcutTitle" = "New Quick Reply";
"QuickReply.CreateShortcutText" = "Add a shortcut for your quick reply.";
"QuickReply.EditShortcutTitle" = "Edit Shortcut";
"QuickReply.EditShortcutText" = "Add a new name for your shortcut.";
"QuickReply.ShortcutExistsInlineError" = "Shortcut with that name already exists";
"QuickReply.ChatRemoveGeneric.Title" = "Remove Shortcut";
"QuickReply.ChatRemoveGeneric.Text" = "You didn't create a quick reply message. Exiting will remove the shortcut.";
"QuickReply.ChatRemoveGreetingMessage.Title" = "Remove Greeting Message";
"QuickReply.ChatRemoveGreetingMessage.Text" = "You didn't create a greeting message. Exiting will remove it.";
"QuickReply.ChatRemoveAwayMessage.Title" = "Remove Away Message";
"QuickReply.ChatRemoveAwayMessage.Text" = "You didn't create an away message. Exiting will remove it.";
"QuickReply.ChatRemoveGeneric.DeleteAction" = "Delete";
"QuickReply.TitleGreetingMessage" = "Greeting Message";
"QuickReply.TitleAwayMessage" = "Away Message";
"QuickReply.InlineCreateAction" = "New Quick Reply";
"QuickReply.DeleteConfirmationSingle" = "Delete Quick Reply";
"QuickReply.DeleteConfirmationMultiple" = "Delete Quick Replies";
"QuickReply.DeleteAction_1" = "Delete 1 Quick Reply";
"QuickReply.DeleteAction_any" = "Delete %d Quick Replies";
"TimeZoneSelection.Title" = "Time Zone";
"BusinessMessageSetup.TitleGreetingMessage" = "Greeting Message";
"BusinessMessageSetup.TextGreetingMessage" = "Greet customers when they message you the first time or after a period of no activity.";
"BusinessMessageSetup.TitleAwayMessage" = "Away Message";
"BusinessMessageSetup.TextAwayMessage" = "Automatically reply with a message when you are away.";
"BusinessMessageSetup.ToggleGreetingMessage" = "Send Greeting Message";
"BusinessMessageSetup.ToggleAwayMessage" = "Send Away Message";
"BusinessMessageSetup.CreateGreetingMessage" = "Create a Greeting Message";
"BusinessMessageSetup.CreateAwayMessage" = "Create an Away Message";
"BusinessMessageSetup.GreetingMessageSectionHeader" = "GREETING MESSAGE";
"BusinessMessageSetup.AwayMessageSectionHeader" = "AWAY MESSAGE";
"BusinessMessageSetup.ScheduleSectionHeader" = "SCHEDULE";
"BusinessMessageSetup.ScheduleAlways" = "Always Send";
"BusinessMessageSetup.ScheduleOutsideBusinessHours" = "Outside of Business Hours";
"BusinessMessageSetup.ScheduleCustom" = "Custom Schedule";
"BusinessMessageSetup.ScheduleStartTime" = "Start Time";
"BusinessMessageSetup.ScheduleEndTime" = "End Time";
"BusinessMessageSetup.ScheduleTimePlaceholder" = "Set";
"BusinessMessageSetup.SendWhenOffline" = "Only if Offline";
"BusinessMessageSetup.SendWhenOfflineFooter" = "Don't send the away message if you've recently been online.";
"BusinessMessageSetup.ErrorNoRecipients.Text" = "No recipients selected. Reset?";
"BusinessMessageSetup.ErrorNoRecipients.ResetAction" = "Reset";
"BusinessMessageSetup.ErrorScheduleEndTimeBeforeStartTime.Text" = "Custom schedule end time must be larger than start time.";
"BusinessMessageSetup.ErrorScheduleTimeMissing.Text" = "Custom schedule time is missing.";
"BusinessMessageSetup.ErrorScheduleStartTimeMissing.Text" = "Custom schedule start time is missing.";
"BusinessMessageSetup.ErrorScheduleEndTimeMissing.Text" = "Custom schedule end time is missing.";
"BusinessMessageSetup.ErrorScheduleTime.ResetAction" = "Reset";
"BusinessMessageSetup.RecipientsSectionHeader" = "RECIPIENTS";
"BusinessMessageSetup.RecipientsOptionAllExcept" = "All 1-to-1 Chats Except...";
"BusinessMessageSetup.RecipientsOptionOnly" = "Only Selected Chats";
"BusinessMessageSetup.Recipients.AddExclude" = "Exclude Chats...";
"BusinessMessageSetup.Recipients.AddInclude" = "Include Chats...";
"BusinessMessageSetup.Recipients.CategoryExistingChats" = "Existing Chats";
"BusinessMessageSetup.Recipients.CategoryNewChats" = "New Chats";
"BusinessMessageSetup.Recipients.CategoryContacts" = "Contacts";
"BusinessMessageSetup.Recipients.CategoryNonContacts" = "Non-Contacts";
"BusinessMessageSetup.Recipients.IncludeSearchTitle" = "Include Chats";
"BusinessMessageSetup.Recipients.ExcludeSearchTitle" = "Exclude Chats";
"BusinessMessageSetup.Recipients.IncludedSectionHeader" = "INCLUDED CHATS";
"BusinessMessageSetup.Recipients.ExcludedSectionHeader" = "EXCLUDED CHATS";
"BusinessMessageSetup.Recipients.GreetingMessageFooter" = "Choose chats or entire chat categories for sending a greeting message.";
"BusinessMessageSetup.Recipients.AwayMessageFooter" = "Choose chats or entire chat categories for sending an away message.";
"BusinessMessageSetup.InactivitySectionHeader" = "PERIOD OF NO ACTIVITY";
"BusinessMessageSetup.InactivitySectionFooter" = "Choose how many days should pass after your last interaction with a recipient to send them the greeting in response to their message.";
"BusinessHoursSetup.Title" = "Business Hours";
"BusinessHoursSetup.Text" = "Turn this on to show your opening hours schedule to your customers.";
"BusinessHoursSetup.MainToggle" = "Show Business Hours";
"BusinessHoursSetup.DaySwitch" = "Open On This Day";
"BusinessHoursSetup.DayIntervalStart" = "Opening time";
"BusinessHoursSetup.DayIntervalEnd" = "Closing time";
"BusinessHoursSetup.DayIntervalRemove" = "Remove";
"BusinessHoursSetup.AddSectionFooter" = "Specify your working hours during the day.";
"BusinessHoursSetup.AddAction" = "Add a Set of Hours";
"BusinessHoursSetup.ErrorIntersectingHours.Text" = "Business hours are intersecting. Reset?";
"BusinessHoursSetup.ErrorIntersectingHours.ResetAction" = "Reset";
"BusinessHoursSetup.ErrorIntersectingDays.Text" = "Business hours are intersecting. Reset?";
"BusinessHoursSetup.ErrorIntersectingDays.ResetAction" = "Reset";
"BusinessHoursSetup.DayOpen24h" = "Open 24 Hours";
"BusinessHoursSetup.DayClosed" = "Closed";
"BusinessHoursSetup.DaysSectionTitle" = "BUSINESS HOURS";
"BusinessHoursSetup.TimeZone" = "Time Zone";
"BusinessLocationSetup.Title" = "Location";
"BusinessLocationSetup.Text" = "Display the location of your business on your account.";
"BusinessLocationSetup.AddressPlaceholder" = "Enter Address";
"BusinessLocationSetup.SetLocationOnMap" = "Set Location on Map";
"BusinessLocationSetup.DeleteLocation" = "Delete Location";
"BusinessLocationSetup.ErrorAddressEmpty.Text" = "Address can't be empty.";
"BusinessLocationSetup.ErrorAddressEmpty.ResetAction" = "Delete";
"ChatbotSetup.Title" = "Chatbots";
"ChatbotSetup.Text" = "Add a bot to your account to help you automatically process and respond to the messages you receive. [Learn More >]()";
"ChatbotSetup.TextLink" = "https://telegram.org";
"ChatbotSetup.BotSearchPlaceholder" = "Bot Username";
"ChatbotSetup.BotSectionFooter" = "Enter the username or URL of the Telegram bot that you want to automatically process your chats.";
"ChatbotSetup.RecipientsSectionHeader" = "CHATS ACCESSIBLE FOR THE BOT";
"ChatbotSetup.Recipients.ExcludedSectionFooter" = "Select chats or entire chat categories which the bot **WILL NOT** have access to.";
"ChatbotSetup.Recipients.IncludedSectionFooter" = "Select chats or entire chat categories which the bot **WILL** have access to.";
"ChatbotSetup.PermissionsSectionHeader" = "BOT PERMISSIONS";
"ChatbotSetup.PermissionsSectionFooter" = "The bot will be able to view all new incoming messages, but not the messages that had been sent before you added the bot.";
"ChatbotSetup.Permission.ReplyToMessages" = "Reply to Messages";
"ChatbotSetup.BotAddAction" = "ADD";
"ChatbotSetup.BotNotFoundStatus" = "Chatbot not found";

View File

@ -218,8 +218,7 @@ private final class AttachButtonComponent: CombinedComponent {
imageName = ""
imageFile = nil
case .quickReply:
//TODO:localize
name = "Reply"
name = strings.Attachment_Reply
imageName = "Chat/Attach Menu/Reply"
}
@ -1188,8 +1187,7 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate {
case .standalone:
accessibilityTitle = ""
case .quickReply:
//TODO:localize
accessibilityTitle = "Reply"
accessibilityTitle = self.presentationData.strings.Attachment_Reply
}
buttonView.isAccessibilityElement = true
buttonView.accessibilityLabel = accessibilityTitle

View File

@ -462,7 +462,6 @@ private enum ChatListFilterPresetEntry: ItemListNodeEntry {
arguments.expandSection(.exclude)
})
case let .tagColorHeader(name, color, isPremium):
//TODO:localize
var badge: String?
var badgeStyle: ItemListSectionHeaderItem.BadgeStyle?
var accessoryText: ItemListSectionHeaderAccessoryText?
@ -474,12 +473,12 @@ private enum ChatListFilterPresetEntry: ItemListNodeEntry {
foreground: color.main
)
} else {
accessoryText = ItemListSectionHeaderAccessoryText(value: "NO TAG", color: .generic)
accessoryText = ItemListSectionHeaderAccessoryText(value: presentationData.strings.ChatListFilter_TagLabelNoTag, color: .generic)
}
} else if color != nil {
accessoryText = ItemListSectionHeaderAccessoryText(value: "PREMIUM EXPIRED", color: .generic)
accessoryText = ItemListSectionHeaderAccessoryText(value: presentationData.strings.ChatListFilter_TagLabelPremiumExpired, color: .generic)
}
return ItemListSectionHeaderItem(presentationData: presentationData, text: "FOLDER COLOR", badge: badge, badgeStyle: badgeStyle, accessoryText: accessoryText, sectionId: self.section)
return ItemListSectionHeaderItem(presentationData: presentationData, text: presentationData.strings.ChatListFilter_TagSectionTitle, badge: badge, badgeStyle: badgeStyle, accessoryText: accessoryText, sectionId: self.section)
case let .tagColor(colors, color, isPremium):
return PeerNameColorItem(
theme: presentationData.theme,
@ -498,8 +497,7 @@ private enum ChatListFilterPresetEntry: ItemListNodeEntry {
sectionId: self.section
)
case .tagColorFooter:
//TODO:localize
return ItemListTextItem(presentationData: presentationData, text: .plain("This color will be used for the folder's tag in the chat list"), sectionId: self.section)
return ItemListTextItem(presentationData: presentationData, text: .plain(presentationData.strings.ChatListFilter_TagSectionFooter), sectionId: self.section)
case .inviteLinkHeader:
return ItemListSectionHeaderItem(presentationData: presentationData, text: presentationData.strings.ChatListFilter_SectionShare, badge: nil, sectionId: self.section)
case let .inviteLinkCreate(hasLinks):
@ -1580,14 +1578,15 @@ func chatListFilterPresetController(context: AccountContext, currentPreset initi
}
},
openTagColorPremium: {
//TODO:localize
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
presentControllerImpl?(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_reorder", scale: 0.05, colors: [:], title: nil, text: "Subscribe to **Telegram Premium** to select folder color.", customUndoText: presentationData.strings.ChatListFolderSettings_SubscribeToMoveAllAction, timeout: nil), elevatedLayout: false, animateInAsReplacement: false, action: { action in
if case .undo = action {
pushControllerImpl?(PremiumIntroScreen(context: context, source: .folders))
var replaceImpl: ((ViewController) -> Void)?
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .folderTags, action: {
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .folderTags, forceDark: false, dismissed: nil)
replaceImpl?(controller)
})
replaceImpl = { [weak controller] c in
controller?.replace(with: c)
}
return false
}), nil)
pushControllerImpl?(controller)
}
)

View File

@ -212,8 +212,7 @@ private enum ChatListFilterPresetListEntry: ItemListNodeEntry {
case let .listFooter(text):
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
case let .displayTags(value):
//TODO:localize
return ItemListSwitchItem(presentationData: presentationData, title: "Show Folder Tags", value: value == true, enableInteractiveChanges: value != nil, enabled: true, displayLocked: value == nil, sectionId: self.section, style: .blocks, updated: { updatedValue in
return ItemListSwitchItem(presentationData: presentationData, title: presentationData.strings.ChatListFilterList_ShowTags, value: value == true, enableInteractiveChanges: value != nil, enabled: true, displayLocked: value == nil, sectionId: self.section, style: .blocks, updated: { updatedValue in
if value != nil {
arguments.updateDisplayTags(updatedValue)
} else {
@ -223,8 +222,7 @@ private enum ChatListFilterPresetListEntry: ItemListNodeEntry {
arguments.updateDisplayTagsLocked()
}, tag: ChatListFilterPresetListEntryTag.displayTags)
case .displayTagsFooter:
//TODO:localize
return ItemListTextItem(presentationData: presentationData, text: .plain("Display folder names for each chat in the chat list."), sectionId: self.section)
return ItemListTextItem(presentationData: presentationData, text: .plain(presentationData.strings.ChatListFilterList_ShowTagsFooter), sectionId: self.section)
}
}
}

View File

@ -3066,8 +3066,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
var trailingTextBadgeLayoutAndApply: (TextNodeLayout, () -> TextNode)?
if case let .peer(peerData) = item.content, let customMessageListData = peerData.customMessageListData, customMessageListData.commandPrefix != nil, let messageCount = customMessageListData.messageCount, messageCount > 1 {
let trailingText: String
//TODO:localize
trailingText = "+\(messageCount - 1) MORE"
trailingText = item.presentationData.strings.ChatList_ItemMoreMessagesFormat(Int32(messageCount - 1))
let trailingAttributedText = NSAttributedString(string: trailingText, font: Font.regular(12.0), textColor: theme.messageTextColor)
let (layout, apply) = makeTrailingTextBadgeLayout(TextNodeLayoutArguments(attributedString: trailingAttributedText, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: rawContentWidth, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
trailingTextBadgeLayoutAndApply = (layout, apply)
@ -3210,10 +3209,9 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
} else if case let .peer(peerData) = item.content, let customMessageListData = peerData.customMessageListData {
peerLeftRevealOptions = []
if customMessageListData.commandPrefix != nil {
//TODO:localize
peerRevealOptions = [
ItemListRevealOption(key: RevealOptionKey.edit.rawValue, title: "Edit", icon: .none, color: item.presentationData.theme.list.itemDisclosureActions.neutral2.fillColor, textColor: item.presentationData.theme.list.itemDisclosureActions.neutral2.foregroundColor),
ItemListRevealOption(key: RevealOptionKey.delete.rawValue, title: "Delete", icon: .none, color: item.presentationData.theme.list.itemDisclosureActions.destructive.fillColor, textColor: item.presentationData.theme.list.itemDisclosureActions.destructive.foregroundColor)
ItemListRevealOption(key: RevealOptionKey.edit.rawValue, title: item.presentationData.strings.ChatList_ItemMenuEdit, icon: .none, color: item.presentationData.theme.list.itemDisclosureActions.neutral2.fillColor, textColor: item.presentationData.theme.list.itemDisclosureActions.neutral2.foregroundColor),
ItemListRevealOption(key: RevealOptionKey.delete.rawValue, title: item.presentationData.strings.ChatList_ItemMenuDelete, icon: .none, color: item.presentationData.theme.list.itemDisclosureActions.destructive.fillColor, textColor: item.presentationData.theme.list.itemDisclosureActions.destructive.foregroundColor)
]
} else {
peerRevealOptions = []

View File

@ -4130,16 +4130,14 @@ private func statusStringForPeerType(accountPeerId: EnginePeer.Id, strings: Pres
if isContact {
return (strings.ChatList_PeerTypeContact, false, false, nil)
} else {
//TODO:localize
return ("non-contact", false, false, nil)
return (strings.ChatList_PeerTypeNonContact, false, false, nil)
}
}
} else if case .secretChat = peer {
if isContact {
return (strings.ChatList_PeerTypeContact, false, false, nil)
} else {
//TODO:localize
return ("non-contact", false, false, nil)
return (strings.ChatList_PeerTypeNonContact, false, false, nil)
}
} else if case .legacyGroup = peer {
return (strings.ChatList_PeerTypeGroup, false, false, nil)

View File

@ -358,7 +358,7 @@ func _internal_applySentQuickReplyMessage(transaction: Transaction, shortcut: St
var state = transaction.getPreferencesEntry(key: PreferencesKeys.shortcutMessages())?.get(QuickReplyMessageShortcutsState.self) ?? QuickReplyMessageShortcutsState(shortcuts: [])
if !state.shortcuts.contains(where: { $0.id == quickReplyId }) {
state.shortcuts.insert(QuickReplyMessageShortcut(id: quickReplyId, shortcut: shortcut), at: 0)
state.shortcuts.append(QuickReplyMessageShortcut(id: quickReplyId, shortcut: shortcut))
transaction.setPreferencesEntry(key: PreferencesKeys.shortcutMessages(), value: PreferencesEntry(state))
}
}
@ -778,19 +778,6 @@ func _internal_updateBusinessAwayMessage(account: Account, awayMessage: Telegram
|> then(remoteApply)
}
/*
connectedBot flags:# can_reply:flags.0?true bot_id:long recipients:BusinessRecipients = ConnectedBot;
account.connectedBots connected_bots:Vector<ConnectedBot> users:Vector<User> = account.ConnectedBots;
---functions---
account.setConnectedBot flags:# can_reply:flags.0?true deleted:flags.1?true bot:InputUser recipients:InputBusinessRecipients = Updates;
account.getConnectedBots = account.ConnectedBots;
*/
public final class TelegramAccountConnectedBot: Codable, Equatable {
public let id: PeerId
public let recipients: TelegramBusinessRecipients

View File

@ -17,9 +17,9 @@ private func dayBusinessHoursText(presentationData: PresentationData, day: Teleg
var businessHoursText: String = ""
switch day {
case .open:
businessHoursText += "open 24 hours"
businessHoursText += presentationData.strings.PeerInfo_BusinessHours_DayOpen24h
case .closed:
businessHoursText += "closed"
businessHoursText += presentationData.strings.PeerInfo_BusinessHours_DayClosed
case let .intervals(intervals):
func clipMinutes(_ value: Int) -> Int {
var value = value
@ -216,22 +216,21 @@ private final class PeerInfoScreenBusinessHoursItemNode: PeerInfoScreenItemNode
for i in 0 ..< businessDays.count {
let dayTitleValue: String
//TODO:localize
switch i {
case 0:
dayTitleValue = "Monday"
dayTitleValue = presentationData.strings.Weekday_Monday
case 1:
dayTitleValue = "Tuesday"
dayTitleValue = presentationData.strings.Weekday_Tuesday
case 2:
dayTitleValue = "Wednesday"
dayTitleValue = presentationData.strings.Weekday_Wednesday
case 3:
dayTitleValue = "Thursday"
dayTitleValue = presentationData.strings.Weekday_Thursday
case 4:
dayTitleValue = "Friday"
dayTitleValue = presentationData.strings.Weekday_Friday
case 5:
dayTitleValue = "Saturday"
dayTitleValue = presentationData.strings.Weekday_Saturday
case 6:
dayTitleValue = "Sunday"
dayTitleValue = presentationData.strings.Weekday_Sunday
default:
dayTitleValue = " "
}
@ -328,8 +327,7 @@ private final class PeerInfoScreenBusinessHoursItemNode: PeerInfoScreenItemNode
}
let isOpen = self.cachedWeekMinuteSet.contains(currentWeekMinute)
//TODO:localize
let openStatusText = isOpen ? "Open" : "Closed"
let openStatusText = isOpen ? presentationData.strings.PeerInfo_BusinessHours_StatusOpen : presentationData.strings.PeerInfo_BusinessHours_StatusClosed
var currentDayStatusText = currentDayIndex >= 0 && currentDayIndex < businessDays.count ? dayBusinessHoursText(presentationData: presentationData, day: businessDays[currentDayIndex], offsetMinutes: timezoneOffsetMinutes) : " "
@ -337,11 +335,10 @@ private final class PeerInfoScreenBusinessHoursItemNode: PeerInfoScreenItemNode
for range in self.cachedWeekMinuteSet.rangeView {
if range.lowerBound > currentWeekMinute {
let openInMinutes = range.lowerBound - currentWeekMinute
//TODO:localize
if openInMinutes < 60 {
currentDayStatusText = "Opens in \(openInMinutes) minutes"
currentDayStatusText = presentationData.strings.PeerInfo_BusinessHours_StatusOpensInMinutes(Int32(openInMinutes))
} else if openInMinutes < 6 * 60 {
currentDayStatusText = "Opens in \(openInMinutes / 60) hours"
currentDayStatusText = presentationData.strings.PeerInfo_BusinessHours_StatusOpensInHours(Int32(openInMinutes / 60))
} else {
let openDate = currentDate.addingTimeInterval(Double(openInMinutes * 60))
let openTimestamp = Int32(openDate.timeIntervalSince1970) + Int32(currentCalendar.timeZone.secondsFromGMT() - TimeZone.current.secondsFromGMT())
@ -360,7 +357,7 @@ private final class PeerInfoScreenBusinessHoursItemNode: PeerInfoScreenItemNode
return PresentationStrings.FormattedString(string: presentationData.strings.Chat_MessageSeenTimestamp_YesterdayAt(value).string, ranges: [])
}
)).string
currentDayStatusText = "opens \(dateText)"
currentDayStatusText = presentationData.strings.PeerInfo_BusinessHours_StatusOpensOnDate(dateText).string
}
break
}
@ -408,11 +405,10 @@ private final class PeerInfoScreenBusinessHoursItemNode: PeerInfoScreenItemNode
self.timezoneSwitchButton = timezoneSwitchButton
}
let timezoneSwitchTitle: String
//TODO:localize
if self.displayLocalTimezone {
timezoneSwitchTitle = "my time"
timezoneSwitchTitle = presentationData.strings.PeerInfo_BusinessHours_TimezoneSwitchMy
} else {
timezoneSwitchTitle = "local time"
timezoneSwitchTitle = presentationData.strings.PeerInfo_BusinessHours_TimezoneSwitchBusiness
}
timezoneSwitchButtonSize = timezoneSwitchButton.update(
transition: .immediate,
@ -510,22 +506,21 @@ private final class PeerInfoScreenBusinessHoursItemNode: PeerInfoScreenItemNode
}
let dayTitleValue: String
//TODO:localize
switch i {
case 0:
dayTitleValue = "Monday"
dayTitleValue = presentationData.strings.Weekday_Monday
case 1:
dayTitleValue = "Tuesday"
dayTitleValue = presentationData.strings.Weekday_Tuesday
case 2:
dayTitleValue = "Wednesday"
dayTitleValue = presentationData.strings.Weekday_Wednesday
case 3:
dayTitleValue = "Thursday"
dayTitleValue = presentationData.strings.Weekday_Thursday
case 4:
dayTitleValue = "Friday"
dayTitleValue = presentationData.strings.Weekday_Friday
case 5:
dayTitleValue = "Saturday"
dayTitleValue = presentationData.strings.Weekday_Saturday
case 6:
dayTitleValue = "Sunday"
dayTitleValue = presentationData.strings.Weekday_Sunday
default:
dayTitleValue = " "
}

View File

@ -1167,8 +1167,7 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
}
if let businessHours = cachedData.businessHours {
//TODO:localize
items[.peerInfo]!.append(PeerInfoScreenBusinessHoursItem(id: 300, label: "business hours", businessHours: businessHours, requestLayout: { animated in
items[.peerInfo]!.append(PeerInfoScreenBusinessHoursItem(id: 300, label: presentationData.strings.PeerInfo_BusinessHours_Label, businessHours: businessHours, requestLayout: { animated in
interaction.requestLayout(animated)
}, longTapAction: { sourceNode, text in
if !text.isEmpty {
@ -1178,12 +1177,11 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
}
if let businessLocation = cachedData.businessLocation {
//TODO:localize
if let coordinates = businessLocation.coordinates {
let imageSignal = chatMapSnapshotImage(engine: context.engine, resource: MapSnapshotMediaResource(latitude: coordinates.latitude, longitude: coordinates.longitude, width: 90, height: 90))
items[.peerInfo]!.append(PeerInfoScreenAddressItem(
id: 301,
label: "location",
label: presentationData.strings.PeerInfo_Location_Label,
text: businessLocation.address,
imageSignal: imageSignal,
action: {
@ -1198,7 +1196,7 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
} else {
items[.peerInfo]!.append(PeerInfoScreenAddressItem(
id: 301,
label: "location",
label: presentationData.strings.PeerInfo_Location_Label,
text: businessLocation.address,
imageSignal: nil,
action: nil,

View File

@ -141,7 +141,7 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
private var customScheduleStart: Date?
private var customScheduleEnd: Date?
private var sendWhenOffline: Bool = false
private var sendWhenOffline: Bool = true
private var hasAccessToAllChatsByDefault: Bool = true
private var additionalPeerList = AdditionalPeerList(
@ -195,11 +195,10 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
if self.isOn {
if !self.hasAccessToAllChatsByDefault && self.additionalPeerList.categories.isEmpty && self.additionalPeerList.peers.isEmpty {
//TODO:localize
self.environment?.controller()?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: "No recipients selected. Reset?", actions: [
TextAlertAction(type: .genericAction, title: "Cancel", action: {
self.environment?.controller()?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: presentationData.strings.BusinessMessageSetup_ErrorNoRecipients_Text, actions: [
TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {
}),
TextAlertAction(type: .defaultAction, title: "Reset", action: {
TextAlertAction(type: .defaultAction, title: presentationData.strings.BusinessMessageSetup_ErrorNoRecipients_ResetAction, action: {
complete()
})
]), in: .window(.root))
@ -208,28 +207,26 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
}
if case .away = component.mode, case .custom = self.schedule {
//TODO:localize
var errorText: String?
if let customScheduleStart = self.customScheduleStart, let customScheduleEnd = self.customScheduleEnd {
if customScheduleStart >= customScheduleEnd {
errorText = "Custom schedule end time must be larger than start time."
errorText = presentationData.strings.BusinessMessageSetup_ErrorScheduleEndTimeBeforeStartTime_Text
}
} else {
if self.customScheduleStart == nil && self.customScheduleEnd == nil {
errorText = "Custom schedule time is missing."
errorText = presentationData.strings.BusinessMessageSetup_ErrorScheduleTimeMissing_Text
} else if self.customScheduleStart == nil {
errorText = "Custom schedule start time is missing."
errorText = presentationData.strings.BusinessMessageSetup_ErrorScheduleStartTimeMissing_Text
} else {
errorText = "Custom schedule end time is missing."
errorText = presentationData.strings.BusinessMessageSetup_ErrorScheduleEndTimeMissing_Text
}
}
if let errorText {
//TODO:localize
self.environment?.controller()?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: errorText, actions: [
TextAlertAction(type: .genericAction, title: "Cancel", action: {
TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {
}),
TextAlertAction(type: .defaultAction, title: "Reset", action: {
TextAlertAction(type: .defaultAction, title: presentationData.strings.BusinessMessageSetup_ErrorScheduleTime_ResetAction, action: {
complete()
})
]), in: .window(.root))
@ -281,7 +278,6 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
if let customScheduleStart = self.customScheduleStart, let customScheduleEnd = self.customScheduleEnd {
mappedSchedule = .custom(beginTimestamp: Int32(customScheduleStart.timeIntervalSince1970), endTimestamp: Int32(customScheduleEnd.timeIntervalSince1970))
} else {
//TODO:localize
return false
}
}
@ -335,7 +331,7 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
}
private func openAdditionalPeerListSetup() {
guard let component = self.component else {
guard let component = self.component, let enviroment = self.environment else {
return
}
@ -351,19 +347,19 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
id: self.hasAccessToAllChatsByDefault ? AdditionalCategoryId.existingChats.rawValue : AdditionalCategoryId.newChats.rawValue,
icon: generateAvatarImage(size: CGSize(width: 40.0, height: 40.0), icon: generateTintedImage(image: UIImage(bundleImageName: self.hasAccessToAllChatsByDefault ? "Chat List/Filters/Chats" : "Chat List/Filters/NewChats"), color: .white), cornerRadius: 12.0, color: .purple),
smallIcon: generateAvatarImage(size: CGSize(width: 22.0, height: 22.0), icon: generateTintedImage(image: UIImage(bundleImageName: self.hasAccessToAllChatsByDefault ? "Chat List/Filters/Chats" : "Chat List/Filters/NewChats"), color: .white), iconScale: 0.6, cornerRadius: 6.0, circleCorners: true, color: .purple),
title: self.hasAccessToAllChatsByDefault ? "Existing Chats" : "New Chats"
title: self.hasAccessToAllChatsByDefault ? enviroment.strings.BusinessMessageSetup_Recipients_CategoryExistingChats : enviroment.strings.BusinessMessageSetup_Recipients_CategoryNewChats
),
ChatListNodeAdditionalCategory(
id: AdditionalCategoryId.contacts.rawValue,
icon: generateAvatarImage(size: CGSize(width: 40.0, height: 40.0), icon: generateTintedImage(image: UIImage(bundleImageName: "Chat List/Filters/Contact"), color: .white), cornerRadius: 12.0, color: .blue),
smallIcon: generateAvatarImage(size: CGSize(width: 22.0, height: 22.0), icon: generateTintedImage(image: UIImage(bundleImageName: "Chat List/Filters/Contact"), color: .white), iconScale: 0.6, cornerRadius: 6.0, circleCorners: true, color: .blue),
title: "Contacts"
title: enviroment.strings.BusinessMessageSetup_Recipients_CategoryContacts
),
ChatListNodeAdditionalCategory(
id: AdditionalCategoryId.nonContacts.rawValue,
icon: generateAvatarImage(size: CGSize(width: 40.0, height: 40.0), icon: generateTintedImage(image: UIImage(bundleImageName: "Chat List/Filters/User"), color: .white), cornerRadius: 12.0, color: .yellow),
smallIcon: generateAvatarImage(size: CGSize(width: 22.0, height: 22.0), icon: generateTintedImage(image: UIImage(bundleImageName: "Chat List/Filters/User"), color: .white), iconScale: 0.6, cornerRadius: 6.0, circleCorners: true, color: .yellow),
title: "Non-Contacts"
title: enviroment.strings.BusinessMessageSetup_Recipients_CategoryNonContacts
)
]
var selectedCategories = Set<Int>()
@ -380,10 +376,9 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
}
}
//TODO:localize
let controller = component.context.sharedContext.makeContactMultiselectionController(ContactMultiselectionControllerParams(context: component.context, mode: .chatSelection(ContactMultiselectionControllerMode.ChatSelection(
title: self.hasAccessToAllChatsByDefault ? "Exclude Chats" : "Include Chats",
searchPlaceholder: "Search chats",
title: self.hasAccessToAllChatsByDefault ? enviroment.strings.BusinessMessageSetup_Recipients_ExcludeSearchTitle : enviroment.strings.BusinessMessageSetup_Recipients_IncludeSearchTitle,
searchPlaceholder: enviroment.strings.ChatListFilter_AddChatsSearchPlaceholder,
selectedChats: Set(self.additionalPeerList.peers.map(\.peer.id)),
additionalCategories: ContactMultiselectionControllerAdditionalCategories(categories: additionalCategories, selectedCategories: selectedCategories),
chatListFilters: nil,
@ -687,11 +682,10 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
//TODO:localize
let navigationTitleSize = self.navigationTitle.update(
transition: transition,
component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(string: component.mode == .greeting ? "Greeting Message" : "Away Message", font: Font.semibold(17.0), textColor: environment.theme.rootController.navigationBar.primaryTextColor)),
text: .plain(NSAttributedString(string: component.mode == .greeting ? environment.strings.BusinessMessageSetup_TitleGreetingMessage : environment.strings.BusinessMessageSetup_TitleAwayMessage, font: Font.semibold(17.0), textColor: environment.theme.rootController.navigationBar.primaryTextColor)),
horizontalAlignment: .center
)),
environment: {},
@ -736,8 +730,7 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
contentHeight += 124.0
//TODO:localize
let subtitleString = NSMutableAttributedString(attributedString: parseMarkdownIntoAttributedString(component.mode == .greeting ? "Greet customers when they message you the first time or after a period of no activity." : "Automatically reply with a message when you are away.", attributes: MarkdownAttributes(
let subtitleString = NSMutableAttributedString(attributedString: parseMarkdownIntoAttributedString(component.mode == .greeting ? environment.strings.BusinessMessageSetup_TextGreetingMessage : environment.strings.BusinessMessageSetup_TextAwayMessage, attributes: MarkdownAttributes(
body: MarkdownAttributeSet(font: Font.regular(15.0), textColor: environment.theme.list.freeTextColor),
bold: MarkdownAttributeSet(font: Font.semibold(15.0), textColor: environment.theme.list.freeTextColor),
link: MarkdownAttributeSet(font: Font.regular(15.0), textColor: environment.theme.list.itemAccentColor),
@ -746,7 +739,6 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
}), textAlignment: .center
))
//TODO:localize
let subtitleSize = self.subtitle.update(
transition: .immediate,
component: AnyComponent(BalancedTextComponent(
@ -789,7 +781,7 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
title: AnyComponent(VStack([
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: component.mode == .greeting ? "Send Greeting Message" : "Send Away Message",
string: component.mode == .greeting ? environment.strings.BusinessMessageSetup_ToggleGreetingMessage : environment.strings.BusinessMessageSetup_ToggleAwayMessage,
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
textColor: environment.theme.list.itemPrimaryTextColor
)),
@ -806,7 +798,6 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
action: nil
))))
//TODO:localize
let generalSectionSize = self.generalSection.update(
transition: transition,
component: AnyComponent(ListSectionComponent(
@ -830,7 +821,6 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
var otherSectionsHeight: CGFloat = 0.0
//TODO:localize
var messagesSectionItems: [AnyComponentWithIdentity<Empty>] = []
if let currentShortcut = self.currentShortcut {
if let accountPeer = self.accountPeer {
@ -855,7 +845,7 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
title: AnyComponent(VStack([
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: component.mode == .greeting ? "Create a Greeting Message" : "Create an Away Message",
string: component.mode == .greeting ? environment.strings.BusinessMessageSetup_CreateGreetingMessage : environment.strings.BusinessMessageSetup_CreateAwayMessage,
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
textColor: environment.theme.list.itemAccentColor
)),
@ -881,7 +871,7 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
theme: environment.theme,
header: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: component.mode == .greeting ? "GREETING MESSAGE" : "AWAY MESSAGE",
string: component.mode == .greeting ? environment.strings.BusinessMessageSetup_GreetingMessageSectionHeader : environment.strings.BusinessMessageSetup_AwayMessageSectionHeader,
font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize),
textColor: environment.theme.list.freeTextColor
)),
@ -906,24 +896,23 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
otherSectionsHeight += sectionSpacing
if case .away = component.mode {
//TODO:localize
var scheduleSectionItems: [AnyComponentWithIdentity<Empty>] = []
optionLoop: for i in 0 ..< 3 {
let title: String
let schedule: Schedule
switch i {
case 0:
title = "Always Send"
title = environment.strings.BusinessMessageSetup_ScheduleAlways
schedule = .always
case 1:
if component.initialData.businessHours == nil {
continue optionLoop
}
title = "Outside of Business Hours"
title = environment.strings.BusinessMessageSetup_ScheduleOutsideBusinessHours
schedule = .outsideBusinessHours
default:
title = "Custom Schedule"
title = environment.strings.BusinessMessageSetup_ScheduleCustom
schedule = .custom
}
let isSelected = self.schedule == schedule
@ -963,7 +952,7 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
theme: environment.theme,
header: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: "SCHEDULE",
string: environment.strings.BusinessMessageSetup_ScheduleSectionHeader,
font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize),
textColor: environment.theme.list.freeTextColor
)),
@ -995,11 +984,11 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
let isStartTime: Bool
switch i {
case 0:
title = "Start Time"
title = environment.strings.BusinessMessageSetup_ScheduleStartTime
itemDate = self.customScheduleStart
isStartTime = true
default:
title = "End Time"
title = environment.strings.BusinessMessageSetup_ScheduleEndTime
itemDate = self.customScheduleEnd
isStartTime = false
}
@ -1059,7 +1048,7 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
} else {
icon = ListActionItemComponent.Icon(component: AnyComponentWithIdentity(id: 1, component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: "Set",
string: environment.strings.BusinessMessageSetup_ScheduleTimePlaceholder,
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
textColor: environment.theme.list.itemSecondaryTextColor
)),
@ -1126,7 +1115,7 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
header: nil,
footer: AnyComponent(MultilineTextComponent(
text: .markdown(
text: "Don't send the away message if you've recently been online.",
text: environment.strings.BusinessMessageSetup_SendWhenOfflineFooter,
attributes: MarkdownAttributes(
body: MarkdownAttributeSet(font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize), textColor: environment.theme.list.freeTextColor),
bold: MarkdownAttributeSet(font: Font.semibold(presentationData.listsFontSize.itemListBaseHeaderFontSize), textColor: environment.theme.list.freeTextColor),
@ -1144,7 +1133,7 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
title: AnyComponent(VStack([
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: "Only if Offline",
string: environment.strings.BusinessMessageSetup_SendWhenOffline,
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
textColor: environment.theme.list.itemPrimaryTextColor
)),
@ -1183,14 +1172,13 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
otherSectionsHeight += sectionSpacing
}
//TODO:localize
let accessSectionSize = self.accessSection.update(
transition: transition,
component: AnyComponent(ListSectionComponent(
theme: environment.theme,
header: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: "RECIPIENTS",
string: environment.strings.BusinessMessageSetup_RecipientsSectionHeader,
font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize),
textColor: environment.theme.list.freeTextColor
)),
@ -1203,7 +1191,7 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
title: AnyComponent(VStack([
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: "All 1-to-1 Chats Except...",
string: environment.strings.BusinessMessageSetup_RecipientsOptionAllExcept,
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
textColor: environment.theme.list.itemPrimaryTextColor
)),
@ -1233,7 +1221,7 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
title: AnyComponent(VStack([
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: "Only Selected Chats",
string: environment.strings.BusinessMessageSetup_RecipientsOptionOnly,
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
textColor: environment.theme.list.itemPrimaryTextColor
)),
@ -1281,7 +1269,7 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
title: AnyComponent(VStack([
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: self.hasAccessToAllChatsByDefault ? "Exclude Chats..." : "Select Chats...",
string: self.hasAccessToAllChatsByDefault ? environment.strings.BusinessMessageSetup_Recipients_AddExclude : environment.strings.BusinessMessageSetup_Recipients_AddInclude,
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
textColor: environment.theme.list.itemAccentColor
)),
@ -1304,23 +1292,22 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
let title: String
let icon: String
let color: AvatarBackgroundColor
//TODO:localize
switch category {
case .newChats:
title = "New Chats"
icon = "Chat List/Filters/Contact"
title = environment.strings.BusinessMessageSetup_Recipients_CategoryNewChats
icon = "Chat List/Filters/NewChats"
color = .purple
case .existingChats:
title = "Existing Chats"
icon = "Chat List/Filters/Contact"
title = environment.strings.BusinessMessageSetup_Recipients_CategoryExistingChats
icon = "Chat List/Filters/Chats"
color = .purple
case .contacts:
title = "Contacts"
title = environment.strings.BusinessMessageSetup_Recipients_CategoryContacts
icon = "Chat List/Filters/Contact"
color = .blue
case .nonContacts:
title = "Non-Contacts"
icon = "Chat List/Filters/Contact"
title = environment.strings.BusinessMessageSetup_Recipients_CategoryNonContacts
icon = "Chat List/Filters/User"
color = .yellow
}
excludedSectionItems.append(AnyComponentWithIdentity(id: category, component: AnyComponent(PeerListItemComponent(
@ -1354,7 +1341,7 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
sideInset: 0.0,
title: peer.peer.displayTitle(strings: environment.strings, displayOrder: .firstLast),
peer: peer.peer,
subtitle: peer.isContact ? "contact" : "non-contact",
subtitle: peer.isContact ? environment.strings.ChatList_PeerTypeContact : environment.strings.ChatList_PeerTypeNonContact,
subtitleAccessory: .none,
presence: nil,
selectionState: .none,
@ -1364,14 +1351,13 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
))))
}
//TODO:localize
let excludedSectionSize = self.excludedSection.update(
transition: transition,
component: AnyComponent(ListSectionComponent(
theme: environment.theme,
header: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: self.hasAccessToAllChatsByDefault ? "EXCLUDED CHATS" : "INCLUDED CHATS",
string: self.hasAccessToAllChatsByDefault ? environment.strings.BusinessMessageSetup_Recipients_ExcludedSectionHeader : environment.strings.BusinessMessageSetup_Recipients_IncludedSectionHeader,
font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize),
textColor: environment.theme.list.freeTextColor
)),
@ -1379,7 +1365,7 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
)),
footer: AnyComponent(MultilineTextComponent(
text: .markdown(
text: component.mode == .greeting ? "Choose chats or entire chat categories for sending a greeting message." : "Choose chats or entire chat categories for sending an away message.",
text: component.mode == .greeting ? environment.strings.BusinessMessageSetup_Recipients_GreetingMessageFooter : environment.strings.BusinessMessageSetup_Recipients_AwayMessageFooter,
attributes: MarkdownAttributes(
body: MarkdownAttributeSet(font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize), textColor: environment.theme.list.freeTextColor),
bold: MarkdownAttributeSet(font: Font.semibold(presentationData.listsFontSize.itemListBaseHeaderFontSize), textColor: environment.theme.list.freeTextColor),
@ -1428,7 +1414,7 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
theme: environment.theme,
header: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: "PERIOD OF NO ACTIVITY",
string: environment.strings.BusinessMessageSetup_InactivitySectionHeader,
font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize),
textColor: environment.theme.list.freeTextColor
)),
@ -1436,7 +1422,7 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
)),
footer: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: "Choose how many days should pass after your last interaction with a recipient to send them the greeting in response to their message.",
string: environment.strings.BusinessMessageSetup_InactivitySectionFooter,
font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize),
textColor: environment.theme.list.freeTextColor
)),
@ -1445,12 +1431,9 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
items: [
AnyComponentWithIdentity(id: 0, component: AnyComponent(ListItemSliderSelectorComponent(
theme: environment.theme,
values: [
"7 days",
"14 days",
"21 days",
"28 days"
],
values: valueList.map { item in
return environment.strings.MessageTimer_Days(Int32(item))
},
selectedIndex: selectedInactivityIndex,
selectedIndexUpdated: { [weak self] index in
guard let self else {

View File

@ -75,7 +75,7 @@ final class QuickReplyEmptyStateComponent: Component {
content: AnyComponentWithIdentity(
id: AnyHashable(0),
component: AnyComponent(ButtonTextContentComponent(
text: "Add Quick Reply",
text: component.strings.QuickReplies_EmptyState_AddButton,
badge: 0,
textColor: component.theme.list.itemCheckColors.foregroundColor,
badgeBackground: component.theme.list.itemCheckColors.foregroundColor,
@ -115,11 +115,10 @@ final class QuickReplyEmptyStateComponent: Component {
containerSize: CGSize(width: 120.0, height: 120.0)
)
//TODO:localize
let titleSize = self.title.update(
transition: .immediate,
component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(string: "No Quick Replies", font: Font.semibold(17.0), textColor: component.theme.rootController.navigationBar.primaryTextColor)),
text: .plain(NSAttributedString(string: component.strings.QuickReplies_EmptyState_Title, font: Font.semibold(17.0), textColor: component.theme.rootController.navigationBar.primaryTextColor)),
horizontalAlignment: .center
)),
environment: {},
@ -129,7 +128,7 @@ final class QuickReplyEmptyStateComponent: Component {
let textSize = self.text.update(
transition: .immediate,
component: AnyComponent(BalancedTextComponent(
text: .plain(NSAttributedString(string: "Set up shortcuts with rich text and media to respond to messages faster.", font: Font.regular(15.0), textColor: component.theme.list.itemSecondaryTextColor)),
text: .plain(NSAttributedString(string: component.strings.QuickReplies_EmptyState_Text, font: Font.regular(15.0), textColor: component.theme.list.itemSecondaryTextColor)),
horizontalAlignment: .center,
maximumNumberOfLines: 20,
lineSpacing: 0.2

View File

@ -87,12 +87,11 @@ final class QuickReplySetupScreenComponent: Component {
func item(listNode: ContentListNode) -> ListViewItem {
switch self {
case .add:
//TODO:localize
return ItemListPeerActionItem(
presentationData: ItemListPresentationData(listNode.presentationData),
icon: PresentationResourcesItemList.plusIconImage(listNode.presentationData.theme),
iconSignal: nil,
title: "New Quick Reply",
title: listNode.presentationData.strings.QuickReply_InlineCreateAction,
additionalBadgeIcon: nil,
alwaysPlain: true,
hasSeparator: true,
@ -525,7 +524,7 @@ final class QuickReplySetupScreenComponent: Component {
}
func openQuickReplyChat(shortcut: String?, shortcutId: Int32?) {
guard let component = self.component else {
guard let component = self.component, let environment = self.environment else {
return
}
@ -564,8 +563,8 @@ final class QuickReplySetupScreenComponent: Component {
var completion: ((String?) -> Void)?
let alertController = quickReplyNameAlertController(
context: component.context,
text: "New Quick Reply",
subtext: "Add a shortcut for your quick reply.",
text: environment.strings.QuickReply_CreateShortcutTitle,
subtext: environment.strings.QuickReply_CreateShortcutText,
value: "",
characterLimit: 32,
apply: { value in
@ -573,7 +572,7 @@ final class QuickReplySetupScreenComponent: Component {
}
)
completion = { [weak self, weak alertController] value in
guard let self else {
guard let self, let environment = self.environment else {
alertController?.dismissAnimated()
return
}
@ -585,7 +584,7 @@ final class QuickReplySetupScreenComponent: Component {
if shortcutMessageList.items.contains(where: { $0.shortcut.lowercased() == value.lowercased() }) {
if let contentNode = alertController?.contentNode as? QuickReplyNameAlertContentNode {
contentNode.setErrorText(errorText: "Shortcut with that name already exists")
contentNode.setErrorText(errorText: environment.strings.QuickReply_ShortcutExistsInlineError)
}
return
}
@ -602,15 +601,15 @@ final class QuickReplySetupScreenComponent: Component {
}
func openEditShortcut(id: Int32, currentValue: String) {
guard let component = self.component else {
guard let component = self.component, let environment = self.environment else {
return
}
var completion: ((String?) -> Void)?
let alertController = quickReplyNameAlertController(
context: component.context,
text: "Edit Shortcut",
subtext: "Add a new name for your shortcut.",
text: environment.strings.QuickReply_EditShortcutTitle,
subtext: environment.strings.QuickReply_EditShortcutText,
value: currentValue,
characterLimit: 32,
apply: { value in
@ -618,7 +617,7 @@ final class QuickReplySetupScreenComponent: Component {
}
)
completion = { [weak self, weak alertController] value in
guard let self, let component = self.component else {
guard let self, let component = self.component, let environment = self.environment else {
alertController?.dismissAnimated()
return
}
@ -634,7 +633,7 @@ final class QuickReplySetupScreenComponent: Component {
if shortcutMessageList.items.contains(where: { $0.shortcut.lowercased() == value.lowercased() }) {
if let contentNode = alertController?.contentNode as? QuickReplyNameAlertContentNode {
contentNode.setErrorText(errorText: "Shortcut with that name already exists")
contentNode.setErrorText(errorText: environment.strings.QuickReply_ShortcutExistsInlineError)
}
} else {
component.context.engine.accountData.editMessageShortcut(id: id, shortcut: value)
@ -665,8 +664,7 @@ final class QuickReplySetupScreenComponent: Component {
let actionSheet = ActionSheetController(presentationData: presentationData)
var items: [ActionSheetItem] = []
//TODO:localize
items.append(ActionSheetButtonItem(title: ids.count == 1 ? "Delete Quick Reply" : "Delete Quick Replies", color: .destructive, action: { [weak self, weak actionSheet] in
items.append(ActionSheetButtonItem(title: ids.count == 1 ? presentationData.strings.QuickReply_DeleteConfirmationSingle : presentationData.strings.QuickReply_DeleteConfirmationMultiple, color: .destructive, action: { [weak self, weak actionSheet] in
actionSheet?.dismissAnimated()
guard let self, let component = self.component else {
return
@ -732,10 +730,9 @@ final class QuickReplySetupScreenComponent: Component {
let titleText: String
if !self.selectedIds.isEmpty {
//TODO:localize
titleText = "\(self.selectedIds.count) Selected"
titleText = strings.QuickReply_SelectedTitle(Int32(self.selectedIds.count))
} else {
titleText = "Quick Replies"
titleText = strings.QuickReply_Title
}
let closeTitle: String
@ -762,7 +759,7 @@ final class QuickReplySetupScreenComponent: Component {
}
))) : nil,
rightButtons: rightButtons,
backTitle: isModal ? nil : "Back",
backTitle: isModal ? nil : strings.Common_Back,
backPressed: { [weak self] in
guard let self else {
return
@ -1060,12 +1057,7 @@ final class QuickReplySetupScreenComponent: Component {
self.selectionPanel = selectionPanel
}
let buttonTitle: String
if self.selectedIds.count == 1 {
buttonTitle = "Delete 1 Quick Reply"
} else {
buttonTitle = "Delete \(self.selectedIds.count) Quick Replies"
}
let buttonTitle: String = environment.strings.QuickReply_DeleteAction(Int32(self.selectedIds.count))
let selectionPanelSize = selectionPanel.update(
transition: selectionPanelTransition,
@ -1098,7 +1090,6 @@ final class QuickReplySetupScreenComponent: Component {
containerSize: availableSize
)
let selectionPanelFrame = CGRect(origin: CGPoint(x: 0.0, y: availableSize.height - selectionPanelSize.height), size: selectionPanelSize)
print("selectionPanelFrame: \(selectionPanelFrame.minY)")
listBottomInset = selectionPanelSize.height
if let selectionPanelView = selectionPanel.view {
var animateIn = false

View File

@ -117,7 +117,7 @@ final class BusinessDaySetupScreenComponent: Component {
}
func attemptNavigation(complete: @escaping () -> Void) -> Bool {
guard let component = self.component else {
guard let component = self.component, let enviroment = self.environment else {
return true
}
@ -126,11 +126,10 @@ final class BusinessDaySetupScreenComponent: Component {
}
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
//TODO:localize
self.environment?.controller()?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: "Business hours are intersecting. Reset?", actions: [
TextAlertAction(type: .genericAction, title: "Cancel", action: {
self.environment?.controller()?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: enviroment.strings.BusinessHoursSetup_ErrorIntersectingHours_Text, actions: [
TextAlertAction(type: .genericAction, title: enviroment.strings.Common_Cancel, action: {
}),
TextAlertAction(type: .defaultAction, title: "Reset", action: {
TextAlertAction(type: .defaultAction, title: enviroment.strings.BusinessHoursSetup_ErrorIntersectingHours_ResetAction, action: {
complete()
})
]), in: .window(.root))
@ -258,23 +257,22 @@ final class BusinessDaySetupScreenComponent: Component {
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
//TODO:localize
let title: String
switch component.dayIndex {
case 0:
title = "Monday"
title = environment.strings.Weekday_Monday
case 1:
title = "Tuesday"
title = environment.strings.Weekday_Tuesday
case 2:
title = "Wednesday"
title = environment.strings.Weekday_Wednesday
case 3:
title = "Thursday"
title = environment.strings.Weekday_Thursday
case 4:
title = "Friday"
title = environment.strings.Weekday_Friday
case 5:
title = "Saturday"
title = environment.strings.Weekday_Saturday
case 6:
title = "Sunday"
title = environment.strings.Weekday_Sunday
default:
title = " "
}
@ -309,7 +307,6 @@ final class BusinessDaySetupScreenComponent: Component {
contentHeight += environment.navigationHeight
contentHeight += 16.0
//TODO:localize
let generalSectionSize = self.generalSection.update(
transition: transition,
component: AnyComponent(ListSectionComponent(
@ -322,7 +319,7 @@ final class BusinessDaySetupScreenComponent: Component {
title: AnyComponent(VStack([
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: "Open On This Day",
string: environment.strings.BusinessHoursSetup_DaySwitch,
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
textColor: environment.theme.list.itemPrimaryTextColor
)),
@ -381,7 +378,7 @@ final class BusinessDaySetupScreenComponent: Component {
title: AnyComponent(VStack([
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: isOpenTime ? "Opening time" : "Closing Time",
string: isOpenTime ? environment.strings.BusinessHoursSetup_DayIntervalStart : environment.strings.BusinessHoursSetup_DayIntervalEnd,
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
textColor: environment.theme.list.itemPrimaryTextColor
)),
@ -420,7 +417,7 @@ final class BusinessDaySetupScreenComponent: Component {
title: AnyComponent(VStack([
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: "Remove",
string: environment.strings.BusinessHoursSetup_DayIntervalRemove,
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
textColor: environment.theme.list.itemDestructiveColor
)),
@ -503,7 +500,6 @@ final class BusinessDaySetupScreenComponent: Component {
canAddRanges = false
}
//TODO:localize
let addSectionSize = self.addSection.update(
transition: transition,
component: AnyComponent(ListSectionComponent(
@ -511,7 +507,7 @@ final class BusinessDaySetupScreenComponent: Component {
header: nil,
footer: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: "Specify your working hours during the day.",
string: environment.strings.BusinessHoursSetup_AddSectionFooter,
font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize),
textColor: environment.theme.list.freeTextColor
)),
@ -523,7 +519,7 @@ final class BusinessDaySetupScreenComponent: Component {
title: AnyComponent(VStack([
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: "Add a Set of Hours",
string: environment.strings.BusinessHoursSetup_AddAction,
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
textColor: environment.theme.list.itemAccentColor
)),

View File

@ -295,7 +295,7 @@ final class BusinessHoursSetupScreenComponent: Component {
}
func attemptNavigation(complete: @escaping () -> Void) -> Bool {
guard let component = self.component else {
guard let component = self.component, let environment = self.environment else {
return true
}
@ -306,11 +306,10 @@ final class BusinessHoursSetupScreenComponent: Component {
return true
} catch _ {
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
//TODO:localize
self.environment?.controller()?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: "Business hours are intersecting. Reset?", actions: [
TextAlertAction(type: .genericAction, title: "Cancel", action: {
self.environment?.controller()?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: environment.strings.BusinessHoursSetup_ErrorIntersectingDays_Text, actions: [
TextAlertAction(type: .genericAction, title: environment.strings.Common_Cancel, action: {
}),
TextAlertAction(type: .defaultAction, title: "Reset", action: { [weak self] in
TextAlertAction(type: .defaultAction, title: environment.strings.BusinessHoursSetup_ErrorIntersectingDays_ResetAction, action: { [weak self] in
guard let self else {
return
}
@ -409,11 +408,10 @@ final class BusinessHoursSetupScreenComponent: Component {
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
//TODO:localize
let navigationTitleSize = self.navigationTitle.update(
transition: transition,
component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(string: "Business Hours", font: Font.semibold(17.0), textColor: environment.theme.rootController.navigationBar.primaryTextColor)),
text: .plain(NSAttributedString(string: environment.strings.BusinessHoursSetup_Title, font: Font.semibold(17.0), textColor: environment.theme.rootController.navigationBar.primaryTextColor)),
horizontalAlignment: .center
)),
environment: {},
@ -461,8 +459,7 @@ final class BusinessHoursSetupScreenComponent: Component {
contentHeight += 126.0
//TODO:localize
let subtitleString = NSMutableAttributedString(attributedString: parseMarkdownIntoAttributedString("Turn this on to show your opening hours schedule to your customers.", attributes: MarkdownAttributes(
let subtitleString = NSMutableAttributedString(attributedString: parseMarkdownIntoAttributedString(environment.strings.BusinessHoursSetup_Text, attributes: MarkdownAttributes(
body: MarkdownAttributeSet(font: Font.regular(15.0), textColor: environment.theme.list.freeTextColor),
bold: MarkdownAttributeSet(font: Font.semibold(15.0), textColor: environment.theme.list.freeTextColor),
link: MarkdownAttributeSet(font: Font.regular(15.0), textColor: environment.theme.list.itemAccentColor),
@ -471,7 +468,6 @@ final class BusinessHoursSetupScreenComponent: Component {
}), textAlignment: .center
))
//TODO:localize
let subtitleSize = self.subtitle.update(
transition: .immediate,
component: AnyComponent(BalancedTextComponent(
@ -508,7 +504,6 @@ final class BusinessHoursSetupScreenComponent: Component {
contentHeight += subtitleSize.height
contentHeight += 27.0
//TODO:localize
let generalSectionSize = self.generalSection.update(
transition: transition,
component: AnyComponent(ListSectionComponent(
@ -521,7 +516,7 @@ final class BusinessHoursSetupScreenComponent: Component {
title: AnyComponent(VStack([
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: "Show Business Hours",
string: environment.strings.BusinessHoursSetup_MainToggle,
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
textColor: environment.theme.list.itemPrimaryTextColor
)),
@ -559,22 +554,21 @@ final class BusinessHoursSetupScreenComponent: Component {
let dayIndex = daysSectionItems.count
let title: String
//TODO:localize
switch dayIndex {
case 0:
title = "Monday"
title = environment.strings.Weekday_Monday
case 1:
title = "Tuesday"
title = environment.strings.Weekday_Tuesday
case 2:
title = "Wednesday"
title = environment.strings.Weekday_Wednesday
case 3:
title = "Thursday"
title = environment.strings.Weekday_Thursday
case 4:
title = "Friday"
title = environment.strings.Weekday_Friday
case 5:
title = "Saturday"
title = environment.strings.Weekday_Saturday
case 6:
title = "Sunday"
title = environment.strings.Weekday_Sunday
default:
title = " "
}
@ -593,17 +587,17 @@ final class BusinessHoursSetupScreenComponent: Component {
if let ranges = self.daysState.days[dayIndex].ranges {
if ranges.isEmpty {
subtitle.append(NSAttributedString(string: "Open 24 Hours", font: subtitleFont, textColor: invalidIndices.contains(0) ? environment.theme.list.itemDestructiveColor : environment.theme.list.itemAccentColor))
subtitle.append(NSAttributedString(string: environment.strings.BusinessHoursSetup_DayOpen24h, font: subtitleFont, textColor: invalidIndices.contains(0) ? environment.theme.list.itemDestructiveColor : environment.theme.list.itemAccentColor))
} else {
for i in 0 ..< ranges.count {
let range = ranges[i]
let startHours = clipMinutes(range.startMinute) / 60
let startMinutes = clipMinutes(range.startMinute) % 60
let startText = stringForShortTimestamp(hours: Int32(startHours), minutes: Int32(startMinutes), dateTimeFormat: PresentationDateTimeFormat())
let startText = stringForShortTimestamp(hours: Int32(startHours), minutes: Int32(startMinutes), dateTimeFormat: presentationData.dateTimeFormat)
let endHours = clipMinutes(range.endMinute) / 60
let endMinutes = clipMinutes(range.endMinute) % 60
let endText = stringForShortTimestamp(hours: Int32(endHours), minutes: Int32(endMinutes), dateTimeFormat: PresentationDateTimeFormat())
let endText = stringForShortTimestamp(hours: Int32(endHours), minutes: Int32(endMinutes), dateTimeFormat: presentationData.dateTimeFormat)
var rangeString = "\(startText)\u{00a0}- \(endText)"
if i != ranges.count - 1 {
@ -614,7 +608,7 @@ final class BusinessHoursSetupScreenComponent: Component {
}
}
} else {
subtitle.append(NSAttributedString(string: "Closed", font: subtitleFont, textColor: environment.theme.list.itemAccentColor))
subtitle.append(NSAttributedString(string: environment.strings.BusinessHoursSetup_DayClosed, font: subtitleFont, textColor: environment.theme.list.itemAccentColor))
}
daysSectionItems.append(AnyComponentWithIdentity(id: dayIndex, component: AnyComponent(ListActionItemComponent(
@ -678,7 +672,7 @@ final class BusinessHoursSetupScreenComponent: Component {
theme: environment.theme,
header: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: "BUSINESS HOURS",
string: environment.strings.BusinessHoursSetup_DaysSectionTitle,
font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize),
textColor: environment.theme.list.freeTextColor
)),
@ -712,8 +706,7 @@ final class BusinessHoursSetupScreenComponent: Component {
timezoneValueText = TimeZone(identifier: self.daysState.timezoneId)?.localizedName(for: .shortStandard, locale: Locale.current) ?? " "
}
} else {
//TODO:localize
timezoneValueText = "Loading..."
timezoneValueText = "..."
}
let timezoneSectionSize = self.timezoneSection.update(
@ -727,7 +720,7 @@ final class BusinessHoursSetupScreenComponent: Component {
theme: environment.theme,
title: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: "Time Zone", //TODO:localize
string: environment.strings.BusinessHoursSetup_TimeZone,
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
textColor: environment.theme.list.itemPrimaryTextColor
)),

View File

@ -118,7 +118,7 @@ final class BusinessLocationSetupScreenComponent: Component {
}
func attemptNavigation(complete: @escaping () -> Void) -> Bool {
guard let component = self.component else {
guard let component = self.component, let environment = self.environment else {
return true
}
@ -134,11 +134,10 @@ final class BusinessLocationSetupScreenComponent: Component {
if businessLocation != nil && address.isEmpty {
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
//TODO:localize
self.environment?.controller()?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: "Address can't be empty.", actions: [
TextAlertAction(type: .genericAction, title: "Cancel", action: {
self.environment?.controller()?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: environment.strings.BusinessLocationSetup_ErrorAddressEmpty_Text, actions: [
TextAlertAction(type: .genericAction, title: environment.strings.Common_Cancel, action: {
}),
TextAlertAction(type: .destructiveAction, title: "Delete", action: {
TextAlertAction(type: .destructiveAction, title: environment.strings.BusinessLocationSetup_ErrorAddressEmpty_ResetAction, action: {
let _ = component.context.engine.accountData.updateAccountBusinessLocation(businessLocation: nil).startStandalone()
complete()
@ -286,11 +285,10 @@ final class BusinessLocationSetupScreenComponent: Component {
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
//TODO:localize
let navigationTitleSize = self.navigationTitle.update(
transition: transition,
component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(string: "Location", font: Font.semibold(17.0), textColor: environment.theme.rootController.navigationBar.primaryTextColor)),
text: .plain(NSAttributedString(string: environment.strings.BusinessLocationSetup_Title, font: Font.semibold(17.0), textColor: environment.theme.rootController.navigationBar.primaryTextColor)),
horizontalAlignment: .center
)),
environment: {},
@ -335,8 +333,7 @@ final class BusinessLocationSetupScreenComponent: Component {
contentHeight += 129.0
//TODO:localize
let subtitleString = NSMutableAttributedString(attributedString: parseMarkdownIntoAttributedString("Display the location of your business on your account.", attributes: MarkdownAttributes(
let subtitleString = NSMutableAttributedString(attributedString: parseMarkdownIntoAttributedString(environment.strings.BusinessLocationSetup_Text, attributes: MarkdownAttributes(
body: MarkdownAttributeSet(font: Font.regular(15.0), textColor: environment.theme.list.freeTextColor),
bold: MarkdownAttributeSet(font: Font.semibold(15.0), textColor: environment.theme.list.freeTextColor),
link: MarkdownAttributeSet(font: Font.regular(15.0), textColor: environment.theme.list.itemAccentColor),
@ -345,7 +342,6 @@ final class BusinessLocationSetupScreenComponent: Component {
}), textAlignment: .center
))
//TODO:localize
let subtitleSize = self.subtitle.update(
transition: .immediate,
component: AnyComponent(BalancedTextComponent(
@ -382,7 +378,6 @@ final class BusinessLocationSetupScreenComponent: Component {
contentHeight += subtitleSize.height
contentHeight += 27.0
//TODO:localize
var addressSectionItems: [AnyComponentWithIdentity<Empty>] = []
addressSectionItems.append(AnyComponentWithIdentity(id: 0, component: AnyComponent(ListMultilineTextFieldItemComponent(
externalState: self.addressTextInputState,
@ -393,7 +388,7 @@ final class BusinessLocationSetupScreenComponent: Component {
resetText: self.resetAddressText.flatMap { resetAddressText in
return ListMultilineTextFieldItemComponent.ResetText(value: resetAddressText)
},
placeholder: "Enter Address",
placeholder: environment.strings.BusinessLocationSetup_AddressPlaceholder,
autocapitalizationType: .none,
autocorrectionType: .no,
characterLimit: 64,
@ -404,7 +399,6 @@ final class BusinessLocationSetupScreenComponent: Component {
))))
self.resetAddressText = nil
//TODO:localize
let addressSectionSize = self.addressSection.update(
transition: transition,
component: AnyComponent(ListSectionComponent(
@ -428,13 +422,12 @@ final class BusinessLocationSetupScreenComponent: Component {
contentHeight += sectionSpacing
var mapSectionItems: [AnyComponentWithIdentity<Empty>] = []
//TODO:localize
mapSectionItems.append(AnyComponentWithIdentity(id: 0, component: AnyComponent(ListActionItemComponent(
theme: environment.theme,
title: AnyComponent(VStack([
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: "Set Location on Map",
string: environment.strings.BusinessLocationSetup_SetLocationOnMap,
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
textColor: environment.theme.list.itemPrimaryTextColor
)),
@ -471,7 +464,6 @@ final class BusinessLocationSetupScreenComponent: Component {
))))
}
//TODO:localize
let mapSectionSize = self.mapSection.update(
transition: transition,
component: AnyComponent(ListSectionComponent(
@ -496,7 +488,6 @@ final class BusinessLocationSetupScreenComponent: Component {
var deleteSectionHeight: CGFloat = 0.0
deleteSectionHeight += sectionSpacing
//TODO:localize
let deleteSectionSize = self.deleteSection.update(
transition: transition,
component: AnyComponent(ListSectionComponent(
@ -509,7 +500,7 @@ final class BusinessLocationSetupScreenComponent: Component {
title: AnyComponent(VStack([
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: "Delete Location",
string: environment.strings.BusinessLocationSetup_DeleteLocation,
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
textColor: environment.theme.list.itemDestructiveColor
)),

View File

@ -108,12 +108,11 @@ final class ChatbotSearchResultItemComponent: Component {
self.addButton = addButton
}
//TODO:localize
addButtonSize = addButton.update(
transition: addButtonTransition,
component: AnyComponent(PlainButtonComponent(
content: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(string: "ADD", font: Font.semibold(15.0), textColor: component.theme.list.itemCheckColors.foregroundColor))
text: .plain(NSAttributedString(string: component.strings.ChatbotSetup_BotAddAction, font: Font.semibold(15.0), textColor: component.theme.list.itemCheckColors.foregroundColor))
)),
background: AnyComponent(RoundedRectangle(color: component.theme.list.itemCheckColors.fillColor, cornerRadius: nil)),
effectAlignment: .center,
@ -159,7 +158,6 @@ final class ChatbotSearchResultItemComponent: Component {
self.removeButton = removeButton
}
//TODO:localize
removeButtonSize = removeButton.update(
transition: removeButtonTransition,
component: AnyComponent(PlainButtonComponent(
@ -205,11 +203,11 @@ final class ChatbotSearchResultItemComponent: Component {
case .searching, .notFound:
isTextVisible = false
titleValue = "AAAAAAAAA"
subtitleValue = "bot" //TODO:localize
subtitleValue = component.strings.Bot_GenericBotStatus
case let .found(peer, _):
isTextVisible = true
titleValue = peer.displayTitle(strings: component.strings, displayOrder: .firstLast)
subtitleValue = "bot"
subtitleValue = component.strings.Bot_GenericBotStatus
}
let titleSize = self.titleLabel.update(
@ -298,11 +296,10 @@ final class ChatbotSearchResultItemComponent: Component {
notFoundLabel = ComponentView()
self.notFoundLabel = notFoundLabel
}
//TODO:localize
let notFoundLabelSize = notFoundLabel.update(
transition: .immediate,
component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(string: "Chatbot not found", font: Font.regular(13.0), textColor: component.theme.list.itemSecondaryTextColor))
text: .plain(NSAttributedString(string: component.strings.ChatbotSetup_BotNotFoundStatus, font: Font.regular(13.0), textColor: component.theme.list.itemSecondaryTextColor))
)),
environment: {},
containerSize: CGSize(width: maxTextWidth, height: 100.0)

View File

@ -296,7 +296,7 @@ final class ChatbotSetupScreenComponent: Component {
}
private func openAdditionalPeerListSetup() {
guard let component = self.component else {
guard let component = self.component, let environment = self.environment else {
return
}
@ -312,19 +312,19 @@ final class ChatbotSetupScreenComponent: Component {
id: self.hasAccessToAllChatsByDefault ? AdditionalCategoryId.existingChats.rawValue : AdditionalCategoryId.newChats.rawValue,
icon: generateAvatarImage(size: CGSize(width: 40.0, height: 40.0), icon: generateTintedImage(image: UIImage(bundleImageName: self.hasAccessToAllChatsByDefault ? "Chat List/Filters/Chats" : "Chat List/Filters/NewChats"), color: .white), cornerRadius: 12.0, color: .purple),
smallIcon: generateAvatarImage(size: CGSize(width: 22.0, height: 22.0), icon: generateTintedImage(image: UIImage(bundleImageName: self.hasAccessToAllChatsByDefault ? "Chat List/Filters/Chats" : "Chat List/Filters/NewChats"), color: .white), iconScale: 0.6, cornerRadius: 6.0, circleCorners: true, color: .purple),
title: self.hasAccessToAllChatsByDefault ? "Existing Chats" : "New Chats"
title: self.hasAccessToAllChatsByDefault ? environment.strings.BusinessMessageSetup_Recipients_CategoryExistingChats : environment.strings.BusinessMessageSetup_Recipients_CategoryNewChats
),
ChatListNodeAdditionalCategory(
id: AdditionalCategoryId.contacts.rawValue,
icon: generateAvatarImage(size: CGSize(width: 40.0, height: 40.0), icon: generateTintedImage(image: UIImage(bundleImageName: "Chat List/Filters/Contact"), color: .white), cornerRadius: 12.0, color: .blue),
smallIcon: generateAvatarImage(size: CGSize(width: 22.0, height: 22.0), icon: generateTintedImage(image: UIImage(bundleImageName: "Chat List/Filters/Contact"), color: .white), iconScale: 0.6, cornerRadius: 6.0, circleCorners: true, color: .blue),
title: "Contacts"
title: environment.strings.BusinessMessageSetup_Recipients_CategoryContacts
),
ChatListNodeAdditionalCategory(
id: AdditionalCategoryId.nonContacts.rawValue,
icon: generateAvatarImage(size: CGSize(width: 40.0, height: 40.0), icon: generateTintedImage(image: UIImage(bundleImageName: "Chat List/Filters/User"), color: .white), cornerRadius: 12.0, color: .yellow),
smallIcon: generateAvatarImage(size: CGSize(width: 22.0, height: 22.0), icon: generateTintedImage(image: UIImage(bundleImageName: "Chat List/Filters/User"), color: .white), iconScale: 0.6, cornerRadius: 6.0, circleCorners: true, color: .yellow),
title: "Non-Contacts"
title: environment.strings.BusinessMessageSetup_Recipients_CategoryNonContacts
)
]
var selectedCategories = Set<Int>()
@ -341,10 +341,9 @@ final class ChatbotSetupScreenComponent: Component {
}
}
//TODO:localize
let controller = component.context.sharedContext.makeContactMultiselectionController(ContactMultiselectionControllerParams(context: component.context, mode: .chatSelection(ContactMultiselectionControllerMode.ChatSelection(
title: self.hasAccessToAllChatsByDefault ? "Exclude Chats" : "Include Chats",
searchPlaceholder: "Search chats",
title: self.hasAccessToAllChatsByDefault ? environment.strings.BusinessMessageSetup_Recipients_ExcludeSearchTitle : environment.strings.BusinessMessageSetup_Recipients_IncludeSearchTitle,
searchPlaceholder: environment.strings.ChatListFilter_AddChatsSearchPlaceholder,
selectedChats: Set(self.additionalPeerList.peers.map(\.peer.id)),
additionalCategories: ContactMultiselectionControllerAdditionalCategories(categories: additionalCategories, selectedCategories: selectedCategories),
chatListFilters: nil,
@ -480,11 +479,10 @@ final class ChatbotSetupScreenComponent: Component {
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
//TODO:localize
let navigationTitleSize = self.navigationTitle.update(
transition: transition,
component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(string: "Chatbots", font: Font.semibold(17.0), textColor: environment.theme.rootController.navigationBar.primaryTextColor)),
text: .plain(NSAttributedString(string: environment.strings.ChatbotSetup_Title, font: Font.semibold(17.0), textColor: environment.theme.rootController.navigationBar.primaryTextColor)),
horizontalAlignment: .center
)),
environment: {},
@ -532,8 +530,7 @@ final class ChatbotSetupScreenComponent: Component {
contentHeight += 129.0
//TODO:localize
let subtitleString = NSMutableAttributedString(attributedString: parseMarkdownIntoAttributedString("Add a bot to your account to help you automatically process and respond to the messages you receive. [Learn More >]()", attributes: MarkdownAttributes(
let subtitleString = NSMutableAttributedString(attributedString: parseMarkdownIntoAttributedString(environment.strings.ChatbotSetup_Text, attributes: MarkdownAttributes(
body: MarkdownAttributeSet(font: Font.regular(15.0), textColor: environment.theme.list.freeTextColor),
bold: MarkdownAttributeSet(font: Font.semibold(15.0), textColor: environment.theme.list.freeTextColor),
link: MarkdownAttributeSet(font: Font.regular(15.0), textColor: environment.theme.list.itemAccentColor),
@ -548,7 +545,6 @@ final class ChatbotSetupScreenComponent: Component {
subtitleString.addAttribute(.attachment, value: chevronImage, range: NSRange(range, in: subtitleString.string))
}
//TODO:localize
let subtitleSize = self.subtitle.update(
transition: .immediate,
component: AnyComponent(BalancedTextComponent(
@ -565,11 +561,10 @@ final class ChatbotSetupScreenComponent: Component {
}
},
tapAction: { [weak self] _, _ in
guard let self, let component = self.component else {
guard let self, let component = self.component, let environment = self.environment else {
return
}
//TODO:localize
component.context.sharedContext.applicationBindings.openUrl("https://telegram.org")
component.context.sharedContext.applicationBindings.openUrl(environment.strings.ChatbotSetup_TextLink)
}
)),
environment: {},
@ -593,7 +588,7 @@ final class ChatbotSetupScreenComponent: Component {
theme: environment.theme,
initialText: "",
resetText: resetQueryText.flatMap { ListTextFieldItemComponent.ResetText(value: $0) },
placeholder: "Bot Username",
placeholder: environment.strings.ChatbotSetup_BotSearchPlaceholder,
autocapitalizationType: .none,
autocorrectionType: .no,
updated: { [weak self] value in
@ -649,7 +644,6 @@ final class ChatbotSetupScreenComponent: Component {
))))
}
//TODO:localize
let nameSectionSize = self.nameSection.update(
transition: transition,
component: AnyComponent(ListSectionComponent(
@ -657,7 +651,7 @@ final class ChatbotSetupScreenComponent: Component {
header: nil,
footer: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: "Enter the username or URL of the Telegram bot that you want to automatically process your chats.",
string: environment.strings.ChatbotSetup_BotSectionFooter,
font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize),
textColor: environment.theme.list.freeTextColor
)),
@ -678,14 +672,13 @@ final class ChatbotSetupScreenComponent: Component {
contentHeight += nameSectionSize.height
contentHeight += sectionSpacing
//TODO:localize
let accessSectionSize = self.accessSection.update(
transition: transition,
component: AnyComponent(ListSectionComponent(
theme: environment.theme,
header: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: "CHATS ACCESSIBLE FOR THE BOT",
string: environment.strings.ChatbotSetup_RecipientsSectionHeader,
font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize),
textColor: environment.theme.list.freeTextColor
)),
@ -698,7 +691,7 @@ final class ChatbotSetupScreenComponent: Component {
title: AnyComponent(VStack([
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: "All 1-to-1 Chats Except...",
string: environment.strings.BusinessMessageSetup_RecipientsOptionAllExcept,
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
textColor: environment.theme.list.itemPrimaryTextColor
)),
@ -728,7 +721,7 @@ final class ChatbotSetupScreenComponent: Component {
title: AnyComponent(VStack([
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: "Only Selected Chats",
string: environment.strings.BusinessMessageSetup_RecipientsOptionOnly,
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
textColor: environment.theme.list.itemPrimaryTextColor
)),
@ -774,7 +767,7 @@ final class ChatbotSetupScreenComponent: Component {
title: AnyComponent(VStack([
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: self.hasAccessToAllChatsByDefault ? "Exclude Chats..." : "Select Chats...",
string: self.hasAccessToAllChatsByDefault ? environment.strings.BusinessMessageSetup_Recipients_AddExclude : environment.strings.BusinessMessageSetup_Recipients_AddInclude,
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
textColor: environment.theme.list.itemAccentColor
)),
@ -797,23 +790,22 @@ final class ChatbotSetupScreenComponent: Component {
let title: String
let icon: String
let color: AvatarBackgroundColor
//TODO:localize
switch category {
case .newChats:
title = "New Chats"
icon = "Chat List/Filters/Contact"
title = environment.strings.BusinessMessageSetup_Recipients_CategoryNewChats
icon = "Chat List/Filters/NewChats"
color = .purple
case .existingChats:
title = "Existing Chats"
icon = "Chat List/Filters/Contact"
title = environment.strings.BusinessMessageSetup_Recipients_CategoryExistingChats
icon = "Chat List/Filters/Chats"
color = .purple
case .contacts:
title = "Contacts"
title = environment.strings.BusinessMessageSetup_Recipients_CategoryContacts
icon = "Chat List/Filters/Contact"
color = .blue
case .nonContacts:
title = "Non-Contacts"
icon = "Chat List/Filters/Contact"
title = environment.strings.BusinessMessageSetup_Recipients_CategoryNonContacts
icon = "Chat List/Filters/User"
color = .yellow
}
excludedSectionItems.append(AnyComponentWithIdentity(id: category, component: AnyComponent(PeerListItemComponent(
@ -847,7 +839,7 @@ final class ChatbotSetupScreenComponent: Component {
sideInset: 0.0,
title: peer.peer.displayTitle(strings: environment.strings, displayOrder: .firstLast),
peer: peer.peer,
subtitle: peer.isContact ? "contact" : "non-contact",
subtitle: peer.isContact ? environment.strings.ChatList_PeerTypeContact : environment.strings.ChatList_PeerTypeNonContact,
subtitleAccessory: .none,
presence: nil,
selectionState: .none,
@ -857,14 +849,13 @@ final class ChatbotSetupScreenComponent: Component {
))))
}
//TODO:localize
let excludedSectionSize = self.excludedSection.update(
transition: transition,
component: AnyComponent(ListSectionComponent(
theme: environment.theme,
header: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: self.hasAccessToAllChatsByDefault ? "EXCLUDED CHATS" : "INCLUDED CHATS",
string: self.hasAccessToAllChatsByDefault ? environment.strings.BusinessMessageSetup_Recipients_ExcludedSectionHeader : environment.strings.BusinessMessageSetup_Recipients_IncludedSectionHeader,
font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize),
textColor: environment.theme.list.freeTextColor
)),
@ -872,7 +863,7 @@ final class ChatbotSetupScreenComponent: Component {
)),
footer: AnyComponent(MultilineTextComponent(
text: .markdown(
text: self.hasAccessToAllChatsByDefault ? "Select chats or entire chat categories which the bot **WILL NOT** have access to." : "Select chats or entire chat categories which the bot **WILL** have access to.",
text: self.hasAccessToAllChatsByDefault ? environment.strings.ChatbotSetup_Recipients_ExcludedSectionFooter : environment.strings.ChatbotSetup_Recipients_IncludedSectionFooter,
attributes: MarkdownAttributes(
body: MarkdownAttributeSet(font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize), textColor: environment.theme.list.freeTextColor),
bold: MarkdownAttributeSet(font: Font.semibold(presentationData.listsFontSize.itemListBaseHeaderFontSize), textColor: environment.theme.list.freeTextColor),
@ -899,14 +890,13 @@ final class ChatbotSetupScreenComponent: Component {
contentHeight += excludedSectionSize.height
contentHeight += sectionSpacing
//TODO:localize
let permissionsSectionSize = self.permissionsSection.update(
transition: transition,
component: AnyComponent(ListSectionComponent(
theme: environment.theme,
header: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: "BOT PERMISSIONS",
string: environment.strings.ChatbotSetup_PermissionsSectionHeader,
font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize),
textColor: environment.theme.list.freeTextColor
)),
@ -914,7 +904,7 @@ final class ChatbotSetupScreenComponent: Component {
)),
footer: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: "The bot will be able to view all new incoming messages, but not the messages that had been sent before you added the bot.",
string: environment.strings.ChatbotSetup_PermissionsSectionFooter,
font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize),
textColor: environment.theme.list.freeTextColor
)),
@ -926,7 +916,7 @@ final class ChatbotSetupScreenComponent: Component {
title: AnyComponent(VStack([
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: "Reply to Messages",
string: environment.strings.ChatbotSetup_Permission_ReplyToMessages,
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
textColor: environment.theme.list.itemPrimaryTextColor
)),

View File

@ -239,8 +239,7 @@ public final class QuickReplyNameAlertContentNode: AlertContentNode {
self.subtext = subtext
self.titleFont = titleFont
//TODO:localize
self.inputFieldNode = PromptInputFieldNode(theme: ptheme, placeholder: "Shortcut", characterLimit: characterLimit)
self.inputFieldNode = PromptInputFieldNode(theme: ptheme, placeholder: strings.QuickReply_ShortcutPlaceholder, characterLimit: characterLimit)
self.inputFieldNode.text = value ?? ""
self.actionNodesSeparator = ASDisplayNode()

View File

@ -39,8 +39,7 @@ public class TimezoneSelectionScreen: ViewController {
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
//TODO:localize
self.title = "Time Zone"
self.title = self.presentationData.strings.TimeZoneSelection_Title
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil)

View File

@ -94,8 +94,8 @@ public final class SliderComponent: Component {
sliderView.minimumValue = 0.0
sliderView.startValue = 0.0
sliderView.disablesInteractiveTransitionGestureRecognizer = true
sliderView.maximumValue = CGFloat(component.valueCount)
sliderView.positionsCount = component.valueCount + 1
sliderView.maximumValue = CGFloat(component.valueCount - 1)
sliderView.positionsCount = component.valueCount
sliderView.useLinesForPositions = true
sliderView.backgroundColor = nil

View File

@ -723,25 +723,24 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
switch customChatContents.kind {
case let .quickReplyMessageInput(_, shortcutType):
if let historyView = strongSelf.chatDisplayNode.historyNode.originalHistoryView, historyView.entries.isEmpty {
//TODO:localize
let titleString: String
let textString: String
switch shortcutType {
case .generic:
titleString = "Remove Shortcut"
textString = "You didn't create a quick reply message. Exiting will remove the shortcut."
titleString = strongSelf.presentationData.strings.QuickReply_ChatRemoveGeneric_Title
textString = strongSelf.presentationData.strings.QuickReply_ChatRemoveGeneric_Text
case .greeting:
titleString = "Remove Greeting Message"
textString = "You didn't create a greeting message. Exiting will remove it."
titleString = strongSelf.presentationData.strings.QuickReply_ChatRemoveGreetingMessage_Title
textString = strongSelf.presentationData.strings.QuickReply_ChatRemoveGreetingMessage_Text
case .away:
titleString = "Remove Away Message"
textString = "You didn't create an away message. Exiting will remove it."
titleString = strongSelf.presentationData.strings.QuickReply_ChatRemoveAwayMessage_Title
textString = strongSelf.presentationData.strings.QuickReply_ChatRemoveAwayMessage_Text
}
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: titleString, text: textString, actions: [
TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {}),
TextAlertAction(type: .defaultAction, title: "Remove", action: { [weak strongSelf] in
TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.QuickReply_ChatRemoveGeneric_DeleteAction, action: { [weak strongSelf] in
strongSelf?.dismiss()
})
]), in: .window(.root))
@ -6204,7 +6203,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self.reportIrrelvantGeoNoticePromise.set(.single(nil))
self.titleDisposable.set(nil)
//TODO:localize
if case let .customChatContents(customChatContents) = self.subject {
switch customChatContents.kind {
case let .quickReplyMessageInput(shortcut, shortcutType):
@ -6212,13 +6210,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
case .generic:
self.chatTitleView?.titleContent = .custom("\(shortcut)", nil, false)
case .greeting:
self.chatTitleView?.titleContent = .custom("Greeting Message", nil, false)
self.chatTitleView?.titleContent = .custom(self.presentationData.strings.QuickReply_TitleGreetingMessage, nil, false)
case .away:
self.chatTitleView?.titleContent = .custom("Away Message", nil, false)
self.chatTitleView?.titleContent = .custom(self.presentationData.strings.QuickReply_TitleAwayMessage, nil, false)
}
}
} else {
self.chatTitleView?.titleContent = .custom("Messages", nil, false)
self.chatTitleView?.titleContent = .custom(" ", nil, false)
}
if !self.didSetChatLocationInfoReady {

View File

@ -11,13 +11,12 @@ import QuickReplyNameAlertController
extension ChatControllerImpl {
func editChat() {
//TODO:localize
if case let .customChatContents(customChatContents) = self.subject, case let .quickReplyMessageInput(currentValue, shortcutType) = customChatContents.kind, case .generic = shortcutType {
var completion: ((String?) -> Void)?
let alertController = quickReplyNameAlertController(
context: self.context,
text: "Edit Shortcut",
subtext: "Add a new name for your shortcut.",
text: self.presentationData.strings.QuickReply_EditShortcutTitle,
subtext: self.presentationData.strings.QuickReply_EditShortcutText,
value: currentValue,
characterLimit: 32,
apply: { value in
@ -45,7 +44,7 @@ extension ChatControllerImpl {
if shortcutMessageList.items.contains(where: { $0.shortcut.lowercased() == value.lowercased() }) {
if let contentNode = alertController?.contentNode as? QuickReplyNameAlertContentNode {
contentNode.setErrorText(errorText: "Shortcut with that name already exists")
contentNode.setErrorText(errorText: self.presentationData.strings.QuickReply_ShortcutExistsInlineError)
}
} else {
self.chatTitleView?.titleContent = .custom("\(value)", nil, false)

View File

@ -736,28 +736,25 @@ private final class ChatEmptyNodeCloudChatContent: ASDisplayNode, ChatEmptyNodeC
switch shortcutType {
case .generic:
iconName = "Chat/Empty Chat/QuickReplies"
//TODO:localize
centerText = false
titleString = "New Quick Reply"
titleString = interfaceState.strings.Chat_EmptyState_QuickReply_Title
strings = [
"· Enter a message below that will be sent in chats when you type \"**/\(shortcut)\"**.",
"· You can access Quick Replies in any chat by typing \"/\" or using the Attachment menu."
interfaceState.strings.Chat_EmptyState_QuickReply_Text1(shortcut).string,
interfaceState.strings.Chat_EmptyState_QuickReply_Text2
]
case .greeting:
iconName = "Chat/Empty Chat/GreetingShortcut"
//TODO:localize
centerText = true
titleString = "New Greeting Message"
titleString = interfaceState.strings.EmptyState_GreetingMessage_Title
strings = [
"Create greetings that will be automatically sent to new customers"
interfaceState.strings.EmptyState_GreetingMessage_Text
]
case .away:
iconName = "Chat/Empty Chat/AwayShortcut"
//TODO:localize
centerText = true
titleString = "New Away Message"
titleString = interfaceState.strings.EmptyState_AwayMessage_Title
strings = [
"Add messages that are automatically sent when you are off."
interfaceState.strings.EmptyState_AwayMessage_Text
]
}
}

View File

@ -243,8 +243,7 @@ private func updatedContextQueryResultStateForQuery(context: AccountContext, pee
return false
}
var sortedCommands = filteredCommands.map(ChatInputTextCommand.command)
if !shortcuts.isEmpty {
sortedCommands.removeAll()
if !shortcuts.isEmpty && sortedCommands.isEmpty {
for shortcut in shortcuts {
sortedCommands.append(.shortcut(shortcut))
}

View File

@ -106,8 +106,7 @@ final class ChatRestrictedInputPanelNode: ChatInputPanelNode {
case .quickReplyMessageInput:
displayCount = 20
}
//TODO:localize
self.textNode.attributedText = NSAttributedString(string: "Limit of \(displayCount) messages reached", font: Font.regular(13.0), textColor: interfaceState.theme.chat.inputPanel.secondaryTextColor)
self.textNode.attributedText = NSAttributedString(string: interfaceState.strings.Chat_QuickReplyMessageLimitReachedText(Int32(displayCount)), font: Font.regular(13.0), textColor: interfaceState.theme.chat.inputPanel.secondaryTextColor)
}
self.buttonNode.isUserInteractionEnabled = isUserInteractionEnabled

View File

@ -1843,16 +1843,15 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate, Ch
}
}
if case let .customChatContents(customChatContents) = interfaceState.subject {
//TODO:localize
switch customChatContents.kind {
case let .quickReplyMessageInput(_, shortcutType):
switch shortcutType {
case .generic:
placeholder = "Add quick reply..."
placeholder = interfaceState.strings.Chat_Placeholder_QuickReply
case .greeting:
placeholder = "Add greeting message..."
placeholder = interfaceState.strings.Chat_Placeholder_GreetingMessage
case .away:
placeholder = "Add away message..."
placeholder = interfaceState.strings.Chat_Placeholder_AwayMessage
}
}
}

View File

@ -78,8 +78,7 @@ private struct CommandChatInputContextPanelEntry: Comparable, Identifiable {
func item(context: AccountContext, presentationData: PresentationData, commandSelected: @escaping (ChatInputTextCommand, Bool) -> Void, openEditShortcuts: @escaping () -> Void) -> ListViewItem {
switch self.content {
case .editShortcuts:
//TODO:localzie
return VerticalListContextResultsChatInputPanelButtonItem(theme: presentationData.theme, style: .round, title: "Edit Quick Replies", pressed: {
return VerticalListContextResultsChatInputPanelButtonItem(theme: presentationData.theme, style: .round, title: presentationData.strings.Chat_CommandList_EditQuickReplies, pressed: {
openEditShortcuts()
})
case let .command(command):

View File

@ -285,8 +285,7 @@ final class EditAccessoryPanelNode: AccessoryPanelNode {
let titleString: String
if let message, message.id.namespace == Namespaces.Message.QuickReplyCloud {
//TODO:localize
titleString = "Edit Quick Reply"
titleString = self.strings.Conversation_EditingQuickReplyPanelTitle
} else if canEditMedia {
titleString = isPhoto ? self.strings.Conversation_EditingPhotoPanelTitle : self.strings.Conversation_EditingCaptionPanelTitle
} else {