Compare commits

..

1 commit

Author SHA1 Message Date
Christian Kußowski
8594d2292b
feat: New login with homeserver picker 2025-09-07 12:04:22 +02:00
459 changed files with 124458 additions and 110879 deletions

View file

@ -34,28 +34,6 @@ body:
placeholder: "e.g. 1.12.0"
validations:
required: true
- type: dropdown
id: platform
attributes:
label: "Platform"
description: "Select the platform where the bug occurs."
options:
- Android (PlayStore)
- Android (F-Droid)
- Android (Other)
- iOS (iPhone)
- iOS (iPad)
- Web (Chrome(ium))
- Web (Firefox)
- Web (Safari)
- Linux (Snap)
- Linux (Flatpak)
- Linux (Other)
- macOS (iOS/iPadOS version)
- macOS (Self-compiled)
- Windows (Self-compiled)
validations:
required: true
- type: input
id: platform-info
attributes:

View file

@ -1,5 +1,5 @@
blank_issues_enabled: false
blank_issues_enabled: true
contact_links:
- name: 👬 FluffyChat Community
url: https://matrix.to/#/#fluffy-space:matrix.org
url: https://matrix.to/#/#fluffychat:matrix.org
about: Please ask and answer questions here.

View file

@ -39,6 +39,3 @@ labels: test
10. Drag&Drop to send a file into a chat still works:
- [ ] Web
- [ ] Linux
11. Deeplinks are still working? https://matrix.to/#/@krille:janian.de
- [ ] Android
- [ ] iOS

View file

@ -1,50 +0,0 @@
name: "Free up space"
inputs:
target:
required: true
runs:
using: "composite"
steps:
- name: Free up space
shell: bash
run: |
sudo rm -rf /usr/share/dotnet
sudo rm -rf /usr/local/share/boost
sudo rm -rf /usr/local/share/chromium
sudo rm -rf /usr/local/share/powershell
sudo rm -rf /usr/local/share/vcpkg
sudo rm -rf /usr/local/share/miniconda
sudo rm -rf /opt/ghc
sudo rm -rf /opt/hostedtoolcache/CodeQL
sudo rm -rf /opt/hostedtoolcache/go
sudo rm -rf /opt/hostedtoolcache/Python
sudo rm -rf /opt/hostedtoolcache/node
sudo rm -rf /opt/hostedtoolcache/R
sudo rm -rf /opt/hostedtoolcache/Java
sudo rm -rf /opt/hostedtoolcache/LLVM
sudo rm -rf /opt/hostedtoolcache/Swift
sudo rm -rf /opt/hostedtoolcache/Php
sudo rm -rf /opt/hostedtoolcache/Perl
sudo rm -rf /opt/hostedtoolcache/Scala
sudo rm -rf /opt/hostedtoolcache/Julia
sudo rm -rf /opt/hostedtoolcache/Mono
sudo rm -rf /opt/hostedtoolcache/PowerShell
sudo rm -rf /opt/hostedtoolcache/Crystal
sudo rm -rf /opt/hostedtoolcache/Elixir
sudo rm -rf /opt/hostedtoolcache/Erlang
sudo rm -rf /opt/hostedtoolcache/FSharp
sudo rm -rf /opt/hostedtoolcache/Haskell
sudo rm -rf /opt/hostedtoolcache/OCaml
sudo rm -rf /opt/hostedtoolcache/Sbt
sudo rm -rf /opt/hostedtoolcache/Solidity
sudo rm -rf /opt/hostedtoolcache/VisualStudio
sudo rm -rf /opt/hostedtoolcache/WinAppDriver
sudo rm -rf /opt/hostedtoolcache/Xamarin
sudo rm -rf /opt/hostedtoolcache/Yarn
sudo rm -rf /opt/hostedtoolcache/Zephyr
sudo rm -rf /opt/hostedtoolcache/zig
sudo rm -rf /opt/hostedtoolcache/zulu
sudo rm -rf /opt/hostedtoolcache/azcopy
echo "export CARGO_BUILD_JOBS=1" >> $GITHUB_ENV

View file

@ -1,6 +1,13 @@
*Thank you so much for your contribution to FluffyChat ❤️❤️❤️*
- [ ] I have read and understood the [contributing guidelines](https://github.com/krille-chan/fluffychat/blob/main/CONTRIBUTING.md).
Please make sure that your Pull Request meet the following **acceptance criteria**:
- [ ] Code formatting and import sorting has been done with `dart format lib/ test/` and `dart run import_sorter:main --no-comments`
- [ ] The commit message uses the format of [Conventional Commits](https://www.conventionalcommits.org)
- [ ] The commit message describes what has been changed, why it has been changed and how it has been changed
- [ ] Every new feature or change of the design/GUI is linked to an approved design proposal in an issue
- [ ] Every new feature in the app or the build system has a strategy how this will be tested and maintained from now on for every release, e.g. a volunteer who takes over maintainership
### Pull Request has been tested on:

28
.github/workflows/check_duplicates.yaml vendored Normal file
View file

@ -0,0 +1,28 @@
name: Check duplicates
on:
issues:
types: [opened]
jobs:
check_duplicates:
runs-on: ubuntu-latest
env:
title: ${{ github.event.issue.title }}
author: ${{ github.event.issue.user.login }}
number: ${{ github.event.issue.number }}
GH_TOKEN: ${{ github.token }}
steps:
- uses: actions/checkout@v5
- name: Check duplicates
run: |
issues=$(gh issue list --search '${{ env.title }}' --json number,title,url)
number=${{ env.number }}
issues_filtered=$(echo "$issues" | jq --arg num "$number" 'map(select(.number != ($num | tonumber)))')
if [ "$(echo "$issues_filtered" | jq length)" -eq 0 ]; then
echo "No duplicates found."
else
issues_markdown=$(echo "$issues_filtered" | jq -r '.[] | "- [" + .title + "](" + .url + ")"')
formatted_body=$(echo -e "@${{ env.author }}\nPossible duplication of:\n$issues_markdown")
gh issue comment ${{ github.event.issue.number }} --body "$formatted_body"
fi

View file

@ -8,19 +8,16 @@ jobs:
code_tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: webiny/action-conventional-commits@v1.3.1
- uses: actions/checkout@v5
- run: ./scripts/generate-locale-config.sh
- run: git diff --exit-code
- run: cat .github/workflows/versions.env >> $GITHUB_ENV
- uses: subosito/flutter-action@v2
with:
flutter-version-file: .tool_versions.yaml
flutter-version: ${{ env.FLUTTER_VERSION }}
cache: true
- name: Check for unused translations
run: flutter pub run translations_cleaner list-unused-terms -a
- run: flutter pub get
- name: Check if pubspec.lock is up to date
run: git diff --exit-code pubspec.lock
- run: flutter gen-l10n
- name: Check formatting
run: dart format lib/ test/ --set-exit-if-changed
- name: Check import formatting
@ -28,87 +25,54 @@ jobs:
- name: Check license compliance
run: dart run license_checker check-licenses -c licenses.yaml --problematic
- run: flutter analyze
- name: Search unused dependencies
run: |
dart pub global activate dependency_validator
dart pub global run dependency_validator
- run: dart run dart_code_linter:metrics analyze lib --reporter=github
- run: dart run dart_code_linter:metrics check-unused-code lib
- run: dart run dart_code_linter:metrics check-unused-files lib
- run: dart run dart_code_linter:metrics check-unused-l10n lib
- name: Check for commented-out Dart code with semicolons
run: |
if grep -R --include="*.dart" -nE '^[[:space:]]*//[^/<].*;[[:space:]]*$' lib/; then
echo ""
echo "❌ Found commented-out Dart code ending with semicolon."
exit 1
fi
- name: Add Firebase Messaging
run: ./scripts/add-firebase-messaging.sh
- run: flutter analyze
- run: flutter test
build_debug_apk:
needs: [ code_tests ]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: ./.github/actions/free_up_space
- uses: actions/checkout@v5
- run: cat .github/workflows/versions.env >> $GITHUB_ENV
- uses: actions/setup-java@v5
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: "zulu"
- uses: subosito/flutter-action@v2
with:
flutter-version-file: .tool_versions.yaml
flutter-version: ${{ env.FLUTTER_VERSION }}
cache: true
- uses: moonrepo/setup-rust@v1
with:
cache: true
- name: Cache Gradle
uses: actions/cache@v5
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: gradle-${{ runner.os }}-
- run: ./scripts/add-firebase-messaging.sh
- run: flutter build apk --debug --target-platform android-x64
- name: Upload Debug APK
uses: actions/upload-artifact@v7
with:
name: debug-apk-x64
path: build/app/outputs/flutter-apk/app-debug.apk
- run: flutter pub get
- run: flutter build apk --debug
build_debug_web:
needs: [ code_tests ]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v5
- run: cat .github/workflows/versions.env >> $GITHUB_ENV
- uses: subosito/flutter-action@v2
with:
flutter-version-file: .tool_versions.yaml
flutter-version: ${{ env.FLUTTER_VERSION }}
cache: true
- uses: moonrepo/setup-rust@v1
- run: rustup component add rust-src --toolchain nightly-x86_64-unknown-linux-gnu
- run: flutter pub get
- name: Prepare web
run: ./scripts/prepare-web.sh
- run: flutter build web --dart-define=WITH_SEMANTICS=true
- name: Upload Web Build
uses: actions/upload-artifact@v7
with:
name: Web Build
path: build/web
- run: flutter build web
build_debug_linux:
needs: [ code_tests ]
strategy:
matrix:
arch: [ x64, arm64 ]
runs-on: ${{ matrix.arch == 'arm64' && 'ubuntu-24.04-arm' || 'ubuntu-latest'}}
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v5
- run: cat .github/workflows/versions.env >> $GITHUB_ENV
- name: Install dependencies
run: sudo apt-get update && sudo apt-get install git wget curl clang cmake ninja-build pkg-config libgtk-3-dev libblkid-dev liblzma-dev libjsoncpp-dev cmake-data libsecret-1-dev libsecret-1-0 librhash0 libwebkit2gtk-4.1-dev -y
- run: echo "FLUTTER_VERSION=$(yq '.environment.flutter' < .tool_versions.yaml)" >> $GITHUB_ENV
run: sudo apt-get update && sudo apt-get install git wget curl clang cmake ninja-build pkg-config libgtk-3-dev libblkid-dev liblzma-dev libjsoncpp-dev cmake-data libsecret-1-dev libsecret-1-0 librhash0 libssl-dev libwebkit2gtk-4.1-dev -y
- name: Install Flutter
run: |
git clone --branch ${{ env.FLUTTER_VERSION }} https://github.com/flutter/flutter.git
@ -118,13 +82,13 @@ jobs:
- run: ./flutter/bin/flutter build linux --target-platform linux-${{ matrix.arch }}
build_debug_ios:
needs: [ code_tests ]
runs-on: macos-15
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v5
- run: cat .github/workflows/versions.env >> $GITHUB_ENV
- uses: subosito/flutter-action@v2
with:
flutter-version-file: .tool_versions.yaml
flutter-version: ${{ env.FLUTTER_VERSION }}
cache: true
- name: Use Xcode 16.4
run: sudo xcode-select --switch /Applications/Xcode_16.4.app
@ -136,114 +100,3 @@ jobs:
sed -i '' 's,//<GOOGLE_SERVICES>,,g' lib/utils/background_push.dart
- run: flutter pub get
- run: flutter build ios --no-codesign
integration_test:
runs-on: ubuntu-latest
timeout-minutes: 60
needs: [ build_debug_apk ]
strategy:
matrix:
api-level: [34]
env:
ANDROID_USER_HOME: /home/runner/.android
ANDROID_EMULATOR_HOME: /home/runner/.android
ANDROID_AVD_HOME: /home/runner/.android/avd
AVD_CONFIG_PATH: "~/.android/avd/test.avd/config.ini"
steps:
- uses: actions/checkout@v6
- uses: actions/download-artifact@v8
with:
name: debug-apk-x64
path: .
- uses: ./.github/actions/free_up_space
# https://github.blog/changelog/2023-02-23-hardware-accelerated-android-virtualization-on-actions-windows-and-linux-larger-hosted-runners/
- name: Enable KVM group perms
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- name: AVD cache
uses: actions/cache@v5
id: avd-cache
with:
path: ~/.android/*
key: avd-${{ matrix.api-level }}-integration_docker
- name: create AVD and generate snapshot for caching
if: steps.avd-cache.outputs.cache-hit != 'true'
uses: reactivecircus/android-emulator-runner@d94c3fbe4fe6a29e4a5ba47c12fb47677c73656b
with:
api-level: ${{ matrix.api-level }}
target: google_apis
arch: x86_64
cores: 16
ndk: 28.2.13676358
force-avd-creation: false
disk-size: 4096M
ram-size: 4096M
sdcard-path-or-size: 4096M
emulator-options: -no-window -wipe-data -accel on -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
script: |
cat ${{ env.AVD_CONFIG_PATH }}
sed -i.bak 's/hw.lcd.density = .*/hw.lcd.density=420/' ${{ env.AVD_CONFIG_PATH }}
sed -i.bak 's/hw.lcd.height = .*/hw.lcd.height=1920/' ${{ env.AVD_CONFIG_PATH }}
sed -i.bak 's/hw.lcd.width = .*/hw.lcd.width=1080/' ${{ env.AVD_CONFIG_PATH }}
if ! grep -q "hw.lcd.density" ${{ env.AVD_CONFIG_PATH }} && echo "hw.lcd.density = 420" >> ${{ env.AVD_CONFIG_PATH }}; then :; fi
if ! grep -q "hw.lcd.height" ${{ env.AVD_CONFIG_PATH }} && echo "hw.lcd.height = 1920" >> ${{ env.AVD_CONFIG_PATH }}; then :; fi
if ! grep -q "hw.lcd.width" ${{ env.AVD_CONFIG_PATH }} && echo "hw.lcd.width = 1080" >> ${{ env.AVD_CONFIG_PATH }}; then :; fi
echo "Emulator settings (${{ env.AVD_CONFIG_PATH }})"
cat ${{ env.AVD_CONFIG_PATH }}
echo "Generated AVD snapshot for caching."
- uses: subosito/flutter-action@v2
with:
flutter-version-file: .tool_versions.yaml
cache: true
- uses: remarkablemark/setup-maestro-cli@v1
- name: Load integration test env
run: cat integration_test/data/integration_users.env >> $GITHUB_ENV
- name: Prepare Homeserver
run: |
docker run -d --name synapse --tmpfs /data \
--volume="$(pwd)/integration_test/synapse/data/homeserver.yaml":/data/homeserver.yaml:rw \
--volume="$(pwd)/integration_test/synapse/data/localhost.log.config":/data/localhost.log.config:rw \
-p 80:80 matrixdotorg/synapse:latest
while ! curl -XGET "http://$HOMESERVER/_matrix/client/v3/login" >/dev/null 2>/dev/null; do
echo "Waiting for homeserver to be available... (GET http://$HOMESERVER/_matrix/client/v3/login)"
sleep 2
done
echo "Homeserver is online!"
# create users
curl -fS --retry 3 -XPOST -d "{\"username\":\"$USER1_NAME\", \"password\":\"$USER1_PW\", \"inhibit_login\":true, \"auth\": {\"type\":\"m.login.dummy\"}}" "http://$HOMESERVER/_matrix/client/r0/register"
curl -fS --retry 3 -XPOST -d "{\"username\":\"$USER2_NAME\", \"password\":\"$USER2_PW\", \"inhibit_login\":true, \"auth\": {\"type\":\"m.login.dummy\"}}" "http://$HOMESERVER/_matrix/client/r0/register"
- name: Integration tests
id: integration_tests
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: ${{ matrix.api-level }}
target: google_apis
arch: x86_64
cores: 16
ndk: 28.2.13676358
force-avd-creation: false
disk-size: 4096M
ram-size: 4096M
sdcard-path-or-size: 4096M
emulator-options: -no-snapshot-save -no-window -wipe-data -accel on -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
script: |
flutter run --use-application-binary=$PWD/app-debug.apk > flutter_logs.txt 2>&1 &
FLUTTER_PID=$!
maestro test integration_test/login.yaml --env HOMESERVER=10.0.2.2 --env USER1_NAME=${USER1_NAME} --env USER1_PW=${USER1_PW}
kill $FLUTTER_PID 2>/dev/null || true
cp flutter_logs.txt ~/.maestro/tests/
- name: Upload Flutter and Maestro logs
if: failure()
uses: actions/upload-artifact@v7
with:
name: maestro-logs
path: ~/.maestro/tests
if-no-files-found: ignore

View file

@ -14,10 +14,11 @@ jobs:
deploy_web:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v5
- run: cat .github/workflows/versions.env >> $GITHUB_ENV
- uses: subosito/flutter-action@v2
with:
flutter-version-file: .tool_versions.yaml
flutter-version: ${{ env.FLUTTER_VERSION }}
- uses: moonrepo/setup-rust@v1
- run: rustup component add rust-src --toolchain nightly-x86_64-unknown-linux-gnu
- name: Prepare web
@ -38,16 +39,20 @@ jobs:
deploy_playstore_internal:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v5
- run: cat .github/workflows/versions.env >> $GITHUB_ENV
- uses: actions/setup-java@v5
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: 'zulu'
- uses: subosito/flutter-action@v2
with:
flutter-version-file: .tool_versions.yaml
flutter-version: ${{ env.FLUTTER_VERSION }}
cache: true
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.3'
- uses: ./.github/actions/free_up_space
- uses: moonrepo/setup-rust@v1
- name: Install Fastlane
run: gem install fastlane -NV
@ -63,7 +68,7 @@ jobs:
PLAYSTORE_DEPLOY_KEY: ${{ secrets.PLAYSTORE_DEPLOY_KEY }}
run: ./scripts/prepare-android-release.sh
- name: Build Android Release
run: flutter build appbundle --target-platform android-arm,android-arm64
run: flutter build appbundle --target-platform android-arm,android-arm64,android-x64
- name: Set changelog
working-directory: android/fastlane/metadata/android/en-US/changelogs
run: git log --no-merges -1 --pretty=%B > default.txt

View file

@ -1,60 +0,0 @@
name: Matrix Notification
on:
issues:
types: [opened]
pull_request_target:
types: [opened]
jobs:
notify:
if: ${{ (github.event_name == 'issues' && github.event.issue.user.login != 'krille-chan') || (github.event_name == 'pull_request_target' && github.event.pull_request.user.login != 'krille-chan') }}
runs-on: ubuntu-latest
steps:
- name: Send notification to Matrix room
env:
HOMESERVER: ${{ secrets.MATRIX_HOMESERVER }}
ACCESS_TOKEN: ${{ secrets.MATRIX_ACCESS_TOKEN }}
ROOM_ID: ${{ secrets.MATRIX_ROOM_ID }}
EVENT_NAME: ${{ github.event_name }}
ISSUE_TITLE: ${{ github.event.issue.title }}
ISSUE_URL: ${{ github.event.issue.html_url }}
ISSUE_LABELS: ${{ join(github.event.issue.labels.*.name, ', ') }}
ISSUE_AUTHOR: ${{ github.event.issue.user.login }}
PR_TITLE: ${{ github.event.pull_request.title }}
PR_URL: ${{ github.event.pull_request.html_url }}
PR_LABELS: ${{ join(github.event.pull_request.labels.*.name, ', ') }}
PR_AUTHOR: ${{ github.event.pull_request.user.login }}
run: |
if [ "${EVENT_NAME}" = "issues" ]; then
EMOJI="📝"
PREFIX="New Issue"
TITLE="${ISSUE_TITLE}"
URL="${ISSUE_URL}"
LABELS="${ISSUE_LABELS}"
AUTHOR="${ISSUE_AUTHOR}"
else
EMOJI="🔀"
PREFIX="New Pull Request"
TITLE="${PR_TITLE}"
URL="${PR_URL}"
LABELS="${PR_LABELS}"
AUTHOR="${PR_AUTHOR}"
fi
AUTHOR_URL="https://github.com/${AUTHOR}"
PLAIN="${EMOJI} ${PREFIX} by ${AUTHOR}: ${TITLE} - ${URL}"
HTML="<h3>${EMOJI} ${PREFIX}</h3>"
HTML="${HTML}<b><a href='${URL}'>${TITLE}</a></b><br/>"
HTML="${HTML}👤 <a href='${AUTHOR_URL}'>${AUTHOR}</a>"
if [ -n "${LABELS}" ]; then
HTML="${HTML}<br/>🏷️ ${LABELS}"
fi
TXN_ID=$(date +%s%N)
curl -s -o /dev/null -w "%{http_code}" -X PUT \
"${HOMESERVER}/_matrix/client/v3/rooms/${ROOM_ID}/send/m.room.message/${TXN_ID}" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg body "$PLAIN" --arg html "$HTML" \
'{"msgtype":"m.notice","body":$body,"format":"org.matrix.custom.html","formatted_body":$html}')"

View file

@ -17,11 +17,14 @@ jobs:
build_web:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v5
- run: cat .github/workflows/versions.env >> $GITHUB_ENV
- uses: subosito/flutter-action@v2
with:
flutter-version-file: .tool_versions.yaml
flutter-version: ${{ env.FLUTTER_VERSION }}
cache: true
- name: Install dependencies
run: sudo apt-get update && sudo apt-get install nodejs -y
- uses: moonrepo/setup-rust@v1
- run: rustup component add rust-src --toolchain nightly-x86_64-unknown-linux-gnu
- run: flutter pub get
@ -29,11 +32,11 @@ jobs:
run: ./scripts/prepare-web.sh
- run: rm ./assets/vodozemac/.gitignore
- name: Build Release Web
run: flutter build web --dart-define=FLUTTER_WEB_CANVASKIT_URL=canvaskit/ --release --source-maps
run: flutter build web --dart-define=FLUTTER_WEB_CANVASKIT_URL=canvaskit/ --release --source-maps --base-href "/web/"
- name: Create archive
run: tar -czf fluffychat-web.tar.gz build/web/
- name: Upload Web Build
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v4
with:
name: Web Build
path: fluffychat-web.tar.gz
@ -46,25 +49,17 @@ jobs:
asset_path: fluffychat-web.tar.gz
asset_name: fluffychat-web.tar.gz
asset_content_type: application/gzip
- name: Clone fluffychat website
run: |
git clone https://github.com/krille-chan/fluffychat-website.git
cp CHANGELOG.md fluffychat-website/
cp PRIVACY.md fluffychat-website/
- name: Build website
working-directory: fluffychat-website
- name: Install and build tailwindcss
working-directory: docs
run: |
npm install tailwindcss @tailwindcss/cli
npx tailwindcss -i ./src/styles.css -o ./src/assets/tailwind.css --minify
npx @11ty/eleventy
mv public ../
- name: Copy FluffyChat web into it
npx tailwindcss -o ./tailwind.css
- name: Build Website
run: |
mkdir public/web
mkdir public/nightly
cp -r build/web/* public/web/
cp -r build/web/* public/nightly/
echo "fluffychat.im" >> public/CNAME
mv docs public
mv repo public || true
mv build/web/ public/web
cp public/web -r public/nightly
- name: Deploy to GitHub Pages
if: startsWith(github.ref, 'refs/tags/v')
uses: peaceiris/actions-gh-pages@v4
@ -77,16 +72,20 @@ jobs:
build_apk:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v5
- run: cat .github/workflows/versions.env >> $GITHUB_ENV
- uses: actions/setup-java@v5
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: 'zulu'
- uses: subosito/flutter-action@v2
with:
flutter-version-file: .tool_versions.yaml
flutter-version: ${{ env.FLUTTER_VERSION }}
cache: true
- name: Add Firebase Messaging
run: |
echo '${{secrets.GOOGLE_SERVICES_JSON}}' | base64 -d > android/app/google-services.json
./scripts/add-firebase-messaging.sh
- uses: ./.github/actions/free_up_space
- uses: moonrepo/setup-rust@v1
- run: flutter pub get
- name: Prepare Android Release Build
@ -95,7 +94,7 @@ jobs:
FDROID_KEY_PASS: ${{ secrets.FDROID_KEY_PASS }}
PLAYSTORE_DEPLOY_KEY: ${{ secrets.PLAYSTORE_DEPLOY_KEY }}
run: ./scripts/prepare-android-release.sh
- run: flutter build apk --release --target-platform android-arm,android-arm64
- run: flutter build apk --release
- name: Upload to release
uses: actions/upload-release-asset@v1
env:
@ -112,10 +111,10 @@ jobs:
arch: [ x64, arm64 ]
runs-on: ${{ matrix.arch == 'arm64' && 'ubuntu-24.04-arm' || 'ubuntu-latest'}}
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v5
- run: cat .github/workflows/versions.env >> $GITHUB_ENV
- name: Install dependencies
run: sudo apt-get update && sudo apt-get install curl clang cmake ninja-build pkg-config libgtk-3-dev libblkid-dev liblzma-dev libjsoncpp-dev cmake-data libsecret-1-dev libsecret-1-0 librhash0 libwebkit2gtk-4.1-dev -y
- run: echo "FLUTTER_VERSION=$(yq '.environment.flutter' < .tool_versions.yaml)" >> $GITHUB_ENV
run: sudo apt-get update && sudo apt-get install curl clang cmake ninja-build pkg-config libgtk-3-dev libblkid-dev liblzma-dev libjsoncpp-dev cmake-data libsecret-1-dev libsecret-1-0 librhash0 libssl-dev libwebkit2gtk-4.1-dev -y
- name: Install Flutter
run: |
git clone --branch ${{ env.FLUTTER_VERSION }} https://github.com/flutter/flutter.git
@ -138,16 +137,20 @@ jobs:
deploy_playstore:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v5
- run: cat .github/workflows/versions.env >> $GITHUB_ENV
- uses: actions/setup-java@v5
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: 'zulu'
- uses: subosito/flutter-action@v2
with:
flutter-version-file: .tool_versions.yaml
flutter-version: ${{ env.FLUTTER_VERSION }}
cache: true
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.3'
- uses: ./.github/actions/free_up_space
- uses: moonrepo/setup-rust@v1
- name: Install Fastlane
working-directory: android
@ -164,7 +167,7 @@ jobs:
PLAYSTORE_DEPLOY_KEY: ${{ secrets.PLAYSTORE_DEPLOY_KEY }}
run: ./scripts/prepare-android-release.sh
- name: Build Android Release
run: flutter build appbundle --target-platform android-arm,android-arm64
run: flutter build appbundle --target-platform android-arm,android-arm64,android-x64
- name: Get Tag Name
id: tag_name
run: echo "::set-output name=tag::$(echo ${GITHUB_REF#refs/tags/})"
@ -190,20 +193,20 @@ jobs:
packages: write
steps:
- name: Check out Git repository
uses: actions/checkout@v6
uses: actions/checkout@v5
- name: Log in to the Container registry
uses: docker/login-action@v4
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v6
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Build and push Docker image
uses: docker/build-push-action@v7
uses: docker/build-push-action@v6
with:
context: .
push: true

View file

@ -1,21 +0,0 @@
name: 'Close stale issues and PRs'
on:
schedule:
- cron: '30 1 * * *'
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v10
with:
stale-issue-message: 'This issue is stale because it has been open 365 days with no activity. Remove stale label or comment or this will be closed in 30 days.'
stale-pr-message: 'This PR is stale because it has been open 365 days with no activity. Remove stale label or comment or this will be closed in 30 days.'
close-issue-message: 'This issue was closed because it has been stalled for 30 days with no activity.'
close-pr-message: 'This PR was closed because it has been stalled for 30 days with no activity.'
days-before-issue-stale: 365
days-before-pr-stale: 365
days-before-issue-close: 30
days-before-pr-close: 30
exempt-all-assignees: true
operations-per-run: 1000

2
.github/workflows/versions.env vendored Normal file
View file

@ -0,0 +1,2 @@
FLUTTER_VERSION=3.35.3
JAVA_VERSION=17

4
.gitignore vendored
View file

@ -13,8 +13,7 @@
prime
# libolm package
web/Imaging.js
web/Imaging.wasm
/assets/js/package
# IntelliJ related
*.iml
@ -71,4 +70,3 @@ android/app/google-services.json
web/pkg/package.json
web/pkg/vodozemac_bindings_dart_bg.wasm
web/pkg/vodozemac_bindings_dart.js
web/native_executor.js*

View file

@ -1,2 +0,0 @@
environment:
flutter: 3.41.4

View file

@ -1,451 +1,3 @@
## v2.5.0
FluffyChat 2.5.0 introduces a new homeserver picker for onboarding, better image compression performance and several smaller new features, design adjustments and bug fixes.
- feat: Add mute notification action (Christian Kußowski)
- feat: Add presetHomeserver config to enforce a homeserver for web (Christian Kußowski)
- feat: Display particle animation on login page (Christian Kußowski)
- feat: Display read receipts for every event (Christian Kußowski)
- feat: Enable audio recording on web (Christian Kußowski)
- feat: Implement low priority for rooms (Christian Kußowski)
- feat: Implement matrix native oidc (Christian Kußowski)
- feat: Implement new sign in flow (Christian Kußowski)
- feat: OIDC Login on same page (Christian Kußowski)
- feat: Reenable native imaging for all platforms (Christian Kußowski)
- feat: Remember last successful logged in homeserver (Christian Kußowski)
- Add lld to install custom dependency for Linux in README (Stephen)
- build: Add llvm-18 to packages for snap (krille-chan)
- build: Add maestro based integration tests (Christian Kußowski)
- chore(translations): Added translation using Weblate (Albanian) (Besnik Bleta)
- chore(translations): Added translation using Weblate (Kabyle) (Amadɣas)
- chore(translations): Translated using Weblate (Basque) (xabirequejo)
- chore(translations): Translated using Weblate (Catalan) (fadelkon)
- chore(translations): Translated using Weblate (Chinese (Simplified Han script)) (大王叫我来巡山)
- chore(translations): Translated using Weblate (Croatian) (Milo Ivir)
- chore(translations): Translated using Weblate (Czech) (Matyáš Caras)
- chore(translations): Translated using Weblate (Danish) (Øjvind Fritjof Arnfred)
- chore(translations): Translated using Weblate (Dutch) (Jelv)
- chore(translations): Translated using Weblate (English) (Christian)
- chore(translations): Translated using Weblate (English) (SpikyBee)
- chore(translations): Translated using Weblate (Estonian) (Priit Jõerüüt)
- chore(translations): Translated using Weblate (Galician) (josé m.)
- chore(translations): Translated using Weblate (Georgian) (Dimitri Tabatadze)
- chore(translations): Translated using Weblate (Georgian) (Temuri Doghonadze)
- chore(translations): Translated using Weblate (German) (Christian)
- chore(translations): Translated using Weblate (German) (Ettore Atalan)
- chore(translations): Translated using Weblate (German) (nautilusx)
- chore(translations): Translated using Weblate (Hindi) (Vishal Singh)
- chore(translations): Translated using Weblate (Indonesian) (Arif Budiman)
- chore(translations): Translated using Weblate (Irish) (Aindriú Mac Giolla Eoin)
- chore(translations): Translated using Weblate (Japanese) (NPL)
- chore(translations): Translated using Weblate (Japanese) (Sayaka Halton)
- chore(translations): Translated using Weblate (Kabyle) (Amadɣas)
- chore(translations): Translated using Weblate (Kabyle) (ButterflyOfFire)
- chore(translations): Translated using Weblate (Kabyle) (Christian)
- chore(translations): Translated using Weblate (Latvian) (Edgars Andersons)
- chore(translations): Translated using Weblate (Norwegian Bokmål) (Frank Paul Silye)
- chore(translations): Translated using Weblate (Norwegian Bokmål) (sunniva)
- chore(translations): Translated using Weblate (Persian) (saok91)
- chore(translations): Translated using Weblate (Polish) (gredzikk)
- chore(translations): Translated using Weblate (Portuguese (Brazil)) (Logaritmica)
- chore(translations): Translated using Weblate (Russian) (-)
- chore(translations): Translated using Weblate (Russian) (Artem Pereverzev)
- chore(translations): Translated using Weblate (Russian) (mikinol)
- chore(translations): Translated using Weblate (Spanish) (Kimby)
- chore(translations): Translated using Weblate (Spanish) (SpikyBee)
- chore(translations): Translated using Weblate (Swedish) (Malva Jakobsson)
- chore(translations): Translated using Weblate (Swedish) (spinningpaprika)
- chore(translations): Translated using Weblate (Tamil) (தமிழ்நேரம்)
- chore(translations): Translated using Weblate (Ukrainian) (Andriy Kushnir)
- chore(translations): Translated using Weblate (Ukrainian) (Ihor Hordiichuk)
- chore(translations): Translated using Weblate (Uzbek) (BeMeritus)
- chore: Add config search textfield (Christian Kußowski)
- chore: Add matrix notify workflow (Christian Kußowski)
- chore: Add recommended homeservers (Christian Kußowski)
- chore: Add reset button for config viewer (Christian Kußowski)
- chore: Add support button everywhere (Christian Kußowski)
- chore: Added deeplinks to test protocol (Christian Kußowski)
- chore: Adjust avatar size and chat list item design (krille-chan)
- chore: Adjust chat input row design (Christian Kußowski)
- chore: Adjust design (Christian Kußowski)
- chore: Adjust design of navrail (Christian Kußowski)
- chore: Adjust design of space avatars and more (Christian Kußowski)
- chore: Adjust design of user viewer and popup buttons (Christian Kußowski)
- chore: Adjust join space child UX (Christian Kußowski)
- chore: Adjust paddings (krille-chan)
- chore: Adjust power level UX (Christian Kußowski)
- chore: Adjust search field design (Christian Kußowski)
- chore: Adjust status header design (Christian Kußowski)
- chore: Adjust styles and animations (Christian Kußowski)
- chore: Adjust support button design (Christian Kußowski)
- chore: Always show filter for messages (Christian Kußowski)
- chore: Avoid unnecessary lambdas (Christian Kußowski)
- chore: Better context menu for space children (Christian Kußowski)
- chore: bump ios version (ShootingStarDragons)
- chore: Check conventional commits in CI (krille-chan)
- chore: Check if pubspec.lock is up to date in CI (Christian Kußowski)
- chore: Check of unused localizations (Christian Kußowski)
- chore: Clean up pages build (Christian Kußowski)
- chore: Display spaces filter chip when spaces present even without children (Christian Kußowski)
- chore: Execute dart code linter in CI (Christian Kußowski)
- chore: Exempt assignees from stale (Christian Kußowski)
- chore: Fix oidc login on web (Christian Kußowski)
- chore: Give issues and PRs more time for stale (Christian Kußowski)
- chore: Hide homepage button if not preset (Christian Kußowski)
- chore: Hide status list by default (Christian Kußowski)
- chore: Implement pick SSO provider from dialog and add tchncs.de (Christian Kußowski)
- chore: Introduce tool versions file (Christian Kußowski)
- chore: Login with localhost (Christian Kußowski)
- chore: Make banner light red (Christian Kußowski)
- chore: Make key fingerprints in chat encryption page selectable (Christian Kußowski)
- chore: make sendTimelineEventTimeout configurable (Christian Kußowski)
- chore: Make unread bubble full round (Christian Kußowski)
- chore: Move file cache to subdirectory (Christian Kußowski)
- chore: Move show image viewer one step up (Christian Kußowski)
- chore: Move website back to fluffychat.im (Christian Kußowski)
- chore: Only show confirm dialog once (Christian Kußowski)
- chore: Put oidc behind a feature flag until fixed (Christian Kußowski)
- chore: Remove converser from recommended homeservers as it doesn't have open registration (Christian Kußowski)
- chore: Remove frei.chat from homeserver list (Christian Kußowski)
- chore: Remove web notification custom sound (Christian Kußowski)
- chore: Replace duplicate check for stale bot (Christian Kußowski)
- chore: Retry sign in tap in tests (Christian Kußowski)
- chore: Run matrix notification in pull request target (Christian Kußowski)
- chore: Sanitize hash param for oidc (Christian Kußowski)
- chore: Set erase flag true on account deactivation (krille-chan)
- chore: Set operations per run to 1000 (krille-chan)
- chore: Skip matrix notify for events from myself (Christian Kußowski)
- chore: Update locale config (Christian Kußowski)
- chore: Update matrix ID localization (Christian Kußowski)
- chore: Update recommended homeservers (Christian Kußowski)
- chore: Update redirect android scheme (Christian Kußowski)
- chore: Use fixed version of fcm shared isolate (Christian Kußowski)
- fix: Add app id to TileLayer user agent (Vespe-r)
- fix: Add missing @@locale (Krille-chan)
- fix: Audioplayer on web buggy (Christian Kußowski)
- fix: build failed on archlinux (ShootingStarDragons)
- fix: Do not cancel notification on reply (Christian Kußowski)
- fix: Do not display formatted body if body is just filename (Christian Kußowski)
- fix: Do not route to backup on soft logout (Christian Kußowski)
- fix: Edit space child button opens space details page and not space child details page (Christian Kußowski)
- fix: Fix formatting of messages with newlines (Philip Fritzsche)
- fix: get correct aspect ratio from VideoPlayerController (Matias)
- fix: Join room by alias even if not found (Christian Kußowski)
- fix: Open deep links (Christian Kußowski)
- fix: Receipt row not auto updating (Christian Kußowski)
- fix: Receipts disappear after reaction (Christian Kußowski)
- fix: Reply voice message displays a broken html body (Christian Kußowski)
- fix: Send reply to voice messages (Christian Kußowski)
- fix: Set mimetype for video player on web (Christian Kußowski)
- fix: Use correct own person for android notification replies (Christian Kußowski)
- fix: Wrong placeholder in kab (Christian Kußowski)
- refactor: Add Flutter lints (Christian Kußowski)
- refactor: Add more linter rules (Christian Kußowski)
- refactor: Add more stricter lints (Christian Kußowski)
- refactor: Avoid redundant async (Christian Kußowski)
- refactor: Avoid unnecessary bool comparison (Christian Kußowski)
- refactor: Better UX for create space children (Christian Kußowski)
- refactor: Disable custom image resizer for macOS and windows (Christian Kußowski)
- refactor: Do show message bubble even for big emotes (Christian Kußowski)
- refactor: Enable avoid-returning-widgets lint (Christian Kußowski)
- refactor: Enable more strict lints (Christian Kußowski)
- refactor: Enable rule avoid dynamic (Christian Kußowski)
- refactor: Make file events more fail safe for failed to send (Christian Kußowski)
- refactor: Remove animation dependency (Christian Kußowski)
- refactor: Remove unused localizations (Christian Kußowski)
- refactor: Remove unused translations (Christian Kußowski)
- refactor: Use getCryptoIdentityState to check backup state (krille-chan)
- refactor: Use more robust and performant way to detect single emoji messages (Christian Kußowski)
- refactor: Use native uri data from bytes instead of html (Christian Kußowski)
## v2.4.0
FluffyChat 2.4.0 adds a new improved GUI for managing stickers with tutorials how to
easily add your own sticker packs.
It also improves the search and image gallery in chats, especially encrypted chats.
Besides that this update comes with a lot of fixes and improvements under the hood.
- feat: Create new sticker packs (krille-chan)
- feat: Edit displayname and attribution for sticker packs (krille-chan)
- feat: Improved search (Christian Kußowski)
- feat: Set usage of custom emojis and stickers (krille-chan)
- feat: Upload multiple stickers at once (krille-chan)
- build: (deps): bump actions/checkout from 5 to 6 (dependabot[bot])
- build: (deps): bump animations from 2.1.0 to 2.1.1 (dependabot[bot])
- build: (deps): bump device_info_plus from 12.2.0 to 12.3.0 (dependabot[bot])
- build: (deps): bump emoji_picker_flutter from 4.3.0 to 4.4.0 (dependabot[bot])
- build: (deps): bump file_picker from 10.3.6 to 10.3.7 (dependabot[bot])
- build: (deps): bump file_picker from 10.3.7 to 10.3.8 (dependabot[bot])
- build: (deps): bump file_selector from 1.0.4 to 1.1.0 (dependabot[bot])
- build: (deps): bump flutter_foreground_task from 9.1.0 to 9.2.0 (dependabot[bot])
- build: (deps): bump flutter_webrtc from 1.2.0 to 1.2.1 (dependabot[bot])
- build: (deps): bump go_router from 17.0.0 to 17.0.1 (dependabot[bot])
- build: (deps): bump image from 4.5.4 to 4.6.0 (dependabot[bot])
- build: (deps): bump image from 4.6.0 to 4.7.1 (dependabot[bot])
- build: (deps): bump image from 4.7.1 to 4.7.2 (dependabot[bot])
- build: (deps): bump matrix from 4.0.0 to 4.0.1 (dependabot[bot])
- build: (deps): bump shared_preferences from 2.5.3 to 2.5.4 (dependabot[bot])
- build: (deps): bump translations_cleaner from 0.0.5 to 0.1.0 (dependabot[bot])
- build: (deps): bump universal_html from 2.2.4 to 2.3.0 (dependabot[bot])
- build: Reenable shrink resources and minify in gradle (Christian Kußowski)
- build: Upgrade to flutter 3.38.4 (Christian Kußowski)
- build: Use matrix sdk vom pub.dev again (Christian Kußowski)
- chore(translations): Translated using Weblate (Basque) (xabirequejo)
- chore(translations): Translated using Weblate (Belarusian) (Alex Katon)
- chore(translations): Translated using Weblate (Bengali) (Kom nake)
- chore(translations): Translated using Weblate (Chinese (Simplified Han script)) (Creeper)
- chore(translations): Translated using Weblate (Chinese (Simplified Han script)) (大王叫我来巡山)
- chore(translations): Translated using Weblate (Croatian) (Milo Ivir)
- chore(translations): Translated using Weblate (Czech) (arxari)
- chore(translations): Translated using Weblate (Dutch) (Jelv)
- chore(translations): Translated using Weblate (Estonian) (Priit Jõerüüt)
- chore(translations): Translated using Weblate (Finnish) (Ricky Tigg)
- chore(translations): Translated using Weblate (French) (hugues de keyzer)
- chore(translations): Translated using Weblate (Galician) (josé m.)
- chore(translations): Translated using Weblate (Georgian) (Nicholas Winterhalter)
- chore(translations): Translated using Weblate (Georgian) (Temuri Doghonadze)
- chore(translations): Translated using Weblate (German) (Bella)
- chore(translations): Translated using Weblate (German) (nautilusx)
- chore(translations): Translated using Weblate (Greek) (Rain4Cats)
- chore(translations): Translated using Weblate (Irish) (Aindriú Mac Giolla Eoin)
- chore(translations): Translated using Weblate (Italian) (Alessio Olivieri)
- chore(translations): Translated using Weblate (Italian) (Claudio Maradonna)
- chore(translations): Translated using Weblate (Latvian) (Edgars Andersons)
- chore(translations): Translated using Weblate (Norwegian Bokmål) (Frank Paul Silye)
- chore(translations): Translated using Weblate (Portuguese (Brazil)) (LucasMZ)
- chore(translations): Translated using Weblate (Russian) (BeMeritus)
- chore(translations): Translated using Weblate (Russian) (Christian)
- chore(translations): Translated using Weblate (Russian) (Дмитрий Михирев)
- chore(translations): Translated using Weblate (Serbian) (Luka)
- chore(translations): Translated using Weblate (Spanish) (Kimby)
- chore(translations): Translated using Weblate (Ukrainian) (Andriy Kushnir)
- chore(translations): Translated using Weblate (Ukrainian) (Ihor Hordiichuk)
- chore(translations): Translated using Weblate (Uzbek) (BeMeritus)
- chore(translations): Translated using Weblate (Uzbek) (Maftuna Vohidjonovna)
- chore: Allow all chars for emoji search (Christian Kußowski)
- chore: Allow export of readonly sticker packs (Christian Kußowski)
- chore: delete unrelated line (ShootingStarDragons)
- chore: Display attribution for sticker packs (krille-chan)
- chore: Escape title in check duplicates job (Christian Kußowski)
- chore: ignore for now deprecated regex (Christian Kußowski)
- chore: Improve room custom emote UX (krille-chan)
- chore: Improve sticker editor UX (krille-chan)
- chore: Improve text selection color for messages (Christian Kußowski)
- chore: Improve via calculation (Christian Kußowski)
- chore: Increase padding for code blocks (Christian Kußowski)
- chore: Link how do I get stickers FAQ entry (Christian Kußowski)
- chore: Localize emoji picker (Christian Kußowski)
- chore: Make attribution url field clickable (Christian Kußowski)
- chore: Make cross signing self sign mandatory for bootstrap (Christian Kußowski)
- chore: make locale for emoji suggestions configureable (krille-chan)
- chore: Make sticker previews in editor clickable (krille-chan)
- chore: Make stickers smaller than normal image messages (Christian Kußowski)
- chore: Override sqlcipher license (Christian Kußowski)
- chore: Remove horizontal scrolling for code blocks (Christian Kußowski)
- chore: remove the userId param (ShootingStarDragons)
- chore: Replace copy action with pin event action in UI (Christian Kußowski)
- chore: Request keys for last room messages after bootstrap (krille-chan)
- chore: Simplify adaptive bottom sheet code (Christian Kußowski)
- chore: Update privacy policy links (Christian Kußowski)
- chore: Update start poll design (Christian Kußowski)
- chore: Update user device keys before creating bootstrap (Christian Kußowski)
- chore: Use license_checker from pub again (Christian Kußowski)
- chore: Wait for secrets after bootstrap verification (Christian Kußowski)
- Fix regression after new linter rules (Andriy Kushnir)
- fix: Better wait for secrets after verification bootstrap (Christian Kußowski)
- fix: Broken ruzzian plurals (Christian Kußowski)
- fix: Do not auto load history in rooms with collapsed state only (Christian Kußowski)
- fix: Do not display empty file description body (Christian Kußowski)
- fix: Do not render html in unformatted messages (Christian Kußowski)
- fix: Do not request hero users for rooms with name (Christian Kußowski)
- fix: enable users without passwords to delete their accounts by using uia request in account deletion (ggurdin)
- fix: Hide no fcm warning after dismissed (Christian Kußowski)
- fix: jump cannot work properly when there are multi users (ShootingStarDragons)
- fix: Make keyboard moving bottom sheet up (Christian Kußowski)
- fix: No description for video and audio messages displayed (Christian Kußowski)
- fix: Render not permitted html tags as text instead of hiding (Christian Kußowski)
- fix: Scrolling in fragmented timeline (Christian Kußowski)
- fix: spoiler formatting in reply (denalena)
- fix: State problem when not changing emote name (krille-chan)
- fix: Unlock app with leading 0 in pin is not possible (Christian Kußowski)
- fix: when user has multi counts,notification not works well (ShootingStarDragons)
- refactor: Adjust state event design (Christian Kußowski)
- refactor: Always open Chat Backup as page right after login (Christian Kußowski)
- refactor: Display all sticker packs in same editor with filterchips (krille-chan)
- refactor: File selector just use default FileType and remove not working zip selector (Christian Kußowski)
- refactor: Improved design and UX for sticker editor (krille-chan)
- refactor: Remove native imaging and enable web worker (Christian Kußowski)
- refactor: Remove unused feature tor browser detector (Christian Kußowski)
- refactor: Remove unused html onfocus streams (Christian Kußowski)
- refactor: Remove unused msix (Christian Kußowski)
- refactor: Remove workaround for download files (Christian Kußowski)
- refactor: Update flutter lints (Christian Kußowski)
- refactor: Update to Dart 3.10 with . shorthands (Christian Kußowski)
- refactor: Use localized emojis for suggestion input (krille-chan)
- refactor: Use own highlight rendering with working scrollbar and text selection (Christian Kußowski)
- chore: Update links to matrix spaces to avoid confusion (Andriy Kushnir)
## v2.3.0
FluffyChat v2.3.0 fixes a possible database corruption bug on Android, also fixes a
major performance leak and introduces polls and threads.
- feat: Implement polls (Christian Kußowski)
- feat: Implement threads (krille-chan)
- fix: Database corruption because notification tab isolate starts too late (Christian Kußowski)
- fix: Import sticker packs (Christian Kußowski)
- refactor: Improved UIA support for OIDC and SSO (Christian Kußowski)
- refactor: Invite users when upgrading private room (Christian Kußowski)
- build: (deps): bump cross_file from 0.3.4+2 to 0.3.5 (dependabot[bot])
- build: (deps): bump file_picker from 10.3.3 to 10.3.6 (dependabot[bot])
- build: (deps): bump go_router from 16.3.0 to 17.0.0 (dependabot[bot])
- build: (deps): bump http from 1.5.0 to 1.6.0 (dependabot[bot])
- build: (deps): bump image_picker from 1.2.0 to 1.2.1 (dependabot[bot])
- build: (deps): bump qr_code_scanner_plus from 2.0.13 to 2.0.14 (dependabot[bot])
- build: (deps): bump video_player from 2.10.0 to 2.10.1 (dependabot[bot])
- build: Switch back to stable web auth package (krille-chan)
- build: Use matrix sdk 4.0.0 (Christian Kußowski)
- build: Use secure storage from pub.dev again (krille-chan)
- chore: Remove Notification actions when using UnifiedPush (Christian Kußowski)
- chore(translations): Added translation using Weblate (Uzbek) (bahrom04)
- chore(translations): Translated using Weblate (Basque) (xabirequejo)
- chore(translations): Translated using Weblate (Belarusian) (Alex Katon)
- chore(translations): Translated using Weblate (Chinese (Simplified Han script)) (大王叫我来巡山)
- chore(translations): Translated using Weblate (Dutch) (Jelv)
- chore(translations): Translated using Weblate (Estonian) (Priit Jõerüüt)
- chore(translations): Translated using Weblate (Finnish) (Priit Jõerüüt)
- chore(translations): Translated using Weblate (Finnish) (Ricky Tigg)
- chore(translations): Translated using Weblate (French) (luneth)
- chore(translations): Translated using Weblate (Galician) (josé m.)
- chore(translations): Translated using Weblate (Irish) (Aindriú Mac Giolla Eoin)
- chore(translations): Translated using Weblate (Latvian) (Edgars Andersons)
- chore(translations): Translated using Weblate (Norwegian Bokmål) (Frank Paul Silye)
- chore(translations): Translated using Weblate (Uzbek) (bahrom04)
- chore(translations): Translated using Weblate (Uzbek) (BeMeritus)
## v2.2.0
FluffyChat 2.2.0 introduces a new UX for spaces and adds support for restricted
join rules.
The app also now has a new design for recording voice messages including a new
pause button.
You also now see the progress when downloading files.
On web the performance for image compressing has been drastically improved. Also
the config.json file loading has finally been fixed. Please be aware that the format
has changed as the available configs are now generated automatically.
Did you know that you can set a lot of additional configs in the new config viewer
inside the app? This now supports much more options but please use with care!
On Android FluffyChat now supports notification actions (reply and mark as read) and
also now supports Android Auto integration. Please do not cause an accident when using
the app while driving!
On iOS the notifications are now localized. Stay tuned for more improvements on iOS
notifications in the next releases!
Besides that this release brings a ton of bug fixes and performance improvements and
of course updated translations. Big thanks to all the volunteers who have helped on weblate!
- feat: Add donation buttons except for PlayStore&AppStore version (Christian Kußowski)
- feat: Add iOS Notification Service Extension for localizable push notifications (Christian Kußowski)
- feat: Add notification actions (krille-chan)
- feat: Add support for restricted join rule (Christian Kußowski)
- feat: Display progress for downloading content (Christian Kußowski)
- feat: Display progress on redact events and clear archive dialogs (Christian Kußowski)
- feat: Enable native imaging for web (Christian Kußowski)
- feat: Forward notifications to Android Auto (Christian Kußowski)
- feat: Nicer record voice message UI with pause function (Christian Kußowski)
- feat: Notification actions on android (krille-chan)
- design: Improved spaces UX (Christian Kußowski)
- fix: Correctly pass through obscure text (Christian Kußowski)
- fix: Create a subdirectory in the tmp directory (Inex Code)
- fix: Cupertino text dialogs (Christian Kußowski)
- fix: Null pointer crash in chat list item (Christian Kußowski)
- chore(translations): Translated using Weblate (Arabic) (jamazi)
- chore(translations): Translated using Weblate (Basque) (xabirequejo)
- chore(translations): Translated using Weblate (Belarusian) (Alex Katon)
- chore(translations): Translated using Weblate (Chinese (Simplified Han script)) (大王叫我来巡山)
- chore(translations): Translated using Weblate (Croatian) (Milo Ivir)
- chore(translations): Translated using Weblate (Czech) (Flibble)
- chore(translations): Translated using Weblate (Dutch) (Jelv)
- chore(translations): Translated using Weblate (Esperanto) (Anonymous)
- chore(translations): Translated using Weblate (Estonian) (Priit Jõerüüt)
- chore(translations): Translated using Weblate (Finnish) (Aminda Suomalainen)
- chore(translations): Translated using Weblate (Galician) (josé m)
- chore(translations): Translated using Weblate (German) (Alex Katon)
- chore(translations): Translated using Weblate (German) (cheese1)
- chore(translations): Translated using Weblate (German) (Christian)
- chore(translations): Translated using Weblate (German) (Jana)
- chore(translations): Translated using Weblate (Greek) (Λευτέρης Τ)
- chore(translations): Translated using Weblate (Hebrew) (Anonymous)
- chore(translations): Translated using Weblate (Hungarian) (Balázs Meskó)
- chore(translations): Translated using Weblate (Indonesian) (Linerly)
- chore(translations): Translated using Weblate (Irish) (Aindriú Mac Giolla Eoin)
- chore(translations): Translated using Weblate (Japanese) (Allan Nordhøy)
- chore(translations): Translated using Weblate (Korean) (loyedison92)
- chore(translations): Translated using Weblate (Latvian) (Edgars Andersons)
- chore(translations): Translated using Weblate (Latvian) (𝕠𝕠𝕠𝕝 (𝕘𝕚𝕥𝕙𝕦𝕓.𝕔𝕠𝕞/𝕠𝕠𝕠𝕝))
- chore(translations): Translated using Weblate (Lithuanian) (Anonymous)
- chore(translations): Translated using Weblate (Norwegian Bokmål) (Frank Paul Silye)
- chore(translations): Translated using Weblate (Norwegian Bokmål) (sunniva)
- chore(translations): Translated using Weblate (Polish) (Paweł Gronowski)
- chore(translations): Translated using Weblate (Portuguese (Brazil)) (LucasMZ)
- chore(translations): Translated using Weblate (Portuguese (Portugal)) (Anonymous)
- chore(translations): Translated using Weblate (Romanian) (Anonymous)
- chore(translations): Translated using Weblate (Russian) (Christian)
- chore(translations): Translated using Weblate (Russian) (Дмитрий Михирев)
- chore(translations): Translated using Weblate (Russian) (Жора Змейкин)
- chore(translations): Translated using Weblate (Serbian) (Anonymous)
- chore(translations): Translated using Weblate (Slovak) (Anonymous)
- chore(translations): Translated using Weblate (Spanish) (Kimby)
- chore(translations): Translated using Weblate (Spanish) (LucasMZ)
- chore(translations): Translated using Weblate (Turkish) (Christian)
- chore(translations): Translated using Weblate (Turkish) (Ufuk Karal)
- chore(translations): Translated using Weblate (Vietnamese) (desperadohp)
- chore: add a link to the platforms' different behaviors for the 24h format (kaanelloed)
- chore: Add ActionsPadding in column mode (Christian Kußowski)
- chore: Add close icon to snackbar in column mode (Christian Kußowski)
- chore: Adjust chat details button design (Christian Kußowski)
- chore: Adjust encryption page design (Christian Kußowski)
- chore: Adjust input bar button design (Christian Kußowski)
- chore: Adjust material dialog button design (krille-chan)
- chore: Adjust padding for status msg list (Christian Kußowski)
- chore: Adjust status header design (krille-chan)
- chore: Better display rooms without known messages (Christian Kußowski)
- chore: Better routing to space id (Christian Kußowski)
- chore: Correctly remove knockRestricted from possible join rules (Christian Kußowski)
- chore: Fix load config.json (Christian Kußowski)
- chore: Go back to pub.dev matrix dep (Christian Kußowski)
- chore: Hide restricted and knock restricted for unsupported room versions (Christian Kußowski)
- chore: Hide topic if empty and cannot be changed (Christian Kußowski)
- chore: Improve chat details icon color design (Christian Kußowski)
- chore: Improve ignore list UX (Christian Kußowski)
- chore: Leave invites and DM rooms when blocking a user (Christian Kußowski)
- chore: Make privacy url not configurable (Christian Kußowski)
- chore: Make progress indicators rounder (Christian Kußowski)
- chore: Mention rebases (Christian Kußowski)
- chore: Move emote settings button to chat popup menu (Christian Kußowski)
- chore: Move encryption button to input row (Christian Kußowski)
- chore: Revert "refactor: Make ChatListItem cache lasteventbody for better performance" (Christian Kußowski)
- chore: Translate iOS notifications into german (Christian Kußowski)
- chore: Try out refactored user device keys update method (Christian Kußowski)
- chore: Update matrix dart sdk (Christian Kußowski)
- chore: use time format based on system settings (kaanelloed)
- ci: Build only for arm64 (Christian Kußowski)
- refactor: Make ChatListItem cache lasteventbody for better performance (Christian Kußowski)
- refactor: Remove unused directories (Christian Kußowski)
- refactor: Rename models for matrix spec 1.16 (Christian Kußowski)
- refactor: Replace flutter typeahead with autocomplete to fix (Christian Kußowski)
- refactor: Use AppSettings enum based configuration everywhere and fix load from json on web (Christian Kußowski)
- build: Flutter upgrade 3.35.5 (Christian Kußowski)
- build: Matrix version 3.0.0 (Christian Kußowski)
- build: Remove dependency for telephony (Christian Kußowski)
- build: Remove openssl dependency (Christian Kußowski)
- build: Use correct fcm_shared_isolate version (Christian Kußowski)
- build: Use correct version of vodozemac for web build (Christian Kußowski)
## v2.1.1
Bugfix release to trigger flatpak arm64 release again.

View file

@ -1,172 +0,0 @@
# Contributing to FluffyChat
Contributions are always welcome. Yet we might lack manpower to review all of them in time.
To improve the process please make sure that you read the following guidelines carefully:
## Contributing Guidelines
1. Always create a Pull Request for any changes.
2. Whenever possible please make sure that your Pull Request only contains **one** commit. Cases where multiple commits make sense are very rare.
3. Do not add merge commits. Use rebases.
4. Every Pull Request should change only one thing. For bigger changes it is often better to split them up in multiple Pull Requests.
5. [Sign your commits](https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits).
6. Format the commit message as [Conventional Commits](https://www.conventionalcommits.org).
7. Format (`flutter format lib`) and sort impots (`dart run import_sorter:main --no-comments`) in all code files.
8. For bigger or complex changes (more than a couple of code lines) write an issue or refer to an existing issue and ask for approval from the maintainers (@krille-chan) **before** starting to implement it. This way you reduce the risk that your Pull Request get's declined.
9. Prefer simple and easy to maintain solutions over complexity and fancy ones.
# Code Style
FluffyChat tries to be as minimal as possible even in the code style. We try to keep the code clean, simple and easy to read. The source code of the app is under `/lib` with the main entry point `/lib/main.dart`.
<!-- editorconfig-checker-disable -->
<!-- prettier-ignore-start -->
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents**
- [Directory Structure:](#directory-structure)
- [Separation of Controllers and Views](#separation-of-controllers-and-views)
- [Formatting](#formatting)
- [Code Analyzis](#code-analyzis)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
<!-- prettier-ignore-end -->
<!-- editorconfig-checker-enable -->
### Directory Structure:
- /lib
- /config
- app_config.dart
- ...Constants, styles and other configurations
- /utils
- handy_function.dart
- ...Helper functions and extensions
- /pages
- /chat
- chat.dart
- chat_view.dart
- /chat_list
- chat_list.dart
- chat_list_view.dart
- ...The pages of the app separated in Controllers and Views
- /widgets
- /layouts
- ...Custom widgets created for this project
- main.dart
Most of the business model is in the Famedly Matrix Dart SDK. We try to not keep a model inside of the source code but extend it under `/utils`.
### Separation of Controllers and Views
We split views and controller logic with stateful widgets as controller where the build method just builds a stateless widget which receives the state as the only parameter. A common controller would look like this:
```dart
// /lib/controller/enter_name_controller.dart
import 'package:flutter/material.dart';
class EnterName extends StatefulWidget {
@override
EnterNameController createState() => EnterNameController();
}
class EnterNameController extends State<EnterName> {
final TextEditingController textEditingController = TextEditingController();
String name = 'Unknown';
/// Changes the name with the content in the textfield. If the textfield is
/// empty, this breaks up and displays a SnackBar.
void setNameAction() {
if (textEditingController.text.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('You have not entered your name'),
),
);
return;
}
setState(() => name = textEditingController.text);
}
@override
Widget build(BuildContext context) => EnterNameView(this);
}
```
So we have a controller for a `EnterName` view which as a `TextEditingController`, a state `name` and an action `void setNameAction()`. Actions must always be methods of a type, that we dont need to pass parameters in the corresponding view class and must have dartdoc comments.
The view class could look like this:
```dart
// /lib/views/enter_name_view.dart
import 'package:flutter/material.dart';
class EnterNameView extends StatelessWidget {
final EnterNameController controller;
const EnterNameView(this.controller, {Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Your name: ${controller.name}'),
),
body: Center(
child: TextField(
controller: controller.textEditingController,
),
),
floatingActionButton: FloatingActionButton(
onPressed: controller.setNameAction,
child: Icon(Icons.save),
),
);
}
}
```
Views should just contain code which describes the view. All other parameters or logic should be in the controller. The job of the view class is just to take the current state and build the widget tree and pipe the callbacks back. If there is any calulation necessary which is not solveable as a simple if-else or switch statement, it should be done in an external helper function unter `/lib/utils/`.
All file names must be lower_snake_case. All views must have a `View` suffix and all controller must have a `Controller` suffix. Widgets may have a controller too but they should pass the callbacks back to the view where possible. Calling one line methods directly in the view is only recommended if there is no need to pass a parameter.
To perform an action on state initialization we use the initState method:
```dart
@override
void initState() {
// TODO: implement initState
super.initState();
}
```
And the dispose method to perform an action on disposing:
```dart
@override
void dispose() {
// TODO: implement dispose
super.dispose();
}
```
To run code after the widget was created first we use the WidgetBindings in the initState:
```dart
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((_) {
// Do something when build is finished
});
super.initState();
}
```
### Formatting
We do not allow code with wrong formatting. Please run `flutter format lib` if your IDE doesn't do this automatically.
### Code Analyzis
We do not allow codes with dart errors or warnings. We use the [flutter_lints](https://pub.dev/packages/flutter_lints) package for static code analysis with additional rules under `analysis_options.yaml`.

View file

@ -7,9 +7,8 @@ FluffyChat is available on Android, iOS, Linux and as a web version. Desktop ver
* [Encryption](#encryption)
* [App Permissions](#app-permissions)
* [Push Notifications](#push-notifications)
* [PlayStore Safety Standards](#playstore-safety)
## <a id="matrix" href="#matrix">#</a> Matrix
## Matrix<a id="matrix"/>
FluffyChat uses the Matrix protocol. This means that FluffyChat is just a client that can be connected to any compatible matrix server. The respective data protection agreement of the server selected by the user then applies.
For convenience, one or more servers are set as default that the FluffyChat developers consider trustworthy. The developers of FluffyChat do not guarantee their trustworthiness. Before the first communication, users are informed which server they are connecting to.
@ -18,17 +17,17 @@ FluffyChat only communicates with the selected server and with [OpenStreetMap](h
More information is available at: [https://matrix.org](https://matrix.org)
## <a id="database" href="#database">#</a> Database
## Database<a id="database"/>
FluffyChat caches some data received from the server in a local sqflite database on the device of the user. On web indexedDB is used. FluffyChat always tries to encrypt the database by using SQLCipher and stores the encryption key in the [Secure Storage](https://pub.dev/packages/flutter_secure_storage) of the device.
More information is available at: [https://pub.dev/packages/sqflite](https://pub.dev/packages/sqflite) and [https://pub.dev/packages/sqlcipher_flutter_libs](https://pub.dev/packages/sqlcipher_flutter_libs)
## <a id="encryption" href="#encryption">#</a> Encryption
## Encryption<a id="encryption"/>
All communication of substantive content between Fluffychat and any server is done in secure way, using transport encryption to protect it.
FluffyChat also uses End-To-End-Encryption by using [Vodozemac](https://github.com/matrix-org/vodozemac) and enables it by default for private chats.
FluffyChat also uses End-To-End-Encryption by using [libolm](https://gitlab.matrix.org/matrix-org/olm) and enables it by default for private chats.
## <a id="app-permissions" href="#app-permissions">#</a> App Permissions
## App Permissions<a id="app-permissions"/>
The permissions are the same on Android and iOS but may differ in the name. This are the Android Permissions:
@ -51,7 +50,7 @@ The user is able to send files from the device's file system.
#### Location
FluffyChat makes it possible to share the current location via the chat. When the user shares their location, FluffyChat uses the device location service and sends the geo-data via Matrix.
## <a id="push-notifications" href="#push-notifications">#</a> Push Notifications
## Push Notifications<a id="push-notifications"/>
FluffyChat uses the Firebase Cloud Messaging service for push notifications on Android and iOS. This takes place in the following steps:
1. The matrix server sends the push notification to the FluffyChat Push Gateway
2. The FluffyChat Push Gateway forwards the message in a different format to Firebase Cloud Messaging
@ -59,7 +58,7 @@ FluffyChat uses the Firebase Cloud Messaging service for push notifications on A
4. The device receives the push notification from Firebase Cloud Messaging and displays it as a notification
The source code of the push gateway can be viewed here:
[https://github.com/krille-chan/fluffygate](https://github.com/krille-chan/fluffygate)
[https://gitlab.com/famedly/services/famedly-push-gateway](https://gitlab.com/famedly/services/famedly-push-gateway)
`event_id_only` is used as the format for the push notification. A typical push notification therefore only contains:
- Event ID
@ -95,7 +94,7 @@ A typical push notification could look like this:
FluffyChat sets the `event_id_only` flag at the Matrix Server. This server is then responsible to send the correct data.
# <a id="playstore-safety" href="#playstore-safety">#</a> Explanation of FluffyChat's Compliance with Google Play Store's Safety Standards
# Explanation of FluffyChat's Compliance with Google Play Store's Safety Standards
FluffyChat is committed to promoting a safe and respectful environment for all users. As a Matrix client, FluffyChat connects users to various Matrix servers. Please note that FluffyChat does not host or manage any servers directly, and as such, we do not have the capability to enforce content moderation or deletion within the app itself.

View file

@ -1,11 +1,11 @@
![Screenshot](https://github.com/krille-chan/fluffychat/blob/main/assets/banner_transparent.png?raw=true)
[FluffyChat](https://fluffy.chat) is an open source, nonprofit and cute [[matrix](https://matrix.org)] client written in [Flutter](https://flutter.dev). The goal of the app is to create an easy to use instant messenger which is open source and accessible for everyone.
[FluffyChat](https://fluffychat.im) is an open source, nonprofit and cute [[matrix](https://matrix.org)] client written in [Flutter](https://flutter.dev). The goal of the app is to create an easy to use instant messenger which is open source and accessible for everyone.
### Links:
- 🌐 [[Weblate] Translate FluffyChat into your language](https://hosted.weblate.org/projects/fluffychat/)
- 🌍 [[m] Join the community](https://matrix.to/#/#fluffy-space:matrix.org)
- 🌍 [[m] Join the community](https://matrix.to/#/#fluffychat:matrix.org)
- 📰 [[Mastodon] Get updates on social media](https://troet.cafe/@krille)
- 🖥️ [[Famedly] Server hosting and professional support](https://famedly.com/kontakt)
- 💝 [[Liberapay] Support FluffyChat development](https://de.liberapay.com/KrilleChritzelius)
@ -14,8 +14,8 @@
### Screenshots:
<img src="https://github.com/krille-chan/fluffychat-website/blob/main/src/assets/screenshots/mobile.png?raw=true" height="300">
<img src="https://github.com/krille-chan/fluffychat-website/blob/main/src/assets/screenshots/desktop.png?raw=true" height="300">
<img src="https://github.com/krille-chan/fluffychat/blob/main/docs/screenshots/mobile.png?raw=true" height="300">
<img src="https://github.com/krille-chan/fluffychat/blob/main/docs/screenshots/desktop.png?raw=true" height="300">
# Features
@ -44,67 +44,13 @@
Please visit the website for installation instructions:
- https://fluffy.chat
- https://fluffychat.im
# How to build
1. To build FluffyChat you need [Flutter](https://flutter.dev) and [Rust](https://www.rust-lang.org/tools/install)
Please visit the [Wiki](https://github.com/krille-chan/fluffychat/wiki) for build instructions:
2. Clone the repo:
```
git clone https://github.com/krille-chan/fluffychat.git
cd fluffychat
```
3. Choose your target platform below and enable support for it.
3.1 If you want, enable Googles Firebase Cloud Messaging:
`./scripts/add-firebase-messaging.sh`
4. Debug with: `flutter run`
### Android
* Build with: `flutter build apk`
### iOS / iPadOS
* Have a Mac with Xcode installed, and set up for Xcode-managed app signing
* If you want automatic app installation to connected devices, make sure you have Apple Configurator installed, with the Automation Tools (`cfgutil`) enabled
* Set a few environment variables
* FLUFFYCHAT_NEW_TEAM: the Apple Developer team that your certificates should live under
* FLUFFYCHAT_NEW_GROUP: the group you want App IDs and such to live under (ie: com.example.fluffychat)
* FLUFFYCHAT_INSTALL_IPA: set to `1` if you want the IPA to be deployed to connected devices after building, otherwise unset
* Run `./scripts/build-ios.sh`
### Web
* Build with:
```bash
./scripts/prepare-web.sh # To install Vodozemac
flutter build web --release
```
* Optionally configure by serving a `config.json` at the same path as fluffychat.
An example can be found at `config.sample.json`. All values there are optional.
**Please only the values, you really need**. If you e.g. only want
to change the default homeserver, then only modify the `defaultHomeserver` key.
### Desktop (Linux, Windows, macOS)
* Enable Desktop support in Flutter: https://flutter.dev/desktop
#### Install custom dependencies (Linux)
```bash
sudo apt install libjsoncpp1 libsecret-1-dev libsecret-1-0 librhash0 libwebkit2gtk-4.0-dev lld
```
* Build with one of these:
```bash
flutter build linux --release
flutter build windows --release
flutter build macos --release
```
- https://github.com/krille-chan/fluffychat/wiki/How-To-Build
# Special thanks

View file

@ -1,15 +0,0 @@
# Security Policy
If you believe you have discovered a security vulnerability in this project, **do not open a public issue**.
To report a security issue responsibly, please go to the Security tab or visit:
https://github.com/krille-chan/fluffychat/security/advisories/new
The following information can help us address the issue:
- Clear steps to reproduce the vulnerability
- The software version you are using
- The affected platforms
We appreciate your report and will respond as quickly as possible. Please note that this project is maintained by volunteers and is provided without guarantees.

View file

@ -2,6 +2,7 @@ include: package:flutter_lints/flutter.yaml
linter:
rules:
- camel_case_types
- avoid_print
- constant_identifier_names
- prefer_final_locals
@ -9,68 +10,45 @@ linter:
- sort_pub_dependencies
- require_trailing_commas
- omit_local_variable_types
- cancel_subscriptions
- always_declare_return_types
- avoid_void_async
- no_adjacent_strings_in_list
- test_types_in_equals
- throw_in_finally
- unnecessary_statements
- avoid_bool_literals_in_conditional_expressions
- prefer_single_quotes
- prefer_const_declarations
- unnecessary_lambdas
- combinators_ordering
- noop_primitive_operations
- unnecessary_null_checks
- unnecessary_null_in_if_null_operators
- unnecessary_to_list_in_spreads
- use_is_even_rather_than_modulo
- use_super_parameters
# Flutter specific:
- use_colored_box
analyzer:
plugins:
- dart_code_linter
errors:
todo: ignore
use_build_context_synchronously: ignore
exclude:
- lib/generated_plugin_registrant.dart
- lib/l10n/*.dart
dart_code_linter:
dart_code_metrics:
metrics:
cyclomatic-complexity: 20
number-of-arguments: 4
maximum-nesting-level: 5
source-lines-of-code: 50
maintainability-index: 40
rules:
# Dart specific:
- avoid-dynamic
- avoid-redundant-async
- avoid-unnecessary-type-assertions
- avoid-unnecessary-type-casts
- avoid-unrelated-type-assertions
- no-boolean-literal-compare
- no-empty-block
- prefer-conditional-expressions
- no-equal-then-else
- prefer-first
- prefer-last
- prefer-immediate-return
- prefer-enums-by-name
- avoid-unnecessary-conditionals
# TODO:
# - member-ordering
# - avoid-global-state
# - prefer-match-file-name
# - avoid-banned-imports:
# entries:
# - paths: ['some/folder/.*\.dart', 'another/folder/.*\.dart']
# deny: ['package:flutter/material.dart']
# message: 'Do not import Flutter Material Design library, we should not depend on it!'
# - no-magic-number:
# allowed: [-1, 0, 1,2,4,6,8,12,16,32,40,56,64]
# allow-only-once: true
# Flutter specific:
- prefer-media-query-direct-access
- no-magic-number:
severity: style
- avoid-late-keyword:
severity: style
- avoid-non-null-assertion:
severity: style
- avoid-unused-parameters
- binary-expression-operand-order
- avoid-unnecessary-setstate
- avoid-wrapping-in-padding
- prefer-correct-edge-insets-constructor
- avoid-returning-widgets
# TODO:
# - prefer-single-widget-per-file:
# ignore-private-widgets: true
# - prefer-extracting-callbacks
- prefer-const-border-radius
- prefer-single-widget-per-file:
ignore-private-widgets: true
- prefer-extracting-callbacks
metrics-exclude:
- test/**
rules-exclude:
- test/**
anti-patterns:
- long-method
- long-parameter-list

View file

@ -14,7 +14,6 @@ if (file("google-services.json").exists()) {
dependencies {
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4") // For flutter_local_notifications // Workaround for: https://github.com/MaikuB/flutter_local_notifications/issues/2286
implementation("androidx.core:core-ktx:1.17.0") // For Android Auto
}
@ -36,7 +35,7 @@ configurations.all {
android {
namespace = "chat.fluffy.fluffychat"
compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion
ndkVersion = "27.0.12077973"
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
@ -71,20 +70,15 @@ android {
defaultConfig {
applicationId = "chat.fluffy.fluffychat"
minSdk = flutter.minSdkVersion
minSdk = 21
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
ndk { // Workaround for https://github.com/flutter/flutter/issues/162153#issuecomment-2612443642
abiFilters += listOf("armeabi-v7a", "arm64-v8a", "x86_64", "x86")
}
}
buildTypes {
release {
signingConfig = signingConfigs.getByName("release")
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
}
}

View file

@ -17,10 +17,14 @@
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.BIND_TELECOM_CONNECTION_SERVICE"/>
<!-- To make app compatible with tablets -->
<uses-feature android:name="android.hardware.camera" android:required="false"/>
<uses-feature android:name="android.hardware.microphone" android:required="false" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"
android:maxSdkVersion="29" />
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-sdk
tools:overrideLibrary="io.wazo.callkeep, net.touchcapture.qr.flutterqr, com.cloudwebrtc.webrtc, org.webrtc, com.it_nomads.fluttersecurestorage, com.pichillilorenzo.flutter_inappwebview, com.example.video_compress, com.otaliastudios.transcoder, com.otaliastudios.opengl, com.kineapps.flutter_file_dialog, com.llfbandit.record, com.pravera.flutter_foreground_task"/>
@ -106,7 +110,7 @@
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="im.fluffychat" android:path="/login"/>
<data android:scheme="im.fluffychat" android:host="login"/>
</intent-filter>
</activity>
@ -121,13 +125,15 @@
android:foregroundServiceType="camera|microphone|mediaProjection">
</service>
<!-- From flutter_local_notifications package for notification actions -->
<receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ActionBroadcastReceiver" />
<!-- To make notifications available in Android Auto -->
<meta-data
android:name="com.google.android.gms.car.application"
android:resource="@xml/automotive_app_desc"/>
<service android:name="io.wazo.callkeep.VoiceConnectionService"
android:label="Wazo"
android:foregroundServiceType="camera|microphone|mediaProjection"
android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE"
android:exported="true">
<intent-filter>
<action android:name="android.telecom.ConnectionService" />
</intent-filter>
</service>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->

View file

@ -1,3 +0,0 @@
<automotiveApp>
<uses name="notification" />
</automotiveApp>

View file

@ -30,7 +30,6 @@
<locale android:name="it"/>
<locale android:name="ja"/>
<locale android:name="ka"/>
<locale android:name="kab"/>
<locale android:name="ko"/>
<locale android:name="lt"/>
<locale android:name="lv"/>
@ -44,7 +43,6 @@
<locale android:name="ru"/>
<locale android:name="sk"/>
<locale android:name="sl"/>
<locale android:name="sq"/>
<locale android:name="sr"/>
<locale android:name="sv"/>
<locale android:name="ta"/>
@ -52,7 +50,6 @@
<locale android:name="th"/>
<locale android:name="tr"/>
<locale android:name="uk"/>
<locale android:name="uz"/>
<locale android:name="vi"/>
<locale android:name="yue"/>
<locale android:name="zh"/>

View file

@ -1,3 +1 @@
FluffyChat 2.5.0 introduces a new homeserver picker for onboarding,
better image compression performance and several smaller new features,
design adjustments and bug fixes.
Fixes broken error reporter for push notifications and wrong clipped avatars. Also updates dependencies and translations.

View file

@ -1,6 +1,6 @@
#Mon Mar 17 08:36:03 CET 2025
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View file

@ -18,7 +18,7 @@ pluginManagement {
plugins {
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
id("com.android.application") version "8.9.1" apply false
id("com.android.application") version "8.7.3" apply false
id("org.jetbrains.kotlin.android") version "2.1.0" apply false
if (file("app/google-services.json").exists()) {
id("com.google.gms.google-services") version "4.3.8" apply false

3
appimage/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
FluffyChat.AppDir
*.AppImage
*.AppImage.zsync

4
appimage/AppRun Executable file
View file

@ -0,0 +1,4 @@
#!/bin/sh
cd "$(dirname "$0")"
exec ./fluffychat

View file

@ -0,0 +1,9 @@
[Desktop Entry]
Type=Application
Version=1.0
Name=FluffyChat
Comment=Matrix Client. Chat with your friends
Exec=AppRun
Icon=fluffychat
Terminal=false
Categories=Network;Chat;InstantMessaging;X-Matrix;

24
appimage/README.md Normal file
View file

@ -0,0 +1,24 @@
# FluffyChat AppImage
FluffyChat is provided as AppImage too. To Download, visit fluffychat.im.
## Building
- Ensure you install `appimagetool`
```shell
flutter build linux
# copy binaries to appimage dir
cp -r build/linux/{x64,arm64}/release/bundle appimage/FluffyChat.AppDir
cd appimage
# prepare AppImage files
cp FluffyChat.desktop FluffyChat.AppDir/
mkdir -p FluffyChat.AppDir/usr/share/icons
cp ../assets/logo.svg FluffyChat.AppDir/fluffychat.svg
cp AppRun FluffyChat.AppDir
# build the AppImage
appimagetool FluffyChat.AppDir
```

View file

@ -1,31 +1,10 @@
{
"applicationName": "FluffyChat",
"defaultHomeserver": "matrix.org",
"presetHomeserver": "",
"welcomeText": "",
"privacyUrl": "https://github.com/krille-chan/fluffychat/blob/main/PRIVACY.md",
"audioRecordingNumChannels": 1,
"audioRecordingAutoGain": true,
"audioRecordingEchoCancel": false,
"audioRecordingNoiseSuppress": true,
"audioRecordingBitRate": 64000,
"audioRecordingSamplingRate": 44100,
"renderHtml": true,
"fontSizeFactor": 1,
"hideRedactedEvents": false,
"hideUnknownEvents": true,
"separateChatTypes": false,
"autoplayImages": true,
"sendTypingNotifications": true,
"sendPublicReadReceipts": true,
"swipeRightToLeftToReply": true,
"sendOnEnter": false,
"showPresences": true,
"displayNavigationRail": false,
"experimentalVoip": false,
"shareKeysWith": "all",
"noEncryptionWarningShown": false,
"displayChatDetailsColumn": false,
"colorSchemeSeedInt": 4283835834,
"enableSoftLogout": false
"application_name": "FluffyChat",
"application_welcome_message": null,
"default_homeserver": "matrix.org",
"web_base_url": "https://fluffychat.im/web",
"privacy_url": "https://fluffychat.im/en/privacy.html",
"render_html": false,
"hide_redacted_events": false,
"hide_unknown_events": false
}

View file

@ -1,3 +0,0 @@
ignore:
- handy_window
- sqlcipher_flutter_libs

View file

@ -0,0 +1,2 @@
# im.fluffychat.Fluffychat
8b25b37b-f160-4350-b4f6-9a04554e8f9e

21
docs/LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Tailwind Toolbox
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

91
docs/OFL.txt Normal file
View file

@ -0,0 +1,91 @@
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

BIN
docs/appstore-badge.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
docs/browser-badge.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
docs/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
docs/fdroid_button.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
docs/feature1.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 647 KiB

BIN
docs/feature2.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 KiB

BIN
docs/feature3.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 KiB

BIN
docs/feature4.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

BIN
docs/feature5.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 KiB

BIN
docs/feature6.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

BIN
docs/feature7.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

BIN
docs/feature8.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 448 KiB

BIN
docs/feature9.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 MiB

BIN
docs/firefox_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
docs/flathub-badge-en.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
docs/google-play-badge.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

183
docs/index.html Normal file
View file

@ -0,0 +1,183 @@
<!DOCTYPE html>
<html lang="en">
<html>
<head>
<meta charset="utf-8">
<title>FluffyChat Official Website</title>
<meta name="identifier-url" content="https://fluffychat.im" />
<meta name="title" content="FluffyChat Official Website" />
<meta name="description" content="The cutest messenger in the Matrix network" />
<meta name="abstract" content="FluffyChat is the cutest messenger in the Matrix network" />
<meta name="keywords" content="FluffyChat, Matrix, Flutter, App" />
<meta name="author" content="Krille Fear" />
<meta name="revisit-after" content="15" />
<meta name="language" content="EN" />
<meta name="robots" content="All" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.png">
<link href="tailwind.css" rel="stylesheet">
</head>
<body
class="flex flex-col items-center min-h-screen w-full bg-gradient-to-t from-purple-200 to-blue-50 dark:from-purple-900 dark:to-slate-900"
style="font-family: 'Zen Kurenaido', sans-serif;">
<div class="w-full md:h-12 min-h-12 px-4 py-4 md:py-0 mb-8">
<nav class="flex flex-wrap h-full justify-center items-center space-x-6 w-full max-w-4xl m-auto">
<a href="https://ko-fi.com/krille/posts"
class="text-lg dark:text-white hover:text-purple-800 dark:hover:text-purple-400">News</a>
<a href="https://github.com/krille-chan/fluffychat/blob/main/CHANGELOG.md"
class="text-lg dark:text-white hover:text-purple-800 dark:hover:text-purple-400">Changelog</a>
<a href="https://github.com/krille-chan/fluffychat/wiki"
class="text-lg dark:text-white hover:text-purple-800 dark:hover:text-purple-400">Wiki</a>
<a href="https://github.com/krille-chan/fluffychat"
class="text-lg dark:text-white hover:text-purple-800 dark:hover:text-purple-400">Code</a>
<div class="md:flex-grow"> </div>
<a href='https://ko-fi.com/C1C86VN53' target='_blank' class="m-2 hover:scale-110 transition-transform "><img
class="h-7" src='https://storage.ko-fi.com/cdn/kofi2.png?v=3' border='0'
alt='Buy Me a Coffee at ko-fi.com' /></a>
<a href="https://troet.cafe/@krille" rel="me" class="m-2 hover:scale-110 transition-transform "><img
src="mastodon.svg" class="h-7" /></a>
</nav>
</div>
<img src="info-logo.png" alt="FluffyChat Logo" class="h-56" />
<p class="text-xl dark:text-gray-200 text-gray-700 mb-8">The cutest messenger in [<a href="https://matrix.org"
target="_blank" class="text-xl underline hover:text-purple-800 dark:hover:text-purple-400">matrix</a>]
</p>
<div class="flex flex-wrap justify-center mb-16 w-full px-8 gap-4">
<img src="screenshots/mobile.png" alt="Mobile screenshot"
class="h-96 w-auto object-contain rounded-xl border border-gray-300 shadow-xl" />
<img src="screenshots/desktop.png" alt="Desktop screenshot"
class="h-96 w-auto object-contain rounded-xl border border-gray-300 shadow-xl" />
</div>
<div class="max-w-lg mb-16 flex justify-center flex-wrap">
<a href="https://apps.apple.com/app/fluffychat/id1551469600"><img src="appstore-badge.png"
class="w-36 pr-2 mb-2 inline hover:scale-105 transition-transform"></a>
<a href="https://play.google.com/store/apps/details?id=chat.fluffy.fluffychat"><img src="google-play-badge.png"
class="w-36 pr-2 mb-2 hover:scale-105 transition-transform inline">
</a><a href="https://f-droid.org/packages/chat.fluffy.fluffychat/"><img src="fdroid_button.png"
class="w-36 pr-2 mb-2 hover:scale-105 transition-transform inline">
</a>
<a href="https://fluffychat.im/web">
<img src="browser-badge.png" class="w-36 pr-2 mb-2 hover:scale-105 transition-transform inline"></a>
<a href="https://snapcraft.io/fluffychat"><img src="snap-store-badge.svg"
class="w-36 pr-2 mb-2 hover:scale-105 transition-transform inline"></a>
<a href="https://flathub.org/apps/details/im.fluffychat.Fluffychat"><img src="flathub-badge-en.png"
class="w-36 pr-2 mb-2 hover:scale-105 transition-transform inline"></a>
</div>
<div class="grid md:grid-cols-3 md:grid-rows-3 max-w-4xl justify-center w-full mb-16">
<div class="flex flex-col justify-center items-center p-8">
<img alt="Animated dancing woman" loading="lazy" src="feature1.gif" class="h-32" />
<h1 class="text-purple-500 dark:text-purple-300 text-2xl">Easy to use</h1>
<p class="text-center dark:text-white">FluffyChat is designed to be as easy to use as possible. No one
should be left behind.</p>
</div>
<div class="flex flex-col justify-center items-center p-8">
<img alt="Animated pencil" loading="lazy" src="feature2.gif" class="h-32" />
<h1 class="text-purple-500 dark:text-purple-300 text-2xl">Material You</h1>
<p class="text-center dark:text-white">The well polished design is based on Material You and works great on
all platforms.</p>
</div>
<div class="flex flex-col justify-center items-center p-8">
<img alt="Animated mechanical arm" loading="lazy" src="feature3.gif" class="h-32" />
<h1 class="text-purple-500 dark:text-purple-300 text-2xl">Secure</h1>
<p class="text-center dark:text-white">With end-to-end encryption, cross-signing and encrypted backups,
FluffyChat is one of the most secure messenger out there.</p>
</div>
<div class="flex flex-col justify-center items-center p-8">
<img alt="Animated planet earth" loading="lazy" src="feature4.gif" class="h-32" />
<h1 class="text-purple-500 dark:text-purple-300 text-2xl">Decentral</h1>
<p class="text-center dark:text-white">You can choose the <a href="https://joinmatrix.org"
class="underline hover:text-purple-800 dark:hover:text-purple-400">server</a> you want to use or
even <a href="https://matrix.org/ecosystem/servers/"
class="underline hover:text-purple-800 dark:hover:text-purple-400">self-host</a> your own!</p>
</div>
<div class="flex flex-col justify-center items-center p-8">
<img alt="Animated bell" loading="lazy" src="feature5.gif" class="h-32" />
<h1 class="text-purple-500 dark:text-purple-300 text-2xl">Push Notifications</h1>
<p class="text-center dark:text-white">You can choose between Firebase Cloud Messaging or the more privacy
focused <a href="https://unifiedpush.org"
class="underline hover:text-purple-800 dark:hover:text-purple-400">Unified Push</a>.</p>
</div>
<div class="flex flex-col justify-center items-center p-8">
<img alt="Animated rocket" loading="lazy" src="feature6.gif" class="h-32" />
<h1 class="text-purple-500 dark:text-purple-300 text-2xl">Spaces</h1>
<p class="text-center dark:text-white">With spaces you can join or create a community which organizes chats
and users. Using sub-spaces you can even nest your communities.</p>
</div>
<div class="flex flex-col justify-center items-center p-8">
<img alt="Animated glass sphere" loading="lazy" src="feature7.gif" class="h-32" />
<h1 class="text-purple-500 dark:text-purple-300 text-2xl">Video calls</h1>
<p class="text-center dark:text-white">Still an experimental feature but you can already try out video and
audio calls, compatible with other [matrix] clients.</p>
</div>
<div class="flex flex-col justify-center items-center p-8">
<img alt="Animated chick" loading="lazy" src="feature8.gif" class="h-32" />
<h1 class="text-purple-500 dark:text-purple-300 text-2xl">Stickers</h1>
<p class="text-center dark:text-white">Create your own sticker sets and share them with your friends. You
can even use them as inline emojis.</p>
</div>
<div class="flex flex-col justify-center items-center p-8">
<img alt="Animated whoa emoji" loading="lazy" src="feature9.gif" class="h-32" />
<h1 class="text-purple-500 dark:text-purple-300 text-2xl">Compatible</h1>
<p class="text-center dark:text-white">FluffyChat is compatible with any other [matrix] client like <a
href="https://element.io"
class="underline hover:text-purple-800 dark:hover:text-purple-400">Element</a>,
<a href="https://nheko-reborn.github.io/"
class="underline hover:text-purple-800 dark:hover:text-purple-400">Nheko</a>, <a
href="https://cinny.in" class="underline hover:text-purple-800 dark:hover:text-purple-400">Cinny</a>
or <a href="https://apps.kde.org/de/neochat/"
class="underline hover:text-purple-800 dark:hover:text-purple-400">NeoChat</a>.
</p>
</div>
</div>
<!--Footer-->
<div class="w-full flex justify-center">
<footer class="w-full text-center max-w-4xl p-4 text-slate-700 dark:text-slate-200">
<a class="text-slate-700 dark:text-slate-200 no-underline hover:text-purple-800 text-sm"
href="https://liberapay.com/KrilleChritzelius">Liberapay</a>
-
<a class="text-slate-700 dark:text-slate-200 no-underline hover:text-purple-800 text-sm"
href="https://github.com/krille-chan/fluffychat">Source
code</a>
-
<a class="text-slate-700 dark:text-slate-200 no-underline hover:text-purple-800 text-sm"
href="https://github.com/krille-chan/fluffychat/blob/main/PRIVACY.md">Privacy</a>
-
<a class="text-slate-700 dark:text-slate-200 no-underline hover:text-purple-800 text-sm"
href="https://github.com/krille-chan/fluffychat/blob/main/CHANGELOG.md">Changelog</a>
-
<a class="text-slate-700 dark:text-slate-200 no-underline hover:text-purple-800 text-sm"
href="https://hosted.weblate.org/projects/fluffychat/">Translations</a>
-
<a class="text-slate-700 dark:text-slate-200 no-underline hover:text-purple-800 text-sm"
href="https://googlefonts.github.io/noto-emoji-animation/">Noto Animated Emojis</a>
-
<a class="text-slate-700 dark:text-slate-200 no-underline hover:text-purple-800 text-sm"
href="https://keys.mailvelope.com/pks/lookup?op=get&search=christian-pauly%40posteo.de">Contact</a>
-
<a class="text-slate-700 dark:text-slate-200 no-underline hover:text-purple-800 text-sm"
href="https://krille-chan.github.io">Created
by Krille-chan</a>
</footer>
</div>
</body>
</html>

BIN
docs/info-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
docs/kofi_button_dark.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

10
docs/mastodon.svg Normal file
View file

@ -0,0 +1,10 @@
<svg width="75" height="79" viewBox="0 0 75 79" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M73.8393 17.4898C72.6973 9.00165 65.2994 2.31235 56.5296 1.01614C55.05 0.797115 49.4441 0 36.4582 0H36.3612C23.3717 0 20.585 0.797115 19.1054 1.01614C10.5798 2.27644 2.79399 8.28712 0.904997 16.8758C-0.00358524 21.1056 -0.100549 25.7949 0.0682394 30.0965C0.308852 36.2651 0.355538 42.423 0.91577 48.5665C1.30307 52.6474 1.97872 56.6957 2.93763 60.6812C4.73325 68.042 12.0019 74.1676 19.1233 76.6666C26.7478 79.2728 34.9474 79.7055 42.8039 77.9162C43.6682 77.7151 44.5217 77.4817 45.3645 77.216C47.275 76.6092 49.5123 75.9305 51.1571 74.7385C51.1797 74.7217 51.1982 74.7001 51.2112 74.6753C51.2243 74.6504 51.2316 74.6229 51.2325 74.5948V68.6416C51.2321 68.6154 51.2259 68.5896 51.2142 68.5661C51.2025 68.5426 51.1858 68.522 51.1651 68.5058C51.1444 68.4896 51.1204 68.4783 51.0948 68.4726C51.0692 68.4669 51.0426 68.467 51.0171 68.4729C45.9835 69.675 40.8254 70.2777 35.6502 70.2682C26.7439 70.2682 24.3486 66.042 23.6626 64.2826C23.1113 62.762 22.7612 61.1759 22.6212 59.5646C22.6197 59.5375 22.6247 59.5105 22.6357 59.4857C22.6466 59.4609 22.6633 59.4391 22.6843 59.422C22.7053 59.4048 22.73 59.3929 22.7565 59.3871C22.783 59.3813 22.8104 59.3818 22.8367 59.3886C27.7864 60.5826 32.8604 61.1853 37.9522 61.1839C39.1768 61.1839 40.3978 61.1839 41.6224 61.1516C46.7435 61.008 52.1411 60.7459 57.1796 59.7621C57.3053 59.7369 57.431 59.7154 57.5387 59.6831C65.4861 58.157 73.0493 53.3672 73.8178 41.2381C73.8465 40.7606 73.9184 36.2364 73.9184 35.7409C73.9219 34.0569 74.4606 23.7949 73.8393 17.4898Z" fill="url(#paint0_linear_549_34)"/>
<path d="M61.2484 27.0263V48.114H52.8916V27.6475C52.8916 23.3388 51.096 21.1413 47.4437 21.1413C43.4287 21.1413 41.4177 23.7409 41.4177 28.8755V40.0782H33.1111V28.8755C33.1111 23.7409 31.0965 21.1413 27.0815 21.1413C23.4507 21.1413 21.6371 23.3388 21.6371 27.6475V48.114H13.2839V27.0263C13.2839 22.7176 14.384 19.2946 16.5843 16.7572C18.8539 14.2258 21.8311 12.926 25.5264 12.926C29.8036 12.926 33.0357 14.5705 35.1905 17.8559L37.2698 21.346L39.3527 17.8559C41.5074 14.5705 44.7395 12.926 49.0095 12.926C52.7013 12.926 55.6784 14.2258 57.9553 16.7572C60.1531 19.2922 61.2508 22.7152 61.2484 27.0263Z" fill="white"/>
<defs>
<linearGradient id="paint0_linear_549_34" x1="37.0692" y1="0" x2="37.0692" y2="79" gradientUnits="userSpaceOnUse">
<stop stop-color="#6364FF"/>
<stop offset="1" stop-color="#563ACC"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 433 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 385 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 557 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 408 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 555 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 556 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 542 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 435 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 952 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 951 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

BIN
docs/screenshots/mobile.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.4 KiB

14
docs/tailwind.config.js Normal file
View file

@ -0,0 +1,14 @@
module.exports = {
purge: [
'./index.html'
],
darkMode: false,
theme: {
extend: {},
},
variants: {
extend: {},
},
plugins: [],
}

4
fdroid/.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
repo
srclibs
tmp
chat.fluffy.fluffychat

13
fdroid/config.nightly.py Normal file
View file

@ -0,0 +1,13 @@
repo_url = "https://fluffychat.im/repo/nightly/repo"
repo_name = "FluffyChat nightly repo"
repo_icon = "fdroid-icon.png"
repo_description = """
FluffyChat nightly repo
"""
archive_older = 0
local_copy_dir = "/fdroid"
keystore = "key.nightly.jks"
repo_keyalias = "vmd66783.contaboserver.net"

13
fdroid/config.stable.py Normal file
View file

@ -0,0 +1,13 @@
repo_url = "https://fluffychat.im/repo/stable/repo"
repo_name = "FluffyChat repo"
repo_icon = "fdroid-icon.png"
repo_description = """
FluffyChat repo
"""
archive_older = 0
local_copy_dir = "/fdroid"
keystore = "key.jks"
repo_keyalias = "key"

BIN
fdroid/fdroid-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View file

@ -0,0 +1,53 @@
Categories:
- Internet
- Phone & SMS
License: AGPL-3.0-only
AuthorName: Famedly
SourceCode: https://github.com/krille-chan/fluffychat
IssueTracker: https://github.com/krille-chan/fluffychat/-/issues
Translation: https://hosted.weblate.org/projects/fluffychat/
Changelog: https://gitlab.com/ChristianPauly/fluffychat-flutter/-/blob/main/CHANGELOG.md
AutoName: FluffyChat
Summary: "Chat with your friends with FluffyChat.\n"
Description: |
FluffyChat is an open, nonprofit and cute matrix messenger app for Ubuntu Touch, Android and iOS.
Open
Opensource and open development where everyone can join.
Nonprofit
FluffyChat is donation funded.
Cute ♥
Cute design and many theme settings including a dark mode.
One-to-one and groupchats
Unlimited groups and direct chats.
Easy
FluffyChat is made as simple to use as possible.
Free
Free to use for everyone without ads.
Decentralized
There is no "FluffyChat server" you are forced to use. Use the server you find trustworthy or host
your own.
Compatible
Compatible with Riot, Fractal, Nekho and all matrix messengers.
FluffyChat comes with a dream
Imagine a world where everyone can choose the messenger they like and is still able to chat with
all of their friends.
A world where there are no companies spying on you when you send selfies to friends and lovers.
And a world where apps are made for fluffyness and not for profit. ♥
RepoType: git
Repo: https://github.com/krille-chan/fluffychat.git
AutoUpdateMode: None
UpdateCheckMode: None

View file

@ -0,0 +1,188 @@
import 'package:fluffychat/config/setting_keys.dart';
import 'package:fluffychat/pages/chat/chat_view.dart';
import 'package:fluffychat/pages/chat_list/chat_list_body.dart';
import 'package:fluffychat/pages/chat_list/search_title.dart';
import 'package:fluffychat/pages/invitation_selection/invitation_selection_view.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:fluffychat/main.dart' as app;
import 'package:shared_preferences/shared_preferences.dart';
import 'extensions/default_flows.dart';
import 'extensions/wait_for.dart';
import 'users.dart';
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
group(
'Integration Test',
() {
setUpAll(
() async {
// this random dialog popping up is super hard to cover in tests
SharedPreferences.setMockInitialValues({
SettingKeys.showNoGoogle: false,
});
},
);
testWidgets(
'Start app, login and logout',
(WidgetTester tester) async {
app.main();
await tester.ensureAppStartedHomescreen();
await tester.ensureLoggedOut();
},
);
testWidgets(
'Login again',
(WidgetTester tester) async {
app.main();
await tester.ensureAppStartedHomescreen();
},
);
testWidgets(
'Start chat and send message',
(WidgetTester tester) async {
app.main();
await tester.ensureAppStartedHomescreen();
await tester.waitFor(find.byType(TextField));
await tester.enterText(find.byType(TextField), Users.user2.name);
await tester.pumpAndSettle();
await tester.scrollUntilVisible(
find.text('Chats').first,
500,
scrollable: find
.descendant(
of: find.byType(ChatListViewBody),
matching: find.byType(Scrollable),
)
.first,
);
await tester.pumpAndSettle();
await tester.tap(find.text('Chats'));
await tester.pumpAndSettle();
await tester.waitFor(find.byType(SearchTitle));
await tester.pumpAndSettle();
await tester.scrollUntilVisible(
find.text(Users.user2.name).first,
500,
scrollable: find
.descendant(
of: find.byType(ChatListViewBody),
matching: find.byType(Scrollable),
)
.first,
);
await tester.pumpAndSettle();
await tester.tap(find.text(Users.user2.name).first);
try {
await tester.waitFor(
find.byType(ChatView),
timeout: const Duration(seconds: 5),
);
} catch (_) {
// in case the homeserver sends the username as search result
if (find.byIcon(Icons.send_outlined).evaluate().isNotEmpty) {
await tester.tap(find.byIcon(Icons.send_outlined));
await tester.pumpAndSettle();
}
}
await tester.waitFor(find.byType(ChatView));
await tester.enterText(find.byType(TextField).last, 'Test');
await tester.pumpAndSettle();
try {
await tester.waitFor(find.byIcon(Icons.send_outlined));
await tester.tap(find.byIcon(Icons.send_outlined));
} catch (_) {
await tester.testTextInput.receiveAction(TextInputAction.done);
}
await tester.pumpAndSettle();
await tester.waitFor(find.text('Test'));
await tester.pumpAndSettle();
},
);
testWidgets('Spaces', (tester) async {
app.main();
await tester.ensureAppStartedHomescreen();
await tester.waitFor(find.byTooltip('Show menu'));
await tester.tap(find.byTooltip('Show menu'));
await tester.pumpAndSettle();
await tester.waitFor(find.byIcon(Icons.workspaces_outlined));
await tester.tap(find.byIcon(Icons.workspaces_outlined));
await tester.pumpAndSettle();
await tester.waitFor(find.byType(TextField));
await tester.enterText(find.byType(TextField).last, 'Test Space');
await tester.pumpAndSettle();
await tester.testTextInput.receiveAction(TextInputAction.done);
await tester.pumpAndSettle();
await tester.waitFor(find.text('Invite contact'));
await tester.tap(find.text('Invite contact'));
await tester.pumpAndSettle();
await tester.waitFor(
find.descendant(
of: find.byType(InvitationSelectionView),
matching: find.byType(TextField),
),
);
await tester.enterText(
find.descendant(
of: find.byType(InvitationSelectionView),
matching: find.byType(TextField),
),
Users.user2.name,
);
await Future.delayed(const Duration(milliseconds: 250));
await tester.testTextInput.receiveAction(TextInputAction.done);
await Future.delayed(const Duration(milliseconds: 1000));
await tester.pumpAndSettle();
await tester.tap(
find
.descendant(
of: find.descendant(
of: find.byType(InvitationSelectionView),
matching: find.byType(ListTile),
),
matching: find.text(Users.user2.name),
)
.last,
);
await tester.pumpAndSettle();
await tester.waitFor(find.maybeUppercaseText('Yes'));
await tester.tap(find.maybeUppercaseText('Yes'));
await tester.pumpAndSettle();
await tester.tap(find.byTooltip('Back'));
await tester.pumpAndSettle();
await tester.waitFor(find.text('Load 2 more participants'));
await tester.tap(find.text('Load 2 more participants'));
await tester.pumpAndSettle();
expect(find.text(Users.user2.name), findsOneWidget);
});
},
);
}

View file

@ -1,5 +0,0 @@
HOMESERVER=localhost
USER1_NAME=alice
USER1_PW=AliceInWonderland
USER2_NAME=bob
USER2_PW=JoWirSchaffenDas

View file

@ -0,0 +1,171 @@
import 'dart:developer';
import 'package:fluffychat/pages/chat_list/chat_list_body.dart';
import 'package:fluffychat/pages/intro/intro_page.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import '../users.dart';
import 'wait_for.dart';
extension DefaultFlowExtensions on WidgetTester {
Future<void> login() async {
final tester = this;
await tester.pumpAndSettle();
await tester.waitFor(find.text('Let\'s start'));
expect(find.text('Let\'s start'), findsOneWidget);
final input = find.byType(TextField);
expect(input, findsOneWidget);
// getting the placeholder in place
await tester.tap(find.byIcon(Icons.search));
await tester.pumpAndSettle();
await tester.enterText(input, homeserver);
await tester.pumpAndSettle();
await tester.testTextInput.receiveAction(TextInputAction.done);
await tester.pumpAndSettle();
// in case registration is allowed
// try {
await Future.delayed(const Duration(milliseconds: 50));
await tester.scrollUntilVisible(
find.text('Login'),
500,
scrollable: find.descendant(
of: find.byKey(const Key('ConnectPageListView')),
matching: find.byType(Scrollable).first,
),
);
await tester.pumpAndSettle();
await tester.tap(find.text('Login'));
await tester.pumpAndSettle();
/*} catch (e) {
log('Registration is not allowed. Proceeding with login...');
}*/
await tester.pumpAndSettle();
await Future.delayed(const Duration(milliseconds: 50));
final inputs = find.byType(TextField);
await tester.enterText(inputs.first, Users.user1.name);
await tester.enterText(inputs.last, Users.user1.password);
await tester.pumpAndSettle();
await tester.testTextInput.receiveAction(TextInputAction.done);
try {
// pumpAndSettle does not work in here as setState is called
// asynchronously
await tester.waitFor(
find.byType(LinearProgressIndicator),
timeout: const Duration(milliseconds: 1500),
skipPumpAndSettle: true,
);
} catch (_) {
// in case the input action does not work on the desired platform
if (find.text('Login').evaluate().isNotEmpty) {
await tester.tap(find.text('Login'));
}
}
try {
await tester.pumpAndSettle();
} catch (_) {
// may fail because of ongoing animation below dialog
}
await tester.waitFor(
find.byType(ChatListViewBody),
skipPumpAndSettle: true,
);
}
/// ensure PushProvider check passes
Future<void> acceptPushWarning() async {
final tester = this;
final matcher = find.maybeUppercaseText('Do not show again');
try {
await tester.waitFor(matcher, timeout: const Duration(seconds: 5));
// the FCM push error dialog to be handled...
await tester.tap(matcher);
await tester.pumpAndSettle();
} catch (_) {}
}
Future<void> ensureLoggedOut() async {
final tester = this;
await tester.pumpAndSettle();
if (find.byType(ChatListViewBody).evaluate().isNotEmpty) {
await tester.tap(find.byTooltip('Show menu'));
await tester.pumpAndSettle();
await tester.tap(find.text('Settings'));
await tester.pumpAndSettle();
await tester.scrollUntilVisible(
find.text('Account'),
500,
scrollable: find.descendant(
of: find.byKey(const Key('SettingsListViewContent')),
matching: find.byType(Scrollable),
),
);
await tester.pumpAndSettle();
await tester.tap(find.text('Logout'));
await tester.pumpAndSettle();
await tester.tap(find.maybeUppercaseText('Yes'));
await tester.pumpAndSettle();
}
}
Future<void> ensureAppStartedHomescreen({
Duration timeout = const Duration(seconds: 20),
}) async {
final tester = this;
await tester.pumpAndSettle();
final homeserverPickerFinder = find.byType(IntroPage);
final chatListFinder = find.byType(ChatListViewBody);
final end = DateTime.now().add(timeout);
log(
'Waiting for HomeserverPicker or ChatListViewBody...',
name: 'Test Runner',
);
do {
if (DateTime.now().isAfter(end)) {
throw Exception(
'Timed out waiting for HomeserverPicker or ChatListViewBody',
);
}
await pumpAndSettle();
await Future.delayed(const Duration(milliseconds: 100));
} while (homeserverPickerFinder.evaluate().isEmpty &&
chatListFinder.evaluate().isEmpty);
if (homeserverPickerFinder.evaluate().isNotEmpty) {
log(
'Found HomeserverPicker, performing login.',
name: 'Test Runner',
);
await tester.login();
} else {
log(
'Found ChatListViewBody, skipping login.',
name: 'Test Runner',
);
}
await tester.acceptPushWarning();
}
}

View file

@ -0,0 +1,49 @@
import 'package:flutter_test/flutter_test.dart';
/// Workaround for https://github.com/flutter/flutter/issues/88765
extension WaitForExtension on WidgetTester {
Future<void> waitFor(
Finder finder, {
Duration timeout = const Duration(seconds: 20),
bool skipPumpAndSettle = false,
}) async {
final end = DateTime.now().add(timeout);
do {
if (DateTime.now().isAfter(end)) {
throw Exception('Timed out waiting for $finder');
}
if (!skipPumpAndSettle) {
await pumpAndSettle();
}
await Future.delayed(const Duration(milliseconds: 100));
} while (finder.evaluate().isEmpty);
}
}
extension MaybeUppercaseFinder on CommonFinders {
/// On Android some button labels are in uppercase while on iOS they
/// are not. This method tries both.
Finder maybeUppercaseText(
String text, {
bool findRichText = false,
bool skipOffstage = true,
}) {
try {
final finder = find.text(
text.toUpperCase(),
findRichText: findRichText,
skipOffstage: skipOffstage,
);
expect(finder, findsOneWidget);
return finder;
} catch (_) {
return find.text(
text,
findRichText: findRichText,
skipOffstage: skipOffstage,
);
}
}
}

View file

@ -1,36 +0,0 @@
appId: chat.fluffy.fluffychat
---
- extendedWaitUntil: # Wait for app to be visible
visible: "Sign in"
timeout: 60000
- retry:
maxRetries: 10 # Emulator might need some time to be ready to
commands:
- tapOn: "Sign in"
- tapOn: "Search or enter homeserver address"
- inputText: "http://${HOMESERVER}"
- pressKey: "back"
- tapOn:
id: "homeserver_tile_0"
- tapOn:
id: "connect_to_homeserver_button"
- assertVisible: "Log in to http://${HOMESERVER}"
- inputText: "${USER1_NAME}"
- tapOn: "Password"
- inputText: "${USER1_PW}"
- tapOn: "Login" # Click the login button
- tapOn:
id: "store_in_secure_storage"
- tapOn: "Next"
- tapOn:
text: "Close"
index: 1
- assertVisible: "Push notifications not available"
- tapOn: "Do not show again"
- tapOn:
id: "accounts_and_settings" # Open the popup menu
- tapOn: "Settings"
- scrollUntilVisible:
element: "Logout"
- tapOn: "Logout"
- tapOn: "Logout" # Confirm logout dialog

View file

@ -0,0 +1,36 @@
abstract class Users {
const Users._();
static const user1 = User(
String.fromEnvironment(
'USER1_NAME',
defaultValue: 'alice',
),
String.fromEnvironment(
'USER1_PW',
defaultValue: 'AliceInWonderland',
),
);
static const user2 = User(
String.fromEnvironment(
'USER2_NAME',
defaultValue: 'bob',
),
String.fromEnvironment(
'USER2_PW',
defaultValue: 'JoWirSchaffenDas',
),
);
}
class User {
final String name;
final String password;
const User(this.name, this.password);
}
const homeserver = 'http://${String.fromEnvironment(
'HOMESERVER',
defaultValue: 'localhost',
)}';

Some files were not shown because too many files have changed in this diff Show more