<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: RustDesk</title>
    <description>The latest articles on DEV Community by RustDesk (@rustdesk).</description>
    <link>https://dev.to/rustdesk</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F642565%2F654838fb-9bd8-4dc3-b4b7-b246705c88b7.png</url>
      <title>DEV Community: RustDesk</title>
      <link>https://dev.to/rustdesk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rustdesk"/>
    <language>en</language>
    <item>
      <title>How to make Flutter 3.24 run on Windows 7?</title>
      <dc:creator>RustDesk</dc:creator>
      <pubDate>Mon, 02 Dec 2024 08:58:21 +0000</pubDate>
      <link>https://dev.to/rustdesk/how-to-make-flutter-324-run-on-windows-7-4ocf</link>
      <guid>https://dev.to/rustdesk/how-to-make-flutter-324-run-on-windows-7-4ocf</guid>
      <description>&lt;p&gt;We recently introduced Flutter 3.24.5 in &lt;a href="https://github.com/rustdesk/rustdesk" rel="noopener noreferrer"&gt;RustDesk&lt;/a&gt;, which resulted in it not running on Windows 7. To solve this problem, we attempted to modify the Flutter Engine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution for Running Flutter 3.24.5 on Windows 7
&lt;/h2&gt;

&lt;p&gt;Given that the Flutter and Dart officials have announced that Dart 3.3 and Flutter 3.19 will be the last versions to support Windows 7 and 8, we are facing the issue of Flutter 3.24.5 not running on Windows 7. To solve this problem, we need to revert some changes in Dart to restore support for Windows 7. Here are the changes that need to be reverted:&lt;/p&gt;

&lt;p&gt;Related link: &lt;a href="https://groups.google.com/g/flutter-announce/c/s0tM5gxAgs4/m/ryxV2vZYAQAJ?pli=1" rel="noopener noreferrer"&gt;Official Announcement&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Fix the issue with &lt;code&gt;Platform.localHostname&lt;/code&gt; in Chinese environments
&lt;/h2&gt;

&lt;p&gt;Originally, Dart used the &lt;code&gt;gethostname&lt;/code&gt; API, which caused &lt;code&gt;Platform.localHostname&lt;/code&gt; to fail in Chinese environments. To solve this problem, Dart switched to the &lt;code&gt;GetHostNameW&lt;/code&gt; API, which is only available in Windows 8 and later versions. To make Flutter run on Windows 7, we need to revert this change. Note that reverting this change will affect the functionality of &lt;code&gt;Platform.localHostname&lt;/code&gt; in Chinese environments.&lt;/p&gt;

&lt;p&gt;Related Issue link: &lt;a href="https://github.com/dart-lang/sdk/issues/52701" rel="noopener noreferrer"&gt;Platform.localHostname fails on Chinese Windows&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Remove the handling of unwinding records API for Windows 7
&lt;/h2&gt;

&lt;p&gt;Dart had previously made compatibility modifications for the lack of the &lt;code&gt;RtlAddGrowableFunctionTable&lt;/code&gt; API in Windows 7, but this modification has now been removed. To maintain compatibility with Windows 7, we need to revert the commit that removed this handling.&lt;/p&gt;

&lt;p&gt;Related Commit link: &lt;a href="https://github.com/dart-lang/sdk/commit/34213ba60578e46fc2455c5a56b09d9efabc532b" rel="noopener noreferrer"&gt;Remove Windows7 handling of unwinding records API&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Fix the issue where relative symbolic links to directories do not work on Windows
&lt;/h2&gt;

&lt;p&gt;Dart had previously fixed the issue where relative symbolic links to directories did not work on Windows and modified the File::GetType method. This modification used the PathCchCombineEx API, which is only available in Windows 8 and later versions. To restore support for Windows 7, we also need to revert this modification.&lt;/p&gt;

&lt;p&gt;Related Commit Link: &lt;a href="https://github.com/dart-lang/sdk/commit/b4574904f9cd0d6f7147950c02ee2447569d0be9" rel="noopener noreferrer"&gt;Fix a bug where relative symlinks to directories did not work on Windows&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;To make Flutter 3.24.5 run on Windows 7, we need to revert some key modifications in Dart. These reverts will have side effects, such as affecting the use of &lt;code&gt;Platform.localHostname&lt;/code&gt; in Chinese environments and issues with relative symbolic links. However, for users who rely on Windows 7, these reverts are necessary steps.&lt;/p&gt;

&lt;p&gt;For full implementation, please check &lt;a href="https://github.com/rustdesk/engine/blob/main/.github/workflows/flutter-engine-windows-x64-release-build.yml" rel="noopener noreferrer"&gt;our CI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/rustdesk/rustdesk/blob/dea99ffb3ab34fee562090d214af419b557debdf/.github/workflows/flutter-build.yml#L109" rel="noopener noreferrer"&gt;Here&lt;/a&gt; is how we apply the modified engine to our project.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>rustdesk</category>
    </item>
    <item>
      <title>Use Telegram bot to receive 2FA verification code (OTP) with the help of Copilot</title>
      <dc:creator>RustDesk</dc:creator>
      <pubDate>Sat, 29 Jun 2024 02:49:36 +0000</pubDate>
      <link>https://dev.to/rustdesk/use-telegram-bot-to-receive-2fa-verification-code-otp-with-the-help-of-copilot-52ao</link>
      <guid>https://dev.to/rustdesk/use-telegram-bot-to-receive-2fa-verification-code-otp-with-the-help-of-copilot-52ao</guid>
      <description>&lt;p&gt;One week ago, I saw a post on RustDesk subreddit, &lt;a href="https://www.reddit.com/r/rustdesk/comments/1dk4mzp/how_can_i_be_notified_track_when_someone_connects/" rel="noopener noreferrer"&gt;https://www.reddit.com/r/rustdesk/comments/1dk4mzp/how_can_i_be_notified_track_when_someone_connects/&lt;/a&gt;. It gave me hint to send the notification to Telegram bot, because I had been using it to receive news and signals while I traded FX before. This also inspired to me to receive OTP through Telegram bot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fveslny7fs03famf006yb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fveslny7fs03famf006yb.png" alt="Talk is cheap, show me the code."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So I started to ask Copilot.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Please write a function to send OTP to telegram bot"&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

async fn send_otp_to_telegram(bot_token: &amp;amp;str, chat_id: &amp;amp;str, otp: &amp;amp;str) -&amp;gt; Result&amp;lt;()&amp;gt; {
    let client = Client::new();
    let url = format!("https://api.telegram.org/bot{}/sendMessage", bot_token);
    let payload = json!({
        "chat_id": chat_id,
        "text": otp
    });

    let response = client.post(&amp;amp;url)
        .json(&amp;amp;payload)
        .send()
        .await?;

    if response.status().is_success() {
        Ok(())
    } else {
        Err(anyhow!("Failed to send OTP to Telegram: {}", response.status()))
    }
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;"Please write a function to send OTP to telegram bot, use reqwest"&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

use reqwest::Client;
use serde_json::json;
use std::error::Error;

async fn send_otp_to_telegram(otp: &amp;amp;str, bot_token: &amp;amp;str, chat_id: &amp;amp;str) -&amp;gt; Result&amp;lt;(), Box&amp;lt;dyn Error&amp;gt;&amp;gt; {
    let client = Client::new();
    let telegram_api_url = format!("https://api.telegram.org/bot{}/sendMessage", bot_token);
    let message = format!("Your OTP is: {}", otp);

    let response = client.post(&amp;amp;telegram_api_url)
        .json(&amp;amp;json!({
            "chat_id": chat_id,
            "text": message,
        }))
        .send()
        .await?;

    if response.status().is_success() {
        Ok(())
    } else {
        Err(Box::new(std::io::Error::new(std::io::ErrorKind::Other, "Failed to send OTP")))
    }
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;"How can I get telegram bot chat id with reqwest?"&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

async fn fetch_telegram_chat_id(bot_token: &amp;amp;str) -&amp;gt; Result&amp;lt;Vec&amp;lt;i64&amp;gt;, Box&amp;lt;dyn Error&amp;gt;&amp;gt; {
    let client = Client::new();
    let url = format!("https://api.telegram.org/bot{}/getUpdates", bot_token);

    let res = client.get(&amp;amp;url).send().await?;
    let body = res.text().await?;
    let json: Value = serde_json::from_str(&amp;amp;body)?;

    let mut chat_ids = Vec::new();
    if let Some(updates) = json["result"].as_array() {
        for update in updates {
            if let Some(chat_id) = update["message"]["chat"]["id"].as_i64() {
                chat_ids.push(chat_id);
            }
        }
    }

    Ok(chat_ids)
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;After some polish, I finished my job, &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rust
&lt;a href="https://github.com/rustdesk/rustdesk/blob/9f72d05749a88bffa577784099d97374c4276ee3/src/auth_2fa.rs#L158" rel="noopener noreferrer"&gt;https://github.com/rustdesk/rustdesk/blob/9f72d05749a88bffa577784099d97374c4276ee3/src/auth_2fa.rs#L158&lt;/a&gt;
```
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;// &lt;a href="https://gist.github.com/dideler/85de4d64f66c1966788c1b2304b9caf1" rel="noopener noreferrer"&gt;https://gist.github.com/dideler/85de4d64f66c1966788c1b2304b9caf1&lt;/a&gt;&lt;br&gt;
pub async fn send_2fa_code_to_telegram(text: &amp;amp;str, bot: TelegramBot) -&amp;gt; ResultType&amp;lt;()&amp;gt; {&lt;br&gt;
    let url = format!("&lt;a href="https://api.telegram.org/bot%7B%7D/sendMessage" rel="noopener noreferrer"&gt;https://api.telegram.org/bot{}/sendMessage&lt;/a&gt;", bot.token_str);&lt;br&gt;
    let params = serde_json::json!({"chat_id": bot.chat_id, "text": text});&lt;br&gt;
    crate::post_request(url, params.to_string(), "").await?;&lt;br&gt;
    Ok(())&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;pub fn get_chatid_telegram(bot_token: &amp;amp;str) -&amp;gt; ResultType&amp;gt; {&lt;br&gt;
    let url = format!("&lt;a href="https://api.telegram.org/bot%7B%7D/getUpdates" rel="noopener noreferrer"&gt;https://api.telegram.org/bot{}/getUpdates&lt;/a&gt;", bot_token);&lt;br&gt;
    // because caller is in tokio runtime, so we must call post_request_sync in new thread.&lt;br&gt;
    let handle = std:🧵:spawn(move || {&lt;br&gt;
        crate::post_request_sync(url, "".to_owned(), "")&lt;br&gt;
    });&lt;br&gt;
    let resp = handle.join().map_err(|_| anyhow!("Thread panicked"))??;&lt;br&gt;
    let value = serde_json::from_str::(&amp;amp;resp).map_err(|e| anyhow!(e))?;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Check for an error_code in the response
if let Some(error_code) = value.get("error_code").and_then(|code| code.as_i64()) {
    // If there's an error_code, try to use the description for the error message
    let description = value["description"]
        .as_str()
        .unwrap_or("Unknown error occurred");
    return Err(anyhow!(
        "Telegram API error: {} (error_code: {})",
        description,
        error_code
    ));
}

let chat_id = &amp;amp;value["result"][0]["message"]["chat"]["id"];
let chat_id = if let Some(id) = chat_id.as_i64() {
    Some(id.to_string())
} else if let Some(id) = chat_id.as_str() {
    Some(id.to_owned())
} else {
    None
};

if let Some(chat_id) = chat_id.as_ref() {
    let bot = TelegramBot {
        token_str: bot_token.to_owned(),
        chat_id: chat_id.to_owned(),
        ..Default::default()
    };
    bot.save()?;
}

Ok(chat_id)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
- Flutter UI
https://github.com/rustdesk/rustdesk/blob/a632718e80649f2be8a1a7cc1df20a6056b119b9/flutter/lib/common/widgets/dialog.dart#L1769

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;void changeBot({Function()? callback}) async {&lt;br&gt;
  if (bind.mainHasValidBotSync()) {&lt;br&gt;
    await bind.mainSetOption(key: "bot", value: "");&lt;br&gt;
    callback?.call();&lt;br&gt;
    return;&lt;br&gt;
  }&lt;br&gt;
  String errorText = '';&lt;br&gt;
  bool loading = false;&lt;br&gt;
  final controller = TextEditingController();&lt;br&gt;
  gFFI.dialogManager.show((setState, close, context) {&lt;br&gt;
    onVerify() async {&lt;br&gt;
      final token = controller.text.trim();&lt;br&gt;
      if (token == "") return;&lt;br&gt;
      loading = true;&lt;br&gt;
      errorText = '';&lt;br&gt;
      setState(() {});&lt;br&gt;
      final error = await bind.mainVerifyBot(token: token);&lt;br&gt;
      if (error == "") {&lt;br&gt;
        callback?.call();&lt;br&gt;
        close();&lt;br&gt;
      } else {&lt;br&gt;
        errorText = translate(error);&lt;br&gt;
        loading = false;&lt;br&gt;
        setState(() {});&lt;br&gt;
      }&lt;br&gt;
    }&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;final codeField = TextField(
  autofocus: true,
  controller: controller,
  decoration: InputDecoration(
    hintText: translate('Token'), 
  ),
);

return CustomAlertDialog(
  title: Text(translate("Telegram bot")),
  content: Column(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
      SelectableText(translate("enable-bot-desc"),
              style: TextStyle(fontSize: 12))
          .marginOnly(bottom: 12),
      Row(children: [Expanded(child: codeField)]),
      if (errorText != '')
        Text(errorText, style: TextStyle(color: Colors.red))
            .marginOnly(top: 12),
    ],
  ),
  actions: [
    dialogButton("Cancel", onPressed: close, isOutline: true),
    loading
        ? CircularProgressIndicator()
        : dialogButton("OK", onPressed: onVerify),
  ],
  onCancel: close,
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;});&lt;br&gt;
}&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

![The UI to set bot token and also get chat id implicitly](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/21d02vaxp6an9ojhumn5.png)

Thanks to Copilot.







&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
    </item>
    <item>
      <title>Build a cross-platform ChatGPT application using Rust + Tauri in two days</title>
      <dc:creator>RustDesk</dc:creator>
      <pubDate>Mon, 08 May 2023 08:04:48 +0000</pubDate>
      <link>https://dev.to/rustdesk/build-a-cross-platform-chatgpt-application-using-rust-tauri-in-two-days-1lp0</link>
      <guid>https://dev.to/rustdesk/build-a-cross-platform-chatgpt-application-using-rust-tauri-in-two-days-1lp0</guid>
      <description>&lt;p&gt;On the rare leisurely May Day holiday, with an itchy hand, I spent two days building a cross-platform ChatGPT application using Rust + Tauri.&lt;/p&gt;

&lt;p&gt;I noticed that there are four open-source ChatGPT applications on GitHub with relatively high popularity, including a wrapped desktop version, a naive-ui web version, a nextjs version, and a pure HTML version without server dependencies. So I wanted to write a cross-platform version. The reason for choosing Rust as the backend instead of directly calling the client API is to expect greater scalability in the future and embed my own models.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/Poordeveloper/chatgpt-app/" rel="noopener noreferrer"&gt;project&lt;/a&gt; is now online and included in awesome tauri. The front-end reuses web-chatgpt, while the backend is rewritten in Rust. It can currently run smoothly on desktops, the web, and mobile phones.&lt;/p&gt;

&lt;p&gt;The official version of Tauri does not yet support mobile devices, so we use the latest version 2.0.0-alpha.8, and the documentation is available here: &lt;a href="https://next--tauri.netlify.app/next/guides/" rel="noopener noreferrer"&gt;Guides | Tauri Apps&lt;/a&gt;. Tauri does not currently support using proxies in browsers, but this can be solved using native Rust.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisite
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;nodejs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pnpm.io/" rel="noopener noreferrer"&gt;pnpm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://rustup.rs/" rel="noopener noreferrer"&gt;rust&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://next--tauri.netlify.app/next/guides/getting-started/prerequisites/" rel="noopener noreferrer"&gt;Android / iOS sdk&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Directory structure
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/Poordeveloper/chatgpt-app/tree/main/src" rel="noopener noreferrer"&gt;src&lt;/a&gt;: the front-end part, modified from web-chatgpt&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/Poordeveloper/chatgpt-app/tree/main/server" rel="noopener noreferrer"&gt;server&lt;/a&gt;: the web backend, using axum. Here, in order to write &lt;a href="https://github.com/Poordeveloper/chatgpt-app/blob/9784e0c61e326ca79f65dddccc4e6dbe7a593563/server/src/service.rs#L169" rel="noopener noreferrer"&gt;stream&lt;/a&gt;, a lot of time was wasted mainly because there were few examples online, and also because it was the first time encountering the concept of stream and there were some misunderstandings.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/Poordeveloper/chatgpt-app/tree/main/shared" rel="noopener noreferrer"&gt;shared&lt;/a&gt;: Rust backend logic part, currently only implements the OpenAI API call. It has to be said that Rust's ecosystem is still slightly inferior to nodejs. The functionality of the OpenAI API SDK is slightly inferior. Here, combined with the async-openai crate and &lt;a href="https://github.com/transitive-bullshit/chatgpt-api" rel="noopener noreferrer"&gt;nodejs chatgpt-api&lt;/a&gt;, &lt;a href="https://github.com/Poordeveloper/chatgpt-app/blob/9784e0c61e326ca79f65dddccc4e6dbe7a593563/shared/src/gpt.rs#L241" rel="noopener noreferrer"&gt;the context function&lt;/a&gt; is implemented, and our own model will be added here in the future.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/Poordeveloper/chatgpt-app/tree/main/src-tauri" rel="noopener noreferrer"&gt;src-tauri&lt;/a&gt; : Tauri implementation, which is relatively simple because the main logic is in &lt;a href="https://github.com/Poordeveloper/chatgpt-app/tree/main/shared" rel="noopener noreferrer"&gt;shared&lt;/a&gt;, which is shared with &lt;a href="https://github.com/Poordeveloper/chatgpt-app/tree/main/server" rel="noopener noreferrer"&gt;server&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Run desktop
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;pnpm tauri dev&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkuj1xqlrjmd98pqt92gp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkuj1xqlrjmd98pqt92gp.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Run web
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&lt;h1&gt;
  
  
  run backend
&lt;/h1&gt;

&lt;p&gt;cargo run --bin server&lt;/p&gt;
&lt;h1&gt;
  
  
  start frontend dev
&lt;/h1&gt;

&lt;p&gt;pnpm dev&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Run iOS&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;pnpm tauri ios dev&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvou31swyc5rfj1y32996.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvou31swyc5rfj1y32996.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Flutter Desktop Development Practice</title>
      <dc:creator>RustDesk</dc:creator>
      <pubDate>Tue, 20 Sep 2022 04:11:39 +0000</pubDate>
      <link>https://dev.to/rustdesk/flutter-desktop-development-practice-4c7a</link>
      <guid>https://dev.to/rustdesk/flutter-desktop-development-practice-4c7a</guid>
      <description>&lt;p&gt;We mentioned earlier that &lt;a href="https://github.com/rustdesk/rustdesk"&gt;RustDesk&lt;/a&gt;'s original Html / Js (Sciter)-based front-end was migrated to Flutter. We have to admit the migration progress was much slower than expected. It seems wrong to choose Flutter, but there were no other better choices indeed.&lt;/p&gt;

&lt;p&gt;Tauri seems to be the best choice, but the performance does not meet our requirement. Sciter uses Html / Js, but it has its own rendering engine with native Video interface. Tauri uses its Wry to unify the API interfaces of browsers on various platforms, but it cannot break the limitations of browser boundary, and the customizability and compatibility are also worse than Electron. I still like Tauri very much, because it is small and pretty, convenient for development and debugging, and efficient enough to meet the production needs of most scenes. I look forward to its future, and I hope their own rendering implementation can be achieved as soon as possible.&lt;/p&gt;

&lt;p&gt;Qt seems a more practical choice, but after seeing its unsafe Rust binding of Qt, we gave up.&lt;/p&gt;

&lt;p&gt;The front-end development of Flutter is similar to the native UI development, the complexity is significantly higher than classic Web technology. This can be seen from the number of lines of source code after our migration. The code is much more verbose and bloated, although it leads to better engineering practices and maintainability (This doesn't mean too much for a small team like us in my opinion).&lt;/p&gt;

&lt;p&gt;Flutter desktop is still buggy, and much more worse than expected. Here are some featured problems we have encountered, and our solutions.&lt;/p&gt;

&lt;h2&gt;
  
  
  1，Multiple Windows Support
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/Kingtous/rustdesk_desktop_multi_window"&gt;https://github.com/Kingtous/rustdesk_desktop_multi_window&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This Pub supports Flutter &amp;lt;=3.0.5 on Windows. There is a related issue on Flutter repo, but the priority is low. As a work around, We stick to the old version of Flutter. We haven't seen any obvious improvements for Windows in the new Flutter version, using new Flutter version is not that important. It seems that the Flutter team focuses on Android / iOS, and many basic problems of Flutter desktop (multi-level menus, local cursor, scrollbar) have been ignored.&lt;/p&gt;

&lt;h2&gt;
  
  
  2，Better Window Operation
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/leanflutter/window_manager/pull/205"&gt;https://github.com/leanflutter/window_manager/pull/205&lt;br&gt;
&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/leanflutter/window_manager/pull/203"&gt;https://github.com/leanflutter/window_manager/pull/203&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3，Native Cursor
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/flutter/engine/pull/36143"&gt;https://github.com/flutter/engine/pull/36143&lt;br&gt;
&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/Kingtous/rustdesk_flutter_custom_cursor"&gt;https://github.com/Kingtous/rustdesk_flutter_custom_cursor&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4，Multi-level Menus
&lt;/h2&gt;

&lt;p&gt;We try to avoid using multi-level menus. There is a native menu implementation, but it is not easy to customize.&lt;/p&gt;

&lt;h2&gt;
  
  
  5，Scroolbar
&lt;/h2&gt;

&lt;p&gt;The wheel speed is slow, and the wheel stops to work when the cursor is moved on the scrollbar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Kingtous/flutter_improved_scrolling"&gt;https://github.com/Kingtous/flutter_improved_scrolling&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  6，Bridge
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/fzyzcjy/flutter_rust_bridge/pull/663"&gt;https://github.com/fzyzcjy/flutter_rust_bridge/pull/663&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  7，Wayland
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/leanflutter/screen_retriever/pull/3"&gt;https://github.com/leanflutter/screen_retriever/pull/3&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  8，CJK Font
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/flutter/flutter/issues/103811#issuecomment-1199227834"&gt;https://github.com/flutter/flutter/issues/103811#issuecomment-1199227834&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/rustdesk/rustdesk/pull/1581/files"&gt;https://github.com/rustdesk/rustdesk/pull/1581/files&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>RustDesk is migrated from Sciter to Flutter</title>
      <dc:creator>RustDesk</dc:creator>
      <pubDate>Fri, 26 Aug 2022 11:33:00 +0000</pubDate>
      <link>https://dev.to/rustdesk/rustdesk-is-migrated-from-sciter-to-flutter-279m</link>
      <guid>https://dev.to/rustdesk/rustdesk-is-migrated-from-sciter-to-flutter-279m</guid>
      <description>&lt;p&gt;Yesterday, the RustDesk project officially merged the flutter_desktop branch into the master branch in preparation for the final release.&lt;/p&gt;

&lt;p&gt;The first desktop version of RustDesk used Sciter. The primary reason for choosing Sciter was its light weight, but Sciter is not open source. The author of Sciter launched an open source Kickstarter last year, but it failed.&lt;/p&gt;

&lt;p&gt;We decided to migrate in this May, and hosted an discussion about chosing Flutter or Tauri, &lt;a href="https://github.com/rustdesk/rustdesk/discussions/533"&gt;https://github.com/rustdesk/rustdesk/discussions/533&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now RustDesk fully embraces Flutter, Flutter is adopted on all platforms (iOS / Android / Windows / Linux / Mac / Web). But since Flutter does not support 32bit Windows, Sciter still has to continue to serve for 32bit Windows.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>rust</category>
      <category>dart</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Summary of Flutter vs Tauri</title>
      <dc:creator>RustDesk</dc:creator>
      <pubDate>Mon, 30 May 2022 14:24:37 +0000</pubDate>
      <link>https://dev.to/rustdesk/summary-of-flutter-vs-tauri-2gkk</link>
      <guid>https://dev.to/rustdesk/summary-of-flutter-vs-tauri-2gkk</guid>
      <description>&lt;p&gt;Last week we posted &lt;a href="https://link.zhihu.com/?target=https://github.com/rustdesk/rustdesk/discussions/533"&gt;a discussion on the selection of Flutter and Tauri on GitHub&lt;/a&gt;, and we are glad that both the author of Tauri and the author flutter_rust_bridge have participated. In the end, the voting score of Tauri is higher. Although we favored Tauri originally, but we still choose Flutter for the time being due to the poor IPC performance of Tauri. I will summarize the discussion, hope it can help you choose between Flutter and Tauri in your future job.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pros of Tauri:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Tauri ecosystem is richer, with massive resources of html/css/js&lt;/li&gt;
&lt;li&gt;Tauri community is awesome&lt;/li&gt;
&lt;li&gt;Tauri is based on the browser kernel which is more mature than Flutter in the desktop environment&lt;/li&gt;
&lt;li&gt;Tauri is simpler, easier to build, easier to learn, and easier to get more contributors&lt;/li&gt;
&lt;li&gt;Simpler integration with Rust, even you can call Rust async functions (I haven't tried it)&lt;/li&gt;
&lt;li&gt;Smaller application after compilation&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cons of Tauri:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;IPC performance is not good (The author of Tauri mentioned the reasons for discarding shared memory support mentioned in the discussion, as well as the problems of IPC, and incomming optimizations, but I can not find it any more)&lt;/li&gt;
&lt;li&gt;Due to the use of the browser kernel, bigger memory footprint. There are also browser compatibility issues on different platforms.&lt;/li&gt;
&lt;li&gt;Win7 without WebView installed is a trouble. You can make a big package yourself, or you can install it online, which are not very friendly.&lt;/li&gt;
&lt;li&gt;Not support mobile. The author mentioned that the mobile version will be launched this year. It is said to be based on EGUI, but there is still a long way to reach stable version.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pros of Flutter:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The ecosystem is also rich&lt;/li&gt;
&lt;li&gt;Desktop + mobile&lt;/li&gt;
&lt;li&gt;Good FFI performance&lt;/li&gt;
&lt;li&gt;Supported by Google&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cons of Flutter:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;32-bit Windows are not supported, Google has explicitly stated that they won't support 32-bit Windows.&lt;/li&gt;
&lt;li&gt;Building, debugging, and integration with Rust is a bit more complicated&lt;/li&gt;
&lt;li&gt;The final package is slightly larger, a &lt;code&gt;hello world&lt;/code&gt; under Windows is 20MB, after zip compression it is 8.36MB, similar size under Linux&lt;/li&gt;
&lt;li&gt;No static link library&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>How does RustDesk work? OpenSource TeamViewer Alternative.</title>
      <dc:creator>RustDesk</dc:creator>
      <pubDate>Thu, 26 May 2022 10:03:26 +0000</pubDate>
      <link>https://dev.to/rustdesk/how-does-rustdesk-work-opensource-teamviewer-alternative-llm</link>
      <guid>https://dev.to/rustdesk/how-does-rustdesk-work-opensource-teamviewer-alternative-llm</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/rustdesk/rustdesk/wiki/How-does-RustDesk-work%3F"&gt;https://github.com/rustdesk/rustdesk/wiki/How-does-RustDesk-work%3F&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kVgqnZk4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mkv3t02yvl1o43plijr0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kVgqnZk4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mkv3t02yvl1o43plijr0.png" alt="Image description" width="780" height="812"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oZzQlG-w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a1a0yx2r6957bo6ej3gv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oZzQlG-w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a1a0yx2r6957bo6ej3gv.png" alt="Image description" width="880" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Tauri or Flutter v3 for a Rust desktop app?</title>
      <dc:creator>RustDesk</dc:creator>
      <pubDate>Tue, 17 May 2022 05:25:19 +0000</pubDate>
      <link>https://dev.to/rustdesk/tauri-or-flutter-v3-for-rust-desktop-app-5dok</link>
      <guid>https://dev.to/rustdesk/tauri-or-flutter-v3-for-rust-desktop-app-5dok</guid>
      <description>&lt;p&gt;Though our open source mobile side is Flutter, but I can not decide either. Our desktop side uses Sciter, similar to html/js. We can use most of old html/js with Tauri. We can also reuse some mobile Flutter code, but our desktop design is super different from mobile. Flutter is not css based, few code can be shared between mobile and desktop per my understanding.&lt;/p&gt;

&lt;p&gt;Drawback of flutter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Debugging rust with Flutter is not conveninent.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Both of them are open source, but Tauri has much smaller code base, we can do code change on Tauri, but it is hard for us on Flutter.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I created a pool on my github discussions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/rustdesk/rustdesk/discussions/533"&gt;https://github.com/rustdesk/rustdesk/discussions/533&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Debugging a Crash in Unsafe Rust with Windbg</title>
      <dc:creator>RustDesk</dc:creator>
      <pubDate>Thu, 03 Jun 2021 03:51:42 +0000</pubDate>
      <link>https://dev.to/rustdesk/debugging-a-crash-in-unsafe-rust-with-windbg-2b39</link>
      <guid>https://dev.to/rustdesk/debugging-a-crash-in-unsafe-rust-with-windbg-2b39</guid>
      <description>&lt;p&gt;Lately, I had a crash in my &lt;a href="https://github.com/rustdesk/rustdesk" rel="noopener noreferrer"&gt;Rust project&lt;/a&gt; on Windows. It is hard to get any clue from the console messages, because it is a segmentfault crash related to unsafe rust code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;error: process didn't exit successfully: `target\debug\rustdesk.exe` (exit code: 0xc0000374, STATUS_HEAP_CORRUPTION)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I am familiar with Linux debugging tools like GDB and Valgrind. So I attempted to use Windbg.&lt;/p&gt;

&lt;h1&gt;
  
  
  Install Windbg
&lt;/h1&gt;

&lt;p&gt;Download and install Windbg via below link first.&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/debugger-download-tools" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/debugger-download-tools&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Debug with Windbg
&lt;/h1&gt;

&lt;p&gt;Start your program &lt;code&gt;cargo run&lt;/code&gt;. It is ok to run release version, but debug version has a bit of nicer symbol information.&lt;/p&gt;

&lt;p&gt;Open Windbg, and attach your process as below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh1sdhxvrqq2xseowcob8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh1sdhxvrqq2xseowcob8.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then the process is attached and paused. Please click on "&lt;strong&gt;Go&lt;/strong&gt;" button on Windbg toolbar to continue the process.&lt;/p&gt;

&lt;p&gt;Now you can run your program until it crashes, and get a crash stack in Windbg as below.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo09tsgz7srqn9us5x6ev.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo09tsgz7srqn9us5x6ev.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is not the exact location that caused the crash，but it does help me solve the problem.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
