call_end

    • chevron_right

      Erlang Solutions: Reduce, Reuse… Refactor: Clearer Elixir with the Enum Module

      news.movim.eu / PlanetJabber • 24 April • 4 minutes

    “When an operation cannot be expressed by any of the functions in the Enum module, developers will most likely resort to reduce/3.”

    From the docs for Enum.reduce/3

    In many Elixir applications, I find Enum.reduce is used frequently. Enum.reduce can do anything, but that doesn’t mean it should. In many cases, other Enum functions are more readable, practically as fast, and easier to refactor.

    I would also like to discuss situations that are a good fit for Enum.reduce and also introduce you to a custom credo check I’ve created, which can help you identify places where Enum.reduce could be replaced with a simpler option.

    Readability

    Here are a few common reduce patterns—and their simpler alternatives.  For example, here’s something I see quite often:

    Enum.reduce(numbers, [], fn i, result -> [i * 10 | result] end)
    |> Enum.reverse()
    
    

    This is a situation that the Enum.map function was designed for:

    Enum.map(numbers, & &1 * 10)
    

    Perhaps you know about Enum.map , but you might see a call to reduce like this:

    Enum.reduce(numbers, 0, fn number, result -> (number * 2) + result end)
    
    

    Let me introduce you to Enum.sum_by !


    Enum.sum_by(numbers, & &1 * 2)
    
    

    Let’s look at something a bit more complex:

    Enum.reduce(numbers, [], fn item, acc ->
      if rem(item, 2) == 0 do
        [item * 2 | acc]
      else
        acc
      end
    end)
    |> Enum.reverse()
    
    

    This is a perfect case for piping together two Enum functions:

    numbers
    |> Enum.filter(& rem(&1, 2) == 0)
    |> Enum.map(& &1 * 2)
    

    Another option for this case could even be to use Enum.flat_map :


    Enum.flat_map(numbers, fn number ->
      if rem(number, 2) == 0 do
        [number * 2]
      else
        []
      end
    end)
    
    

    This is a decent option, but while this achieves the purpose of both filtering and mapping in a single pass, it may not be as intuitive for everybody.

    Lastly, say you see something like this and think that it would be difficult to improve:

    Enum.reduce(invoices, {[], []}, fn invoice, result ->
      Enum.reduce(invoice.items, result, fn item, {no_tax, with_tax} ->
        if Invoices.Items.taxable?(item) do
          tax = tax_for_value(item.amount, item.product_type)
          item = Map.put(item, :tax, tax)
    
          if Decimal.equal?(tax, 0) do
            {no_tax ++ [item], with_tax}
          else
            {no_tax, with_tax ++ [item]}
          end
        else
          {no_tax, with_tax}
        end
      end)
    end)
    
    

    But this is just the same:

    invoices
    |> Enum.flat_map(& &1.items)
    |> Enum.filter(&Invoices.Items.taxable?/1)
    |> Enum.map(& Map.put(&1, :tax, tax_for_value(&1.amount, &1.product_type)))
    |> Enum.split_with(& Decimal.equal?(&1.tax, 0))
    
    
    

    Aside from improving readability, splitting code out into pipes like this can make it easier to see the different parts of your logic.  Especially once you’ve created more than a few lines of pipes, it becomes easier to see how I can pull out different pieces when refactoring.  In the above, for example, you might decide to create a calculate_item_taxes function which takes a list of items and performs the logic of the Enum.map line.

    Performance

    You may have already thought of a counterpoint: when you pipe functions together, you end up creating new lists, which means more work to be done as well as more memory usage (which means more garbage collection).  This is absolutely true, and you should be thinking about this!

    But I find that 99% of the time, the data I’m working with makes the performance difference negligible.  If you find that your code is slow because of the amount of data that you need to process, you might try using the Stream module — it has many of the same functions as Enum , but works lazily.  If that doesn’t work, then by all means, create a reduce (and maybe put it into a well-named function)!

    As Joe Armstrong said:

    “Make it work, then make it beautiful, then if you really, really have to, make it fast.”

    For some information about benchmarks that I’ve run to understand this better, see this analysis and discussion .

    Good Opportunities for Enum.reduce

    Aside from occasional performance reasons, Enum.reduce can often be the simplest solution when you want to transform a data structure over a series of steps.  For example:

    Find Cases in Your Own Code with credo_unnecessary_reduce

    Remember that no one pattern works in all cases, so know what tools you have available! If you’d like to quickly find instances for potential improvements in readability, I built a Credo check to help spot where reduce can be swapped for something simpler.

    You can drop it into your project and start catching these anti-patterns automatically.

    https://github.com/cheerfulstoic/credo_unnecessary_reduce

    Simply add it to your mix.exs file:


    {:credo_unnecessary_reduce, "~> 0.1.0"}
    

    …and then enable it in your .credo.exs file:


    {CredounnecessaryReduce.Check, []}
    

    The post Reduce, Reuse… Refactor: Clearer Elixir with the Enum Module appeared first on Erlang Solutions .

    • wifi_tethering open_in_new

      This post is public

      www.erlang-solutions.com /blog/reduce-reuse-refactor-clearer-elixir-with-the-enum-module/

    • chevron_right

      Erlang Solutions: Erlang Solutions’ Blog round-up

      news.movim.eu / PlanetJabber • 17 April • 2 minutes

    The tech world doesn’t slow down, and neither do we. From the power of big data in healthcare to keeping you up-to-date about fintech compliance, our latest blog posts explore the important topics shaping today’s digital world.

    Whether you’re leading a business, building software, or just curious about the future of tech, check out what the Erlang Solutions team has been talking about.

    Understanding Big Data in Healthcare


    From smartwatches to digital patient records, healthcare is generating more data than ever before. In our post, Understanding Big Data in Healthcare , we explore how big data is transforming patient care—think predictive health trends, precision medicine, and smarter decision-making.

    We also dig into the challenges of handling sensitive information and how tech like Erlang, Elixir, and SAFE can help keep that data secure. It’s a must-read if you’re curious about how data is shaping the future of healthcare.

    Understanding Digital Wallets


    Digital wallets aren’t just convenient, but they’re quickly becoming essential. In Understanding Digital Wallets , we break down how they work, why they’re gaining momentum, and what they mean for businesses today.

    From improved security and cost savings to global access and smoother customer experiences, this blog gives a clear look at the benefits (and a few of the challenges) of going digital.

    Women in BEAM

    Lorena Mireles takes us through the key takeaways from her Women in BEAM survey, while also sharing her personal journey within the Elixir community.

    From representation gaps to the importance of strong role models, this piece highlights real experiences from developers in the BEAM ecosystem and why inclusion still matters in tech.

    Top 5 IoT Business Security Basics

    Billions of connected devices = billions of entry points for hackers. In Top 5 IoT Business Security Basics , we outline five practical tips to boost your IoT security:

    • Use strong, unique passwords
    • Encrypt your data
    • Run regular security audits
    • Train your team
    • Disable features you don’t use

    Simple, effective, and easy to implement—these tips will help you keep your systems (and customers) safe.

    DORA Compliance: What Fintech Businesses Need to Know


    Digital Operational Resilience Act (DORA) for fintech

    As of January 2025, the Digital Operational Resilience Act (DORA) is live, and if you’re in fintech, you need to be ready. Our post, DORA Compliance: What Fintech Businesses Need to Know , breaks down what DORA is, who it affects, and what steps you need to take to stay compliant (if you haven’t already).

    We explore its five key pillars and how to build a more resilient, disruption-proof business. With over 22,000 companies affected, it’s a timely read for anyone in the financial space.

    To conclude

    Staying ahead in tech doesn’t have to be overwhelming. Our goal? To make it easier for you to understand what’s happening and what it means for your business.

    Got questions? Let’s chat.

    The post Erlang Solutions’ Blog round-up appeared first on Erlang Solutions .

    • chevron_right

      Gajim: Gajim 2.1.1

      news.movim.eu / PlanetJabber • 17 April • 1 minute

    This release brings layout improvements to Gajim’s Start Chat dialog, an improved message search, and includes fixes for some issues with Message Displayed Synchronization. Thank you for all your contributions!

    What’s New

    Gajim 2.1 comes with a new ‘Activity feed’ which displays events around group chat invitations, contact requests, and updates. This will be the central feed for all kinds of activities in the future (e.g. reactions, replies, mentions, message reminders).

    Activity feed in Gajim 2.1

    Activity feed in Gajim 2.1

    Gajim 2.1.1 brings layout improvements for its Start Chat dialog, which now renders more compact and shows more information. This release also improves message search by displaying the last correction of a message and by not showing moderated messages. Last but not least, some issues with XEP-0490: Message Displayed Synchronization have been fixed.

    A note for Windows users: At the time of writing, there are some issues with emoji rendering on Windows. That’s why there is no release of Gajim 2.1 for Windows yet. This issue should soon be resolved and we will post an update once Gajim 2.1 is released on Windows.

    More Changes

    • Group chats now show voice request errors, if they happen
    • Setting your status for multiple accounts though the account sidebar now works properly

    And much more! Have a look at the changelog for a complete list.

    Gajim

    As always, don’t hesitate to contact us at gajim@conference.gajim.org or open an issue on our Gitlab .

    Support Gajim

    Gajim is free software developed by volunteers.
    If you like to support Gajim, please consider making a donation.

    Donate via Liberapay:

    liberapay-donate.svg

    • wifi_tethering open_in_new

      This post is public

      gajim.org /post/2025-04-17-gajim-2.1.1-released/

    • chevron_right

      ProcessOne: ejabberd 25.04

      news.movim.eu / PlanetJabber • 16 April • 2 minutes

    ejabberd 25.04

    Just a few weeks after previous release, ejabberd 25.04 is published with an important security fix, several bug fixes and a new API command.

    Release Highlights:

    If you are upgrading from a previous version, there are no changes in SQL schemas, configuration, API commands or hooks.

    Other contents:

    Below is a detailed breakdown of the improvements and enhancements:

    mod_muc_occupantid: Fix handling multiple occupant-id

    Fixed issue with handling of user provided occupant-id in messages and presences sent to muc room. Server was replacing just first instance of occupant-id with its own version, leaving other ones untouched. That would mean that depending on order in which clients send occupant-id, they could see value provided by sender, and that could be used to spoof as different sender.

    New kick_users API command

    There is a new API command kick_users that disconnects all the client sessions in a given virtual host.

    Acknowledgments

    We would like to thank the contributions to the source code, documentation, and translation provided for this release by:

    And also to all the people contributing in the ejabberd chatroom, issue tracker...

    Improvements in ejabberd Business Edition

    For customers of the ejabberd Business Edition , in addition to all those improvements and bugfixes:

    • Bugfix on max_concurrent_connections for mod_gcm , mod_webhook and mod_webpush

    ChangeLog

    This is a more complete list of changes in this ejabberd release:

    Security fixes

    • mod_muc_occupantid : Fix handling multiple occupant-id

    Commands API

    • kick_users : New command to kick all logged users for a given host

    Bugfixes

    • Fix issue with sql schema auto upgrade when using sqlite database
    • Fix problem with container update, that could ignore previous data stored in mnesia database
    • Revert limit of allowed characters in shared roster group names, that will again allow using symbols like :
    • Binary installers and ejabberd container image: Updated to Erlang/OTP 27.3.2

    Full Changelog

    https://github.com/processone/ejabberd/compare/25.03...25.04

    ejabberd 25.04 download & feedback

    As usual, the release is tagged in the Git source code repository on GitHub .

    The source package and installers are available in ejabberd Downloads page. To check the *.asc signature files, see How to verify ProcessOne downloads integrity .

    For convenience, there are alternative download locations like the ejabberd DEB/RPM Packages Repository and the GitHub Release / Tags .

    The ecs container image is available in docker.io/ejabberd/ecs and ghcr.io/processone/ecs . The alternative ejabberd container image is available in ghcr.io/processone/ejabberd .

    If you consider that you&aposve found a bug, please search or fill a bug report on GitHub Issues .

    • chevron_right

      ProcessOne: Hello from the other side: Matrix LEFT RIGHT ARROW XMPP via ejabberd 25.03

      news.movim.eu / PlanetJabber • 15 April • 2 minutes

    Hello from the other side: Matrix ↔ XMPP via ejabberd 25.03


    With ejabberd 25.03 , the Matrix gateway ( mod_matrix_gw ) now supports not only one-to-one chats, but also joining Matrix rooms via XMPP. That’s right — your favorite XMPP client can now talk to Matrix users or hop into Matrix rooms just like regular MUCs. ✨

    In this guide, we’ll show a quick demo of:

    1. One-to-one chat between an XMPP and a Matrix user.
    2. Joining a Matrix room and chatting from your XMPP client.

    And the best part? You don’t need to install a Matrix client at all. Keep your favorite XMPP client near, welcome to the magic of federation & interoperability.


    🛠 Setup Summary

    We won’t repeat the full configuration steps here — they’re already covered in this earlier blogpost and the 25.03 release note .

    In short, you’ll need:

    • A properly configured ejabberd server with mod_matrix_gw
    • Block outgoing connections to lethe.matrix.org to avoid conflicts with their XMPP instance

    Here’s a minimal config snippet:

    listen:
      -
        port: 8448
        module: ejabberd_http
        tls: true
        request_handlers:
          "/_matrix": mod_matrix_gw
    
    modules:
      mod_matrix_gw:
        key_name: "xxxxxx"
        key: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
        matrix_id_as_jid: true
    

    Wondering what is the Matrix signing key? Please refer to previous blog post: Matrix gateway setup with ejabberd

    Still not sure if your setup is correct? Try Matrix Federation Tester to check if everything is wired up properly.

    🧪 One-to-One Chat (XMPP ↔ Matrix)

    In your XMPP client (e.g. Psi), add a Matrix contact using this format:
    matrixUser%theirMatrixServer.tld@yourXMPPserver.tld

    In my case, that means:
    adrien-p1%matrix.org@matrix.mickael.m.in-app.io

    On the Matrix side (e.g. Element Web), your contact will get a request. Once accepted, you’re good to chat!

    ✅ Demo: XMPP user (Psi) chats with Matrix user (Element Web)

    🧪 Join a Matrix Room from your XMPP Client

    Alright, let’s join a public Matrix room now.

    From your XMPP client, you can join any Matrix public room using this format:
    #matrixRoom%theirMatrixServer.tld@yourXMPPserver.tld

    We’ll use the following room: #ejabberd-demo:matrix.org , so in my case, that means joining:
    #ejabberd-demo%matrix.org@matrix.mickael.m.in-app.io

    Once connected, you’ll be able to send and receive messages from any other participant, just like in a regular MUC. :)

    ✅ Demo: Join and chat in a Matrix room from XMPP

    🐞 Known Caveats

    There&aposs still a lot of work to do to make it seamless, here&aposs a short list of currently known caveats:

    • Room presence can be overwhelming in large rooms (thousands of Matrix users may appear "online").
    • No E2EE support between Matrix and XMPP — encryption must be disabled for now.
    • If the server restarts, 1-to-1 conversations must be restarted (re-added), as persistence is not implemented yet.
    • Only Matrix room protocol versions 9, 10, and 11 are supported.

    🧵 Wrapping Up

    With this, ejabberd makes another step into being a powerful bridge into the Matrix federation, for both private and public communication.

    It’s a great way to keep using your favorite XMPP tools while staying connected to Matrix communities.

    Got feedback? Drop us a line in the comments or open a PR .

    Happy bridging! 🙌

    • wifi_tethering open_in_new

      This post is public

      www.process-one.net /blog/hello-from-the-other-side-matrix-xmpp-via-ejabberd-25-03/

    • chevron_right

      Dino: Dino 0.5 Release

      news.movim.eu / PlanetJabber • 11 April • 1 minute

    Dino is a secure and open-source messaging application. It uses the XMPP (Jabber) protocol for decentralized communication. We aim to provide an intuitive and enjoyable user interface.

    The 0.5 release improves the user experience around file transfers and includes two completely reworked dialogs.

    Improved file sharing

    image_preview_loading.png

    The way file transfers are currently done in the XMPP ecosystem is limited in functionality and files can sometimes be received out-of-order. Dino now supports a new method for announcing file transfers ( XEP-0447 ), which solves this issue. Additionally, users can now see preview images or other file details before downloading the file. Dino currently only uses the new method for unencrypted file transfers, for example in public channels. Encrypted file transfers will also support the new protocol once Dino supports full-stanza encryption. All file transfers now also display the upload or download progress.

    Screenshots of three dialogs for account settings, encryption and contact details

    Reworked dialogs

    The account and preferences dialogs have been combined into a single, new dialog. This dialog lets you manage accounts and adjust encryption and other settings. It now also includes some new settings like an option for OMEMO encryption by default, which is enabled by default.

    Additionally, the conversation details dialog has been completely redesigned. Both dialogs are now fully compatible with mobile devices.

    Colors and more

    Dino now uses the same fallback avatar colors as other clients ( XEP-0392 ), creating a more consistent experience across applications.

    A new unread line has been added, indicating the point up to which you’ve already read the messages.

    Dino has also switched from CMake to Meson, which allows for an easier development process.

    Alentejo

    We named this Dino release “Alentejo” after a region in Portugal.

    monsaraz.jpg

    Alentejo is a region in southern Portugal that is known for its wide plains that are dotted with wineyards and cork trees. The region has a Mediterranean climate with summers regularly reaching temperatures above 40 degrees.

    Currently, about 3.6% of all deaths in the region are caused by heat. Heatwaves, in particular, pose a serious health risk and are expected to become more frequent and severe due to global warming [ 1 ]. If CO₂ emissions keep increasing, heat-related deaths could make up 15.8% of all deaths in the region by 2100. However, if action is taken to combat climate change, this number could be limited to 6.6% [ 2 ].

    • wifi_tethering open_in_new

      This post is public

      dino.im /blog/2025/04/dino-0.5-release/

    • chevron_right

      Ignite Realtime Blog: New releases for Tinder and Whack!

      news.movim.eu / PlanetJabber • 11 April • 1 minute

    The IgniteRealtime community is happy to announce releases for two of its projects! Both are for XMPP-libraries that we produce.

    Tinder is a Java based XMPP library, providing an implementation for XMPP stanzas and components. Tinder’s origins lie in code that’s shared between our Openfire and Whack implementations. The implementation that’s provided in Tinder hasn’t been written again from scratch. Instead, code has been moved from the original projects into Tinder, preserving al of the existing features and functionality.

    The v2.1.0 release of Tinder is a maintenance release. It updates various libraries that are used by Tinder, and removes deprecated, unused code. Tinder now requires Java 11 or later. The full list of changes in this release can be found in the release notes .

    Whack is a Java library that easily allows the creation of external components that follow the XEP-0114: Jabber Component Protocol. This library allows you to create server-sided components of your XMPP network that can run as stand-alone processes. That’s particularly useful when you are creating functionality for which scalability configuration differs from that of Openfire, or if you want to re-use your component for XMPP servers other than Openfire!

    The v3.0.0 release of Whack is a maintenance release. It improves reconnection logic (when connection to the XMPP server is lost), it no longer ships with an embedded webserver (that was old, unused, and was raising vulnerability warnings, and updates some libraries (such as Tinder) to more recent versions. The fulll list of chagnes in this release can be found in the release notes .

    We would love to hear from you! If you have any questions, please stop by our community forum or our live groupchat .

    For other release announcements and news follow us on Mastodon or X

    1 post - 1 participant

    Read full topic

    • chevron_right

      Erlang Solutions: Elixir for Business: 5 Ways It Transforms Your Processes

      news.movim.eu / PlanetJabber • 10 April • 2 minutes

    Elixir is a lightweight, high-performance programming language built on the Erlang virtual machine. It’s known for its simple syntax and efficient use of digital resources. But how does this translate to business benefits?

    Elixir is already powering companies like Discord and Pinterest. It helps businesses reduce costs, improve process efficiency, and speed up time to market.

    Here are five reasons why Elixir is a game-changer for your business.

    1. Cleaner Code, Faster Progress

    Elixir is designed for simplicity. Its clean syntax and functional style help developers write concise, readable code, with fewer bugs and less overhead.

    For teams, this means faster development cycles and smoother collaboration. For businesses, it means shorter time to market and reduced long-term maintenance costs, which is especially useful during talent shortages.

    Projects move faster when your team isn’t fighting complexity.

    2. Built-In Concurrency, Built-In Stability

    Concurrency – the ability to run multiple tasks at once -is essential for modern applications. Elixir handles this natively, thanks to the Erlang virtual machine it runs on.

    With Elixir, you can run millions of lightweight processes simultaneously . It’s ideal for:

    • Real-time systems (e.g., messaging, live data feeds)
    • Applications with high user demand
    • Businesses that can’t afford downtime

    Crucially, these processes run independently. If one fails, the rest carry on — making your application more resilient by design.

    3. Smarter Use of Resources

    Elixir is resource-efficient. As your infrastructure scales, Elixir adapts automatically using the processing power available.

    This has clear benefits:

    • No wasted server capacity
    • Better app performance on existing infrastructure
    • Lower hosting and scaling costs

    Your tech stack runs leaner and more efficiently, with fewer surprises at scale.

    4. Elixir means simple scalability

    Elixir was made for scalable systems. Its lightweight processes and distributed architecture allow your application to grow without rewriting core components.

    What sets it apart:

    • Seamless horizontal scaling across machines
    • High fault tolerance through process isolation
    • Built-in support for distributed systems

    This makes Elixir especially strong for digital products that need to scale quickly or support unpredictable usage.

    Take Bleacher Report . They switched from Ruby to Elixir and saw results:

    Bleacher report Elixir

    • Server count dropped from 150 to 8
    • The app now handles over 200 million push notifications a day
    • Performance improved, with far fewer bottlenecks

    All of this was achieved while reducing infrastructure overhead.

    Read the full case study here .

    Modern Tools for Modern Challenges

    Elixir isn’t just fast it’s current.

    It supports distributed teams, integrates with today’s tools, and works well alongside other languages and frameworks.

    It’s especially useful for:

    • Products that need to ship fast and scale cleanly
    • Teams juggling real-time features, analytics or event-driven systems
    • Organisations focused on reliability and long-term performance

    Unlike many programming languages, Elixir is both powerful and practical.

    To conclude

    Elixir helps teams move quickly, handle growth with ease, and build reliable systems without unnecessary complexity. For modern businesses building digital platforms, it’s a quiet powerhouse and a strong strategic choice.

    Want to learn more about Elixir? Explore the full “What is Elixir?” post .

    Want to discuss how Elixir can enhance your business performance? Get in touch with the team.

    The post Elixir for Business: 5 Ways It Transforms Your Processes appeared first on Erlang Solutions .

    • wifi_tethering open_in_new

      This post is public

      www.erlang-solutions.com /blog/5-ways-elixir-can-improve-business-performance/

    • chevron_right

      Gajim: Gajim 2.1.0

      news.movim.eu / PlanetJabber • 8 April • 1 minute

    This release brings an all-new activity feed and adds support for Message Displayed Synchronization across group chats. Thank you for all your contributions!

    What’s New

    Gajim 2.1 comes with a new page called ‘Activity feed’. Currently, it displays events around group chat invitations, contact requests, and updates. Clicking an event allows you to act on it (e.g. accept an invitation) A badge indicates new activities on the top left corner of Gajim’s window. This will be the central feed for all kinds of activities in the future (e.g. reactions, replies, mentions, message reminders).

    Activity feed in Gajim 2.1

    Activity feed in Gajim 2.1

    If you have more than one account enabled in Gajim, accounts will now be displayed inside a menu available at the bottom left corner of the window. A left click brings you to your account, while a right click allows your to set your status.

    Account and status selection in Gajim 2.1

    Account and status selection in Gajim 2.1

    When following large group chats across multiple devices, you’ve probably experienced this: You read all new messages on one device, and later you switch to another device, but all those messages you’ve already read are now shown as unread messages. Seeing if you have read messages on another device is now supported by Gajim through XEP-0490: Message Displayed Synchronization . This feature is also supported by Conversations on Android for example. Thanks @nicoco for contributing to this feature!

    A note for Windows users: At the time of writing, there are some issues with emoji rendering on Windows. That’s why there is no release of Gajim 2.1 for Windows yet. This issue should soon be resolved and we will post an update once Gajim 2.1 is released on Windows.

    More Changes

    • Status icon: Fixed showing menu correctly
    • Emoji chooser: Fixed segfault after choosing emoji, which occurred on some systems
    • Nickname: Fixed displaying published nickname correctly
    • Start chat: Added ‘Execute Command…’ menu item
    • Removed unread message confirmation dialog at shutdown

    And much more! Have a look at the changelog for a complete list.

    Gajim

    As always, don’t hesitate to contact us at gajim@conference.gajim.org or open an issue on our Gitlab .

    Support Gajim

    Gajim is free software developed by volunteers.
    If you like to support Gajim, please consider making a donation.

    Donate via Liberapay:

    liberapay-donate.svg

    • wifi_tethering open_in_new

      This post is public

      gajim.org /post/2025-04-08-gajim-2.1.0-released/