An ultra-light Telegram client for iOS 12.5.7 / iPhone 6 (jailbreak). It inherits the architecture and engineering decisions of the ORClient project.
| Layer | Choice |
|---|---|
| Language | Objective-C |
| UI | Programmatic UIKit, manual frame-based layout, no Storyboard / Auto Layout |
| Protocol | TDLib via the JSON interface (td_send / td_receive) |
| Storage | Built-in TDLib database (no custom SQLite layer needed) |
| Audio | opusfile → PCM → WAV → AVAudioPlayer |
| Video / GIF / video notes | AVPlayer (all of it is mp4/h264, using the hardware decoder) |
| Build | Theos, iphone:clang:latest:12.0, arm64, .deb |
Bundle ID: vip.encrize.ortelegram
Included: private chats and groups, text, emoji, photos, videos, GIFs, voice messages, video notes, read markers, dark theme, reply, forwarding and paged history.
Intentionally excluded: calls, animated stickers (rendered as emoji), reactions, themes, folders, secret chats, polls, web previews, and premium animations.
# 0. one time: keys from my.telegram.org
cp Sources/TGSecrets.h.example Sources/TGSecrets.h
$EDITOR Sources/TGSecrets.h
# 1. dependencies (one time)
./build.sh deps
# 2. device smoke test BEFORE UI work
./scripts/smoke_test.sh 192.168.0.101
# 3. application
python3 make_assets.py
./build.sh package
./build.sh install 192.168.0.101ORTelegram_CODESIGN_FLAGS = -Sentitlements.plist -Ivip.encrize.ortelegram
Without -I<bundle id>, ldid adds the .unsigned suffix and CommCenter blocks
network access by PID (NEPathEvent Wi-Fi Blocked). That is fatal here because
TDLib keeps a persistent socket.
After installation, always use uicache -a, not -p.
First run the host build with --target prepare_cross_compiling (TL code generation),
then the target build. Without the first phase, the second one fails because
td_api.cpp is missing.
- Use the first size ≥ 320 px from
photo.sizes, not the original photo - Decode through ImageIO with
kCGImageSourceThumbnailMaxPixelSize, notUIImage - Message window in RAM:
kPageSize=30,kMaxRowsInMemory=100 - Cell height is cached in
TGMessage.cachedHeight,estimatedRowHeight = 0 - Chat list updates are batched with a 0.15 s timer (same idea as SSE in ORClient)
./build.sh package strips U+200B / BOM before every build automatically.
Makefile Theos application.mk
control / entitlements.plist
build.sh deps | clean | package | install <ip>
make_assets.py icons via Pillow
cmake/ios-arm64-theos.cmake cross-build toolchain
scripts/
env.sh shared variables + clang wrappers
build_openssl.sh
build_opus.sh libogg + libopus + opusfile
build_tdlib.sh two phases + .a merge
smoke_test.sh TDLib device check
Sources/
main.m
TGSecrets.h.example api_id / api_hash
TGClient.h/.m TDLib bridge, @extra routing, file downloads
TGAppDelegate.h/.m
TGAuthViewController.h/.m phone → code → 2FA
TGChatStore.h/.m chat list assembly from updates
TGChatListViewController.h/.m
TGChatViewController.h/.m history, sending, media playback
TGMessageCell.h/.m model + manually laid out cell
TGMediaCache.h/.m ImageIO thumbnails + LRU
TGVoicePlayer.h/.m Opus → WAV