diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 2b993ea05..7e75afa95 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -1,20 +1,22 @@
-version: 2
-updates:
- - package-ecosystem: "pub"
- directory: "/"
- schedule:
- interval: "daily"
- allow:
- - dependency-name: "*"
- commit-message:
- prefix: "build: "
- include: "scope"
- - package-ecosystem: "github-actions"
- directory: "/"
- schedule:
- interval: "daily"
- allow:
- - dependency-name: "*"
- commit-message:
- prefix: "build: "
- include: "scope"
+# #Pangea
+# version: 2
+# updates:
+# - package-ecosystem: "pub"
+# directory: "/"
+# schedule:
+# interval: "daily"
+# allow:
+# - dependency-name: "*"
+# commit-message:
+# prefix: "build: "
+# include: "scope"
+# - package-ecosystem: "github-actions"
+# directory: "/"
+# schedule:
+# interval: "daily"
+# allow:
+# - dependency-name: "*"
+# commit-message:
+# prefix: "build: "
+# include: "scope"
+# Pangea#
diff --git a/.github/workflows/auto_pull_request.yaml b/.github/workflows/auto_pull_request.yaml
deleted file mode 100644
index cf6bb228c..000000000
--- a/.github/workflows/auto_pull_request.yaml
+++ /dev/null
@@ -1,41 +0,0 @@
-name: Auto Pull Request
-
-#on:
-# schedule:
-# - cron: '0 0 * * 0' # Run at midnight (00:00) every Sunday
-
-on:
- push:
- branches:
- - auto-pr # Change this to match your main branch name
-
-jobs:
- auto_pull_request:
- runs-on: ubuntu-latest
-
- steps:
- - name: Checkout code
- uses: actions/checkout@v4
- - name: Test
- run: echo ${{ github.head_ref }}.${{ github.sha }}
-
- - name: Pull changes from FluffyChat
- run: |
- git config --global user.email "${{ vars.CI_EMAIL }}"
- git config --global user.name "${{ vars.CI_USERNAME }}"
- git remote add fluffychat https://github.com/krille-chan/fluffychat
- git fetch fluffychat main
- git merge --no-edit fluffychat/main --allow-unrelated-histories
-
- - name: Push changes
- run: |
- git push origin HEAD:main-update-fluffy-automatic
-
- - name: Create Pull Request
- uses: peter-evans/create-pull-request@v3
- with:
- token: ${{ secrets.GH_TOKEN }}
- title: Updated fork with new fluffy changes
- body: |
- This is an automatic PR created by GitHub Actions.
- branch: main
diff --git a/.github/workflows/build-ios.yml b/.github/workflows/build-ios.yml
deleted file mode 100644
index aa7a13d70..000000000
--- a/.github/workflows/build-ios.yml
+++ /dev/null
@@ -1,79 +0,0 @@
-name: build-ios
-on:
- workflow_call:
- inputs:
- screenshot:
- type: string
- required: true
- ipa:
- description: 'Run IPA build'
- type: string
- required: true
- workflow_dispatch:
- inputs:
- screenshot:
- description: 'Run screenshot build'
- type: choice
- options: ['true', 'false']
- required: true
- ipa:
- description: 'Run IPA build'
- type: choice
- options: ['true', 'false']
- required: true
-
-
-jobs:
- build-ios:
- runs-on: macos-latest
- timeout-minutes: 20
- defaults:
- run:
- working-directory: ios
- steps:
- - uses: actions/checkout@v4
- with:
- fetch-depth: 0
-
- - run: 'echo "$API_KEY" | base64 --decode > AuthKey.p8'
- shell: bash
- env:
- API_KEY: ${{ secrets.APP_STORE_CONNECT_API_KEY }}
-
- - run: bundle install
-
- - run: bundle exec fastlane versioning
-
- - name: Flutter
- uses: subosito/flutter-action@v2
- with:
- cache: true
- cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
- cache-path: "${{ runner.tool_cache }}/flutter/:channel:-:version:-:arch:"
- - run: flutter build ios --simulator --target=integration_test/screenshot_test.dart
- if: ${{ inputs.screenshot == 'true' }}
-
- - name: Archive integration ipa
- if: ${{ inputs.screenshot == 'true' }}
- uses: actions/upload-artifact@v4
- with:
- name: app-simulator-build
- path: build/ios/iphonesimulator/Runner.app
- if-no-files-found: error
- retention-days: 3
-
- # Build ios Release
- - run: flutter build ios --release --config-only --no-codesign --target=lib/main.dart
- if: ${{ inputs.ipa == 'true' }}
-
- - run: bundle exec fastlane build
- if: ${{ inputs.ipa == 'true' }}
-
- - name: Archive ipa
- if: ${{ inputs.ipa == 'true' }}
- uses: actions/upload-artifact@v4
- with:
- name: Runner.ipa
- path: ios/Runner.ipa
- if-no-files-found: error
- retention-days: 3
\ No newline at end of file
diff --git a/.github/workflows/dart_format.yaml b/.github/workflows/dart_format.yaml
deleted file mode 100644
index 5e1a142c5..000000000
--- a/.github/workflows/dart_format.yaml
+++ /dev/null
@@ -1,39 +0,0 @@
-# name: Dart Code Formatter
-
-# on:
-# pull_request:
-# push:
-# branches: main
-
-# jobs:
-# format:
-# runs-on: ubuntu-latest
-
-# steps:
-# - name: Checkout code
-# uses: actions/checkout@v3
-# with:
-# ref: ${{ github.head_ref }}
-
-# - run: cat .github/workflows/versions.env >> $GITHUB_ENV
-# - uses: subosito/flutter-action@v2
-# with:
-# flutter-version: ${{ env.FLUTTER_VERSION }}
-# cache: true
-
-# - name: Auto-format Dart code
-# run: |
-# dart format lib/ test/
-# dart run import_sorter:main --no-comments
-# if ! git diff --exit-code; then
-# git config user.name "github-actions[bot]"
-# git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
-# git add .
-# git commit -m "generated"
-# git push
-# fi
-
-# - name: Check for unformatted files
-# if: ${{ failure() }}
-# run: |
-# echo "Code was formatted. Please verify the changes in the PR."
diff --git a/.github/workflows/integrate.yaml b/.github/workflows/integrate.yaml
index c4307fadf..dc4df96cf 100644
--- a/.github/workflows/integrate.yaml
+++ b/.github/workflows/integrate.yaml
@@ -1,107 +1,105 @@
-name: Pull Request Workflow
+# #Pangea
+# name: Pull Request Workflow
-on:
- pull_request:
- merge_group:
+# on:
+# pull_request:
+# merge_group:
-jobs:
- code_tests:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - run: ./scripts/generate-locale-config.sh
- - run: git diff --exit-code
- - run: cat .github/workflows/versions.env >> $GITHUB_ENV
- - uses: subosito/flutter-action@v2
- with:
- flutter-version: ${{ env.FLUTTER_VERSION }}
- cache: true
- - run: flutter pub get
- - run: flutter gen-l10n
- - name: Check formatting
- run: dart format lib/ test/ --set-exit-if-changed
- - name: Check import formatting
- run: dart run import_sorter:main --no-comments --exit-if-changed
- - name: Check license compliance
- run: dart run license_checker check-licenses -c licenses.yaml --problematic
- - run: flutter analyze
- # #Pangea - Commented out the following lines, we already have fcm enabled by default
- # - name: Apply google services patch
- # run: git apply ./scripts/enable-android-google-services.patch
- # Pangea#
- - run: flutter analyze
- - run: flutter test
+# jobs:
+# code_tests:
+# runs-on: ubuntu-latest
+# steps:
+# - uses: actions/checkout@v4
+# - run: ./scripts/generate-locale-config.sh
+# - run: git diff --exit-code
+# - run: cat .github/workflows/versions.env >> $GITHUB_ENV
+# - uses: subosito/flutter-action@v2
+# with:
+# flutter-version: ${{ env.FLUTTER_VERSION }}
+# cache: true
+# - run: flutter pub get
+# - run: flutter gen-l10n
+# - name: Check formatting
+# run: dart format lib/ test/ --set-exit-if-changed
+# - name: Check import formatting
+# run: dart run import_sorter:main --no-comments --exit-if-changed
+# - name: Check license compliance
+# run: dart run license_checker check-licenses -c licenses.yaml --problematic
+# - run: flutter analyze
+# - name: Apply google services patch
+# run: git apply ./scripts/enable-android-google-services.patch
+# - run: flutter analyze
+# - run: flutter test
- build_apk:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - run: cat .github/workflows/versions.env >> $GITHUB_ENV
- - uses: actions/setup-java@v4
- with:
- java-version: ${{ env.JAVA_VERSION }}
- distribution: "zulu"
- - uses: subosito/flutter-action@v2
- with:
- flutter-version: ${{ env.FLUTTER_VERSION }}
- cache: false
- - run: flutter pub get
- - name: Free Disk Space (Ubuntu)
- uses: jlumbroso/free-disk-space@main
- with:
- # this might remove tools that are actually needed,
- # if set to "true" but frees about 6 GB
- tool-cache: false
- android: false
- - run: flutter build apk --debug
+# build_apk:
+# runs-on: ubuntu-latest
+# steps:
+# - uses: actions/checkout@v4
+# - run: cat .github/workflows/versions.env >> $GITHUB_ENV
+# - uses: actions/setup-java@v4
+# with:
+# java-version: ${{ env.JAVA_VERSION }}
+# distribution: "zulu"
+# - uses: subosito/flutter-action@v2
+# with:
+# flutter-version: ${{ env.FLUTTER_VERSION }}
+# cache: false
+# - run: flutter pub get
+# - name: Free Disk Space (Ubuntu)
+# uses: jlumbroso/free-disk-space@main
+# with:
+# # this might remove tools that are actually needed,
+# # if set to "true" but frees about 6 GB
+# tool-cache: false
+# android: false
+# - run: flutter build apk --debug
- build_web:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - run: cat .github/workflows/versions.env >> $GITHUB_ENV
- - uses: subosito/flutter-action@v2
- with:
- flutter-version: ${{ env.FLUTTER_VERSION }}
- cache: false
- - run: flutter pub get
- - name: Prepare web
- run: ./scripts/prepare-web.sh
- - run: flutter build web
+# build_web:
+# runs-on: ubuntu-latest
+# steps:
+# - uses: actions/checkout@v4
+# - run: cat .github/workflows/versions.env >> $GITHUB_ENV
+# - uses: subosito/flutter-action@v2
+# with:
+# flutter-version: ${{ env.FLUTTER_VERSION }}
+# cache: false
+# - run: flutter pub get
+# - name: Prepare web
+# run: ./scripts/prepare-web.sh
+# - run: flutter build web
- # #Pangea
- # commented out because we do not build Pangea Chat to linux
- # build_debug_linux:
- # strategy:
- # matrix:
- # arch: [ x64, arm64 ]
- # runs-on: ${{ matrix.arch == 'arm64' && 'self-hosted' || 'ubuntu-latest'}}
- # steps:
- # - uses: actions/checkout@v4
- # - run: cat .github/workflows/versions.env >> $GITHUB_ENV
- # - name: Install dependencies
- # run: sudo apt-get update && sudo apt-get install git wget curl clang cmake ninja-build pkg-config libgtk-3-dev libblkid-dev liblzma-dev libjsoncpp-dev cmake-data libsecret-1-dev libsecret-1-0 librhash0 libssl-dev libwebkit2gtk-4.1-dev -y
- # - name: Install Flutter
- # run: |
- # git clone --branch ${{ env.FLUTTER_VERSION }} https://github.com/flutter/flutter.git
- # ./flutter/bin/flutter doctor
- # - run: ./flutter/bin/flutter pub get
- # - run: ./flutter/bin/flutter build linux --target-platform linux-${{ matrix.arch }}
- # Pangea#
+# commented out because we do not build Pangea Chat to linux
+# build_debug_linux:
+# strategy:
+# matrix:
+# arch: [ x64, arm64 ]
+# runs-on: ${{ matrix.arch == 'arm64' && 'self-hosted' || 'ubuntu-latest'}}
+# steps:
+# - uses: actions/checkout@v4
+# - run: cat .github/workflows/versions.env >> $GITHUB_ENV
+# - name: Install dependencies
+# run: sudo apt-get update && sudo apt-get install git wget curl clang cmake ninja-build pkg-config libgtk-3-dev libblkid-dev liblzma-dev libjsoncpp-dev cmake-data libsecret-1-dev libsecret-1-0 librhash0 libssl-dev libwebkit2gtk-4.1-dev -y
+# - name: Install Flutter
+# run: |
+# git clone --branch ${{ env.FLUTTER_VERSION }} https://github.com/flutter/flutter.git
+# ./flutter/bin/flutter doctor
+# - run: ./flutter/bin/flutter pub get
+# - run: ./flutter/bin/flutter build linux --target-platform linux-${{ matrix.arch }}
- build_debug_ios:
- runs-on: macos-15
- steps:
- - uses: actions/checkout@v4
- - run: cat .github/workflows/versions.env >> $GITHUB_ENV
- - uses: subosito/flutter-action@v2
- with:
- flutter-version: ${{ env.FLUTTER_VERSION }}
- cache: true
- - name: Setup Xcode version
- uses: maxim-lobanov/setup-xcode@v1.6.0
- with:
- xcode-version: latest
- - run: brew install sqlcipher
- - run: flutter pub get
- - run: flutter build ipa --no-codesign
+# build_debug_ios:
+# runs-on: macos-15
+# steps:
+# - uses: actions/checkout@v4
+# - run: cat .github/workflows/versions.env >> $GITHUB_ENV
+# - uses: subosito/flutter-action@v2
+# with:
+# flutter-version: ${{ env.FLUTTER_VERSION }}
+# cache: true
+# - name: Setup Xcode version
+# uses: maxim-lobanov/setup-xcode@v1.6.0
+# with:
+# xcode-version: latest
+# - run: brew install sqlcipher
+# - run: flutter pub get
+# - run: flutter build ipa --no-codesign
+# Pangea#
diff --git a/.github/workflows/manual.yml b/.github/workflows/manual.yml
index 1999c49d3..e9d809e60 100644
--- a/.github/workflows/manual.yml
+++ b/.github/workflows/manual.yml
@@ -77,13 +77,4 @@ jobs:
bundle install
bundle update fastlane
bundle exec fastlane deploy_internal_test
- cd ..
-
- deploy_ios_testflight: # stashed on old.yml
- environment:
- name: ${{ inputs.environment }}
- env:
- WEB_APP_ENV: ${{ vars.WEB_APP_ENV }}
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
\ No newline at end of file
+ cd ..
\ No newline at end of file
diff --git a/.github/workflows/matrix_notification.yaml b/.github/workflows/matrix_notification.yaml
deleted file mode 100644
index 1d6dd8085..000000000
--- a/.github/workflows/matrix_notification.yaml
+++ /dev/null
@@ -1,26 +0,0 @@
-# name: Matrix Notification
-
-# on:
-# issues:
-# types: [ opened ]
-# issue_comment:
-# types: [ created ]
-
-# jobs:
-# notify:
-# runs-on: ubuntu-latest
-
-# steps:
-# - name: Send Matrix Notification
-# env:
-# MATRIX_URL: https://matrix.janian.de/_matrix/client/v3/rooms/${{ secrets.MATRIX_MANAGEMENT_ROOM }}/send/m.room.message
-# run: |
-# if [ "${{ github.event.action }}" == "opened" ]; then
-# PAYLOAD="{\"msgtype\": \"m.notice\", \"body\": \"New Issue from ${{ github.event.issue.user.login }}\\n${{ github.event.issue.title }}\\n\\n${{ github.event.issue.body }}\\n\\nURL: ${{ github.event.issue.html_url }}\"}"
-# elif [ "${{ github.event.action }}" == "created" ]; then
-# PAYLOAD="{\"msgtype\": \"m.notice\", \"body\": \"New Comment from ${{ github.event.comment.user.login }}\\n\\n${{ github.event.comment.body }}\\n\\nURL: ${{ github.event.comment.html_url }}\"}"
-# fi
-# curl -X POST -H "Authorization: Bearer ${{ secrets.MATRIX_BOT_TOKEN }}" \
-# -H "Content-Type: application/json" \
-# -d "$PAYLOAD" \
-# $MATRIX_URL
diff --git a/.github/workflows/old.yml b/.github/workflows/old.yml
deleted file mode 100644
index 62d57416b..000000000
--- a/.github/workflows/old.yml
+++ /dev/null
@@ -1,44 +0,0 @@
-name: Old Release Workflow
-
-on:
- push:
- branches:
- - master-unused
-
-concurrency:
- group: release_workflow
- cancel-in-progress: true
-
-jobs:
- deploy_ios_internal:
- runs-on: macos-latest
- environment: staging
- steps:
- - uses: actions/checkout@v4
- - run: cat ../.github/workflows/versions.env >> $GITHUB_ENV
-
- - name: Flutter
- uses: subosito/flutter-action@v2
- with:
- cache: true
- cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
- cache-path: "${{ runner.tool_cache }}/flutter/:channel:-:version:-:arch:"
-
- # Build ios Release
- - run: flutter build ios --release --config-only --no-codesign --target=lib/main.dart
-
- - name: Deploy ios
- run: |
- mkdir -p build/ios
- cp build/app/outputs/bundle/release/app-release.aab build/ios/
- cd ios
- bundle install
- bundle update fastlane
- cd ..
- - name: Execute fastlane signing
- env:
- APP_STORE_CONNECT_API_KEY_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ISSUER_ID }}
- APP_STORE_CONNECT_API_KEY_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_KEY_ID }}
- APP_STORE_CONNECT_API_KEY_IS_KEY_CONTENT_BASE64: ${{ secrets.APP_STORE_CONNECT_API_KEY_IS_KEY_CONTENT_BASE64 }}
- APP_STORE_CONNECT_API_KEY_KEY: ${{ secrets.APP_STORE_CONNECT_API_KEY_KEY }}
- run: bundle exec fastlane ios beta
\ No newline at end of file
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index b6751456d..51705779a 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -142,36 +142,39 @@ jobs:
asset_path: build/app/outputs/flutter-apk/app-release.apk
asset_name: pangeachat.apk
asset_content_type: application/vnd.android.package-archive
- build_linux:
- strategy:
- matrix:
- arch: [ x64 ]
- runs-on: ubuntu-latest
- needs: create_release
- steps:
- - uses: actions/checkout@v4
- - run: cat .github/workflows/versions.env >> $GITHUB_ENV
- - name: Install dependencies
- run: sudo apt-get update && sudo apt-get install curl clang cmake ninja-build pkg-config libgtk-3-dev libblkid-dev liblzma-dev libjsoncpp-dev cmake-data libsecret-1-dev libsecret-1-0 librhash0 libssl-dev libwebkit2gtk-4.1-dev -y
- - name: Install dependencies for audio-player
- run: sudo apt-get install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev
- - name: Install Flutter
- run: |
- git clone --branch ${{ env.FLUTTER_VERSION }} https://github.com/flutter/flutter.git
- ./flutter/bin/flutter doctor
- - run: ./flutter/bin/flutter pub get
- - run: ./flutter/bin/flutter build linux --target-platform linux-${{ matrix.arch }}
- - name: Create archive
- run: tar -czf pangeachat-linux-${{ matrix.arch }}.tar.gz -C build/linux/${{ matrix.arch }}/release/bundle/ .
- - name: Upload to release
- uses: actions/upload-release-asset@v1
- env:
- GITHUB_TOKEN: ${{ secrets.PAGES_DEPLOY_TOKEN }}
- with:
- upload_url: ${{ needs.create_release.outputs.upload_url }}
- asset_path: pangeachat-linux-${{ matrix.arch }}.tar.gz
- asset_name: pangeachat-linux-${{ matrix.arch }}.tar.gz
- asset_content_type: application/gzip
+
+ # #Pangea
+ # build_linux:
+ # strategy:
+ # matrix:
+ # arch: [ x64 ]
+ # runs-on: ubuntu-latest
+ # needs: create_release
+ # steps:
+ # - uses: actions/checkout@v4
+ # - run: cat .github/workflows/versions.env >> $GITHUB_ENV
+ # - name: Install dependencies
+ # run: sudo apt-get update && sudo apt-get install curl clang cmake ninja-build pkg-config libgtk-3-dev libblkid-dev liblzma-dev libjsoncpp-dev cmake-data libsecret-1-dev libsecret-1-0 librhash0 libssl-dev libwebkit2gtk-4.1-dev -y
+ # - name: Install dependencies for audio-player
+ # run: sudo apt-get install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev
+ # - name: Install Flutter
+ # run: |
+ # git clone --branch ${{ env.FLUTTER_VERSION }} https://github.com/flutter/flutter.git
+ # ./flutter/bin/flutter doctor
+ # - run: ./flutter/bin/flutter pub get
+ # - run: ./flutter/bin/flutter build linux --target-platform linux-${{ matrix.arch }}
+ # - name: Create archive
+ # run: tar -czf pangeachat-linux-${{ matrix.arch }}.tar.gz -C build/linux/${{ matrix.arch }}/release/bundle/ .
+ # - name: Upload to release
+ # uses: actions/upload-release-asset@v1
+ # env:
+ # GITHUB_TOKEN: ${{ secrets.PAGES_DEPLOY_TOKEN }}
+ # with:
+ # upload_url: ${{ needs.create_release.outputs.upload_url }}
+ # asset_path: pangeachat-linux-${{ matrix.arch }}.tar.gz
+ # asset_name: pangeachat-linux-${{ matrix.arch }}.tar.gz
+ # asset_content_type: application/gzip
+ # Pangea#
deploy_web:
runs-on: ubuntu-latest
diff --git a/.github/workflows/upload-release-ios.yml b/.github/workflows/upload-release-ios.yml
deleted file mode 100644
index aa70cd9ca..000000000
--- a/.github/workflows/upload-release-ios.yml
+++ /dev/null
@@ -1,39 +0,0 @@
-name: upload-release-ios
-on:
- workflow_call:
- inputs:
- new_release:
- required: true
- type: string
- description: "The new release version number"
- new_release_notes:
- required: true
- type: string
- description: "The release notes for the new release"
-
-jobs:
- build:
- runs-on: macos-latest
- timeout-minutes: 10
- steps:
- - uses: actions/checkout@v4
- with:
- fetch-depth: 0
-
- - name: Download app
- uses: actions/download-artifact@v4
- with:
- name: Runner.ipa
- path: ios/
-
- - run: 'echo "$API_KEY" | base64 --decode > AuthKey.p8'
- shell: bash
- env:
- API_KEY: ${{ secrets.APP_STORE_CONNECT_API_KEY }}
-
- - run: bundle install
-
- - run: bundle exec fastlane upload_testflight
- env:
- RELEASE_NOTES: ${{ inputs.new_release_notes }}
- - run: bundle exec fastlane upload_metadata_app_store
\ No newline at end of file
diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb
index b85b940fe..00ebd337f 100644
--- a/lib/l10n/intl_en.arb
+++ b/lib/l10n/intl_en.arb
@@ -5031,5 +5031,6 @@
"type": "int"
}
}
- }
+ },
+ "failedToFetchTranscription": "Failed to fetch transcription"
}
\ No newline at end of file
diff --git a/lib/pages/chat/events/html_message.dart b/lib/pages/chat/events/html_message.dart
index 06b203f0f..268abbcac 100644
--- a/lib/pages/chat/events/html_message.dart
+++ b/lib/pages/chat/events/html_message.dart
@@ -185,6 +185,23 @@ class HtmlMessage extends StatelessWidget {
result.add(html.substring(lastEnd)); // Remaining text after last tag
}
+ final replyTagIndex = result.indexWhere(
+ (string) => string.contains(''),
+ );
+ if (replyTagIndex != -1) {
+ final closingReplyTagIndex = result.indexWhere(
+ (string) => string.contains(''),
+ replyTagIndex,
+ );
+ if (closingReplyTagIndex != -1) {
+ result.replaceRange(
+ replyTagIndex,
+ closingReplyTagIndex + 1,
+ [result.sublist(replyTagIndex, closingReplyTagIndex + 1).join()],
+ );
+ }
+ }
+
for (final PangeaToken token in tokens ?? []) {
final String tokenText = token.text.content;
final substringIndex = result.indexWhere(
diff --git a/lib/pangea/phonetic_transcription/phonetic_transcription_widget.dart b/lib/pangea/phonetic_transcription/phonetic_transcription_widget.dart
index 0e7c69f74..e6c91bad8 100644
--- a/lib/pangea/phonetic_transcription/phonetic_transcription_widget.dart
+++ b/lib/pangea/phonetic_transcription/phonetic_transcription_widget.dart
@@ -9,6 +9,7 @@ import 'package:fluffychat/pangea/learning_settings/models/language_model.dart';
import 'package:fluffychat/pangea/phonetic_transcription/phonetic_transcription_repo.dart';
import 'package:fluffychat/pangea/phonetic_transcription/phonetic_transcription_request.dart';
import 'package:fluffychat/pangea/toolbar/controllers/tts_controller.dart';
+import 'package:fluffychat/widgets/hover_builder.dart';
import 'package:fluffychat/widgets/matrix.dart';
class PhoneticTranscriptionWidget extends StatefulWidget {
@@ -32,51 +33,61 @@ class PhoneticTranscriptionWidget extends StatefulWidget {
class _PhoneticTranscriptionWidgetState
extends State {
- late Future _transcriptionFuture;
- bool _hovering = false;
bool _isPlaying = false;
bool _isLoading = false;
- late final StreamSubscription _loadingChoreoSubscription;
+ Object? _error;
+
+ String? _transcription;
@override
void initState() {
super.initState();
- _transcriptionFuture = _fetchTranscription();
- _loadingChoreoSubscription =
- TtsController.loadingChoreoStream.stream.listen((val) {
- if (mounted) setState(() => _isLoading = val);
- });
+ _fetchTranscription();
}
- @override
- void dispose() {
- TtsController.stop();
- _loadingChoreoSubscription.cancel();
- super.dispose();
- }
+ Future _fetchTranscription() async {
+ try {
+ setState(() {
+ _isLoading = true;
+ _error = null;
+ _transcription = null;
+ });
- Future _fetchTranscription() async {
- if (MatrixState.pangeaController.languageController.userL1 == null) {
+ if (MatrixState.pangeaController.languageController.userL1 == null) {
+ ErrorHandler.logError(
+ e: Exception('User L1 is not set'),
+ data: {
+ 'text': widget.text,
+ 'textLanguageCode': widget.textLanguage.langCode,
+ },
+ );
+ _error = Exception('User L1 is not set');
+ return;
+ }
+ final req = PhoneticTranscriptionRequest(
+ arc: LanguageArc(
+ l1: MatrixState.pangeaController.languageController.userL1!,
+ l2: widget.textLanguage,
+ ),
+ content: PangeaTokenText.fromString(widget.text),
+ // arc can be omitted for default empty map
+ );
+ final res = await PhoneticTranscriptionRepo.get(req);
+ _transcription = res.phoneticTranscriptionResult.phoneticTranscription
+ .first.phoneticL1Transcription.content;
+ } catch (e, s) {
+ _error = e;
ErrorHandler.logError(
- e: Exception('User L1 is not set'),
+ e: e,
+ s: s,
data: {
'text': widget.text,
'textLanguageCode': widget.textLanguage.langCode,
},
);
- return widget.text; // Fallback to original text if no L1 is set
+ } finally {
+ if (mounted) setState(() => _isLoading = false);
}
- final req = PhoneticTranscriptionRequest(
- arc: LanguageArc(
- l1: MatrixState.pangeaController.languageController.userL1!,
- l2: widget.textLanguage,
- ),
- content: PangeaTokenText.fromString(widget.text),
- // arc can be omitted for default empty map
- );
- final res = await PhoneticTranscriptionRepo.get(req);
- return res.phoneticTranscriptionResult.phoneticTranscription.first
- .phoneticL1Transcription.content;
}
Future _handleAudioTap(BuildContext context) async {
@@ -101,55 +112,66 @@ class _PhoneticTranscriptionWidgetState
@override
Widget build(BuildContext context) {
- return FutureBuilder(
- future: _transcriptionFuture,
- builder: (context, snapshot) {
- final transcription = snapshot.data ?? '';
- return MouseRegion(
- onEnter: (_) => setState(() => _hovering = true),
- onExit: (_) => setState(() => _hovering = false),
- child: GestureDetector(
- onTap: () => _handleAudioTap(context),
- child: AnimatedContainer(
- duration: const Duration(milliseconds: 150),
- decoration: BoxDecoration(
- color: _hovering
- ? Colors.grey.withAlpha((0.2 * 255).round())
- : Colors.transparent,
- borderRadius: BorderRadius.circular(6),
- ),
- padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
- child: Row(
- mainAxisSize: MainAxisSize.min,
- children: [
+ return HoverBuilder(
+ builder: (context, hovering) {
+ return GestureDetector(
+ onTap: () => _handleAudioTap(context),
+ child: AnimatedContainer(
+ duration: const Duration(milliseconds: 150),
+ decoration: BoxDecoration(
+ color: hovering
+ ? Colors.grey.withAlpha((0.2 * 255).round())
+ : Colors.transparent,
+ borderRadius: BorderRadius.circular(6),
+ ),
+ padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
+ child: Row(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ if (_error != null)
+ Row(
+ spacing: 8.0,
+ children: [
+ Icon(
+ Icons.error_outline,
+ size: widget.iconSize ?? 24,
+ color: Theme.of(context).colorScheme.error,
+ ),
+ Text(
+ L10n.of(context).failedToFetchTranscription,
+ style: widget.style,
+ ),
+ ],
+ )
+ else if (_isLoading || _transcription == null)
+ const SizedBox(
+ width: 16,
+ height: 16,
+ child: CircularProgressIndicator.adaptive(),
+ )
+ else
Flexible(
child: Text(
- "/${transcription.isNotEmpty ? transcription : widget.text}/",
+ "/$_transcription/",
style: widget.style ??
Theme.of(context).textTheme.bodyMedium,
),
),
- const SizedBox(width: 8),
+ const SizedBox(width: 8),
+ if (_transcription != null && _error == null)
Tooltip(
message: _isPlaying
? L10n.of(context).stop
: L10n.of(context).playAudio,
- child: _isLoading
- ? const SizedBox(
- width: 16,
- height: 16,
- child: CircularProgressIndicator(strokeWidth: 3),
- )
- : Icon(
- _isPlaying ? Icons.pause_outlined : Icons.volume_up,
- size: widget.iconSize ?? 24,
- color: _isPlaying
- ? Theme.of(context).colorScheme.primary
- : Theme.of(context).iconTheme.color,
- ),
+ child: Icon(
+ _isPlaying ? Icons.pause_outlined : Icons.volume_up,
+ size: widget.iconSize ?? 24,
+ color: _isPlaying
+ ? Theme.of(context).colorScheme.primary
+ : Theme.of(context).iconTheme.color,
+ ),
),
- ],
- ),
+ ],
),
),
);