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

This commit is contained in:
Ilya Laktyushin 2021-01-17 10:21:02 +03:00
commit d5a25602ce
41 changed files with 1831 additions and 464 deletions

159
Makefile
View File

@ -1,159 +0,0 @@
.PHONY : kill_xcode clean bazel_app_debug_arm64 bazel_app_debug_sim_arm64 bazel_app_arm64 bazel_app_armv7 bazel_app check_sandbox_debug_build bazel_project bazel_project_noextensions
APP_VERSION="7.3"
CORE_COUNT=$(shell sysctl -n hw.logicalcpu)
CORE_COUNT_MINUS_ONE=$(shell expr ${CORE_COUNT} \- 1)
BAZEL=$(shell which bazel)
ifneq ($(BAZEL_HTTP_CACHE_URL),)
export BAZEL_CACHE_FLAGS=\
--remote_cache="$(BAZEL_HTTP_CACHE_URL)" --experimental_remote_downloader="$(BAZEL_HTTP_CACHE_URL)"
else ifneq ($(BAZEL_CACHE_DIR),)
export BAZEL_CACHE_FLAGS=\
--disk_cache="${BAZEL_CACHE_DIR}"
endif
ifneq ($(BAZEL_KEEP_GOING),)
export BAZEL_KEEP_GOING_FLAGS=\
-k
else ifneq ($(BAZEL_CACHE_DIR),)
export BAZEL_KEEP_GOING_FLAGS=
endif
BAZEL_COMMON_FLAGS=\
--announce_rc \
--features=swift.use_global_module_cache \
--features=swift.split_derived_files_generation \
--features=swift.skip_function_bodies_for_derived_files \
--jobs=${CORE_COUNT} \
${BAZEL_KEEP_GOING_FLAGS} \
BAZEL_DEBUG_FLAGS=\
--features=swift.enable_batch_mode \
--swiftcopt=-j${CORE_COUNT_MINUS_ONE} \
--experimental_guard_against_concurrent_changes \
BAZEL_SANDBOX_FLAGS=\
--strategy=Genrule=sandboxed \
--spawn_strategy=sandboxed \
--strategy=SwiftCompile=sandboxed \
# --num-threads 0 forces swiftc to generate one object file per module; it:
# 1. resolves issues with the linker caused by swift-objc mixing.
# 2. makes the resulting binaries significantly smaller (up to 9% for this project).
BAZEL_OPT_FLAGS=\
--features=swift.opt_uses_wmo \
--features=swift.opt_uses_osize \
--swiftcopt='-num-threads' --swiftcopt='0' \
--features=dead_strip \
--objc_enable_binary_stripping \
--apple_bitcode=watchos=embedded \
kill_xcode:
killall Xcode || true
clean:
"${BAZEL}" clean --expunge
bazel_app_debug_arm64:
APP_VERSION="${APP_VERSION}" \
BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \
BAZEL_HTTP_CACHE_URL="${BAZEL_HTTP_CACHE_URL}" \
TELEGRAM_DISABLE_EXTENSIONS="0" \
build-system/prepare-build.sh Telegram distribution
"${BAZEL}" build Telegram/Telegram ${BAZEL_CACHE_FLAGS} ${BAZEL_COMMON_FLAGS} ${BAZEL_DEBUG_FLAGS} \
-c dbg \
--ios_multi_cpus=arm64 \
--watchos_cpus=armv7k,arm64_32 \
--verbose_failures
bazel_app_debug_sim_arm64:
APP_VERSION="${APP_VERSION}" \
BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \
BAZEL_HTTP_CACHE_URL="${BAZEL_HTTP_CACHE_URL}" \
TELEGRAM_DISABLE_EXTENSIONS="0" \
build-system/prepare-build.sh Telegram distribution
"${BAZEL}" build Telegram/Telegram ${BAZEL_CACHE_FLAGS} ${BAZEL_COMMON_FLAGS} ${BAZEL_DEBUG_FLAGS} \
-c dbg \
--ios_multi_cpus=sim_arm64 \
--watchos_cpus=armv7k,arm64_32 \
--verbose_failures
bazel_app_arm64:
APP_VERSION="${APP_VERSION}" \
BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \
BAZEL_HTTP_CACHE_URL="${BAZEL_HTTP_CACHE_URL}" \
TELEGRAM_DISABLE_EXTENSIONS="0" \
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=arm64 \
--watchos_cpus=armv7k,arm64_32 \
--apple_generate_dsym \
--output_groups=+dsyms \
--verbose_failures
bazel_app_armv7:
APP_VERSION="${APP_VERSION}" \
BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \
BAZEL_HTTP_CACHE_URL="${BAZEL_HTTP_CACHE_URL}" \
TELEGRAM_DISABLE_EXTENSIONS="0" \
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 \
--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}" \
TELEGRAM_DISABLE_EXTENSIONS="0" \
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 \
--apple_generate_dsym \
--output_groups=+dsyms \
--verbose_failures
check_sandbox_debug_build:
APP_VERSION="${APP_VERSION}" \
BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \
BAZEL_HTTP_CACHE_URL="${BAZEL_HTTP_CACHE_URL}" \
TELEGRAM_DISABLE_EXTENSIONS="0" \
build-system/prepare-build.sh Telegram distribution
"${BAZEL}" build Telegram/Telegram ${BAZEL_CACHE_FLAGS} ${BAZEL_COMMON_FLAGS} ${BAZEL_DEBUG_FLAGS} ${BAZEL_SANDBOX_FLAGS} \
-c opt \
--ios_multi_cpus=arm64 \
--watchos_cpus=armv7k,arm64_32 \
--apple_generate_dsym \
--output_groups=+dsyms \
--verbose_failures
bazel_project: kill_xcode
APP_VERSION="${APP_VERSION}" \
BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \
BAZEL_HTTP_CACHE_URL="${BAZEL_HTTP_CACHE_URL}" \
TELEGRAM_DISABLE_EXTENSIONS="0" \
build-system/prepare-build.sh Telegram development
APP_VERSION="${APP_VERSION}" \
BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \
BAZEL_HTTP_CACHE_URL="${BAZEL_HTTP_CACHE_URL}" \
build-system/generate-xcode-project.sh Telegram
bazel_project_noextensions: kill_xcode
APP_VERSION="${APP_VERSION}" \
BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \
BAZEL_HTTP_CACHE_URL="${BAZEL_HTTP_CACHE_URL}" \
TELEGRAM_DISABLE_EXTENSIONS="1" \
build-system/prepare-build.sh Telegram development
APP_VERSION="${APP_VERSION}" \
BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \
BAZEL_HTTP_CACHE_URL="${BAZEL_HTTP_CACHE_URL}" \
build-system/generate-xcode-project.sh Telegram

100
README.md
View File

@ -1,16 +1,96 @@
# Telegram iOS Source Code Compilation Guide
1. Install the brew package manager, if you havent already.
2. Install the packages yasm, cmake:
```
brew install yasm cmake
```
3. Clone the project from GitHub:
We welcome all developers to use our API and source code to create applications on our platform.
There are several things we require from **all developers** for the moment.
# Creating your Telegram Application
1. [**Obtain your own api_id**](https://core.telegram.org/api/obtaining_api_id) for your application.
2. Please **do not** use the name Telegram for your app — or make sure your users understand that it is unofficial.
3. Kindly **do not** use our standard logo (white paper plane in a blue circle) as your app's logo.
3. Please study our [**security guidelines**](https://core.telegram.org/mtproto/security_guidelines) and take good care of your users' data and privacy.
4. Please remember to publish **your** code too in order to comply with the licences.
# Compilation Guide
1. Install Xcode (directly from https://developer.apple.com/download/more or using the App Store).
2. Clone the project from GitHub:
```
git clone --recursive https://github.com/TelegramMessenger/Telegram-iOS.git
```
4. Open Telegram-iOS.workspace.
5. Open the Telegram-iOS-Fork scheme.
6. Start the compilation process.
7. To run the app on your device, you will need to set the correct values for the signature, .entitlements files and package IDs in accordance with your developer account values.
3. Download Bazel 3.7.0
```
mkdir -p $HOME/bazel-dist
cd $HOME/bazel-dist
curl -O -L https://github.com/bazelbuild/bazel/releases/download/3.7.0/bazel-3.7.0-darwin-x86_64
mv bazel-3.7.0* bazel
```
Verify that it's working
```
chmod +x bazel
./bazel --version
```
4. Adjust configuration parameters
```
mkdir -p $HOME/telegram-configuration
cp -R build-system/example-configuration/* $HOME/telegram-configuration/
```
- Modify the values in `variables.bzl`
- Replace the provisioning profiles in `provisioning` with valid files
5. (Optional) Create a build cache directory to speed up rebuilds
```
mkdir -p "$HOME/telegram-bazel-cache"
```
5. Build the app
```
python3 build-system/Make/Make.py \
--bazel="$HOME/bazel-dist/bazel" \
--cacheDir="$HOME/telegram-bazel-cache" \
build \
--configurationPath="$HOME/telegram-configuration" \
--buildNumber=100001 \
--configuration=release_universal
```
6. (Optional) Generate an Xcode project
```
python3 build-system/Make/Make.py \
--bazel="$HOME/bazel-dist/bazel" \
--cacheDir="$HOME/telegram-bazel-cache" \
generateProject \
--configurationPath="$HOME/telegram-configuration" \
--disableExtensions
```
Tip: use `--disableExtensions` when developing to speed up development by not building application extensions.
# Tips
Bazel is used to build the app. To simplify the development setup a helper script is provided (`build-system/Make/Make.py`). See help:
```
python3 build-system/Make/Make.py --help
python3 build-system/Make/Make.py build --help
python3 build-system/Make/Make.py generateProject --help
```
Each release is built using specific Xcode and Bazel versions (see `versions.json`). The helper script checks the versions of installed software and reports an error if they don't match the ones specified in `versions.json`. There are flags that allow to bypass these checks:
```
python3 build-system/Make/Make.py --overrideBazelVersion build ... # Don't check the version of Bazel
python3 build-system/Make/Make.py --overrideXcodeVersion build ... # Don't check the version of Xcode
```

View File

@ -1,3 +1,7 @@
load("@bazel_skylib//rules:common_settings.bzl",
"bool_flag",
)
load("@build_bazel_rules_apple//apple:ios.bzl",
"ios_application",
"ios_extension",
@ -18,13 +22,10 @@ load("//build-system/bazel-utils:plist_fragment.bzl",
)
load(
"//build-input/data:variables.bzl",
"telegram_build_number",
"telegram_version",
"@build_configuration//:variables.bzl",
"telegram_bundle_id",
"telegram_aps_environment",
"telegram_team_id",
"telegram_disable_extensions",
)
config_setting(
@ -34,6 +35,19 @@ config_setting(
},
)
bool_flag(
name = "disableExtensions",
build_setting_default = False,
visibility = ["//visibility:public"],
)
config_setting(
name = "disableExtensionsSetting",
flag_values = {
":disableExtensions": "True",
},
)
genrule(
name = "empty",
outs = ["empty.swift"],
@ -190,14 +204,20 @@ swift_library(
)
plist_fragment(
name = "AdditionalInfoPlist",
name = "BuildNumberInfoPlist",
extension = "plist",
template =
"""
<key>CFBundleShortVersionString</key>
<string>{telegram_version}</string>
<key>CFBundleVersion</key>
<string>{telegram_build_number}</string>
<string>{buildNumber}</string>
"""
)
plist_fragment(
name = "UrlTypesInfoPlist",
extension = "plist",
template =
"""
<key>CFBundleURLTypes</key>
<array>
<dict>
@ -210,16 +230,6 @@ plist_fragment(
<string>telegram</string>
</array>
</dict>
<dict>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>CFBundleURLName</key>
<string>{telegram_bundle_id}.ton</string>
<key>CFBundleURLSchemes</key>
<array>
<string>ton</string>
</array>
</dict>
<dict>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
@ -232,8 +242,6 @@ plist_fragment(
</dict>
</array>
""".format(
telegram_version = telegram_version,
telegram_build_number = telegram_build_number,
telegram_bundle_id = telegram_bundle_id,
)
)
@ -371,13 +379,8 @@ plist_fragment(
template =
"""
<key>CFBundleShortVersionString</key>
<string>{telegram_version}</string>
<key>CFBundleVersion</key>
<string>{telegram_build_number}</string>
""".format(
telegram_version = telegram_version,
telegram_build_number = telegram_build_number,
)
<string>{telegramVersion}</string>
"""
)
plist_fragment(
@ -478,11 +481,12 @@ watchos_extension(
infoplists = [
":WatchExtensionInfoPlist",
":VersionInfoPlist",
":BuildNumberInfoPlist",
":AppNameInfoPlist",
":WatchExtensionNSExtensionInfoPlist",
],
minimum_os_version = "5.0",
provisioning_profile = "//build-input/data/provisioning-profiles:WatchExtension.mobileprovision",
provisioning_profile = "@build_configuration//provisioning:WatchExtension.mobileprovision",
resources = [
":TelegramWatchExtensionResources",
],
@ -505,11 +509,12 @@ watchos_application(
infoplists = [
":WatchAppInfoPlist",
":VersionInfoPlist",
"BuildNumberInfoPlist",
":AppNameInfoPlist",
":WatchAppCompanionInfoPlist",
],
minimum_os_version = "5.0",
provisioning_profile = "//build-input/data/provisioning-profiles:WatchApp.mobileprovision",
provisioning_profile = "@build_configuration//provisioning:WatchApp.mobileprovision",
resources = [
":TelegramWatchAppResources",
":TelegramWatchAppAssets",
@ -528,20 +533,14 @@ plist_fragment(
"""
<key>CFBundleIdentifier</key>
<string>{telegram_bundle_id}.MtProtoKit</string>
<key>CFBundleVersion</key>
<string>{telegram_build_number}</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleName</key>
<string>MtProtoKit</string>
<key>CFBundleShortVersionString</key>
<string>{telegram_version}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
""".format(
telegram_bundle_id = telegram_bundle_id,
telegram_version = telegram_version,
telegram_build_number = telegram_build_number,
)
)
@ -556,6 +555,8 @@ ios_framework(
],
infoplists = [
":MtProtoKitInfoPlist",
":BuildNumberInfoPlist",
":VersionInfoPlist",
],
minimum_os_version = "9.0",
ipa_post_processor = strip_framework,
@ -571,20 +572,14 @@ plist_fragment(
"""
<key>CFBundleIdentifier</key>
<string>{telegram_bundle_id}.SwiftSignalKit</string>
<key>CFBundleVersion</key>
<string>{telegram_build_number}</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleName</key>
<string>SwiftSignalKit</string>
<key>CFBundleShortVersionString</key>
<string>{telegram_version}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
""".format(
telegram_bundle_id = telegram_bundle_id,
telegram_version = telegram_version,
telegram_build_number = telegram_build_number,
)
)
@ -599,6 +594,8 @@ ios_framework(
],
infoplists = [
":SwiftSignalKitInfoPlist",
":BuildNumberInfoPlist",
":VersionInfoPlist",
],
minimum_os_version = "9.0",
ipa_post_processor = strip_framework,
@ -614,20 +611,14 @@ plist_fragment(
"""
<key>CFBundleIdentifier</key>
<string>{telegram_bundle_id}.Postbox</string>
<key>CFBundleVersion</key>
<string>{telegram_build_number}</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleName</key>
<string>Postbox</string>
<key>CFBundleShortVersionString</key>
<string>{telegram_version}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
""".format(
telegram_bundle_id = telegram_bundle_id,
telegram_version = telegram_version,
telegram_build_number = telegram_build_number,
)
)
@ -642,6 +633,8 @@ ios_framework(
],
infoplists = [
":PostboxInfoPlist",
":BuildNumberInfoPlist",
":VersionInfoPlist",
],
frameworks = [
":SwiftSignalKitFramework",
@ -660,20 +653,14 @@ plist_fragment(
"""
<key>CFBundleIdentifier</key>
<string>{telegram_bundle_id}.TelegramApi</string>
<key>CFBundleVersion</key>
<string>{telegram_build_number}</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleName</key>
<string>TelegramApi</string>
<key>CFBundleShortVersionString</key>
<string>{telegram_version}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
""".format(
telegram_bundle_id = telegram_bundle_id,
telegram_version = telegram_version,
telegram_build_number = telegram_build_number,
)
)
@ -688,6 +675,8 @@ ios_framework(
],
infoplists = [
":TelegramApiInfoPlist",
":BuildNumberInfoPlist",
":VersionInfoPlist",
],
minimum_os_version = "9.0",
ipa_post_processor = strip_framework,
@ -703,20 +692,14 @@ plist_fragment(
"""
<key>CFBundleIdentifier</key>
<string>{telegram_bundle_id}.SyncCore</string>
<key>CFBundleVersion</key>
<string>{telegram_build_number}</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleName</key>
<string>SyncCore</string>
<key>CFBundleShortVersionString</key>
<string>{telegram_version}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
""".format(
telegram_bundle_id = telegram_bundle_id,
telegram_version = telegram_version,
telegram_build_number = telegram_build_number,
)
)
@ -731,6 +714,8 @@ ios_framework(
],
infoplists = [
":SyncCoreInfoPlist",
":BuildNumberInfoPlist",
":VersionInfoPlist",
],
frameworks = [
":SwiftSignalKitFramework",
@ -750,20 +735,14 @@ plist_fragment(
"""
<key>CFBundleIdentifier</key>
<string>{telegram_bundle_id}.TelegramCore</string>
<key>CFBundleVersion</key>
<string>{telegram_build_number}</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleName</key>
<string>TelegramCore</string>
<key>CFBundleShortVersionString</key>
<string>{telegram_version}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
""".format(
telegram_bundle_id = telegram_bundle_id,
telegram_version = telegram_version,
telegram_build_number = telegram_build_number,
)
)
@ -778,13 +757,14 @@ ios_framework(
],
infoplists = [
":TelegramCoreInfoPlist",
":BuildNumberInfoPlist",
":VersionInfoPlist",
],
frameworks = [
":MtProtoKitFramework",
":SwiftSignalKitFramework",
":PostboxFramework",
":SyncCoreFramework",
#":TelegramApiFramework",
],
minimum_os_version = "9.0",
ipa_post_processor = strip_framework,
@ -800,20 +780,14 @@ plist_fragment(
"""
<key>CFBundleIdentifier</key>
<string>{telegram_bundle_id}.AsyncDisplayKit</string>
<key>CFBundleVersion</key>
<string>{telegram_build_number}</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleName</key>
<string>AsyncDisplayKit</string>
<key>CFBundleShortVersionString</key>
<string>{telegram_version}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
""".format(
telegram_bundle_id = telegram_bundle_id,
telegram_version = telegram_version,
telegram_build_number = telegram_build_number,
)
)
@ -828,6 +802,8 @@ ios_framework(
],
infoplists = [
":AsyncDisplayKitInfoPlist",
":BuildNumberInfoPlist",
":VersionInfoPlist",
],
minimum_os_version = "9.0",
ipa_post_processor = strip_framework,
@ -843,20 +819,14 @@ plist_fragment(
"""
<key>CFBundleIdentifier</key>
<string>{telegram_bundle_id}.Display</string>
<key>CFBundleVersion</key>
<string>{telegram_build_number}</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleName</key>
<string>Display</string>
<key>CFBundleShortVersionString</key>
<string>{telegram_version}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
""".format(
telegram_bundle_id = telegram_bundle_id,
telegram_version = telegram_version,
telegram_build_number = telegram_build_number,
)
)
@ -914,6 +884,8 @@ ios_framework(
],
infoplists = [
":DisplayInfoPlist",
":BuildNumberInfoPlist",
":VersionInfoPlist",
],
frameworks = [
":SwiftSignalKitFramework",
@ -933,20 +905,14 @@ plist_fragment(
"""
<key>CFBundleIdentifier</key>
<string>{telegram_bundle_id}.TelegramUI</string>
<key>CFBundleVersion</key>
<string>{telegram_build_number}</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleName</key>
<string>TelegramUI</string>
<key>CFBundleShortVersionString</key>
<string>{telegram_version}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
""".format(
telegram_bundle_id = telegram_bundle_id,
telegram_version = telegram_version,
telegram_build_number = telegram_build_number,
)
)
@ -961,12 +927,13 @@ ios_framework(
],
infoplists = [
":TelegramUIInfoPlist",
":BuildNumberInfoPlist",
":VersionInfoPlist",
],
frameworks = [
":MtProtoKitFramework",
":SwiftSignalKitFramework",
":PostboxFramework",
#":TelegramApiFramework",
":SyncCoreFramework",
":TelegramCoreFramework",
":AsyncDisplayKitFramework",
@ -1052,10 +1019,11 @@ ios_extension(
infoplists = [
":ShareInfoPlist",
":VersionInfoPlist",
":BuildNumberInfoPlist",
":AppNameInfoPlist",
],
minimum_os_version = "9.0",
provisioning_profile = "//build-input/data/provisioning-profiles:Share.mobileprovision",
provisioning_profile = "@build_configuration//provisioning:Share.mobileprovision",
deps = [":ShareExtensionLib"],
frameworks = [
":TelegramUIFramework"
@ -1120,10 +1088,11 @@ ios_extension(
infoplists = [
":NotificationContentInfoPlist",
":VersionInfoPlist",
":BuildNumberInfoPlist",
":AppNameInfoPlist",
],
minimum_os_version = "10.0",
provisioning_profile = "//build-input/data/provisioning-profiles:NotificationContent.mobileprovision",
provisioning_profile = "@build_configuration//provisioning:NotificationContent.mobileprovision",
deps = [":NotificationContentExtensionLib"],
frameworks = [
":TelegramUIFramework"
@ -1157,25 +1126,35 @@ plist_fragment(
)
)
swift_library(
name = "GeneratedSources",
module_name = "GeneratedSources",
srcs = glob([
"Generated/**/*.swift",
]),
visibility = ["//visibility:public"],
)
swift_library(
name = "WidgetExtensionLib",
module_name = "WidgetExtensionLib",
srcs = glob([
"WidgetKitWidget/**/*.swift",
"Generated/**/*.swift",
]),
data = [
"SiriIntents/Intents.intentdefinition",
],
deps = [
"//submodules/BuildConfig:BuildConfig",
"//submodules/WidgetItems:WidgetItems",
"//submodules/WidgetItems:WidgetItems_iOS14",
"//submodules/WidgetItemsUtils:WidgetItemsUtils",
"//submodules/AppLockState:AppLockState",
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
"//submodules/Postbox:Postbox",
"//submodules/TelegramCore:TelegramCore",
"//submodules/SyncCore:SyncCore",
"//submodules/OpenSSLEncryptionProvider:OpenSSLEncryptionProvider",
":GeneratedSources",
],
)
@ -1191,11 +1170,12 @@ ios_extension(
infoplists = [
":WidgetInfoPlist",
":VersionInfoPlist",
":BuildNumberInfoPlist",
":AppNameInfoPlist",
],
minimum_os_version = "14.0",
provides_main = True,
provisioning_profile = "//build-input/data/provisioning-profiles:Widget.mobileprovision",
provisioning_profile = "@build_configuration//provisioning:Widget.mobileprovision",
deps = [":WidgetExtensionLib"],
frameworks = [
":SwiftSignalKitFramework",
@ -1251,7 +1231,6 @@ swift_library(
module_name = "IntentsExtensionLib",
srcs = glob([
"SiriIntents/**/*.swift",
"Generated/**/*.swift",
]),
data = [
"SiriIntents/Intents.intentdefinition",
@ -1265,6 +1244,7 @@ swift_library(
"//submodules/BuildConfig:BuildConfig",
"//submodules/OpenSSLEncryptionProvider:OpenSSLEncryptionProvider",
"//submodules/AppLockState:AppLockState",
":GeneratedSources",
],
)
@ -1280,16 +1260,16 @@ ios_extension(
infoplists = [
":IntentsInfoPlist",
":VersionInfoPlist",
":BuildNumberInfoPlist",
":AppNameInfoPlist",
],
minimum_os_version = "10.0",
provisioning_profile = "//build-input/data/provisioning-profiles:Intents.mobileprovision",
provisioning_profile = "@build_configuration//provisioning:Intents.mobileprovision",
deps = [":IntentsExtensionLib"],
frameworks = [
":SwiftSignalKitFramework",
":PostboxFramework",
":TelegramCoreFramework",
#":TelegramApiFramework",
":SyncCoreFramework",
],
)
@ -1331,17 +1311,16 @@ ios_extension(
infoplists = [
":NotificationServiceInfoPlist",
":VersionInfoPlist",
":BuildNumberInfoPlist",
":AppNameInfoPlist",
],
minimum_os_version = "10.0",
provisioning_profile = "//build-input/data/provisioning-profiles:NotificationService.mobileprovision",
provisioning_profile = "@build_configuration//provisioning:NotificationService.mobileprovision",
deps = ["//Telegram/NotificationService:NotificationServiceExtensionLib"],
frameworks = [
":MtProtoKitFramework",
":SwiftSignalKitFramework",
":PostboxFramework",
#":TelegramApiFramework",
#":SyncCoreFramework",
],
)
@ -1522,11 +1501,13 @@ ios_application(
),
families = ["iphone", "ipad"],
minimum_os_version = "9.0",
provisioning_profile = "//build-input/data/provisioning-profiles:Telegram.mobileprovision",
provisioning_profile = "@build_configuration//provisioning:Telegram.mobileprovision",
entitlements = ":TelegramEntitlements.entitlements",
infoplists = [
":TelegramInfoPlist",
":AdditionalInfoPlist",
":BuildNumberInfoPlist",
":VersionInfoPlist",
":UrlTypesInfoPlist",
],
ipa_post_processor = ":AddAlternateIcons",
resources = [
@ -1547,14 +1528,16 @@ ios_application(
strings = [
":AppStringResources",
],
extensions = [
] if telegram_disable_extensions else [
":ShareExtension",
":NotificationContentExtension",
":NotificationServiceExtension",
":IntentsExtension",
":WidgetExtension",
],
extensions = select({
":disableExtensionsSetting": [],
"//conditions:default": [
":ShareExtension",
":NotificationContentExtension",
":NotificationServiceExtension",
":IntentsExtension",
":WidgetExtension",
],
}),
watch_application = ":TelegramWatchApp",
deps = [
":Main",

View File

@ -9,6 +9,7 @@ import Contacts
import OpenSSLEncryptionProvider
import AppLockState
import UIKit
import GeneratedSources
private var accountCache: Account?

View File

@ -13,6 +13,9 @@ import Postbox
import SyncCore
import TelegramCore
import OpenSSLEncryptionProvider
import WidgetItemsUtils
import GeneratedSources
private var installedSharedLogger = false
@ -156,9 +159,16 @@ struct Provider: IntentTimelineProvider {
)
}
var mappedMessage: WidgetDataPeer.Message?
if let index = transaction.getTopPeerMessageIndex(peerId: peer.id) {
if let message = transaction.getMessage(index.id) {
mappedMessage = WidgetDataPeer.Message(message: message)
}
}
peers.append(WidgetDataPeer(id: peer.id.toInt64(), name: name, lastName: lastName, letters: peer.displayLetters, avatarPath: smallestImageRepresentation(peer.profileImageRepresentations).flatMap { representation in
return postbox.mediaBox.resourcePath(representation.resource)
}, badge: badge))
}, badge: badge, message: mappedMessage))
}
}
return WidgetDataPeers(accountPeerId: widgetPeers.accountPeerId, peers: peers)
@ -195,12 +205,13 @@ struct AvatarItemView: View {
var accountPeerId: Int64
var peer: WidgetDataPeer
var itemSize: CGFloat
var displayBadge: Bool = true
var body: some View {
return ZStack {
Image(uiImage: avatarImage(accountPeerId: accountPeerId, peer: peer, size: CGSize(width: itemSize, height: itemSize)))
.clipShape(Circle())
if let badge = peer.badge, badge.count > 0 {
if displayBadge, let badge = peer.badge, badge.count > 0 {
Text("\(badge.count)")
.font(Font.system(size: 16.0))
.multilineTextAlignment(.center)
@ -219,6 +230,7 @@ struct AvatarItemView: View {
struct WidgetView: View {
@Environment(\.widgetFamily) private var widgetFamily
@Environment(\.colorScheme) private var colorScheme
let data: PeersWidgetData
func placeholder(geometry: GeometryProxy) -> some View {
@ -329,12 +341,150 @@ struct WidgetView: View {
}
}
var body: some View {
var body1: some View {
ZStack {
peerViews()
}
.padding(0.0)
}
func chatTopLine(_ peer: WidgetDataPeer) -> some View {
let dateText: String
if let message = peer.message {
dateText = DateFormatter.localizedString(from: Date(timeIntervalSince1970: Double(message.timestamp)), dateStyle: .none, timeStyle: .short)
} else {
dateText = ""
}
return HStack(alignment: .center, spacing: 0.0, content: {
Text(peer.name).font(Font.system(size: 16.0, weight: .medium, design: .default)).foregroundColor(.primary)
Spacer()
Text(dateText).font(Font.system(size: 14.0, weight: .regular, design: .default)).foregroundColor(.secondary)
})
}
func chatBottomLine(_ peer: WidgetDataPeer) -> some View {
var text = peer.message?.text ?? ""
if let message = peer.message {
//TODO:localize
switch message.content {
case .text:
break
case .image:
text = "🖼 Photo"
case .video:
text = "📹 Video"
case .gif:
text = "Gif"
case let .file(file):
text = "📎 \(file.name)"
case let .music(music):
if !music.title.isEmpty && !music.artist.isEmpty {
text = "\(music.artist)\(music.title)"
} else if !music.title.isEmpty {
text = music.title
} else if !music.artist.isEmpty {
text = music.artist
} else {
text = "Music"
}
case .voiceMessage:
text = "🎤 Voice Message"
case .videoMessage:
text = "Video Message"
case let .sticker(sticker):
text = "\(sticker.altText) Sticker"
case let .call(call):
if call.isVideo {
text = "Video Call"
} else {
text = "Voice Call"
}
case .mapLocation:
text = "Location"
case let .game(game):
text = "🎮 \(game.title)"
case let .poll(poll):
text = "📊 \(poll.title)"
}
}
var hasBadge = false
if let badge = peer.badge, badge.count > 0 {
hasBadge = true
}
return HStack(alignment: .center, spacing: hasBadge ? 6.0 : 0.0, content: {
Text(text).lineLimit(nil).font(Font.system(size: 15.0, weight: .regular, design: .default)).foregroundColor(.secondary).multilineTextAlignment(.leading).frame(maxHeight: .infinity, alignment: .topLeading)
Spacer()
if let badge = peer.badge, badge.count > 0 {
VStack {
Spacer()
Text("\(badge.count)")
.font(Font.system(size: 14.0))
.multilineTextAlignment(.center)
.foregroundColor(.white)
.padding(.horizontal, 4.0)
.background(
RoundedRectangle(cornerRadius: 10)
.fill(badge.isMuted ? Color.gray : Color.blue)
.frame(minWidth: 20, idealWidth: 20, maxWidth: .infinity, minHeight: 20, idealHeight: 20, maxHeight: 20.0, alignment: .center)
)
.padding(EdgeInsets(top: 0.0, leading: 0.0, bottom: 6.0, trailing: 3.0))
}
}
})
}
func chatContent(_ peer: WidgetDataPeer) -> some View {
return VStack(alignment: .leading, spacing: 2.0, content: {
chatTopLine(peer)
chatBottomLine(peer).frame(maxHeight: .infinity)
})
}
func chatContentView(_ index: Int) -> AnyView {
let peers: WidgetDataPeers
switch data {
case let .peers(peersValue):
peers = peersValue
if peers.peers.count <= index {
return AnyView(Spacer())
}
default:
return AnyView(Spacer())
}
return AnyView(
Link(destination: URL(string: linkForPeer(id: peers.peers[index].id))!, label: {
HStack(alignment: .center, spacing: 0.0, content: {
AvatarItemView(accountPeerId: peers.accountPeerId, peer: peers.peers[index], itemSize: 60.0, displayBadge: false).frame(width: 60.0, height: 60.0, alignment: .leading).padding(EdgeInsets(top: 0.0, leading: 10.0, bottom: 0.0, trailing: 10.0))
chatContent(peers.peers[index]).frame(maxWidth: .infinity).padding(EdgeInsets(top: 10.0, leading: 0.0, bottom: 10.0, trailing: 10.0))
})
})
)
}
func getSeparatorColor() -> Color {
switch colorScheme {
case .light:
return Color(.sRGB, red: 200.0 / 255.0, green: 199.0 / 255.0, blue: 204.0 / 255.0, opacity: 1.0)
case .dark:
return Color(.sRGB, red: 61.0 / 255.0, green: 61.0 / 255.0, blue: 64.0 / 255.0, opacity: 1.0)
@unknown default:
return .secondary
}
}
var body: some View {
GeometryReader(content: { geometry in
ZStack {
chatContentView(0).position(x: geometry.size.width / 2.0, y: geometry.size.height / 4.0).frame(width: geometry.size.width, height: geometry.size.height / 2.0, alignment: .leading)
chatContentView(1).position(x: geometry.size.width / 2.0, y: geometry.size.height / 2.0 + geometry.size.height / 4.0).frame(width: geometry.size.width, height: geometry.size.height / 2.0, alignment: .leading)
Rectangle().foregroundColor(getSeparatorColor()).position(x: geometry.size.width / 2.0, y: geometry.size.height / 4.0).frame(width: geometry.size.width, height: 0.33, alignment: .leading)
}
})
.padding(0.0)
}
}
private let buildConfig: BuildConfig = {
@ -429,7 +579,7 @@ struct Static_Widget: Widget {
return IntentConfiguration(kind: kind, intent: SelectFriendsIntent.self, provider: Provider(), content: { entry in
WidgetView(data: getWidgetData(contents: entry.contents))
})
.supportedFamilies([.systemSmall, .systemMedium])
.supportedFamilies([.systemMedium])
.configurationDisplayName(presentationData.widgetGalleryTitle)
.description(presentationData.widgetGalleryDescription)
}

View File

@ -0,0 +1,148 @@
import json
import os
import platform
import subprocess
def is_apple_silicon():
if platform.processor() == 'arm':
return True
else:
return False
def get_clean_env():
clean_env = os.environ.copy()
clean_env['PATH'] = '/usr/bin:/bin:/usr/sbin:/sbin'
return clean_env
def resolve_executable(program):
def is_executable(fpath):
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
for path in get_clean_env()["PATH"].split(os.pathsep):
executable_file = os.path.join(path, program)
if is_executable(executable_file):
return executable_file
return None
def run_executable_with_output(path, arguments):
executable_path = resolve_executable(path)
if executable_path is None:
raise Exception('Could not resolve {} to a valid executable file'.format(path))
process = subprocess.Popen(
[executable_path] + arguments,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
env=get_clean_env()
)
output_data, _ = process.communicate()
output_string = output_data.decode('utf-8')
return output_string
def call_executable(arguments, use_clean_environment=True, check_result=True):
executable_path = resolve_executable(arguments[0])
if executable_path is None:
raise Exception('Could not resolve {} to a valid executable file'.format(arguments[0]))
if use_clean_environment:
resolved_env = get_clean_env()
else:
resolved_env = os.environ
resolved_arguments = [executable_path] + arguments[1:]
if check_result:
subprocess.check_call(resolved_arguments, env=resolved_env)
else:
subprocess.call(resolved_arguments, env=resolved_env)
def get_bazel_version(bazel_path):
command_result = run_executable_with_output(bazel_path, ['--version']).strip('\n')
if not command_result.startswith('bazel '):
raise Exception('{} is not a valid bazel binary'.format(bazel_path))
command_result = command_result.replace('bazel ', '')
return command_result
def get_xcode_version():
xcode_path = run_executable_with_output('xcode-select', ['-p']).strip('\n')
if not os.path.isdir(xcode_path):
print('The path reported by \'xcode-select -p\' does not exist')
exit(1)
plist_path = '{}/../Info.plist'.format(xcode_path)
info_plist_lines = run_executable_with_output('plutil', [
'-p', plist_path
]).split('\n')
pattern = 'CFBundleShortVersionString" => '
for line in info_plist_lines:
index = line.find(pattern)
if index != -1:
version = line[index + len(pattern):].strip('"')
return version
print('Could not parse the Xcode version from {}'.format(plist_path))
exit(1)
class BuildEnvironment:
def __init__(
self,
base_path,
bazel_path,
bazel_x86_64_path,
override_bazel_version,
override_xcode_version
):
self.base_path = os.path.expanduser(base_path)
self.bazel_path = os.path.expanduser(bazel_path)
if bazel_x86_64_path is not None:
self.bazel_x86_64_path = os.path.expanduser(bazel_x86_64_path)
else:
self.bazel_x86_64_path = None
configuration_path = os.path.join(self.base_path, 'versions.json')
with open(configuration_path) as file:
configuration_dict = json.load(file)
if configuration_dict['app'] is None:
raise Exception('Missing app version in {}'.format(configuration_path))
else:
self.app_version = configuration_dict['app']
if configuration_dict['bazel'] is None:
raise Exception('Missing bazel version in {}'.format(configuration_path))
else:
self.bazel_version = configuration_dict['bazel']
if configuration_dict['xcode'] is None:
raise Exception('Missing xcode version in {}'.format(configuration_path))
else:
self.xcode_version = configuration_dict['xcode']
actual_bazel_version = get_bazel_version(self.bazel_path)
if actual_bazel_version != self.bazel_version:
if override_bazel_version:
print('Overriding the required bazel version {} with {} as reported by {}'.format(
self.bazel_version, actual_bazel_version, self.bazel_path))
self.bazel_version = actual_bazel_version
else:
print('Required bazel version is "{}", but "{}"" is reported by {}'.format(
self.bazel_version, actual_bazel_version, self.bazel_path))
exit(1)
actual_xcode_version = get_xcode_version()
if actual_xcode_version != self.xcode_version:
if override_xcode_version:
print('Overriding the required Xcode version {} with {} as reported by \'xcode-select -p\''.format(
self.xcode_version, actual_xcode_version, self.bazel_path))
self.xcode_version = actual_xcode_version
else:
print('Required Xcode version is {}, but {} is reported by \'xcode-select -p\''.format(
self.xcode_version, actual_xcode_version, self.bazel_path))
exit(1)

484
build-system/Make/Make.py Normal file
View File

@ -0,0 +1,484 @@
#!/bin/python3
import argparse
import os
import shlex
import sys
import tempfile
import subprocess
from BuildEnvironment import is_apple_silicon, resolve_executable, call_executable, BuildEnvironment
from ProjectGeneration import generate
class BazelCommandLine:
def __init__(self, bazel_path, bazel_x86_64_path, override_bazel_version, override_xcode_version):
self.build_environment = BuildEnvironment(
base_path=os.getcwd(),
bazel_path=bazel_path,
bazel_x86_64_path=bazel_x86_64_path,
override_bazel_version=override_bazel_version,
override_xcode_version=override_xcode_version
)
self.remote_cache = None
self.cache_dir = None
self.additional_args = None
self.build_number = None
self.configuration_args = None
self.configuration_path = None
self.common_args = [
# https://docs.bazel.build/versions/master/command-line-reference.html
# Ask bazel to print the actual resolved command line options.
'--announce_rc',
# https://github.com/bazelbuild/rules_swift
# If enabled, Swift compilation actions will use the same global Clang module
# cache used by Objective-C compilation actions. This is disabled by default
# because under some circumstances Clang module cache corruption can cause the
# Swift compiler to crash (sometimes when switching configurations or syncing a
# repository), but disabling it also causes a noticeable build time regression
# so it can be explicitly re-enabled by users who are not affected by those
# crashes.
'--features=swift.use_global_module_cache',
# https://docs.bazel.build/versions/master/command-line-reference.html
# Print the subcommand details in case of failure.
'--verbose_failures',
]
self.common_build_args = [
# https://github.com/bazelbuild/rules_swift
# If enabled and whole module optimisation is being used, the `*.swiftdoc`,
# `*.swiftmodule` and `*-Swift.h` are generated with a separate action
# rather than as part of the compilation.
'--features=swift.split_derived_files_generation',
# https://github.com/bazelbuild/rules_swift
# If enabled the skip function bodies frontend flag is passed when using derived
# files generation.
'--features=swift.skip_function_bodies_for_derived_files',
# Set the number of parallel processes to match the available CPU core count.
'--jobs={}'.format(os.cpu_count()),
]
self.common_debug_args = [
# https://github.com/bazelbuild/rules_swift
# If enabled, Swift compilation actions will use batch mode by passing
# `-enable-batch-mode` to `swiftc`. This is a new compilation mode as of
# Swift 4.2 that is intended to speed up non-incremental non-WMO builds by
# invoking a smaller number of frontend processes and passing them batches of
# source files.
'--features=swift.enable_batch_mode',
# https://docs.bazel.build/versions/master/command-line-reference.html
# Set the number of parallel jobs per module to saturate the available CPU resources.
'--swiftcopt=-j{}'.format(os.cpu_count() - 1),
]
self.common_release_args = [
# https://github.com/bazelbuild/rules_swift
# Enable whole module optimization.
'--features=swift.opt_uses_wmo',
# https://github.com/bazelbuild/rules_swift
# Use -Osize instead of -O when building swift modules.
'--features=swift.opt_uses_osize',
# --num-threads 0 forces swiftc to generate one object file per module; it:
# 1. resolves issues with the linker caused by the swift-objc mixing.
# 2. makes the resulting binaries significantly smaller (up to 9% for this project).
'--swiftcopt=-num-threads', '--swiftcopt=0',
# Strip unsused code.
'--features=dead_strip',
'--objc_enable_binary_stripping',
# Always embed bitcode into Watch binaries. This is required by the App Store.
'--apple_bitcode=watchos=embedded',
]
def add_remote_cache(self, host):
self.remote_cache = host
def add_cache_dir(self, path):
self.cache_dir = path
def add_additional_args(self, additional_args):
self.additional_args = additional_args
def set_build_number(self, build_number):
self.build_number = build_number
def set_configuration_path(self, path):
self.configuration_path = path
def set_configuration(self, configuration):
if configuration == 'debug_arm64':
self.configuration_args = [
# bazel debug build configuration
'-c', 'dbg',
# Build single-architecture binaries. It is almost 2 times faster is 32-bit support is not required.
'--ios_multi_cpus=arm64',
# Always build universal Watch binaries.
'--watchos_cpus=armv7k,arm64_32'
] + self.common_debug_args
elif configuration == 'release_arm64':
self.configuration_args = [
# bazel optimized build configuration
'-c', 'opt',
# Build single-architecture binaries. It is almost 2 times faster is 32-bit support is not required.
'--ios_multi_cpus=arm64',
# Always build universal Watch binaries.
'--watchos_cpus=armv7k,arm64_32',
# Generate DSYM files when building.
'--apple_generate_dsym',
# Require DSYM files as build output.
'--output_groups=+dsyms'
] + self.common_release_args
elif configuration == 'release_universal':
self.configuration_args = [
# bazel optimized build configuration
'-c', 'opt',
# Build universal binaries.
'--ios_multi_cpus=armv7,arm64',
# Always build universal Watch binaries.
'--watchos_cpus=armv7k,arm64_32',
# Generate DSYM files when building.
'--apple_generate_dsym',
# Require DSYM files as build output.
'--output_groups=+dsyms'
] + self.common_release_args
else:
raise Exception('Unknown configuration {}'.format(configuration))
def invoke_clean(self):
combined_arguments = [
self.build_environment.bazel_path,
'clean',
'--expunge'
]
print('TelegramBuild: running {}'.format(combined_arguments))
call_executable(combined_arguments)
def get_define_arguments(self):
return [
'--define=buildNumber={}'.format(self.build_number),
'--define=telegramVersion={}'.format(self.build_environment.app_version)
]
def get_project_generation_arguments(self):
combined_arguments = []
combined_arguments += self.common_args
combined_arguments += self.common_debug_args
combined_arguments += self.get_define_arguments()
if self.remote_cache is not None:
combined_arguments += [
'--remote_cache={}'.format(self.remote_cache),
'--experimental_remote_downloader={}'.format(self.remote_cache)
]
elif self.cache_dir is not None:
combined_arguments += [
'--disk_cache={path}'.format(path=self.cache_dir)
]
return combined_arguments
def invoke_build(self):
combined_arguments = [
self.build_environment.bazel_path,
'build',
'Telegram/Telegram'
]
if self.configuration_path is None:
raise Exception('configuration_path is not defined')
combined_arguments += [
'--override_repository=build_configuration={}'.format(self.configuration_path)
]
combined_arguments += self.common_args
combined_arguments += self.common_build_args
combined_arguments += self.get_define_arguments()
if self.remote_cache is not None:
combined_arguments += [
'--remote_cache={}'.format(self.remote_cache),
'--experimental_remote_downloader={}'.format(self.remote_cache)
]
elif self.cache_dir is not None:
combined_arguments += [
'--disk_cache={path}'.format(path=self.cache_dir)
]
combined_arguments += self.configuration_args
print('TelegramBuild: running')
print(subprocess.list2cmdline(combined_arguments))
call_executable(combined_arguments)
def clean(arguments):
bazel_command_line = BazelCommandLine(
bazel_path=arguments.bazel,
bazel_x86_64_path=None,
override_bazel_version=arguments.overrideBazelVersion,
override_xcode_version=arguments.overrideXcodeVersion
)
bazel_command_line.invoke_clean()
def resolve_configuration(bazel_command_line: BazelCommandLine, arguments):
if arguments.configurationGenerator is not None:
configuration_generator_arguments = shlex.split(arguments.configurationGenerator)
configuration_generator_executable = resolve_executable(configuration_generator_arguments[0])
if configuration_generator_executable is None:
print('{} is not a valid executable'.format(configuration_generator_arguments[0]))
exit(1)
temp_configuration_path = tempfile.mkdtemp()
resolved_configuration_generator_arguments = [configuration_generator_executable]
resolved_configuration_generator_arguments += configuration_generator_arguments[1:]
resolved_configuration_generator_arguments += [temp_configuration_path]
call_executable(resolved_configuration_generator_arguments, use_clean_environment=False)
print('TelegramBuild: using generated configuration in {}'.format(temp_configuration_path))
bazel_command_line.set_configuration_path(temp_configuration_path)
elif arguments.configurationPath is not None:
absolute_configuration_path = os.path.abspath(arguments.configurationPath)
if not os.path.isdir(absolute_configuration_path):
print('Error: {} does not exist'.format(absolute_configuration_path))
exit(1)
bazel_command_line.set_configuration_path(absolute_configuration_path)
else:
raise Exception('Neither configurationPath nor configurationGenerator are set')
def generate_project(arguments):
bazel_x86_64_path = None
if is_apple_silicon():
bazel_x86_64_path = arguments.bazel_x86_64
bazel_command_line = BazelCommandLine(
bazel_path=arguments.bazel,
bazel_x86_64_path=bazel_x86_64_path,
override_bazel_version=arguments.overrideBazelVersion,
override_xcode_version=arguments.overrideXcodeVersion
)
if arguments.cacheDir is not None:
bazel_command_line.add_cache_dir(arguments.cacheDir)
elif arguments.cacheHost is not None:
bazel_command_line.add_remote_cache(arguments.cacheHost)
resolve_configuration(bazel_command_line, arguments)
bazel_command_line.set_build_number(arguments.buildNumber)
disable_extensions = False
if arguments.disableExtensions is not None:
disable_extensions = arguments.disableExtensions
call_executable(['killall', 'Xcode'], check_result=False)
generate(
build_environment=bazel_command_line.build_environment,
disable_extensions=disable_extensions,
configuration_path=bazel_command_line.configuration_path,
bazel_app_arguments=bazel_command_line.get_project_generation_arguments()
)
def build(arguments):
bazel_command_line = BazelCommandLine(
bazel_path=arguments.bazel,
bazel_x86_64_path=None,
override_bazel_version=arguments.overrideBazelVersion,
override_xcode_version=arguments.overrideXcodeVersion
)
if arguments.cacheDir is not None:
bazel_command_line.add_cache_dir(arguments.cacheDir)
elif arguments.cacheHost is not None:
bazel_command_line.add_remote_cache(arguments.cacheHost)
resolve_configuration(bazel_command_line, arguments)
bazel_command_line.set_configuration(arguments.configuration)
bazel_command_line.set_build_number(arguments.buildNumber)
bazel_command_line.invoke_build()
def add_project_and_build_common_arguments(current_parser: argparse.ArgumentParser):
group = current_parser.add_mutually_exclusive_group(required=True)
group.add_argument(
'--configurationPath',
help='''
Path to a folder containing build configuration and provisioning profiles.
See build-system/example-configuration for an example.
''',
metavar='path'
)
group.add_argument(
'--configurationGenerator',
help='''
A command line invocation that will dynamically generate the configuration data
(project constants and provisioning profiles).
The expression will be parsed according to the shell parsing rules into program and arguments parts.
The program will be then invoked with the given arguments plus the path to the output directory.
See build-system/generate-configuration.sh for an example.
Example: --configurationGenerator="sh ~/my_script.sh argument1"
''',
metavar='command'
)
if __name__ == '__main__':
parser = argparse.ArgumentParser(prog='Make')
parser.add_argument(
'--verbose',
action='store_true',
default=False,
help='Print debug info'
)
parser.add_argument(
'--bazel',
required=True,
help='Use custom bazel binary',
metavar='path'
)
parser.add_argument(
'--overrideBazelVersion',
action='store_true',
help='Override bazel version with the actual version reported by the bazel binary'
)
parser.add_argument(
'--overrideXcodeVersion',
action='store_true',
help='Override xcode version with the actual version reported by \'xcode-select -p\''
)
parser.add_argument(
'--bazelArguments',
required=False,
help='Add additional arguments to all bazel invocations.',
metavar='arguments'
)
cacheTypeGroup = parser.add_mutually_exclusive_group()
cacheTypeGroup.add_argument(
'--cacheHost',
required=False,
help='Use remote build artifact cache to speed up rebuilds (See https://github.com/buchgr/bazel-remote).',
metavar='http://host:9092'
)
cacheTypeGroup.add_argument(
'--cacheDir',
required=False,
help='Cache build artifacts in a local directory to speed up rebuilds.',
metavar='path'
)
subparsers = parser.add_subparsers(dest='commandName', help='Commands')
cleanParser = subparsers.add_parser(
'clean', help='''
Clean local bazel cache. Does not affect files cached remotely (via --cacheHost=...) or
locally in an external directory ('--cacheDir=...')
'''
)
generateProjectParser = subparsers.add_parser('generateProject', help='Generate Xcode project')
if is_apple_silicon():
generateProjectParser.add_argument(
'--bazel_x86_64',
required=True,
help='A standalone bazel x86_64 binary is required to generate a project on Apple Silicon.',
metavar='path'
)
generateProjectParser.add_argument(
'--buildNumber',
required=False,
type=int,
default=10000,
help='Build number.',
metavar='number'
)
add_project_and_build_common_arguments(generateProjectParser)
generateProjectParser.add_argument(
'--disableExtensions',
action='store_true',
default=False,
help='''
The generated project will not include app extensions.
This allows Xcode to properly index the source code.
'''
)
buildParser = subparsers.add_parser('build', help='Build the app')
buildParser.add_argument(
'--buildNumber',
required=True,
type=int,
help='Build number.',
metavar='number'
)
add_project_and_build_common_arguments(buildParser)
buildParser.add_argument(
'--configuration',
choices=[
'debug_arm64',
'release_arm64',
'release_universal'
],
required=True,
help='Build configuration'
)
if len(sys.argv) < 2:
parser.print_help()
sys.exit(1)
args = parser.parse_args()
if args.verbose:
print(args)
if args.commandName is None:
exit(0)
try:
if args.commandName == 'clean':
clean(arguments=args)
elif args.commandName == 'generateProject':
generate_project(arguments=args)
elif args.commandName == 'build':
build(arguments=args)
else:
raise Exception('Unknown command')
except KeyboardInterrupt:
pass

View File

@ -0,0 +1,155 @@
import json
import os
import shutil
from BuildEnvironment import is_apple_silicon, call_executable, BuildEnvironment
def remove_directory(path):
if os.path.isdir(path):
shutil.rmtree(path)
def generate(build_environment: BuildEnvironment, disable_extensions, configuration_path, bazel_app_arguments):
project_path = os.path.join(build_environment.base_path, 'build-input/gen/project')
app_target = 'Telegram'
'''
TULSI_APP="build-input/gen/project/Tulsi.app"
TULSI="$TULSI_APP/Contents/MacOS/Tulsi"
rm -rf "$GEN_DIRECTORY/${APP_TARGET}.tulsiproj"
rm -rf "$TULSI_APP"
'''
os.makedirs(project_path, exist_ok=True)
remove_directory('{}/Tulsi.app'.format(project_path))
remove_directory('{project}/{target}.tulsiproj'.format(project=project_path, target=app_target))
tulsi_path = os.path.join(project_path, 'Tulsi.app/Contents/MacOS/Tulsi')
if is_apple_silicon():
tulsi_build_bazel_path = build_environment.bazel_x86_64_path
if tulsi_build_bazel_path is None or not os.path.isfile(tulsi_build_bazel_path):
print('Could not find a valid bazel x86_64 binary at {}'.format(tulsi_build_bazel_path))
exit(1)
else:
tulsi_build_bazel_path = build_environment.bazel_path
current_dir = os.getcwd()
os.chdir(os.path.join(build_environment.base_path, 'build-system/tulsi'))
call_executable([
tulsi_build_bazel_path,
'build', '//:tulsi',
'--xcode_version={}'.format(build_environment.xcode_version),
'--use_top_level_targets_for_symlinks',
'--verbose_failures'
])
os.chdir(current_dir)
bazel_wrapper_path = os.path.abspath('build-input/gen/project/bazel')
bazel_wrapper_arguments = []
bazel_wrapper_arguments += ['--override_repository=build_configuration={}'.format(configuration_path)]
if disable_extensions and False:
bazel_wrapper_arguments += ['--//Telegram:disableExtensions']
with open(bazel_wrapper_path, 'wb') as bazel_wrapper:
bazel_wrapper.write('''#!/bin/sh
{bazel} "$@" {arguments}
'''.format(
bazel=build_environment.bazel_path,
arguments=' '.join(bazel_wrapper_arguments)
).encode('utf-8'))
call_executable(['chmod', '+x', bazel_wrapper_path])
call_executable([
'unzip', '-oq',
'build-system/tulsi/bazel-bin/tulsi.zip',
'-d', project_path
])
user_defaults_path = os.path.expanduser('~/Library/Preferences/com.google.Tulsi.plist')
if os.path.isfile(user_defaults_path):
os.unlink(user_defaults_path)
with open(user_defaults_path, 'wb') as user_defaults:
user_defaults.write('''
<?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>defaultBazelURL</key>
<string>{}</string>
</dict>
</plist>
'''.format(bazel_wrapper_path).encode('utf-8'))
bazel_build_arguments = []
bazel_build_arguments += ['--override_repository=build_configuration={}'.format(configuration_path)]
if disable_extensions:
bazel_build_arguments += ['--//Telegram:disableExtensions']
call_executable([
tulsi_path,
'--',
'--verbose',
'--create-tulsiproj', app_target,
'--workspaceroot', './',
'--bazel', bazel_wrapper_path,
'--outputfolder', project_path,
'--target', '{target}:{target}'.format(target=app_target),
'--build-options', ' '.join(bazel_build_arguments)
])
additional_arguments = []
additional_arguments += ['--override_repository=build_configuration={}'.format(configuration_path)]
additional_arguments += bazel_app_arguments
if disable_extensions:
additional_arguments += ['--//Telegram:disableExtensions']
additional_arguments_string = ' '.join(additional_arguments)
tulsi_config_path = 'build-input/gen/project/{target}.tulsiproj/Configs/{target}.tulsigen'.format(target=app_target)
with open(tulsi_config_path, 'rb') as tulsi_config:
tulsi_config_json = json.load(tulsi_config)
for category in ['BazelBuildOptionsDebug', 'BazelBuildOptionsRelease']:
tulsi_config_json['optionSet'][category]['p'] += ' {}'.format(additional_arguments_string)
tulsi_config_json['sourceFilters'] = [
'Telegram/...',
'submodules/...',
'third-party/...'
]
with open(tulsi_config_path, 'wb') as tulsi_config:
tulsi_config.write(json.dumps(tulsi_config_json, indent=2).encode('utf-8'))
call_executable([
tulsi_path,
'--',
'--verbose',
'--genconfig', '{project}/{target}.tulsiproj:{target}'.format(project=project_path, target=app_target),
'--bazel', bazel_wrapper_path,
'--outputfolder', project_path,
'--no-open-xcode'
])
xcodeproj_path = '{project}/{target}.xcodeproj'.format(project=project_path, target=app_target)
bazel_build_settings_path = '{}/.tulsi/Scripts/bazel_build_settings.py'.format(xcodeproj_path)
with open(bazel_build_settings_path, 'rb') as bazel_build_settings:
bazel_build_settings_contents = bazel_build_settings.read().decode('utf-8')
bazel_build_settings_contents = bazel_build_settings_contents.replace(
'BUILD_SETTINGS = BazelBuildSettings(',
'import os\nBUILD_SETTINGS = BazelBuildSettings('
)
bazel_build_settings_contents = bazel_build_settings_contents.replace(
'\'--cpu=ios_arm64\'',
'\'--cpu=ios_arm64\'.replace(\'ios_arm64\', \'ios_sim_arm64\' if os.environ.get(\'EFFECTIVE_PLATFORM_NAME\') '
'== \'-iphonesimulator\' else \'ios_arm64\')'
)
with open(bazel_build_settings_path, 'wb') as bazel_build_settings:
bazel_build_settings.write(bazel_build_settings_contents.encode('utf-8'))
call_executable(['open', xcodeproj_path])

View File

@ -1 +0,0 @@
3.7.0

View File

@ -0,0 +1,11 @@
exports_files([
"Intents.mobileprovision",
"NotificationContent.mobileprovision",
"NotificationService.mobileprovision",
"Share.mobileprovision",
"Telegram.mobileprovision",
"WatchApp.mobileprovision",
"WatchExtension.mobileprovision",
"Widget.mobileprovision",
])

View File

@ -0,0 +1,10 @@
telegram_bundle_id = "ph.telegra.Telegraph"
telegram_api_id = "8"
telegram_api_hash = "7245de8e747a0d6fbe11f7cc14fcc0bb"
telegram_team_id = "C67CF9S4VU"
telegram_app_center_id = "0"
telegram_is_internal_build = "false"
telegram_is_appstore_build = "true"
telegram_appstore_id = "0"
telegram_app_specific_url_scheme = "tg"
telegram_aps_environment = "production"

View File

@ -0,0 +1,7 @@
#!/bin/sh
if [ ! -d "$1" ]; then
exit 1
fi
cp -R build-system/example-configuration/* "$1/"

View File

@ -1,129 +0,0 @@
#!/bin/bash
set -e
FASTLANE="$(which fastlane)"
EXPECTED_VARIABLES=(\
APPLE_ID \
BASE_BUNDLE_ID \
APP_NAME \
TEAM_ID \
PROVISIONING_DIRECTORY \
)
MISSING_VARIABLES="0"
for VARIABLE_NAME in ${EXPECTED_VARIABLES[@]}; do
if [ "${!VARIABLE_NAME}" = "" ]; then
echo "$VARIABLE_NAME not defined"
MISSING_VARIABLES="1"
fi
done
if [ "$MISSING_VARIABLES" == "1" ]; then
exit 1
fi
if [ ! -d "$PROVISIONING_DIRECTORY" ]; then
echo "Directory $PROVISIONING_DIRECTORY does not exist"
exit 1
fi
BASE_DIR=$(mktemp -d)
FASTLANE_DIR="$BASE_DIR/fastlane"
mkdir "$FASTLANE_DIR"
FASTFILE="$FASTLANE_DIR/Fastfile"
touch "$FASTFILE"
CREDENTIALS=(\
--username "$APPLE_ID" \
--team_id "$TEAM_ID" \
)
export FASTLANE_SKIP_UPDATE_CHECK=1
APP_EXTENSIONS=(\
Share \
SiriIntents \
NotificationContent \
NotificationService \
Widget \
)
echo "lane :manage_app do" >> "$FASTFILE"
echo " produce(" >> "$FASTFILE"
echo " username: '$APPLE_ID'," >> "$FASTFILE"
echo " app_identifier: '${BASE_BUNDLE_ID}'," >> "$FASTFILE"
echo " app_name: '$APP_NAME'," >> "$FASTFILE"
echo " language: 'English'," >> "$FASTFILE"
echo " app_version: '1.0'," >> "$FASTFILE"
echo " team_id: '$TEAM_ID'," >> "$FASTFILE"
echo " skip_itc: true," >> "$FASTFILE"
echo " )" >> "$FASTFILE"
echo " produce(" >> "$FASTFILE"
echo " username: '$APPLE_ID'," >> "$FASTFILE"
echo " app_identifier: '${BASE_BUNDLE_ID}.watchkitapp'," >> "$FASTFILE"
echo " app_name: '$APP_NAME Watch App'," >> "$FASTFILE"
echo " language: 'English'," >> "$FASTFILE"
echo " app_version: '1.0'," >> "$FASTFILE"
echo " team_id: '$TEAM_ID'," >> "$FASTFILE"
echo " skip_itc: true," >> "$FASTFILE"
echo " )" >> "$FASTFILE"
echo " produce(" >> "$FASTFILE"
echo " username: '$APPLE_ID'," >> "$FASTFILE"
echo " app_identifier: '${BASE_BUNDLE_ID}.watchkitapp.watchkitextension'," >> "$FASTFILE"
echo " app_name: '$APP_NAME Watch App Extension'," >> "$FASTFILE"
echo " language: 'English'," >> "$FASTFILE"
echo " app_version: '1.0'," >> "$FASTFILE"
echo " team_id: '$TEAM_ID'," >> "$FASTFILE"
echo " skip_itc: true," >> "$FASTFILE"
echo " )" >> "$FASTFILE"
for EXTENSION in ${APP_EXTENSIONS[@]}; do
echo " produce(" >> "$FASTFILE"
echo " username: '$APPLE_ID'," >> "$FASTFILE"
echo " app_identifier: '${BASE_BUNDLE_ID}.${EXTENSION}'," >> "$FASTFILE"
echo " app_name: '${APP_NAME} ${EXTENSION}'," >> "$FASTFILE"
echo " language: 'English'," >> "$FASTFILE"
echo " app_version: '1.0'," >> "$FASTFILE"
echo " team_id: '$TEAM_ID'," >> "$FASTFILE"
echo " skip_itc: true," >> "$FASTFILE"
echo " )" >> "$FASTFILE"
done
echo "end" >> "$FASTFILE"
pushd "$BASE_DIR"
fastlane cert ${CREDENTIALS[@]} --development
fastlane manage_app
fastlane produce group -g "group.$BASE_BUNDLE_ID" -n "$APP_NAME Group" ${CREDENTIALS[@]}
fastlane produce enable_services -a "$BASE_BUNDLE_ID" ${CREDENTIALS[@]} \
--app-group \
--push-notification \
--sirikit
fastlane produce associate_group -a "$BASE_BUNDLE_ID" "group.$BASE_BUNDLE_ID" ${CREDENTIALS[@]}
for EXTENSION in ${APP_EXTENSIONS[@]}; do
fastlane produce enable_services -a "${BASE_BUNDLE_ID}.${EXTENSION}" ${CREDENTIALS[@]} \
--app-group
fastlane produce associate_group -a "${BASE_BUNDLE_ID}.${EXTENSION}" "group.$BASE_BUNDLE_ID" ${CREDENTIALS[@]}
done
for DEVELOPMENT_FLAG in "--development"; do
fastlane sigh -a "$BASE_BUNDLE_ID" ${CREDENTIALS[@]} -o "$PROVISIONING_DIRECTORY" $DEVELOPMENT_FLAG \
--skip_install
for EXTENSION in ${APP_EXTENSIONS[@]}; do
fastlane sigh -a "${BASE_BUNDLE_ID}.${EXTENSION}" ${CREDENTIALS[@]} -o "$PROVISIONING_DIRECTORY" $DEVELOPMENT_FLAG \
--skip_install
done
done
popd
rm -rf "$BASE_DIR"

@ -1 +1 @@
Subproject commit b965114f31a464185318c71ef3d0c1538d0c52de
Subproject commit 734518e85d769de070b5a78b234080d9580ae625

View File

@ -1 +0,0 @@
12.2

View File

@ -5,7 +5,7 @@ set -e
BUILD_TELEGRAM_VERSION="1"
MACOS_VERSION="10.15"
XCODE_VERSION="12.2"
XCODE_VERSION="12.3"
GUEST_SHELL="bash"
VM_BASE_NAME="macos$(echo $MACOS_VERSION | sed -e 's/\.'/_/g)_Xcode$(echo $XCODE_VERSION | sed -e 's/\.'/_/g)"
@ -58,7 +58,7 @@ cp "$BAZEL" "tools/bazel"
BUILD_CONFIGURATION="$1"
if [ "$BUILD_CONFIGURATION" == "hockeyapp" ] || [ "$BUILD_CONFIGURATION" == "appcenter-experimental" ] || [ "$BUILD_CONFIGURATION" == "appcenter-experimental-2" ]; then
CODESIGNING_SUBPATH="transient-data/codesigning"
CODESIGNING_SUBPATH="transient-data/telegram-codesigning/codesigning"
CODESIGNING_TEAMS_SUBPATH="transient-data/teams"
elif [ "$BUILD_CONFIGURATION" == "appstore" ]; then
CODESIGNING_SUBPATH="transient-data/codesigning"
@ -90,28 +90,25 @@ fi
BASE_DIR=$(pwd)
if [ "$BUILD_CONFIGURATION" == "hockeyapp" ] || [ "$BUILD_CONFIGURATION" == "appcenter-experimental" ] || [ "$BUILD_CONFIGURATION" == "appcenter-experimental-2" ] || [ "$BUILD_CONFIGURATION" == "appstore" ]; then
if [ ! `which setup-telegram-build.sh` ]; then
echo "setup-telegram-build.sh not found in PATH $PATH"
if [ ! `which generate-configuration.sh` ]; then
echo "generate-configuration.sh not found in PATH $PATH"
exit 1
fi
if [ ! `which setup-codesigning.sh` ]; then
echo "setup-codesigning.sh not found in PATH $PATH"
exit 1
fi
source `which setup-telegram-build.sh`
setup_telegram_build "$BUILD_CONFIGURATION" "$BASE_DIR/$BUILDBOX_DIR/transient-data"
source `which setup-codesigning.sh`
CODESIGNING_CONFIGURATION="$BUILD_CONFIGURATION"
if [ "$BUILD_CONFIGURATION" == "appcenter-experimental" ] || [ "$BUILD_CONFIGURATION" == "appcenter-experimental-2" ]; then
CODESIGNING_CONFIGURATION="hockeyapp"
fi
setup_codesigning "$CODESIGNING_CONFIGURATION" "$BASE_DIR/$BUILDBOX_DIR/transient-data"
if [ "$SETUP_TELEGRAM_BUILD_VERSION" != "$BUILD_TELEGRAM_VERSION" ]; then
echo "setup-telegram-build.sh script version doesn't match"
exit 1
fi
mkdir -p "$BASE_DIR/$BUILDBOX_DIR/transient-data/telegram-codesigning"
mkdir -p "$BASE_DIR/$BUILDBOX_DIR/transient-data/build-configuration"
case "$BUILD_CONFIGURATION" in
"hockeyapp")
generate-configuration.sh internal release "$BASE_DIR/$BUILDBOX_DIR/transient-data/telegram-codesigning" "$BASE_DIR/$BUILDBOX_DIR/transient-data/build-configuration"
;;
*)
echo "Unknown build configuration $BUILD_CONFIGURATION"
exit 1
;;
esac
if [ "$BUILD_CONFIGURATION" == "appstore" ]; then
if [ -z "$TELEGRAM_BUILD_APPSTORE_PASSWORD" ]; then
echo "TELEGRAM_BUILD_APPSTORE_PASSWORD is not set"
@ -186,13 +183,14 @@ elif [ "$BUILD_MACHINE" == "macOS" ]; then
fi
scp -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -pr "$BUILDBOX_DIR/$CODESIGNING_SUBPATH" telegram@"$VM_IP":codesigning_data
scp -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -pr "$BUILDBOX_DIR/$CODESIGNING_TEAMS_SUBPATH" telegram@"$VM_IP":codesigning_teams
scp -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -pr "$BASE_DIR/$BUILDBOX_DIR/transient-data/build-configuration" telegram@"$VM_IP":telegram-configuration
#scp -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -pr "$BUILDBOX_DIR/$CODESIGNING_TEAMS_SUBPATH" telegram@"$VM_IP":codesigning_teams
if [ "$BUILD_CONFIGURATION" == "verify" ]; then
ssh -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null telegram@"$VM_IP" -o ServerAliveInterval=60 -t "mkdir -p telegram-ios-shared/fastlane; echo '' > telegram-ios-shared/fastlane/Fastfile"
else
scp -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -pr "$BUILDBOX_DIR/transient-data/telegram-ios-shared" telegram@"$VM_IP":telegram-ios-shared
fi
#if [ "$BUILD_CONFIGURATION" == "verify" ]; then
# ssh -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null telegram@"$VM_IP" -o ServerAliveInterval=60 -t "mkdir -p telegram-ios-shared/fastlane; echo '' > telegram-ios-shared/fastlane/Fastfile"
#else
# scp -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -pr "$BUILDBOX_DIR/transient-data/telegram-ios-shared" telegram@"$VM_IP":telegram-ios-shared
#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":
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

View File

@ -13,8 +13,8 @@ if [ -z "COMMIT_ID" ]; then
fi
if [ "$1" == "hockeyapp" ] || [ "$1" == "appcenter-experimental" ] || [ "$1" == "appcenter-experimental-2" ] || [ "$1" == "testinghockeyapp" ]; then
CERTS_PATH="$HOME/codesigning_data/certs"
PROFILES_PATH="$HOME/codesigning_data/profiles"
CERTS_PATH="$HOME/codesigning_data/certs/enterprise"
#PROFILES_PATH="$HOME/codesigning_data/profiles"
elif [ "$1" == "testinghockeyapp-local" ]; then
CERTS_PATH="$HOME/codesigning_data/certs"
PROFILES_PATH="$HOME/codesigning_data/profiles"
@ -79,7 +79,7 @@ echo "Unpacking files..."
mkdir -p "$SOURCE_PATH/buildbox"
mkdir -p "$SOURCE_PATH/buildbox/transient-data"
cp -r "$HOME/codesigning_teams" "$SOURCE_PATH/buildbox/transient-data/teams"
#cp -r "$HOME/codesigning_teams" "$SOURCE_PATH/buildbox/transient-data/teams"
BASE_DIR=$(pwd)
cd "$SOURCE_PATH"
@ -95,17 +95,18 @@ done
security set-key-partition-list -S apple-tool:,apple: -k "$MY_KEYCHAIN_PASSWORD" "$MY_KEYCHAIN"
mkdir -p "$HOME/Library/MobileDevice/Provisioning Profiles"
#mkdir -p "$HOME/Library/MobileDevice/Provisioning Profiles"
for f in $(ls "$PROFILES_PATH"); do
PROFILE_PATH="$PROFILES_PATH/$f"
uuid=`grep UUID -A1 -a "$PROFILE_PATH" | grep -io "[-A-F0-9]\{36\}"`
cp -f "$PROFILE_PATH" "$HOME/Library/MobileDevice/Provisioning Profiles/$uuid.mobileprovision"
done
#for f in $(ls "$PROFILES_PATH"); do
# PROFILE_PATH="$PROFILES_PATH/$f"
# uuid=`grep UUID -A1 -a "$PROFILE_PATH" | grep -io "[-A-F0-9]\{36\}"`
# cp -f "$PROFILE_PATH" "$HOME/Library/MobileDevice/Provisioning Profiles/$uuid.mobileprovision"
#done
if [ "$1" == "hockeyapp" ] || [ "$1" == "appcenter-experimental" ] || [ "$1" == "appcenter-experimental-2" ]; then
BUILD_ENV_SCRIPT="../telegram-ios-shared/buildbox/bin/internal.sh"
APP_TARGET="bazel_app_arm64"
#BUILD_ENV_SCRIPT="../telegram-ios-shared/buildbox/bin/internal.sh"
#APP_TARGET="bazel_app_arm64"
echo "" >> /dev/null
elif [ "$1" == "appstore" ]; then
BUILD_ENV_SCRIPT="../telegram-ios-shared/buildbox/bin/appstore.sh"
APP_TARGET="bazel_app"
@ -126,7 +127,15 @@ elif [ "$1" == "appcenter-experimental-2" ]; then
export APP_CENTER_ID="$APP_CENTER_EXPERIMENTAL_2_ID"
fi
PATH="$PATH:$(pwd)/tools" BAZEL_HTTP_CACHE_URL="$BAZEL_HTTP_CACHE_URL" 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"
python3 build-system/Make/Make.py \
--bazel="$(pwd)/tools/bazel" \
--cacheHost="$BAZEL_HTTP_CACHE_URL" \
build \
--configurationPath="$HOME/telegram-configuration" \
--buildNumber="$BUILD_NUMBER" \
--configuration=release_arm64
OUTPUT_PATH="build/artifacts"
rm -rf "$OUTPUT_PATH"

View File

@ -1,5 +1,5 @@
load(
"//build-input/data:variables.bzl",
"@build_configuration//:variables.bzl",
"telegram_api_id",
"telegram_api_hash",
"telegram_app_center_id",

View File

@ -0,0 +1,44 @@
import Foundation
final class MutableTopChatMessageView: MutablePostboxView {
private let peerIds: Set<PeerId>
fileprivate var messages: [PeerId: Message] = [:]
init(postbox: Postbox, peerIds: Set<PeerId>) {
self.peerIds = peerIds
for peerId in self.peerIds {
if let index = postbox.chatListIndexTable.get(peerId: peerId).topMessageIndex {
self.messages[peerId] = postbox.getMessage(index.id)
}
}
}
func replay(postbox: Postbox, transaction: PostboxTransaction) -> Bool {
var updated = false
for peerId in self.peerIds {
if transaction.currentOperationsByPeerId[peerId] != nil {
if let index = postbox.chatListIndexTable.get(peerId: peerId).topMessageIndex {
self.messages[peerId] = postbox.getMessage(index.id)
} else {
self.messages.removeValue(forKey: peerId)
}
updated = true
}
}
return updated
}
func immutableView() -> PostboxView {
return TopChatMessageView(self)
}
}
public final class TopChatMessageView: PostboxView {
public let messages: [PeerId: Message]
init(_ view: MutableTopChatMessageView) {
self.messages = view.messages
}
}

View File

@ -30,6 +30,7 @@ public enum PostboxViewKey: Hashable {
case basicPeer(PeerId)
case allChatListHoles(PeerGroupId)
case historyTagInfo(peerId: PeerId, tag: MessageTags)
case topChatMessage(peerIds: [PeerId])
public var hashValue: Int {
switch self {
@ -91,6 +92,8 @@ public enum PostboxViewKey: Hashable {
return groupId.hashValue
case let .historyTagInfo(peerId, tag):
return peerId.hashValue ^ tag.hashValue
case let .topChatMessage(peerIds):
return peerIds.hashValue
}
}
@ -270,6 +273,12 @@ public enum PostboxViewKey: Hashable {
} else {
return false
}
case let .topChatMessage(peerIds):
if case .topChatMessage(peerIds) = rhs {
return true
} else {
return false
}
}
}
}
@ -334,5 +343,7 @@ func postboxViewForKey(postbox: Postbox, key: PostboxViewKey) -> MutablePostboxV
return MutableAllChatListHolesView(postbox: postbox, groupId: groupId)
case let .historyTagInfo(peerId, tag):
return MutableHistoryTagInfoView(postbox: postbox, peerId: peerId, tag: tag)
case let .topChatMessage(peerIds):
return MutableTopChatMessageView(postbox: postbox, peerIds: Set(peerIds))
}
}

View File

@ -12,7 +12,7 @@ public func ensuredExistingPeerExportedInvitation(account: Account, peerId: Peer
let flags: Int32 = (1 << 2)
if let _ = peer as? TelegramChannel {
if let cachedData = transaction.getPeerCachedData(peerId: peerId) as? CachedChannelData, cachedData.exportedInvitation != nil && !revokeExisted {
return .complete()
return .single(cachedData.exportedInvitation)
} else {
return account.network.request(Api.functions.messages.exportChatInvite(flags: flags, peer: inputPeer, expireDate: nil, usageLimit: nil))
|> retryRequest
@ -99,10 +99,13 @@ public func peerExportedInvitations(account: Account, peerId: PeerId, revoked: B
return account.postbox.transaction { transaction -> Signal<ExportedInvitations?, NoError> in
if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
var flags: Int32 = 0
if let _ = offsetLink {
flags |= (1 << 2)
}
if revoked {
flags |= (1 << 3)
}
return account.network.request(Api.functions.messages.getExportedChatInvites(flags: flags, peer: inputPeer, adminId: nil, offsetLink: nil, limit: 50))
return account.network.request(Api.functions.messages.getExportedChatInvites(flags: flags, peer: inputPeer, adminId: nil, offsetLink: offsetLink, limit: 50))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.messages.ExportedChatInvites?, NoError> in
return .single(nil)

View File

@ -187,6 +187,7 @@ swift_library(
"//submodules/Markdown:Markdown",
"//submodules/SearchPeerMembers:SearchPeerMembers",
"//submodules/WidgetItems:WidgetItems",
"//submodules/WidgetItemsUtils:WidgetItemsUtils",
"//submodules/OpenSSLEncryptionProvider:OpenSSLEncryptionProvider",
"//submodules/PhoneNumberFormat:PhoneNumberFormat",
"//submodules/AppLock:AppLock",
@ -211,6 +212,7 @@ swift_library(
"//submodules/SlotMachineAnimationNode:SlotMachineAnimationNode",
"//submodules/AnimatedNavigationStripeNode:AnimatedNavigationStripeNode",
"//submodules/AudioBlob:AudioBlob",
"//Telegram:GeneratedSources",
],
visibility = [
"//visibility:public",

View File

@ -8,6 +8,9 @@ import TelegramPresentationData
import NotificationsPresentationData
import WidgetKit
import TelegramUIPreferences
import WidgetItemsUtils
import GeneratedSources
final class WidgetDataContext {
private var currentAccount: Account?
@ -32,9 +35,45 @@ final class WidgetDataContext {
}
case disabled
case peers(peers: [Peer], unread: [PeerId: Unread])
case peers(peers: [Peer], unread: [PeerId: Unread], messages: [PeerId: WidgetDataPeer.Message])
}
let updatedAdditionalPeerIds: Signal<Set<PeerId>, NoError> = Signal { subscriber in
if #available(iOSApplicationExtension 14.0, iOS 14.0, *) {
#if arch(arm64) || arch(i386) || arch(x86_64)
WidgetCenter.shared.getCurrentConfigurations({ result in
var peerIds = Set<PeerId>()
if case let .success(infos) = result {
for info in infos {
if let configuration = info.configuration as? SelectFriendsIntent {
if let items = configuration.friends {
for item in items {
guard let identifier = item.identifier, let peerIdValue = Int64(identifier) else {
continue
}
peerIds.insert(PeerId(peerIdValue))
}
}
}
}
}
subscriber.putNext(peerIds)
subscriber.putCompletion()
})
#else
subscriber.putNext(Set())
subscriber.putCompletion()
#endif
} else {
subscriber.putNext(Set())
subscriber.putCompletion()
}
return EmptyDisposable
}
|> runOn(.mainQueue())
let preferencesKey: PostboxViewKey = .preferences(keys: Set([
ApplicationSpecificPreferencesKeys.widgetSettings
]))
@ -69,13 +108,24 @@ final class WidgetDataContext {
case .disabled:
return .single(.disabled)
case let .peers(peers):
return combineLatest(queue: .mainQueue(), peers.filter { !$0.isDeleted }.map { account.postbox.peerView(id: $0.id)}) |> mapToSignal { peerViews -> Signal<CombinedRecentPeers, NoError> in
return account.postbox.unreadMessageCountsView(items: peerViews.map {
.peer($0.peerId)
})
|> map { values -> CombinedRecentPeers in
return combineLatest(queue: .mainQueue(), peers.filter { !$0.isDeleted }.map { account.postbox.peerView(id: $0.id)})
|> mapToSignal { peerViews -> Signal<CombinedRecentPeers, NoError> in
let topMessagesKey: PostboxViewKey = .topChatMessage(peerIds: peerViews.map {
$0.peerId
})
return combineLatest(queue: .mainQueue(),
account.postbox.unreadMessageCountsView(items: peerViews.map {
.peer($0.peerId)
}),
account.postbox.combinedView(keys: [topMessagesKey])
)
|> map { values, combinedView -> CombinedRecentPeers in
var peers: [Peer] = []
var unread: [PeerId: CombinedRecentPeers.Unread] = [:]
var messages: [PeerId: WidgetDataPeer.Message] = [:]
let topMessages = combinedView.views[topMessagesKey] as! TopChatMessageView
for peerView in peerViews {
if let peer = peerViewMainPeer(peerView) {
var isMuted: Bool = false
@ -93,21 +143,25 @@ final class WidgetDataContext {
unread[peerView.peerId] = CombinedRecentPeers.Unread(count: Int32(unreadCount), isMuted: isMuted)
}
if let message = topMessages.messages[peerView.peerId] {
messages[peerView.peerId] = WidgetDataPeer.Message(message: message)
}
peers.append(peer)
}
}
return .peers(peers: peers, unread: unread)
return .peers(peers: peers, unread: unread, messages: messages)
}
}
}
}
return recent
let processedRecent = recent
|> map { result -> WidgetData in
switch result {
case .disabled:
return WidgetData(accountId: account.id.int64, content: .disabled)
case let .peers(peers, unread):
case let .peers(peers, unread, messages):
return WidgetData(accountId: account.id.int64, content: .peers(WidgetDataPeers(accountPeerId: account.peerId.toInt64(), peers: peers.compactMap { peer -> WidgetDataPeer? in
var name: String = ""
var lastName: String?
@ -133,13 +187,110 @@ final class WidgetDataContext {
)
}
let message = messages[peer.id]
return WidgetDataPeer(id: peer.id.toInt64(), name: name, lastName: lastName, letters: peer.displayLetters, avatarPath: smallestImageRepresentation(peer.profileImageRepresentations).flatMap { representation in
return account.postbox.mediaBox.resourcePath(representation.resource)
}, badge: badge)
}, badge: badge, message: message)
})))
}
}
|> distinctUntilChanged
let additionalPeerIds = Signal<Set<PeerId>, NoError>.single(Set()) |> then(updatedAdditionalPeerIds)
let processedCustom: Signal<WidgetData, NoError> = additionalPeerIds
|> distinctUntilChanged
|> mapToSignal { additionalPeerIds -> Signal<CombinedRecentPeers, NoError> in
return combineLatest(queue: .mainQueue(), additionalPeerIds.map { account.postbox.peerView(id: $0) })
|> mapToSignal { peerViews -> Signal<CombinedRecentPeers, NoError> in
let topMessagesKey: PostboxViewKey = .topChatMessage(peerIds: peerViews.map {
$0.peerId
})
return combineLatest(queue: .mainQueue(),
account.postbox.unreadMessageCountsView(items: peerViews.map {
.peer($0.peerId)
}),
account.postbox.combinedView(keys: [topMessagesKey])
)
|> map { values, combinedView -> CombinedRecentPeers in
var peers: [Peer] = []
var unread: [PeerId: CombinedRecentPeers.Unread] = [:]
var messages: [PeerId: WidgetDataPeer.Message] = [:]
let topMessages = combinedView.views[topMessagesKey] as! TopChatMessageView
for peerView in peerViews {
if let peer = peerViewMainPeer(peerView) {
var isMuted: Bool = false
if let notificationSettings = peerView.notificationSettings as? TelegramPeerNotificationSettings {
switch notificationSettings.muteState {
case .muted:
isMuted = true
default:
break
}
}
let unreadCount = values.count(for: .peer(peerView.peerId))
if let unreadCount = unreadCount, unreadCount > 0 {
unread[peerView.peerId] = CombinedRecentPeers.Unread(count: Int32(unreadCount), isMuted: isMuted)
}
if let message = topMessages.messages[peerView.peerId] {
messages[peerView.peerId] = WidgetDataPeer.Message(message: message)
}
peers.append(peer)
}
}
return .peers(peers: peers, unread: unread, messages: messages)
}
}
}
|> map { result -> WidgetData in
switch result {
case .disabled:
return WidgetData(accountId: account.id.int64, content: .disabled)
case let .peers(peers, unread, messages):
return WidgetData(accountId: account.id.int64, content: .peers(WidgetDataPeers(accountPeerId: account.peerId.toInt64(), peers: peers.compactMap { peer -> WidgetDataPeer? in
var name: String = ""
var lastName: String?
if let user = peer as? TelegramUser {
if let firstName = user.firstName {
name = firstName
lastName = user.lastName
} else if let lastName = user.lastName {
name = lastName
} else if let phone = user.phone, !phone.isEmpty {
name = phone
}
} else {
name = peer.debugDisplayTitle
}
var badge: WidgetDataPeer.Badge?
if let unreadValue = unread[peer.id], unreadValue.count > 0 {
badge = WidgetDataPeer.Badge(
count: Int(unreadValue.count),
isMuted: unreadValue.isMuted
)
}
let message = messages[peer.id]
return WidgetDataPeer(id: peer.id.toInt64(), name: name, lastName: lastName, letters: peer.displayLetters, avatarPath: smallestImageRepresentation(peer.profileImageRepresentations).flatMap { representation in
return account.postbox.mediaBox.resourcePath(representation.resource)
}, badge: badge, message: message)
})))
}
}
|> distinctUntilChanged
return combineLatest(processedRecent, processedCustom)
|> map { processedRecent, _ -> WidgetData in
return processedRecent
}
}).start(next: { widgetData in
let path = basePath + "/widget-data"
if let data = try? JSONEncoder().encode(widgetData) {

View File

@ -10,3 +10,14 @@ swift_library(
"//visibility:public",
],
)
swift_library(
name = "WidgetItems_iOS14",
module_name = "WidgetItems_iOS14",
srcs = glob([
"Sources/**/*.swift",
]),
visibility = [
"//visibility:public",
],
)

View File

@ -15,20 +15,223 @@ public struct WidgetDataPeer: Codable, Equatable {
}
}
public struct Message: Codable, Equatable {
public enum Content: Codable, Equatable {
public enum DecodingError: Error {
case generic
}
public struct Image: Codable, Equatable {
public init() {
}
}
public struct Video: Codable, Equatable {
public init() {
}
}
public struct File: Codable, Equatable {
public var name: String
public init(name: String) {
self.name = name
}
}
public struct Gif: Codable, Equatable {
public init() {
}
}
public struct Music: Codable, Equatable {
public var artist: String
public var title: String
public var duration: Int32
public init(artist: String, title: String, duration: Int32) {
self.artist = artist
self.title = title
self.duration = duration
}
}
public struct VoiceMessage: Codable, Equatable {
public var duration: Int32
public init(duration: Int32) {
self.duration = duration
}
}
public struct VideoMessage: Codable, Equatable {
public var duration: Int32
public init(duration: Int32) {
self.duration = duration
}
}
public struct Sticker: Codable, Equatable {
public var altText: String
public init(altText: String) {
self.altText = altText
}
}
public struct Call: Codable, Equatable {
public var isVideo: Bool
public init(isVideo: Bool) {
self.isVideo = isVideo
}
}
public struct MapLocation: Codable, Equatable {
public init() {
}
}
public struct Game: Codable, Equatable {
public var title: String
public init(title: String) {
self.title = title
}
}
public struct Poll: Codable, Equatable {
public var title: String
public init(title: String) {
self.title = title
}
}
enum CodingKeys: String, CodingKey {
case text
case image
case video
case file
case gif
case music
case voiceMessage
case videoMessage
case sticker
case call
case mapLocation
case game
case poll
}
case text
case image(Image)
case video(Video)
case file(File)
case gif(Gif)
case music(Music)
case voiceMessage(VoiceMessage)
case videoMessage(VideoMessage)
case sticker(Sticker)
case call(Call)
case mapLocation(MapLocation)
case game(Game)
case poll(Poll)
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
if let _ = try? container.decode(String.self, forKey: .text) {
self = .text
} else if let image = try? container.decode(Image.self, forKey: .image) {
self = .image(image)
} else if let video = try? container.decode(Video.self, forKey: .video) {
self = .video(video)
} else if let gif = try? container.decode(Gif.self, forKey: .gif) {
self = .gif(gif)
} else if let file = try? container.decode(File.self, forKey: .file) {
self = .file(file)
} else if let music = try? container.decode(Music.self, forKey: .voiceMessage) {
self = .music(music)
} else if let voiceMessage = try? container.decode(VoiceMessage.self, forKey: .voiceMessage) {
self = .voiceMessage(voiceMessage)
} else if let videoMessage = try? container.decode(VideoMessage.self, forKey: .videoMessage) {
self = .videoMessage(videoMessage)
} else if let sticker = try? container.decode(Sticker.self, forKey: .sticker) {
self = .sticker(sticker)
} else if let call = try? container.decode(Call.self, forKey: .call) {
self = .call(call)
} else if let mapLocation = try? container.decode(MapLocation.self, forKey: .mapLocation) {
self = .mapLocation(mapLocation)
} else if let game = try? container.decode(Game.self, forKey: .game) {
self = .game(game)
} else if let poll = try? container.decode(Poll.self, forKey: .poll) {
self = .poll(poll)
} else {
throw DecodingError.generic
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
switch self {
case .text:
try container.encode("", forKey: .text)
case let .image(image):
try container.encode(image, forKey: .image)
case let .video(video):
try container.encode(video, forKey: .video)
case let .file(file):
try container.encode(file, forKey: .file)
case let .gif(gif):
try container.encode(gif, forKey: .gif)
case let .music(music):
try container.encode(music, forKey: .music)
case let .voiceMessage(voiceMessage):
try container.encode(voiceMessage, forKey: .voiceMessage)
case let .videoMessage(videoMessage):
try container.encode(videoMessage, forKey: .videoMessage)
case let .sticker(sticker):
try container.encode(sticker, forKey: .sticker)
case let .call(call):
try container.encode(call, forKey: .call)
case let .mapLocation(mapLocation):
try container.encode(mapLocation, forKey: .mapLocation)
case let .game(game):
try container.encode(game, forKey: .game)
case let .poll(poll):
try container.encode(poll, forKey: .poll)
}
}
}
public var text: String
public var content: Content
public var timestamp: Int32
public init(text: String, content: Content, timestamp: Int32) {
self.text = text
self.content = content
self.timestamp = timestamp
}
}
public var id: Int64
public var name: String
public var lastName: String?
public var letters: [String]
public var avatarPath: String?
public var badge: Badge?
public var message: Message?
public init(id: Int64, name: String, lastName: String?, letters: [String], avatarPath: String?, badge: Badge?) {
public init(id: Int64, name: String, lastName: String?, letters: [String], avatarPath: String?, badge: Badge?, message: Message?) {
self.id = id
self.name = name
self.lastName = lastName
self.letters = letters
self.avatarPath = avatarPath
self.badge = badge
self.message = message
}
}

View File

@ -0,0 +1,19 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "WidgetItemsUtils",
module_name = "WidgetItemsUtils",
srcs = glob([
"Sources/**/*.swift",
]),
deps = [
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
"//submodules/Postbox:Postbox",
"//submodules/SyncCore:SyncCore",
"//submodules/TelegramCore:TelegramCore",
"//submodules/WidgetItems:WidgetItems",
],
visibility = [
"//visibility:public",
],
)

View File

@ -0,0 +1,59 @@
import Foundation
import Postbox
import SyncCore
import TelegramCore
import WidgetItems
public extension WidgetDataPeer.Message {
init(message: Message) {
var content: WidgetDataPeer.Message.Content = .text
for media in message.media {
switch media {
case _ as TelegramMediaImage:
content = .image(WidgetDataPeer.Message.Content.Image())
case let file as TelegramMediaFile:
var fileName = "file"
for attribute in file.attributes {
if case let .FileName(value) = attribute {
fileName = value
break
}
}
content = .file(WidgetDataPeer.Message.Content.File(name: fileName))
for attribute in file.attributes {
switch attribute {
case let .Sticker(altText, _, _):
content = .sticker(WidgetDataPeer.Message.Content.Sticker(altText: altText))
case let .Video(duration, _, flags):
if flags.contains(.instantRoundVideo) {
content = .videoMessage(WidgetDataPeer.Message.Content.VideoMessage(duration: Int32(duration)))
} else {
content = .video(WidgetDataPeer.Message.Content.Video())
}
case let .Audio(isVoice, duration, title, performer, _):
if isVoice {
content = .voiceMessage(WidgetDataPeer.Message.Content.VoiceMessage(duration: Int32(duration)))
} else {
content = .music(WidgetDataPeer.Message.Content.Music(artist: performer ?? "", title: title ?? "", duration: Int32(duration)))
}
default:
break
}
}
case let action as TelegramMediaAction:
switch action.action {
case let .phoneCall(_, _, _, isVideo):
content = .call(WidgetDataPeer.Message.Content.Call(isVideo: isVideo))
default:
break
}
case _ as TelegramMediaMap:
content = .mapLocation(WidgetDataPeer.Message.Content.MapLocation())
default:
break
}
}
self.init(text: message.text, content: content, timestamp: message.timestamp)
}
}

View File

@ -55,6 +55,12 @@ genrule(
rm -rf "$$BUILD_DIR"
mkdir -p "$$BUILD_DIR"
YASM_DIR="$$BUILD_DIR/yasm"
rm -rf "$$YASM_DIR"
mkdir -p "$$YASM_DIR"
tar -xf "$(location //third-party/yasm:yasm.tar)" -C "$$YASM_DIR"
ABS_YASM_DIR="$$(pwd)/$$(dirname $$YASM_DIR)/$$(basename $$YASM_DIR)"
cp $(location :build-libvpx-bazel.sh) "$$BUILD_DIR/"
cp $(location :0001-Add-support-for-arm64-iphonesimulator-gcc.patch) "$$BUILD_DIR/"
@ -81,6 +87,9 @@ genrule(
outs = ["Public/vpx/" + x for x in headers] +
["Public/vpx/vpx_config.h"] +
["Public/vpx/lib{}.a".format(x) for x in libs],
tools = [
"//third-party/yasm:yasm.tar",
],
visibility = [
"//visibility:public",
]

View File

@ -0,0 +1,73 @@
/* Version ID for the JPEG library.
* Might be useful for tests like "#if JPEG_LIB_VERSION >= 60".
*/
#define JPEG_LIB_VERSION 80
/* libjpeg-turbo version */
#define LIBJPEG_TURBO_VERSION 4.0.0
/* libjpeg-turbo version in integer form */
#define LIBJPEG_TURBO_VERSION_NUMBER 4000000
/* Support arithmetic encoding */
#define C_ARITH_CODING_SUPPORTED 1
/* Support arithmetic decoding */
#define D_ARITH_CODING_SUPPORTED 1
/* Support in-memory source/destination managers */
/* #undef MEM_SRCDST_SUPPORTED */
/* Use accelerated SIMD routines. */
#define WITH_SIMD 1
/*
* Define BITS_IN_JSAMPLE as either
* 8 for 8-bit sample values (the usual setting)
* 12 for 12-bit sample values
* Only 8 and 12 are legal data precisions for lossy JPEG according to the
* JPEG standard, and the IJG code does not support anything else!
* We do not support run-time selection of data precision, sorry.
*/
#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */
/* Define to 1 if you have the <locale.h> header file. */
#define HAVE_LOCALE_H 1
/* Define to 1 if you have the <stddef.h> header file. */
#define HAVE_STDDEF_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define if you need to include <sys/types.h> to get size_t. */
#define NEED_SYS_TYPES_H 1
/* Define if you have BSD-like bzero and bcopy in <strings.h> rather than
memset/memcpy in <string.h>. */
/* #undef NEED_BSD_STRINGS */
/* Define to 1 if the system has the type `unsigned char'. */
#define HAVE_UNSIGNED_CHAR 1
/* Define to 1 if the system has the type `unsigned short'. */
#define HAVE_UNSIGNED_SHORT 1
/* Compiler does not support pointers to undefined structures. */
/* #undef INCOMPLETE_TYPES_BROKEN */
/* Define if your (broken) compiler shifts signed values as if they were
unsigned. */
/* #undef RIGHT_SHIFT_IS_UNSIGNED */
/* Define to 1 if type `char' is unsigned and you are not using gcc. */
#ifndef __CHAR_UNSIGNED__
/* #undef __CHAR_UNSIGNED__ */
#endif
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
/* Define to `unsigned int' if <sys/types.h> does not define. */
/* #undef size_t */

View File

@ -0,0 +1,31 @@
/* libjpeg-turbo build number */
#define BUILD "20201129"
/* Compiler's inline keyword */
#undef inline
/* How to obtain function inlining. */
#define INLINE __inline__ __attribute__((always_inline))
/* Define to the full name of this package. */
#define PACKAGE_NAME "mozjpeg"
/* Version number of package */
#define VERSION "4.0.0"
/* The size of `size_t', as computed by sizeof. */
#define SIZEOF_SIZE_T 8
/* Define if your compiler has __builtin_ctzl() and sizeof(unsigned long) == sizeof(size_t). */
#define HAVE_BUILTIN_CTZL
/* Define to 1 if you have the <intrin.h> header file. */
/* #undef HAVE_INTRIN_H */
#if defined(_MSC_VER) && defined(HAVE_INTRIN_H)
#if (SIZEOF_SIZE_T == 8)
#define HAVE_BITSCANFORWARD64
#elif (SIZEOF_SIZE_T == 4)
#define HAVE_BITSCANFORWARD
#endif
#endif

5
versions.json Normal file
View File

@ -0,0 +1,5 @@
{
"app": "7.3.1",
"bazel": "3.7.0",
"xcode": "12.3"
}