Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
171 changes: 160 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,166 @@
# androidircx
# AndroidIRCx Flutter

A new Flutter project.
Flutter rewrite of AndroidIRCx, focused on preserving behavior, features, and UX parity with the
existing React Native application.

## Getting Started
## Current Status

This project is a starting point for a Flutter application.
This repository is an active rewrite in progress.

A few resources to get you started if this is your first Flutter project:
Implemented in the current Flutter app:

- [Learn Flutter](https://docs.flutter.dev/get-started/learn-flutter)
- [Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
- [Flutter learning resources](https://docs.flutter.dev/reference/learning-resources)
- network list and add/edit flow
- basic IRC socket connection lifecycle
- server, channel, and query tabs
- basic message sending and receiving
- local persistence for networks, tabs, message history, and a small settings set
- reconnect banner and basic connection status UX

For help getting started with Flutter development, view the
[online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
Not implemented yet in full parity:

- CAP/SASL full flow
- multi-network orchestration parity
- advanced numerics and command coverage
- notifications/background behavior
- encryption
- DCC/media
- monetization and security platform features

The feature list below describes the target AndroidIRCx parity scope, not the current Flutter
implementation status.

## 🔐 Security

- **TLS/SSL** -- full encrypted connection support
- **SASL** -- PLAIN, SCRAM-SHA-256, EXTERNAL (client certificates)
- **E2E Encryption** -- libsodium XChaCha20-Poly1305 with context-bound AAD
- **Secure Storage** -- device Keychain for secrets (AsyncStorage fallback with warning)
- **App Lock** -- PIN and biometric with auto-lock on background/launch
- **Kill Switch** -- emergency disconnect and optional data wipe
- **Play Integrity** -- Google Play Integrity verification


## 🤝 Contributing

AndroidIRCX is open source and contributions are welcome.

**Areas where you can help:**

- IRC protocol -- new IRCv3 capabilities, IRCd-specific features
- Testing -- more edge cases, integration tests
- Translations -- add or improve translations via Transifex
- UI/UX -- accessibility, new themes, layout improvements
- Documentation -- guides, tutorials, examples
- Security -- audit, improvements, new encryption features

- **Before submitting a PR:**

```bash
flutter analyze
flutter test # Must pass all
```

## 📝 IRC Protocol Compliance

| Standard | Coverage |
|----------|------------------------------------------------|
| RFC 1459 | Full compliance |
| RFC 2812 | Extended numeric support (390+ handlers) |
| IRCv3 | 27 capabilities requested, full implementation |
| SASL | PLAIN + SCRAM-SHA-256 (RFC 7677) + EXTERNAL |
| DCC | SEND, CHAT |
| CTCP | Full (VERSION, TIME, PING, ACTION, etc.) |

---

## 🎨 Credits & Inspiration

**IRCap** (c) Carlos Esteve Cremades, 1997-2026 - the legendary mIRC script that inspired
AndroidIRCX's away system, protection features, writing styles, and the IRcap theme. If you used
mIRC in the 2000s, you probably know IRCap. Its futuristic design and complete feature set set the
bar for what an IRC experience should be.

**IRcap theme for AndroidIRCX** by ARGENTIN07, based on the original IRCap theme.

**Translations:** ARGENTIN07 and Cubanita83 (Spanish), Yusbastian Lemon (Indonesian). See the full
credits in the app's Credits screen.

As an open-source creator, I deeply respect the work of **Linus Torvalds** and **Richard Stallman**
for the free/open-source software movement. Their vision and persistence were a direct inspiration
for building this app as open source.

[![Linux](https://img.shields.io/badge/Linux-Tux-FCC624?logo=linux&logoColor=black)](https://www.kernel.org/)
[![GNU](https://img.shields.io/badge/GNU-Project-A42E2B?logo=gnu&logoColor=white)](https://www.gnu.org/)

---

## 📄 License

**GNU General Public License v3.0 or later (GPL-3.0-or-later)**

Copyright (C) 2025-2026 Velimir Majstorov

This program is free software: you can redistribute it and/or modify it under the terms of the GNU
General Public License as published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
the [GNU General Public License](LICENSE.md) for more details.

You should have received a copy of the GNU General Public License along with this program. If not,
see <https://www.gnu.org/licenses/>.

---

## 🤖 AI Usage Disclaimer

This project was built with modern tools, including AI-assisted development.

Like robotics in manufacturing, autopilot systems in agriculture, and autocomplete in software,
AI is a tool -- no more, no less.

**AI did not build this project on its own.**
Every decision, architectural choice, security consideration, and final line of code was reviewed,
validated, and maintained by a human engineer with more than 25 years of professional experience.

AI did not replace engineering judgment; it accelerated routine work so more time could be spent on
architecture, quality, and usability.

If you prefer software created without automation or AI assistance, that choice is fully respected.
At the same time, refusing tools has never stopped progress -- it has only determined who
participates in shaping it.

This project exists to contribute something real to open source, with practical value and
long-term maintenance. You are welcome to:

- use it or study it
- fork it or improve it
- or simply ignore it

All are valid choices.

Builders shape the future in silence. Spectators explain it when the work is already done.

In the end, technology moves forward with or without permission. The only question is who chose to
be part of it.

Some build loudly. Others build correctly.

Those who recognize the work will understand. Time will explain the rest.

🜂🜃🜂

---

<p align="center">
<a href="https://AndroidIRCx.com">
<img src="https://AndroidIRCx.com/android-icon-192x192.webp" width="64" height="64" alt="AndroidIRCx">
</a>
</p>

<p align="center">
<b><a href="https://androidircx.com">AndroidIRCx.com</a></b>
</p>

---
4 changes: 2 additions & 2 deletions android/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ plugins {
}

android {
namespace = "com.example.androidircx"
namespace = "com.androidircx.flutter"
compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion

Expand All @@ -21,7 +21,7 @@ android {

defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId = "com.example.androidircx"
applicationId = "com.androidircx.flutter"
// You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = flutter.minSdkVersion
Expand Down
2 changes: 1 addition & 1 deletion android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:label="androidircx"
android:label="@string/app_name"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.example.androidircx
package com.androidircx.flutter

import io.flutter.embedding.android.FlutterActivity

Expand Down
Binary file modified android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions android/app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<resources>
<string name="app_name">AndroidIRCx Flutter</string>
</resources>
12 changes: 6 additions & 6 deletions ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.androidircx;
PRODUCT_BUNDLE_IDENTIFIER = com.androidircx.flutter;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
Expand All @@ -388,7 +388,7 @@
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.androidircx.RunnerTests;
PRODUCT_BUNDLE_IDENTIFIER = com.androidircx.flutter.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
Expand All @@ -405,7 +405,7 @@
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.androidircx.RunnerTests;
PRODUCT_BUNDLE_IDENTIFIER = com.androidircx.flutter.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
Expand All @@ -420,7 +420,7 @@
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.androidircx.RunnerTests;
PRODUCT_BUNDLE_IDENTIFIER = com.androidircx.flutter.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
Expand Down Expand Up @@ -551,7 +551,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.androidircx;
PRODUCT_BUNDLE_IDENTIFIER = com.androidircx.flutter;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
Expand All @@ -573,7 +573,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.androidircx;
PRODUCT_BUNDLE_IDENTIFIER = com.androidircx.flutter;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
Expand Down
Loading