Writing a blatant Telegram clone using Qt, QML and Rust. And C++

2025/12/17 0:41

Writing a blatant Telegram clone using Qt, QML and Rust. And C++

RSS: https://news.ycombinator.com/rss

要約

Japanese Translation:

著者は、UIにQMLを使用し、コアロジックにはRustを採用したTelegram風メッセンジャー「Provoke」を構築しました。これにより高速ビルドとライブリロード機能が実現されました。

cxx-qt
から
qmetaobject-rs
へ切り替えることでコンパイル時間が短縮され、カスタム
HotReload
ウォッチャーはファイル変更時にアプリを再起動します。ビルドシステムはCMakeとRustの
cmake
クレートを利用し、手作業で構築したC++モジュールをコンパイルし、
qmlRegisterSingletonType
を通じて QML へ
ProvokeTools
として公開します。

QML のシステムトレイアイコン(

Qt.labs.platform
から)は、
ShaderEffectSource
経由で QML イメージを描画し、動的バッジカウントを表示します。UI コンポーネントは Telegram の外観を模倣しており、折りたたみ可能なサイドバー、カスタムスプリッター、アニメーション付き絵文字リアクションポップアップ、およびテール付きメッセージバブルが
NumberAnimation
で同期されます。

著者は VS Code における QML 言語サーバーの設定や Qt の実験的モジュールへの対応といった課題を指摘しています。今後の作業ではアニメーションの洗練とコンポーネントの磨きを目指し、Provoke を「Telegram とほぼ区別できない」レベルに仕上げることを計画しています。これにより、Rust がモダンなチャットアプリを動かすことが可能であり、QML/C++ を活用してリッチなインターフェースを実現できることを示しています。

本文

このプロジェクトは数日間の楽しい試作でしたが、結局今は置いておくことにしました。なぜなら、すでに取り組んでいた別の仕事を継続したいからです。以下では私の進捗状況をご紹介します。

ネタバレ注意: ここまでしか進められませんでした。


意見まとめ

10年前にQt、とくにQMLを使ったときのことが今でも鮮明に覚えています。デザインを思い浮かべてすぐに実装できる点が魅力的でした。
それゆえ、Webアプリを作るためにまだベータ版だったSvelteを選びました。QMLに最も近い感覚があったからです。

Rustは本当に素晴らしい言語です。2012年にコンパイル時にポインタ使用を検証し、実行時のオーバーヘッドを増やさない例を見たときから好きになりました。
私は計画とは裏腹にフルタイムでFull‑Stack Web開発者となってしまいましたが、それでも UI を作ることや難しい問題を解決することは好きです。本当に「ネイティブ」なアプリを作りたいと考えています。

Telegram はその UI の洗練さからお気に入りです。「Saved Messages」で10年分のチャットを閲覧できます。
Android 上で動く Matrix クライアント Element も悪くありませんが、デスクトップ版は Telegram に比べて喜びに欠けます。Element X は Rust の

matrix-rust-sdk
ライブラリを利用しているので、将来的には役立つかもしれません。


プロジェクト:QML + Rust で作る Telegram クローン

Day One – Hour Zero

Rust アプリの UI に QML を使う試みとして、以下を調査しました:

  • qmetaobject‑rs
  • cxx‑qt

どちらも選択肢ですが、

cxx-qt
は「公式」らしさがありますがコード生成によりビルドが遅くなります。まず
cxx‑qt
でシンプルな「ウィンドウを開く」プログラムを書きました。それにワクしたのでコミットしました。

ホットリロード

cxx-qt
が高価な再コンパイルを避けられるよう試行錯誤。VS Code はターミナルと違う
cargo check
を実行し、毎回キャッシュが消えてしまいました。
そこで
qmetaobject‑rs
に切り替え、ビルドは速く、QML も即座に動きました。ただしホットリロードを欲しかったので以下のような構成を試しました。

Rust 側実装例(簡略化)

let (tx, rx) = std::sync::mpsc::channel();
let mut watcher = notify::recommended_watcher(tx).unwrap();
watcher.configure(notify::Config::default().with_compare_contents(true)).unwrap();
watcher.watch(Path::new(qml_folder), notify::RecursiveMode::Recursive).unwrap();

thread_dirty_state.clone();
std::thread::spawn(move || {
    while let Ok(change) = rx.recv() {
        if let notify::EventKind::Modify(_) = change.kind {
            thread_dirty_state.store(true, std::sync::atomic::Ordering::SeqCst);
        }
    }
});

イベントループ側:

loop {
    hot_reload_state.store(false, Ordering::SeqCst);
    let mut engine = QmlEngine::new();
    engine.set_property("HotReload".into(), hot_reload.pinned().into());
    engine.load_file(format!("{qml_folder}main.qml").into());
    engine.exec();

    if !hot_reload_state.load(Ordering::SeqCst) {
        break;
    }
}

QML の

HotReload
オブジェクトがクリーンアップしてループを再起動します。
また、VS Code で QML Language Server を稼働させるのに少し手間はかかったものの、Qt Creator は QML 編集には依然として優秀です。


Hour Five – Telegram クローン作り始め

スプリッター

Telegram のサイドバーは折りたたみモード(65 px)と通常モード(260 px)の二つがあり、右側の最小幅は 380 px。組み込みスプリッターに機能不足を感じ、独自実装しました。

  • マウスカーソルを正しく表示
  • カスタムサイズロジックをサポート

アクセシビリティも念頭に置いてプロトタイピングしました。

UI 実験

  • OpacityMask
    を使って Material Design の「伸びる円」アニメーションを再実装
  • 送信者別に尾アイコン付きのチャットバブル作成
  • Telegram に似た絵文字リアクションポップアップ(行列、スクロールビュー拡張、検索ボックス)
  • メッセージ選択と数値アニメーションを駆使した華麗なトランジション
property real expandness: expand ? 1 : 0
Behavior on expandness { NumberAnimation { duration: 500; easing.type: Easing.InOutQuad } }
opacity: 1 - expandness
height: lerp(0, topSectionContent.height, expandness)
radius: lerp(barHeight / 2, 5, expandness)

システムトレイ

  • Qt.labs.platform
    SystemTrayIcon
    を実験的に使用
  • メッセージカウントバッジは
    ShaderEffectSource
    で描画した画像を取得し、
    icon.source
    に設定
  • アプリアイコンが他と被らないよう独自メガホンアイコンを作成

Rust + C++ の統合

Qt の機能を qmetaobject‑rs で露出できないものにアクセスしたいので、最小限の C++ ラッパーを追加しました。

CMakeLists.txt

cmake_minimum_required(VERSION 3.16)
project(provokecpp LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_AUTOMOC ON)
find_package(Qt6 COMPONENTS Core Gui Qml REQUIRED)

qt_add_library(provokecpp STATIC provokecpp.cpp provokecpp.hpp)
target_link_libraries(provokecpp Qt6::Core Qt6::Gui Qt6::Qml)

C++ ソース (provokecpp.cpp)

QObject* provoke_tools_singleton_provider(QQmlEngine*, QJSEngine*) {
    return new ProvokeTools();
}
extern "C" void register_provoke_qml_types() {
    qmlRegisterSingletonType<ProvokeTools>("provoke", 1, 0, "ProvokeTools",
                                            provoke_tools_singleton_provider);
    qmlRegisterType<OverrideMouseCursor>("provoke", 1, 0, "OverrideMouseCursor");
}

Rust ビルドスクリプト (build.rs)

fn main() {
    let dest = cmake::Config::new("cpp")
        .build_target("all")
        .build();

    println!("cargo::rerun-if-changed=cpp/CMakeLists.txt");
    println!("cargo::rerun-if-changed=cpp/provokecpp.cpp");
    println!("cargo::rerun-if-changed=cpp/provokecpp.hpp");

    println!("cargo::rustc-link-search=native={}/build", dest.display());
    println!("cargo::rustc-link-lib=static=provokecpp");
}

Rust 側使用例

extern "C" {
    fn register_provoke_qml_types();
}

fn main() {
    unsafe { register_provoke_qml_types(); }
    // ... アプリの残り
}

この構成ならビルドはキャッシュのおかげで即時に完了し、Rust が制御を保ちながら C++ Qt タイプを公開できます。


結果

プロトタイプは Telegram に驚くほど似ており、スプリットビュー、チャットバブル、絵文字リアクション、システムトレイアイコン付きバッジ、滑らかなアニメーションが実装済みです。実際のアプリではなくても、まるで本物を見ているような錯覚にびっくりしています。

リポジトリ: (リンク)


次なるステップと疑問

  • これが人気メッセンジャーになるか?
  • 継続開発するのか、それともゲームエンジンや CAD といった別プロジェクトに戻るのか?
  • 今後もブログ記事を投稿するか?

次回の App Dev By That Guy! をお楽しみに!

同じ日のほかのニュース

一覧に戻る →

2025/12/17 6:14

Prediction: AI will make formal verification go mainstream

## Japanese Translation: > 記事は、人工知能がソフトウェアが仕様を満たしていることを数学的に証明する「形式検証」を、ニッチな研究活動から日常のエンジニアリング実務へと導くと主張しています。Coq、Isabelle、Lean、F*、Agda などの証明支援ツールはすでに OS カーネル、コンパイラ、暗号スタックなど大規模システムを形式的に検証することを可能にしています。現在では言語モデル型コーディングアシスタントが実装コードとそれに付随する証明スクリプトの両方をドラフトでき、極小の検証済みチェッカーは無効な証明を拒否し、AI エージェントが幻覚(hallucinate)した場合には再試行を強制します。2009 年に公開された seL4 マイクロカーネル(8,700 行の C コードで 20 人年と 20 万行の Isabelle コード)が示すように、従来は労力集約的な検証が行われてきましたが、世界中で数百人程度の専門家しかそのような証明を作成できず、コストはバグ修正費用を上回ることも多いです。著者は AI がこれらのコストを低減するにつれて、より多くのソフトウェアが形式検証され、人間によるレビューではなく AI 生成コードに依存するようになると予測しています。残された最大の障壁は正確な仕様書を書くことです——仕様書作成は証明より容易ですが、それでも専門知識を要します。AI は自然言語での要求を形式的に翻訳する手助けができるかもしれませんが、ニュアンスの損失リスクがあります。広範な採用はバグと脆弱性を削減し、エンジニアリングワークフローを再構築し、仕様書作成に関する新たなスキルを要求しますが、文化的受容こそが主流化への主要障壁となります。

2025/12/17 1:54

alpr.watch

## Japanese Translation: 米国全土の自治体は急速に監視技術を導入しており、既に8万台以上のカメラが設置されています。 新しいプラットフォーム **alpr.watch** は、市議会の議題リストから「flock」「license plate reader」「ALPR」などのキーワードをスキャンし、それぞれの議論をマップ上にピン留めします。住民はこれらのシステムについて議論が行われている場所を確認でき、必要に応じて行動を起こすことができます。ユーザーはメールアドレスで登録すると、自分のエリア内の会議通知を受け取ることが可能です。 12月中旬以前に収集された全データは未検証です。今後提出される情報は正確性を確認するためにモデレートされます。 **ALPR** システムは、24時間365日すべての通行車両からナンバープレートデータを取得し、読み取り、保存します。最大規模のメーカーの一つである **Flock Safety** は、そのユニットを直接近隣住民や警察署に販売しています。カメラは機関・管轄区域間でデータを共有し、数百万の米国人を追跡する監視ウェブを構築します。これらのシステムは、意図された範囲を超えて拡張されることが多く、例えば移民取り締まりに使用されたり、恒久的なインフラストラクチャーとなったりします。 Electronic Frontier Foundation(EFF)、ACLU、Fight for the Future、STOP、Institute for Justice、および地域コミュニティグループなどのプライバシー擁護団体は、すでにこれらの動向を監視しています。 *この改訂された要約はリストからすべての主要ポイントを反映し、未確認推測を含まず、メインメッセージを明確かつ簡潔に保っています。*

2025/12/17 4:20

No Graphics API