diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index 409c370380..cd196c2e37 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -197,6 +197,11 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController } } + private let hasPendingStoriesPromise = ValuePromise(false, ignoreRepeated: true) + public var hasPendingStories: Signal { + return self.hasPendingStoriesPromise.get() + } + private var storyProgressDisposable: Disposable? private var storySubscriptionsDisposable: Disposable? private var preloadStorySubscriptionsDisposable: Disposable? @@ -1956,6 +1961,8 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController } self.maybeDisplayStoryTooltip() }) + + self.hasPendingStoriesPromise.set(rawStoryArchiveSubscriptions.accountItem?.hasPending ?? false) }) } } diff --git a/submodules/TelegramStringFormatting/Sources/PresenceStrings.swift b/submodules/TelegramStringFormatting/Sources/PresenceStrings.swift index f69fc0775a..c563c5da65 100644 --- a/submodules/TelegramStringFormatting/Sources/PresenceStrings.swift +++ b/submodules/TelegramStringFormatting/Sources/PresenceStrings.swift @@ -362,6 +362,37 @@ public func stringForRelativeLiveLocationUpdateTimestamp(strings: PresentationSt } } +private func monthAtIndex(_ index: Int, strings: PresentationStrings) -> String { + switch index { + case 0: + return strings.Month_GenJanuary + case 1: + return strings.Month_GenFebruary + case 2: + return strings.Month_GenMarch + case 3: + return strings.Month_GenApril + case 4: + return strings.Month_GenMay + case 5: + return strings.Month_GenJune + case 6: + return strings.Month_GenJuly + case 7: + return strings.Month_GenAugust + case 8: + return strings.Month_GenSeptember + case 9: + return strings.Month_GenOctober + case 10: + return strings.Month_GenNovember + case 11: + return strings.Month_GenDecember + default: + return "" + } +} + public func stringForRelativeActivityTimestamp(strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, preciseTime: Bool = false, relativeTimestamp: Int32, relativeTo timestamp: Int32) -> String { let difference = timestamp - relativeTimestamp if difference < 60 { @@ -400,6 +431,55 @@ public func stringForRelativeActivityTimestamp(strings: PresentationStrings, dat } } +public func stringForStoryActivityTimestamp(strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, preciseTime: Bool = false, relativeTimestamp: Int32, relativeTo timestamp: Int32) -> String { + let difference = timestamp - relativeTimestamp + if difference < 60 { + return strings.Time_JustNow + } else if difference < 60 * 60 { + let minutes = difference / 60 + return strings.Time_MinutesAgo(minutes) + } else { + var t: time_t = time_t(relativeTimestamp) + var timeinfo: tm = tm() + localtime_r(&t, &timeinfo) + + var now: time_t = time_t(timestamp) + var timeinfoNow: tm = tm() + localtime_r(&now, &timeinfoNow) + + if timeinfo.tm_year != timeinfoNow.tm_year { + return strings.Time_AtDate(stringForTimestamp(day: timeinfo.tm_mday, month: timeinfo.tm_mon + 1, year: timeinfo.tm_year, dateTimeFormat: dateTimeFormat)).string + } + + let dayDifference = timeinfo.tm_yday - timeinfoNow.tm_yday + if dayDifference == 0 || dayDifference == -1 { + let day: RelativeTimestampFormatDay + if dayDifference == 0 { + let minutes = difference / (60 * 60) + return strings.Time_HoursAgo(minutes) + } else { + day = .yesterday + } + return humanReadableStringForTimestamp(strings: strings, day: day, dateTimeFormat: dateTimeFormat, hours: timeinfo.tm_hour, minutes: timeinfo.tm_min).string + } else if preciseTime { + let yearDate: String + if timeinfo.tm_year == timeinfoNow.tm_year { + if timeinfo.tm_yday == timeinfoNow.tm_yday { + yearDate = strings.Weekday_Today + } else { + yearDate = strings.Date_ChatDateHeader(monthAtIndex(Int(timeinfo.tm_mon), strings: strings), "\(timeinfo.tm_mday)").string + } + } else { + yearDate = strings.Date_ChatDateHeaderYear(monthAtIndex(Int(timeinfo.tm_mon), strings: strings), "\(timeinfo.tm_mday)", "\(1900 + timeinfo.tm_year)").string + } + + return strings.Time_AtPreciseDate(yearDate, stringForShortTimestamp(hours: timeinfo.tm_hour, minutes: timeinfo.tm_min, dateTimeFormat: dateTimeFormat)).string + } else { + return strings.Time_AtDate(stringForTimestamp(day: timeinfo.tm_mday, month: timeinfo.tm_mon + 1, year: timeinfo.tm_year, dateTimeFormat: dateTimeFormat)).string + } + } +} + public func stringAndActivityForUserPresence(strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, presence: EnginePeer.Presence, relativeTo timestamp: Int32, expanded: Bool = false) -> (String, Bool) { switch presence.status { case let .present(statusTimestamp): diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryAuthorInfoComponent.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryAuthorInfoComponent.swift index f2dd959ca4..a6440e81d4 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryAuthorInfoComponent.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryAuthorInfoComponent.swift @@ -87,7 +87,7 @@ final class StoryAuthorInfoComponent: Component { } let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970) - var subtitle = stringForRelativeActivityTimestamp(strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, preciseTime: true, relativeTimestamp: component.timestamp, relativeTo: timestamp) + var subtitle = stringForStoryActivityTimestamp(strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, preciseTime: true, relativeTimestamp: component.timestamp, relativeTo: timestamp) if component.isEdited { subtitle.append(" • ") diff --git a/submodules/TelegramUI/Sources/TelegramRootController.swift b/submodules/TelegramUI/Sources/TelegramRootController.swift index 2784378cb8..6886d76c58 100644 --- a/submodules/TelegramUI/Sources/TelegramRootController.swift +++ b/submodules/TelegramUI/Sources/TelegramRootController.swift @@ -368,17 +368,38 @@ public final class TelegramRootController: NavigationController, TelegramRootCon } } - if let chatListController = self.chatListController as? ChatListControllerImpl { - chatListController.scrollToStories() + let completionImpl: () -> Void = { [weak self] in + guard let self else { + return + } + + if let chatListController = self.chatListController as? ChatListControllerImpl { + let _ = (chatListController.hasPendingStories + |> filter { $0 } + |> take(1) + |> timeout(0.25, queue: .mainQueue(), alternate: .single(true)) + |> deliverOnMainQueue).start(completed: { [weak chatListController] in + chatListController?.scrollToStories() + Queue.mainQueue().justDispatch { + commit({}) + } + }) + } else { + Queue.mainQueue().justDispatch { + commit({}) + } + } + } + + if let _ = self.chatListController as? ChatListControllerImpl { switch mediaResult { case let .image(image, dimensions): if let imageData = compressImageToJPEG(image, quality: 0.7) { let entities = generateChatInputTextEntities(caption) Logger.shared.log("MediaEditor", "Calling uploadStory for image, randomId \(randomId)") self.context.engine.messages.uploadStory(media: .image(dimensions: dimensions, data: imageData, stickers: stickers), text: caption.string, entities: entities, pin: privacy.pin, privacy: privacy.privacy, isForwardingDisabled: privacy.isForwardingDisabled, period: privacy.timeout, randomId: randomId) - Queue.mainQueue().justDispatch { - commit({}) - } + + completionImpl() } case let .video(content, firstFrameImage, values, duration, dimensions): let adjustments: VideoMediaResourceAdjustments @@ -408,9 +429,8 @@ public final class TelegramRootController: NavigationController, TelegramRootCon Logger.shared.log("MediaEditor", "Calling uploadStory for video, randomId \(randomId)") let entities = generateChatInputTextEntities(caption) self.context.engine.messages.uploadStory(media: .video(dimensions: dimensions, duration: duration, resource: resource, firstFrameFile: firstFrameFile, stickers: stickers), text: caption.string, entities: entities, pin: privacy.pin, privacy: privacy.privacy, isForwardingDisabled: privacy.isForwardingDisabled, period: privacy.timeout, randomId: randomId) - Queue.mainQueue().justDispatch { - commit({}) - } + + completionImpl() } } }