Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios

This commit is contained in:
Ilya Laktyushin 2020-10-30 21:37:58 +04:00
commit 5547abb639
117 changed files with 3462 additions and 2868 deletions

1
.gitignore vendored
View File

@ -27,6 +27,7 @@ DerivedData
buck-out/* buck-out/*
.buckd/* .buckd/*
tools/buck tools/buck
tools/bazel
AppBinary.xcworkspace/* AppBinary.xcworkspace/*
Project.xcodeproj/* Project.xcodeproj/*
Watch/Watch.xcodeproj/* Watch/Watch.xcodeproj/*

View File

@ -48,7 +48,7 @@ BAZEL=$(shell which bazel)
ifneq ($(BAZEL_HTTP_CACHE_URL),) ifneq ($(BAZEL_HTTP_CACHE_URL),)
export BAZEL_CACHE_FLAGS=\ export BAZEL_CACHE_FLAGS=\
--remote_cache="$(BAZEL_HTTP_CACHE_URL)" --remote_cache="$(BAZEL_HTTP_CACHE_URL)" --experimental_remote_downloader="$(BAZEL_HTTP_CACHE_URL)"
else ifneq ($(BAZEL_CACHE_DIR),) else ifneq ($(BAZEL_CACHE_DIR),)
export BAZEL_CACHE_FLAGS=\ export BAZEL_CACHE_FLAGS=\
--disk_cache="${BAZEL_CACHE_DIR}" --disk_cache="${BAZEL_CACHE_DIR}"
@ -57,6 +57,9 @@ endif
BAZEL_COMMON_FLAGS=\ BAZEL_COMMON_FLAGS=\
--announce_rc \ --announce_rc \
--features=swift.use_global_module_cache \ --features=swift.use_global_module_cache \
--features=swift.split_derived_files_generation \
--features=swift.skip_function_bodies_for_derived_files \
--jobs=${CORE_COUNT}
BAZEL_DEBUG_FLAGS=\ BAZEL_DEBUG_FLAGS=\
--features=swift.enable_batch_mode \ --features=swift.enable_batch_mode \
@ -403,6 +406,7 @@ bazel_app_debug_arm64:
bazel_app_arm64: bazel_app_arm64:
APP_VERSION="${APP_VERSION}" \ APP_VERSION="${APP_VERSION}" \
BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \ BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \
BAZEL_HTTP_CACHE_URL="${BAZEL_HTTP_CACHE_URL}" \
build-system/prepare-build.sh Telegram distribution build-system/prepare-build.sh Telegram distribution
"${BAZEL}" build Telegram/Telegram ${BAZEL_CACHE_FLAGS} ${BAZEL_COMMON_FLAGS} ${BAZEL_OPT_FLAGS} \ "${BAZEL}" build Telegram/Telegram ${BAZEL_CACHE_FLAGS} ${BAZEL_COMMON_FLAGS} ${BAZEL_OPT_FLAGS} \
-c opt \ -c opt \
@ -414,24 +418,58 @@ bazel_app_arm64:
--output_groups=+dsyms \ --output_groups=+dsyms \
--verbose_failures --verbose_failures
bazel_app_armv7:
APP_VERSION="${APP_VERSION}" \
BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \
BAZEL_HTTP_CACHE_URL="${BAZEL_HTTP_CACHE_URL}" \
build-system/prepare-build.sh Telegram distribution
"${BAZEL}" build Telegram/Telegram ${BAZEL_CACHE_FLAGS} ${BAZEL_COMMON_FLAGS} ${BAZEL_OPT_FLAGS} \
-c opt \
--ios_multi_cpus=armv7 \
--watchos_cpus=armv7k,arm64_32 \
--objc_enable_binary_stripping=true \
--features=dead_strip \
--apple_generate_dsym \
--output_groups=+dsyms \
--verbose_failures
bazel_app:
APP_VERSION="${APP_VERSION}" \
BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \
BAZEL_HTTP_CACHE_URL="${BAZEL_HTTP_CACHE_URL}" \
build-system/prepare-build.sh Telegram distribution
"${BAZEL}" build Telegram/Telegram ${BAZEL_CACHE_FLAGS} ${BAZEL_COMMON_FLAGS} ${BAZEL_OPT_FLAGS} \
-c opt \
--ios_multi_cpus=armv7,arm64 \
--watchos_cpus=armv7k,arm64_32 \
--objc_enable_binary_stripping=true \
--features=dead_strip \
--apple_generate_dsym \
--output_groups=+dsyms \
--verbose_failures
bazel_prepare_development_build: bazel_prepare_development_build:
APP_VERSION="${APP_VERSION}" \ APP_VERSION="${APP_VERSION}" \
BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \ BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \
BAZEL_HTTP_CACHE_URL="${BAZEL_HTTP_CACHE_URL}" \
build-system/prepare-build.sh Telegram development build-system/prepare-build.sh Telegram development
bazel_project: kill_xcode bazel_prepare_development_build bazel_project: kill_xcode bazel_prepare_development_build
APP_VERSION="${APP_VERSION}" \ APP_VERSION="${APP_VERSION}" \
BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \ BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \
BAZEL_HTTP_CACHE_URL="${BAZEL_HTTP_CACHE_URL}" \
build-system/generate-xcode-project.sh Telegram build-system/generate-xcode-project.sh Telegram
bazel_soft_project: bazel_prepare_development_build bazel_soft_project: bazel_prepare_development_build
APP_VERSION="${APP_VERSION}" \ APP_VERSION="${APP_VERSION}" \
BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \ BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \
BAZEL_HTTP_CACHE_URL="${BAZEL_HTTP_CACHE_URL}" \
build-system/generate-xcode-project.sh Telegram build-system/generate-xcode-project.sh Telegram
bazel_opt_project: bazel_prepare_development_build bazel_opt_project: bazel_prepare_development_build
APP_VERSION="${APP_VERSION}" \ APP_VERSION="${APP_VERSION}" \
BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \ BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \
BAZEL_HTTP_CACHE_URL="${BAZEL_HTTP_CACHE_URL}" \
GENERATE_OPT_PROJECT=1 \ GENERATE_OPT_PROJECT=1 \
build-system/generate-xcode-project.sh Telegram build-system/generate-xcode-project.sh Telegram

View File

@ -1628,13 +1628,8 @@ ios_application(
":AdditionalInfoPlist", ":AdditionalInfoPlist",
":TelegramInfoIconsPlist", ":TelegramInfoIconsPlist",
], ],
#app_icons = [
# ":DefaultAppIcon",
#],
resources = [ resources = [
":AdditionalIcons", ":AdditionalIcons",
#":DefaultAppIcon",
#":AppIcons",
], ],
frameworks = [ frameworks = [
":MtProtoKitFramework", ":MtProtoKitFramework",
@ -1652,10 +1647,10 @@ ios_application(
], ],
extensions = [ extensions = [
":ShareExtension", ":ShareExtension",
":WidgetExtension",
":NotificationContentExtension", ":NotificationContentExtension",
":NotificationServiceExtension", ":NotificationServiceExtension",
":IntentsExtension", ":IntentsExtension",
":WidgetExtension",
], ],
watch_application = ":TelegramWatchApp", watch_application = ":TelegramWatchApp",
deps = [ deps = [

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.telegram.TelegramHD</string>
</array>
</dict>
</plist>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.ph.telegra.Telegraph</string>
</array>
</dict>
</plist>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.fork.telegram.Telegram-iOS</string>
</array>
</dict>
</plist>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.telegram.Telegram-iOS</string>
</array>
</dict>
</plist>

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array/>
</dict>
</plist>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.telegram.TelegramHD</string>
</array>
</dict>
</plist>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.ph.telegra.Telegraph</string>
</array>
</dict>
</plist>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.fork.telegram.Telegram-iOS</string>
</array>
</dict>
</plist>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.telegram.Telegram-iOS</string>
</array>
</dict>
</plist>

View File

@ -102,7 +102,7 @@ dispatch_block_t fetchImage(BuildConfig *buildConfig, AccountProxyConnection * _
apiEnvironment.langPack = @"ios"; apiEnvironment.langPack = @"ios";
apiEnvironment.layer = @([serialization currentLayer]); apiEnvironment.layer = @([serialization currentLayer]);
apiEnvironment.disableUpdates = true; apiEnvironment.disableUpdates = true;
apiEnvironment = [apiEnvironment withUpdatedLangPackCode:@"en"]; apiEnvironment = [apiEnvironment withUpdatedLangPackCode:@""];
if (proxyConnection != nil) { if (proxyConnection != nil) {
apiEnvironment = [apiEnvironment withUpdatedSocksProxySettings:[[MTSocksProxySettings alloc] initWithIp:proxyConnection.host port:(uint16_t)proxyConnection.port username:proxyConnection.username password:proxyConnection.password secret:proxyConnection.secret]]; apiEnvironment = [apiEnvironment withUpdatedSocksProxySettings:[[MTSocksProxySettings alloc] initWithIp:proxyConnection.host port:(uint16_t)proxyConnection.port username:proxyConnection.username password:proxyConnection.password secret:proxyConnection.secret]];

View File

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.telegram.TelegramHD</string>
</array>
<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)org.telegram.TelegramHD</string>
</array>
</dict>
</plist>

View File

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.ph.telegra.Telegraph</string>
</array>
<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)ph.telegra.Telegraph</string>
</array>
</dict>
</plist>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.fork.telegram.Telegram-iOS</string>
</array>
</dict>
</plist>

View File

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.telegram.Telegram-iOS</string>
</array>
<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)org.telegram.Telegram-iOS</string>
</array>
</dict>
</plist>

View File

@ -56,7 +56,7 @@ func unreadMessages(account: Account) -> Signal<[INMessage], NoError> {
} }
if !isMuted && hasUnread { if !isMuted && hasUnread {
signals.append(account.postbox.aroundMessageHistoryViewForLocation(.peer(index.messageIndex.id.peerId), anchor: .upperBound, count: 10, fixedCombinedReadStates: fixedCombinedReadStates, topTaggedMessageIdNamespaces: Set(), tagMask: nil, namespaces: .not(Namespaces.Message.allScheduled), orderStatistics: .combinedLocation) signals.append(account.postbox.aroundMessageHistoryViewForLocation(.peer(index.messageIndex.id.peerId), anchor: .upperBound, count: 10, fixedCombinedReadStates: fixedCombinedReadStates, topTaggedMessageIdNamespaces: Set(), tagMask: nil, appendMessagesFromTheSameGroup: false, namespaces: .not(Namespaces.Message.allScheduled), orderStatistics: .combinedLocation)
|> take(1) |> take(1)
|> map { view -> [INMessage] in |> map { view -> [INMessage] in
var messages: [INMessage] = [] var messages: [INMessage] = []

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.telegram.TelegramHD</string>
</array>
</dict>
</plist>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.ph.telegra.Telegraph</string>
</array>
</dict>
</plist>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.fork.telegram.Telegram-iOS</string>
</array>
</dict>
</plist>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.telegram.Telegram-iOS</string>
</array>
</dict>
</plist>

View File

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>production</string>
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:telegram.me</string>
<string>applinks:t.me</string>
</array>
<key>com.apple.developer.siri</key>
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.telegram.TelegramHD</string>
</array>
</dict>
</plist>

View File

@ -1,40 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.icloud-services</key>
<array>
<string>CloudDocuments</string>
<string>CloudKit</string>
</array>
<key>com.apple.developer.icloud-container-identifiers</key>
<array>
<string>iCloud.$(CFBundleIdentifier)</string>
</array>
<key>aps-environment</key>
<string>production</string>
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:telegram.me</string>
<string>applinks:t.me</string>
</array>
<key>com.apple.developer.siri</key>
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>group.ph.telegra.Telegraph</string>
</array>
<key>com.apple.developer.in-app-payments</key>
<array>
<string>merchant.ph.telegra.Telegraph</string>
<string>merchant.yandex.ph.telegra.Telegraph</string>
<string>merchant.sberbank.ph.telegra.Telegraph</string>
<string>merchant.sberbank.test.ph.telegra.Telegraph</string>
<string>merchant.privatbank.test.telergramios</string>
<string>merchant.privatbank.prod.telergram</string>
<string>merchant.telegram.tranzzo.test</string>
</array>
<key>com.apple.developer.pushkit.unrestricted-voip</key>
<true/>
</dict>
</plist>

View File

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>production</string>
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:telegram.me</string>
<string>applinks:t.me</string>
</array>
<key>com.apple.developer.siri</key>
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>group.fork.telegram.Fork</string>
</array>
</dict>
</plist>

View File

@ -1,38 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>development</string>
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:telegram.me</string>
<string>applinks:t.me</string>
</array>
<key>com.apple.developer.icloud-container-identifiers</key>
<array>
<string>iCloud.org.telegram.Telegram-iOS</string>
</array>
<key>com.apple.developer.icloud-services</key>
<array>
<string>CloudKit</string>
<string>CloudDocuments</string>
</array>
<key>com.apple.developer.siri</key>
<true/>
<key>com.apple.developer.ubiquity-container-identifiers</key>
<array>
<string>iCloud.org.telegram.Telegram-iOS</string>
</array>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.telegram.Telegram-iOS</string>
</array>
<key>keychain-access-groups</key>
<array>
<string>X834Q8SBVP.org.telegram.Telegram-iOS</string>
</array>
<key>com.apple.developer.pushkit.unrestricted-voip</key>
<true/>
</dict>
</plist>

View File

@ -1974,6 +1974,7 @@
"Conversation.PinMessageAlertGroup" = "Pin this message and notify all members of the group?"; "Conversation.PinMessageAlertGroup" = "Pin this message and notify all members of the group?";
"Conversation.PinMessageAlert.OnlyPin" = "Only Pin"; "Conversation.PinMessageAlert.OnlyPin" = "Only Pin";
"Conversation.PinMessageAlert.PinAndNotifyMembers" = "Pin and notify all members";
"Conversation.UnpinMessageAlert" = "Would you like to unpin this message?"; "Conversation.UnpinMessageAlert" = "Would you like to unpin this message?";
@ -5887,3 +5888,5 @@ Sorry for the inconvenience.";
"Stats.Message.Views" = "Views"; "Stats.Message.Views" = "Views";
"Stats.Message.PublicShares" = "Public Shares"; "Stats.Message.PublicShares" = "Public Shares";
"Stats.Message.PrivateShares" = "Private Shares"; "Stats.Message.PrivateShares" = "Private Shares";
"ChatSettings.WidgetSettings" = "Widget";

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.telegram.TelegramHD</string>
</array>
</dict>
</plist>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.ph.telegra.Telegraph</string>
</array>
</dict>
</plist>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.fork.telegram.Telegram-iOS</string>
</array>
</dict>
</plist>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.telegram.Telegram-iOS</string>
</array>
</dict>
</plist>

View File

@ -52,43 +52,98 @@ extension PeersWidgetData {
static let previewData = PeersWidgetData.placeholder static let previewData = PeersWidgetData.placeholder
} }
struct AvatarItemView: View {
var accountPeerId: Int64
var peer: WidgetDataPeer
var itemSize: CGFloat
var body: some View {
return ZStack {
Image(uiImage: avatarImage(accountPeerId: accountPeerId, peer: peer, size: CGSize(width: itemSize, height: itemSize)))
if let badge = peer.badge, badge.count > 0 {
Text("\(badge.count)")
.font(Font.system(size: 16.0))
.multilineTextAlignment(.center)
.foregroundColor(.white)
.padding(.horizontal, 4.0)
.background(
RoundedRectangle(cornerRadius: 10)
.fill(badge.isMuted ? Color.gray : Color.red)
.frame(minWidth: 20, idealWidth: 20, maxWidth: .infinity, minHeight: 20, idealHeight: 20, maxHeight: 20.0, alignment: .center)
)
.position(x: floor(0.84 * itemSize), y: floor(0.16 * itemSize))
}
}
}
}
struct WidgetView: View { struct WidgetView: View {
@Environment(\.widgetFamily) private var widgetFamily
let data: PeersWidgetData let data: PeersWidgetData
func placeholder(geometry: GeometryProxy) -> some View { func placeholder(geometry: GeometryProxy) -> some View {
let defaultItemSize: CGFloat = 60.0 let defaultItemSize: CGFloat = 60.0
let defaultPaddingFraction: CGFloat = 0.36 let defaultPaddingFraction: CGFloat = 0.36
let rowCount = Int(round(geometry.size.width / (defaultItemSize * (1.0 + defaultPaddingFraction)))) let columnCount = Int(round(geometry.size.width / (defaultItemSize * (1.0 + defaultPaddingFraction))))
let itemSize = floor(geometry.size.width / (CGFloat(rowCount) + defaultPaddingFraction * CGFloat(rowCount - 1))) let itemSize = floor(geometry.size.width / (CGFloat(columnCount) + defaultPaddingFraction * CGFloat(columnCount - 1)))
let firstRowY = itemSize / 2.0 let firstRowY = itemSize / 2.0
let secondRowY = itemSize / 2.0 + geometry.size.height - itemSize let secondRowY = itemSize / 2.0 + geometry.size.height - itemSize
return ZStack { return ZStack {
ForEach(0 ..< rowCount * 2, content: { i in ForEach(0 ..< columnCount * 2, content: { i in
return Circle().frame(width: itemSize, height: itemSize).position(x: itemSize / 2.0 + floor(CGFloat(i % rowCount) * itemSize * (1.0 + defaultPaddingFraction)), y: i / rowCount == 0 ? firstRowY : secondRowY).foregroundColor(.gray) return Circle().frame(width: itemSize, height: itemSize).position(x: itemSize / 2.0 + floor(CGFloat(i % columnCount) * itemSize * (1.0 + defaultPaddingFraction)), y: i / columnCount == 0 ? firstRowY : secondRowY).foregroundColor(.gray)
}) })
} }
} }
private func linkForPeer(id: Int64) -> String {
switch self.widgetFamily {
case .systemSmall:
return "\(buildConfig.appSpecificUrlScheme)://"
default:
return "\(buildConfig.appSpecificUrlScheme)://localpeer?id=\(id)"
}
}
func peersView(geometry: GeometryProxy, peers: WidgetDataPeers) -> some View { func peersView(geometry: GeometryProxy, peers: WidgetDataPeers) -> some View {
let defaultItemSize: CGFloat = 60.0 let defaultItemSize: CGFloat = 60.0
let defaultPaddingFraction: CGFloat = 0.36 let defaultPaddingFraction: CGFloat = 0.36
let rowCount = Int(round(geometry.size.width / (defaultItemSize * (1.0 + defaultPaddingFraction)))) let rowCount: Int
let itemSize = floor(geometry.size.width / (CGFloat(rowCount) + defaultPaddingFraction * CGFloat(rowCount - 1))) let rowHeight: CGFloat
let topOffset: CGFloat
switch self.widgetFamily {
case .systemLarge:
rowCount = 4
rowHeight = 88.0
topOffset = 12.0
default:
rowCount = 2
rowHeight = 76.0
topOffset = 0.0
}
let columnCount = Int(round(geometry.size.width / (defaultItemSize * (1.0 + defaultPaddingFraction))))
let itemSize = floor(geometry.size.width / (CGFloat(columnCount) + defaultPaddingFraction * CGFloat(columnCount - 1)))
let firstRowY = itemSize / 2.0 let rowOffset: [CGFloat] = [
let secondRowY = itemSize / 2.0 + geometry.size.height - itemSize topOffset + itemSize / 2.0,
topOffset + itemSize / 2.0 + rowHeight,
topOffset + itemSize / 2.0 + rowHeight * 2,
topOffset + itemSize / 2.0 + rowHeight * 3,
]
return ZStack { return ZStack {
ForEach(0 ..< min(peers.peers.count, rowCount * 2), content: { i in ForEach(0 ..< min(peers.peers.count, columnCount * rowCount), content: { i in
Link(destination: URL(string: "\(buildConfig.appSpecificUrlScheme)://localpeer?id=\(peers.peers[i].id)")!, label: { Link(destination: URL(string: linkForPeer(id: peers.peers[i].id))!, label: {
Image(uiImage: avatarImage(accountPeerId: peers.accountPeerId, peer: peers.peers[i], size: CGSize(width: itemSize, height: itemSize))) AvatarItemView(
.frame(width: itemSize, height: itemSize) accountPeerId: peers.accountPeerId,
peer: peers.peers[i],
itemSize: itemSize
).frame(width: itemSize, height: itemSize)
}).frame(width: itemSize, height: itemSize) }).frame(width: itemSize, height: itemSize)
.position(x: itemSize / 2.0 + floor(CGFloat(i % rowCount) * itemSize * (1.0 + defaultPaddingFraction)), y: i / rowCount == 0 ? firstRowY : secondRowY) .position(x: itemSize / 2.0 + floor(CGFloat(i % columnCount) * itemSize * (1.0 + defaultPaddingFraction)), y: rowOffset[i / columnCount])
}) })
} }
} }
@ -123,7 +178,6 @@ struct WidgetView: View {
var body: some View { var body: some View {
ZStack { ZStack {
Color(.systemBackground)
peerViews() peerViews()
} }
.padding(.all) .padding(.all)
@ -214,7 +268,7 @@ struct Static_Widget: Widget {
WidgetView(data: getWidgetData()) WidgetView(data: getWidgetData())
} }
) )
.supportedFamilies([.systemMedium]) .supportedFamilies([.systemSmall, .systemMedium, .systemLarge])
.configurationDisplayName(presentationData.widgetGalleryTitle) .configurationDisplayName(presentationData.widgetGalleryTitle)
.description(presentationData.widgetGalleryDescription) .description(presentationData.widgetGalleryDescription)
} }

View File

@ -31,9 +31,6 @@ ifneq ($(BUCK_DIR_CACHE),)
endif endif
check_env: check_env:
ifndef BUCK
$(error BUCK is not set)
endif
sh check_env.sh sh check_env.sh
kill_xcode: kill_xcode:

View File

@ -1,4 +1,4 @@
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file")
http_archive( http_archive(
name = "com_google_protobuf", name = "com_google_protobuf",
@ -50,3 +50,9 @@ apple_support_dependencies()
load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace") load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
bazel_skylib_workspace() bazel_skylib_workspace()
http_file(
name = "cmake_tar_gz",
urls = ["https://github.com/Kitware/CMake/releases/download/v3.18.4/cmake-3.18.4-Darwin-x86_64.tar.gz"],
sha256 = "9d27049660474cf134ab46fa0e0db771b263313fcb8ba82ee8b2d1a1a62f8f20",
)

@ -1 +1 @@
Subproject commit b8755bd2884d6bf651827c30e00bd0ea318e41a2 Subproject commit 2583fa0bfd6909e7936da5b30e3547ba13e198dc

@ -1 +1 @@
Subproject commit d6f9a87d70781e92b95b9344c7d21d921ccc3ae2 Subproject commit 21c0ca93b0cd44e7eb500a1c02729a08b496b6c2

@ -1 +1 @@
Subproject commit 44e8c29afe3baa7f5fc434f4a7e83f7ac786644e Subproject commit ed81c15f9b577880c13b987101100cbac03f45c2

View File

@ -1 +1 @@
3.4.1 3.7.0

View File

@ -10,7 +10,7 @@ export API_ID="8"
export API_HASH="7245de8e747a0d6fbe11f7cc14fcc0bb" export API_HASH="7245de8e747a0d6fbe11f7cc14fcc0bb"
export BUNDLE_ID="ph.telegra.Telegraph" export BUNDLE_ID="ph.telegra.Telegraph"
export APP_CENTER_ID="" export APP_CENTER_ID="0"
export IS_INTERNAL_BUILD="false" export IS_INTERNAL_BUILD="false"
export IS_APPSTORE_BUILD="true" export IS_APPSTORE_BUILD="true"
export APPSTORE_ID="686449807" export APPSTORE_ID="686449807"

View File

@ -38,13 +38,13 @@ if [ `which cleanup-telegram-build-vms.sh` ]; then
cleanup-telegram-build-vms.sh cleanup-telegram-build-vms.sh
fi fi
if [ -z "$BUCK" ]; then if [ -z "$BAZEL" ]; then
echo "BUCK is not defined" echo "BAZEL is not defined"
exit 1 exit 1
fi fi
if [ ! -f "$BUCK" ]; then if [ ! -f "$BAZEL" ]; then
echo "buck not found at $BUCK" echo "bazel not found at $BAZEL"
exit 1 exit 1
fi fi
@ -52,8 +52,8 @@ BUILDBOX_DIR="buildbox"
mkdir -p "$BUILDBOX_DIR/transient-data" mkdir -p "$BUILDBOX_DIR/transient-data"
rm -f "tools/buck" rm -f "tools/bazel"
cp "$BUCK" "tools/buck" cp "$BAZEL" "tools/bazel"
BUILD_CONFIGURATION="$1" BUILD_CONFIGURATION="$1"
@ -73,7 +73,7 @@ fi
COMMIT_COMMENT="$(git log -1 --pretty=%B)" COMMIT_COMMENT="$(git log -1 --pretty=%B)"
case "$COMMIT_COMMENT" in case "$COMMIT_COMMENT" in
*"[nocache]"*) *"[nocache]"*)
export BUCK_HTTP_CACHE="" export BAZEL_HTTP_CACHE_URL=""
;; ;;
esac esac
@ -195,7 +195,7 @@ else
fi fi
scp -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -pr "$BUILDBOX_DIR/guest-build-telegram.sh" "$BUILDBOX_DIR/transient-data/source.tar" telegram@"$VM_IP": scp -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -pr "$BUILDBOX_DIR/guest-build-telegram.sh" "$BUILDBOX_DIR/transient-data/source.tar" telegram@"$VM_IP":
ssh -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null telegram@"$VM_IP" -o ServerAliveInterval=60 -t "export TELEGRAM_BUILD_APPSTORE_PASSWORD=\"$TELEGRAM_BUILD_APPSTORE_PASSWORD\"; export TELEGRAM_BUILD_APPSTORE_TEAM_NAME=\"$TELEGRAM_BUILD_APPSTORE_TEAM_NAME\"; export TELEGRAM_BUILD_APPSTORE_USERNAME=\"$TELEGRAM_BUILD_APPSTORE_USERNAME\"; export BUILD_NUMBER=\"$BUILD_NUMBER\"; export COMMIT_ID=\"$COMMIT_ID\"; export COMMIT_AUTHOR=\"$COMMIT_AUTHOR\"; export BUCK_HTTP_CACHE=\"$BUCK_HTTP_CACHE\"; export BUCK_DIR_CACHE=\"$BUCK_DIR_CACHE\"; export BUCK_CACHE_MODE=\"$BUCK_CACHE_MODE\"; $GUEST_SHELL -l guest-build-telegram.sh $BUILD_CONFIGURATION" || true ssh -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null telegram@"$VM_IP" -o ServerAliveInterval=60 -t "export TELEGRAM_BUILD_APPSTORE_PASSWORD=\"$TELEGRAM_BUILD_APPSTORE_PASSWORD\"; export TELEGRAM_BUILD_APPSTORE_TEAM_NAME=\"$TELEGRAM_BUILD_APPSTORE_TEAM_NAME\"; export TELEGRAM_BUILD_APPSTORE_USERNAME=\"$TELEGRAM_BUILD_APPSTORE_USERNAME\"; export BUILD_NUMBER=\"$BUILD_NUMBER\"; export COMMIT_ID=\"$COMMIT_ID\"; export COMMIT_AUTHOR=\"$COMMIT_AUTHOR\"; export BAZEL_HTTP_CACHE_URL=\"$BAZEL_HTTP_CACHE_URL\"; $GUEST_SHELL -l guest-build-telegram.sh $BUILD_CONFIGURATION" || true
OUTPUT_PATH="build/artifacts" OUTPUT_PATH="build/artifacts"
rm -rf "$OUTPUT_PATH" rm -rf "$OUTPUT_PATH"
@ -208,8 +208,9 @@ if [ -z "$RUNNING_VM" ]; then
virsh destroy "$VM_NAME" virsh destroy "$VM_NAME"
virsh undefine "$VM_NAME" --remove-all-storage --nvram virsh undefine "$VM_NAME" --remove-all-storage --nvram
elif [ "$BUILD_MACHINE" == "macOS" ]; then elif [ "$BUILD_MACHINE" == "macOS" ]; then
prlctl stop "$VM_NAME" --kill echo "Deleting VM..."
prlctl delete "$VM_NAME" #prlctl stop "$VM_NAME" --kill
#prlctl delete "$VM_NAME"
fi fi
fi fi

View File

@ -1,2 +0,0 @@
#!/bin/bash

View File

@ -101,13 +101,13 @@ done
if [ "$1" == "hockeyapp" ] || [ "$1" == "appcenter-experimental" ] || [ "$1" == "appcenter-experimental-2" ]; then if [ "$1" == "hockeyapp" ] || [ "$1" == "appcenter-experimental" ] || [ "$1" == "appcenter-experimental-2" ]; then
BUILD_ENV_SCRIPT="../telegram-ios-shared/buildbox/bin/internal.sh" BUILD_ENV_SCRIPT="../telegram-ios-shared/buildbox/bin/internal.sh"
APP_TARGET="app_arm64" APP_TARGET="bazel_app_arm64"
elif [ "$1" == "appstore" ]; then elif [ "$1" == "appstore" ]; then
BUILD_ENV_SCRIPT="../telegram-ios-shared/buildbox/bin/appstore.sh" BUILD_ENV_SCRIPT="../telegram-ios-shared/buildbox/bin/appstore.sh"
APP_TARGET="app" APP_TARGET="bazel_app"
elif [ "$1" == "verify" ]; then elif [ "$1" == "verify" ]; then
BUILD_ENV_SCRIPT="build-system/verify.sh" BUILD_ENV_SCRIPT="build-system/verify.sh"
APP_TARGET="app" APP_TARGET="bazel_app_arm64"
export CODESIGNING_DATA_PATH="build-system/fake-codesigning" export CODESIGNING_DATA_PATH="build-system/fake-codesigning"
export CODESIGNING_CERTS_VARIANT="distribution" export CODESIGNING_CERTS_VARIANT="distribution"
export CODESIGNING_PROFILES_VARIANT="appstore" export CODESIGNING_PROFILES_VARIANT="appstore"
@ -116,23 +116,27 @@ else
exit 1 exit 1
fi fi
if [ -d "$BUCK_DIR_CACHE" ]; then
sudo chown telegram "$BUCK_DIR_CACHE"
fi
if [ "$1" == "appcenter-experimental" ]; then if [ "$1" == "appcenter-experimental" ]; then
export APP_CENTER_ID="$APP_CENTER_EXPERIMENTAL_ID" export APP_CENTER_ID="$APP_CENTER_EXPERIMENTAL_ID"
elif [ "$1" == "appcenter-experimental-2" ]; then elif [ "$1" == "appcenter-experimental-2" ]; then
export APP_CENTER_ID="$APP_CENTER_EXPERIMENTAL_2_ID" export APP_CENTER_ID="$APP_CENTER_EXPERIMENTAL_2_ID"
fi fi
BUCK="$(pwd)/tools/buck" BUCK_HTTP_CACHE="$BUCK_HTTP_CACHE" BUCK_CACHE_MODE="$BUCK_CACHE_MODE" BUCK_DIR_CACHE="$BUCK_DIR_CACHE" LOCAL_CODESIGNING=1 sh "$BUILD_ENV_SCRIPT" make "$APP_TARGET" PATH="$PATH:$(pwd)/tools" BAZEL_HTTP_CACHE_URL="$BAZEL_HTTP_CACHE_URL" LOCAL_CODESIGNING=1 sh "$BUILD_ENV_SCRIPT" make "$APP_TARGET"
OUTPUT_PATH="build/artifacts" OUTPUT_PATH="build/artifacts"
rm -rf "$OUTPUT_PATH" rm -rf "$OUTPUT_PATH"
mkdir -p "$OUTPUT_PATH" mkdir -p "$OUTPUT_PATH"
cp "build/Telegram_signed.ipa" "./$OUTPUT_PATH/Telegram.ipa" for f in bazel-out/applebin_ios-ios_arm*-opt-ST-*/bin/Telegram/Telegram.ipa; do
cp "build/DSYMs.zip" "./$OUTPUT_PATH/Telegram.DSYMs.zip" cp "$f" $OUTPUT_PATH/
done
mkdir -p build/DSYMs
for f in bazel-out/applebin_ios-ios_arm*-opt-ST-*/bin/Telegram/*.dSYM; do
cp -R "$f" build/DSYMs/
done
zip -r "./$OUTPUT_PATH/Telegram.DSYMs.zip" build/DSYMs 1>/dev/null
cd "$BASE_DIR" cd "$BASE_DIR"

View File

@ -12,10 +12,10 @@ if [ -z "$CONFIGURATION" ] || [ -z "$MODE" ] ; then
fi fi
if [ "$MODE" == "cached" ]; then if [ "$MODE" == "cached" ]; then
BUCK_HTTP_CACHE="$BUCK_HTTP_CACHE" BAZEL_HTTP_CACHE_URL="$BAZEL_HTTP_CACHE_URL"
ERROR_OUTPUT_PATH="build/verifysanity_artifacts" ERROR_OUTPUT_PATH="build/verifysanity_artifacts"
elif [ "$MODE" == "full" ]; then elif [ "$MODE" == "full" ]; then
BUCK_HTTP_CACHE="" BAZEL_HTTP_CACHE_URL=""
ERROR_OUTPUT_PATH="build/verify_artifacts" ERROR_OUTPUT_PATH="build/verify_artifacts"
else else
echo "Unknown mode $MODE" echo "Unknown mode $MODE"
@ -25,7 +25,9 @@ fi
OUTPUT_PATH="build/artifacts" OUTPUT_PATH="build/artifacts"
if [ "$CONFIGURATION" == "appstore" ]; then if [ "$CONFIGURATION" == "appstore" ]; then
IPA_PATH="$OUTPUT_PATH/Telegram.ipa" if [ -z "$IPA_PATH" ]; then
IPA_PATH="$OUTPUT_PATH/Telegram.ipa"
fi
else else
echo "Unknown configuration $CONFIGURATION" echo "Unknown configuration $CONFIGURATION"
exit 1 exit 1
@ -38,9 +40,10 @@ fi
VERIFY_PATH="TelegramVerifyBuild.ipa" VERIFY_PATH="TelegramVerifyBuild.ipa"
mv "$IPA_PATH" "$VERIFY_PATH" rm -f "$VERIFY_PATH"
cp "$IPA_PATH" "$VERIFY_PATH"
BUCK_HTTP_CACHE="$BUCK_HTTP_CACHE" sh buildbox/build-telegram.sh verify BAZEL_HTTP_CACHE_URL="$BAZEL_HTTP_CACHE_URL" sh buildbox/build-telegram.sh verify
python3 tools/ipadiff.py "$IPA_PATH" "$VERIFY_PATH" python3 tools/ipadiff.py "$IPA_PATH" "$VERIFY_PATH"
retVal=$? retVal=$?

View File

@ -1175,4 +1175,8 @@ public final class AnimatedStickerNode: ASDisplayNode {
public func updateLayout(size: CGSize) { public func updateLayout(size: CGSize) {
self.renderer?.frame = CGRect(origin: CGPoint(), size: size) self.renderer?.frame = CGRect(origin: CGPoint(), size: size)
} }
public func setOverlayColor(_ color: UIColor?, animated: Bool) {
self.renderer?.setOverlayColor(color, animated: animated)
}
} }

View File

@ -9,4 +9,6 @@ public enum AnimationRendererFrameType {
protocol AnimationRenderer { protocol AnimationRenderer {
func render(queue: Queue, width: Int, height: Int, bytesPerRow: Int, data: Data, type: AnimationRendererFrameType, completion: @escaping () -> Void) func render(queue: Queue, width: Int, height: Int, bytesPerRow: Int, data: Data, type: AnimationRendererFrameType, completion: @escaping () -> Void)
func setOverlayColor(_ color: UIColor?, animated: Bool)
} }

View File

@ -6,6 +6,9 @@ import SwiftSignalKit
import YuvConversion import YuvConversion
final class SoftwareAnimationRenderer: ASDisplayNode, AnimationRenderer { final class SoftwareAnimationRenderer: ASDisplayNode, AnimationRenderer {
private var highlightedContentNode: ASDisplayNode?
private var highlightedColor: UIColor?
func render(queue: Queue, width: Int, height: Int, bytesPerRow: Int, data: Data, type: AnimationRendererFrameType, completion: @escaping () -> Void) { func render(queue: Queue, width: Int, height: Int, bytesPerRow: Int, data: Data, type: AnimationRendererFrameType, completion: @escaping () -> Void) {
queue.async { [weak self] in queue.async { [weak self] in
switch type { switch type {
@ -31,8 +34,57 @@ final class SoftwareAnimationRenderer: ASDisplayNode, AnimationRenderer {
Queue.mainQueue().async { Queue.mainQueue().async {
self?.contents = image?.cgImage self?.contents = image?.cgImage
self?.updateHighlightedContentNode()
completion() completion()
} }
} }
} }
private func updateHighlightedContentNode() {
guard let highlightedContentNode = self.highlightedContentNode, let highlightedColor = self.highlightedColor, let contents = self.contents, CFGetTypeID(contents as CFTypeRef) == CGImage.typeID else {
return
}
(highlightedContentNode.view as! UIImageView).image = UIImage(cgImage: contents as! CGImage).withRenderingMode(.alwaysTemplate)
highlightedContentNode.tintColor = highlightedColor
}
func setOverlayColor(_ color: UIColor?, animated: Bool) {
var updated = false
if let current = self.highlightedColor, let color = color {
updated = !current.isEqual(color)
} else if (self.highlightedColor != nil) != (color != nil) {
updated = true
}
if !updated {
return
}
self.highlightedColor = color
if let _ = color {
if let highlightedContentNode = self.highlightedContentNode {
highlightedContentNode.alpha = 1.0
} else {
let highlightedContentNode = ASDisplayNode(viewBlock: {
return UIImageView()
}, didLoad: nil)
highlightedContentNode.displaysAsynchronously = false
self.highlightedContentNode = highlightedContentNode
highlightedContentNode.frame = self.bounds
self.addSubnode(highlightedContentNode)
}
self.updateHighlightedContentNode()
} else if let highlightedContentNode = self.highlightedContentNode {
highlightedContentNode.alpha = 0.0
highlightedContentNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, completion: { [weak self] completed in
guard let strongSelf = self, completed else {
return
}
strongSelf.highlightedContentNode?.removeFromSupernode()
strongSelf.highlightedContentNode = nil
})
}
}
} }

View File

@ -440,7 +440,7 @@ public class GalleryController: ViewController, StandalonePresentableController
} else { } else {
namespaces = .not(Namespaces.Message.allScheduled) namespaces = .not(Namespaces.Message.allScheduled)
} }
return context.account.postbox.aroundMessageHistoryViewForLocation(context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), anchor: .index(message!.index), count: 50, clipHoles: false, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tagMask: tags, namespaces: namespaces, orderStatistics: [.combinedLocation]) return context.account.postbox.aroundMessageHistoryViewForLocation(context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), anchor: .index(message!.index), count: 50, clipHoles: false, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tagMask: tags, appendMessagesFromTheSameGroup: false, namespaces: namespaces, orderStatistics: [.combinedLocation])
|> mapToSignal { (view, _, _) -> Signal<GalleryMessageHistoryView?, NoError> in |> mapToSignal { (view, _, _) -> Signal<GalleryMessageHistoryView?, NoError> in
let mapped = GalleryMessageHistoryView.view(view) let mapped = GalleryMessageHistoryView.view(view)
return .single(mapped) return .single(mapped)
@ -1029,7 +1029,7 @@ public class GalleryController: ViewController, StandalonePresentableController
} else { } else {
namespaces = .not(Namespaces.Message.allScheduled) namespaces = .not(Namespaces.Message.allScheduled)
} }
let signal = strongSelf.context.account.postbox.aroundMessageHistoryViewForLocation(strongSelf.context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), anchor: .index(reloadAroundIndex), count: 50, clipHoles: false, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tagMask: tagMask, namespaces: namespaces, orderStatistics: [.combinedLocation]) let signal = strongSelf.context.account.postbox.aroundMessageHistoryViewForLocation(strongSelf.context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), anchor: .index(reloadAroundIndex), count: 50, clipHoles: false, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tagMask: tagMask, appendMessagesFromTheSameGroup: false, namespaces: namespaces, orderStatistics: [.combinedLocation])
|> mapToSignal { (view, _, _) -> Signal<GalleryMessageHistoryView?, NoError> in |> mapToSignal { (view, _, _) -> Signal<GalleryMessageHistoryView?, NoError> in
let mapped = GalleryMessageHistoryView.view(view) let mapped = GalleryMessageHistoryView.view(view)
return .single(mapped) return .single(mapped)

View File

@ -208,11 +208,13 @@ private final class LoadingShimmerNode: ASDisplayNode {
public struct ItemListPeerItemEditing: Equatable { public struct ItemListPeerItemEditing: Equatable {
public var editable: Bool public var editable: Bool
public var editing: Bool public var editing: Bool
public var canBeReordered: Bool
public var revealed: Bool? public var revealed: Bool?
public init(editable: Bool, editing: Bool, revealed: Bool?) { public init(editable: Bool, editing: Bool, canBeReordered: Bool = false, revealed: Bool?) {
self.editable = editable self.editable = editable
self.editing = editing self.editing = editing
self.canBeReordered = canBeReordered
self.revealed = revealed self.revealed = revealed
} }
} }
@ -460,6 +462,7 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
private var layoutParams: (ItemListPeerItem, ListViewItemLayoutParams, ItemListNeighbors, Bool)? private var layoutParams: (ItemListPeerItem, ListViewItemLayoutParams, ItemListNeighbors, Bool)?
private var editableControlNode: ItemListEditableControlNode? private var editableControlNode: ItemListEditableControlNode?
private var reorderControlNode: ItemListEditableReorderControlNode?
override public var canBeSelected: Bool { override public var canBeSelected: Bool {
if self.editableControlNode != nil || self.disabledOverlayNode != nil { if self.editableControlNode != nil || self.disabledOverlayNode != nil {
@ -560,6 +563,7 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
let makeStatusLayout = TextNode.asyncLayout(self.statusNode) let makeStatusLayout = TextNode.asyncLayout(self.statusNode)
let makeLabelLayout = TextNode.asyncLayout(self.labelNode) let makeLabelLayout = TextNode.asyncLayout(self.labelNode)
let editableControlLayout = ItemListEditableControlNode.asyncLayout(self.editableControlNode) let editableControlLayout = ItemListEditableControlNode.asyncLayout(self.editableControlNode)
let reorderControlLayout = ItemListEditableReorderControlNode.asyncLayout(self.reorderControlNode)
var currentDisabledOverlayNode = self.disabledOverlayNode var currentDisabledOverlayNode = self.disabledOverlayNode
@ -761,12 +765,20 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
} }
var editableControlSizeAndApply: (CGFloat, (CGFloat) -> ItemListEditableControlNode)? var editableControlSizeAndApply: (CGFloat, (CGFloat) -> ItemListEditableControlNode)?
var reorderControlSizeAndApply: (CGFloat, (CGFloat, Bool, ContainedViewLayoutTransition) -> ItemListEditableReorderControlNode)?
let editingOffset: CGFloat let editingOffset: CGFloat
var reorderInset: CGFloat = 0.0
if item.editing.editing { if item.editing.editing {
let sizeAndApply = editableControlLayout(item.presentationData.theme, false) let sizeAndApply = editableControlLayout(item.presentationData.theme, false)
editableControlSizeAndApply = sizeAndApply editableControlSizeAndApply = sizeAndApply
editingOffset = sizeAndApply.0 editingOffset = sizeAndApply.0
if item.editing.canBeReordered {
let reorderSizeAndApply = reorderControlLayout(item.presentationData.theme)
reorderControlSizeAndApply = reorderSizeAndApply
reorderInset = reorderSizeAndApply.0
}
} else { } else {
editingOffset = 0.0 editingOffset = 0.0
} }
@ -804,6 +816,8 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
labelInset += 15.0 labelInset += 15.0
} }
labelInset += reorderInset
let (labelLayout, labelApply) = makeLabelLayout(TextNodeLayoutArguments(attributedString: labelAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - 16.0 - editingOffset - rightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) let (labelLayout, labelApply) = makeLabelLayout(TextNodeLayoutArguments(attributedString: labelAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - 16.0 - editingOffset - rightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: titleAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - 12.0 - editingOffset - rightInset - labelLayout.size.width - labelInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: titleAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - 12.0 - editingOffset - rightInset - labelLayout.size.width - labelInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
@ -931,6 +945,23 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
}) })
} }
if let reorderControlSizeAndApply = reorderControlSizeAndApply {
if strongSelf.reorderControlNode == nil {
let reorderControlNode = reorderControlSizeAndApply.1(layout.contentSize.height, false, .immediate)
strongSelf.reorderControlNode = reorderControlNode
strongSelf.addSubnode(reorderControlNode)
reorderControlNode.alpha = 0.0
transition.updateAlpha(node: reorderControlNode, alpha: 1.0)
}
let reorderControlFrame = CGRect(origin: CGPoint(x: params.width + revealOffset - params.rightInset - reorderControlSizeAndApply.0, y: 0.0), size: CGSize(width: reorderControlSizeAndApply.0, height: layout.contentSize.height))
strongSelf.reorderControlNode?.frame = reorderControlFrame
} else if let reorderControlNode = strongSelf.reorderControlNode {
strongSelf.reorderControlNode = nil
transition.updateAlpha(node: reorderControlNode, alpha: 0.0, completion: { [weak reorderControlNode] _ in
reorderControlNode?.removeFromSupernode()
})
}
let _ = titleApply() let _ = titleApply()
let _ = statusApply() let _ = statusApply()
let _ = labelApply() let _ = labelApply()
@ -1293,6 +1324,13 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
shimmerNode.updateAbsoluteRect(rect, within: containerSize) shimmerNode.updateAbsoluteRect(rect, within: containerSize)
} }
} }
override public func isReorderable(at point: CGPoint) -> Bool {
if let reorderControlNode = self.reorderControlNode, reorderControlNode.frame.contains(point), !self.isDisplayingRevealedOptions {
return true
}
return false
}
} }
public final class ItemListPeerItemHeader: ListViewItemHeader { public final class ItemListPeerItemHeader: ListViewItemHeader {

View File

@ -226,7 +226,7 @@ public func mergeListsStableWithUpdates<T>(leftList: [T], rightList: [T], isLess
} }
var i = 0 var i = 0
while i < rightList.count { while i < rightList.count {
if updatedItems[i].1 != getId(rightList[i]) { if updatedItems.count <= i || updatedItems[i].1 != getId(rightList[i]) {
updatedItems.insert((rightList[i], getId(rightList[i])), at: i) updatedItems.insert((rightList[i], getId(rightList[i])), at: i)
var previousIndex: Int? var previousIndex: Int?
for k in 0 ..< leftList.count { for k in 0 ..< leftList.count {

View File

@ -629,7 +629,9 @@ static int32_t fixedTimeDifferenceValue = 0;
} }
if (MTLogEnabled()) { if (MTLogEnabled()) {
MTLog(@"[MTContext#%x: auth info updated for %d selector %d to %@]", (int)self, datacenterId, selector, authInfo); MTDatacenterAuthInfo *persistentInfo = _datacenterAuthInfoById[authInfoMapIntegerKey((int32_t)datacenterId, MTDatacenterAuthInfoSelectorPersistent)];
MTLog(@"[MTContext#%x: auth info updated for %d selector %d to %@ (persistent key id is %llu)]", (int)self, datacenterId, selector, authInfo, persistentInfo.authKeyId);
} }
[_keychain setObject:_datacenterAuthInfoById forKey:@"datacenterAuthInfoById" group:@"persistent"]; [_keychain setObject:_datacenterAuthInfoById forKey:@"datacenterAuthInfoById" group:@"persistent"];

View File

@ -292,7 +292,7 @@
if (initializeApi && _apiEnvironment != nil) if (initializeApi && _apiEnvironment != nil)
{ {
if (MTLogEnabled()) { if (MTLogEnabled()) {
MTLog(@"apiEnvironment: %d", (int)_apiEnvironment.systemCode.length); MTLog(@"apiEnvironment: %@", [_apiEnvironment apiInitializationHash]);
} }
MTBuffer *buffer = [[MTBuffer alloc] init]; MTBuffer *buffer = [[MTBuffer alloc] init];

View File

@ -313,6 +313,7 @@ public enum HistoryViewInputAnchor: Equatable {
final class MutableMessageHistoryView { final class MutableMessageHistoryView {
private(set) var peerIds: MessageHistoryViewInput private(set) var peerIds: MessageHistoryViewInput
let tag: MessageTags? let tag: MessageTags?
private let appendMessagesFromTheSameGroup: Bool
let namespaces: MessageIdNamespaces let namespaces: MessageIdNamespaces
private let orderStatistics: MessageHistoryViewOrderStatistics private let orderStatistics: MessageHistoryViewOrderStatistics
private let clipHoles: Bool private let clipHoles: Bool
@ -331,7 +332,7 @@ final class MutableMessageHistoryView {
fileprivate var isAddedToChatList: Bool fileprivate var isAddedToChatList: Bool
init(postbox: Postbox, orderStatistics: MessageHistoryViewOrderStatistics, clipHoles: Bool, peerIds: MessageHistoryViewInput, anchor inputAnchor: HistoryViewInputAnchor, combinedReadStates: MessageHistoryViewReadState?, transientReadStates: MessageHistoryViewReadState?, tag: MessageTags?, namespaces: MessageIdNamespaces, count: Int, topTaggedMessages: [MessageId.Namespace: MessageHistoryTopTaggedMessage?], additionalDatas: [AdditionalMessageHistoryViewDataEntry], getMessageCountInRange: (MessageIndex, MessageIndex) -> Int32) { init(postbox: Postbox, orderStatistics: MessageHistoryViewOrderStatistics, clipHoles: Bool, peerIds: MessageHistoryViewInput, anchor inputAnchor: HistoryViewInputAnchor, combinedReadStates: MessageHistoryViewReadState?, transientReadStates: MessageHistoryViewReadState?, tag: MessageTags?, appendMessagesFromTheSameGroup: Bool, namespaces: MessageIdNamespaces, count: Int, topTaggedMessages: [MessageId.Namespace: MessageHistoryTopTaggedMessage?], additionalDatas: [AdditionalMessageHistoryViewDataEntry], getMessageCountInRange: (MessageIndex, MessageIndex) -> Int32) {
self.anchor = inputAnchor self.anchor = inputAnchor
self.orderStatistics = orderStatistics self.orderStatistics = orderStatistics
@ -340,6 +341,7 @@ final class MutableMessageHistoryView {
self.combinedReadStates = combinedReadStates self.combinedReadStates = combinedReadStates
self.transientReadStates = transientReadStates self.transientReadStates = transientReadStates
self.tag = tag self.tag = tag
self.appendMessagesFromTheSameGroup = appendMessagesFromTheSameGroup
self.namespaces = namespaces self.namespaces = namespaces
self.fillCount = count self.fillCount = count
self.topTaggedMessages = topTaggedMessages self.topTaggedMessages = topTaggedMessages
@ -354,12 +356,12 @@ final class MutableMessageHistoryView {
self.isAddedToChatList = postbox.chatListTable.getPeerChatListIndex(peerId: input.peerId) != nil self.isAddedToChatList = postbox.chatListTable.getPeerChatListIndex(peerId: input.peerId) != nil
} }
self.state = HistoryViewState(postbox: postbox, inputAnchor: inputAnchor, tag: tag, namespaces: namespaces, statistics: self.orderStatistics, halfLimit: count + 1, locations: peerIds) self.state = HistoryViewState(postbox: postbox, inputAnchor: inputAnchor, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, statistics: self.orderStatistics, halfLimit: count + 1, locations: peerIds)
if case let .loading(loadingState) = self.state { if case let .loading(loadingState) = self.state {
let sampledState = loadingState.checkAndSample(postbox: postbox) let sampledState = loadingState.checkAndSample(postbox: postbox)
switch sampledState { switch sampledState {
case let .ready(anchor, holes): case let .ready(anchor, holes):
self.state = .loaded(HistoryViewLoadedState(anchor: anchor, tag: tag, namespaces: namespaces, statistics: self.orderStatistics, halfLimit: count + 1, locations: peerIds, postbox: postbox, holes: holes)) self.state = .loaded(HistoryViewLoadedState(anchor: anchor, tag: tag, appendMessagesFromTheSameGroup: self.appendMessagesFromTheSameGroup, namespaces: namespaces, statistics: self.orderStatistics, halfLimit: count + 1, locations: peerIds, postbox: postbox, holes: holes))
self.sampledState = self.state.sample(postbox: postbox, clipHoles: self.clipHoles) self.sampledState = self.state.sample(postbox: postbox, clipHoles: self.clipHoles)
case .loadHole: case .loadHole:
break break
@ -371,12 +373,12 @@ final class MutableMessageHistoryView {
} }
private func reset(postbox: Postbox) { private func reset(postbox: Postbox) {
self.state = HistoryViewState(postbox: postbox, inputAnchor: self.anchor, tag: self.tag, namespaces: self.namespaces, statistics: self.orderStatistics, halfLimit: self.fillCount + 1, locations: self.peerIds) self.state = HistoryViewState(postbox: postbox, inputAnchor: self.anchor, tag: self.tag, appendMessagesFromTheSameGroup: self.appendMessagesFromTheSameGroup, namespaces: self.namespaces, statistics: self.orderStatistics, halfLimit: self.fillCount + 1, locations: self.peerIds)
if case let .loading(loadingState) = self.state { if case let .loading(loadingState) = self.state {
let sampledState = loadingState.checkAndSample(postbox: postbox) let sampledState = loadingState.checkAndSample(postbox: postbox)
switch sampledState { switch sampledState {
case let .ready(anchor, holes): case let .ready(anchor, holes):
self.state = .loaded(HistoryViewLoadedState(anchor: anchor, tag: self.tag, namespaces: self.namespaces, statistics: self.orderStatistics, halfLimit: self.fillCount + 1, locations: self.peerIds, postbox: postbox, holes: holes)) self.state = .loaded(HistoryViewLoadedState(anchor: anchor, tag: self.tag, appendMessagesFromTheSameGroup: self.appendMessagesFromTheSameGroup, namespaces: self.namespaces, statistics: self.orderStatistics, halfLimit: self.fillCount + 1, locations: self.peerIds, postbox: postbox, holes: holes))
case .loadHole: case .loadHole:
break break
} }
@ -385,7 +387,7 @@ final class MutableMessageHistoryView {
let sampledState = loadingState.checkAndSample(postbox: postbox) let sampledState = loadingState.checkAndSample(postbox: postbox)
switch sampledState { switch sampledState {
case let .ready(anchor, holes): case let .ready(anchor, holes):
self.state = .loaded(HistoryViewLoadedState(anchor: anchor, tag: self.tag, namespaces: self.namespaces, statistics: self.orderStatistics, halfLimit: self.fillCount + 1, locations: self.peerIds, postbox: postbox, holes: holes)) self.state = .loaded(HistoryViewLoadedState(anchor: anchor, tag: self.tag, appendMessagesFromTheSameGroup: self.appendMessagesFromTheSameGroup, namespaces: self.namespaces, statistics: self.orderStatistics, halfLimit: self.fillCount + 1, locations: self.peerIds, postbox: postbox, holes: holes))
case .loadHole: case .loadHole:
break break
} }
@ -521,8 +523,23 @@ final class MutableMessageHistoryView {
for operation in operationSet { for operation in operationSet {
switch operation { switch operation {
case let .InsertMessage(message): case let .InsertMessage(message):
var matchesTag = false
if unwrappedTag.isEmpty {
matchesTag = true
} else if message.tags.contains(unwrappedTag) {
matchesTag = true
} else if self.appendMessagesFromTheSameGroup, let _ = message.groupInfo {
if let group = postbox.messageHistoryTable.getMessageGroup(at: message.index, limit: 20) {
for groupMessage in group {
if groupMessage.tags.contains(unwrappedTag) {
matchesTag = true
}
}
}
}
var matches = false var matches = false
if unwrappedTag.isEmpty || message.tags.contains(unwrappedTag) { if matchesTag {
if threadId == nil || message.threadId == threadId { if threadId == nil || message.threadId == threadId {
if self.namespaces.contains(message.id.namespace) { if self.namespaces.contains(message.id.namespace) {
matches = true matches = true
@ -613,7 +630,7 @@ final class MutableMessageHistoryView {
let sampledState = loadingState.checkAndSample(postbox: postbox) let sampledState = loadingState.checkAndSample(postbox: postbox)
switch sampledState { switch sampledState {
case let .ready(anchor, holes): case let .ready(anchor, holes):
self.state = .loaded(HistoryViewLoadedState(anchor: anchor, tag: self.tag, namespaces: self.namespaces, statistics: self.orderStatistics, halfLimit: self.fillCount + 1, locations: self.peerIds, postbox: postbox, holes: holes)) self.state = .loaded(HistoryViewLoadedState(anchor: anchor, tag: self.tag, appendMessagesFromTheSameGroup: self.appendMessagesFromTheSameGroup, namespaces: self.namespaces, statistics: self.orderStatistics, halfLimit: self.fillCount + 1, locations: self.peerIds, postbox: postbox, holes: holes))
case .loadHole: case .loadHole:
break break
} }

View File

@ -1,7 +1,17 @@
import Foundation import Foundation
public enum MessageHistoryInput: Equatable, Hashable { public enum MessageHistoryInput: Equatable, Hashable {
case automatic(MessageTags?) public struct Automatic: Equatable, Hashable {
public var tag: MessageTags
public var appendMessagesFromTheSameGroup: Bool
public init(tag: MessageTags, appendMessagesFromTheSameGroup: Bool) {
self.tag = tag
self.appendMessagesFromTheSameGroup = appendMessagesFromTheSameGroup
}
}
case automatic(Automatic?)
case external(MessageHistoryViewExternalInput, MessageTags?) case external(MessageHistoryViewExternalInput, MessageTags?)
public func hash(into hasher: inout Hasher) { public func hash(into hasher: inout Hasher) {
@ -17,8 +27,48 @@ public enum MessageHistoryInput: Equatable, Hashable {
private extension MessageHistoryInput { private extension MessageHistoryInput {
func fetch(postbox: Postbox, peerId: PeerId, namespace: MessageId.Namespace, from fromIndex: MessageIndex, includeFrom: Bool, to toIndex: MessageIndex, limit: Int) -> [IntermediateMessage] { func fetch(postbox: Postbox, peerId: PeerId, namespace: MessageId.Namespace, from fromIndex: MessageIndex, includeFrom: Bool, to toIndex: MessageIndex, limit: Int) -> [IntermediateMessage] {
switch self { switch self {
case let .automatic(tag): case let .automatic(automatic):
return postbox.messageHistoryTable.fetch(peerId: peerId, namespace: namespace, tag: tag, threadId: nil, from: fromIndex, includeFrom: includeFrom, to: toIndex, limit: limit) var items = postbox.messageHistoryTable.fetch(peerId: peerId, namespace: namespace, tag: automatic?.tag, threadId: nil, from: fromIndex, includeFrom: includeFrom, to: toIndex, limit: limit)
if let automatic = automatic, automatic.appendMessagesFromTheSameGroup {
enum Direction {
case lowToHigh
case highToLow
}
func processItem(index: Int, direction: Direction) {
guard let _ = items[index].groupInfo else {
return
}
if var group = postbox.messageHistoryTable.getMessageGroup(at: items[index].index, limit: 20), group.count > 1 {
switch direction {
case .lowToHigh:
group.sort(by: { lhs, rhs in
return lhs.index < rhs.index
})
case .highToLow:
group.sort(by: { lhs, rhs in
return lhs.index > rhs.index
})
}
items.replaceSubrange(index ..< index + 1, with: group)
switch direction {
case .lowToHigh:
items.removeFirst(group.count - 1)
case .highToLow:
items.removeLast(group.count - 1)
}
}
}
if fromIndex < toIndex {
for i in 0 ..< items.count {
processItem(index: i, direction: .lowToHigh)
}
} else {
for i in (0 ..< items.count).reversed() {
processItem(index: i, direction: .highToLow)
}
}
}
return items
case let .external(input, tag): case let .external(input, tag):
return postbox.messageHistoryTable.fetch(peerId: peerId, namespace: namespace, tag: tag, threadId: input.threadId, from: fromIndex, includeFrom: includeFrom, to: toIndex, limit: limit) return postbox.messageHistoryTable.fetch(peerId: peerId, namespace: namespace, tag: tag, threadId: input.threadId, from: fromIndex, includeFrom: includeFrom, to: toIndex, limit: limit)
} }
@ -26,9 +76,9 @@ private extension MessageHistoryInput {
func getMessageCountInRange(postbox: Postbox, peerId: PeerId, namespace: MessageId.Namespace, lowerBound: MessageIndex, upperBound: MessageIndex) -> Int { func getMessageCountInRange(postbox: Postbox, peerId: PeerId, namespace: MessageId.Namespace, lowerBound: MessageIndex, upperBound: MessageIndex) -> Int {
switch self { switch self {
case let .automatic(tag): case let .automatic(automatic):
if let tag = tag { if let automatic = automatic {
return postbox.messageHistoryTagsTable.getMessageCountInRange(tag: tag, peerId: peerId, namespace: namespace, lowerBound: lowerBound, upperBound: upperBound) return postbox.messageHistoryTagsTable.getMessageCountInRange(tag: automatic.tag, peerId: peerId, namespace: namespace, lowerBound: lowerBound, upperBound: upperBound)
} else { } else {
return 0 return 0
} }
@ -342,8 +392,8 @@ private func sampleHoleRanges(input: MessageHistoryInput, orderedEntriesBySpace:
var tag: MessageTags? var tag: MessageTags?
var threadId: Int64? var threadId: Int64?
switch input { switch input {
case let .automatic(value): case let .automatic(automatic):
tag = value tag = automatic?.tag
case let .external(value, _): case let .external(value, _):
threadId = value.threadId threadId = value.threadId
} }
@ -834,7 +884,7 @@ final class HistoryViewLoadedState {
var holes: HistoryViewHoles var holes: HistoryViewHoles
var spacesWithRemovals = Set<PeerIdAndNamespace>() var spacesWithRemovals = Set<PeerIdAndNamespace>()
init(anchor: HistoryViewAnchor, tag: MessageTags?, namespaces: MessageIdNamespaces, statistics: MessageHistoryViewOrderStatistics, halfLimit: Int, locations: MessageHistoryViewInput, postbox: Postbox, holes: HistoryViewHoles) { init(anchor: HistoryViewAnchor, tag: MessageTags?, appendMessagesFromTheSameGroup: Bool, namespaces: MessageIdNamespaces, statistics: MessageHistoryViewOrderStatistics, halfLimit: Int, locations: MessageHistoryViewInput, postbox: Postbox, holes: HistoryViewHoles) {
precondition(halfLimit >= 3) precondition(halfLimit >= 3)
self.anchor = anchor self.anchor = anchor
self.namespaces = namespaces self.namespaces = namespaces
@ -849,13 +899,17 @@ final class HistoryViewLoadedState {
switch locations { switch locations {
case let .single(peerId): case let .single(peerId):
peerIds.append(peerId) peerIds.append(peerId)
input = .automatic(tag) input = .automatic(tag.flatMap { tag in
MessageHistoryInput.Automatic(tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup)
})
case let .associated(peerId, associatedId): case let .associated(peerId, associatedId):
peerIds.append(peerId) peerIds.append(peerId)
if let associatedId = associatedId { if let associatedId = associatedId {
peerIds.append(associatedId.peerId) peerIds.append(associatedId.peerId)
} }
input = .automatic(tag) input = .automatic(tag.flatMap { tag in
MessageHistoryInput.Automatic(tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup)
})
case let .external(external): case let .external(external):
peerIds.append(external.peerId) peerIds.append(external.peerId)
input = .external(external, tag) input = .external(external, tag)
@ -927,7 +981,7 @@ final class HistoryViewLoadedState {
var entries = OrderedHistoryViewEntries(lowerOrAtAnchor: lowerOrAtAnchorMessages, higherThanAnchor: higherThanAnchorMessages) var entries = OrderedHistoryViewEntries(lowerOrAtAnchor: lowerOrAtAnchorMessages, higherThanAnchor: higherThanAnchorMessages)
if case let .automatic(tagValue) = self.input, let _ = tagValue, self.statistics.contains(.combinedLocation), let first = entries.first { if case let .automatic(automaticValue) = self.input, let _ = automaticValue, self.statistics.contains(.combinedLocation), let first = entries.first {
let messageIndex = first.index let messageIndex = first.index
let previousCount = self.input.getMessageCountInRange(postbox: postbox, peerId: space.peerId, namespace: space.namespace, lowerBound: MessageIndex.lowerBound(peerId: space.peerId, namespace: space.namespace), upperBound: messageIndex) let previousCount = self.input.getMessageCountInRange(postbox: postbox, peerId: space.peerId, namespace: space.namespace, lowerBound: MessageIndex.lowerBound(peerId: space.peerId, namespace: space.namespace), upperBound: messageIndex)
let nextCount = self.input.getMessageCountInRange(postbox: postbox, peerId: space.peerId, namespace: space.namespace, lowerBound: messageIndex, upperBound: MessageIndex.upperBound(peerId: space.peerId, namespace: space.namespace)) let nextCount = self.input.getMessageCountInRange(postbox: postbox, peerId: space.peerId, namespace: space.namespace, lowerBound: messageIndex, upperBound: MessageIndex.upperBound(peerId: space.peerId, namespace: space.namespace))
@ -1333,7 +1387,9 @@ private func fetchHoles(postbox: Postbox, locations: MessageHistoryViewInput, ta
let indices = postbox.messageHistoryHoleIndexTable.closest(peerId: peerId, namespace: namespace, space: holeSpace, range: 1 ... (Int32.max - 1)) let indices = postbox.messageHistoryHoleIndexTable.closest(peerId: peerId, namespace: namespace, space: holeSpace, range: 1 ... (Int32.max - 1))
if !indices.isEmpty { if !indices.isEmpty {
let peerIdAndNamespace = PeerIdAndNamespace(peerId: peerId, namespace: namespace) let peerIdAndNamespace = PeerIdAndNamespace(peerId: peerId, namespace: namespace)
assert(canContainHoles(peerIdAndNamespace, input: .automatic(tag), seedConfiguration: postbox.seedConfiguration)) assert(canContainHoles(peerIdAndNamespace, input: .automatic(tag.flatMap { tag in
MessageHistoryInput.Automatic(tag: tag, appendMessagesFromTheSameGroup: false)
}), seedConfiguration: postbox.seedConfiguration))
holesBySpace[peerIdAndNamespace] = indices holesBySpace[peerIdAndNamespace] = indices
} }
} }
@ -1414,14 +1470,14 @@ enum HistoryViewState {
case loaded(HistoryViewLoadedState) case loaded(HistoryViewLoadedState)
case loading(HistoryViewLoadingState) case loading(HistoryViewLoadingState)
init(postbox: Postbox, inputAnchor: HistoryViewInputAnchor, tag: MessageTags?, namespaces: MessageIdNamespaces, statistics: MessageHistoryViewOrderStatistics, halfLimit: Int, locations: MessageHistoryViewInput) { init(postbox: Postbox, inputAnchor: HistoryViewInputAnchor, tag: MessageTags?, appendMessagesFromTheSameGroup: Bool, namespaces: MessageIdNamespaces, statistics: MessageHistoryViewOrderStatistics, halfLimit: Int, locations: MessageHistoryViewInput) {
switch inputAnchor { switch inputAnchor {
case let .index(index): case let .index(index):
self = .loaded(HistoryViewLoadedState(anchor: .index(index), tag: tag, namespaces: namespaces, statistics: statistics, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag, namespaces: namespaces)))) self = .loaded(HistoryViewLoadedState(anchor: .index(index), tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, statistics: statistics, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag, namespaces: namespaces))))
case .lowerBound: case .lowerBound:
self = .loaded(HistoryViewLoadedState(anchor: .lowerBound, tag: tag, namespaces: namespaces, statistics: statistics, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag, namespaces: namespaces)))) self = .loaded(HistoryViewLoadedState(anchor: .lowerBound, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, statistics: statistics, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag, namespaces: namespaces))))
case .upperBound: case .upperBound:
self = .loaded(HistoryViewLoadedState(anchor: .upperBound, tag: tag, namespaces: namespaces, statistics: statistics, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag, namespaces: namespaces)))) self = .loaded(HistoryViewLoadedState(anchor: .upperBound, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, statistics: statistics, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag, namespaces: namespaces))))
case .unread: case .unread:
let anchorPeerId: PeerId let anchorPeerId: PeerId
switch locations { switch locations {
@ -1430,7 +1486,7 @@ enum HistoryViewState {
case let .associated(peerId, _): case let .associated(peerId, _):
anchorPeerId = peerId anchorPeerId = peerId
case .external: case .external:
self = .loaded(HistoryViewLoadedState(anchor: .upperBound, tag: tag, namespaces: namespaces, statistics: statistics, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag, namespaces: namespaces)))) self = .loaded(HistoryViewLoadedState(anchor: .upperBound, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, statistics: statistics, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag, namespaces: namespaces))))
return return
} }
if postbox.chatListIndexTable.get(peerId: anchorPeerId).includedIndex(peerId: anchorPeerId) != nil, let combinedState = postbox.readStateTable.getCombinedState(anchorPeerId) { if postbox.chatListIndexTable.get(peerId: anchorPeerId).includedIndex(peerId: anchorPeerId) != nil, let combinedState = postbox.readStateTable.getCombinedState(anchorPeerId) {
@ -1461,12 +1517,12 @@ enum HistoryViewState {
let sampledState = loadingState.checkAndSample(postbox: postbox) let sampledState = loadingState.checkAndSample(postbox: postbox)
switch sampledState { switch sampledState {
case let .ready(anchor, holes): case let .ready(anchor, holes):
self = .loaded(HistoryViewLoadedState(anchor: anchor, tag: tag, namespaces: namespaces, statistics: statistics, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: holes)) self = .loaded(HistoryViewLoadedState(anchor: anchor, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, statistics: statistics, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: holes))
case .loadHole: case .loadHole:
self = .loading(loadingState) self = .loading(loadingState)
} }
} else { } else {
self = .loaded(HistoryViewLoadedState(anchor: anchor ?? .upperBound, tag: tag, namespaces: namespaces, statistics: statistics, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag, namespaces: namespaces)))) self = .loaded(HistoryViewLoadedState(anchor: anchor ?? .upperBound, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, statistics: statistics, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag, namespaces: namespaces))))
} }
} else { } else {
preconditionFailure() preconditionFailure()
@ -1483,7 +1539,7 @@ enum HistoryViewState {
let sampledState = loadingState.checkAndSample(postbox: postbox) let sampledState = loadingState.checkAndSample(postbox: postbox)
switch sampledState { switch sampledState {
case let .ready(anchor, holes): case let .ready(anchor, holes):
self = .loaded(HistoryViewLoadedState(anchor: anchor, tag: tag, namespaces: namespaces, statistics: statistics, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: holes)) self = .loaded(HistoryViewLoadedState(anchor: anchor, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, statistics: statistics, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: holes))
case .loadHole: case .loadHole:
self = .loading(loadingState) self = .loading(loadingState)
} }

View File

@ -60,7 +60,7 @@ final class MutableMessageOfInterestHolesView: MutablePostboxView {
} }
} }
self.anchor = anchor self.anchor = anchor
self.wrappedView = MutableMessageHistoryView(postbox: postbox, orderStatistics: [], clipHoles: true, peerIds: peerIds, anchor: self.anchor, combinedReadStates: nil, transientReadStates: nil, tag: nil, namespaces: .all, count: self.count, topTaggedMessages: [:], additionalDatas: [], getMessageCountInRange: { _, _ in return 0}) self.wrappedView = MutableMessageHistoryView(postbox: postbox, orderStatistics: [], clipHoles: true, peerIds: peerIds, anchor: self.anchor, combinedReadStates: nil, transientReadStates: nil, tag: nil, appendMessagesFromTheSameGroup: false, namespaces: .all, count: self.count, topTaggedMessages: [:], additionalDatas: [], getMessageCountInRange: { _, _ in return 0})
let _ = self.updateFromView() let _ = self.updateFromView()
} }
@ -132,7 +132,7 @@ final class MutableMessageOfInterestHolesView: MutablePostboxView {
case let .peer(id): case let .peer(id):
peerIds = postbox.peerIdsForLocation(.peer(id), ignoreRelatedChats: false) peerIds = postbox.peerIdsForLocation(.peer(id), ignoreRelatedChats: false)
} }
self.wrappedView = MutableMessageHistoryView(postbox: postbox, orderStatistics: [], clipHoles: true, peerIds: peerIds, anchor: self.anchor, combinedReadStates: nil, transientReadStates: nil, tag: nil, namespaces: .all, count: self.count, topTaggedMessages: [:], additionalDatas: [], getMessageCountInRange: { _, _ in return 0}) self.wrappedView = MutableMessageHistoryView(postbox: postbox, orderStatistics: [], clipHoles: true, peerIds: peerIds, anchor: self.anchor, combinedReadStates: nil, transientReadStates: nil, tag: nil, appendMessagesFromTheSameGroup: false, namespaces: .all, count: self.count, topTaggedMessages: [:], additionalDatas: [], getMessageCountInRange: { _, _ in return 0})
return self.updateFromView() return self.updateFromView()
} else if self.wrappedView.replay(postbox: postbox, transaction: transaction) { } else if self.wrappedView.replay(postbox: postbox, transaction: transaction) {
var reloadView = false var reloadView = false
@ -163,7 +163,7 @@ final class MutableMessageOfInterestHolesView: MutablePostboxView {
case let .peer(id): case let .peer(id):
peerIds = postbox.peerIdsForLocation(.peer(id), ignoreRelatedChats: false) peerIds = postbox.peerIdsForLocation(.peer(id), ignoreRelatedChats: false)
} }
self.wrappedView = MutableMessageHistoryView(postbox: postbox, orderStatistics: [], clipHoles: true, peerIds: peerIds, anchor: self.anchor, combinedReadStates: nil, transientReadStates: nil, tag: nil, namespaces: .all, count: self.count, topTaggedMessages: [:], additionalDatas: [], getMessageCountInRange: { _, _ in return 0}) self.wrappedView = MutableMessageHistoryView(postbox: postbox, orderStatistics: [], clipHoles: true, peerIds: peerIds, anchor: self.anchor, combinedReadStates: nil, transientReadStates: nil, tag: nil, appendMessagesFromTheSameGroup: false, namespaces: .all, count: self.count, topTaggedMessages: [:], additionalDatas: [], getMessageCountInRange: { _, _ in return 0})
} }
return self.updateFromView() return self.updateFromView()

View File

@ -1009,7 +1009,7 @@ public final class Transaction {
view = next.0 view = next.0
}, error: { _ in }, completed: {}) }, error: { _ in }, completed: {})
let disposable = postbox.syncAroundMessageHistoryViewForPeerId(subscriber: subscriber, peerIds: input, count: count, clipHoles: clipHoles, anchor: anchor, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: Set(), tagMask: nil, namespaces: namespaces, orderStatistics: MessageHistoryViewOrderStatistics(), additionalData: []) let disposable = postbox.syncAroundMessageHistoryViewForPeerId(subscriber: subscriber, peerIds: input, count: count, clipHoles: clipHoles, anchor: anchor, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: Set(), tagMask: nil, appendMessagesFromTheSameGroup: false, namespaces: namespaces, orderStatistics: MessageHistoryViewOrderStatistics(), additionalData: [])
disposable.dispose() disposable.dispose()
return view! return view!
@ -2460,7 +2460,7 @@ public final class Postbox {
return peerIds return peerIds
} }
public func aroundMessageOfInterestHistoryViewForChatLocation(_ chatLocation: ChatLocationInput, count: Int, clipHoles: Bool = true, topTaggedMessageIdNamespaces: Set<MessageId.Namespace>, tagMask: MessageTags?, namespaces: MessageIdNamespaces, orderStatistics: MessageHistoryViewOrderStatistics, additionalData: [AdditionalMessageHistoryViewData]) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> { public func aroundMessageOfInterestHistoryViewForChatLocation(_ chatLocation: ChatLocationInput, count: Int, clipHoles: Bool = true, topTaggedMessageIdNamespaces: Set<MessageId.Namespace>, tagMask: MessageTags?, appendMessagesFromTheSameGroup: Bool, namespaces: MessageIdNamespaces, orderStatistics: MessageHistoryViewOrderStatistics, additionalData: [AdditionalMessageHistoryViewData]) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> {
return self.resolvedChatLocationInput(chatLocation: chatLocation) return self.resolvedChatLocationInput(chatLocation: chatLocation)
|> mapToSignal { chatLocationData in |> mapToSignal { chatLocationData in
let (chatLocation, isHoleFill) = chatLocationData let (chatLocation, isHoleFill) = chatLocationData
@ -2516,7 +2516,7 @@ public final class Postbox {
anchor = .upperBound anchor = .upperBound
} }
} }
return self.syncAroundMessageHistoryViewForPeerId(subscriber: subscriber, peerIds: peerIds, count: count, clipHoles: clipHoles, anchor: anchor, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: topTaggedMessageIdNamespaces, tagMask: tagMask, namespaces: namespaces, orderStatistics: orderStatistics, additionalData: additionalData) return self.syncAroundMessageHistoryViewForPeerId(subscriber: subscriber, peerIds: peerIds, count: count, clipHoles: clipHoles, anchor: anchor, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: topTaggedMessageIdNamespaces, tagMask: tagMask, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, orderStatistics: orderStatistics, additionalData: additionalData)
}) })
return signal return signal
@ -2530,13 +2530,13 @@ public final class Postbox {
} }
} }
public func aroundIdMessageHistoryViewForLocation(_ chatLocation: ChatLocationInput, count: Int, clipHoles: Bool = true, ignoreRelatedChats: Bool = false, messageId: MessageId, topTaggedMessageIdNamespaces: Set<MessageId.Namespace>, tagMask: MessageTags?, namespaces: MessageIdNamespaces, orderStatistics: MessageHistoryViewOrderStatistics, additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> { public func aroundIdMessageHistoryViewForLocation(_ chatLocation: ChatLocationInput, count: Int, clipHoles: Bool = true, ignoreRelatedChats: Bool = false, messageId: MessageId, topTaggedMessageIdNamespaces: Set<MessageId.Namespace>, tagMask: MessageTags?, appendMessagesFromTheSameGroup: Bool, namespaces: MessageIdNamespaces, orderStatistics: MessageHistoryViewOrderStatistics, additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> {
return self.resolvedChatLocationInput(chatLocation: chatLocation) return self.resolvedChatLocationInput(chatLocation: chatLocation)
|> mapToSignal { chatLocationData in |> mapToSignal { chatLocationData in
let (chatLocation, isHoleFill) = chatLocationData let (chatLocation, isHoleFill) = chatLocationData
let signal: Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> = self.transactionSignal { subscriber, transaction in let signal: Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> = self.transactionSignal { subscriber, transaction in
let peerIds = self.peerIdsForLocation(chatLocation, ignoreRelatedChats: ignoreRelatedChats) let peerIds = self.peerIdsForLocation(chatLocation, ignoreRelatedChats: ignoreRelatedChats)
return self.syncAroundMessageHistoryViewForPeerId(subscriber: subscriber, peerIds: peerIds, count: count, clipHoles: clipHoles, anchor: .message(messageId), fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: topTaggedMessageIdNamespaces, tagMask: tagMask, namespaces: namespaces, orderStatistics: orderStatistics, additionalData: additionalData) return self.syncAroundMessageHistoryViewForPeerId(subscriber: subscriber, peerIds: peerIds, count: count, clipHoles: clipHoles, anchor: .message(messageId), fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: topTaggedMessageIdNamespaces, tagMask: tagMask, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, orderStatistics: orderStatistics, additionalData: additionalData)
} }
return signal return signal
@ -2550,14 +2550,14 @@ public final class Postbox {
} }
} }
public func aroundMessageHistoryViewForLocation(_ chatLocation: ChatLocationInput, anchor: HistoryViewInputAnchor, count: Int, clipHoles: Bool = true, ignoreRelatedChats: Bool = false, fixedCombinedReadStates: MessageHistoryViewReadState?, topTaggedMessageIdNamespaces: Set<MessageId.Namespace>, tagMask: MessageTags?, namespaces: MessageIdNamespaces, orderStatistics: MessageHistoryViewOrderStatistics, additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> { public func aroundMessageHistoryViewForLocation(_ chatLocation: ChatLocationInput, anchor: HistoryViewInputAnchor, count: Int, clipHoles: Bool = true, ignoreRelatedChats: Bool = false, fixedCombinedReadStates: MessageHistoryViewReadState?, topTaggedMessageIdNamespaces: Set<MessageId.Namespace>, tagMask: MessageTags?, appendMessagesFromTheSameGroup: Bool, namespaces: MessageIdNamespaces, orderStatistics: MessageHistoryViewOrderStatistics, additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> {
return self.resolvedChatLocationInput(chatLocation: chatLocation) return self.resolvedChatLocationInput(chatLocation: chatLocation)
|> mapToSignal { chatLocationData -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> in |> mapToSignal { chatLocationData -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> in
let (chatLocation, isHoleFill) = chatLocationData let (chatLocation, isHoleFill) = chatLocationData
let signal: Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> = self.transactionSignal { subscriber, transaction in let signal: Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> = self.transactionSignal { subscriber, transaction in
let peerIds = self.peerIdsForLocation(chatLocation, ignoreRelatedChats: ignoreRelatedChats) let peerIds = self.peerIdsForLocation(chatLocation, ignoreRelatedChats: ignoreRelatedChats)
return self.syncAroundMessageHistoryViewForPeerId(subscriber: subscriber, peerIds: peerIds, count: count, clipHoles: clipHoles, anchor: anchor, fixedCombinedReadStates: fixedCombinedReadStates, topTaggedMessageIdNamespaces: topTaggedMessageIdNamespaces, tagMask: tagMask, namespaces: namespaces, orderStatistics: orderStatistics, additionalData: additionalData) return self.syncAroundMessageHistoryViewForPeerId(subscriber: subscriber, peerIds: peerIds, count: count, clipHoles: clipHoles, anchor: anchor, fixedCombinedReadStates: fixedCombinedReadStates, topTaggedMessageIdNamespaces: topTaggedMessageIdNamespaces, tagMask: tagMask, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, orderStatistics: orderStatistics, additionalData: additionalData)
} }
return signal return signal
@ -2572,7 +2572,7 @@ public final class Postbox {
} }
} }
fileprivate func syncAroundMessageHistoryViewForPeerId(subscriber: Subscriber<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError>, peerIds: MessageHistoryViewInput, count: Int, clipHoles: Bool, anchor: HistoryViewInputAnchor, fixedCombinedReadStates: MessageHistoryViewReadState?, topTaggedMessageIdNamespaces: Set<MessageId.Namespace>, tagMask: MessageTags?, namespaces: MessageIdNamespaces, orderStatistics: MessageHistoryViewOrderStatistics, additionalData: [AdditionalMessageHistoryViewData]) -> Disposable { fileprivate func syncAroundMessageHistoryViewForPeerId(subscriber: Subscriber<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError>, peerIds: MessageHistoryViewInput, count: Int, clipHoles: Bool, anchor: HistoryViewInputAnchor, fixedCombinedReadStates: MessageHistoryViewReadState?, topTaggedMessageIdNamespaces: Set<MessageId.Namespace>, tagMask: MessageTags?, appendMessagesFromTheSameGroup: Bool, namespaces: MessageIdNamespaces, orderStatistics: MessageHistoryViewOrderStatistics, additionalData: [AdditionalMessageHistoryViewData]) -> Disposable {
var topTaggedMessages: [MessageId.Namespace: MessageHistoryTopTaggedMessage?] = [:] var topTaggedMessages: [MessageId.Namespace: MessageHistoryTopTaggedMessage?] = [:]
var mainPeerIdForTopTaggedMessages: PeerId? var mainPeerIdForTopTaggedMessages: PeerId?
switch peerIds { switch peerIds {
@ -2668,7 +2668,7 @@ public final class Postbox {
readStates = transientReadStates readStates = transientReadStates
} }
let mutableView = MutableMessageHistoryView(postbox: self, orderStatistics: orderStatistics, clipHoles: clipHoles, peerIds: peerIds, anchor: anchor, combinedReadStates: readStates, transientReadStates: transientReadStates, tag: tagMask, namespaces: namespaces, count: count, topTaggedMessages: topTaggedMessages, additionalDatas: additionalDataEntries, getMessageCountInRange: { lowerBound, upperBound in let mutableView = MutableMessageHistoryView(postbox: self, orderStatistics: orderStatistics, clipHoles: clipHoles, peerIds: peerIds, anchor: anchor, combinedReadStates: readStates, transientReadStates: transientReadStates, tag: tagMask, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, count: count, topTaggedMessages: topTaggedMessages, additionalDatas: additionalDataEntries, getMessageCountInRange: { lowerBound, upperBound in
if let tagMask = tagMask { if let tagMask = tagMask {
return Int32(self.messageHistoryTable.getMessageCountInRange(peerId: lowerBound.id.peerId, namespace: lowerBound.id.namespace, tag: tagMask, lowerBound: lowerBound, upperBound: upperBound)) return Int32(self.messageHistoryTable.getMessageCountInRange(peerId: lowerBound.id.peerId, namespace: lowerBound.id.namespace, tag: tagMask, lowerBound: lowerBound, upperBound: upperBound))
} else { } else {

View File

@ -86,6 +86,7 @@ swift_library(
"//submodules/OpenInExternalAppUI:OpenInExternalAppUI", "//submodules/OpenInExternalAppUI:OpenInExternalAppUI",
"//submodules/AccountUtils:AccountUtils", "//submodules/AccountUtils:AccountUtils",
"//submodules/AuthTransferUI:AuthTransferUI", "//submodules/AuthTransferUI:AuthTransferUI",
"//submodules/WidgetSetupScreen:WidgetSetupScreen",
], ],
visibility = [ visibility = [
"//visibility:public", "//visibility:public",

View File

@ -12,6 +12,7 @@ import ItemListUI
import PresentationDataUtils import PresentationDataUtils
import AccountContext import AccountContext
import OpenInExternalAppUI import OpenInExternalAppUI
import WidgetSetupScreen
private final class DataAndStorageControllerArguments { private final class DataAndStorageControllerArguments {
let openStorageUsage: () -> Void let openStorageUsage: () -> Void
@ -27,9 +28,10 @@ private final class DataAndStorageControllerArguments {
let toggleDownloadInBackground: (Bool) -> Void let toggleDownloadInBackground: (Bool) -> Void
let openBrowserSelection: () -> Void let openBrowserSelection: () -> Void
let openIntents: () -> Void let openIntents: () -> Void
let openWidgetSettings: () -> Void
let toggleEnableSensitiveContent: (Bool) -> Void let toggleEnableSensitiveContent: (Bool) -> Void
init(openStorageUsage: @escaping () -> Void, openNetworkUsage: @escaping () -> Void, openProxy: @escaping () -> Void, openAutomaticDownloadConnectionType: @escaping (AutomaticDownloadConnectionType) -> Void, resetAutomaticDownload: @escaping () -> Void, openVoiceUseLessData: @escaping () -> Void, openSaveIncomingPhotos: @escaping () -> Void, toggleSaveEditedPhotos: @escaping (Bool) -> Void, toggleAutoplayGifs: @escaping (Bool) -> Void, toggleAutoplayVideos: @escaping (Bool) -> Void, toggleDownloadInBackground: @escaping (Bool) -> Void, openBrowserSelection: @escaping () -> Void, openIntents: @escaping () -> Void, toggleEnableSensitiveContent: @escaping (Bool) -> Void) { init(openStorageUsage: @escaping () -> Void, openNetworkUsage: @escaping () -> Void, openProxy: @escaping () -> Void, openAutomaticDownloadConnectionType: @escaping (AutomaticDownloadConnectionType) -> Void, resetAutomaticDownload: @escaping () -> Void, openVoiceUseLessData: @escaping () -> Void, openSaveIncomingPhotos: @escaping () -> Void, toggleSaveEditedPhotos: @escaping (Bool) -> Void, toggleAutoplayGifs: @escaping (Bool) -> Void, toggleAutoplayVideos: @escaping (Bool) -> Void, toggleDownloadInBackground: @escaping (Bool) -> Void, openBrowserSelection: @escaping () -> Void, openIntents: @escaping () -> Void, openWidgetSettings: @escaping () -> Void, toggleEnableSensitiveContent: @escaping (Bool) -> Void) {
self.openStorageUsage = openStorageUsage self.openStorageUsage = openStorageUsage
self.openNetworkUsage = openNetworkUsage self.openNetworkUsage = openNetworkUsage
self.openProxy = openProxy self.openProxy = openProxy
@ -43,6 +45,7 @@ private final class DataAndStorageControllerArguments {
self.toggleDownloadInBackground = toggleDownloadInBackground self.toggleDownloadInBackground = toggleDownloadInBackground
self.openBrowserSelection = openBrowserSelection self.openBrowserSelection = openBrowserSelection
self.openIntents = openIntents self.openIntents = openIntents
self.openWidgetSettings = openWidgetSettings
self.toggleEnableSensitiveContent = toggleEnableSensitiveContent self.toggleEnableSensitiveContent = toggleEnableSensitiveContent
} }
} }
@ -87,6 +90,7 @@ private enum DataAndStorageEntry: ItemListNodeEntry {
case useLessVoiceData(PresentationTheme, String, String) case useLessVoiceData(PresentationTheme, String, String)
case otherHeader(PresentationTheme, String) case otherHeader(PresentationTheme, String)
case shareSheet(PresentationTheme, String) case shareSheet(PresentationTheme, String)
case widgetSettings(String)
case saveIncomingPhotos(PresentationTheme, String) case saveIncomingPhotos(PresentationTheme, String)
case saveEditedPhotos(PresentationTheme, String, Bool) case saveEditedPhotos(PresentationTheme, String, Bool)
case openLinksIn(PresentationTheme, String, String) case openLinksIn(PresentationTheme, String, String)
@ -106,7 +110,7 @@ private enum DataAndStorageEntry: ItemListNodeEntry {
return DataAndStorageSection.autoPlay.rawValue return DataAndStorageSection.autoPlay.rawValue
case .voiceCallsHeader, .useLessVoiceData: case .voiceCallsHeader, .useLessVoiceData:
return DataAndStorageSection.voiceCalls.rawValue return DataAndStorageSection.voiceCalls.rawValue
case .otherHeader, .shareSheet, .saveIncomingPhotos, .saveEditedPhotos, .openLinksIn, .downloadInBackground, .downloadInBackgroundInfo: case .otherHeader, .shareSheet, .widgetSettings, .saveIncomingPhotos, .saveEditedPhotos, .openLinksIn, .downloadInBackground, .downloadInBackgroundInfo:
return DataAndStorageSection.other.rawValue return DataAndStorageSection.other.rawValue
case .connectionHeader, .connectionProxy: case .connectionHeader, .connectionProxy:
return DataAndStorageSection.connection.rawValue return DataAndStorageSection.connection.rawValue
@ -143,22 +147,24 @@ private enum DataAndStorageEntry: ItemListNodeEntry {
return 11 return 11
case .shareSheet: case .shareSheet:
return 12 return 12
case .saveIncomingPhotos: case .widgetSettings:
return 13 return 13
case .saveEditedPhotos: case .saveIncomingPhotos:
return 14 return 14
case .openLinksIn: case .saveEditedPhotos:
return 15 return 15
case .downloadInBackground: case .openLinksIn:
return 16 return 16
case .downloadInBackgroundInfo: case .downloadInBackground:
return 17 return 17
case .connectionHeader: case .downloadInBackgroundInfo:
return 18 return 18
case .connectionProxy: case .connectionHeader:
return 19 return 19
case .enableSensitiveContent: case .connectionProxy:
return 20 return 20
case .enableSensitiveContent:
return 21
} }
} }
@ -242,6 +248,12 @@ private enum DataAndStorageEntry: ItemListNodeEntry {
} else { } else {
return false return false
} }
case let .widgetSettings(text):
if case .widgetSettings(text) = rhs {
return true
} else {
return false
}
case let .saveIncomingPhotos(lhsTheme, lhsText): case let .saveIncomingPhotos(lhsTheme, lhsText):
if case let .saveIncomingPhotos(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { if case let .saveIncomingPhotos(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true return true
@ -346,6 +358,10 @@ private enum DataAndStorageEntry: ItemListNodeEntry {
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: "", sectionId: self.section, style: .blocks, action: { return ItemListDisclosureItem(presentationData: presentationData, title: text, label: "", sectionId: self.section, style: .blocks, action: {
arguments.openIntents() arguments.openIntents()
}) })
case let .widgetSettings(text):
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: "", sectionId: self.section, style: .blocks, action: {
arguments.openWidgetSettings()
})
case let .saveIncomingPhotos(theme, text): case let .saveIncomingPhotos(theme, text):
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: "", sectionId: self.section, style: .blocks, action: { return ItemListDisclosureItem(presentationData: presentationData, title: text, label: "", sectionId: self.section, style: .blocks, action: {
arguments.openSaveIncomingPhotos() arguments.openSaveIncomingPhotos()
@ -489,6 +505,9 @@ private func dataAndStorageControllerEntries(state: DataAndStorageControllerStat
if #available(iOSApplicationExtension 13.2, iOS 13.2, *) { if #available(iOSApplicationExtension 13.2, iOS 13.2, *) {
entries.append(.shareSheet(presentationData.theme, presentationData.strings.ChatSettings_IntentsSettings)) entries.append(.shareSheet(presentationData.theme, presentationData.strings.ChatSettings_IntentsSettings))
} }
if #available(iOSApplicationExtension 14.0, iOS 14.0, *) {
entries.append(.widgetSettings(presentationData.strings.ChatSettings_WidgetSettings))
}
entries.append(.saveIncomingPhotos(presentationData.theme, presentationData.strings.Settings_SaveIncomingPhotos)) entries.append(.saveIncomingPhotos(presentationData.theme, presentationData.strings.Settings_SaveIncomingPhotos))
entries.append(.saveEditedPhotos(presentationData.theme, presentationData.strings.Settings_SaveEditedPhotos, data.generatedMediaStoreSettings.storeEditedPhotos)) entries.append(.saveEditedPhotos(presentationData.theme, presentationData.strings.Settings_SaveEditedPhotos, data.generatedMediaStoreSettings.storeEditedPhotos))
entries.append(.openLinksIn(presentationData.theme, presentationData.strings.ChatSettings_OpenLinksIn, defaultWebBrowser)) entries.append(.openLinksIn(presentationData.theme, presentationData.strings.ChatSettings_OpenLinksIn, defaultWebBrowser))
@ -641,6 +660,9 @@ public func dataAndStorageController(context: AccountContext, focusOnItemTag: Da
}, openIntents: { }, openIntents: {
let controller = intentsSettingsController(context: context) let controller = intentsSettingsController(context: context)
pushControllerImpl?(controller) pushControllerImpl?(controller)
}, openWidgetSettings: {
let controller = widgetSetupScreen(context: context)
pushControllerImpl?(controller)
}, toggleEnableSensitiveContent: { value in }, toggleEnableSensitiveContent: { value in
let _ = (contentSettingsConfiguration.get() let _ = (contentSettingsConfiguration.get()
|> take(1) |> take(1)

View File

@ -247,6 +247,9 @@ public final class SlotMachineAnimationNode: ASDisplayNode {
} }
} }
} }
public func setOverlayColor(_ color: UIColor?, animated: Bool) {
}
} }
class DiceAnimatedStickerNode: ASDisplayNode { class DiceAnimatedStickerNode: ASDisplayNode {
@ -350,4 +353,7 @@ class DiceAnimatedStickerNode: ASDisplayNode {
self.animationNode.updateLayout(size: self.bounds.size) self.animationNode.updateLayout(size: self.bounds.size)
self.animationNode.frame = self.bounds self.animationNode.frame = self.bounds
} }
public func setOverlayColor(_ color: UIColor?, animated: Bool) {
}
} }

View File

@ -1420,7 +1420,7 @@ public final class AccountViewTracker {
public func scheduledMessagesViewForLocation(_ chatLocation: ChatLocationInput, additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> { public func scheduledMessagesViewForLocation(_ chatLocation: ChatLocationInput, additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> {
if let account = self.account { if let account = self.account {
let signal = account.postbox.aroundMessageHistoryViewForLocation(chatLocation, anchor: .upperBound, count: 200, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tagMask: nil, namespaces: .just(Namespaces.Message.allScheduled), orderStatistics: [], additionalData: additionalData) let signal = account.postbox.aroundMessageHistoryViewForLocation(chatLocation, anchor: .upperBound, count: 200, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tagMask: nil, appendMessagesFromTheSameGroup: false, namespaces: .just(Namespaces.Message.allScheduled), orderStatistics: [], additionalData: additionalData)
return withState(signal, { [weak self] () -> Int32 in return withState(signal, { [weak self] () -> Int32 in
if let strongSelf = self { if let strongSelf = self {
return OSAtomicIncrement32(&strongSelf.nextViewId) return OSAtomicIncrement32(&strongSelf.nextViewId)
@ -1448,25 +1448,25 @@ public final class AccountViewTracker {
} }
} }
public func aroundMessageOfInterestHistoryViewForLocation(_ chatLocation: ChatLocationInput, count: Int, tagMask: MessageTags? = nil, orderStatistics: MessageHistoryViewOrderStatistics = [], additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> { public func aroundMessageOfInterestHistoryViewForLocation(_ chatLocation: ChatLocationInput, count: Int, tagMask: MessageTags? = nil, appendMessagesFromTheSameGroup: Bool = false, orderStatistics: MessageHistoryViewOrderStatistics = [], additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> {
if let account = self.account { if let account = self.account {
let signal = account.postbox.aroundMessageOfInterestHistoryViewForChatLocation(chatLocation, count: count, topTaggedMessageIdNamespaces: [Namespaces.Message.Cloud], tagMask: tagMask, namespaces: .not(Namespaces.Message.allScheduled), orderStatistics: orderStatistics, additionalData: wrappedHistoryViewAdditionalData(chatLocation: chatLocation, additionalData: additionalData)) let signal = account.postbox.aroundMessageOfInterestHistoryViewForChatLocation(chatLocation, count: count, topTaggedMessageIdNamespaces: [Namespaces.Message.Cloud], tagMask: tagMask, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: .not(Namespaces.Message.allScheduled), orderStatistics: orderStatistics, additionalData: wrappedHistoryViewAdditionalData(chatLocation: chatLocation, additionalData: additionalData))
return wrappedMessageHistorySignal(chatLocation: chatLocation, signal: signal, addHoleIfNeeded: true) return wrappedMessageHistorySignal(chatLocation: chatLocation, signal: signal, addHoleIfNeeded: true)
} else { } else {
return .never() return .never()
} }
} }
public func aroundIdMessageHistoryViewForLocation(_ chatLocation: ChatLocationInput, count: Int, ignoreRelatedChats: Bool, messageId: MessageId, tagMask: MessageTags? = nil, orderStatistics: MessageHistoryViewOrderStatistics = [], additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> { public func aroundIdMessageHistoryViewForLocation(_ chatLocation: ChatLocationInput, count: Int, ignoreRelatedChats: Bool, messageId: MessageId, tagMask: MessageTags? = nil, appendMessagesFromTheSameGroup: Bool = false, orderStatistics: MessageHistoryViewOrderStatistics = [], additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> {
if let account = self.account { if let account = self.account {
let signal = account.postbox.aroundIdMessageHistoryViewForLocation(chatLocation, count: count, ignoreRelatedChats: ignoreRelatedChats, messageId: messageId, topTaggedMessageIdNamespaces: [Namespaces.Message.Cloud], tagMask: tagMask, namespaces: .not(Namespaces.Message.allScheduled), orderStatistics: orderStatistics, additionalData: wrappedHistoryViewAdditionalData(chatLocation: chatLocation, additionalData: additionalData)) let signal = account.postbox.aroundIdMessageHistoryViewForLocation(chatLocation, count: count, ignoreRelatedChats: ignoreRelatedChats, messageId: messageId, topTaggedMessageIdNamespaces: [Namespaces.Message.Cloud], tagMask: tagMask, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: .not(Namespaces.Message.allScheduled), orderStatistics: orderStatistics, additionalData: wrappedHistoryViewAdditionalData(chatLocation: chatLocation, additionalData: additionalData))
return wrappedMessageHistorySignal(chatLocation: chatLocation, signal: signal, addHoleIfNeeded: false) return wrappedMessageHistorySignal(chatLocation: chatLocation, signal: signal, addHoleIfNeeded: false)
} else { } else {
return .never() return .never()
} }
} }
public func aroundMessageHistoryViewForLocation(_ chatLocation: ChatLocationInput, index: MessageHistoryAnchorIndex, anchorIndex: MessageHistoryAnchorIndex, count: Int, clipHoles: Bool = true, ignoreRelatedChats: Bool = false, fixedCombinedReadStates: MessageHistoryViewReadState?, tagMask: MessageTags? = nil, orderStatistics: MessageHistoryViewOrderStatistics = [], additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> { public func aroundMessageHistoryViewForLocation(_ chatLocation: ChatLocationInput, index: MessageHistoryAnchorIndex, anchorIndex: MessageHistoryAnchorIndex, count: Int, clipHoles: Bool = true, ignoreRelatedChats: Bool = false, fixedCombinedReadStates: MessageHistoryViewReadState?, tagMask: MessageTags? = nil, appendMessagesFromTheSameGroup: Bool = false, orderStatistics: MessageHistoryViewOrderStatistics = [], additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> {
if let account = self.account { if let account = self.account {
let inputAnchor: HistoryViewInputAnchor let inputAnchor: HistoryViewInputAnchor
switch index { switch index {
@ -1477,7 +1477,7 @@ public final class AccountViewTracker {
case let .message(index): case let .message(index):
inputAnchor = .index(index) inputAnchor = .index(index)
} }
let signal = account.postbox.aroundMessageHistoryViewForLocation(chatLocation, anchor: inputAnchor, count: count, clipHoles: clipHoles, ignoreRelatedChats: ignoreRelatedChats, fixedCombinedReadStates: fixedCombinedReadStates, topTaggedMessageIdNamespaces: [Namespaces.Message.Cloud], tagMask: tagMask, namespaces: .not(Namespaces.Message.allScheduled), orderStatistics: orderStatistics, additionalData: wrappedHistoryViewAdditionalData(chatLocation: chatLocation, additionalData: additionalData)) let signal = account.postbox.aroundMessageHistoryViewForLocation(chatLocation, anchor: inputAnchor, count: count, clipHoles: clipHoles, ignoreRelatedChats: ignoreRelatedChats, fixedCombinedReadStates: fixedCombinedReadStates, topTaggedMessageIdNamespaces: [Namespaces.Message.Cloud], tagMask: tagMask, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: .not(Namespaces.Message.allScheduled), orderStatistics: orderStatistics, additionalData: wrappedHistoryViewAdditionalData(chatLocation: chatLocation, additionalData: additionalData))
return wrappedMessageHistorySignal(chatLocation: chatLocation, signal: signal, addHoleIfNeeded: false) return wrappedMessageHistorySignal(chatLocation: chatLocation, signal: signal, addHoleIfNeeded: false)
} else { } else {
return .never() return .never()

View File

@ -269,6 +269,11 @@ final class HistoryViewStateValidationContexts {
for entry in view.entries { for entry in view.entries {
if historyState.matchesPeerId(entry.message.id.peerId) && entry.message.id.namespace == Namespaces.Message.Cloud { if historyState.matchesPeerId(entry.message.id.peerId) && entry.message.id.namespace == Namespaces.Message.Cloud {
if let tag = view.tagMask {
if !entry.message.tags.contains(tag) {
continue
}
}
if !historyState.isMessageValid(entry.message) { if !historyState.isMessageValid(entry.message) {
addToRange(entry.message.id, &rangesToInvalidate) addToRange(entry.message.id, &rangesToInvalidate)
} else { } else {

View File

@ -3368,7 +3368,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
location = .Initial(count: count) location = .Initial(count: count)
} }
return (chatHistoryViewForLocation(ChatHistoryLocationInput(content: location, id: 0), context: context, chatLocation: .peer(peerId), chatLocationContextHolder: Atomic<ChatLocationContextHolder?>(value: nil), scheduled: false, fixedCombinedReadStates: nil, tagMask: MessageTags.pinned, additionalData: [], orderStatistics: .combinedLocation) return (chatHistoryViewForLocation(ChatHistoryLocationInput(content: location, id: 0), context: context, chatLocation: .peer(peerId), chatLocationContextHolder: Atomic<ChatLocationContextHolder?>(value: nil), scheduled: false, fixedCombinedReadStates: nil, tagMask: MessageTags.pinned, appendMessagesFromTheSameGroup: false, additionalData: [], orderStatistics: .combinedLocation)
|> castError(Bool.self) |> castError(Bool.self)
|> mapToSignal { update -> Signal<ChatHistoryViewUpdate, Bool> in |> mapToSignal { update -> Signal<ChatHistoryViewUpdate, Bool> in
switch update { switch update {
@ -5152,69 +5152,83 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return return
} else { } else {
let continueAction: () -> Void = {
guard let strongSelf = self else {
return
}
var pinImmediately = false
if let channel = peer as? TelegramChannel, case .broadcast = channel.info {
pinImmediately = true
} else if let _ = peer as? TelegramUser {
pinImmediately = true
}
if pinImmediately {
pinAction(true, false)
} else {
let topPinnedMessage: Signal<ChatPinnedMessage?, NoError> = strongSelf.topPinnedMessageSignal(latest: true)
|> take(1)
let _ = (topPinnedMessage
|> deliverOnMainQueue).start(next: { value in
guard let strongSelf = self else {
return
}
let title: String?
let text: String
let actionLayout: TextAlertContentActionLayout
let actions: [TextAlertAction]
if let value = value, value.message.id > messageId {
title = strongSelf.presentationData.strings.Conversation_PinOlderMessageAlertTitle
text = strongSelf.presentationData.strings.Conversation_PinOlderMessageAlertText
actionLayout = .vertical
actions = [
TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Conversation_PinMessageAlertPin, action: {
pinAction(false, false)
}),
TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {
})
]
} else {
title = nil
text = strongSelf.presentationData.strings.Conversation_PinMessageAlertGroup
actionLayout = .horizontal
actions = [
TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Conversation_PinMessageAlert_OnlyPin, action: {
pinAction(false, false)
}),
TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_Yes, action: {
pinAction(true, false)
})
]
}
strongSelf.present(textAlertController(context: strongSelf.context, title: title, text: text, actions: actions, actionLayout: actionLayout), in: .window(.root))
})
}
}
if let contextController = contextController { if let contextController = contextController {
contextController.dismiss(completion: { var contextItems: [ContextMenuItem] = []
continueAction()
}) contextItems.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Conversation_PinMessageAlert_PinAndNotifyMembers, textColor: .primary, icon: { _ in nil }, action: { c, _ in
c.dismiss(completion: {
pinAction(true, false)
})
})))
contextItems.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Conversation_PinMessageAlert_OnlyPin, textColor: .primary, icon: { _ in nil }, action: { c, _ in
c.dismiss(completion: {
pinAction(false, false)
})
})))
contextController.setItems(.single(contextItems))
return
} else { } else {
let continueAction: () -> Void = {
guard let strongSelf = self else {
return
}
var pinImmediately = false
if let channel = peer as? TelegramChannel, case .broadcast = channel.info {
pinImmediately = true
} else if let _ = peer as? TelegramUser {
pinImmediately = true
}
if pinImmediately {
pinAction(true, false)
} else {
let topPinnedMessage: Signal<ChatPinnedMessage?, NoError> = strongSelf.topPinnedMessageSignal(latest: true)
|> take(1)
let _ = (topPinnedMessage
|> deliverOnMainQueue).start(next: { value in
guard let strongSelf = self else {
return
}
let title: String?
let text: String
let actionLayout: TextAlertContentActionLayout
let actions: [TextAlertAction]
if let value = value, value.message.id > messageId {
title = strongSelf.presentationData.strings.Conversation_PinOlderMessageAlertTitle
text = strongSelf.presentationData.strings.Conversation_PinOlderMessageAlertText
actionLayout = .vertical
actions = [
TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Conversation_PinMessageAlertPin, action: {
pinAction(false, false)
}),
TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {
})
]
} else {
title = nil
text = strongSelf.presentationData.strings.Conversation_PinMessageAlertGroup
actionLayout = .horizontal
actions = [
TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Conversation_PinMessageAlert_OnlyPin, action: {
pinAction(false, false)
}),
TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_Yes, action: {
pinAction(true, false)
})
]
}
strongSelf.present(textAlertController(context: strongSelf.context, title: title, text: text, actions: actions, actionLayout: actionLayout), in: .window(.root))
})
}
}
continueAction() continueAction()
} }
} }

View File

@ -593,8 +593,10 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
public init(context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>, tagMask: MessageTags?, source: ChatHistoryListSource = .default, subject: ChatControllerSubject?, controllerInteraction: ChatControllerInteraction, selectedMessages: Signal<Set<MessageId>?, NoError>, mode: ChatHistoryListMode = .bubbles) { public init(context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>, tagMask: MessageTags?, source: ChatHistoryListSource = .default, subject: ChatControllerSubject?, controllerInteraction: ChatControllerInteraction, selectedMessages: Signal<Set<MessageId>?, NoError>, mode: ChatHistoryListMode = .bubbles) {
var tagMask = tagMask var tagMask = tagMask
var appendMessagesFromTheSameGroup = false
if case .pinnedMessages = subject { if case .pinnedMessages = subject {
tagMask = .pinned tagMask = .pinned
appendMessagesFromTheSameGroup = true
} }
self.context = context self.context = context
@ -720,7 +722,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
historyViewUpdate = self.chatHistoryLocationPromise.get() historyViewUpdate = self.chatHistoryLocationPromise.get()
|> distinctUntilChanged |> distinctUntilChanged
|> mapToSignal { location in |> mapToSignal { location in
return chatHistoryViewForLocation(location, context: context, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder, scheduled: isScheduledMessages, fixedCombinedReadStates: fixedCombinedReadStates.with { $0 }, tagMask: tagMask, additionalData: additionalData) return chatHistoryViewForLocation(location, context: context, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder, scheduled: isScheduledMessages, fixedCombinedReadStates: fixedCombinedReadStates.with { $0 }, tagMask: tagMask, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, additionalData: additionalData)
|> beforeNext { viewUpdate in |> beforeNext { viewUpdate in
switch viewUpdate { switch viewUpdate {
case let .HistoryView(view, _, _, _, _, _, _): case let .HistoryView(view, _, _, _, _, _, _):

View File

@ -19,7 +19,7 @@ func preloadedChatHistoryViewForLocation(_ location: ChatHistoryLocationInput, c
tagMask = .pinned tagMask = .pinned
} }
return (chatHistoryViewForLocation(location, context: context, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder, scheduled: isScheduled, fixedCombinedReadStates: fixedCombinedReadStates, tagMask: tagMask, additionalData: additionalData, orderStatistics: orderStatistics) return (chatHistoryViewForLocation(location, context: context, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder, scheduled: isScheduled, fixedCombinedReadStates: fixedCombinedReadStates, tagMask: tagMask, appendMessagesFromTheSameGroup: false, additionalData: additionalData, orderStatistics: orderStatistics)
|> castError(Bool.self) |> castError(Bool.self)
|> mapToSignal { update -> Signal<ChatHistoryViewUpdate, Bool> in |> mapToSignal { update -> Signal<ChatHistoryViewUpdate, Bool> in
switch update { switch update {
@ -37,7 +37,7 @@ func preloadedChatHistoryViewForLocation(_ location: ChatHistoryLocationInput, c
|> restartIfError |> restartIfError
} }
func chatHistoryViewForLocation(_ location: ChatHistoryLocationInput, context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>, scheduled: Bool, fixedCombinedReadStates: MessageHistoryViewReadState?, tagMask: MessageTags?, additionalData: [AdditionalMessageHistoryViewData], orderStatistics: MessageHistoryViewOrderStatistics = []) -> Signal<ChatHistoryViewUpdate, NoError> { func chatHistoryViewForLocation(_ location: ChatHistoryLocationInput, context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>, scheduled: Bool, fixedCombinedReadStates: MessageHistoryViewReadState?, tagMask: MessageTags?, appendMessagesFromTheSameGroup: Bool, additionalData: [AdditionalMessageHistoryViewData], orderStatistics: MessageHistoryViewOrderStatistics = []) -> Signal<ChatHistoryViewUpdate, NoError> {
let account = context.account let account = context.account
if scheduled { if scheduled {
var first = true var first = true
@ -84,9 +84,9 @@ func chatHistoryViewForLocation(_ location: ChatHistoryLocationInput, context: A
var fadeIn = false var fadeIn = false
let signal: Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> let signal: Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError>
if let tagMask = tagMask { if let tagMask = tagMask {
signal = account.viewTracker.aroundMessageHistoryViewForLocation(context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), index: .upperBound, anchorIndex: .upperBound, count: count, ignoreRelatedChats: ignoreRelatedChats, fixedCombinedReadStates: nil, tagMask: tagMask, orderStatistics: orderStatistics) signal = account.viewTracker.aroundMessageHistoryViewForLocation(context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), index: .upperBound, anchorIndex: .upperBound, count: count, ignoreRelatedChats: ignoreRelatedChats, fixedCombinedReadStates: nil, tagMask: tagMask, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, orderStatistics: orderStatistics)
} else { } else {
signal = account.viewTracker.aroundMessageOfInterestHistoryViewForLocation(context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), count: count, tagMask: tagMask, orderStatistics: orderStatistics, additionalData: additionalData) signal = account.viewTracker.aroundMessageOfInterestHistoryViewForLocation(context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), count: count, tagMask: tagMask, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, orderStatistics: orderStatistics, additionalData: additionalData)
} }
return signal return signal
|> map { view, updateType, initialData -> ChatHistoryViewUpdate in |> map { view, updateType, initialData -> ChatHistoryViewUpdate in
@ -170,9 +170,9 @@ func chatHistoryViewForLocation(_ location: ChatHistoryLocationInput, context: A
let signal: Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> let signal: Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError>
switch searchLocation { switch searchLocation {
case let .index(index): case let .index(index):
signal = account.viewTracker.aroundMessageHistoryViewForLocation(context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), index: .message(index), anchorIndex: .message(index), count: count, ignoreRelatedChats: ignoreRelatedChats, fixedCombinedReadStates: nil, tagMask: tagMask, orderStatistics: orderStatistics, additionalData: additionalData) signal = account.viewTracker.aroundMessageHistoryViewForLocation(context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), index: .message(index), anchorIndex: .message(index), count: count, ignoreRelatedChats: ignoreRelatedChats, fixedCombinedReadStates: nil, tagMask: tagMask, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, orderStatistics: orderStatistics, additionalData: additionalData)
case let .id(id): case let .id(id):
signal = account.viewTracker.aroundIdMessageHistoryViewForLocation(context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), count: count, ignoreRelatedChats: ignoreRelatedChats, messageId: id, tagMask: tagMask, orderStatistics: orderStatistics, additionalData: additionalData) signal = account.viewTracker.aroundIdMessageHistoryViewForLocation(context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), count: count, ignoreRelatedChats: ignoreRelatedChats, messageId: id, tagMask: tagMask, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, orderStatistics: orderStatistics, additionalData: additionalData)
} }
return signal |> map { view, updateType, initialData -> ChatHistoryViewUpdate in return signal |> map { view, updateType, initialData -> ChatHistoryViewUpdate in
@ -220,7 +220,7 @@ func chatHistoryViewForLocation(_ location: ChatHistoryLocationInput, context: A
} }
case let .Navigation(index, anchorIndex, count, highlight): case let .Navigation(index, anchorIndex, count, highlight):
var first = true var first = true
return account.viewTracker.aroundMessageHistoryViewForLocation(context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), index: index, anchorIndex: anchorIndex, count: count, ignoreRelatedChats: ignoreRelatedChats, fixedCombinedReadStates: fixedCombinedReadStates, tagMask: tagMask, orderStatistics: orderStatistics, additionalData: additionalData) |> map { view, updateType, initialData -> ChatHistoryViewUpdate in return account.viewTracker.aroundMessageHistoryViewForLocation(context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), index: index, anchorIndex: anchorIndex, count: count, ignoreRelatedChats: ignoreRelatedChats, fixedCombinedReadStates: fixedCombinedReadStates, tagMask: tagMask, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, orderStatistics: orderStatistics, additionalData: additionalData) |> map { view, updateType, initialData -> ChatHistoryViewUpdate in
let (cachedData, cachedDataMessages, readStateData) = extractAdditionalData(view: view, chatLocation: chatLocation) let (cachedData, cachedDataMessages, readStateData) = extractAdditionalData(view: view, chatLocation: chatLocation)
let genericType: ViewUpdateType let genericType: ViewUpdateType
@ -236,7 +236,7 @@ func chatHistoryViewForLocation(_ location: ChatHistoryLocationInput, context: A
let directionHint: ListViewScrollToItemDirectionHint = sourceIndex > index ? .Down : .Up let directionHint: ListViewScrollToItemDirectionHint = sourceIndex > index ? .Down : .Up
let chatScrollPosition = ChatHistoryViewScrollPosition.index(index: index, position: scrollPosition, directionHint: directionHint, animated: animated, highlight: highlight) let chatScrollPosition = ChatHistoryViewScrollPosition.index(index: index, position: scrollPosition, directionHint: directionHint, animated: animated, highlight: highlight)
var first = true var first = true
return account.viewTracker.aroundMessageHistoryViewForLocation(context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), index: index, anchorIndex: anchorIndex, count: 128, ignoreRelatedChats: ignoreRelatedChats, fixedCombinedReadStates: fixedCombinedReadStates, tagMask: tagMask, orderStatistics: orderStatistics, additionalData: additionalData) return account.viewTracker.aroundMessageHistoryViewForLocation(context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), index: index, anchorIndex: anchorIndex, count: 128, ignoreRelatedChats: ignoreRelatedChats, fixedCombinedReadStates: fixedCombinedReadStates, tagMask: tagMask, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, orderStatistics: orderStatistics, additionalData: additionalData)
|> map { view, updateType, initialData -> ChatHistoryViewUpdate in |> map { view, updateType, initialData -> ChatHistoryViewUpdate in
let (cachedData, cachedDataMessages, readStateData) = extractAdditionalData(view: view, chatLocation: chatLocation) let (cachedData, cachedDataMessages, readStateData) = extractAdditionalData(view: view, chatLocation: chatLocation)

View File

@ -27,7 +27,7 @@ private let inlineBotPrefixFont = Font.regular(14.0)
private let inlineBotNameFont = nameFont private let inlineBotNameFont = nameFont
protocol GenericAnimatedStickerNode: ASDisplayNode { protocol GenericAnimatedStickerNode: ASDisplayNode {
func setOverlayColor(_ color: UIColor?, animated: Bool)
} }
extension AnimatedStickerNode: GenericAnimatedStickerNode { extension AnimatedStickerNode: GenericAnimatedStickerNode {
@ -1542,8 +1542,10 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
if highlighted { if highlighted {
self.imageNode.setOverlayColor(item.presentationData.theme.theme.chat.message.mediaHighlightOverlayColor, animated: false) self.imageNode.setOverlayColor(item.presentationData.theme.theme.chat.message.mediaHighlightOverlayColor, animated: false)
self.animationNode?.setOverlayColor(item.presentationData.theme.theme.chat.message.mediaHighlightOverlayColor, animated: false)
} else { } else {
self.imageNode.setOverlayColor(nil, animated: animated) self.imageNode.setOverlayColor(nil, animated: animated)
self.animationNode?.setOverlayColor(nil, animated: false)
} }
} }
} }

Some files were not shown because too many files have changed in this diff Show More