Compare commits
No commits in common. "main" and "v1.7.3" have entirely different histories.
3
.gitignore
vendored
@ -10,6 +10,7 @@
|
|||||||
.buildlog/
|
.buildlog/
|
||||||
.history
|
.history
|
||||||
.svn/
|
.svn/
|
||||||
|
lib/generated_plugin_registrant.dart
|
||||||
prime
|
prime
|
||||||
|
|
||||||
# libolm package
|
# libolm package
|
||||||
@ -37,6 +38,7 @@ prime
|
|||||||
/build/
|
/build/
|
||||||
|
|
||||||
# Web related
|
# Web related
|
||||||
|
lib/generated_plugin_registrant.dart
|
||||||
docs/build/
|
docs/build/
|
||||||
docs/.jekyll-cache/
|
docs/.jekyll-cache/
|
||||||
docs/_site/
|
docs/_site/
|
||||||
@ -60,4 +62,3 @@ ios/Podfile.lock
|
|||||||
/linux/out
|
/linux/out
|
||||||
/macos/out
|
/macos/out
|
||||||
.vs
|
.vs
|
||||||
olm
|
|
||||||
|
|||||||
172
.gitlab-ci.yml
@ -1,7 +1,7 @@
|
|||||||
variables:
|
variables:
|
||||||
FLUTTER_VERSION: 3.10.0
|
FLUTTER_VERSION: 3.3.9
|
||||||
|
|
||||||
image: ghcr.io/cirruslabs/flutter:${FLUTTER_VERSION}
|
image: cirrusci/flutter:${FLUTTER_VERSION}
|
||||||
|
|
||||||
.shared_windows_runners:
|
.shared_windows_runners:
|
||||||
tags:
|
tags:
|
||||||
@ -16,22 +16,20 @@ stages:
|
|||||||
|
|
||||||
code_analyze:
|
code_analyze:
|
||||||
stage: test
|
stage: test
|
||||||
script:
|
script: [./scripts/code_analyze.sh]
|
||||||
- flutter pub get
|
|
||||||
- dart run import_sorter:main --no-comments --exit-if-changed
|
|
||||||
- dart format lib/ test/ --set-exit-if-changed
|
|
||||||
- flutter analyze
|
|
||||||
- git apply ./scripts/enable-android-google-services.patch
|
|
||||||
- flutter pub get
|
|
||||||
- flutter analyze
|
|
||||||
- flutter pub run dart_code_metrics:metrics lib -r gitlab > code-quality-report.json || true
|
|
||||||
artifacts:
|
artifacts:
|
||||||
reports:
|
reports:
|
||||||
codequality: code-quality-report.json
|
codequality: code-quality-report.json
|
||||||
|
tags:
|
||||||
|
- docker
|
||||||
|
- famedly
|
||||||
|
|
||||||
widget_test:
|
widget_test:
|
||||||
stage: test
|
stage: test
|
||||||
script: [flutter test]
|
script: [flutter test]
|
||||||
|
tags:
|
||||||
|
- docker
|
||||||
|
- famedly
|
||||||
|
|
||||||
# the basic integration test configuration testing FLOSS builds on Synapse
|
# the basic integration test configuration testing FLOSS builds on Synapse
|
||||||
.integration_test:
|
.integration_test:
|
||||||
@ -51,13 +49,15 @@ widget_test:
|
|||||||
FF_NETWORK_PER_BUILD: "true"
|
FF_NETWORK_PER_BUILD: "true"
|
||||||
# Tell docker CLI how to talk to Docker daemon.
|
# Tell docker CLI how to talk to Docker daemon.
|
||||||
DOCKER_HOST: tcp://docker:2375/
|
DOCKER_HOST: tcp://docker:2375/
|
||||||
# Use the btrfs driver for improved performance.
|
# Use the overlayfs driver for improved performance.
|
||||||
DOCKER_DRIVER: btrfs
|
DOCKER_DRIVER: overlay2
|
||||||
# Disable TLS since we're running inside local network.
|
# Disable TLS since we're running inside local network.
|
||||||
DOCKER_TLS_CERTDIR: ""
|
DOCKER_TLS_CERTDIR: ""
|
||||||
HOMESERVER: docker
|
HOMESERVER: "docker"
|
||||||
before_script:
|
before_script:
|
||||||
- scripts/integration-prepare-host.sh
|
# start AVD and keep running in background
|
||||||
|
- scripts/integration-start-avd.sh &
|
||||||
|
- scripts/integration-prepare-alpine.sh
|
||||||
# create test user environment variables
|
# create test user environment variables
|
||||||
- source scripts/integration-create-environment-variables.sh
|
- source scripts/integration-create-environment-variables.sh
|
||||||
# create Synapse instance
|
# create Synapse instance
|
||||||
@ -65,57 +65,31 @@ widget_test:
|
|||||||
# properly set the homeserver IP and create test users
|
# properly set the homeserver IP and create test users
|
||||||
- scripts/integration-prepare-homeserver.sh
|
- scripts/integration-prepare-homeserver.sh
|
||||||
script:
|
script:
|
||||||
# start AVD and keep running in background
|
|
||||||
- scripts/integration-start-avd.sh &
|
|
||||||
- flutter pub get
|
- flutter pub get
|
||||||
- scrcpy --no-display --record video.mkv &
|
- flutter test integration_test
|
||||||
- flutter test integration_test --dart-define=HOMESERVER=$HOMESERVER --dart-define=USER1_NAME=$USER1_NAME --dart-define=USER2_NAME=$USER2_NAME --dart-define=USER1_PW=$USER1_PW --dart-define=USER2_PW=$USER2_PW || ( sleep 10 && exit 1 )
|
timeout: 20m
|
||||||
after_script:
|
|
||||||
- ffmpeg -i video.mkv -vf scale=iw/2:-2 -crf 40 -b:v 2000k -preset fast video.mp4 || true
|
|
||||||
timeout: 30m
|
|
||||||
retry: 2
|
|
||||||
only:
|
|
||||||
- tags
|
|
||||||
artifacts:
|
|
||||||
when: always
|
|
||||||
paths:
|
|
||||||
- video.mp4
|
|
||||||
tags:
|
tags:
|
||||||
- docker
|
- docker
|
||||||
- famedly
|
- famedly
|
||||||
|
|
||||||
|
|
||||||
# integration tests for Linux builds
|
# integration tests for Linux builds
|
||||||
### disabled because of Linux headless issues
|
|
||||||
.integration_test_linux:
|
.integration_test_linux:
|
||||||
extends: .integration_test
|
extends: .integration_test
|
||||||
parallel:
|
|
||||||
matrix:
|
|
||||||
- HOMESERVER_IMPLEMENTATION:
|
|
||||||
- conduit
|
|
||||||
script:
|
script:
|
||||||
- apt-get update
|
- apk add cmake ninja gtk+3.0-dev clang pkgconf xz-dev libsecret-dev jsoncpp-dev
|
||||||
- apt-get install -y clang cmake ninja-build pkg-config libgtk-3-dev liblzma-dev libsecret-1-dev libjsoncpp-dev
|
|
||||||
- flutter pub get
|
- flutter pub get
|
||||||
- flutter test integration_test -d linux --dart-define=HOMESERVER=$HOMESERVER --dart-define=USER1_NAME=$USER1_NAME --dart-define=USER2_NAME=$USER2_NAME --dart-define=USER1_PW=$USER1_PW --dart-define=USER2_PW=$USER2_PW || ( sleep 10 && exit 1 )
|
- flutter test integration_test -d linux
|
||||||
after_script: []
|
|
||||||
artifacts:
|
|
||||||
|
|
||||||
# extending the default tests to test the Google-flavored builds
|
# extending the default tests to test the Google-flavored builds
|
||||||
.integration_test_proprietary:
|
.integration_test_proprietary:
|
||||||
extends: .integration_test
|
extends: .integration_test
|
||||||
parallel:
|
|
||||||
matrix:
|
|
||||||
- HOMESERVER_IMPLEMENTATION:
|
|
||||||
- conduit
|
|
||||||
script:
|
script:
|
||||||
# start AVD and keep running in background
|
|
||||||
- scripts/integration-start-avd.sh &
|
|
||||||
- git apply ./scripts/enable-android-google-services.patch
|
- git apply ./scripts/enable-android-google-services.patch
|
||||||
- flutter pub get
|
- flutter pub get
|
||||||
- scrcpy --no-display --record video.mkv &
|
- flutter test integration_test
|
||||||
- flutter test integration_test --dart-define=HOMESERVER=$HOMESERVER --dart-define=USER1_NAME=$USER1_NAME --dart-define=USER2_NAME=$USER2_NAME --dart-define=USER1_PW=$USER1_PW --dart-define=USER2_PW=$USER2_PW || ( sleep 10 && exit 1 )
|
|
||||||
|
|
||||||
release_mode_launches:
|
.release_mode_launches:
|
||||||
parallel:
|
parallel:
|
||||||
matrix:
|
matrix:
|
||||||
- FLAVOR:
|
- FLAVOR:
|
||||||
@ -125,17 +99,15 @@ release_mode_launches:
|
|||||||
stage: test
|
stage: test
|
||||||
before_script:
|
before_script:
|
||||||
- |
|
- |
|
||||||
if [ "$FLAVOR" == "proprietary" ]; then
|
if [ "$FLAVOR" == "proprietary" ]; then
|
||||||
git apply ./scripts/enable-android-google-services.patch
|
git apply ./scripts/enable-android-google-services.patch
|
||||||
fi
|
fi
|
||||||
script:
|
script:
|
||||||
# start AVD and keep running in background
|
# start AVD and keep running in background
|
||||||
- scripts/integration-start-avd.sh &
|
- scripts/integration-start-avd.sh &
|
||||||
# generate temporary release build configuration and ensure app launches
|
# generate temporary release build configuration and ensure app launches
|
||||||
- scripts/integration-check-release-build.sh
|
- scripts/integration-check-release-build.sh
|
||||||
timeout: 20m
|
timeout: 20m
|
||||||
only:
|
|
||||||
- tags
|
|
||||||
tags:
|
tags:
|
||||||
- docker
|
- docker
|
||||||
- famedly
|
- famedly
|
||||||
@ -144,46 +116,20 @@ build_web:
|
|||||||
stage: build
|
stage: build
|
||||||
before_script:
|
before_script:
|
||||||
[sudo apt update && sudo apt install curl -y, ./scripts/prepare-web.sh]
|
[sudo apt update && sudo apt install curl -y, ./scripts/prepare-web.sh]
|
||||||
script:
|
script: [./scripts/build-web.sh]
|
||||||
- flutter build web --release --verbose --source-maps
|
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- build/web/
|
- build/web/
|
||||||
|
tags:
|
||||||
# yes, we *do* build a Windows DLL on Linux. More reliable.
|
- docker
|
||||||
build_olm_windows:
|
- famedly
|
||||||
image: archlinux:latest
|
|
||||||
stage: test
|
|
||||||
before_script:
|
|
||||||
- pacman-key --init
|
|
||||||
- pacman --noconfirm -Sy mingw-w64 cmake git base-devel
|
|
||||||
script:
|
|
||||||
- ./scripts/build-olm-windows.sh
|
|
||||||
- mv olm/build/libolm.dll .
|
|
||||||
artifacts:
|
|
||||||
paths:
|
|
||||||
- libolm.dll
|
|
||||||
allow_failure: true
|
|
||||||
only:
|
|
||||||
- main
|
|
||||||
- tags
|
|
||||||
|
|
||||||
build_windows:
|
build_windows:
|
||||||
extends:
|
extends:
|
||||||
- .shared_windows_runners
|
- .shared_windows_runners
|
||||||
stage: test
|
stage: build
|
||||||
before_script:
|
before_script: [./scripts/prepare-windows.ps1]
|
||||||
- ./scripts/prepare-windows.ps1
|
script: [./scripts/build-windows.ps1]
|
||||||
# workarounding artifacts download being broken
|
|
||||||
- $response = Invoke-WebRequest -Uri "$CI_API_V4_URL/projects/$CI_PROJECT_ID/pipelines/$CI_PIPELINE_ID/jobs" -UseBasicParsing
|
|
||||||
- $jobs = $response | ConvertFrom-Json
|
|
||||||
- $job = $jobs | where { $_.name -eq "build_olm_windows" }
|
|
||||||
- $jobId = $job.id
|
|
||||||
- Invoke-WebRequest -Uri "$CI_API_V4_URL/projects/$CI_PROJECT_ID/jobs/$jobId/artifacts/libolm.dll" -UseBasicParsing -OutFile libolm.dll
|
|
||||||
script:
|
|
||||||
- ./scripts/build-windows.ps1
|
|
||||||
- Copy-Item -Path "libolm.dll" -Destination "build/windows/runner/Release"
|
|
||||||
- ./scripts/package-windows.ps1
|
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- build/windows/runner/Release
|
- build/windows/runner/Release
|
||||||
@ -194,28 +140,28 @@ build_windows:
|
|||||||
|
|
||||||
build_android_debug:
|
build_android_debug:
|
||||||
stage: build
|
stage: build
|
||||||
script: [flutter build apk --debug]
|
script: [./scripts/build-android-debug.sh]
|
||||||
artifacts:
|
artifacts:
|
||||||
when: on_success
|
when: on_success
|
||||||
paths:
|
paths:
|
||||||
- build/app/outputs/apk/debug/app-debug.apk
|
- build/app/outputs/apk/debug/app-debug.apk
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
- famedly
|
|
||||||
except:
|
except:
|
||||||
- main
|
- main
|
||||||
- tags
|
- tags
|
||||||
|
tags:
|
||||||
|
- docker
|
||||||
|
- famedly
|
||||||
|
|
||||||
build_android_apk:
|
build_android_apk:
|
||||||
stage: build
|
stage: build
|
||||||
before_script:
|
before_script:
|
||||||
- git apply ./scripts/enable-android-google-services.patch
|
- git apply ./scripts/enable-android-google-services.patch
|
||||||
- ./scripts/prepare-android-release.sh
|
- ./scripts/prepare-android-release.sh
|
||||||
script: [flutter build apk --release]
|
script: [./scripts/build-android-apk.sh]
|
||||||
artifacts:
|
artifacts:
|
||||||
when: on_success
|
when: on_success
|
||||||
paths:
|
paths:
|
||||||
- build/app/outputs/apk/release/app-release.apk
|
- build/android/app-release.apk
|
||||||
tags:
|
tags:
|
||||||
- docker
|
- docker
|
||||||
- famedly
|
- famedly
|
||||||
@ -255,6 +201,9 @@ fdroid_repo:
|
|||||||
needs:
|
needs:
|
||||||
- "build_android_apk"
|
- "build_android_apk"
|
||||||
resource_group: playstore_release
|
resource_group: playstore_release
|
||||||
|
tags:
|
||||||
|
- docker
|
||||||
|
- famedly
|
||||||
allow_failure: true
|
allow_failure: true
|
||||||
only:
|
only:
|
||||||
- main
|
- main
|
||||||
@ -274,7 +223,12 @@ pages:
|
|||||||
- cd ..
|
- cd ..
|
||||||
- mv docs public
|
- mv docs public
|
||||||
- mv repo public || true
|
- mv repo public || true
|
||||||
- mv build/web/ public/web
|
- mv build/web/ public/nightly
|
||||||
|
# ensure the nightly deployment knows its location
|
||||||
|
- sed -i "s/href=\"\/web\/\"/href=\"\/nightly\/\"/g" public/nightly/index.html
|
||||||
|
- rm -rf build
|
||||||
|
- ./scripts/download-web-stable.sh
|
||||||
|
- mv stable public/web
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- public
|
- public
|
||||||
@ -283,11 +237,11 @@ pages:
|
|||||||
|
|
||||||
build_linux_x86:
|
build_linux_x86:
|
||||||
stage: build
|
stage: build
|
||||||
image: registry.gitlab.com/famedly/company/frontend/flutter-dockerimages/flutter-linux/stable:${FLUTTER_VERSION}
|
|
||||||
before_script:
|
before_script:
|
||||||
- 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 -y
|
sudo apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install keyboard-configuration -y && 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 -y,
|
||||||
script: [flutter build linux --release]
|
]
|
||||||
|
script: [./scripts/build-linux.sh]
|
||||||
tags:
|
tags:
|
||||||
- docker
|
- docker
|
||||||
- famedly
|
- famedly
|
||||||
@ -298,9 +252,8 @@ build_linux_x86:
|
|||||||
|
|
||||||
build_linux_arm64:
|
build_linux_arm64:
|
||||||
stage: build
|
stage: build
|
||||||
before_script:
|
before_script: [flutter upgrade]
|
||||||
- flutter upgrade $FLUTTER_VERSION --force
|
script: [./scripts/build-linux.sh]
|
||||||
script: [flutter build linux --release]
|
|
||||||
tags: [docker_arm64]
|
tags: [docker_arm64]
|
||||||
only:
|
only:
|
||||||
- main
|
- main
|
||||||
@ -314,6 +267,8 @@ build_linux_arm64:
|
|||||||
update_dependencies:
|
update_dependencies:
|
||||||
stage: build
|
stage: build
|
||||||
needs: []
|
needs: []
|
||||||
|
tags:
|
||||||
|
- docker
|
||||||
only:
|
only:
|
||||||
- schedules
|
- schedules
|
||||||
variables:
|
variables:
|
||||||
@ -338,6 +293,9 @@ update_dependencies:
|
|||||||
.release:
|
.release:
|
||||||
stage: deploy
|
stage: deploy
|
||||||
image: curlimages/curl:latest
|
image: curlimages/curl:latest
|
||||||
|
tags:
|
||||||
|
- docker
|
||||||
|
- famedly
|
||||||
rules:
|
rules:
|
||||||
- if: '$CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/'
|
- if: '$CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/'
|
||||||
- if: '$CI_COMMIT_TAG =~ /^rc\d+\.\d+\.\d+-\d+$/'
|
- if: '$CI_COMMIT_TAG =~ /^rc\d+\.\d+\.\d+-\d+$/'
|
||||||
@ -350,29 +308,28 @@ upload_android:
|
|||||||
extends: .release
|
extends: .release
|
||||||
script:
|
script:
|
||||||
- |
|
- |
|
||||||
curl --fail-with-body --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file build/app/outputs/apk/release/app-release.apk ${PACKAGE_REGISTRY_URL}/fluffychat.apk
|
curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file build/android/app-release.apk ${PACKAGE_REGISTRY_URL}/fluffychat.apk
|
||||||
|
|
||||||
upload_web:
|
upload_web:
|
||||||
extends: .release
|
extends: .release
|
||||||
script:
|
script:
|
||||||
- tar czf package.tar.gz -C build/web/ .
|
- tar czf package.tar.gz -C build/web/ .
|
||||||
- |
|
- |
|
||||||
curl --fail-with-body --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file package.tar.gz ${PACKAGE_REGISTRY_URL}/fluffychat-web.tar.gz
|
curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file package.tar.gz ${PACKAGE_REGISTRY_URL}/fluffychat-web.tar.gz
|
||||||
|
|
||||||
upload_linux_x86:
|
upload_linux_x86:
|
||||||
extends: .release
|
extends: .release
|
||||||
script:
|
script:
|
||||||
- tar czf package.tar.gz -C build/linux/x64/release/bundle/ .
|
- tar czf package.tar.gz -C build/linux/x64/release/bundle/ .
|
||||||
- |
|
- |
|
||||||
curl --fail-with-body --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file package.tar.gz ${PACKAGE_REGISTRY_URL}/fluffychat-linux-x86.tar.gz
|
curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file package.tar.gz ${PACKAGE_REGISTRY_URL}/fluffychat-linux-x86.tar.gz
|
||||||
|
|
||||||
upload_linux_arm64:
|
upload_linux_arm64:
|
||||||
extends: .release
|
extends: .release
|
||||||
script:
|
script:
|
||||||
- tar czf package.tar.gz -C build/linux/arm64/release/bundle/ .
|
- tar czf package.tar.gz -C build/linux/arm64/release/bundle/ .
|
||||||
- |
|
- |
|
||||||
curl --fail-with-body --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file package.tar.gz ${PACKAGE_REGISTRY_URL}/fluffychat-linux-arm64.tar.gz
|
curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file package.tar.gz ${PACKAGE_REGISTRY_URL}/fluffychat-linux-arm64.tar.gz
|
||||||
allow_failure: true
|
|
||||||
|
|
||||||
upload_windows:
|
upload_windows:
|
||||||
extends: .release
|
extends: .release
|
||||||
@ -382,9 +339,8 @@ upload_windows:
|
|||||||
- mv build/windows/runner/Release/fluffychat.msix fluffychat.msix
|
- mv build/windows/runner/Release/fluffychat.msix fluffychat.msix
|
||||||
- cd build/windows/runner/Release; zip -r ../../../../package.zip . ; cd -
|
- cd build/windows/runner/Release; zip -r ../../../../package.zip . ; cd -
|
||||||
- |
|
- |
|
||||||
curl --fail-with-body --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file package.zip ${PACKAGE_REGISTRY_URL}/fluffychat-windows.zip
|
curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file package.zip ${PACKAGE_REGISTRY_URL}/fluffychat-windows.zip
|
||||||
curl --fail-with-body --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file fluffychat.msix ${PACKAGE_REGISTRY_URL}/fluffychat-windows.msix
|
curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file fluffychat.msix ${PACKAGE_REGISTRY_URL}/fluffychat-windows.msix
|
||||||
allow_failure: true
|
|
||||||
|
|
||||||
deploy_playstore:
|
deploy_playstore:
|
||||||
stage: deploy
|
stage: deploy
|
||||||
|
|||||||
25
.metadata
@ -4,7 +4,7 @@
|
|||||||
# This file should be version controlled.
|
# This file should be version controlled.
|
||||||
|
|
||||||
version:
|
version:
|
||||||
revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
|
revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849
|
||||||
channel: stable
|
channel: stable
|
||||||
|
|
||||||
project_type: app
|
project_type: app
|
||||||
@ -13,11 +13,26 @@ project_type: app
|
|||||||
migration:
|
migration:
|
||||||
platforms:
|
platforms:
|
||||||
- platform: root
|
- platform: root
|
||||||
create_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
|
create_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849
|
||||||
base_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
|
base_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849
|
||||||
|
- platform: android
|
||||||
|
create_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849
|
||||||
|
base_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849
|
||||||
|
- platform: ios
|
||||||
|
create_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849
|
||||||
|
base_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849
|
||||||
|
- platform: linux
|
||||||
|
create_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849
|
||||||
|
base_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849
|
||||||
- platform: macos
|
- platform: macos
|
||||||
create_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
|
create_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849
|
||||||
base_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
|
base_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849
|
||||||
|
- platform: web
|
||||||
|
create_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849
|
||||||
|
base_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849
|
||||||
|
- platform: windows
|
||||||
|
create_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849
|
||||||
|
base_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849
|
||||||
|
|
||||||
# User provided section
|
# User provided section
|
||||||
|
|
||||||
|
|||||||
226
CHANGELOG.md
@ -1,229 +1,3 @@
|
|||||||
## v1.12.0
|
|
||||||
- Added translation using Weblate (Toki Pona) (Mæve Rey)
|
|
||||||
- Translated using Weblate (Arabic) (Rex_sa)
|
|
||||||
- Translated using Weblate (Chinese (Simplified)) (Eric)
|
|
||||||
- Translated using Weblate (Croatian) (Milo Ivir)
|
|
||||||
- Translated using Weblate (Estonian) (Priit Jõerüüt)
|
|
||||||
- Translated using Weblate (Galician) (josé m)
|
|
||||||
- Translated using Weblate (Indonesian) (Linerly)
|
|
||||||
- Translated using Weblate (Polish) (lauren n. liberda)
|
|
||||||
- Translated using Weblate (Romanian) (Riley)
|
|
||||||
- Translated using Weblate (Russian) (DarkCoder15)
|
|
||||||
- Translated using Weblate (Spanish) (José Muñoz)
|
|
||||||
- Translated using Weblate (Ukrainian) (Ihor Hordiichuk)
|
|
||||||
- build: Remove dependency overwrite for ffi (Krille)
|
|
||||||
- build: Update dependencies (Krille)
|
|
||||||
- builds: Change minsdkversion of Android from 16 to 19 (Krille)
|
|
||||||
- builds: Do not allow failure for linux x86 (Krille)
|
|
||||||
- builds: Do not use verbose mode on building linux (Krille)
|
|
||||||
- builds: Linux with flutter 3.10 (Krille)
|
|
||||||
- builds: Remove workaround for building linux arm64 (Krille)
|
|
||||||
- builds: Update file_picker to 5.3.0 (Krille)
|
|
||||||
- builds: Update flutter table html (Krille)
|
|
||||||
- builds: Update flutter_html (Krille)
|
|
||||||
- builds: migrate to dart 3.0/flutter 3.10 (lauren n. liberda)
|
|
||||||
- chore: Add missing blockquote style (Krille)
|
|
||||||
- chore: Allow failure in build linux for now (Krille)
|
|
||||||
- chore: Ask for storage persistence (Krille)
|
|
||||||
- chore: Clean unused translations (Malin Errenst)
|
|
||||||
- chore: Enhance room pills (Krille)
|
|
||||||
- chore: Minor code clean up (Krille)
|
|
||||||
- chore: Update flutter webrtc (Krille)
|
|
||||||
- chore: Upgrade to Flutter 3.10.1 (Malin Errenst)
|
|
||||||
- chore: change release curl calls to use --fail-with-body (Tim Flink)
|
|
||||||
- chore: update macOS icons and add build script (TheOneWithTheBraid)
|
|
||||||
- design: Replace anime images with neutral cupertino icons (Krille)
|
|
||||||
- feat: Add toggle to mute notifications from chat groups (fbievan)
|
|
||||||
- feat: Allow ruby tags in html (Krille)
|
|
||||||
- feat: Display progress value for initial sync (Krille)
|
|
||||||
- feat: Implement new error reporting tool when critical features break like playing audio or video messages or opening a chat (Krille)
|
|
||||||
- feat: clean up macOS build metadata (TheOneWithTheBraid)
|
|
||||||
- feat: set display information correctly (TheOneWithTheBraid)
|
|
||||||
- feat: update macOS build files (TheOneWithTheBraid)
|
|
||||||
- feat: update macOS build information for macOS Ventura (TheOneWithTheBraid)
|
|
||||||
- fix "Unhandled Exception: VRouter.of(context) was called with a context which does not contain a VRouter." (Lauren N. Liberda)
|
|
||||||
- fix: Broken arb file (Krille)
|
|
||||||
- fix: Do not unnecessary request all members in public rooms (Krille)
|
|
||||||
- fix: Remove wrong rendered linebreak in html (Krille)
|
|
||||||
- fix: Scroll down button (Krille)
|
|
||||||
- fix: Scroll up and scroll down buttons in chat list (Krille)
|
|
||||||
- fix: Scrolldown button (Krille)
|
|
||||||
- fix: Too long file name cause a render overflow (Skying)
|
|
||||||
- fix: Try to reload timeline on IOException (Krille)
|
|
||||||
- fix: User pills (Krille)
|
|
||||||
- fix: broken CI artifact uploads (TheOneWithTheBraid)
|
|
||||||
- fix: custom emote placeholder (TheOneWithTheBraid)
|
|
||||||
- fix: path of libolm (TheOneWithTheBraid)
|
|
||||||
- fix: Quick account switching (JHansen)
|
|
||||||
- fix: read reciepts (JHansen)
|
|
||||||
- perf: Use valuenotifier to not rebuild chatlist (Krille)
|
|
||||||
- refactor: Reimplement flutter matrix html locally (Krille)
|
|
||||||
- refactor: Update Roboto and Noto Emoji (The one with the Braid)
|
|
||||||
- refactor: Use AnimatedSize for FAB (Krille)
|
|
||||||
- refactor: Use DateTime for weekday localization (Malin Errenst)
|
|
||||||
|
|
||||||
## v1.11.2
|
|
||||||
- Translated using Weblate (Croatian) (Milo Ivir)
|
|
||||||
- Translated using Weblate (Dutch) (Jelv)
|
|
||||||
- Translated using Weblate (Estonian) (Priit Jõerüüt)
|
|
||||||
- Translated using Weblate (Galician) (josé m)
|
|
||||||
- Translated using Weblate (Polish) (Eryk Michalak)
|
|
||||||
- Translated using Weblate (Turkish) (Oğuz Ersen)
|
|
||||||
- Translated using Weblate (Ukrainian) (Ihor Hordiichuk)
|
|
||||||
- feat: Permission dialog before open link in browser (Krille)
|
|
||||||
- fix: Chats do not load (Krille)
|
|
||||||
|
|
||||||
## v1.11.1 - 2023-04-20
|
|
||||||
- fix: Download files on web and iOS with correct mimetype
|
|
||||||
|
|
||||||
## v1.11.0 - 2023-04-14
|
|
||||||
- feat: Add visual read marker (Krille)
|
|
||||||
- feat: Jump to last read event (Krille)
|
|
||||||
- feat: Use fragmented timeline to jump to event (Krille)
|
|
||||||
- feat: change to flutterwebauth2 (ShootingStarDragons)
|
|
||||||
- fix: Join public room (Krille)
|
|
||||||
- fix: Set fcm priority to max on android (Krille)
|
|
||||||
- refactor: CI scripts and old workarounds for build scripts (Krille)
|
|
||||||
- refactor: Client in ChatPage (Krille)
|
|
||||||
- refactor: Not nullable room in ChatPage (Krille)
|
|
||||||
- refactor: Switch to file_picker package and get rid of some dependency overrides (Krille)
|
|
||||||
- refactor: Use correct Matrix instance (Krille)
|
|
||||||
- style: Make emptypage logo bigger (Krille)
|
|
||||||
- style: Minor adjustments for modal bottom sheets (Krille)
|
|
||||||
- style: Move chats to top (Krille)
|
|
||||||
- style: Use SliverList for chatlist (Krille)
|
|
||||||
- refactor: Container -> SizedBox.shrink() (noob_tea)
|
|
||||||
- Translated using Weblate (Chinese (Simplified)) (Eric)
|
|
||||||
- Translated using Weblate (Dutch) (Jelv)
|
|
||||||
- Translated using Weblate (Estonian) (Priit Jõerüüt)
|
|
||||||
- Translated using Weblate (French) (Anne Onyme 017)
|
|
||||||
- Translated using Weblate (Galician) (josé m)
|
|
||||||
- Translated using Weblate (Indonesian) (Linerly)
|
|
||||||
- Translated using Weblate (Persian) (Parsa)
|
|
||||||
- Translated using Weblate (Persian) (Siavash)
|
|
||||||
- Translated using Weblate (Polish) (Luna)
|
|
||||||
- Translated using Weblate (Swedish) (Kristoffer Grundström)
|
|
||||||
- Translated using Weblate (Turkish) (Oğuz Ersen)
|
|
||||||
- Translated using Weblate (Ukrainian) (Ihor Hordiichuk)
|
|
||||||
|
|
||||||
## v1.10.0 - 2023-02-25
|
|
||||||
- Added translation using Weblate (Thai) (Wphaoka)
|
|
||||||
- Added translation using Weblate (Tibetan) (Nathan Freitas)
|
|
||||||
- Default hardcoded message when l10n is not available (fabienli)
|
|
||||||
- Fix: The stable repo fingerprint (TODO the qr-code should be updated) (machiav3lli)
|
|
||||||
- Translated using Weblate (Basque) (xabirequejo)
|
|
||||||
- Translated using Weblate (Dutch) (Jelv)
|
|
||||||
- Translated using Weblate (Estonian) (Priit Jõerüüt)
|
|
||||||
- Translated using Weblate (French) (Anne Onyme 017)
|
|
||||||
- Translated using Weblate (Galician) (josé m)
|
|
||||||
- Translated using Weblate (Galician) (josé m)
|
|
||||||
- Translated using Weblate (Indonesian) (Linerly)
|
|
||||||
- Translated using Weblate (Japanese) (Suguru Hirahara)
|
|
||||||
- Translated using Weblate (Persian) (Farooq Karimi Zadeh)
|
|
||||||
- Translated using Weblate (Swedish) (Joaquim Homrighausen)
|
|
||||||
- Translated using Weblate (Turkish) (Oğuz Ersen)
|
|
||||||
- Translated using Weblate (Ukrainian) (Ihor Hordiichuk)
|
|
||||||
- chore: Disable stable for web until script is fixed (Krille)
|
|
||||||
- chore: Display warning when logout without backup (Krille)
|
|
||||||
- chore: Downgrade flutter CI version (Krille)
|
|
||||||
- chore: Follow up audioplayer on linux (Krille)
|
|
||||||
- chore: Follow up chat encryption desgin (Krille)
|
|
||||||
- chore: Follow up fix audioplayer on android (Christian Pauly)
|
|
||||||
- chore: Follow up formatting (Christian Pauly)
|
|
||||||
- chore: Follow up formatting (Krille)
|
|
||||||
- chore: Follow up remove hero animation (Krille)
|
|
||||||
- chore: Follow up secrity settings design (Krille)
|
|
||||||
- chore: Follow up settings page (Krille)
|
|
||||||
- chore: Follow up settings page design (Christian Pauly)
|
|
||||||
- chore: Follow up style adjustments (Krille)
|
|
||||||
- chore: Lookup l10n in pushhelper if null (Krille)
|
|
||||||
- chore: Update matrix package to 0.17.0 (Krille)
|
|
||||||
- chore: Update to Flutter 3.7.1 (Krille)
|
|
||||||
- docs/qr-stable.svg: update the QR code (Aminda Suomalainen)
|
|
||||||
- feat: Enable audioplayer for web and linux (Christian Pauly)
|
|
||||||
- fix: Display error when user tries to send too large file (Christian Pauly)
|
|
||||||
- refactor: Do only instantiate AudioPlayer() object when in use (Christian Pauly)
|
|
||||||
- refactor: Remove syncstatus verbose logs (Christian Pauly)
|
|
||||||
- refactor: Store cached files in tmp directory so OS will clear file cache from time to time (Krille)
|
|
||||||
- style: Adjust key verification dialog (Christian Pauly)
|
|
||||||
- style: Bootstrap design adjustments (Christian Pauly)
|
|
||||||
- style: Encryption page adjustments (Christian Pauly)
|
|
||||||
- style: Enhance user device settings design (Krille)
|
|
||||||
- style: Enhanced chat details design (Krille)
|
|
||||||
- style: Give chat list list tiles rounded corners (Krille)
|
|
||||||
- style: Link underline color (Christian Pauly)
|
|
||||||
- style: Make adaptive bottom sheets scrollable by default (Krille)
|
|
||||||
- style: Make invite page more pretty (Krille)
|
|
||||||
- style: New settings design (Krille)
|
|
||||||
- style: Nicer chips in encryption settings and icons showing device status (Krille)
|
|
||||||
- style: Use emojis on web as well (Christian Pauly)
|
|
||||||
- style: Use robotomono to display device keys (Christian Pauly)
|
|
||||||
- utils/url_launcher: force opening http(s) links in external browser (Marcus Hoffmann)
|
|
||||||
|
|
||||||
## v1.9.0 - 2023-01-29
|
|
||||||
- Translated using Weblate (Czech) (Michal Bedáň)
|
|
||||||
- Translated using Weblate (Czech) (grreby)
|
|
||||||
- Translated using Weblate (Dutch) (Jelv)
|
|
||||||
- Translated using Weblate (Estonian) (Priit Jõerüüt)
|
|
||||||
- Translated using Weblate (Galician) (josé m)
|
|
||||||
- Translated using Weblate (German) (Christian)
|
|
||||||
- Translated using Weblate (German) (Vri 🌈)
|
|
||||||
- Translated using Weblate (Indonesian) (Linerly)
|
|
||||||
- Translated using Weblate (Korean) (Youngbin Han)
|
|
||||||
- Translated using Weblate (Polish) (Wiktor)
|
|
||||||
- Translated using Weblate (Turkish) (Oğuz Ersen)
|
|
||||||
- Translated using Weblate (Ukrainian) (Ihor Hordiichuk)
|
|
||||||
- chore: Change invite link textfield label (Krille)
|
|
||||||
- chore: Remove unused dependency (Krille)
|
|
||||||
- chore: Remove unused translations (Krille)
|
|
||||||
- chore: Update Matrix SDK and refactor (Krille)
|
|
||||||
- chore: Update dependencies (Krille)
|
|
||||||
- chore: Update flutter_map (Krille)
|
|
||||||
- chore: add integration tests (TheOneWithTheBraid)
|
|
||||||
- chore: add integration tests for spaces (TheOneWithTheBraid)
|
|
||||||
- design: More clear chat background and rounded popup menu (Krille)
|
|
||||||
- design: Nicer navigationrail (Krille)
|
|
||||||
- design: Upgrade to Flutter 3.7
|
|
||||||
- feat: Bring back disabling the header bar on Linux desktop (q234rty)
|
|
||||||
- feat: Nicer design for abandonded DM rooms (Christian Pauly)
|
|
||||||
- fix: Archive (Krille)
|
|
||||||
- fix: Shared preferences package for flutter 3.7 (Christian Pauly)
|
|
||||||
- fix: permission of web builds (TheOneWithTheBraid)
|
|
||||||
- fix: Notification Settings (Krille)
|
|
||||||
- refactor: Migrate to Flutter 3.7.0 (Christian Pauly)
|
|
||||||
- refactor: Same animations everywhere in app (Krille)
|
|
||||||
- refactor: Stories header with futurebuilder (Krille)
|
|
||||||
- refactor: disable some redundant tests (TheOneWithTheBraid)
|
|
||||||
- style: Animate in out search results (Krille)
|
|
||||||
- style: New modal bottom sheets (Krille)
|
|
||||||
- style: Redesign public room bottomsheets (Krille)
|
|
||||||
|
|
||||||
## v1.8.0 2022-12-30
|
|
||||||
- Added translation using Weblate (Yue (yue_HK)) (Raatty)
|
|
||||||
- Translated using Weblate (Chinese (Simplified)) (Mike Evans)
|
|
||||||
- Translated using Weblate (Estonian) (Priit Jõerüüt)
|
|
||||||
- Translated using Weblate (French) (Anne Onyme 017)
|
|
||||||
- Translated using Weblate (Indonesian) (Linerly)
|
|
||||||
- Translated using Weblate (Turkish) (Oğuz Ersen)
|
|
||||||
- Translated using Weblate (Ukrainian) (Ihor Hordiichuk)
|
|
||||||
- design: New encryption page (Krille Fear)
|
|
||||||
- feat: Add audio message support to linux (Krille Fear)
|
|
||||||
- feat: Use Android system accent color (Krille Fear)
|
|
||||||
- feat: include olm to Windows builds (TheOneWithTheBraid)
|
|
||||||
- feat: Store drafts (Krille)
|
|
||||||
- fix: Android push notification follow-up (TheOneWithTheBraid)
|
|
||||||
- fix: Content banner (Krille Fear)
|
|
||||||
- fix: Correct redacted by username (Krille Fear)
|
|
||||||
- fix: Do not setup push on every app resume (Krille Fear)
|
|
||||||
- fix: Encryption button is orange in public rooms (Krille Fear)
|
|
||||||
- fix: File event design (Krille Fear)
|
|
||||||
- fix: Hide google services warning after marked (Krille Fear)
|
|
||||||
- fix: Improve story page appearance (Reinhart Previano Koentjoro)
|
|
||||||
- fix: Libhandy windows (Krille Fear)
|
|
||||||
- fix: Monochromatic icon rendering for Android 13+ (Reinhart Previano Koentjoro)
|
|
||||||
- fix: homeserver error text not visible in app bar (TheOneWithTheBraid)
|
|
||||||
- fix: minor issues in room list (TheOneWithTheBraid)
|
|
||||||
|
|
||||||
## v1.7.2 2022-12-19
|
## v1.7.2 2022-12-19
|
||||||
Update dependencies and translations.
|
Update dependencies and translations.
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
FROM ghcr.io/cirruslabs/flutter as builder
|
FROM cirrusci/flutter as builder
|
||||||
RUN sudo apt update && sudo apt install curl -y
|
RUN sudo apt update && sudo apt install curl -y
|
||||||
COPY . /app
|
COPY . /app
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|||||||
@ -8,7 +8,6 @@ linter:
|
|||||||
- prefer_final_locals
|
- prefer_final_locals
|
||||||
- prefer_final_in_for_each
|
- prefer_final_in_for_each
|
||||||
- sort_pub_dependencies
|
- sort_pub_dependencies
|
||||||
- require_trailing_commas
|
|
||||||
|
|
||||||
analyzer:
|
analyzer:
|
||||||
errors:
|
errors:
|
||||||
|
|||||||
@ -44,7 +44,7 @@ android {
|
|||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "chat.fluffy.fluffychat"
|
applicationId "chat.fluffy.fluffychat"
|
||||||
minSdkVersion 19
|
minSdkVersion 16
|
||||||
targetSdkVersion 31
|
targetSdkVersion 31
|
||||||
versionCode flutterVersionCode.toInteger()
|
versionCode flutterVersionCode.toInteger()
|
||||||
versionName flutterVersionName
|
versionName flutterVersionName
|
||||||
|
|||||||
@ -93,9 +93,8 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity android:name="com.linusu.flutter_web_auth.CallbackActivity"
|
||||||
android:name="com.linusu.flutter_web_auth_2.CallbackActivity"
|
android:exported="true">
|
||||||
android:exported="true">
|
|
||||||
<intent-filter android:label="flutter_web_auth">
|
<intent-filter android:label="flutter_web_auth">
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
|||||||
@ -2,5 +2,5 @@
|
|||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<background android:drawable="@color/ic_launcher_background"/>
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
<monochrome android:drawable="@drawable/ic_launcher_monochrome"/>
|
<monochrome android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
||||||
@ -1,5 +1,5 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.8.0'
|
ext.kotlin_version = '1.6.10'
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
@ -27,6 +27,6 @@ subprojects {
|
|||||||
project.evaluationDependsOn(':app')
|
project.evaluationDependsOn(':app')
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register("clean", Delete) {
|
task clean(type: Delete) {
|
||||||
delete rootProject.buildDir
|
delete rootProject.buildDir
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,17 +5,12 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="0: update_fastlane" time="1.455419">
|
<testcase classname="fastlane.lanes" name="0: update_fastlane" time="0.000202">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="1: default_platform" time="0.000127">
|
<testcase classname="fastlane.lanes" name="1: default_platform" time="7.9e-05">
|
||||||
|
|
||||||
</testcase>
|
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="2: google_play_track_version_codes" time="2.638619">
|
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 37 KiB |
@ -1,25 +1,30 @@
|
|||||||
{
|
{
|
||||||
"@@last_modified": "2021-08-14 12:41:10.154280",
|
"@@last_modified": "2021-08-14 12:41:10.154280",
|
||||||
"about": "সম্পর্কে",
|
"about": "সম্পর্কে",
|
||||||
"@about": {
|
"@about": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
"accept": "স্বীকার করি",
|
"accept": "স্বীকার করি",
|
||||||
"@accept": {
|
"@accept": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
"acceptedTheInvitation": "{username} আমন্ত্রণ গ্রহণ করেছে",
|
"acceptedTheInvitation": "{username} আমন্ত্রণ গ্রহণ করেছে",
|
||||||
"@acceptedTheInvitation": {
|
"@acceptedTheInvitation": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"username": {}
|
"username": {}
|
||||||
}
|
|
||||||
},
|
|
||||||
"account": "অ্যাকাউন্ট",
|
|
||||||
"@account": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"account": "অ্যাকাউন্ট",
|
||||||
|
"@account": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"accountInformation": "অ্যাকাউন্ট তথ্য",
|
||||||
|
"@accountInformation": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -1 +0,0 @@
|
|||||||
{}
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{}
|
|
||||||
@ -1 +1 @@
|
|||||||
{}
|
{}
|
||||||
|
|||||||
1551
assets/l10n/intl_hy.arb
Normal file
@ -1,120 +1,155 @@
|
|||||||
{
|
{
|
||||||
"@@last_modified": "2021-08-14 12:41:09.940318",
|
"@@last_modified": "2021-08-14 12:41:09.940318",
|
||||||
"copiedToClipboard": "Copiada para a área de transferência",
|
"copiedToClipboard": "Copiada para a área de transferência",
|
||||||
"@copiedToClipboard": {
|
"@copiedToClipboard": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
"login": "Iniciar sessão",
|
"login": "Iniciar sessão",
|
||||||
"@login": {
|
"@login": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
"about": "Sobre",
|
"monday": "segunda-feira",
|
||||||
"@about": {
|
"@monday": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
"admin": "Admin",
|
"saturday": "sábado",
|
||||||
"@admin": {
|
"@saturday": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
"areYouSure": "Tens a certeza?",
|
"wednesday": "quarta-feira",
|
||||||
"@areYouSure": {
|
"@wednesday": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
"notifications": "Notificações",
|
"about": "Sobre",
|
||||||
"@notifications": {
|
"@about": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
"account": "Conta",
|
"admin": "Admin",
|
||||||
"@account": {
|
"@admin": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
"cancel": "Cancelar",
|
"areYouSure": "Tens a certeza?",
|
||||||
"@cancel": {
|
"@areYouSure": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
"delete": "Eliminar",
|
"notifications": "Notificações",
|
||||||
"@delete": {
|
"@notifications": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
"dateAndTimeOfDay": "{date}, {timeOfDay}",
|
"account": "Conta",
|
||||||
"@dateAndTimeOfDay": {
|
"@account": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {
|
"placeholders": {}
|
||||||
"date": {},
|
},
|
||||||
"timeOfDay": {}
|
"cancel": "Cancelar",
|
||||||
}
|
"@cancel": {
|
||||||
},
|
"type": "text",
|
||||||
"dateWithYear": "{day}-{month}-{year}",
|
"placeholders": {}
|
||||||
"@dateWithYear": {
|
},
|
||||||
"type": "text",
|
"delete": "Eliminar",
|
||||||
"placeholders": {
|
"@delete": {
|
||||||
"year": {},
|
"type": "text",
|
||||||
"month": {},
|
"placeholders": {}
|
||||||
"day": {}
|
},
|
||||||
}
|
"dateAndTimeOfDay": "{date}, {timeOfDay}",
|
||||||
},
|
"@dateAndTimeOfDay": {
|
||||||
"help": "Ajuda",
|
"type": "text",
|
||||||
"@help": {
|
"placeholders": {
|
||||||
"type": "text",
|
"date": {},
|
||||||
"placeholders": {}
|
"timeOfDay": {}
|
||||||
},
|
|
||||||
"messages": "Mensagens",
|
|
||||||
"@messages": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"reason": "Razão",
|
|
||||||
"@reason": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"privacy": "Privacidade",
|
|
||||||
"@privacy": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"openCamera": "Abrir câmara",
|
|
||||||
"@openCamera": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"settings": "Configurações",
|
|
||||||
"@settings": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"logout": "Terminar sessão",
|
|
||||||
"@logout": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"search": "Pesquisar",
|
|
||||||
"@search": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"users": "Utilizadores",
|
|
||||||
"@users": {},
|
|
||||||
"close": "Fechar",
|
|
||||||
"@close": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"dateWithoutYear": "{day}-{month}",
|
|
||||||
"@dateWithoutYear": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {
|
|
||||||
"month": {},
|
|
||||||
"day": {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"dateWithYear": "{day}-{month}-{year}",
|
||||||
|
"@dateWithYear": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {
|
||||||
|
"year": {},
|
||||||
|
"month": {},
|
||||||
|
"day": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"help": "Ajuda",
|
||||||
|
"@help": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"messages": "Mensagens",
|
||||||
|
"@messages": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"reason": "Razão",
|
||||||
|
"@reason": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"privacy": "Privacidade",
|
||||||
|
"@privacy": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"openCamera": "Abrir câmara",
|
||||||
|
"@openCamera": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"settings": "Configurações",
|
||||||
|
"@settings": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"tuesday": "terça-feira",
|
||||||
|
"@tuesday": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"logout": "Terminar sessão",
|
||||||
|
"@logout": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"search": "Pesquisar",
|
||||||
|
"@search": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"sunday": "domingo",
|
||||||
|
"@sunday": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"users": "Utilizadores",
|
||||||
|
"@users": {},
|
||||||
|
"close": "Fechar",
|
||||||
|
"@close": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"dateWithoutYear": "{day}-{month}",
|
||||||
|
"@dateWithoutYear": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {
|
||||||
|
"month": {},
|
||||||
|
"day": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"friday": "sexta-feira",
|
||||||
|
"@friday": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"thursday": "quinta-feira",
|
||||||
|
"@thursday": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
374
assets/l10n/intl_si.arb
Normal file
@ -0,0 +1,374 @@
|
|||||||
|
{
|
||||||
|
"@@last_modified": "2021-08-14 12:41:09.895217",
|
||||||
|
"about": "පිළිබඳව",
|
||||||
|
"@about": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"accept": "පිළිගන්න",
|
||||||
|
"@accept": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"account": "ගිණුම",
|
||||||
|
"@account": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"accountInformation": "ගිණුමේ තොරතුරු",
|
||||||
|
"@accountInformation": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"addEmail": "වි-තැපෑල එකතු කරන්න",
|
||||||
|
"@addEmail": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"admin": "පරිපාලක",
|
||||||
|
"@admin": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"allChats": "සියලුම සංවාද",
|
||||||
|
"@allChats": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"alreadyHaveAnAccount": "දැනටමත් ගිණුමක් තිබේද?",
|
||||||
|
"@alreadyHaveAnAccount": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"anyoneCanJoin": "ඕනෑම කෙනෙකුට එක්විය හැකිය",
|
||||||
|
"@anyoneCanJoin": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"archive": "සංරක්ෂිතය",
|
||||||
|
"@archive": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"archivedRoom": "සංරක්ෂිත කාමරය",
|
||||||
|
"@archivedRoom": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"areGuestsAllowedToJoin": "ආගන්තුක පරිශීලකයින්ට එක්වීමට අවසර තිබේද",
|
||||||
|
"@areGuestsAllowedToJoin": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"areYouSure": "ඔබට විශ්වාසද?",
|
||||||
|
"@areYouSure": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"areYouSureYouWantToLogout": "ඔබට නික්මීමට අවශ්ය බව විශ්වාසද?",
|
||||||
|
"@areYouSureYouWantToLogout": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"audioPlayerPlay": "ධාවනය",
|
||||||
|
"@audioPlayerPlay": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"blockDevice": "උපාංගය අවහිර කරන්න",
|
||||||
|
"@blockDevice": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"cachedKeys": "යතුරු නිහිතගතයි",
|
||||||
|
"@cachedKeys": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"cancel": "අවලංගු කරන්න",
|
||||||
|
"@cancel": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"changeDeviceName": "උපාංගයේ නම වෙනස් කරන්න",
|
||||||
|
"@changeDeviceName": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"changePassword": "මුරපදය වෙනස් කරන්න",
|
||||||
|
"@changePassword": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"chat": "සංවාදය",
|
||||||
|
"@chat": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"chatBackup": "සංවාද උපස්ථය",
|
||||||
|
"@chatBackup": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"chatDetails": "සංවාදයේ විස්තර",
|
||||||
|
"@chatDetails": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"chats": "සංවාද",
|
||||||
|
"@chats": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"chooseAStrongPassword": "ශක්තිමත් මුරපදයක් තෝරන්න",
|
||||||
|
"@chooseAStrongPassword": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"chooseAUsername": "පරිශීලක නාමයක් තෝරන්න",
|
||||||
|
"@chooseAUsername": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"clearArchive": "සංරක්ෂිතය හිස් කරන්න",
|
||||||
|
"@clearArchive": {},
|
||||||
|
"close": "වසන්න",
|
||||||
|
"@close": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"commandHint_join": "දී ඇති කාමරයට එක්වන්න",
|
||||||
|
"@commandHint_join": {
|
||||||
|
"type": "text",
|
||||||
|
"description": "Usage hint for the command /join"
|
||||||
|
},
|
||||||
|
"commandHint_leave": "මෙම කාමරය හැරයන්න",
|
||||||
|
"@commandHint_leave": {
|
||||||
|
"type": "text",
|
||||||
|
"description": "Usage hint for the command /leave"
|
||||||
|
},
|
||||||
|
"commandInvalid": "විධානය වලංගු නොවේ",
|
||||||
|
"@commandInvalid": {
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
"commandMissing": "{{command} විධානයක් නොවේ.",
|
||||||
|
"@commandMissing": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {
|
||||||
|
"command": {}
|
||||||
|
},
|
||||||
|
"description": "State that {command} is not a valid /command."
|
||||||
|
},
|
||||||
|
"compareEmojiMatch": "සසඳා බලා පහත දැක්වෙන ඉමොජි අනෙක් උපාංගයට නිසැකවම ගැලපෙන බවට වග බලා ගන්න:",
|
||||||
|
"@compareEmojiMatch": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"compareNumbersMatch": "සංසන්දනය කර පහත දැක්වෙන අංක අනෙක් උපාංගට නිසැකව ගැලපෙන බවට වග බලා ගන්න:",
|
||||||
|
"@compareNumbersMatch": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"confirm": "තහවුරු කරන්න",
|
||||||
|
"@confirm": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"connect": "සබඳින්න",
|
||||||
|
"@connect": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"connectionAttemptFailed": "සබැඳීමේ උත්සාහය අසාර්ථකයි",
|
||||||
|
"@connectionAttemptFailed": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"contactHasBeenInvitedToTheGroup": "සමූහය වෙත සබඳතාවයකට ආරාධනා කර ඇත",
|
||||||
|
"@contactHasBeenInvitedToTheGroup": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"copy": "පිටපත්",
|
||||||
|
"@copy": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"create": "සාදන්න",
|
||||||
|
"@create": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"createAccountNow": "දැන් ගිණුමක් සාදන්න",
|
||||||
|
"@createAccountNow": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"createNewGroup": "නව සමූහයක් සාදන්න",
|
||||||
|
"@createNewGroup": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"donate": "පරිත්යාග",
|
||||||
|
"@donate": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"encryption": "සංකේතාංකනය",
|
||||||
|
"@encryption": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"everythingReady": "සියල්ල සූදානම්!",
|
||||||
|
"@everythingReady": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"fontSize": "මුද්රණඅකුරේ ප්රමාණය",
|
||||||
|
"@fontSize": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"goToTheNewRoom": "නව කාමරයට යන්න",
|
||||||
|
"@goToTheNewRoom": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"joinRoom": "කාමරයට එක්වන්න",
|
||||||
|
"@joinRoom": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"keysCached": "යතුරු නිහිතගත යි",
|
||||||
|
"@keysCached": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"next": "ඊලඟ",
|
||||||
|
"@next": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"noPublicRoomsFound": "ප්රසිද්ධ කාමර හමු නොවිණි…",
|
||||||
|
"@noPublicRoomsFound": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"people": "මිනිසුන්",
|
||||||
|
"@people": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"publicGroups": "ප්රසිද්ධ සමූහ",
|
||||||
|
"@publicGroups": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"removeDevice": "උපාංගය ඉවත්කරන්න",
|
||||||
|
"@removeDevice": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"roomVersion": "කාමරයේ අනුවාදය",
|
||||||
|
"@roomVersion": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"savedFileAs": "ලෙස ගොනුව සුරකින්න {filename}",
|
||||||
|
"@savedFileAs": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {
|
||||||
|
"filename": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"saveFile": "ගොනුව සුරකින්න",
|
||||||
|
"@saveFile": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"saveFileToFolder": "ගොනුව මෙම බහාලුමට සුරකින්න",
|
||||||
|
"@saveFileToFolder": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"securityKey": "ආරක්ෂක යතුර",
|
||||||
|
"@securityKey": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"securityKeyLost": "ආරක්ෂක යතුර නැතිවුනාද?",
|
||||||
|
"@securityKeyLost": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"send": "යවන්න",
|
||||||
|
"@send": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"showPassword": "මුරපදය පෙන්වන්න",
|
||||||
|
"@showPassword": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"sunday": "ඉරිදා",
|
||||||
|
"@sunday": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"username": "පරිශීලක නාමය",
|
||||||
|
"@username": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"videoCall": "දෘශ්ය ඇමතුම",
|
||||||
|
"@videoCall": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"wallpaper": "බිතුපත",
|
||||||
|
"@wallpaper": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"warning": "අවවාදයයි!",
|
||||||
|
"@warning": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"wednesday": "බදාදා",
|
||||||
|
"@wednesday": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"writeAMessage": "පණිවිඩයක් ලියන්න…",
|
||||||
|
"@writeAMessage": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"yes": "ඔව්",
|
||||||
|
"@yes": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"you": "ඔබ",
|
||||||
|
"@you": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"yourOwnUsername": "ඔබට හිමි පරිශීලකනාමය",
|
||||||
|
"@yourOwnUsername": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"zoomIn": "විශාලනය",
|
||||||
|
"@zoomIn": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"zoomOut": "කුඩාලනය",
|
||||||
|
"@zoomOut": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,20 +1,20 @@
|
|||||||
{
|
{
|
||||||
"@@last_modified": "2021-08-14 12:41:09.826673",
|
"@@last_modified": "2021-08-14 12:41:09.826673",
|
||||||
"acceptedTheInvitation": "{username} அழைப்பை ஏற்றுக்கொண்டார்",
|
"acceptedTheInvitation": "{username} அழைப்பை ஏற்றுக்கொண்டார்",
|
||||||
"@acceptedTheInvitation": {
|
"@acceptedTheInvitation": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"username": {}
|
"username": {}
|
||||||
}
|
|
||||||
},
|
|
||||||
"accept": "ஏற்றுக்கொள்",
|
|
||||||
"@accept": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"about": "பற்றி",
|
|
||||||
"@about": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"accept": "ஏற்றுக்கொள்",
|
||||||
|
"@accept": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"about": "பற்றி",
|
||||||
|
"@about": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1 +0,0 @@
|
|||||||
{}
|
|
||||||
|
Before Width: | Height: | Size: 146 KiB After Width: | Height: | Size: 212 KiB |
BIN
assets/private_chat_wallpaper.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
docs/Kofi_pixel_logo.png
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
@ -7,9 +7,11 @@ are also published on it.
|
|||||||
|
|
||||||
Easiest way to add the Repository is to either **scan the QR-Code** or if you are on your phone **directly click it**.
|
Easiest way to add the Repository is to either **scan the QR-Code** or if you are on your phone **directly click it**.
|
||||||
|
|
||||||
<a href="fdroidrepos://fluffychat.im/repo/stable/repo/?fingerprint=5EDB5C4395B2F2D9BA682F6A1D275170CCE5365A6FA27D2220EA8D52A6D95F07" >
|
{::nomarkdown}
|
||||||
|
<a href="fdroidrepos://fluffychat.im/repo/stable/repo/?fingerprint=8E2637AEF6697CC6DD486AF044A6EE45B1A742AE3EF56566E748CDE8BC65C1FB" >
|
||||||
<img src="qr-stable.svg" width="300" height="300"/>
|
<img src="qr-stable.svg" width="300" height="300"/>
|
||||||
</a>
|
</a>
|
||||||
|
{:/}
|
||||||
|
|
||||||
|
|
||||||
### If the QR-Code doesn't work:
|
### If the QR-Code doesn't work:
|
||||||
@ -22,11 +24,11 @@ If this still isn't working follow the next steps:
|
|||||||
2. Go to the `Settings` Tab in the Bottom bar
|
2. Go to the `Settings` Tab in the Bottom bar
|
||||||
3. Click the `Repositories` Action
|
3. Click the `Repositories` Action
|
||||||
4. Click on the plus sign at the top.
|
4. Click on the plus sign at the top.
|
||||||
5. Fill in `https://fluffychat.im/repo/stable/repo/` into the top field and `5EDB5C4395B2F2D9BA682F6A1D275170CCE5365A6FA27D2220EA8D52A6D95F07` in the bottom field.
|
5. Fill in `https://fluffychat.im/repo/stable/repo/` into the top field and `8E2637AEF6697CC6DD486AF044A6EE45B1A742AE3EF56566E748CDE8BC65C1FB` in the bottom field.
|
||||||
|
|
||||||
## What is the fingerprint?
|
## What is the fingerprint?
|
||||||
|
|
||||||
The fingerprint of the Repository is: `5EDB5C4395B2F2D9BA682F6A1D275170CCE5365A6FA27D2220EA8D52A6D95F07`
|
The fingerprint of the Repository is: `8E2637AEF6697CC6DD486AF044A6EE45B1A742AE3EF56566E748CDE8BC65C1FB`
|
||||||
|
|
||||||
# Nightly Repository
|
# Nightly Repository
|
||||||
|
|
||||||
@ -34,9 +36,11 @@ The fingerprint of the Repository is: `5EDB5C4395B2F2D9BA682F6A1D275170CCE5365A6
|
|||||||
|
|
||||||
Easiest way to add the Repository is to either **scan the QR-Code** or if you are on your phone **directly click** it.
|
Easiest way to add the Repository is to either **scan the QR-Code** or if you are on your phone **directly click** it.
|
||||||
|
|
||||||
|
{::nomarkdown}
|
||||||
<a href="fdroidrepos://fluffychat.im/repo/nightly/repo/?fingerprint=21A469657300576478B623DF99D8EB889A80BCD939ACA60A4074741BEAEC397D" >
|
<a href="fdroidrepos://fluffychat.im/repo/nightly/repo/?fingerprint=21A469657300576478B623DF99D8EB889A80BCD939ACA60A4074741BEAEC397D" >
|
||||||
<img src="qr-nightly.svg" width="300" height="300"/>
|
<img src="qr-nightly.svg" width="300" height="300"/>
|
||||||
</a>
|
</a>
|
||||||
|
{:/}
|
||||||
|
|
||||||
|
|
||||||
### If the QR-Code doesn't work:
|
### If the QR-Code doesn't work:
|
||||||
|
|||||||
646
docs/index.html
@ -1,119 +1,565 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<html>
|
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="UTF-8">
|
||||||
<title>FluffyChat Official Website</title>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="identifier-url" content="https://fluffychat.im" />
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||||
<meta name="title" content="FluffyChat Official Website" />
|
<title>FluffyChat - Official Website</title>
|
||||||
<meta name="description" content="The cutest messenger in the Matrix network" />
|
<meta name="description" content="A cute and secure chatclient for the matrix protocol">
|
||||||
<meta name="abstract" content="FluffyChat is the cutest messenger in the Matrix network" />
|
<meta name="keywords"
|
||||||
<meta name="keywords" content="FluffyChat, Matrix, Flutter, App" />
|
content="Fluffychat, Matrix, Web, Android, iOS, Desktop, Chat, Client, Chatclient, Matrix.org, Secure, E2EE, End to End, Encryption, End to End Encryption, F-Droid, Foss, FOSS, OpenSource, Free, Community, Open">
|
||||||
<meta name="author" content="Krille Fear" />
|
<script type="application/ld+json">
|
||||||
<meta name="revisit-after" content="15" />
|
{
|
||||||
<meta name="language" content="EN" />
|
"@context": "https://schema.org",
|
||||||
<meta name="robots" content="All" />
|
"@type": "MobileApplication",
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
"name": "Fluffychat",
|
||||||
<link rel="icon" type="image/x-icon" href="favicon.png">
|
"applicationCategory": "CommunicationApplication",
|
||||||
<link href="tailwind.css" rel="stylesheet">
|
"countriesNotSupported": "fr",
|
||||||
|
"operatingSystem": "ANDROID",
|
||||||
|
"releaseNotes": "https://gitlab.com/famedly/fluffychat/-/blob/main/CHANGELOG.md",
|
||||||
|
"screenshot": "https://gitlab.com/famedly/fluffychat/-/raw/main/docs/screenshots/mobile.png",
|
||||||
|
"softwareHelp": "https://gitlab.com/famedly/fluffychat/-/wikis/FAQ",
|
||||||
|
"author": {
|
||||||
|
"@type": "Person",
|
||||||
|
"callSign": "KrilleFear"
|
||||||
|
},
|
||||||
|
"license": "https://gitlab.com/famedly/fluffychat/-/blob/main/LICENSE",
|
||||||
|
"offers": {
|
||||||
|
"@type": "Offer",
|
||||||
|
"price": "0",
|
||||||
|
"priceCurrency": "USD"
|
||||||
|
},
|
||||||
|
"aggregateRating": {
|
||||||
|
"@type": "AggregateRating",
|
||||||
|
"ratingValue": "4.5",
|
||||||
|
"ratingCount": "133"
|
||||||
|
},
|
||||||
|
"installUrl": "https://play.google.com/store/apps/details?id=chat.fluffy.fluffychat"
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "MobileApplication",
|
||||||
|
"name": "Fluffychat",
|
||||||
|
"applicationCategory": "CommunicationApplication",
|
||||||
|
"countriesNotSupported": "fr",
|
||||||
|
"operatingSystem": "ANDROID",
|
||||||
|
"releaseNotes": "https://gitlab.com/famedly/fluffychat/-/blob/main/CHANGELOG.md",
|
||||||
|
"screenshot": "https://gitlab.com/famedly/fluffychat/-/raw/main/docs/screenshots/mobile.png",
|
||||||
|
"softwareHelp": "https://gitlab.com/famedly/fluffychat/-/wikis/FAQ",
|
||||||
|
"author": {
|
||||||
|
"@type": "Person",
|
||||||
|
"callSign": "KrilleFear"
|
||||||
|
},
|
||||||
|
"license": "https://gitlab.com/famedly/fluffychat/-/blob/main/LICENSE",
|
||||||
|
"offers": {
|
||||||
|
"@type": "Offer",
|
||||||
|
"price": "0",
|
||||||
|
"priceCurrency": "USD"
|
||||||
|
},
|
||||||
|
"aggregateRating": {
|
||||||
|
"@type": "AggregateRating",
|
||||||
|
"ratingValue": "4.5",
|
||||||
|
"ratingCount": "133"
|
||||||
|
},
|
||||||
|
"installUrl": "https://f-droid.org/de/packages/chat.fluffy.fluffychat/"
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "MobileApplication",
|
||||||
|
"name": "Fluffychat",
|
||||||
|
"applicationCategory": "CommunicationApplication",
|
||||||
|
"countriesNotSupported": "fr",
|
||||||
|
"operatingSystem": "IOS",
|
||||||
|
"releaseNotes": "https://gitlab.com/famedly/fluffychat/-/blob/main/CHANGELOG.md",
|
||||||
|
"screenshot": "https://gitlab.com/famedly/fluffychat/-/raw/main/docs/screenshots/mobile.png",
|
||||||
|
"softwareHelp": "https://gitlab.com/famedly/fluffychat/-/wikis/FAQ",
|
||||||
|
"author": {
|
||||||
|
"@type": "Person",
|
||||||
|
"callSign": "KrilleFear"
|
||||||
|
},
|
||||||
|
"license": "https://gitlab.com/famedly/fluffychat/-/blob/main/LICENSE",
|
||||||
|
"offers": {
|
||||||
|
"@type": "Offer",
|
||||||
|
"price": "0",
|
||||||
|
"priceCurrency": "USD"
|
||||||
|
},
|
||||||
|
"aggregateRating": {
|
||||||
|
"@type": "AggregateRating",
|
||||||
|
"ratingValue": "4.4",
|
||||||
|
"ratingCount": "28"
|
||||||
|
},
|
||||||
|
"installUrl": "https://apps.apple.com/app/fluffychat/id1551469600"
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "WebApplication",
|
||||||
|
"name": "Fluffychat",
|
||||||
|
"applicationCategory": "CommunicationApplication",
|
||||||
|
"countriesNotSupported": "fr",
|
||||||
|
"operatingSystem": "WEB",
|
||||||
|
"releaseNotes": "https://gitlab.com/famedly/fluffychat/-/blob/main/CHANGELOG.md",
|
||||||
|
"screenshot": "https://gitlab.com/famedly/fluffychat/-/raw/main/docs/screenshots/mobile.png",
|
||||||
|
"softwareHelp": "https://gitlab.com/famedly/fluffychat/-/wikis/FAQ",
|
||||||
|
"author": {
|
||||||
|
"@type": "Person",
|
||||||
|
"callSign": "KrilleFear"
|
||||||
|
},
|
||||||
|
"license": "https://gitlab.com/famedly/fluffychat/-/blob/main/LICENSE",
|
||||||
|
"offers": {
|
||||||
|
"@type": "Offer",
|
||||||
|
"price": "0",
|
||||||
|
"priceCurrency": "USD"
|
||||||
|
},
|
||||||
|
"aggregateRating": {
|
||||||
|
"@type": "AggregateRating",
|
||||||
|
"ratingValue": "4.5",
|
||||||
|
"ratingCount": "133"
|
||||||
|
},
|
||||||
|
"url": "https://fluffychat.im/web",
|
||||||
|
"downloadUrl": "https://fluffychat.im/web",
|
||||||
|
"installUrl": "https://fluffychat.im/web"
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "SoftwareApplication",
|
||||||
|
"name": "Fluffychat",
|
||||||
|
"applicationCategory": "CommunicationApplication",
|
||||||
|
"countriesNotSupported": "fr",
|
||||||
|
"operatingSystem": "LINUX",
|
||||||
|
"releaseNotes": "https://gitlab.com/famedly/fluffychat/-/blob/main/CHANGELOG.md",
|
||||||
|
"screenshot": "https://gitlab.com/famedly/fluffychat/-/raw/main/docs/screenshots/mobile.png",
|
||||||
|
"softwareHelp": "https://gitlab.com/famedly/fluffychat/-/wikis/FAQ",
|
||||||
|
"author": {
|
||||||
|
"@type": "Person",
|
||||||
|
"callSign": "KrilleFear"
|
||||||
|
},
|
||||||
|
"license": "https://gitlab.com/famedly/fluffychat/-/blob/main/LICENSE",
|
||||||
|
"offers": {
|
||||||
|
"@type": "Offer",
|
||||||
|
"price": "0",
|
||||||
|
"priceCurrency": "USD"
|
||||||
|
},
|
||||||
|
"aggregateRating": {
|
||||||
|
"@type": "AggregateRating",
|
||||||
|
"ratingValue": "4.5",
|
||||||
|
"ratingCount": "133"
|
||||||
|
},
|
||||||
|
"downloadUrl": "https://snapcraft.io/fluffychat",
|
||||||
|
"installUrl": "https://snapcraft.io/fluffychat"
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "SoftwareApplication",
|
||||||
|
"name": "Fluffychat",
|
||||||
|
"applicationCategory": "CommunicationApplication",
|
||||||
|
"countriesNotSupported": "fr",
|
||||||
|
"operatingSystem": "LINUX",
|
||||||
|
"releaseNotes": "https://gitlab.com/famedly/fluffychat/-/blob/main/CHANGELOG.md",
|
||||||
|
"screenshot": "https://gitlab.com/famedly/fluffychat/-/raw/main/docs/screenshots/mobile.png",
|
||||||
|
"softwareHelp": "https://gitlab.com/famedly/fluffychat/-/wikis/FAQ",
|
||||||
|
"author": {
|
||||||
|
"@type": "Person",
|
||||||
|
"callSign": "KrilleFear"
|
||||||
|
},
|
||||||
|
"license": "https://gitlab.com/famedly/fluffychat/-/blob/main/LICENSE",
|
||||||
|
"offers": {
|
||||||
|
"@type": "Offer",
|
||||||
|
"price": "0",
|
||||||
|
"priceCurrency": "USD"
|
||||||
|
},
|
||||||
|
"aggregateRating": {
|
||||||
|
"@type": "AggregateRating",
|
||||||
|
"ratingValue": "4.5",
|
||||||
|
"ratingCount": "133"
|
||||||
|
},
|
||||||
|
"downloadUrl": "https://flathub.org/apps/details/im.fluffychat.Fluffychat",
|
||||||
|
"installUrl": "https://flathub.org/apps/details/im.fluffychat.Fluffychat"
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "WebSite",
|
||||||
|
"name": "FluffyChat - Official Website",
|
||||||
|
"url": "https://fluffychat.im",
|
||||||
|
"description": "A cute and secure chatclient for the matrix protocol",
|
||||||
|
"thumbnailUrl": "https://fluffychat.im/favicon.png",
|
||||||
|
"inLanguage": "de-de"
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "BreadcrumbList",
|
||||||
|
"description": "Breadcrumbs list",
|
||||||
|
"name": "Breadcrumbs",
|
||||||
|
"itemListElement": [
|
||||||
|
{
|
||||||
|
"@type": "ListItem",
|
||||||
|
"item": {
|
||||||
|
"@id": "https://fluffychat.im",
|
||||||
|
"name": "Homepage"
|
||||||
|
},
|
||||||
|
"position": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<link rel="icon" type="image/png" href="favicon.png">
|
||||||
|
<link rel="stylesheet" href="tailwind.css">
|
||||||
|
<!-- Animation CSS-->
|
||||||
<style>
|
<style>
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: Zen Kurenaido;
|
font-family: Zen Kurenaido;
|
||||||
src: url(ZenKurenaido-Regular.ttf);
|
src: url(ZenKurenaido-Regular.ttf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------
|
||||||
|
* Generated by Animista
|
||||||
|
* w: http://animista.net, t: @cssanimista
|
||||||
|
* ---------------------------------------------- */
|
||||||
|
|
||||||
|
.slide-in-bottom {
|
||||||
|
-webkit-animation: slide-in-bottom .5s cubic-bezier(.25, .46, .45, .94) both;
|
||||||
|
animation: slide-in-bottom .5s cubic-bezier(.25, .46, .45, .94) both
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-in-bottom-h1 {
|
||||||
|
-webkit-animation: slide-in-bottom .5s cubic-bezier(.25, .46, .45, .94) .5s both;
|
||||||
|
animation: slide-in-bottom .5s cubic-bezier(.25, .46, .45, .94) .5s both
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-in-bottom-subtitle {
|
||||||
|
-webkit-animation: slide-in-bottom .5s cubic-bezier(.25, .46, .45, .94) .75s both;
|
||||||
|
animation: slide-in-bottom .5s cubic-bezier(.25, .46, .45, .94) .75s both
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-in {
|
||||||
|
-webkit-animation: fade-in 1.2s cubic-bezier(.39, .575, .565, 1.000) 1s both;
|
||||||
|
animation: fade-in 1.2s cubic-bezier(.39, .575, .565, 1.000) 1s both
|
||||||
|
}
|
||||||
|
|
||||||
|
.bounce-top-icons {
|
||||||
|
-webkit-animation: bounce-top .9s 1s both;
|
||||||
|
animation: bounce-top .9s 1s both
|
||||||
|
}
|
||||||
|
|
||||||
|
@-webkit-keyframes slide-in-bottom {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: translateY(1000px);
|
||||||
|
transform: translateY(1000px);
|
||||||
|
opacity: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
-webkit-transform: translateY(0);
|
||||||
|
transform: translateY(0);
|
||||||
|
opacity: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slide-in-bottom {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: translateY(1000px);
|
||||||
|
transform: translateY(1000px);
|
||||||
|
opacity: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
-webkit-transform: translateY(0);
|
||||||
|
transform: translateY(0);
|
||||||
|
opacity: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@-webkit-keyframes bounce-top {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: translateY(-45px);
|
||||||
|
transform: translateY(-45px);
|
||||||
|
-webkit-animation-timing-function: ease-in;
|
||||||
|
animation-timing-function: ease-in;
|
||||||
|
opacity: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
24% {
|
||||||
|
opacity: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
40% {
|
||||||
|
-webkit-transform: translateY(-24px);
|
||||||
|
transform: translateY(-24px);
|
||||||
|
-webkit-animation-timing-function: ease-in;
|
||||||
|
animation-timing-function: ease-in
|
||||||
|
}
|
||||||
|
|
||||||
|
65% {
|
||||||
|
-webkit-transform: translateY(-12px);
|
||||||
|
transform: translateY(-12px);
|
||||||
|
-webkit-animation-timing-function: ease-in;
|
||||||
|
animation-timing-function: ease-in
|
||||||
|
}
|
||||||
|
|
||||||
|
82% {
|
||||||
|
-webkit-transform: translateY(-6px);
|
||||||
|
transform: translateY(-6px);
|
||||||
|
-webkit-animation-timing-function: ease-in;
|
||||||
|
animation-timing-function: ease-in
|
||||||
|
}
|
||||||
|
|
||||||
|
93% {
|
||||||
|
-webkit-transform: translateY(-4px);
|
||||||
|
transform: translateY(-4px);
|
||||||
|
-webkit-animation-timing-function: ease-in;
|
||||||
|
animation-timing-function: ease-in
|
||||||
|
}
|
||||||
|
|
||||||
|
25%,
|
||||||
|
55%,
|
||||||
|
75%,
|
||||||
|
87% {
|
||||||
|
-webkit-transform: translateY(0);
|
||||||
|
transform: translateY(0);
|
||||||
|
-webkit-animation-timing-function: ease-out;
|
||||||
|
animation-timing-function: ease-out
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
-webkit-transform: translateY(0);
|
||||||
|
transform: translateY(0);
|
||||||
|
-webkit-animation-timing-function: ease-out;
|
||||||
|
animation-timing-function: ease-out;
|
||||||
|
opacity: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes bounce-top {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: translateY(-45px);
|
||||||
|
transform: translateY(-45px);
|
||||||
|
-webkit-animation-timing-function: ease-in;
|
||||||
|
animation-timing-function: ease-in;
|
||||||
|
opacity: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
24% {
|
||||||
|
opacity: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
40% {
|
||||||
|
-webkit-transform: translateY(-24px);
|
||||||
|
transform: translateY(-24px);
|
||||||
|
-webkit-animation-timing-function: ease-in;
|
||||||
|
animation-timing-function: ease-in
|
||||||
|
}
|
||||||
|
|
||||||
|
65% {
|
||||||
|
-webkit-transform: translateY(-12px);
|
||||||
|
transform: translateY(-12px);
|
||||||
|
-webkit-animation-timing-function: ease-in;
|
||||||
|
animation-timing-function: ease-in
|
||||||
|
}
|
||||||
|
|
||||||
|
82% {
|
||||||
|
-webkit-transform: translateY(-6px);
|
||||||
|
transform: translateY(-6px);
|
||||||
|
-webkit-animation-timing-function: ease-in;
|
||||||
|
animation-timing-function: ease-in
|
||||||
|
}
|
||||||
|
|
||||||
|
93% {
|
||||||
|
-webkit-transform: translateY(-4px);
|
||||||
|
transform: translateY(-4px);
|
||||||
|
-webkit-animation-timing-function: ease-in;
|
||||||
|
animation-timing-function: ease-in
|
||||||
|
}
|
||||||
|
|
||||||
|
25%,
|
||||||
|
55%,
|
||||||
|
75%,
|
||||||
|
87% {
|
||||||
|
-webkit-transform: translateY(0);
|
||||||
|
transform: translateY(0);
|
||||||
|
-webkit-animation-timing-function: ease-out;
|
||||||
|
animation-timing-function: ease-out
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
-webkit-transform: translateY(0);
|
||||||
|
transform: translateY(0);
|
||||||
|
-webkit-animation-timing-function: ease-out;
|
||||||
|
animation-timing-function: ease-out;
|
||||||
|
opacity: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@-webkit-keyframes fade-in {
|
||||||
|
0% {
|
||||||
|
opacity: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fade-in {
|
||||||
|
0% {
|
||||||
|
opacity: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body
|
|
||||||
class="flex flex-col items-center justify-center min-h-screen w-screen bg-gradient-to-t from-purple-200 to-blue-50 dark:from-gray-800 dark:to-slate-900 p-4"
|
|
||||||
style="font-family: 'Zen Kurenaido', sans-serif;">
|
|
||||||
<img src="favicon.png" class="h-10" />
|
|
||||||
<h1 class="flex text-4xl items-center mb-4">
|
|
||||||
<span style="color: #5625BA">Fluffy</span>
|
|
||||||
<span style="color: #41a2bc">Chat</span>
|
|
||||||
</h1>
|
|
||||||
<img src="screenshots/screenshots.png" class="sm:max-w-lg max-w-screen mb-8" />
|
|
||||||
|
|
||||||
<div class="max-w-lg mb-8 flex justify-center flex-wrap">
|
<body class="leading-normal tracking-normal text-gray-900" style="font-family: 'Zen Kurenaido', sans-serif;">
|
||||||
<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">
|
<div class="h-screen pb-14 bg-right bg-cover" style="background-image:url('bg.svg');">
|
||||||
</a><a href="https://f-droid.org/packages/chat.fluffy.fluffychat/"><img src="fdroid_button.png"
|
<!--Nav-->
|
||||||
class="w-36 pr-2 mb-2 hover:scale-105 transition-transform inline">
|
<div class="w-full container mx-auto p-6">
|
||||||
</a>
|
|
||||||
<a href="https://fluffychat.im/web">
|
<div class="w-full flex items-center justify-between">
|
||||||
<img src="browser-badge.png" class="w-36 pr-2 mb-2 hover:scale-105 transition-transform inline"></a>
|
<a class="flex items-center no-underline hover:no-underline font-bold text-2xl lg:text-4xl" href="#">
|
||||||
<a href="https://snapcraft.io/fluffychat"><img
|
<img src="favicon.png" class="h-8 fill-current text-indigo-600 pr-2" /> <span
|
||||||
src="https://snapcraft.io/static/images/badges/en/snap-store-black.svg"
|
style="color: #5625BA">Fluffy</span><span style="color: #41a2bc">Chat</span>
|
||||||
class="w-36 pr-2 mb-2 hover:scale-105 transition-transform inline"></a>
|
</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 class="flex w-1/2 justify-end content-center">
|
||||||
</div>
|
<a class="inline-block text-blue-300 no-underline hover:text-indigo-800 hover:text-underline text-center h-10 p-2 md:h-auto md:p-4"
|
||||||
|
href="https://matrix.to/#/#fluffychat:matrix.org">
|
||||||
|
<svg class="fill-current h-6" enable-background="new -91 49.217 56.693 56.693" id="Layer_1"
|
||||||
|
version="1.1" viewBox="-91 49.217 56.693 56.693" xml:space="preserve"
|
||||||
|
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<path
|
||||||
|
d="M-38.3289,79.8244c-0.7526-2.2362-3.1756-3.4388-5.4117-2.6861l-4.5351,1.5264l-3.0737-9.1321l4.4169-1.4866 c2.2362-0.7526,3.4388-3.1756,2.6861-5.4117c-0.7526-2.2362-3.1756-3.4388-5.4117-2.6861l-4.4168,1.4866l-1.4877-4.4201 c-0.7527-2.2362-3.1756-3.4388-5.4117-2.6861v0c-2.2362,0.7526-3.4388,3.1756-2.6861,5.4117l1.4877,4.4201l-9.3246,3.1385 l-1.4697-4.3666c-0.7527-2.2362-3.1756-3.4388-5.4117-2.6861c-2.2362,0.7527-3.4388,3.1756-2.6861,5.4117l1.4697,4.3666 l-4.445,1.4961c-2.2362,0.7527-3.4388,3.1756-2.6861,5.4117v0c0.7526,2.2362,3.1756,3.4388,5.4117,2.6861l4.445-1.4961 l3.0737,9.1321l-4.3268,1.4563c-2.2362,0.7527-3.4388,3.1756-2.6861,5.4117c0.7526,2.2362,3.1756,3.4388,5.4117,2.6861 l4.3268-1.4563l1.5778,4.6877c0.7527,2.2362,3.1756,3.4388,5.4117,2.6861c2.2362-0.7527,3.4388-3.1756,2.6861-5.4117l-1.5778-4.6877 l9.3246-3.1385l1.5598,4.6342c0.7527,2.2362,3.1756,3.4388,5.4117,2.6861c2.2362-0.7527,3.4388-3.1756,2.6861-5.4117l-1.5598-4.6342 l4.5351-1.5264C-38.7789,84.4835-37.5762,82.0606-38.3289,79.8244z M-65.6982,84.5288l-3.0737-9.1321l9.3246-3.1385l3.0737,9.1321 L-65.6982,84.5288z" />
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
<a class="inline-block text-blue-300 no-underline hover:text-indigo-800 hover:text-underline text-center h-10 p-2 md:h-auto md:p-4"
|
||||||
|
href="https://twitter.com/KrilleFear">
|
||||||
|
<svg class="fill-current h-6" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||||
|
<path
|
||||||
|
d="M30.063 7.313c-.813 1.125-1.75 2.125-2.875 2.938v.75c0 1.563-.188 3.125-.688 4.625a15.088 15.088 0 0 1-2.063 4.438c-.875 1.438-2 2.688-3.25 3.813a15.015 15.015 0 0 1-4.625 2.563c-1.813.688-3.75 1-5.75 1-3.25 0-6.188-.875-8.875-2.625.438.063.875.125 1.375.125 2.688 0 5.063-.875 7.188-2.5-1.25 0-2.375-.375-3.375-1.125s-1.688-1.688-2.063-2.875c.438.063.813.125 1.125.125.5 0 1-.063 1.5-.25-1.313-.25-2.438-.938-3.313-1.938a5.673 5.673 0 0 1-1.313-3.688v-.063c.813.438 1.688.688 2.625.688a5.228 5.228 0 0 1-1.875-2c-.5-.875-.688-1.813-.688-2.75 0-1.063.25-2.063.75-2.938 1.438 1.75 3.188 3.188 5.25 4.25s4.313 1.688 6.688 1.813a5.579 5.579 0 0 1 1.5-5.438c1.125-1.125 2.5-1.688 4.125-1.688s3.063.625 4.188 1.813a11.48 11.48 0 0 0 3.688-1.375c-.438 1.375-1.313 2.438-2.563 3.188 1.125-.125 2.188-.438 3.313-.875z">
|
||||||
|
</path>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
<a class="inline-block text-blue-300 no-underline hover:text-indigo-800 hover:text-underline text-center h-10 p-2 md:h-auto md:p-4"
|
||||||
|
href="https://metalhead.club/@krille">
|
||||||
|
<svg class="fill-current h-6" viewBox="0 0 1000 1000" version="1.1"
|
||||||
|
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xml:space="preserve"
|
||||||
|
style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;">
|
||||||
|
<clipPath id="_clip1">
|
||||||
|
<rect x="33.6" y="-0.035" width="932.844" height="1000" />
|
||||||
|
</clipPath>
|
||||||
|
<g clip-path="url(#_clip1)">
|
||||||
|
<path
|
||||||
|
d="M946.586,599.455c-13.713,70.541 -122.816,147.742 -248.121,162.703c-65.341,7.796 -129.674,14.962 -198.275,11.815c-112.191,-5.139 -200.716,-26.776 -200.716,-26.776c0,10.92 0.673,21.319 2.02,31.044c14.586,110.711 109.787,117.344 199.967,120.436c91.021,3.114 172.068,-22.44 172.068,-22.44l3.74,82.281c0,0 -63.666,34.185 -177.079,40.473c-62.539,3.437 -140.192,-1.573 -230.636,-25.511c-196.158,-51.916 -229.893,-260.996 -235.055,-473.143c-1.573,-62.987 -0.603,-122.381 -0.603,-172.056c0,-216.931 142.142,-280.516 142.142,-280.516c71.672,-32.914 194.655,-46.755 322.508,-47.8l3.142,0c127.853,1.045 250.917,14.886 322.583,47.8c0,0 142.138,63.585 142.138,280.516c0,0 1.783,160.053 -19.823,271.174"
|
||||||
|
style="fill-rule:nonzero;" />
|
||||||
|
<path
|
||||||
|
d="M798.748,345.11l0,262.667l-104.07,0l0,-254.946c0,-53.743 -22.614,-81.021 -67.847,-81.021c-50.012,0 -75.077,32.359 -75.077,96.343l0,139.547l-103.457,0l0,-139.547c0,-63.984 -25.07,-96.343 -75.082,-96.343c-45.233,0 -67.847,27.278 -67.847,81.021l0,254.946l-104.07,0l0,-262.667c0,-53.683 13.669,-96.343 41.127,-127.904c28.314,-31.561 65.395,-47.741 111.425,-47.741c53.256,0 93.585,20.468 120.251,61.41l25.922,43.451l25.927,-43.451c26.66,-40.942 66.99,-61.41 120.251,-61.41c46.025,0 83.106,16.18 111.425,47.741c27.453,31.561 41.122,74.221 41.122,127.904"
|
||||||
|
style="fill:#fff;fill-rule:nonzero;" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
<a class="inline-block text-blue-300 no-underline hover:text-indigo-800 hover:text-underline text-center h-10 p-2 md:h-auto md:p-4"
|
||||||
|
href="https://ko-fi.com/krille">
|
||||||
|
<img class="w-10 hover:animate-bounce" src="Kofi_pixel_logo.png"/>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!--Main-->
|
||||||
|
<div class="container pt-8 px-6 mx-auto flex flex-wrap flex-col md:flex-row items-center">
|
||||||
|
|
||||||
|
<!--Left Col-->
|
||||||
|
<div class="flex flex-col w-full xl:w-2/5 justify-center lg:items-start overflow-y-hidden">
|
||||||
|
<h1
|
||||||
|
class="my-4 text-3xl md:text-5xl text-purple-800 font-bold leading-tight text-center md:text-left slide-in-bottom-h1">
|
||||||
|
Open. Nonprofit. Cute.</h1>
|
||||||
|
<p class="leading-normal text-base md:text-2xl mb-8 text-center md:text-left slide-in-bottom-subtitle">
|
||||||
|
Easy to use (<a class="underline hover:text-blue-700 transition-all"
|
||||||
|
href="https://matrix.org">matrix</a>) messenger. Secure and decentralized.</p>
|
||||||
|
|
||||||
|
<p class="text-blue-700 font-bold pb-4 text-center md:text-left fade-in">Mobile app:</p>
|
||||||
|
<div class="w-full flex justify-center md:justify-start pb-24 lg:pb-0 fade-in">
|
||||||
|
<a href="https://apps.apple.com/app/fluffychat/id1551469600"><img src="appstore-badge.png"
|
||||||
|
class="max-h-12 pr-2 mb-2 bounce-top-icons inline"></a>
|
||||||
|
<a href="https://play.google.com/store/apps/details?id=chat.fluffy.fluffychat"><img
|
||||||
|
src="google-play-badge.png" class="max-h-12 pr-2 mb-2 bounce-top-icons inline">
|
||||||
|
</a><a href="https://f-droid.org/de/packages/chat.fluffy.fluffychat/"><img src="fdroid_button.png"
|
||||||
|
class="max-h-12 pr-2 mb-2 bounce-top-icons inline">
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<p class="text-blue-700 font-bold py-4 text-center md:text-left fade-in">Desktop app:</p>
|
||||||
|
<div class="w-full flex justify-center md:justify-start pb-24 lg:pb-0 fade-in">
|
||||||
|
<a href="https://fluffychat.im/web">
|
||||||
|
<img src="browser-badge.png" class="max-h-12 pr-2 mb-2 bounce-top-icons inline"></a>
|
||||||
|
<a href="https://snapcraft.io/fluffychat"><img
|
||||||
|
src="https://snapcraft.io/static/images/badges/en/snap-store-black.svg"
|
||||||
|
class="max-h-12 pr-2 mb-2 bounce-top-icons inline"></a>
|
||||||
|
<a href="https://flathub.org/apps/details/im.fluffychat.Fluffychat"><img src="flathub-badge-en.png"
|
||||||
|
class="max-h-12 pr-2 mb-2 bounce-top-icons inline"></a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!--Right Col-->
|
||||||
|
<div class="w-full xl:w-3/5 py-6 relative">
|
||||||
|
<img class="w-full mx-auto slide-in-bottom" src="screenshots/screenshots.png">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!--Footer-->
|
||||||
|
<div class="w-full pt-16 pb-6 text-sm text-center md:text-left fade-in">
|
||||||
|
<a class="text-gray-500 no-underline hover:text-purple-800"
|
||||||
|
href="https://gitlab.com/famedly/fluffychat">Source code</a>
|
||||||
|
-
|
||||||
|
<a class="text-gray-500 no-underline hover:text-purple-800"
|
||||||
|
href="https://gitlab.com/famedly/fluffychat/-/blob/main/PRIVACY.md">Privacy</a>
|
||||||
|
-
|
||||||
|
<a class="text-gray-500 no-underline hover:text-purple-800"
|
||||||
|
href="https://gitlab.com/famedly/fluffychat/-/blob/main/CHANGELOG.md">Changelog</a>
|
||||||
|
-
|
||||||
|
<a class="text-gray-500 no-underline hover:text-purple-800"
|
||||||
|
href="https://hosted.weblate.org/projects/fluffychat/">Translations</a>
|
||||||
|
-
|
||||||
|
<a class="text-gray-500 no-underline hover:text-purple-800"
|
||||||
|
href="https://gitlab.com/famedly/fluffychat/-/blob/main/docs/fdroid_repo.md">FluffyChat F-Droid repository</a>
|
||||||
|
-
|
||||||
|
<a class="text-gray-500 no-underline hover:text-purple-800"
|
||||||
|
href="https://liberapay.com/KrilleChritzelius/donate">Donate</a>
|
||||||
|
-
|
||||||
|
<a class="text-gray-500 no-underline hover:text-purple-800"
|
||||||
|
href="https://keys.mailvelope.com/pks/lookup?op=get&search=christian-pauly%40posteo.de">Contact</a>
|
||||||
|
-
|
||||||
|
<a class="text-gray-500 no-underline hover:text-purple-800" href="https://krillefear.gitlab.io">Created
|
||||||
|
by Krille Fear</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="flex mb-8 justify-center content-center">
|
|
||||||
<a rel="me"
|
|
||||||
class="inline-block text-indigo-500 no-underline hover:text-indigo-900 hover:scale-105 transition-all text-center h-auto p-4"
|
|
||||||
rel="me" href="https://mastodon.art/@krille">
|
|
||||||
<svg class="fill-current h-6" viewBox="0 0 1000 1000" version="1.1" xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve"
|
|
||||||
style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;">
|
|
||||||
<clipPath id="_clip1">
|
|
||||||
<rect x="33.6" y="-0.035" width="932.844" height="1000" />
|
|
||||||
</clipPath>
|
|
||||||
<g clip-path="url(#_clip1)">
|
|
||||||
<path
|
|
||||||
d="M946.586,599.455c-13.713,70.541 -122.816,147.742 -248.121,162.703c-65.341,7.796 -129.674,14.962 -198.275,11.815c-112.191,-5.139 -200.716,-26.776 -200.716,-26.776c0,10.92 0.673,21.319 2.02,31.044c14.586,110.711 109.787,117.344 199.967,120.436c91.021,3.114 172.068,-22.44 172.068,-22.44l3.74,82.281c0,0 -63.666,34.185 -177.079,40.473c-62.539,3.437 -140.192,-1.573 -230.636,-25.511c-196.158,-51.916 -229.893,-260.996 -235.055,-473.143c-1.573,-62.987 -0.603,-122.381 -0.603,-172.056c0,-216.931 142.142,-280.516 142.142,-280.516c71.672,-32.914 194.655,-46.755 322.508,-47.8l3.142,0c127.853,1.045 250.917,14.886 322.583,47.8c0,0 142.138,63.585 142.138,280.516c0,0 1.783,160.053 -19.823,271.174"
|
|
||||||
style="fill-rule:nonzero;" />
|
|
||||||
<path
|
|
||||||
d="M798.748,345.11l0,262.667l-104.07,0l0,-254.946c0,-53.743 -22.614,-81.021 -67.847,-81.021c-50.012,0 -75.077,32.359 -75.077,96.343l0,139.547l-103.457,0l0,-139.547c0,-63.984 -25.07,-96.343 -75.082,-96.343c-45.233,0 -67.847,27.278 -67.847,81.021l0,254.946l-104.07,0l0,-262.667c0,-53.683 13.669,-96.343 41.127,-127.904c28.314,-31.561 65.395,-47.741 111.425,-47.741c53.256,0 93.585,20.468 120.251,61.41l25.922,43.451l25.927,-43.451c26.66,-40.942 66.99,-61.41 120.251,-61.41c46.025,0 83.106,16.18 111.425,47.741c27.453,31.561 41.122,74.221 41.122,127.904"
|
|
||||||
style="fill:#fff;fill-rule:nonzero;" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
</a>
|
|
||||||
<a class="inline-block text-indigo-500 no-underline hover:text-indigo-900 hover:scale-105 transition-all text-center h-auto p-4"
|
|
||||||
href="https://matrix.to/#/#fluffychat:matrix.org">
|
|
||||||
<svg class="fill-current h-6" enable-background="new -91 49.217 56.693 56.693" id="Layer_1" version="1.1"
|
|
||||||
viewBox="-91 49.217 56.693 56.693" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
||||||
<path
|
|
||||||
d="M-38.3289,79.8244c-0.7526-2.2362-3.1756-3.4388-5.4117-2.6861l-4.5351,1.5264l-3.0737-9.1321l4.4169-1.4866 c2.2362-0.7526,3.4388-3.1756,2.6861-5.4117c-0.7526-2.2362-3.1756-3.4388-5.4117-2.6861l-4.4168,1.4866l-1.4877-4.4201 c-0.7527-2.2362-3.1756-3.4388-5.4117-2.6861v0c-2.2362,0.7526-3.4388,3.1756-2.6861,5.4117l1.4877,4.4201l-9.3246,3.1385 l-1.4697-4.3666c-0.7527-2.2362-3.1756-3.4388-5.4117-2.6861c-2.2362,0.7527-3.4388,3.1756-2.6861,5.4117l1.4697,4.3666 l-4.445,1.4961c-2.2362,0.7527-3.4388,3.1756-2.6861,5.4117v0c0.7526,2.2362,3.1756,3.4388,5.4117,2.6861l4.445-1.4961 l3.0737,9.1321l-4.3268,1.4563c-2.2362,0.7527-3.4388,3.1756-2.6861,5.4117c0.7526,2.2362,3.1756,3.4388,5.4117,2.6861 l4.3268-1.4563l1.5778,4.6877c0.7527,2.2362,3.1756,3.4388,5.4117,2.6861c2.2362-0.7527,3.4388-3.1756,2.6861-5.4117l-1.5778-4.6877 l9.3246-3.1385l1.5598,4.6342c0.7527,2.2362,3.1756,3.4388,5.4117,2.6861c2.2362-0.7527,3.4388-3.1756,2.6861-5.4117l-1.5598-4.6342 l4.5351-1.5264C-38.7789,84.4835-37.5762,82.0606-38.3289,79.8244z M-65.6982,84.5288l-3.0737-9.1321l9.3246-3.1385l3.0737,9.1321 L-65.6982,84.5288z" />
|
|
||||||
</svg>
|
|
||||||
</a>
|
|
||||||
<a class="inline-block no-underline hover:scale-105 transition-all text-center h-auto p-4"
|
|
||||||
href="https://ko-fi.com/krille">
|
|
||||||
<img src="kofi_button_dark.png" class="h-6 fill-current" />
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--Footer-->
|
|
||||||
<div class="w-full text-sm text-center max-w-lg">
|
|
||||||
<a class="text-slate-700 dark:text-slate-200 no-underline hover:text-purple-800"
|
|
||||||
href="https://gitlab.com/famedly/fluffychat">Source
|
|
||||||
code</a>
|
|
||||||
-
|
|
||||||
<a class="text-slate-700 dark:text-slate-200 no-underline hover:text-purple-800"
|
|
||||||
href="https://gitlab.com/famedly/fluffychat/-/blob/main/PRIVACY.md">Privacy</a>
|
|
||||||
-
|
|
||||||
<a class="text-slate-700 dark:text-slate-200 no-underline hover:text-purple-800"
|
|
||||||
href="https://gitlab.com/famedly/fluffychat/-/blob/main/CHANGELOG.md">Changelog</a>
|
|
||||||
-
|
|
||||||
<a class="text-slate-700 dark:text-slate-200 no-underline hover:text-purple-800"
|
|
||||||
href="https://hosted.weblate.org/projects/fluffychat/">Translations</a>
|
|
||||||
-
|
|
||||||
<a class="text-slate-700 dark:text-slate-200 no-underline hover:text-purple-800"
|
|
||||||
href="https://gitlab.com/famedly/fluffychat/-/blob/main/docs/fdroid_repo.md">FluffyChat F-Droid
|
|
||||||
repository</a>
|
|
||||||
-
|
|
||||||
<a class="text-slate-700 dark:text-slate-200 no-underline hover:text-purple-800"
|
|
||||||
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"
|
|
||||||
href="https://krillefear.gitlab.io">Created
|
|
||||||
by Krille Fear</a>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 84 KiB |
BIN
fonts/NotoEmoji/NotoEmoji-Regular.ttf
Normal file
@ -1,193 +1,49 @@
|
|||||||
import 'package:fluffychat/config/setting_keys.dart';
|
import 'dart:developer';
|
||||||
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/material.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:hive_flutter/hive_flutter.dart';
|
|
||||||
import 'package:integration_test/integration_test.dart';
|
import 'package:integration_test/integration_test.dart';
|
||||||
|
|
||||||
import 'package:fluffychat/main.dart' as app;
|
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';
|
import 'users.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
group(
|
group('Integration Test', () {
|
||||||
'Integration Test',
|
testWidgets('Test if the app starts', (WidgetTester tester) async {
|
||||||
() {
|
app.main();
|
||||||
setUpAll(
|
await tester.pumpAndSettle();
|
||||||
() async {
|
|
||||||
// this random dialog popping up is super hard to cover in tests
|
|
||||||
SharedPreferences.setMockInitialValues({
|
|
||||||
SettingKeys.showNoGoogle: false,
|
|
||||||
});
|
|
||||||
try {
|
|
||||||
Hive.deleteFromDisk();
|
|
||||||
Hive.initFlutter();
|
|
||||||
} catch (_) {}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
testWidgets(
|
await Future.delayed(const Duration(seconds: 10));
|
||||||
'Start app, login and logout',
|
|
||||||
(WidgetTester tester) async {
|
|
||||||
app.main();
|
|
||||||
await tester.ensureAppStartedHomescreen();
|
|
||||||
await tester.ensureLoggedOut();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
testWidgets(
|
await tester.pumpAndSettle();
|
||||||
'Login again',
|
|
||||||
(WidgetTester tester) async {
|
|
||||||
app.main();
|
|
||||||
await tester.ensureAppStartedHomescreen();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
testWidgets(
|
expect(find.text('Connect'), findsOneWidget);
|
||||||
'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(
|
final input = find.byType(TextField);
|
||||||
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(
|
expect(input, findsOneWidget);
|
||||||
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.enterText(input, homeserver);
|
||||||
await tester.waitFor(
|
await tester.testTextInput.receiveAction(TextInputAction.done);
|
||||||
find.byType(ChatView),
|
await tester.pumpAndSettle();
|
||||||
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));
|
// in case registration is allowed
|
||||||
await tester.enterText(find.byType(TextField).last, 'Test');
|
try {
|
||||||
await tester.pumpAndSettle();
|
await tester.tap(find.text('Login'));
|
||||||
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.pumpAndSettle();
|
||||||
|
} catch (e) {
|
||||||
|
log('Registration is not allowed. Proceeding with login...');
|
||||||
|
}
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
await tester.waitFor(find.byIcon(Icons.workspaces_outlined));
|
final inputs = find.byType(TextField);
|
||||||
await tester.tap(find.byIcon(Icons.workspaces_outlined));
|
|
||||||
await tester.pumpAndSettle();
|
|
||||||
|
|
||||||
await tester.waitFor(find.byType(TextField));
|
await tester.enterText(inputs.first, Users.user1.name);
|
||||||
await tester.enterText(find.byType(TextField).last, 'Test Space');
|
await tester.enterText(inputs.last, Users.user1.password);
|
||||||
await tester.pumpAndSettle();
|
await tester.testTextInput.receiveAction(TextInputAction.done);
|
||||||
|
});
|
||||||
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);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,171 +0,0 @@
|
|||||||
import 'dart:developer';
|
|
||||||
|
|
||||||
import 'package:fluffychat/pages/chat_list/chat_list_body.dart';
|
|
||||||
import 'package:fluffychat/pages/homeserver_picker/homeserver_picker.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(HomeserverPicker);
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,49 +0,0 @@
|
|||||||
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,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,25 +1,15 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
abstract class Users {
|
abstract class Users {
|
||||||
const Users._();
|
const Users._();
|
||||||
|
|
||||||
static const user1 = User(
|
static final user1 = User(
|
||||||
String.fromEnvironment(
|
Platform.environment['USER1_NAME'] ?? 'alice',
|
||||||
'USER1_NAME',
|
Platform.environment['USER1_PW'] ?? 'AliceInWonderland',
|
||||||
defaultValue: 'alice',
|
|
||||||
),
|
|
||||||
String.fromEnvironment(
|
|
||||||
'USER1_PW',
|
|
||||||
defaultValue: 'AliceInWonderland',
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
static const user2 = User(
|
static final user2 = User(
|
||||||
String.fromEnvironment(
|
Platform.environment['USER2_NAME'] ?? 'bob',
|
||||||
'USER2_NAME',
|
Platform.environment['USER2_PW'] ?? 'JoWirSchaffenDas',
|
||||||
defaultValue: 'bob',
|
|
||||||
),
|
|
||||||
String.fromEnvironment(
|
|
||||||
'USER2_PW',
|
|
||||||
defaultValue: 'JoWirSchaffenDas',
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,7 +20,5 @@ class User {
|
|||||||
const User(this.name, this.password);
|
const User(this.name, this.password);
|
||||||
}
|
}
|
||||||
|
|
||||||
const homeserver = 'http://${const String.fromEnvironment(
|
final homeserver =
|
||||||
'HOMESERVER',
|
'http://${Platform.environment['HOMESERVER'] ?? 'localhost'}';
|
||||||
defaultValue: 'localhost',
|
|
||||||
)}';
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
archiveVersion = 1;
|
archiveVersion = 1;
|
||||||
classes = {
|
classes = {
|
||||||
};
|
};
|
||||||
objectVersion = 54;
|
objectVersion = 51;
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
@ -286,12 +286,10 @@
|
|||||||
/* Begin PBXShellScriptBuildPhase section */
|
/* Begin PBXShellScriptBuildPhase section */
|
||||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
alwaysOutOfDate = 1;
|
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
);
|
);
|
||||||
inputPaths = (
|
inputPaths = (
|
||||||
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
|
|
||||||
);
|
);
|
||||||
name = "Thin Binary";
|
name = "Thin Binary";
|
||||||
outputPaths = (
|
outputPaths = (
|
||||||
@ -324,7 +322,6 @@
|
|||||||
};
|
};
|
||||||
9740EEB61CF901F6004384FC /* Run Script */ = {
|
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
alwaysOutOfDate = 1;
|
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
);
|
);
|
||||||
|
|||||||
@ -110,7 +110,5 @@
|
|||||||
</dict>
|
</dict>
|
||||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
|
||||||
<true/>
|
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
app_identifier("im.fluffychat.app") # The bundle identifier of your app
|
app_identifier("im.fluffychat.app") # The bundle identifier of your app
|
||||||
apple_id("christian-kussowski@posteo.de") # Your Apple email address
|
apple_id("christian.pauly@wtal.de") # Your Apple email address
|
||||||
|
|
||||||
itc_team_id("122628977") # App Store Connect Team ID
|
itc_team_id("122628977") # App Store Connect Team ID
|
||||||
team_id("4NXF6Z997G") # Developer Portal Team ID
|
team_id("4NXF6Z997G") # Developer Portal Team ID
|
||||||
|
|||||||
@ -16,7 +16,7 @@ abstract class AppConfig {
|
|||||||
static const double messageFontSize = 15.75;
|
static const double messageFontSize = 15.75;
|
||||||
static const bool allowOtherHomeservers = true;
|
static const bool allowOtherHomeservers = true;
|
||||||
static const bool enableRegistration = true;
|
static const bool enableRegistration = true;
|
||||||
static const Color primaryColor = Color(0xFF5625BA);
|
static const Color primaryColor = Color.fromARGB(255, 135, 103, 172);
|
||||||
static const Color primaryColorLight = Color(0xFFCCBDEA);
|
static const Color primaryColorLight = Color(0xFFCCBDEA);
|
||||||
static const Color secondaryColor = Color(0xFF41a2bc);
|
static const Color secondaryColor = Color(0xFF41a2bc);
|
||||||
static String _privacyUrl =
|
static String _privacyUrl =
|
||||||
@ -24,8 +24,6 @@ abstract class AppConfig {
|
|||||||
static String get privacyUrl => _privacyUrl;
|
static String get privacyUrl => _privacyUrl;
|
||||||
static const String enablePushTutorial =
|
static const String enablePushTutorial =
|
||||||
'https://gitlab.com/famedly/fluffychat/-/wikis/Push-Notifications-without-Google-Services';
|
'https://gitlab.com/famedly/fluffychat/-/wikis/Push-Notifications-without-Google-Services';
|
||||||
static const String encryptionTutorial =
|
|
||||||
'https://gitlab.com/famedly/fluffychat/-/wikis/How-to-use-end-to-end-encryption-in-FluffyChat';
|
|
||||||
static const String appId = 'im.fluffychat.FluffyChat';
|
static const String appId = 'im.fluffychat.FluffyChat';
|
||||||
static const String appOpenUrlScheme = 'im.fluffychat';
|
static const String appOpenUrlScheme = 'im.fluffychat';
|
||||||
static String _webBaseUrl = 'https://fluffychat.im/web';
|
static String _webBaseUrl = 'https://fluffychat.im/web';
|
||||||
@ -33,11 +31,6 @@ abstract class AppConfig {
|
|||||||
static const String sourceCodeUrl = 'https://gitlab.com/famedly/fluffychat';
|
static const String sourceCodeUrl = 'https://gitlab.com/famedly/fluffychat';
|
||||||
static const String supportUrl =
|
static const String supportUrl =
|
||||||
'https://gitlab.com/famedly/fluffychat/issues';
|
'https://gitlab.com/famedly/fluffychat/issues';
|
||||||
static final Uri newIssueUrl = Uri(
|
|
||||||
scheme: 'https',
|
|
||||||
host: 'gitlab.com',
|
|
||||||
path: '/famedly/fluffychat/-/issues/new',
|
|
||||||
);
|
|
||||||
static const bool enableSentry = true;
|
static const bool enableSentry = true;
|
||||||
static const String sentryDns =
|
static const String sentryDns =
|
||||||
'https://8591d0d863b646feb4f3dda7e5dcab38@o256755.ingest.sentry.io/5243143';
|
'https://8591d0d863b646feb4f3dda7e5dcab38@o256755.ingest.sentry.io/5243143';
|
||||||
@ -75,9 +68,8 @@ abstract class AppConfig {
|
|||||||
colorSchemeSeed = Color(json['chat_color']);
|
colorSchemeSeed = Color(json['chat_color']);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Logs().w(
|
Logs().w(
|
||||||
'Invalid color in config.json! Please make sure to define the color in this format: "0xffdd0000"',
|
'Invalid color in config.json! Please make sure to define the color in this format: "0xffdd0000"',
|
||||||
e,
|
e);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (json['application_name'] is String) {
|
if (json['application_name'] is String) {
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import 'package:fluffychat/pages/chat_details/chat_details.dart';
|
|||||||
import 'package:fluffychat/pages/chat_encryption_settings/chat_encryption_settings.dart';
|
import 'package:fluffychat/pages/chat_encryption_settings/chat_encryption_settings.dart';
|
||||||
import 'package:fluffychat/pages/chat_list/chat_list.dart';
|
import 'package:fluffychat/pages/chat_list/chat_list.dart';
|
||||||
import 'package:fluffychat/pages/chat_permissions_settings/chat_permissions_settings.dart';
|
import 'package:fluffychat/pages/chat_permissions_settings/chat_permissions_settings.dart';
|
||||||
|
import 'package:fluffychat/pages/connect/connect_page.dart';
|
||||||
import 'package:fluffychat/pages/device_settings/device_settings.dart';
|
import 'package:fluffychat/pages/device_settings/device_settings.dart';
|
||||||
import 'package:fluffychat/pages/homeserver_picker/homeserver_picker.dart';
|
import 'package:fluffychat/pages/homeserver_picker/homeserver_picker.dart';
|
||||||
import 'package:fluffychat/pages/invitation_selection/invitation_selection.dart';
|
import 'package:fluffychat/pages/invitation_selection/invitation_selection.dart';
|
||||||
@ -18,6 +19,7 @@ import 'package:fluffychat/pages/new_private_chat/new_private_chat.dart';
|
|||||||
import 'package:fluffychat/pages/new_space/new_space.dart';
|
import 'package:fluffychat/pages/new_space/new_space.dart';
|
||||||
import 'package:fluffychat/pages/settings/settings.dart';
|
import 'package:fluffychat/pages/settings/settings.dart';
|
||||||
import 'package:fluffychat/pages/settings_3pid/settings_3pid.dart';
|
import 'package:fluffychat/pages/settings_3pid/settings_3pid.dart';
|
||||||
|
import 'package:fluffychat/pages/settings_account/settings_account.dart';
|
||||||
import 'package:fluffychat/pages/settings_chat/settings_chat.dart';
|
import 'package:fluffychat/pages/settings_chat/settings_chat.dart';
|
||||||
import 'package:fluffychat/pages/settings_emotes/settings_emotes.dart';
|
import 'package:fluffychat/pages/settings_emotes/settings_emotes.dart';
|
||||||
import 'package:fluffychat/pages/settings_ignore_list/settings_ignore_list.dart';
|
import 'package:fluffychat/pages/settings_ignore_list/settings_ignore_list.dart';
|
||||||
@ -26,6 +28,7 @@ import 'package:fluffychat/pages/settings_notifications/settings_notifications.d
|
|||||||
import 'package:fluffychat/pages/settings_security/settings_security.dart';
|
import 'package:fluffychat/pages/settings_security/settings_security.dart';
|
||||||
import 'package:fluffychat/pages/settings_stories/settings_stories.dart';
|
import 'package:fluffychat/pages/settings_stories/settings_stories.dart';
|
||||||
import 'package:fluffychat/pages/settings_style/settings_style.dart';
|
import 'package:fluffychat/pages/settings_style/settings_style.dart';
|
||||||
|
import 'package:fluffychat/pages/sign_up/signup.dart';
|
||||||
import 'package:fluffychat/pages/story/story_page.dart';
|
import 'package:fluffychat/pages/story/story_page.dart';
|
||||||
import 'package:fluffychat/widgets/layouts/empty_page.dart';
|
import 'package:fluffychat/widgets/layouts/empty_page.dart';
|
||||||
import 'package:fluffychat/widgets/layouts/loading_view.dart';
|
import 'package:fluffychat/widgets/layouts/loading_view.dart';
|
||||||
@ -68,25 +71,21 @@ class AppRoutes {
|
|||||||
widget: const ChatDetails(),
|
widget: const ChatDetails(),
|
||||||
stackedRoutes: _chatDetailsRoutes,
|
stackedRoutes: _chatDetailsRoutes,
|
||||||
),
|
),
|
||||||
VWidget(
|
VWidget(path: ':roomid', widget: const Chat(), stackedRoutes: [
|
||||||
path: ':roomid',
|
VWidget(
|
||||||
widget: const ChatPage(),
|
path: 'encryption',
|
||||||
stackedRoutes: [
|
widget: const ChatEncryptionSettings(),
|
||||||
VWidget(
|
),
|
||||||
path: 'encryption',
|
VWidget(
|
||||||
widget: const ChatEncryptionSettings(),
|
path: 'invite',
|
||||||
),
|
widget: const InvitationSelection(),
|
||||||
VWidget(
|
),
|
||||||
path: 'invite',
|
VWidget(
|
||||||
widget: const InvitationSelection(),
|
path: 'details',
|
||||||
),
|
widget: const ChatDetails(),
|
||||||
VWidget(
|
stackedRoutes: _chatDetailsRoutes,
|
||||||
path: 'details',
|
),
|
||||||
widget: const ChatDetails(),
|
]),
|
||||||
stackedRoutes: _chatDetailsRoutes,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
VWidget(
|
VWidget(
|
||||||
path: '/settings',
|
path: '/settings',
|
||||||
widget: const Settings(),
|
widget: const Settings(),
|
||||||
@ -95,13 +94,6 @@ class AppRoutes {
|
|||||||
VWidget(
|
VWidget(
|
||||||
path: '/archive',
|
path: '/archive',
|
||||||
widget: const Archive(),
|
widget: const Archive(),
|
||||||
stackedRoutes: [
|
|
||||||
VWidget(
|
|
||||||
path: ':roomid',
|
|
||||||
widget: const ChatPage(),
|
|
||||||
buildTransition: _dynamicTransition,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
VWidget(
|
VWidget(
|
||||||
path: '/newprivatechat',
|
path: '/newprivatechat',
|
||||||
@ -172,14 +164,14 @@ class AppRoutes {
|
|||||||
VNester(
|
VNester(
|
||||||
path: ':roomid',
|
path: ':roomid',
|
||||||
widgetBuilder: (child) => SideViewLayout(
|
widgetBuilder: (child) => SideViewLayout(
|
||||||
mainView: const ChatPage(),
|
mainView: const Chat(),
|
||||||
sideView: child,
|
sideView: child,
|
||||||
),
|
),
|
||||||
buildTransition: _fadeTransition,
|
buildTransition: _fadeTransition,
|
||||||
nestedRoutes: [
|
nestedRoutes: [
|
||||||
VWidget(
|
VWidget(
|
||||||
path: '',
|
path: '',
|
||||||
widget: const ChatPage(),
|
widget: const Chat(),
|
||||||
buildTransition: _fadeTransition,
|
buildTransition: _fadeTransition,
|
||||||
),
|
),
|
||||||
VWidget(
|
VWidget(
|
||||||
@ -228,25 +220,13 @@ class AppRoutes {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
VNester(
|
VWidget(
|
||||||
path: '/archive',
|
path: '/archive',
|
||||||
widgetBuilder: (child) => TwoColumnLayout(
|
widget: const TwoColumnLayout(
|
||||||
mainView: const Archive(),
|
mainView: Archive(),
|
||||||
sideView: child,
|
sideView: EmptyPage(),
|
||||||
),
|
),
|
||||||
buildTransition: _fadeTransition,
|
buildTransition: _fadeTransition,
|
||||||
nestedRoutes: [
|
|
||||||
VWidget(
|
|
||||||
path: '',
|
|
||||||
widget: const EmptyPage(),
|
|
||||||
buildTransition: _dynamicTransition,
|
|
||||||
),
|
|
||||||
VWidget(
|
|
||||||
path: ':roomid',
|
|
||||||
widget: const ChatPage(),
|
|
||||||
buildTransition: _dynamicTransition,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -264,6 +244,22 @@ class AppRoutes {
|
|||||||
widget: const Login(),
|
widget: const Login(),
|
||||||
buildTransition: _fadeTransition,
|
buildTransition: _fadeTransition,
|
||||||
),
|
),
|
||||||
|
VWidget(
|
||||||
|
path: 'connect',
|
||||||
|
widget: const ConnectPage(),
|
||||||
|
buildTransition: _fadeTransition,
|
||||||
|
stackedRoutes: [
|
||||||
|
VWidget(
|
||||||
|
path: 'login',
|
||||||
|
widget: const Login(),
|
||||||
|
buildTransition: _fadeTransition,
|
||||||
|
),
|
||||||
|
VWidget(
|
||||||
|
path: 'signup',
|
||||||
|
widget: const SignupPage(),
|
||||||
|
buildTransition: _fadeTransition,
|
||||||
|
),
|
||||||
|
]),
|
||||||
VWidget(
|
VWidget(
|
||||||
path: 'logs',
|
path: 'logs',
|
||||||
widget: const LogViewer(),
|
widget: const LogViewer(),
|
||||||
@ -330,14 +326,37 @@ class AppRoutes {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
VWidget(
|
VWidget(
|
||||||
path: 'addaccount',
|
path: 'account',
|
||||||
widget: const HomeserverPicker(),
|
widget: const SettingsAccount(),
|
||||||
buildTransition: _fadeTransition,
|
buildTransition: _dynamicTransition,
|
||||||
stackedRoutes: [
|
stackedRoutes: [
|
||||||
VWidget(
|
VWidget(
|
||||||
path: 'login',
|
path: 'add',
|
||||||
widget: const Login(),
|
widget: const HomeserverPicker(),
|
||||||
buildTransition: _fadeTransition,
|
buildTransition: _fadeTransition,
|
||||||
|
stackedRoutes: [
|
||||||
|
VWidget(
|
||||||
|
path: 'login',
|
||||||
|
widget: const Login(),
|
||||||
|
buildTransition: _fadeTransition,
|
||||||
|
),
|
||||||
|
VWidget(
|
||||||
|
path: 'connect',
|
||||||
|
widget: const ConnectPage(),
|
||||||
|
buildTransition: _fadeTransition,
|
||||||
|
stackedRoutes: [
|
||||||
|
VWidget(
|
||||||
|
path: 'login',
|
||||||
|
widget: const Login(),
|
||||||
|
buildTransition: _fadeTransition,
|
||||||
|
),
|
||||||
|
VWidget(
|
||||||
|
path: 'signup',
|
||||||
|
widget: const SignupPage(),
|
||||||
|
buildTransition: _fadeTransition,
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@ -8,6 +8,7 @@ abstract class SettingKeys {
|
|||||||
static const String showDirectChatsInSpaces =
|
static const String showDirectChatsInSpaces =
|
||||||
'chat.fluffy.showDirectChatsInSpaces';
|
'chat.fluffy.showDirectChatsInSpaces';
|
||||||
static const String separateChatTypes = 'chat.fluffy.separateChatTypes';
|
static const String separateChatTypes = 'chat.fluffy.separateChatTypes';
|
||||||
|
static const String chatColor = 'chat.fluffy.chat_color';
|
||||||
static const String sentry = 'sentry';
|
static const String sentry = 'sentry';
|
||||||
static const String theme = 'theme';
|
static const String theme = 'theme';
|
||||||
static const String amoledEnabled = 'amoled_enabled';
|
static const String amoledEnabled = 'amoled_enabled';
|
||||||
|
|||||||
@ -9,10 +9,7 @@ import 'app_config.dart';
|
|||||||
abstract class FluffyThemes {
|
abstract class FluffyThemes {
|
||||||
static const double columnWidth = 360.0;
|
static const double columnWidth = 360.0;
|
||||||
|
|
||||||
static const double navRailWidth = 64.0;
|
static bool isColumnModeByWidth(double width) => width > columnWidth * 2 + 64;
|
||||||
|
|
||||||
static bool isColumnModeByWidth(double width) =>
|
|
||||||
width > columnWidth * 2 + navRailWidth;
|
|
||||||
|
|
||||||
static bool isColumnMode(BuildContext context) =>
|
static bool isColumnMode(BuildContext context) =>
|
||||||
isColumnModeByWidth(MediaQuery.of(context).size.width);
|
isColumnModeByWidth(MediaQuery.of(context).size.width);
|
||||||
@ -26,47 +23,31 @@ abstract class FluffyThemes {
|
|||||||
);
|
);
|
||||||
|
|
||||||
static var fallbackTextTheme = const TextTheme(
|
static var fallbackTextTheme = const TextTheme(
|
||||||
bodyLarge: fallbackTextStyle,
|
bodyText1: fallbackTextStyle,
|
||||||
bodyMedium: fallbackTextStyle,
|
bodyText2: fallbackTextStyle,
|
||||||
labelLarge: fallbackTextStyle,
|
button: fallbackTextStyle,
|
||||||
bodySmall: fallbackTextStyle,
|
caption: fallbackTextStyle,
|
||||||
labelSmall: fallbackTextStyle,
|
overline: fallbackTextStyle,
|
||||||
displayLarge: fallbackTextStyle,
|
headline1: fallbackTextStyle,
|
||||||
displayMedium: fallbackTextStyle,
|
headline2: fallbackTextStyle,
|
||||||
displaySmall: fallbackTextStyle,
|
headline3: fallbackTextStyle,
|
||||||
headlineMedium: fallbackTextStyle,
|
headline4: fallbackTextStyle,
|
||||||
headlineSmall: fallbackTextStyle,
|
headline5: fallbackTextStyle,
|
||||||
titleLarge: fallbackTextStyle,
|
headline6: fallbackTextStyle,
|
||||||
titleMedium: fallbackTextStyle,
|
subtitle1: fallbackTextStyle,
|
||||||
titleSmall: fallbackTextStyle,
|
subtitle2: fallbackTextStyle,
|
||||||
);
|
);
|
||||||
|
|
||||||
static LinearGradient backgroundGradient(
|
static ThemeData buildTheme(Brightness brightness,
|
||||||
BuildContext context,
|
[ColorScheme? colorScheme]) =>
|
||||||
int alpha,
|
|
||||||
) {
|
|
||||||
final colorScheme = Theme.of(context).colorScheme;
|
|
||||||
return LinearGradient(
|
|
||||||
begin: Alignment.topCenter,
|
|
||||||
colors: [
|
|
||||||
colorScheme.primaryContainer.withAlpha(alpha),
|
|
||||||
colorScheme.secondaryContainer.withAlpha(alpha),
|
|
||||||
colorScheme.tertiaryContainer.withAlpha(alpha),
|
|
||||||
colorScheme.primaryContainer.withAlpha(alpha),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const Duration animationDuration = Duration(milliseconds: 250);
|
|
||||||
static const Curve animationCurve = Curves.easeInOut;
|
|
||||||
|
|
||||||
static ThemeData buildTheme(Brightness brightness, [Color? seed]) =>
|
|
||||||
ThemeData(
|
ThemeData(
|
||||||
visualDensity: VisualDensity.standard,
|
visualDensity: VisualDensity.standard,
|
||||||
useMaterial3: true,
|
useMaterial3: true,
|
||||||
brightness: brightness,
|
brightness: brightness,
|
||||||
colorSchemeSeed: seed ?? AppConfig.colorSchemeSeed,
|
colorSchemeSeed: AppConfig.colorSchemeSeed ??
|
||||||
textTheme: PlatformInfos.isDesktop || PlatformInfos.isWeb
|
colorScheme?.primary ??
|
||||||
|
AppConfig.chatColor,
|
||||||
|
textTheme: PlatformInfos.isDesktop
|
||||||
? brightness == Brightness.light
|
? brightness == Brightness.light
|
||||||
? Typography.material2018().black.merge(fallbackTextTheme)
|
? Typography.material2018().black.merge(fallbackTextTheme)
|
||||||
: Typography.material2018().white.merge(fallbackTextTheme)
|
: Typography.material2018().white.merge(fallbackTextTheme)
|
||||||
@ -77,16 +58,8 @@ abstract class FluffyThemes {
|
|||||||
dividerColor: brightness == Brightness.light
|
dividerColor: brightness == Brightness.light
|
||||||
? Colors.blueGrey.shade50
|
? Colors.blueGrey.shade50
|
||||||
: Colors.blueGrey.shade900,
|
: Colors.blueGrey.shade900,
|
||||||
popupMenuTheme: PopupMenuThemeData(
|
inputDecorationTheme: const InputDecorationTheme(
|
||||||
shape: RoundedRectangleBorder(
|
border: InputBorder.none,
|
||||||
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
inputDecorationTheme: InputDecorationTheme(
|
|
||||||
border: UnderlineInputBorder(
|
|
||||||
borderSide: BorderSide.none,
|
|
||||||
borderRadius: BorderRadius.circular(AppConfig.borderRadius / 2),
|
|
||||||
),
|
|
||||||
filled: true,
|
filled: true,
|
||||||
),
|
),
|
||||||
appBarTheme: AppBarTheme(
|
appBarTheme: AppBarTheme(
|
||||||
@ -99,32 +72,10 @@ abstract class FluffyThemes {
|
|||||||
statusBarBrightness: brightness,
|
statusBarBrightness: brightness,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
textButtonTheme: TextButtonThemeData(
|
|
||||||
style: TextButton.styleFrom(
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(AppConfig.borderRadius / 2),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
outlinedButtonTheme: OutlinedButtonThemeData(
|
|
||||||
style: OutlinedButton.styleFrom(
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(AppConfig.borderRadius / 2),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
dialogTheme: DialogTheme(
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(AppConfig.borderRadius / 2),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
elevatedButtonTheme: ElevatedButtonThemeData(
|
elevatedButtonTheme: ElevatedButtonThemeData(
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
textStyle: const TextStyle(fontSize: 16),
|
textStyle: const TextStyle(fontSize: 16),
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@ -3,8 +3,7 @@ import 'dart:math';
|
|||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:collection/collection.dart';
|
import 'package:file_picker_cross/file_picker_cross.dart';
|
||||||
import 'package:file_picker/file_picker.dart';
|
|
||||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
import 'package:matrix/matrix.dart';
|
import 'package:matrix/matrix.dart';
|
||||||
@ -13,12 +12,12 @@ import 'package:vrouter/vrouter.dart';
|
|||||||
|
|
||||||
import 'package:fluffychat/pages/add_story/add_story_view.dart';
|
import 'package:fluffychat/pages/add_story/add_story_view.dart';
|
||||||
import 'package:fluffychat/pages/add_story/invite_story_page.dart';
|
import 'package:fluffychat/pages/add_story/invite_story_page.dart';
|
||||||
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_file_extension.dart';
|
import 'package:fluffychat/utils/matrix_sdk_extensions.dart/matrix_file_extension.dart';
|
||||||
import 'package:fluffychat/utils/resize_image.dart';
|
import 'package:fluffychat/utils/resize_image.dart';
|
||||||
import 'package:fluffychat/utils/story_theme_data.dart';
|
import 'package:fluffychat/utils/story_theme_data.dart';
|
||||||
import 'package:fluffychat/utils/string_color.dart';
|
import 'package:fluffychat/utils/string_color.dart';
|
||||||
import 'package:fluffychat/widgets/matrix.dart';
|
import 'package:fluffychat/widgets/matrix.dart';
|
||||||
import '../../utils/matrix_sdk_extensions/client_stories_extension.dart';
|
import '../../utils/matrix_sdk_extensions.dart/client_stories_extension.dart';
|
||||||
|
|
||||||
class AddStoryPage extends StatefulWidget {
|
class AddStoryPage extends StatefulWidget {
|
||||||
const AddStoryPage({Key? key}) : super(key: key);
|
const AddStoryPage({Key? key}) : super(key: key);
|
||||||
@ -69,15 +68,14 @@ class AddStoryController extends State<AddStoryPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void importMedia() async {
|
void importMedia() async {
|
||||||
final picked = await FilePicker.platform.pickFiles(
|
final picked = await FilePickerCross.importFromStorage(
|
||||||
type: FileType.image,
|
type: FileTypeCross.image,
|
||||||
withData: true,
|
|
||||||
);
|
);
|
||||||
final file = picked?.files.firstOrNull;
|
final fileName = picked.fileName;
|
||||||
if (file == null) return;
|
if (fileName == null) return;
|
||||||
final matrixFile = MatrixImageFile(
|
final matrixFile = MatrixImageFile(
|
||||||
bytes: file.bytes!,
|
bytes: picked.toUint8List(),
|
||||||
name: file.name,
|
name: fileName,
|
||||||
);
|
);
|
||||||
setState(() {
|
setState(() {
|
||||||
image = matrixFile;
|
image = matrixFile;
|
||||||
@ -90,15 +88,14 @@ class AddStoryController extends State<AddStoryPage> {
|
|||||||
);
|
);
|
||||||
if (picked == null) return;
|
if (picked == null) return;
|
||||||
final matrixFile = await showFutureLoadingDialog(
|
final matrixFile = await showFutureLoadingDialog(
|
||||||
context: context,
|
context: context,
|
||||||
future: () async {
|
future: () async {
|
||||||
final bytes = await picked.readAsBytes();
|
final bytes = await picked.readAsBytes();
|
||||||
return MatrixImageFile(
|
return MatrixImageFile(
|
||||||
bytes: bytes,
|
bytes: bytes,
|
||||||
name: picked.name,
|
name: picked.name,
|
||||||
);
|
);
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
image = matrixFile.result;
|
image = matrixFile.result;
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import 'package:future_loading_dialog/future_loading_dialog.dart';
|
|||||||
import 'package:matrix/matrix.dart';
|
import 'package:matrix/matrix.dart';
|
||||||
|
|
||||||
import 'package:fluffychat/utils/localized_exception_extension.dart';
|
import 'package:fluffychat/utils/localized_exception_extension.dart';
|
||||||
import 'package:fluffychat/utils/matrix_sdk_extensions/client_stories_extension.dart';
|
import 'package:fluffychat/utils/matrix_sdk_extensions.dart/client_stories_extension.dart';
|
||||||
import 'package:fluffychat/widgets/avatar.dart';
|
import 'package:fluffychat/widgets/avatar.dart';
|
||||||
import 'package:fluffychat/widgets/matrix.dart';
|
import 'package:fluffychat/widgets/matrix.dart';
|
||||||
|
|
||||||
@ -92,39 +92,34 @@ class InviteStoryPageState extends State<InviteStoryPage> {
|
|||||||
const Divider(height: 1),
|
const Divider(height: 1),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: FutureBuilder<List<User>>(
|
child: FutureBuilder<List<User>>(
|
||||||
future: loadContacts,
|
future: loadContacts,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
final contacts = snapshot.data;
|
final contacts = snapshot.data;
|
||||||
if (contacts == null) {
|
if (contacts == null) {
|
||||||
final error = snapshot.error;
|
final error = snapshot.error;
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
return Center(
|
return Center(
|
||||||
child: Text(error.toLocalizedString(context)),
|
child: Text(error.toLocalizedString(context)));
|
||||||
);
|
}
|
||||||
|
return const Center(
|
||||||
|
child: CircularProgressIndicator.adaptive());
|
||||||
}
|
}
|
||||||
return const Center(
|
_undecided = contacts.map((u) => u.id).toSet();
|
||||||
child: CircularProgressIndicator.adaptive(),
|
return ListView.builder(
|
||||||
);
|
itemCount: contacts.length,
|
||||||
}
|
itemBuilder: (context, i) => SwitchListTile.adaptive(
|
||||||
_undecided = contacts.map((u) => u.id).toSet();
|
value: _invite.contains(contacts[i].id),
|
||||||
return ListView.builder(
|
onChanged: (b) => setState(() => b
|
||||||
itemCount: contacts.length,
|
|
||||||
itemBuilder: (context, i) => SwitchListTile.adaptive(
|
|
||||||
value: _invite.contains(contacts[i].id),
|
|
||||||
onChanged: (b) => setState(
|
|
||||||
() => b
|
|
||||||
? _invite.add(contacts[i].id)
|
? _invite.add(contacts[i].id)
|
||||||
: _invite.remove(contacts[i].id),
|
: _invite.remove(contacts[i].id)),
|
||||||
|
secondary: Avatar(
|
||||||
|
mxContent: contacts[i].avatarUrl,
|
||||||
|
name: contacts[i].calcDisplayname(),
|
||||||
|
),
|
||||||
|
title: Text(contacts[i].calcDisplayname()),
|
||||||
),
|
),
|
||||||
secondary: Avatar(
|
);
|
||||||
mxContent: contacts[i].avatarUrl,
|
}),
|
||||||
name: contacts[i].calcDisplayname(),
|
|
||||||
),
|
|
||||||
title: Text(contacts[i].calcDisplayname()),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@ -21,9 +21,11 @@ class ArchiveController extends State<Archive> {
|
|||||||
Future<List<Room>> getArchive(BuildContext context) async {
|
Future<List<Room>> getArchive(BuildContext context) async {
|
||||||
final archive = this.archive;
|
final archive = this.archive;
|
||||||
if (archive != null) return archive;
|
if (archive != null) return archive;
|
||||||
return this.archive = await Matrix.of(context).client.loadArchive();
|
return await Matrix.of(context).client.loadArchive();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void forgetAction(int i) => setState(() => archive?.removeAt(i));
|
||||||
|
|
||||||
void forgetAllAction() async {
|
void forgetAllAction() async {
|
||||||
final archive = this.archive;
|
final archive = this.archive;
|
||||||
if (archive == null) return;
|
if (archive == null) return;
|
||||||
@ -42,7 +44,7 @@ class ArchiveController extends State<Archive> {
|
|||||||
context: context,
|
context: context,
|
||||||
future: () async {
|
future: () async {
|
||||||
while (archive.isNotEmpty) {
|
while (archive.isNotEmpty) {
|
||||||
Logs().v('Forget room ${archive.last.getLocalizedDisplayname()}');
|
Logs().v('Forget room ${archive.last.displayname}');
|
||||||
await archive.last.forget();
|
await archive.last.forget();
|
||||||
archive.removeLast();
|
archive.removeLast();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,14 +21,10 @@ class ArchiveView extends StatelessWidget {
|
|||||||
leading: const BackButton(),
|
leading: const BackButton(),
|
||||||
title: Text(L10n.of(context)!.archive),
|
title: Text(L10n.of(context)!.archive),
|
||||||
actions: [
|
actions: [
|
||||||
if (snapshot.data?.isNotEmpty ?? false)
|
if (snapshot.hasData && archive != null && archive!.isNotEmpty)
|
||||||
Padding(
|
TextButton(
|
||||||
padding: const EdgeInsets.all(8.0),
|
onPressed: controller.forgetAllAction,
|
||||||
child: TextButton.icon(
|
child: Text(L10n.of(context)!.clearArchive),
|
||||||
onPressed: controller.forgetAllAction,
|
|
||||||
label: Text(L10n.of(context)!.clearArchive),
|
|
||||||
icon: const Icon(Icons.cleaning_services_outlined),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -36,27 +32,25 @@ class ArchiveView extends StatelessWidget {
|
|||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
if (snapshot.hasError) {
|
if (snapshot.hasError) {
|
||||||
return Center(
|
return Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
L10n.of(context)!.oopsSomethingWentWrong,
|
L10n.of(context)!.oopsSomethingWentWrong,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (!snapshot.hasData) {
|
if (!snapshot.hasData) {
|
||||||
return const Center(
|
return const Center(
|
||||||
child: CircularProgressIndicator.adaptive(strokeWidth: 2),
|
child: CircularProgressIndicator.adaptive(strokeWidth: 2));
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
archive = snapshot.data;
|
archive = snapshot.data;
|
||||||
if (archive == null || archive!.isEmpty) {
|
if (archive == null || archive!.isEmpty) {
|
||||||
return const Center(
|
return const Center(
|
||||||
child: Icon(Icons.archive_outlined, size: 80),
|
child: Icon(Icons.archive_outlined, size: 80));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
itemCount: archive!.length,
|
itemCount: archive!.length,
|
||||||
itemBuilder: (BuildContext context, int i) => ChatListItem(
|
itemBuilder: (BuildContext context, int i) => ChatListItem(
|
||||||
archive![i],
|
archive![i],
|
||||||
|
onForget: controller.forgetAction,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -125,12 +125,9 @@ class BootstrapDialogState extends State<BootstrapDialog> {
|
|||||||
children: [
|
children: [
|
||||||
ListTile(
|
ListTile(
|
||||||
contentPadding: const EdgeInsets.symmetric(horizontal: 8.0),
|
contentPadding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||||
trailing: CircleAvatar(
|
trailing: Icon(
|
||||||
backgroundColor: Colors.transparent,
|
Icons.info_outlined,
|
||||||
child: Icon(
|
color: Theme.of(context).colorScheme.primary,
|
||||||
Icons.info_outlined,
|
|
||||||
color: Theme.of(context).colorScheme.primary,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
subtitle: Text(L10n.of(context)!.chatBackupDescription),
|
subtitle: Text(L10n.of(context)!.chatBackupDescription),
|
||||||
),
|
),
|
||||||
@ -139,15 +136,10 @@ class BootstrapDialogState extends State<BootstrapDialog> {
|
|||||||
thickness: 1,
|
thickness: 1,
|
||||||
),
|
),
|
||||||
TextField(
|
TextField(
|
||||||
minLines: 2,
|
minLines: 4,
|
||||||
maxLines: 4,
|
maxLines: 4,
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
style: const TextStyle(fontFamily: 'RobotoMono'),
|
|
||||||
controller: TextEditingController(text: key),
|
controller: TextEditingController(text: key),
|
||||||
decoration: const InputDecoration(
|
|
||||||
contentPadding: EdgeInsets.all(16),
|
|
||||||
suffixIcon: Icon(Icons.key_outlined),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
if (_supportsSecureStorage)
|
if (_supportsSecureStorage)
|
||||||
@ -241,13 +233,12 @@ class BootstrapDialogState extends State<BootstrapDialog> {
|
|||||||
icon: const Icon(Icons.close),
|
icon: const Icon(Icons.close),
|
||||||
onPressed: Navigator.of(context).pop,
|
onPressed: Navigator.of(context).pop,
|
||||||
),
|
),
|
||||||
title: Text(L10n.of(context)!.chatBackup),
|
title: Text(L10n.of(context)!.unlockOldMessages),
|
||||||
),
|
),
|
||||||
body: Center(
|
body: Center(
|
||||||
child: ConstrainedBox(
|
child: ConstrainedBox(
|
||||||
constraints: const BoxConstraints(
|
constraints: const BoxConstraints(
|
||||||
maxWidth: FluffyThemes.columnWidth * 1.5,
|
maxWidth: FluffyThemes.columnWidth * 1.5),
|
||||||
),
|
|
||||||
child: ListView(
|
child: ListView(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
children: [
|
children: [
|
||||||
@ -259,85 +250,74 @@ class BootstrapDialogState extends State<BootstrapDialog> {
|
|||||||
color: Theme.of(context).colorScheme.primary,
|
color: Theme.of(context).colorScheme.primary,
|
||||||
),
|
),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
L10n.of(context)!.pleaseEnterRecoveryKeyDescription,
|
L10n.of(context)!.pleaseEnterRecoveryKeyDescription),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const Divider(height: 32),
|
const Divider(height: 32),
|
||||||
TextField(
|
TextField(
|
||||||
minLines: 1,
|
minLines: 1,
|
||||||
maxLines: 2,
|
maxLines: 1,
|
||||||
autocorrect: false,
|
autocorrect: false,
|
||||||
readOnly: _recoveryKeyInputLoading,
|
readOnly: _recoveryKeyInputLoading,
|
||||||
autofillHints: _recoveryKeyInputLoading
|
autofillHints: _recoveryKeyInputLoading
|
||||||
? null
|
? null
|
||||||
: [AutofillHints.password],
|
: [AutofillHints.password],
|
||||||
controller: _recoveryKeyTextEditingController,
|
controller: _recoveryKeyTextEditingController,
|
||||||
style: const TextStyle(fontFamily: 'RobotoMono'),
|
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
contentPadding: const EdgeInsets.all(16),
|
hintText: 'Abc123 Def456',
|
||||||
hintStyle: TextStyle(
|
labelText: L10n.of(context)!.recoveryKey,
|
||||||
fontFamily:
|
|
||||||
Theme.of(context).textTheme.bodyLarge?.fontFamily,
|
|
||||||
),
|
|
||||||
hintText: L10n.of(context)!.recoveryKey,
|
|
||||||
errorText: _recoveryKeyInputError,
|
errorText: _recoveryKeyInputError,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
ElevatedButton.icon(
|
ElevatedButton.icon(
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
foregroundColor:
|
foregroundColor:
|
||||||
Theme.of(context).colorScheme.onPrimary,
|
Theme.of(context).colorScheme.onPrimary,
|
||||||
backgroundColor: Theme.of(context).primaryColor,
|
backgroundColor: Theme.of(context).primaryColor,
|
||||||
),
|
|
||||||
icon: _recoveryKeyInputLoading
|
|
||||||
? const CircularProgressIndicator.adaptive()
|
|
||||||
: const Icon(Icons.lock_open_outlined),
|
|
||||||
label: Text(L10n.of(context)!.unlockOldMessages),
|
|
||||||
onPressed: _recoveryKeyInputLoading
|
|
||||||
? null
|
|
||||||
: () async {
|
|
||||||
setState(() {
|
|
||||||
_recoveryKeyInputError = null;
|
|
||||||
_recoveryKeyInputLoading = true;
|
|
||||||
});
|
|
||||||
try {
|
|
||||||
final key =
|
|
||||||
_recoveryKeyTextEditingController.text;
|
|
||||||
await bootstrap.newSsssKey!.unlock(
|
|
||||||
keyOrPassphrase: key,
|
|
||||||
);
|
|
||||||
Logs().d('SSSS unlocked');
|
|
||||||
await bootstrap.client.encryption!.crossSigning
|
|
||||||
.selfSign(
|
|
||||||
keyOrPassphrase: key,
|
|
||||||
);
|
|
||||||
Logs().d('Successful elfsigned');
|
|
||||||
await bootstrap.openExistingSsss();
|
|
||||||
} catch (e, s) {
|
|
||||||
Logs().w('Unable to unlock SSSS', e, s);
|
|
||||||
setState(
|
|
||||||
() => _recoveryKeyInputError =
|
|
||||||
L10n.of(context)!.oopsSomethingWentWrong,
|
|
||||||
);
|
|
||||||
} finally {
|
|
||||||
setState(
|
|
||||||
() => _recoveryKeyInputLoading = false,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
const Expanded(child: Divider()),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(12.0),
|
|
||||||
child: Text(L10n.of(context)!.or),
|
|
||||||
),
|
),
|
||||||
const Expanded(child: Divider()),
|
icon: _recoveryKeyInputLoading
|
||||||
],
|
? const CircularProgressIndicator.adaptive()
|
||||||
),
|
: const Icon(Icons.lock_open_outlined),
|
||||||
|
label: Text(L10n.of(context)!.unlockOldMessages),
|
||||||
|
onPressed: _recoveryKeyInputLoading
|
||||||
|
? null
|
||||||
|
: () async {
|
||||||
|
setState(() {
|
||||||
|
_recoveryKeyInputError = null;
|
||||||
|
_recoveryKeyInputLoading = true;
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
final key =
|
||||||
|
_recoveryKeyTextEditingController.text;
|
||||||
|
await bootstrap.newSsssKey!.unlock(
|
||||||
|
keyOrPassphrase: key,
|
||||||
|
);
|
||||||
|
Logs().d('SSSS unlocked');
|
||||||
|
await bootstrap
|
||||||
|
.client.encryption!.crossSigning
|
||||||
|
.selfSign(
|
||||||
|
keyOrPassphrase: key,
|
||||||
|
);
|
||||||
|
Logs().d('Successful elfsigned');
|
||||||
|
await bootstrap.openExistingSsss();
|
||||||
|
} catch (e, s) {
|
||||||
|
Logs().w('Unable to unlock SSSS', e, s);
|
||||||
|
setState(() => _recoveryKeyInputError =
|
||||||
|
L10n.of(context)!.oopsSomethingWentWrong);
|
||||||
|
} finally {
|
||||||
|
setState(
|
||||||
|
() => _recoveryKeyInputLoading = false);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Row(children: [
|
||||||
|
const Expanded(child: Divider()),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(12.0),
|
||||||
|
child: Text(L10n.of(context)!.or),
|
||||||
|
),
|
||||||
|
const Expanded(child: Divider()),
|
||||||
|
]),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
ElevatedButton.icon(
|
ElevatedButton.icon(
|
||||||
icon: const Icon(Icons.cast_connected_outlined),
|
icon: const Icon(Icons.cast_connected_outlined),
|
||||||
@ -414,13 +394,11 @@ class BootstrapDialogState extends State<BootstrapDialog> {
|
|||||||
case BootstrapState.error:
|
case BootstrapState.error:
|
||||||
titleText = L10n.of(context)!.oopsSomethingWentWrong;
|
titleText = L10n.of(context)!.oopsSomethingWentWrong;
|
||||||
body = const Icon(Icons.error_outline, color: Colors.red, size: 40);
|
body = const Icon(Icons.error_outline, color: Colors.red, size: 40);
|
||||||
buttons.add(
|
buttons.add(AdaptiveFlatButton(
|
||||||
AdaptiveFlatButton(
|
label: L10n.of(context)!.close,
|
||||||
label: L10n.of(context)!.close,
|
onPressed: () =>
|
||||||
onPressed: () =>
|
Navigator.of(context, rootNavigator: false).pop<bool>(false),
|
||||||
Navigator.of(context, rootNavigator: false).pop<bool>(false),
|
));
|
||||||
),
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case BootstrapState.done:
|
case BootstrapState.done:
|
||||||
titleText = L10n.of(context)!.everythingReady;
|
titleText = L10n.of(context)!.everythingReady;
|
||||||
@ -431,13 +409,11 @@ class BootstrapDialogState extends State<BootstrapDialog> {
|
|||||||
Text(L10n.of(context)!.yourChatBackupHasBeenSetUp),
|
Text(L10n.of(context)!.yourChatBackupHasBeenSetUp),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
buttons.add(
|
buttons.add(AdaptiveFlatButton(
|
||||||
AdaptiveFlatButton(
|
label: L10n.of(context)!.close,
|
||||||
label: L10n.of(context)!.close,
|
onPressed: () =>
|
||||||
onPressed: () =>
|
Navigator.of(context, rootNavigator: false).pop<bool>(false),
|
||||||
Navigator.of(context, rootNavigator: false).pop<bool>(false),
|
));
|
||||||
),
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -75,8 +75,7 @@ class AddWidgetTileState extends State<AddWidgetTile> {
|
|||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(content: Text(L10n.of(context)!.errorAddingWidget)),
|
SnackBar(content: Text(L10n.of(context)!.errorAddingWidget)));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||