Compare commits
No commits in common. "trunk" and "integtest2" have entirely different histories.
trunk
...
integtest2
152
.drone.yml
|
@ -8,7 +8,7 @@ clone:
|
|||
|
||||
steps:
|
||||
- name: clone
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.19.3
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.7.1
|
||||
environment:
|
||||
buildbot_key_b64:
|
||||
from_secret: buildbot_key_b64
|
||||
|
@ -24,14 +24,14 @@ steps:
|
|||
- git checkout $DRONE_COMMIT
|
||||
|
||||
- name: fetch
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.19.3
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.7.1
|
||||
volumes:
|
||||
- name: deps
|
||||
path: /root/.pub-cache
|
||||
commands:
|
||||
- ./fetch-tor.sh
|
||||
- echo `git describe --tags --abbrev=1` > VERSION
|
||||
- echo `git log -1 --format=%cd --date=format:%G-%m-%d-%H-%M` > COMMIT_DATE
|
||||
- echo `date +%G-%m-%d-%H-%M` > BUILDDATE
|
||||
- flutter pub get
|
||||
- mkdir deploy
|
||||
- ./fetch-libcwtch-go.sh
|
||||
|
@ -47,46 +47,31 @@ steps:
|
|||
# #Todo: fix all the lint errors and add `-set_exit_status` above to enforce linting
|
||||
|
||||
- name: build-linux
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.19.3
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.7.1
|
||||
volumes:
|
||||
- name: deps
|
||||
path: /root/.pub-cache
|
||||
commands:
|
||||
- flutter build linux --dart-define BUILD_VER=`cat VERSION` --dart-define BUILD_DATE=`cat COMMIT_DATE`
|
||||
- flutter build linux --dart-define BUILD_VER=`cat VERSION` --dart-define BUILD_DATE=`cat BUILDDATE`
|
||||
- linux/package-release.sh
|
||||
- mkdir -p deploy/cwtch
|
||||
- mkdir -p deploy/deb/cwtch/usr
|
||||
- mkdir -p deploy/deb/cwtch/DEBIAN
|
||||
- export VERSION=`cat VERSION | tr -d 'v'`
|
||||
- sed "s|VERSION|$VERSION|g" linux/deb/control > deploy/deb/cwtch/DEBIAN/control
|
||||
- cp -r build/linux/x64/release/bundle/* deploy/cwtch
|
||||
- cd deploy
|
||||
- cd cwtch
|
||||
- INSTALL_PREFIX=./../deb/cwtch/usr DESKTOP_PREFIX=/usr/ ./install.sh
|
||||
- cd ..
|
||||
# we depend on tor, get it from the tor project apt repo
|
||||
- rm -r deb/cwtch/usr/lib/cwtch/Tor
|
||||
# Tar archives need a few tricks to make this deterministic, see https://reproducible-builds.org/docs/archives/
|
||||
- tar --sort=name --mtime=`cat COMMIT_DATE` --owner=0 --group=0 --numeric-owner --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime -czf cwtch-`cat ../VERSION`.tar.gz cwtch
|
||||
- tar -czf cwtch-`cat ../VERSION`.tar.gz cwtch
|
||||
- rm -r cwtch
|
||||
- cd deb
|
||||
- dpkg-deb --build cwtch
|
||||
- cd ..
|
||||
- mv deb/cwtch.deb cwtch-$VERSION.deb
|
||||
- rm -r deb
|
||||
|
||||
|
||||
- name: linux-ui-tests
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.19.3
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.7.1
|
||||
volumes:
|
||||
- name: deps
|
||||
path: /root/.pub-cache
|
||||
commands:
|
||||
# Run 01_general, 01_tor, 02_global_settings, and 04_profile_mgmt features...
|
||||
- ./run-tests-headless.sh "01_general|01_tor|02_global_settings|04_profile_mgmt"
|
||||
- ./fetch-tor.sh
|
||||
# Run 01_general and 02_global_settings features...
|
||||
- ./run-tests-headless.sh "01_general|02_global_settings"
|
||||
|
||||
- name: test-build-android
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.19.3
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.7.1
|
||||
when:
|
||||
event: pull_request
|
||||
volumes:
|
||||
|
@ -96,7 +81,7 @@ steps:
|
|||
- flutter build apk --debug
|
||||
|
||||
- name: build-android
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.19.3
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.7.1
|
||||
when:
|
||||
event: push
|
||||
environment:
|
||||
|
@ -111,16 +96,16 @@ steps:
|
|||
- echo $upload_jks_file_b64 > upload-keystore.jks.b64
|
||||
- base64 -i --decode upload-keystore.jks.b64 > android/app/upload-keystore.jks
|
||||
- sed -i "s/%jks-password%/$upload_jks_pass/g" android/key.properties
|
||||
- flutter build appbundle --dart-define BUILD_VER=`cat VERSION` --dart-define BUILD_DATE=`cat COMMIT_DATE`
|
||||
- flutter build appbundle --dart-define BUILD_VER=`cat VERSION` --dart-define BUILD_DATE=`cat BUILDDATE`
|
||||
# cant do debug for final release, this is just a stop gap
|
||||
- flutter build apk --dart-define BUILD_VER=`cat VERSION` --dart-define BUILD_DATE=`cat COMMIT_DATE`
|
||||
- flutter build apk --dart-define BUILD_VER=`cat VERSION` --dart-define BUILD_DATE=`cat BUILDDATE`
|
||||
# or build apk --split-per-abi ?
|
||||
- cp build/app/outputs/bundle/release/app-release.aab deploy/cwtch-`cat VERSION`.aab
|
||||
- cp build/app/outputs/apk/release/app-release.apk deploy/cwtch-`cat VERSION`.apk
|
||||
- cp build/app/outputs/bundle/release/app-release.aab deploy/
|
||||
- cp build/app/outputs/apk/release/app-release.apk deploy/
|
||||
#- cp build/app/outputs/flutter-apk/app-debug.apk deploy/android
|
||||
|
||||
- name: widget-tests
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.19.3
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.7.1
|
||||
volumes:
|
||||
- name: deps
|
||||
path: /root/.pub-cache
|
||||
|
@ -129,21 +114,6 @@ steps:
|
|||
- flutter test --coverage
|
||||
- genhtml coverage/lcov.info -o coverage/html
|
||||
|
||||
- name: upload-nightlies
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.19.3
|
||||
environment:
|
||||
GOGS_ACCOUNT_TOKEN:
|
||||
from_secret: gogs_account_token
|
||||
secrets: [gogs_account_token]
|
||||
volumes:
|
||||
- name: deps
|
||||
path: /root/.pub-cache
|
||||
when:
|
||||
event: push
|
||||
status: [ success ]
|
||||
commands:
|
||||
- ./upload-releases.sh deploy/cwtch-`cat VERSION`.apk application/vnd.android.package-archive cwtch-`cat VERSION`.apk
|
||||
|
||||
- name: deploy-buildfiles
|
||||
image: kroniak/ssh-client
|
||||
pull: if-not-exists
|
||||
|
@ -158,17 +128,26 @@ steps:
|
|||
- echo $BUILDFILES_KEY > ~/id_rsab64
|
||||
- base64 -d ~/id_rsab64 > ~/id_rsa
|
||||
- chmod 400 ~/id_rsa
|
||||
- export DIR=flwtch-`cat COMMIT_DATE`-`cat VERSION`
|
||||
- export DIR=flwtch-`cat BUILDDATE`-`cat VERSION`
|
||||
- mv deploy $DIR
|
||||
- cp -r coverage/html $DIR/coverage-tests
|
||||
- cp -r test/failures $DIR/test-failures || true
|
||||
- cd $DIR
|
||||
- find . -type f -exec sha512sum {} \; > ./../sha512s.txt
|
||||
- mv ./../sha512s.txt .
|
||||
- find . -type f -exec sha256sum {} \; > ./../sha256s.txt
|
||||
- mv ./../sha256s.txt .
|
||||
- cd ..
|
||||
- scp -r -o StrictHostKeyChecking=no -i ~/id_rsa $DIR buildfiles@build.openprivacy.ca:/home/buildfiles/buildfiles/
|
||||
- ./gen-nightly-index.sh $DIR
|
||||
- scp -r -o StrictHostKeyChecking=no -i ~/id_rsa cwtch-nightly.html buildfiles@build.openprivacy.ca:/home/buildfiles/buildfiles/
|
||||
|
||||
- name: notify-email
|
||||
image: drillster/drone-email
|
||||
pull: if-not-exists
|
||||
settings:
|
||||
host: build.openprivacy.ca
|
||||
port: 25
|
||||
skip_verify: true
|
||||
from: drone@openprivacy.ca
|
||||
when:
|
||||
status: [ failure ]
|
||||
|
||||
- name: notify-gogs
|
||||
image: openpriv/drone-gogs
|
||||
|
@ -208,7 +187,7 @@ clone:
|
|||
|
||||
steps:
|
||||
- name: clone
|
||||
image: openpriv/flutter-desktop:windows-sdk30-fstable-3.19.3
|
||||
image: openpriv/flutter-desktop:windows-sdk30-fstable-3.7.1
|
||||
environment:
|
||||
buildbot_key_b64:
|
||||
from_secret: buildbot_key_b64
|
||||
|
@ -226,28 +205,28 @@ steps:
|
|||
- git checkout $Env:DRONE_COMMIT
|
||||
|
||||
- name: fetch
|
||||
image: openpriv/flutter-desktop:windows-sdk30-fstable-3.19.3
|
||||
image: openpriv/flutter-desktop:windows-sdk30-fstable-3.7.1
|
||||
commands:
|
||||
- git describe --tags --abbrev=1 > VERSION
|
||||
- git log -1 --format=%cd --date=format:'%Y-%m-%d-%H-%M' > COMMIT_DATE
|
||||
- powershell -command "Get-Date -Format 'yyyy-MM-dd-HH-mm'" > BUILDDATE
|
||||
- .\fetch-tor-win.ps1
|
||||
- .\fetch-libcwtch-go.ps1
|
||||
|
||||
- name: build-windows
|
||||
image: openpriv/flutter-desktop:windows-sdk30-fstable-3.19.3
|
||||
image: openpriv/flutter-desktop:windows-sdk30-fstable-3.7.1
|
||||
commands:
|
||||
- flutter pub get
|
||||
- $Env:version += type .\VERSION
|
||||
- $Env:commitdate += type .\COMMIT_DATE
|
||||
- $Env:releasedir = "build\\windows\\x64\\runner\\Release\\"
|
||||
- flutter build windows --dart-define BUILD_VER=$Env:version --dart-define BUILD_DATE=$Env:commitdate
|
||||
- $Env:builddate += type .\BUILDDATE
|
||||
- $Env:releasedir = "build\\windows\\runner\\Release\\"
|
||||
- flutter build windows --dart-define BUILD_VER=$Env:version --dart-define BUILD_DATE=$Env:builddate
|
||||
- copy windows\libCwtch.dll $Env:releasedir
|
||||
# flutter hasn't worked out it's packaging of required dll's so we have to resort to this manual nonsense
|
||||
# https://github.com/google/flutter-desktop-embedding/issues/587
|
||||
# https://github.com/flutter/flutter/issues/53167
|
||||
- copy 'C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Redist\MSVC\14.36.32532\x64\Microsoft.VC143.CRT\vcruntime140.dll' $Env:releasedir
|
||||
- copy 'C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Redist\MSVC\14.36.32532\x64\Microsoft.VC143.CRT\vcruntime140_1.dll' $Env:releasedir
|
||||
- copy 'C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Redist\MSVC\14.36.32532\x64\Microsoft.VC143.CRT\msvcp140.dll' $Env:releasedir
|
||||
- copy C:\BuildTools\VC\Redist\MSVC\14.29.30133\x64\Microsoft.VC142.CRT\vcruntime140.dll $Env:releasedir
|
||||
- copy C:\BuildTools\VC\Redist\MSVC\14.29.30133\x64\Microsoft.VC142.CRT\vcruntime140_1.dll $Env:releasedir
|
||||
- copy C:\BuildTools\VC\Redist\MSVC\14.29.30133\x64\Microsoft.VC142.CRT\msvcp140.dll $Env:releasedir
|
||||
- copy README.md $Env:releasedir\
|
||||
- copy windows\*.bat $Env:releasedir\
|
||||
- powershell -command "Expand-Archive -Path tor.zip -DestinationPath $Env:releasedir\Tor"
|
||||
|
@ -265,11 +244,13 @@ steps:
|
|||
from_secret: pfx_pass
|
||||
commands:
|
||||
- $Env:version += type .\VERSION
|
||||
- $Env:commitdate += type .\COMMIT_DATE
|
||||
- $Env:releasedir = "build\\windows\\x64\\runner\\Release\\"
|
||||
- $Env:builddate += type .\BUILDDATE
|
||||
- $Env:releasedir = "build\\windows\\runner\\Release\\"
|
||||
- $Env:zip = 'cwtch-' + $Env:version + '.zip'
|
||||
- $Env:zipsha = $Env:zip + '.sha512.txt'
|
||||
- $Env:buildname = 'flwtch-' + $Env:commitdate + '-' + $Env:version
|
||||
- $Env:zipsha = $Env:zip + '.sha512'
|
||||
- $Env:msix = 'cwtch-install-' + $Env:version + '.msix'
|
||||
- $Env:msixsha = $Env:msix + '.sha512'
|
||||
- $Env:buildname = 'flwtch-win-' + $Env:builddate + '-' + $Env:version
|
||||
- $Env:builddir = $Env:buildname
|
||||
- echo $Env:pfx > codesign.pfx.b64
|
||||
- certutil -decode codesign.pfx.b64 codesign.pfx
|
||||
|
@ -280,18 +261,18 @@ steps:
|
|||
- makensis windows\nsis\cwtch-installer.nsi
|
||||
- move windows\nsis\cwtch-installer.exe cwtch-installer.exe
|
||||
- signtool sign /v /fd sha256 /a /f codesign.pfx /p $Env:pfx_pass /tr http://timestamp.digicert.com cwtch-installer.exe
|
||||
- powershell -command "(Get-FileHash cwtch-installer.exe -Algorithm sha512).Hash" > cwtch-installer.sha512.txt
|
||||
- powershell -command "(Get-FileHash cwtch-installer.exe -Algorithm sha512).Hash" > cwtch-installer.sha512
|
||||
- mkdir deploy
|
||||
- mkdir deploy\$Env:builddir
|
||||
- move $Env:releasedir $Env:builddir
|
||||
- powershell -command "Compress-Archive -Path $Env:builddir -DestinationPath cwtch.zip"
|
||||
- powershell -command "(Get-FileHash cwtch.zip -Algorithm sha512).Hash" > $Env:zipsha
|
||||
- move cwtch-installer.exe deploy\$Env:builddir\cwtch-installer-$Env:version.exe
|
||||
- move cwtch-installer.exe deploy\$Env:builddir\cwtch-installer.exe
|
||||
- move cwtch.zip deploy\$Env:builddir\$Env:zip
|
||||
- move *.sha512.txt deploy\$Env:builddir
|
||||
- move *.sha512 deploy\$Env:builddir
|
||||
|
||||
- name: deploy-windows
|
||||
image: openpriv/flutter-desktop:windows-sdk30-fstable-3.19.3
|
||||
image: openpriv/flutter-desktop:windows-sdk30-fstable-3.7.1
|
||||
when:
|
||||
event: push
|
||||
status: [ success ]
|
||||
|
@ -330,8 +311,7 @@ steps:
|
|||
commands:
|
||||
- mkdir ~/.ssh
|
||||
- echo $buildbot_key_b64 > ~/.ssh/id_rsa.b64
|
||||
- ls -lh ~/.ssh/id_rsa.b64
|
||||
- base64 -d -i ~/.ssh/id_rsa.b64 -o ~/.ssh/id_rsa
|
||||
- base64 -d ~/.ssh/id_rsa.b64 > ~/.ssh/id_rsa
|
||||
- chmod 400 ~/.ssh/id_rsa
|
||||
# force by pass of ssh host key check, less secure
|
||||
- ssh-keyscan -H git.openprivacy.ca >> ~/.ssh/known_hosts
|
||||
|
@ -349,26 +329,24 @@ steps:
|
|||
commands:
|
||||
- ./fetch-tor-macos.sh
|
||||
- echo `git describe --tags --abbrev=1` > VERSION
|
||||
- echo `git log -1 --format=%cd --date=format:%G-%m-%d-%H-%M` > COMMIT_DATE
|
||||
- export PATH=$PATH:/Users/drone/development/flutter/bin
|
||||
- echo `date +%G-%m-%d-%H-%M` > BUILDDATE
|
||||
- export PATH=$PATH:/Users/Dan/development/flutter/bin
|
||||
- flutter pub get
|
||||
- mkdir deploy
|
||||
- ./fetch-libcwtch-go-macos.sh
|
||||
# Drone builds in container directories and gem seems to have some weird side effects so have to manually re install these locally
|
||||
- gem install --user-install ffi -v 1.15.5 -- --enable-libffi-alloc
|
||||
# currently unneeded to reinstall but was, and may be again? so saving
|
||||
#- gem install --user-install cocoapods -v 1.11.3
|
||||
- gem install --user-install cocoapods
|
||||
|
||||
- name: build-macos
|
||||
commands:
|
||||
- export PATH=$PATH:/Users/drone/bin/flutter/bin
|
||||
- export PATH=$PATH:/Users/Dan/development/flutter/bin
|
||||
- export GEM_HOME=$HOME/.gem
|
||||
- export PATH=$GEM_HOME/ruby/2.6.0/bin:$PATH
|
||||
- flutter doctor
|
||||
- flutter build macos --dart-define BUILD_VER=`cat VERSION` --dart-define BUILD_DATE=`cat COMMIT_DATE`
|
||||
- export PATH=$PATH:/opt/homebrew/bin/ #create-dmg
|
||||
- flutter config --enable-macos-desktop
|
||||
- flutter build macos --dart-define BUILD_VER=`cat VERSION` --dart-define BUILD_DATE=`cat BUILDDATE`
|
||||
- export PATH=$PATH:/usr/local/bin #create-dmg
|
||||
- macos/package-release.sh
|
||||
- mkdir -p deploy
|
||||
- mv Cwtch.dmg deploy/Cwtch-`cat VERSION`.dmg
|
||||
- mv Cwtch.dmg deploy
|
||||
|
||||
- name: deploy-buildfiles
|
||||
environment:
|
||||
|
@ -379,13 +357,13 @@ steps:
|
|||
status: [ success ]
|
||||
commands:
|
||||
- echo $BUILDFILES_KEY > ~/id_rsab64
|
||||
- base64 -d -i ~/id_rsab64 -o ~/id_rsa
|
||||
- base64 -d ~/id_rsab64 > ~/id_rsa
|
||||
- chmod 400 ~/id_rsa
|
||||
- export DIR=flwtch-`cat COMMIT_DATE`-`cat VERSION`
|
||||
- export DIR=flwtch-macos-`cat BUILDDATE`-`cat VERSION`
|
||||
- mv deploy $DIR
|
||||
- cd $DIR
|
||||
- find . -type f -exec shasum -a 512 {} \; > ./../Cwtch.dmg.sha512.txt
|
||||
- mv ./../Cwtch.dmg.sha512.txt .
|
||||
- find . -type f -exec shasum -a 512 {} \; > ./../sha512s.txt
|
||||
- mv ./../sha512s.txt .
|
||||
- cd ..
|
||||
- scp -r -o StrictHostKeyChecking=no -i ~/id_rsa $DIR buildfiles@build.openprivacy.ca:/home/buildfiles/buildfiles/
|
||||
|
||||
|
|
|
@ -3,16 +3,11 @@
|
|||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
package.json
|
||||
package-lock.json
|
||||
libCwtch*
|
||||
cwtch.aar
|
||||
node_modules
|
||||
test_home
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
|
@ -35,7 +30,6 @@ test_home
|
|||
.pub-cache/
|
||||
.pub/
|
||||
/build/
|
||||
./lib/gen/
|
||||
|
||||
# Web related
|
||||
lib/generated_plugin_registrant.dart
|
||||
|
@ -59,7 +53,7 @@ package.
|
|||
# Compiled Libs
|
||||
linux/tor
|
||||
linux/libCwtch.so
|
||||
android/app/cwtch/cwtch.aar
|
||||
android/cwtch/cwtch.aar
|
||||
android/app/src/main/jniLibs/*/libtor.so
|
||||
*.dylib
|
||||
integration_test/gherkin_suite_test.g.dart
|
||||
|
|
24
.metadata
|
@ -1,30 +1,10 @@
|
|||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled.
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf
|
||||
revision: 78910062997c3a836feee883712c241a5fd22983
|
||||
channel: stable
|
||||
|
||||
project_type: app
|
||||
|
||||
# Tracks metadata for the flutter migrate command
|
||||
migration:
|
||||
platforms:
|
||||
- platform: root
|
||||
create_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf
|
||||
base_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf
|
||||
- platform: macos
|
||||
create_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf
|
||||
base_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf
|
||||
|
||||
# User provided section
|
||||
|
||||
# List of Local paths (relative to this file) that should be
|
||||
# ignored by the migrate tool.
|
||||
#
|
||||
# Files that are not part of the templates will be ignored by default.
|
||||
unmanaged_files:
|
||||
- 'lib/main.dart'
|
||||
- 'ios/Runner.xcodeproj/project.pbxproj'
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
2023-02-08-16-57-v1.10.5
|
|
@ -1 +1 @@
|
|||
2024-02-26-18-01-v0.0.14
|
||||
2023-02-08-21-57-v1.10.5
|
2
LICENSE
|
@ -1,5 +1,5 @@
|
|||
MIT License
|
||||
Copyright (c) 2021-2024 Open Privacy Research Society
|
||||
Copyright (c) 2021 Open Privacy Research Society
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
# NSIS Notes
|
||||
|
||||
## Images
|
||||
|
||||
Requires Windows 3 Compatible Bitmaps.
|
||||
|
||||
Can convert to the correct format with e.g. `mogrify -compress none -format bmp3 windows/nsis/cwtch_title.bmp
|
||||
`
|
15
README.md
|
@ -21,13 +21,6 @@ Cwtch processes the following environment variables:
|
|||
- `LOG_FILE=` will reroute all of libcwtch-go's logging to the specified file instead of the console
|
||||
- `LOG_LEVEL=debug` will set the log level to debug instead of info
|
||||
|
||||
## Running Tests
|
||||
|
||||
You can run specific tests with `./run-tests-headless.sh`. See also the `.drone.yml` file for information on the specific tests that run.1
|
||||
|
||||
The gherkin test framework will occasionally fail silently with incomplete test. This is usually because a previous run resulted in an exception and the underlying Tor
|
||||
process was not cleaned up (See #711).
|
||||
|
||||
## Building
|
||||
|
||||
### Getting Started
|
||||
|
@ -71,14 +64,10 @@ To build a release version and load normal profiles, use `build-release.sh X` in
|
|||
|
||||
### Building on MacOS
|
||||
|
||||
- Cocoapods is required. Mac and Ruby don't seem to care about version stability and compatibility so good luck. The version of Ruby Mac seems to ship is very incompatible with software in the gem repo. You will probablly need to manually specify a specific older version of cocoapods that is compatible with your system. First you will also probably need to make sure you are on the latest MacOS version and then try `gem install cocoapods -v 1.x.x`
|
||||
- For MacOS 13.4 `gem install cocoapods -v 1.11.3` worked on 2023.05.28
|
||||
- copy `libCwtch.x64.dylib` and `libCwtch.arm.dylib` into the root folder, or run `fetch-libcwtch-go-macos.sh` to download it
|
||||
- The error 'Podfile not found' has still been seen on fresh repos, depending on varios versions. To fix run `flutter create --platforms=macos . --org im.cwtch`
|
||||
- You may have to temporarily rename the project folder a "dart project suitable name" like "cwtch"
|
||||
- Cocaopods is required, you may need to `gem install cocaopods -v 1.9.3`
|
||||
- copy `libCwtch.x64.dylib` and `libCwtch.arm/dylib` into the root folder, or run `fetch-libcwtch-go-macos.sh` to download it
|
||||
- run `fetch-tor-macos.sh` to fetch Tor or Download and install Tor Browser and `cp -r /Applications/Tor\ Browser.app/Contents/MacOS/Tor ./macos/`
|
||||
- `flutter build macos`
|
||||
- If you are building on Mac Arm Silicon you may need to append `--no-tree-shake-icons` as the build seems to invoke a mac x64 binary that Arm Mac "cannot verify" and therefor will not run on some versions of Flutter
|
||||
- optional: launch cwtch-ui release build with `./build/macos/Build/Products/Release/Cwtch.app/Contents/MacOS/Cwtch`
|
||||
- To package the UI: `./macos/package-release.sh`, which results in a Cwtch.dmg that has libCwtch.dylib and tor in it as well and can be installed into Applications
|
||||
|
||||
|
|
|
@ -1,9 +1,3 @@
|
|||
plugins {
|
||||
id "com.android.application"
|
||||
id "kotlin-android"
|
||||
id "dev.flutter.flutter-gradle-plugin"
|
||||
}
|
||||
|
||||
def localProperties = new Properties()
|
||||
def localPropertiesFile = rootProject.file('local.properties')
|
||||
if (localPropertiesFile.exists()) {
|
||||
|
@ -12,6 +6,11 @@ if (localPropertiesFile.exists()) {
|
|||
}
|
||||
}
|
||||
|
||||
def flutterRoot = localProperties.getProperty('flutter.sdk')
|
||||
if (flutterRoot == null) {
|
||||
throw new FileNotFoundException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
|
||||
}
|
||||
|
||||
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
|
||||
if (flutterVersionCode == null) {
|
||||
flutterVersionCode = '1'
|
||||
|
@ -22,6 +21,10 @@ if (flutterVersionName == null) {
|
|||
flutterVersionName = '1.0'
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||
|
||||
// key.properties MUST have password placeholders filled in (via drone with secrets) and cwtch-upload.jks file must be added (from drone secret)
|
||||
def keystoreProperties = new Properties()
|
||||
def keystorePropertiesFile = rootProject.file('key.properties')
|
||||
|
@ -30,7 +33,7 @@ if (keystorePropertiesFile.exists()) {
|
|||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 34
|
||||
compileSdkVersion 33
|
||||
|
||||
sourceSets {
|
||||
main.java.srcDirs += 'src/main/kotlin'
|
||||
|
@ -50,8 +53,8 @@ android {
|
|||
defaultConfig {
|
||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||
applicationId "im.cwtch.flwtch"
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 34
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 31
|
||||
versionCode flutterVersionCode.toInteger()
|
||||
versionName flutterVersionName
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
@ -90,11 +93,11 @@ flutter {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.21" // same as kotlin version in settings.gradle
|
||||
implementation fileTree( dir: 'cwtch')
|
||||
implementation files ('cwtch/cwtch.aar')
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
implementation project(':cwtch')
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.2"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.2"
|
||||
implementation "com.airbnb.android:lottie:5.2.0"
|
||||
implementation "androidx.localbroadcastmanager:localbroadcastmanager:1.0.0"
|
||||
implementation "com.android.support.constraint:constraint-layout:2.0.4"
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="im.cwtch.flwtch">
|
||||
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
|
||||
calls FlutterMain.startInitialization(this); in its onCreate method.
|
||||
|
@ -13,7 +13,7 @@
|
|||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@style/LaunchTheme"
|
||||
android:theme="@style/NormalTheme"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize"
|
||||
|
@ -38,30 +38,22 @@
|
|||
android:name="flutterEmbedding"
|
||||
android:value="2" />
|
||||
|
||||
<!--Needed to run in background (lol)-->
|
||||
<service
|
||||
android:name="androidx.work.impl.foreground.SystemForegroundService"
|
||||
android:foregroundServiceType="dataSync"
|
||||
tools:node="merge" />
|
||||
|
||||
</application>
|
||||
|
||||
<!--Needed to access Tor socket-->
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<!-- Needed for running in the background -->
|
||||
<!--Needed to run in background (lol)-->
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<!-- As of Android 13 this permission is required -->
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
|
||||
|
||||
<!-- Ability to ask user to exempt app from power management (which can kill it more frequently especially on some devices.
|
||||
Allows app to use ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS -->
|
||||
<uses-permission-sdk-23 android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
||||
|
||||
|
||||
<!-- TODO when we support sdk 31
|
||||
<uses-permission-sdk-23 android:name="android.permission.HIDE_OVERLAY_WINDOWS" />
|
||||
|
||||
-->
|
||||
|
||||
<!--Needed to check if activity is foregrounded or if messages from the service should be queued-->
|
||||
<uses-permission android:name="android.permission.GET_TASKS" />
|
||||
|
|
|
@ -11,7 +11,6 @@ import android.graphics.Color
|
|||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import android.content.pm.ServiceInfo
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||
|
@ -23,13 +22,6 @@ import io.flutter.FlutterInjector
|
|||
import org.json.JSONObject
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
import java.io.FileInputStream
|
||||
|
||||
|
||||
import java.io.File
|
||||
|
||||
|
||||
|
||||
|
||||
class FlwtchWorker(context: Context, parameters: WorkerParameters) :
|
||||
CoroutineWorker(context, parameters) {
|
||||
|
@ -92,7 +84,6 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) :
|
|||
|
||||
Log.i(TAG, "startCwtch success, starting coroutine AppbusEvent loop...")
|
||||
val downloadIDs = mutableMapOf<String, Int>()
|
||||
val downloadFinishedIDs = mutableMapOf<String, Int>()
|
||||
var flags = PendingIntent.FLAG_UPDATE_CURRENT
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
flags = flags or PendingIntent.FLAG_IMMUTABLE
|
||||
|
@ -101,6 +92,7 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) :
|
|||
try {
|
||||
val evt = MainActivity.AppbusEvent(Cwtch.getAppBusEvent())
|
||||
// TODO replace this notification block with the NixNotification manager in dart as it has access to contact names and also needs less working around
|
||||
|
||||
if (evt.EventType == "NewMessageFromPeer" || evt.EventType == "NewMessageFromGroup") {
|
||||
val data = JSONObject(evt.Data)
|
||||
val handle = data.getString("RemotePeer");
|
||||
|
@ -145,19 +137,7 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) :
|
|||
Log.i(TAG, "notification for " + evt.EventType + " " + handle + " " + conversationId + " " + channelId)
|
||||
Log.i(TAG, data.toString());
|
||||
val key = loader.getLookupKeyForAsset(data.getString("picture"))//"assets/profiles/001-centaur.png")
|
||||
var fh : java.io.InputStream? = null;
|
||||
try {
|
||||
fh = applicationContext.assets.open(key)
|
||||
} catch (e: Exception) {
|
||||
Log.d("FlwtchWorker->ContactInfo", e.toString() + " :: " + e.getStackTrace());
|
||||
}
|
||||
|
||||
try {
|
||||
val file = File(data.getString("picture"))
|
||||
fh = FileInputStream(file)
|
||||
} catch (e: Exception) {
|
||||
Log.d("FlwtchWorker->ContactInfo", e.toString() + " :: " + e.getStackTrace());
|
||||
}
|
||||
val fh = applicationContext.assets.open(key)
|
||||
|
||||
val clickIntent = Intent(applicationContext, MainActivity::class.java).also { intent ->
|
||||
intent.action = Intent.ACTION_RUN
|
||||
|
@ -165,21 +145,18 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) :
|
|||
intent.putExtra("ProfileOnion", data.getString("ProfileOnion"))
|
||||
intent.putExtra("Handle", handle)
|
||||
}
|
||||
val image : android.graphics.Bitmap? = if (fh != null) BitmapFactory.decodeStream(fh ) else null;
|
||||
|
||||
val newNotification = NotificationCompat.Builder(applicationContext, channelId)
|
||||
.setContentTitle(data.getString("Nick"))
|
||||
.setContentText((notificationConversationInfo
|
||||
?: "New Message From %1").replace("%1", data.getString("Nick")))
|
||||
.setLargeIcon(image)
|
||||
.setLargeIcon(BitmapFactory.decodeStream(fh))
|
||||
.setSmallIcon(R.mipmap.knott_transparent)
|
||||
.setContentIntent(PendingIntent.getActivity(applicationContext, 1, clickIntent, flags))
|
||||
.setAutoCancel(true)
|
||||
.build()
|
||||
|
||||
notificationManager.notify(getNotificationID(data.getString("ProfileOnion"), channelId), newNotification)
|
||||
if (fh != null) {
|
||||
fh.close()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -190,36 +167,32 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) :
|
|||
val title = data.getString("NameSuggestion");
|
||||
val progress = data.getString("Progress").toInt();
|
||||
val progressMax = data.getString("FileSizeInChunks").toInt();
|
||||
|
||||
// if we have seen a download finished update for this key then ignore it
|
||||
if (!downloadFinishedIDs.containsKey(fileKey)) {
|
||||
if (!downloadIDs.containsKey(fileKey)) {
|
||||
downloadIDs.put(fileKey, downloadIDs.count());
|
||||
}
|
||||
var dlID = downloadIDs.get(fileKey);
|
||||
if (dlID == null) {
|
||||
dlID = 0;
|
||||
}
|
||||
if (progress >= 0) {
|
||||
val channelId =
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
createDownloadNotificationChannel(fileKey, fileKey)
|
||||
} else {
|
||||
// If earlier version channel ID is not used
|
||||
// https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#NotificationCompat.Builder(android.content.Context)
|
||||
""
|
||||
};
|
||||
val newNotification = NotificationCompat.Builder(applicationContext, channelId)
|
||||
.setOngoing(true)
|
||||
.setContentTitle("Downloading")//todo: translate
|
||||
.setContentText(title)
|
||||
.setSmallIcon(android.R.drawable.stat_sys_download)
|
||||
.setProgress(progressMax, progress, false)
|
||||
.setSound(null)
|
||||
//.setSilent(true)
|
||||
.build();
|
||||
notificationManager.notify(dlID, newNotification);
|
||||
}
|
||||
if (!downloadIDs.containsKey(fileKey)) {
|
||||
downloadIDs.put(fileKey, downloadIDs.count());
|
||||
}
|
||||
var dlID = downloadIDs.get(fileKey);
|
||||
if (dlID == null) {
|
||||
dlID = 0;
|
||||
}
|
||||
if (progress >= 0) {
|
||||
val channelId =
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
createDownloadNotificationChannel(fileKey, fileKey)
|
||||
} else {
|
||||
// If earlier version channel ID is not used
|
||||
// https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#NotificationCompat.Builder(android.content.Context)
|
||||
""
|
||||
};
|
||||
val newNotification = NotificationCompat.Builder(applicationContext, channelId)
|
||||
.setOngoing(true)
|
||||
.setContentTitle("Downloading")//todo: translate
|
||||
.setContentText(title)
|
||||
.setSmallIcon(android.R.drawable.stat_sys_download)
|
||||
.setProgress(progressMax, progress, false)
|
||||
.setSound(null)
|
||||
//.setSilent(true)
|
||||
.build();
|
||||
notificationManager.notify(dlID, newNotification);
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.d("FlwtchWorker->FileDownloadProgressUpdate", e.toString() + " :: " + e.getStackTrace());
|
||||
|
@ -243,8 +216,6 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) :
|
|||
Files.delete(sourcePath);
|
||||
}
|
||||
}
|
||||
// Suppress future notifications...
|
||||
downloadFinishedIDs.put(fileKey, downloadIDs.count());
|
||||
if (downloadIDs.containsKey(fileKey)) {
|
||||
notificationManager.cancel(downloadIDs.get(fileKey) ?: 0);
|
||||
}
|
||||
|
@ -315,7 +286,7 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) :
|
|||
.addAction(android.R.drawable.ic_delete, cancel, PendingIntent.getActivity(applicationContext, 2, cancelIntent, flags))
|
||||
.build()
|
||||
|
||||
return ForegroundInfo(101, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC)
|
||||
return ForegroundInfo(101, notification)
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package im.cwtch.flwtch
|
||||
|
||||
import SplashView
|
||||
import android.annotation.TargetApi
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
|
@ -18,6 +19,7 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
|||
import androidx.work.*
|
||||
import cwtch.Cwtch
|
||||
import io.flutter.embedding.android.FlutterActivity
|
||||
import io.flutter.embedding.android.SplashScreen
|
||||
import io.flutter.embedding.engine.FlutterEngine
|
||||
import io.flutter.plugin.common.ErrorLogResult
|
||||
import io.flutter.plugin.common.MethodCall
|
||||
|
@ -27,14 +29,15 @@ import org.json.JSONObject
|
|||
import java.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlinx.coroutines.*
|
||||
|
||||
|
||||
class MainActivity: FlutterActivity() {
|
||||
override fun provideSplashScreen(): SplashScreen? = SplashView()
|
||||
|
||||
|
||||
// Channel to get app info
|
||||
private val CHANNEL_APP_INFO = "test.flutter.dev/applicationInfo"
|
||||
private val CALL_APP_INFO = "getNativeLibDir"
|
||||
private val CALL_SERVICE_INFO = "getForegroundServiceInfo"
|
||||
private val ANDROID_SETTINGS_CHANNEL_NAME = "androidSettings"
|
||||
private val ANDROID_SETTINGS_CHANGE_NAME= "androidSettingsChanged"
|
||||
private var andoidSettingsChangeChannel: MethodChannel? = null
|
||||
|
@ -65,7 +68,6 @@ class MainActivity: FlutterActivity() {
|
|||
private val PROFILE_EXPORT_REQUEST_CODE = 236
|
||||
private val REQUEST_DOZE_WHITELISTING_CODE:Int = 9
|
||||
private var dlToProfile = ""
|
||||
private var dlManifestPath = ""
|
||||
private var dlToHandle = 0
|
||||
private var dlToFileKey = ""
|
||||
private var exportFromPath = ""
|
||||
|
@ -125,12 +127,13 @@ class MainActivity: FlutterActivity() {
|
|||
|
||||
if (requestCode == FILEPICKER_REQUEST_CODE) {
|
||||
val filePath = intent!!.getData().toString();
|
||||
val manifestPath = StringBuilder().append(this.applicationContext.cacheDir).append("/").append(this.dlToFileKey).toString();
|
||||
Log.d("MainActivity:FILEPICKER_REQUEST_CODE", "DownloadableFileCreated");
|
||||
handleCwtch(MethodCall("DownloadFile", mapOf(
|
||||
"ProfileOnion" to this.dlToProfile,
|
||||
"conversation" to this.dlToHandle.toInt(),
|
||||
"filepath" to filePath,
|
||||
"manifestpath" to this.dlManifestPath,
|
||||
"manifestpath" to manifestPath,
|
||||
"filekey" to this.dlToFileKey
|
||||
)), ErrorLogResult(""));//placeholder; this Result is never actually invoked
|
||||
} else if (requestCode == PREVIEW_EXPORT_REQUEST_CODE) {
|
||||
|
@ -186,9 +189,7 @@ class MainActivity: FlutterActivity() {
|
|||
when (call.method) {
|
||||
CALL_APP_INFO -> result.success(getNativeLibDir())
|
||||
?: result.error("Unavailable", "nativeLibDir not available", null);
|
||||
CALL_SERVICE_INFO -> result.success(getForegroundServiceInfo())
|
||||
?: result.error("Unavailable", "getForegroundServiceInfo not available", null);
|
||||
else -> result.notImplemented()
|
||||
else -> result.notImplemented()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -223,24 +224,6 @@ class MainActivity: FlutterActivity() {
|
|||
return ainfo.nativeLibraryDir
|
||||
}
|
||||
|
||||
|
||||
fun getForegroundServiceInfo(): HashMap<String,String> {
|
||||
var hashMap : HashMap<String, String>
|
||||
= HashMap<String, String> ();
|
||||
val workmanager = WorkManager.getInstance(this);
|
||||
if (workmanager != null) {
|
||||
runBlocking {
|
||||
var lastCancelAllTime = workmanager.getLastCancelAllTimeMillis().await();
|
||||
hashMap.put("workmanager.lastCancelAllTime", lastCancelAllTime.toString());
|
||||
}
|
||||
val works = workmanager.getWorkInfosByTag(WORKER_TAG).get()
|
||||
for (workInfo in works) {
|
||||
hashMap.put("workmanager.${workInfo.id}.state", workInfo.state.toString());
|
||||
}
|
||||
}
|
||||
return hashMap
|
||||
}
|
||||
|
||||
// receives messages from the ForegroundService (which provides, ironically enough, the backend)
|
||||
private fun handleCwtch(@NonNull call: MethodCall, @NonNull result: Result) {
|
||||
var method = call.method
|
||||
|
@ -251,7 +234,6 @@ class MainActivity: FlutterActivity() {
|
|||
// the frontend calls Start every time it fires up, but we don't want to *actually* call Cwtch.Start()
|
||||
// in case the ForegroundService is still running. in both cases, however, we *do* want to re-register
|
||||
// the eventbus listener.
|
||||
|
||||
when (call.method) {
|
||||
"Start" -> {
|
||||
val uniqueTag = argmap["torPath"] ?: "nullEventBus"
|
||||
|
@ -275,7 +257,6 @@ class MainActivity: FlutterActivity() {
|
|||
"CreateDownloadableFile" -> {
|
||||
this.dlToProfile = argmap["ProfileOnion"] ?: ""
|
||||
this.dlToHandle = call.argument("conversation")!!
|
||||
this.dlManifestPath = argmap["manifestpath"] ?: ""
|
||||
val suggestedName = argmap["filename"] ?: "filename.ext"
|
||||
this.dlToFileKey = argmap["filekey"] ?: ""
|
||||
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
|
||||
|
@ -327,9 +308,8 @@ class MainActivity: FlutterActivity() {
|
|||
val conversation: Int = call.argument("conversation") ?: 0
|
||||
val indexI: Int = call.argument("index") ?: 0
|
||||
val count: Int = call.argument("count") ?: 1
|
||||
val ucount : Int = maxOf(1, count) // don't allow negative counts
|
||||
|
||||
result.success(Cwtch.getMessages(profile, conversation.toLong(), indexI.toLong(), ucount.toLong()))
|
||||
result.success(Cwtch.getMessages(profile, conversation.toLong(), indexI.toLong(), count.toLong()))
|
||||
return
|
||||
}
|
||||
"SendMessage" -> {
|
||||
|
@ -343,7 +323,7 @@ class MainActivity: FlutterActivity() {
|
|||
val profile: String = call.argument("ProfileOnion") ?: ""
|
||||
val conversation: Int = call.argument("conversation") ?: 0
|
||||
val target: Int = call.argument("target") ?: 0
|
||||
result.success(Cwtch.sendInviteMessage(profile, conversation.toLong(), target.toLong()))
|
||||
result.success(Cwtch.sendInvitation(profile, conversation.toLong(), target.toLong()))
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -362,51 +342,20 @@ class MainActivity: FlutterActivity() {
|
|||
return
|
||||
}
|
||||
|
||||
"RestartFileShare" -> {
|
||||
"RestartSharing" -> {
|
||||
val profile: String = call.argument("ProfileOnion") ?: ""
|
||||
val filepath: String = call.argument("filekey") ?: ""
|
||||
result.success(Cwtch.restartFileShare(profile, filepath))
|
||||
result.success(Cwtch.restartSharing(profile, filepath))
|
||||
return
|
||||
}
|
||||
|
||||
"StopSharing" -> {
|
||||
val profile: String = call.argument("ProfileOnion") ?: ""
|
||||
val filepath: String = call.argument("filekey") ?: ""
|
||||
result.success(Cwtch.stopFileShare(profile, filepath))
|
||||
result.success(Cwtch.stopSharing(profile, filepath))
|
||||
return
|
||||
}
|
||||
|
||||
"DeleteServerInfo" -> {
|
||||
val profile: String = call.argument("ProfileOnion") ?: ""
|
||||
val handle: String = call.argument("handle") ?: ""
|
||||
result.success(Cwtch.deleteServerInfo(profile, handle))
|
||||
return
|
||||
}
|
||||
"PublishServerUpdate" -> {
|
||||
val profile: String = call.argument("ProfileOnion") ?: ""
|
||||
result.success(Cwtch.publishServerUpdate(profile))
|
||||
return
|
||||
}
|
||||
"PeerWithOnion" -> {
|
||||
val profile: String = call.argument("ProfileOnion") ?: ""
|
||||
val onion: String = call.argument("onion") ?: ""
|
||||
Cwtch.peerWithOnion(profile, onion)
|
||||
}
|
||||
"QueueJoinServer" -> {
|
||||
val profile: String = call.argument("ProfileOnion") ?: ""
|
||||
val onion: String = call.argument("onion") ?: ""
|
||||
Cwtch.peerWithOnion(profile, onion)
|
||||
}
|
||||
"DisconnectFromPeer" -> {
|
||||
val profile: String = call.argument("ProfileOnion") ?: ""
|
||||
val onion: String = call.argument("onion") ?: ""
|
||||
Cwtch.peerWithOnion(profile, onion)
|
||||
}
|
||||
"DisconnectFromServer" -> {
|
||||
val profile: String = call.argument("ProfileOnion") ?: ""
|
||||
val onion: String = call.argument("onion") ?: ""
|
||||
Cwtch.peerWithOnion(profile, onion)
|
||||
}
|
||||
"CreateProfile" -> {
|
||||
val nick: String = call.argument("nick") ?: ""
|
||||
val pass: String = call.argument("pass") ?: ""
|
||||
|
@ -421,13 +370,6 @@ class MainActivity: FlutterActivity() {
|
|||
val profile: String = call.argument("profile") ?: ""
|
||||
Cwtch.activatePeerEngine(profile)
|
||||
}
|
||||
"ConfigureConnections" -> {
|
||||
val profile: String = call.argument("ProfileOnion") ?: ""
|
||||
val listen: Boolean = call.argument("listen") ?: false
|
||||
val peers: Boolean = call.argument("peers") ?: false
|
||||
val servers: Boolean = call.argument("servers") ?: false
|
||||
Cwtch.configureConnections(profile, listen, peers, servers)
|
||||
}
|
||||
"DeactivatePeerEngine" -> {
|
||||
val profile: String = call.argument("profile") ?: ""
|
||||
Cwtch.deactivatePeerEngine(profile)
|
||||
|
@ -439,18 +381,25 @@ class MainActivity: FlutterActivity() {
|
|||
val passNew2: String = call.argument("NewPassAgain") ?: ""
|
||||
Cwtch.changePassword(profile, pass, passNew, passNew2)
|
||||
}
|
||||
"GetMessage" -> {
|
||||
val profile: String = call.argument("ProfileOnion") ?: ""
|
||||
val conversation: Int = call.argument("conversation") ?: 0
|
||||
val indexI: Int = call.argument("index") ?: 0
|
||||
result.success(Cwtch.getMessage(profile, conversation.toLong(), indexI.toLong()))
|
||||
return
|
||||
}
|
||||
"GetMessageByID" -> {
|
||||
val profile: String = call.argument("ProfileOnion") ?: ""
|
||||
val conversation: Int = call.argument("conversation") ?: 0
|
||||
val id: Int = call.argument("id") ?: 0
|
||||
result.success(Cwtch.getMessageById(profile, conversation.toLong(), id.toLong()))
|
||||
result.success(Cwtch.getMessageByID(profile, conversation.toLong(), id.toLong()))
|
||||
return
|
||||
}
|
||||
"GetMessageByContentHash" -> {
|
||||
val profile: String = call.argument("ProfileOnion") ?: ""
|
||||
val conversation: Int = call.argument("conversation") ?: 0
|
||||
val contentHash: String = call.argument("contentHash") ?: ""
|
||||
result.success(Cwtch.getMessageByContentHash(profile, conversation.toLong(), contentHash))
|
||||
result.success(Cwtch.getMessagesByContentHash(profile, conversation.toLong(), contentHash))
|
||||
return
|
||||
}
|
||||
"SetMessageAttribute" -> {
|
||||
|
@ -460,7 +409,7 @@ class MainActivity: FlutterActivity() {
|
|||
val midx: Int = call.argument("Message") ?: 0
|
||||
val key: String = call.argument("key") ?: ""
|
||||
val value: String = call.argument("value") ?: ""
|
||||
Cwtch.updateMessageAttribute(profile, conversation.toLong(), channel.toLong(), midx.toLong(), key, value)
|
||||
Cwtch.setMessageAttribute(profile, conversation.toLong(), channel.toLong(), midx.toLong(), key, value)
|
||||
}
|
||||
"AcceptConversation" -> {
|
||||
val profile: String = call.argument("ProfileOnion") ?: ""
|
||||
|
@ -470,12 +419,12 @@ class MainActivity: FlutterActivity() {
|
|||
"BlockContact" -> {
|
||||
val profile: String = call.argument("ProfileOnion") ?: ""
|
||||
val conversation: Int = call.argument("conversation") ?: 0
|
||||
Cwtch.blockConversation(profile, conversation.toLong())
|
||||
Cwtch.blockContact(profile, conversation.toLong())
|
||||
}
|
||||
"UnblockContact" -> {
|
||||
val profile: String = call.argument("ProfileOnion") ?: ""
|
||||
val conversation: Int = call.argument("conversation") ?: 0
|
||||
Cwtch.unblockConversation(profile, conversation.toLong())
|
||||
Cwtch.unblockContact(profile, conversation.toLong())
|
||||
}
|
||||
|
||||
"DownloadFile" -> {
|
||||
|
@ -487,7 +436,7 @@ class MainActivity: FlutterActivity() {
|
|||
val filekey: String = call.argument("filekey") ?: ""
|
||||
// FIXME: Prevent spurious calls by Intent
|
||||
if (profile != "") {
|
||||
Cwtch.downloadFileDefaultLimit(profile, conversation.toLong(), filepath, manifestpath, filekey)
|
||||
Cwtch.downloadFile(profile, conversation.toLong(), filepath, manifestpath, filekey)
|
||||
}
|
||||
}
|
||||
"CheckDownloadStatus" -> {
|
||||
|
@ -499,11 +448,16 @@ class MainActivity: FlutterActivity() {
|
|||
val profile: String = call.argument("ProfileOnion") ?: ""
|
||||
val conversation: Int = call.argument("conversation") ?: 0
|
||||
val fileKey: String = call.argument("fileKey") ?: ""
|
||||
Cwtch.verifyOrResumeDownloadDefaultLimit(profile, conversation.toLong(), fileKey)
|
||||
Cwtch.verifyOrResumeDownload(profile, conversation.toLong(), fileKey)
|
||||
}
|
||||
"UpdateSettings" -> {
|
||||
val json: String = call.argument("json") ?: ""
|
||||
Cwtch.updateSettings(json)
|
||||
"SendProfileEvent" -> {
|
||||
val onion: String= call.argument("onion") ?: ""
|
||||
val jsonEvent: String = call.argument("jsonEvent") ?: ""
|
||||
Cwtch.sendProfileEvent(onion, jsonEvent)
|
||||
}
|
||||
"SendAppEvent" -> {
|
||||
val jsonEvent: String = call.argument("jsonEvent") ?: ""
|
||||
Cwtch.sendAppEvent(jsonEvent)
|
||||
}
|
||||
"ResetTor" -> {
|
||||
Cwtch.resetTor()
|
||||
|
@ -517,7 +471,7 @@ class MainActivity: FlutterActivity() {
|
|||
val profile: String = call.argument("ProfileOnion") ?: ""
|
||||
val server: String = call.argument("server") ?: ""
|
||||
val groupName: String = call.argument("groupName") ?: ""
|
||||
Cwtch.startGroup(profile, groupName, server)
|
||||
Cwtch.createGroup(profile, server, groupName)
|
||||
}
|
||||
"DeleteProfile" -> {
|
||||
val profile: String = call.argument("ProfileOnion") ?: ""
|
||||
|
@ -532,7 +486,7 @@ class MainActivity: FlutterActivity() {
|
|||
"DeleteConversation" -> {
|
||||
val profile: String = call.argument("ProfileOnion") ?: ""
|
||||
val conversation: Int = call.argument("conversation") ?: 0
|
||||
Cwtch.deleteConversation(profile, conversation.toLong())
|
||||
Cwtch.deleteContact(profile, conversation.toLong())
|
||||
}
|
||||
"SetProfileAttribute" -> {
|
||||
val profile: String = call.argument("ProfileOnion") ?: ""
|
||||
|
@ -540,20 +494,6 @@ class MainActivity: FlutterActivity() {
|
|||
val v: String = call.argument("Val") ?: ""
|
||||
Cwtch.setProfileAttribute(profile, key, v)
|
||||
}
|
||||
"GetProfileAttribute" -> {
|
||||
val profile: String = call.argument("ProfileOnion") ?: ""
|
||||
val key: String = call.argument("key") ?: ""
|
||||
var resultjson = Cwtch.getProfileAttribute(profile, key);
|
||||
return result.success(resultjson)
|
||||
}
|
||||
"GetConversationAttribute" -> {
|
||||
val profile: String = call.argument("ProfileOnion") ?: ""
|
||||
val conversation: Int = call.argument("conversation") ?: 0
|
||||
val key: String = call.argument("key") ?: ""
|
||||
var resultjson = Cwtch.getConversationAttribute(profile, conversation.toLong(), key);
|
||||
result.success(resultjson)
|
||||
return
|
||||
}
|
||||
"SetConversationAttribute" -> {
|
||||
val profile: String = call.argument("ProfileOnion") ?: ""
|
||||
val conversation: Int = call.argument("conversation") ?: 0
|
||||
|
@ -561,17 +501,51 @@ class MainActivity: FlutterActivity() {
|
|||
val v: String = call.argument("Val") ?: ""
|
||||
Cwtch.setConversationAttribute(profile, conversation.toLong(), key, v)
|
||||
}
|
||||
"LoadServers" -> {
|
||||
val password: String = call.argument("Password") ?: ""
|
||||
Cwtch.loadServers(password)
|
||||
}
|
||||
"CreateServer" -> {
|
||||
val password: String = call.argument("Password") ?: ""
|
||||
val desc: String = call.argument("Description") ?: ""
|
||||
val autostart: Boolean = call.argument("Autostart") ?: false
|
||||
Cwtch.createServer(password, desc, autostart)
|
||||
}
|
||||
"DeleteServer" -> {
|
||||
val serverOnion: String = call.argument("ServerOnion") ?: ""
|
||||
val password: String = call.argument("Password") ?: ""
|
||||
Cwtch.deleteServer(serverOnion, password)
|
||||
}
|
||||
"LaunchServers" -> {
|
||||
Cwtch.launchServers()
|
||||
}
|
||||
"LaunchServer" -> {
|
||||
val serverOnion: String = call.argument("ServerOnion") ?: ""
|
||||
Cwtch.launchServer(serverOnion)
|
||||
}
|
||||
"StopServer" -> {
|
||||
val serverOnion: String = call.argument("ServerOnion") ?: ""
|
||||
Cwtch.stopServer(serverOnion)
|
||||
}
|
||||
"StopServers" -> {
|
||||
Cwtch.stopServers()
|
||||
}
|
||||
"DestroyServers" -> {
|
||||
Cwtch.destroyServers()
|
||||
}
|
||||
"SetServerAttribute" -> {
|
||||
val serverOnion: String = call.argument("ServerOnion") ?: ""
|
||||
val key: String = call.argument("Key") ?: ""
|
||||
val v: String = call.argument("Val") ?: ""
|
||||
Cwtch.setServerAttribute(serverOnion, key, v)
|
||||
}
|
||||
"ImportProfile" -> {
|
||||
val file: String = call.argument("file") ?: ""
|
||||
val pass: String = call.argument("pass") ?: ""
|
||||
result.success(Cwtch.importProfile(file, pass))
|
||||
return
|
||||
Data.Builder().putString("result", Cwtch.importProfile(file, pass)).build()
|
||||
}
|
||||
"SearchConversations" -> {
|
||||
val profile: String = call.argument("ProfileOnion") ?: ""
|
||||
val pattern: String = call.argument("pattern") ?: ""
|
||||
result.success(Cwtch.searchConversations(profile, pattern))
|
||||
return
|
||||
"ReconnectCwtchForeground" -> {
|
||||
Cwtch.reconnectCwtchForeground()
|
||||
}
|
||||
"Shutdown" -> {
|
||||
Cwtch.shutdownCwtch();
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import im.cwtch.flwtch.R
|
||||
import io.flutter.embedding.android.SplashScreen
|
||||
|
||||
class SplashView : SplashScreen {
|
||||
override fun createSplashView(context: Context, savedInstanceState: Bundle?): View? =
|
||||
LayoutInflater.from(context).inflate(R.layout.splash_view, null, false)
|
||||
|
||||
override fun transitionToFlutter(onTransitionComplete: Runnable) {
|
||||
onTransitionComplete.run()
|
||||
}
|
||||
}
|
|
@ -1,12 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Modify this file to customize your launch splash screen -->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@color/darkGreyPurple" />
|
||||
<item android:drawable="?android:colorBackground" />
|
||||
|
||||
<!-- You can insert your own image assets here -->
|
||||
<item>
|
||||
<!-- <item>
|
||||
<bitmap
|
||||
android:gravity="center"
|
||||
android:src="@mipmap/knott" />
|
||||
</item>
|
||||
android:src="@mipmap/launch_image" />
|
||||
</item> -->
|
||||
</layer-list>
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="500dp"
|
||||
android:height="500dp"
|
||||
android:viewportWidth="500"
|
||||
android:viewportHeight="500">
|
||||
<path
|
||||
android:pathData="M436.2,215c-0.6,3 -2,6.4 -4.3,10.4l18.2,18.2c2.4,-4.8 6.2,-13.1 8.2,-22.9c4.1,-20.2 -0.5,-37.1 -13.7,-50.3c-24.2,-24.2 -49.4,-26.4 -81.8,-7.3c-7.8,4.6 -16.1,10.6 -24.6,17.7c-19.5,16.3 -41.3,39.5 -64.9,69.2c15.4,19.4 30.2,36.2 43.8,49.8c6.3,6.3 12.4,12 18.3,17.1l16.2,-16.2c-5.9,-5 -12.1,-10.7 -18.4,-17c-9,-9 -18.5,-19.5 -28.4,-31.2l-2.1,-2.5l2.1,-2.5c18.1,-21.5 35,-38.6 50.1,-50.9c9.6,-7.8 18.6,-13.8 26.7,-17.7c7,-3.4 13.4,-5.3 19,-5.6c2.7,-0.2 6.9,-0.1 12.1,2c5,2.1 10.2,5.8 15.7,11.3c2.1,2.1 5,5.4 6.8,10.4C437.1,202.1 437.5,208 436.2,215L436.2,215z"
|
||||
android:fillColor="#242425"/>
|
||||
<path
|
||||
android:pathData="M340.9,354.7l81.5,-81.5c-4.8,-7.1 -11.1,-14 -14.6,-17.7L327.3,336C332.5,342.4 337.1,348.6 340.9,354.7z"
|
||||
android:fillColor="#242425"/>
|
||||
<path
|
||||
android:pathData="M444.6,329.6c13.2,-13.2 17.8,-30.1 13.7,-50.3c-2.8,-14 -9.1,-24.9 -10.3,-26.9L382.6,187c-6,3.1 -12.5,7.4 -19.4,12.8l50.1,50.1l0,0c4.1,4.3 12.1,13 17.4,21.6c3.2,5.2 5.1,9.7 5.6,13.5c1.2,6.9 0.9,12.7 -0.9,17.9c-1.8,5 -4.8,8.3 -6.8,10.4c-5.9,5.9 -11.3,9.7 -16.7,11.7c-5.5,2 -10,1.8 -13.3,1.4c-4.4,-0.5 -9.2,-2 -14.3,-4.2l-17,17C397.5,355.7 421.5,352.7 444.6,329.6z"
|
||||
android:fillColor="#242425"/>
|
||||
<path
|
||||
android:pathData="M303.1,64.7c5,1.8 8.3,4.8 10.4,6.8c5.9,5.9 9.7,11.3 11.7,16.7c2,5.5 1.8,10 1.4,13.3c-0.5,4.4 -2,9.2 -4.2,14.3l17,17c16.4,-30.3 13.3,-54.4 -9.7,-77.4c-13.2,-13.2 -30.1,-17.8 -50.3,-13.7c-14,2.8 -24.9,9.1 -26.9,10.3L187,117.4c3.1,6 7.4,12.5 12.8,19.4L250,86.7l0,0c4.3,-4.1 13,-12.1 21.6,-17.4c5.2,-3.2 9.7,-5.1 13.5,-5.6C292,62.6 297.9,62.9 303.1,64.7z"
|
||||
android:fillColor="#242425"/>
|
||||
<path
|
||||
android:pathData="M170.4,55.4c-24.2,24.2 -26.4,49.4 -7.3,81.8c4.6,7.8 10.6,16.1 17.7,24.6c16.3,19.5 39.5,41.3 69.2,64.9c19.4,-15.4 36.2,-30.2 49.8,-43.8c6.3,-6.3 12,-12.4 17.1,-18.3l-16.2,-16.2c-5,5.9 -10.7,12.1 -17,18.4c-9,9 -19.5,18.5 -31.2,28.4l-2.5,2.1l-2.5,-2.1c-21.5,-18.1 -38.6,-35 -50.9,-50.1c-7.8,-9.6 -13.8,-18.6 -17.7,-26.7c-3.4,-7 -5.3,-13.4 -5.6,-19c-0.2,-2.7 -0.1,-6.9 2,-12.1c2.1,-5 5.8,-10.2 11.3,-15.7c2.1,-2.1 5.4,-5 10.4,-6.8c5.2,-1.9 11.1,-2.2 18,-0.9l0.1,0c3,0.6 6.4,2 10.4,4.3l18.2,-18.2c-4.8,-2.4 -13.1,-6.2 -23,-8.2C200.5,37.6 183.6,42.2 170.4,55.4z"
|
||||
android:fillColor="#242425"/>
|
||||
<path
|
||||
android:pathData="M273.2,77.6c-7.1,4.8 -14,11.1 -17.7,14.6l80.5,80.5c6.4,-5.2 12.7,-9.7 18.7,-13.6L273.2,77.6z"
|
||||
android:fillColor="#242425"/>
|
||||
<path
|
||||
android:pathData="M55.4,329.6c24.2,24.2 49.4,26.4 81.8,7.3c7.8,-4.6 16.1,-10.6 24.6,-17.7c19.5,-16.3 41.3,-39.5 64.9,-69.2c-15.4,-19.4 -30.2,-36.2 -43.8,-49.8c-6.3,-6.3 -12.4,-12 -18.3,-17.1l-16.2,16.2c5.9,5 12.1,10.7 18.4,17c9,9 18.5,19.5 28.4,31.2l2.1,2.5l-2.1,2.5c-18.1,21.5 -35,38.6 -50.1,50.9c-9.6,7.8 -18.6,13.8 -26.7,17.7c-7,3.4 -13.4,5.3 -19,5.6c-2.7,0.2 -6.9,0.1 -12.1,-2c-5,-2.1 -10.2,-5.8 -15.7,-11.3c-2.1,-2.1 -5,-5.4 -6.8,-10.4c-1.9,-5.2 -2.2,-11.1 -0.9,-18l0,-0.1c0.6,-3 2,-6.4 4.3,-10.4l-18.2,-18.2c-2.4,4.8 -6.2,13.1 -8.2,23C37.6,299.5 42.2,316.4 55.4,329.6z"
|
||||
android:fillColor="#242425"/>
|
||||
<path
|
||||
android:pathData="M86.7,250L86.7,250c-4.1,-4.4 -12,-13.1 -17.3,-21.6c-3.2,-5.2 -5.1,-9.7 -5.6,-13.5c-1.2,-6.9 -0.9,-12.7 0.9,-17.9c1.8,-5 4.8,-8.3 6.8,-10.4c5.9,-5.9 11.3,-9.7 16.7,-11.7c5.5,-2 10,-1.8 13.3,-1.4c4.4,0.5 9.2,2 14.3,4.2l17,-17c-30.3,-16.4 -54.4,-13.3 -77.4,9.7c-13.2,13.2 -17.8,30.1 -13.7,50.3c2.8,14 9.1,24.9 10.3,26.9l65.4,65.4c6,-3.1 12.5,-7.4 19.4,-12.8L86.7,250z"
|
||||
android:fillColor="#242425"/>
|
||||
<path
|
||||
android:pathData="M92.2,244.5l80.5,-80.5c-5.2,-6.4 -9.7,-12.7 -13.6,-18.7l-81.5,81.5C82.4,233.9 88.6,240.8 92.2,244.5z"
|
||||
android:fillColor="#242425"/>
|
||||
<path
|
||||
android:pathData="M329.6,444.6c24.2,-24.2 26.4,-49.4 7.3,-81.8c-4.6,-7.8 -10.6,-16.1 -17.7,-24.6c-16.3,-19.5 -39.5,-41.3 -69.2,-64.9c-19.4,15.4 -36.2,30.2 -49.8,43.8c-6.3,6.3 -12,12.4 -17.1,18.3l16.2,16.2c5,-5.9 10.7,-12.1 17,-18.4c9,-9 19.5,-18.5 31.2,-28.4l2.5,-2.1l2.5,2.1c21.5,18.1 38.6,35 50.9,50.1c7.8,9.6 13.8,18.6 17.7,26.7c3.4,7 5.3,13.4 5.6,19c0.2,2.7 0.1,6.9 -2,12.1c-2.1,5 -5.8,10.2 -11.3,15.7c-2.1,2.1 -5.4,5 -10.4,6.8c-5.2,1.9 -11.1,2.2 -18,0.9l-0.1,0c-3,-0.6 -6.4,-2 -10.4,-4.3l-18.2,18.2c4.7,2.4 13.1,6.1 22.9,8.2C299.4,462.4 316.4,457.8 329.6,444.6z"
|
||||
android:fillColor="#242425"/>
|
||||
<path
|
||||
android:pathData="M244.5,407.8L164,327.3c-6.4,5.2 -12.7,9.7 -18.7,13.6l81.5,81.5C233.9,417.6 240.8,411.4 244.5,407.8z"
|
||||
android:fillColor="#242425"/>
|
||||
<path
|
||||
android:pathData="M483.4,250c2.6,-6.3 5.3,-14 7.1,-22.7c6.3,-30.8 -1.8,-59.2 -22.7,-80.1c-19.7,-19.7 -41.7,-29.7 -65.5,-29.7c-7.5,0 -15.1,1 -22.8,3c2.9,-11.3 3.7,-22.3 2.3,-33.2c-2.5,-19.8 -12.3,-38.3 -29,-55.1C336.6,15.9 315.9,7.4 293,7.4c-6.6,0 -13.4,0.7 -20.2,2.1c-8.7,1.8 -16.5,4.5 -22.7,7.1c-6.3,-2.6 -14.1,-5.3 -22.8,-7.1c-6.9,-1.4 -13.7,-2.1 -20.2,-2.1c-22.9,0 -43.6,8.6 -59.9,24.8c-17.6,17.6 -27.5,37.2 -29.4,58.1c-0.9,9.9 0,19.9 2.7,30.2c-7.7,-2 -15.3,-3 -22.8,-3c-23.8,0 -45.8,10 -65.5,29.7c-20.9,20.9 -28.9,49.3 -22.7,80.1c1.8,8.7 4.5,16.5 7.1,22.7c-2.6,6.3 -5.3,14.1 -7.1,22.8c-6.2,30.8 1.8,59.2 22.7,80.1c19.7,19.7 41.7,29.7 65.5,29.7c0,0 0,0 0,0c7.5,0 15.1,-1 22.8,-3c-2.9,11.3 -3.7,22.3 -2.3,33.2c2.5,19.8 12.3,38.3 29,55.1c16.2,16.2 36.9,24.8 59.8,24.8c0,0 0,0 0,0c6.6,0 13.4,-0.7 20.2,-2.1c8.7,-1.8 16.5,-4.4 22.7,-7.1c6.3,2.6 14,5.3 22.7,7.1c6.9,1.4 13.7,2.1 20.3,2.1c0,0 0,0 0,0c22.9,0 43.6,-8.6 59.9,-24.8c17.6,-17.6 27.5,-37.2 29.4,-58.1c0.9,-9.9 0,-19.9 -2.7,-30.2c7.7,2 15.3,3 22.8,3c0,0 0,0 0,0c23.8,0 45.8,-10 65.5,-29.7c20.9,-20.9 29,-49.3 22.7,-80.1C488.8,264 486.1,256.3 483.4,250z"
|
||||
android:fillColor="#242425"/>
|
||||
<path
|
||||
android:pathData="M170.4,444.6c13.2,13.2 30.1,17.8 50.3,13.7c14,-2.8 24.9,-9.1 26.9,-10.3l65.4,-65.4c-3.1,-6 -7.4,-12.5 -12.8,-19.4L250,413.3l0,0c-4.3,4.1 -13,12.1 -21.6,17.4c-5.2,3.2 -9.7,5.1 -13.5,5.6c-6.9,1.2 -12.7,0.9 -17.9,-0.9c-5,-1.8 -8.3,-4.8 -10.4,-6.8c-5.9,-5.9 -9.7,-11.3 -11.7,-16.7c-2,-5.5 -1.8,-10 -1.4,-13.3c0.5,-4.4 2,-9.2 4.2,-14.3l-17,-17C144.3,397.5 147.3,421.5 170.4,444.6z"
|
||||
android:fillColor="#242425"/>
|
||||
<path
|
||||
android:pathData="M436.2,215c-0.6,3 -2,6.4 -4.3,10.4l18.2,18.2c2.4,-4.8 6.2,-13.1 8.2,-22.9c4.1,-20.2 -0.5,-37.1 -13.7,-50.3c-24.2,-24.2 -49.4,-26.4 -81.8,-7.3c-7.8,4.6 -16.1,10.6 -24.6,17.7c-19.5,16.3 -41.3,39.5 -64.9,69.2c15.4,19.4 30.2,36.2 43.8,49.8c6.3,6.3 12.4,12 18.3,17.1l16.2,-16.2c-5.9,-5 -12.1,-10.7 -18.4,-17c-9,-9 -18.5,-19.5 -28.4,-31.2l-2.1,-2.5l2.1,-2.5c18.1,-21.5 35,-38.6 50.1,-50.9c9.6,-7.8 18.6,-13.8 26.7,-17.7c7,-3.4 13.4,-5.3 19,-5.6c2.7,-0.2 6.9,-0.1 12.1,2c5,2.1 10.2,5.8 15.7,11.3c2.1,2.1 5,5.4 6.8,10.4C437.1,202.1 437.5,208 436.2,215L436.2,215z"
|
||||
android:fillColor="#FFFFFF"/>
|
||||
<path
|
||||
android:pathData="M340.9,354.7l81.5,-81.5c-4.8,-7.1 -11.1,-14 -14.6,-17.7L327.3,336C332.5,342.4 337.1,348.6 340.9,354.7z"
|
||||
android:fillColor="#FFFFFF"/>
|
||||
<path
|
||||
android:pathData="M444.6,329.6c13.2,-13.2 17.8,-30.1 13.7,-50.3c-2.8,-14 -9.1,-24.9 -10.3,-26.9L382.6,187c-6,3.1 -12.5,7.4 -19.4,12.8l50.1,50.1l0,0c4.1,4.3 12.1,13 17.4,21.6c3.2,5.2 5.1,9.7 5.6,13.5c1.2,6.9 0.9,12.7 -0.9,17.9c-1.8,5 -4.8,8.3 -6.8,10.4c-5.9,5.9 -11.3,9.7 -16.7,11.7c-5.5,2 -10,1.8 -13.3,1.4c-4.4,-0.5 -9.2,-2 -14.3,-4.2l-17,17C397.5,355.7 421.5,352.7 444.6,329.6z"
|
||||
android:fillColor="#FFFFFF"/>
|
||||
<path
|
||||
android:pathData="M303.1,64.7c5,1.8 8.3,4.8 10.4,6.8c5.9,5.9 9.7,11.3 11.7,16.7c2,5.5 1.8,10 1.4,13.3c-0.5,4.4 -2,9.2 -4.2,14.3l17,17c16.4,-30.3 13.3,-54.4 -9.7,-77.4c-13.2,-13.2 -30.1,-17.8 -50.3,-13.7c-14,2.8 -24.9,9.1 -26.9,10.3L187,117.4c3.1,6 7.4,12.5 12.8,19.4L250,86.7l0,0c4.3,-4.1 13,-12.1 21.6,-17.4c5.2,-3.2 9.7,-5.1 13.5,-5.6C292,62.6 297.9,62.9 303.1,64.7z"
|
||||
android:fillColor="#FFFFFF"/>
|
||||
<path
|
||||
android:pathData="M170.4,55.4c-24.2,24.2 -26.4,49.4 -7.3,81.8c4.6,7.8 10.6,16.1 17.7,24.6c16.3,19.5 39.5,41.3 69.2,64.9c19.4,-15.4 36.2,-30.2 49.8,-43.8c6.3,-6.3 12,-12.4 17.1,-18.3l-16.2,-16.2c-5,5.9 -10.7,12.1 -17,18.4c-9,9 -19.5,18.5 -31.2,28.4l-2.5,2.1l-2.5,-2.1c-21.5,-18.1 -38.6,-35 -50.9,-50.1c-7.8,-9.6 -13.8,-18.6 -17.7,-26.7c-3.4,-7 -5.3,-13.4 -5.6,-19c-0.2,-2.7 -0.1,-6.9 2,-12.1c2.1,-5 5.8,-10.2 11.3,-15.7c2.1,-2.1 5.4,-5 10.4,-6.8c5.2,-1.9 11.1,-2.2 18,-0.9l0.1,0c3,0.6 6.4,2 10.4,4.3l18.2,-18.2c-4.8,-2.4 -13.1,-6.2 -23,-8.2C200.5,37.6 183.6,42.2 170.4,55.4z"
|
||||
android:fillColor="#FFFFFF"/>
|
||||
<path
|
||||
android:pathData="M273.2,77.6c-7.1,4.8 -14,11.1 -17.7,14.6l80.5,80.5c6.4,-5.2 12.7,-9.7 18.7,-13.6L273.2,77.6z"
|
||||
android:fillColor="#FFFFFF"/>
|
||||
<path
|
||||
android:pathData="M55.4,329.6c24.2,24.2 49.4,26.4 81.8,7.3c7.8,-4.6 16.1,-10.6 24.6,-17.7c19.5,-16.3 41.3,-39.5 64.9,-69.2c-15.4,-19.4 -30.2,-36.2 -43.8,-49.8c-6.3,-6.3 -12.4,-12 -18.3,-17.1l-16.2,16.2c5.9,5 12.1,10.7 18.4,17c9,9 18.5,19.5 28.4,31.2l2.1,2.5l-2.1,2.5c-18.1,21.5 -35,38.6 -50.1,50.9c-9.6,7.8 -18.6,13.8 -26.7,17.7c-7,3.4 -13.4,5.3 -19,5.6c-2.7,0.2 -6.9,0.1 -12.1,-2c-5,-2.1 -10.2,-5.8 -15.7,-11.3c-2.1,-2.1 -5,-5.4 -6.8,-10.4c-1.9,-5.2 -2.2,-11.1 -0.9,-18l0,-0.1c0.6,-3 2,-6.4 4.3,-10.4l-18.2,-18.2c-2.4,4.8 -6.2,13.1 -8.2,23C37.6,299.5 42.2,316.4 55.4,329.6z"
|
||||
android:fillColor="#FFFFFF"/>
|
||||
<path
|
||||
android:pathData="M86.7,250L86.7,250c-4.1,-4.4 -12,-13.1 -17.3,-21.6c-3.2,-5.2 -5.1,-9.7 -5.6,-13.5c-1.2,-6.9 -0.9,-12.7 0.9,-17.9c1.8,-5 4.8,-8.3 6.8,-10.4c5.9,-5.9 11.3,-9.7 16.7,-11.7c5.5,-2 10,-1.8 13.3,-1.4c4.4,0.5 9.2,2 14.3,4.2l17,-17c-30.3,-16.4 -54.4,-13.3 -77.4,9.7c-13.2,13.2 -17.8,30.1 -13.7,50.3c2.8,14 9.1,24.9 10.3,26.9l65.4,65.4c6,-3.1 12.5,-7.4 19.4,-12.8L86.7,250z"
|
||||
android:fillColor="#FFFFFF"/>
|
||||
<path
|
||||
android:pathData="M92.2,244.5l80.5,-80.5c-5.2,-6.4 -9.7,-12.7 -13.6,-18.7l-81.5,81.5C82.4,233.9 88.6,240.8 92.2,244.5z"
|
||||
android:fillColor="#FFFFFF"/>
|
||||
<path
|
||||
android:pathData="M329.6,444.6c24.2,-24.2 26.4,-49.4 7.3,-81.8c-4.6,-7.8 -10.6,-16.1 -17.7,-24.6c-16.3,-19.5 -39.5,-41.3 -69.2,-64.9c-19.4,15.4 -36.2,30.2 -49.8,43.8c-6.3,6.3 -12,12.4 -17.1,18.3l16.2,16.2c5,-5.9 10.7,-12.1 17,-18.4c9,-9 19.5,-18.5 31.2,-28.4l2.5,-2.1l2.5,2.1c21.5,18.1 38.6,35 50.9,50.1c7.8,9.6 13.8,18.6 17.7,26.7c3.4,7 5.3,13.4 5.6,19c0.2,2.7 0.1,6.9 -2,12.1c-2.1,5 -5.8,10.2 -11.3,15.7c-2.1,2.1 -5.4,5 -10.4,6.8c-5.2,1.9 -11.1,2.2 -18,0.9l-0.1,0c-3,-0.6 -6.4,-2 -10.4,-4.3l-18.2,18.2c4.7,2.4 13.1,6.1 22.9,8.2C299.4,462.4 316.4,457.8 329.6,444.6z"
|
||||
android:fillColor="#FFFFFF"/>
|
||||
<path
|
||||
android:pathData="M244.5,407.8L164,327.3c-6.4,5.2 -12.7,9.7 -18.7,13.6l81.5,81.5C233.9,417.6 240.8,411.4 244.5,407.8z"
|
||||
android:fillColor="#FFFFFF"/>
|
||||
<path
|
||||
android:pathData="M170.4,444.6c13.2,13.2 30.1,17.8 50.3,13.7c14,-2.8 24.9,-9.1 26.9,-10.3l65.4,-65.4c-3.1,-6 -7.4,-12.5 -12.8,-19.4L250,413.3l0,0c-4.3,4.1 -13,12.1 -21.6,17.4c-5.2,3.2 -9.7,5.1 -13.5,5.6c-6.9,1.2 -12.7,0.9 -17.9,-0.9c-5,-1.8 -8.3,-4.8 -10.4,-6.8c-5.9,-5.9 -9.7,-11.3 -11.7,-16.7c-2,-5.5 -1.8,-10 -1.4,-13.3c0.5,-4.4 2,-9.2 4.2,-14.3l-17,-17C144.3,397.5 147.3,421.5 170.4,444.6z"
|
||||
android:fillColor="#FFFFFF"/>
|
||||
</vector>
|
|
@ -1,10 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Modify this file to customize your launch splash screen -->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@color/darkGreyPurple" />
|
||||
<item android:drawable="@android:color/white" />
|
||||
|
||||
<!-- You can insert your own image assets here -->
|
||||
<item android:drawable="@drawable/knott"
|
||||
android:gravity="center"
|
||||
/>
|
||||
<!-- <item>
|
||||
<bitmap
|
||||
android:gravity="center"
|
||||
android:src="@mipmap/launch_image" />
|
||||
</item> -->
|
||||
</layer-list>
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.airbnb.lottie.LottieAnimationView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:lottie_autoPlay="true"
|
||||
app:lottie_rawRes="@raw/cwtch_animated_logo_op"
|
||||
app:lottie_loop="true"
|
||||
app:lottie_speed="1.00"
|
||||
app:lottie_enableMergePathsForKitKatAndAbove="true" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -1,5 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/knott"/>
|
||||
</adaptive-icon>
|
After Width: | Height: | Size: 544 B |
After Width: | Height: | Size: 442 B |
After Width: | Height: | Size: 721 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.4 KiB |
|
@ -1,23 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<!-- Show a splash screen on the activity. Automatically removed when
|
||||
the Flutter engine draws its first frame -->
|
||||
Flutter draws its first frame -->
|
||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||
running.
|
||||
|
||||
|
||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
</resources>
|
||||
</resources>
|
|
@ -1,14 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<item name="android:windowSplashScreenBackground">@color/darkGreyPurple</item>
|
||||
<item name="android:windowSplashScreenAnimatedIcon">@drawable/knott</item>
|
||||
<item name="android:windowSplashScreenIconBackgroundColor">@color/darkGreyPurple</item>
|
||||
</style>
|
||||
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
|
@ -1,5 +0,0 @@
|
|||
<resources>
|
||||
<color name="darkGreyPurple">#281831</color>
|
||||
<color name="testGreen">#00ff00</color>
|
||||
<color name="ic_launcher_background">@color/darkGreyPurple</color>
|
||||
</resources>
|
|
@ -1,3 +1,18 @@
|
|||
buildscript {
|
||||
ext.kotlin_version = '1.6.21'
|
||||
repositories {
|
||||
google()
|
||||
// jCenter() no longer exists... https://blog.gradle.org/jcenter-shutdown
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:4.1.0'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
|
@ -13,6 +28,7 @@ subprojects {
|
|||
project.evaluationDependsOn(':app')
|
||||
}
|
||||
|
||||
tasks.register("clean", Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
||||
//removed due to gradle namespace conflicts that are beyond erinn's mere mortal understanding
|
||||
//task clean(type: Delete) {
|
||||
// delete rootProject.buildDir
|
||||
//}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#Mon Jun 20 10:33:21 PDT 2022
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
# third party plugin connectivity_plus should match, so when updating, also update
|
||||
# lib/third_party/connectivity_plus/connectivity_plus/android/gradle/wrapper/gradle-wrapper.properties
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
zipStorePath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
|
|
@ -1,25 +1,11 @@
|
|||
pluginManagement {
|
||||
def flutterSdkPath = {
|
||||
def properties = new Properties()
|
||||
file("local.properties").withInputStream { properties.load(it) }
|
||||
def flutterSdkPath = properties.getProperty("flutter.sdk")
|
||||
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
|
||||
return flutterSdkPath
|
||||
}()
|
||||
include ':app', ':cwtch'
|
||||
|
||||
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
|
||||
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
|
||||
def properties = new Properties()
|
||||
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
assert localPropertiesFile.exists()
|
||||
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
|
||||
|
||||
plugins {
|
||||
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
||||
id "com.android.application" version "7.4.2" apply false
|
||||
id "org.jetbrains.kotlin.android" version "1.8.21" apply false
|
||||
}
|
||||
|
||||
include ":app"
|
||||
def flutterSdkPath = properties.getProperty("flutter.sdk")
|
||||
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
|
||||
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
|
||||
|
|
Before Width: | Height: | Size: 1.4 MiB |
|
@ -1,202 +0,0 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -1,93 +0,0 @@
|
|||
Copyright 2020 The Inter Project Authors (https://github.com/rsms/inter)
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
@ -1,93 +0,0 @@
|
|||
Copyright 2021 Google Inc. All Rights Reserved.
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
Before Width: | Height: | Size: 19 KiB |
|
@ -1,107 +0,0 @@
|
|||
---
|
||||
colors:
|
||||
darkGreyPurple: 0x281831
|
||||
deepPurple: 0x422850
|
||||
mauvePurple: 0x8E64A5
|
||||
whiteishPurple: 0xE3DFE4
|
||||
lightGrey: 0x9E9E9E
|
||||
softGreen: 0xA0FFB0
|
||||
softRed: 0xFFA0B0
|
||||
whitePurple: 0xFFFDFF
|
||||
softPurple: 0xFDF3FC
|
||||
purple: 0xDFB9DE
|
||||
brightPurple: 0xD1B0E0 # not in new: portrait badge color
|
||||
darkPurple: 0x350052
|
||||
greyPurple: 0x775F84 # not in new: portrait borders
|
||||
pink: 0xE85DA1 # not in new: active button color
|
||||
hotPink: 0xD20070 # #D01972)
|
||||
softGrey: 0xB3B6B3 # not in new theme: blocked
|
||||
themes:
|
||||
name: cwtch
|
||||
dark:
|
||||
colors:
|
||||
background: darkGreyPurple
|
||||
header: darkGreyPurple
|
||||
userBubble: mauvePurple
|
||||
peerBubble: deepPurple
|
||||
font: whiteishPurple
|
||||
settings: whiteishPurple
|
||||
accent: hotPink
|
||||
theme:
|
||||
backgroundHilightElementColor: deepPurple
|
||||
backgroundMainColor: background # darkGreyPurple
|
||||
backgroundPaneColor: header # darkGreyPurple
|
||||
defaultButtonColor: accent # hotPink
|
||||
defaultButtonDisabledColor: lightGrey
|
||||
defaultButtonDisabledTextColor: darkGreyPurple
|
||||
defaultButtonTextColor: whiteishPurple
|
||||
dropShadowColor: mauvePurple
|
||||
hilightElementColor: purple
|
||||
mainTextColor: font # whiteishPurple
|
||||
messageFromMeBackgroundColor: userBubble # mauvePurple
|
||||
messageFromMeTextColor: font # whiteishPurple
|
||||
messageFromOtherBackgroundColor: peerBubble # deepPurple
|
||||
messageFromOtherTextColor: font # whiteishPurple
|
||||
portraitBackgroundColor: deepPurple
|
||||
portraitBlockedBorderColor: lightGrey
|
||||
portraitBlockedTextColor: lightGrey
|
||||
portraitContactBadgeColor: hotPink
|
||||
portraitContactBadgeTextColor: whiteishPurple
|
||||
portraitOfflineBorderColor: purple
|
||||
portraitOnlineBorderColor: whiteishPurple
|
||||
portraitProfileBadgeColor: hotPink
|
||||
portraitProfileBadgeTextColor: whiteishPurple
|
||||
scrollbarDefaultColor: purple
|
||||
sendHintTextColor: mauvePurple
|
||||
chatReactionIconColor: mauvePurple
|
||||
textfieldBackgroundColor: deepPurple
|
||||
textfieldBorderColor: deepPurple
|
||||
textfieldErrorColor: hotPink
|
||||
textfieldHintColor: mainTextColor
|
||||
toolbarIconColor: settings # whiteishPurple
|
||||
topbarColor: header # darkGreyPurple
|
||||
chatImage: Cwtch.png
|
||||
chatImageColor: peerBubble
|
||||
light:
|
||||
colors:
|
||||
background: whitePurple
|
||||
header: softPurple
|
||||
userBubble: purple
|
||||
peerBubble: softPurple
|
||||
font: 0x281831
|
||||
settings: 0x281831
|
||||
accent: hotPink
|
||||
theme:
|
||||
backgroundHilightElementColor: softPurple
|
||||
backgroundMainColor: background # whitePurple
|
||||
backgroundPaneColor: background # whitePurple
|
||||
defaultButtonColor: accent # hotPink
|
||||
defaultButtonDisabledColor: softGrey
|
||||
defaultButtonTextColor: whitePurple # ?
|
||||
dropShadowColor: purple
|
||||
hilightElementColor: purple
|
||||
mainTextColor: settings
|
||||
messageFromMeBackgroundColor: userBubble # brightPurple
|
||||
messageFromMeTextColor: font # mainTextColor
|
||||
messageFromOtherBackgroundColor: peerBubble # purple
|
||||
messageFromOtherTextColor: font # darkPurple
|
||||
portraitBackgroundColor: softPurple
|
||||
portraitBlockedBorderColor: softGrey
|
||||
portraitBlockedTextColor: softGrey
|
||||
portraitContactBadgeColor: accent
|
||||
portraitContactBadgeTextColor: whitePurple
|
||||
portraitOfflineBorderColor: greyPurple
|
||||
portraitOnlineBorderColor: font
|
||||
portraitProfileBadgeColor: accent
|
||||
portraitProfileBadgeTextColor: whitePurple
|
||||
scrollbarDefaultColor: accent
|
||||
sendHintTextColor: purple
|
||||
chatReactionIconColor: purple
|
||||
textfieldBackgroundColor: purple
|
||||
textfieldBorderColor: purple
|
||||
textfieldErrorColor: hotPink
|
||||
textfieldHintColor: font
|
||||
toolbarIconColor: background # darkPurple
|
||||
topbarColor: header # softPurple
|
||||
chatImage: Cwtch.png
|
||||
chatImageColor: 0xf1dff0
|
Before Width: | Height: | Size: 20 KiB |
|
@ -1,86 +0,0 @@
|
|||
---
|
||||
colors:
|
||||
darkDarkBlue: 0x0E1628
|
||||
darkLightBlue: 0x19243E
|
||||
white: 0xE6E9F4
|
||||
darkBlue: 0x131B2E
|
||||
lighterDarkBlue: 0x19243E
|
||||
lightBlue: 0xC0C8E5
|
||||
|
||||
themes:
|
||||
name: ghost
|
||||
dark:
|
||||
colors:
|
||||
background: 0x131B2E
|
||||
header: 0x0E1628
|
||||
userBubble: 0x25355A
|
||||
peerBubble: 0x19243E
|
||||
font: 0xE6E9F4
|
||||
settings: 0xE6E9F4
|
||||
accent: 0xD20070
|
||||
reaction: 0x96A5D4
|
||||
theme:
|
||||
backgroundHilightElementColor: darkDarkBlue
|
||||
backgroundMainColor: background
|
||||
backgroundPaneColor: header
|
||||
defaultButtonColor: accent
|
||||
dropShadowColor: darkBlue
|
||||
mainTextColor: font
|
||||
messageFromMeBackgroundColor: userBubble
|
||||
messageFromMeTextColor: font
|
||||
messageFromOtherBackgroundColor: peerBubble
|
||||
messageFromOtherTextColor: font
|
||||
portraitOfflineBorderColor: 0x96A5D4
|
||||
portraitOnlineBorderColor: font
|
||||
portraitBackgroundColor: background
|
||||
scrollbarDefaultColor: darkLightBlue
|
||||
sendHintTextColor: userBubble
|
||||
textfieldBackgroundColor: peerBubble
|
||||
textfieldBorderColor: userBubble
|
||||
textfieldHintColor: font
|
||||
toolbarIconColor: settings
|
||||
topbarColor: header
|
||||
chatReactionIconColor: reaction
|
||||
chatImage: Ghost.png
|
||||
chatImageColor: userBubble
|
||||
snackbarBackgroundColor: accent
|
||||
snackbarTextColor: 0xE6E9F4
|
||||
light:
|
||||
colors:
|
||||
background: 0xE6E9F4
|
||||
header: 0x96A5D4
|
||||
userBubble: 0x96A5D4
|
||||
peerBubble: 0xC0C8E5
|
||||
font: 0x131B2E
|
||||
settings: 0x131B2E
|
||||
accent: 0xD20070
|
||||
reaction: 0x96A5D4
|
||||
theme:
|
||||
backgroundHilightElementColor: peerBubble
|
||||
backgroundMainColor: background
|
||||
backgroundPaneColor: background
|
||||
defaultButtonColor: accent
|
||||
defaultButtonActiveColor: lighterDarkBlue
|
||||
defaultButtonDisabledColor: userBubble
|
||||
dropShadowColor: darkBlue
|
||||
mainTextColor: settings
|
||||
messageFromMeBackgroundColor: userBubble
|
||||
messageFromMeTextColor: font
|
||||
messageFromOtherBackgroundColor: peerBubble
|
||||
messageFromOtherTextColor: font
|
||||
portraitContactBadgeColor: accent
|
||||
portraitOfflineBorderColor: header
|
||||
portraitOnlineBorderColor: font
|
||||
portraitBackgroundColor: background
|
||||
scrollbarDefaultColor: accent
|
||||
sendHintTextColor: peerBubble
|
||||
textfieldBackgroundColor: peerBubble
|
||||
textfieldBorderColor: userBubble
|
||||
textfieldHintColor: font
|
||||
toolbarIconColor: 0xffffff
|
||||
topbarColor: header
|
||||
chatReactionIconColor: reaction
|
||||
chatImage: Ghost.png
|
||||
chatImageColor: peerBubble
|
||||
snackbarBackgroundColor: accent
|
||||
snackbarTextColor: background
|
Before Width: | Height: | Size: 19 KiB |
|
@ -1,53 +0,0 @@
|
|||
---
|
||||
|
||||
themes:
|
||||
name: juniper
|
||||
dark:
|
||||
colors:
|
||||
background: 0x1B1B1B
|
||||
backgroundAlt: 0x494949
|
||||
header: 0x1B1B1B
|
||||
userBubble: 0x373737
|
||||
peerBubble: 0x494949
|
||||
font: 0xFFFFFF
|
||||
settings: 0xFFFDFF
|
||||
accent: 0x9E6A56
|
||||
accentAlt: 0x9E6A56
|
||||
theme:
|
||||
backgroundMainColor: background
|
||||
backgroundPaneColor: header
|
||||
topbarColor: header
|
||||
mainTextColor: font
|
||||
defaultButtonColor: accent
|
||||
textfieldHintColor: mainTextColor
|
||||
toolbarIconColor: settings
|
||||
messageFromMeBackgroundColor: userBubble
|
||||
messageFromMeTextColor: font
|
||||
messageFromOtherBackgroundColor: peerBubble
|
||||
messageFromOtherTextColor: font
|
||||
textfieldBackgroundColor: peerBubble
|
||||
textfieldBorderColor: userBubble
|
||||
backgroundHilightElementColor: accent
|
||||
sendHintTextColor: accentAlt
|
||||
hilightElementColor: accentAlt
|
||||
defaultButtonTextColor: mainTextColor
|
||||
defaultButtonDisabledColor: peerBubble
|
||||
defaultButtonDisabledTextColor: peerBubble
|
||||
textfieldErrorColor: accent
|
||||
scrollbarDefaultColor: accent
|
||||
portraitBackgroundColor: header
|
||||
portraitOnlineBorderColor: font
|
||||
portraitOfflineBorderColor: peerBubble
|
||||
portraitBlockedBorderColor: peerBubble
|
||||
portraitBlockedTextColor: peerBubble
|
||||
portraitContactBadgeColor: accent
|
||||
portraitContactBadgeTextColor: mainTextColor
|
||||
portraitProfileBadgeColor: accent
|
||||
portraitProfileBadgeTextColor: mainTextColor
|
||||
dropShadowColor: accentAlt
|
||||
chatReactionIconColor: accentAlt
|
||||
chatImage: JuniperDark.png
|
||||
chatImageColor: userBubble
|
||||
messageSelectionColor: accent
|
||||
textfieldSelectionColor: accent
|
||||
menuBackgroundColor: accent
|
Before Width: | Height: | Size: 22 KiB |
|
@ -1,91 +0,0 @@
|
|||
---
|
||||
colors:
|
||||
lavender: 0xB194C1
|
||||
|
||||
themes:
|
||||
name: mermaid
|
||||
dark:
|
||||
colors:
|
||||
background: 0x15282A
|
||||
header: 0x15282A
|
||||
userBubble: 0x1d5754
|
||||
peerBubble: 0x253D3F
|
||||
font: 0xEDFAFC
|
||||
settings: 0xEDFAFC
|
||||
accent: 0x8E64A5
|
||||
reaction: 0x8E64A5
|
||||
theme:
|
||||
backgroundHilightElementColor: peerBubble
|
||||
backgroundMainColor: background # darkGreyPurple
|
||||
backgroundPaneColor: header # darkGreyPurple
|
||||
defaultButtonColor: accent # hotPink
|
||||
dropShadowColor: lavender
|
||||
mainTextColor: font # whiteishPurple
|
||||
messageFromMeBackgroundColor: userBubble # mauvePurple
|
||||
messageFromMeTextColor: font # whiteishPurple
|
||||
messageFromOtherBackgroundColor: peerBubble # deepPurple
|
||||
messageFromOtherTextColor: font # whiteishPurple
|
||||
portraitOfflineBorderColor: userBubble
|
||||
portraitOnlineBorderColor: font
|
||||
portraitContactBadgeColor: accent
|
||||
portraitContactBadgeTextColor: 0xffffff
|
||||
portraitProfileBadgeColor: accent
|
||||
portraitProfileBadgeTextColor: 0xffffff
|
||||
portraitBackgroundColor: background
|
||||
textfieldBackgroundColor: peerBubble
|
||||
textfieldBorderColor: userBubble
|
||||
textfieldHintColor: mainTextColor
|
||||
toolbarIconColor: settings # whiteishPurple
|
||||
topbarColor: header # darkGreyPurple
|
||||
sendHintTextColor: userBubble
|
||||
chatReactionIconColor: reaction
|
||||
chatImage: Mermaid.png
|
||||
chatImageColor: peerBubble
|
||||
snackbarBackgroundColor: accent
|
||||
snackbarTextColor: 0xEDFAFC
|
||||
messageSelectionColor: accent
|
||||
textfieldSelectionColor: accent
|
||||
menuBackgroundColor: accent
|
||||
light:
|
||||
colors:
|
||||
background: 0xEDFAFC
|
||||
header: 0x71C1BF
|
||||
userBubble: 0x71C1BF
|
||||
peerBubble: 0xD2EFF3
|
||||
font: 0x15282A
|
||||
settings: 0x15282A
|
||||
accent: 0x8E64A5
|
||||
reaction: 0x71C1BF
|
||||
theme:
|
||||
backgroundHilightElementColor: peerBubble
|
||||
backgroundMainColor: background # whitePurple
|
||||
backgroundPaneColor: background # whitePurple
|
||||
defaultButtonColor: accent # hotPink
|
||||
dropShadowColor: peerBubble
|
||||
mainTextColor: settings
|
||||
messageFromMeBackgroundColor: userBubble # brightPurple
|
||||
messageFromMeTextColor: font # mainTextColor
|
||||
messageFromOtherBackgroundColor: peerBubble # purple
|
||||
messageFromOtherTextColor: font # darkPurple
|
||||
portraitContactBadgeColor: accent
|
||||
portraitContactBadgeTextColor: 0xffffff
|
||||
portraitProfileBadgeColor: accent
|
||||
portraitProfileBadgeTextColor: 0xffffff
|
||||
portraitOfflineBorderColor: userBubble
|
||||
portraitOnlineBorderColor: font
|
||||
portraitBackgroundColor: background
|
||||
scrollbarDefaultColor: accent
|
||||
textfieldBackgroundColor: peerBubble
|
||||
textfieldBorderColor: userBubble
|
||||
textfieldHintColor: font
|
||||
toolbarIconColor: 0xffffff
|
||||
topbarColor: header # softPurple
|
||||
sendHintTextColor: userBubble
|
||||
chatReactionIconColor: reaction
|
||||
chatImage: Mermaid.png
|
||||
chatImageColor: peerBubble
|
||||
snackbarBackgroundColor: accent
|
||||
snackbarTextColor: background
|
||||
messageSelectionColor: 0xb1e3ea
|
||||
textfieldSelectionColor: 0xb1e3ea
|
||||
menuBackgroundColor: 0xb1e3ea
|
Before Width: | Height: | Size: 26 KiB |
|
@ -1,77 +0,0 @@
|
|||
---
|
||||
|
||||
themes:
|
||||
name: midnight
|
||||
dark:
|
||||
colors:
|
||||
accentGray: 0xE0E0E0
|
||||
background: 0x111111
|
||||
backgroundAlt: 0x494949
|
||||
header: 0x111111
|
||||
userBubble: 0x2D2D2D
|
||||
peerBubble: 0x1B1B1B
|
||||
font: 0xF0F1F1
|
||||
settings: 0xF0F1F1
|
||||
accent: 0xD20070
|
||||
reaction: 0xD20070
|
||||
theme:
|
||||
backgroundHilightElementColor: backgroundAlt
|
||||
backgroundMainColor: background # darkGreyPurple
|
||||
backgroundPaneColor: header # darkGreyPurple
|
||||
defaultButtonColor: accent # hotPink
|
||||
dropShadowColor: accentGray
|
||||
mainTextColor: font # whiteishPurple
|
||||
messageFromMeBackgroundColor: userBubble # mauvePurple
|
||||
messageFromMeTextColor: font # whiteishPurple
|
||||
messageFromOtherBackgroundColor: peerBubble # deepPurple
|
||||
messageFromOtherTextColor: font # whiteishPurple
|
||||
scrollbarDefaultColor: accentGray
|
||||
textfieldBackgroundColor: peerBubble
|
||||
textfieldBorderColor: userBubble
|
||||
textfieldHintColor: mainTextColor
|
||||
portraitOfflineBorderColor: 0x676767
|
||||
portraitOnlineBorderColor: font
|
||||
portraitBackgroundColor: background
|
||||
toolbarIconColor: settings # whiteishPurple
|
||||
topbarColor: header # darkGreyPurple
|
||||
sendHintTextColor: userBubble
|
||||
chatReactionIconColor: reaction
|
||||
chatImage: Midnight.png
|
||||
chatImageColor: userBubble
|
||||
snackbarBackgroundColor: accent
|
||||
snackbarTextColor: 0xF0F1F1
|
||||
light:
|
||||
colors:
|
||||
background: 0xF0F1F1 # Color( 0xFFFDFF)
|
||||
header: 0xE0E0E0
|
||||
userBubble: 0xBABDBE
|
||||
peerBubble: 0xE0E0E0
|
||||
font: 0x111111
|
||||
settings: 0x111111
|
||||
accent: 0xD20070
|
||||
reaction: 0xD20070
|
||||
theme:
|
||||
backgroundHilightElementColor: peerBubble
|
||||
backgroundMainColor: background # whitePurple
|
||||
backgroundPaneColor: background # whitePurple
|
||||
defaultButtonColor: accent # hotPink
|
||||
mainTextColor: settings
|
||||
messageFromMeBackgroundColor: userBubble # brightPurple
|
||||
messageFromMeTextColor: font # mainTextColor
|
||||
messageFromOtherBackgroundColor: peerBubble # purple
|
||||
messageFromOtherTextColor: font # darkPurple
|
||||
portraitContactBadgeColor: accent
|
||||
portraitOfflineBorderColor: userBubble
|
||||
portraitOnlineBorderColor: font
|
||||
portraitBackgroundColor: background
|
||||
scrollbarDefaultColor: accent
|
||||
textfieldBackgroundColor: userBubble
|
||||
textfieldHintColor: font
|
||||
toolbarIconColor: 0xffffff
|
||||
topbarColor: header # softPurple
|
||||
sendHintTextColor: userBubble
|
||||
chatReactionIconColor: reaction
|
||||
chatImage: Midnight.png
|
||||
chatImageColor: peerBubble
|
||||
snackbarBackgroundColor: accent
|
||||
snackbarTextColor: background
|
Before Width: | Height: | Size: 17 KiB |
|
@ -1,86 +0,0 @@
|
|||
---
|
||||
|
||||
themes:
|
||||
name: neon1
|
||||
dark:
|
||||
colors:
|
||||
background: 0x281831
|
||||
header: 0x281831
|
||||
userBubble: 0x7F00C5
|
||||
peerBubble: 0x422850
|
||||
font: 0xFBF3FF
|
||||
settings: 0x281831
|
||||
accent: 0x56DCD8
|
||||
reaction: 0xD891FF
|
||||
theme:
|
||||
backgroundMainColor: background # darkGreyPurple
|
||||
backgroundPaneColor: header # darkGreyPurple
|
||||
defaultButtonColor: accent # hotPink
|
||||
mainTextColor: 0xFBF3FF # whiteishPurple
|
||||
messageFromMeBackgroundColor: userBubble # mauvePurple
|
||||
messageFromMeTextColor: font # whiteishPurple
|
||||
messageFromOtherBackgroundColor: peerBubble # deepPurple
|
||||
messageFromOtherTextColor: font # whiteishPurple
|
||||
portraitContactBadgeColor: accent
|
||||
portraitContactBadgeTextColor: background
|
||||
portraitProfileBadgeColor: accent
|
||||
portraitProfileBadgeTextColor: background
|
||||
portraitBackgroundColor: background
|
||||
portraitOfflineBorderColor: 0x775F84
|
||||
portraitOnlineBorderColor: font
|
||||
scrollbarDefaultColor: accent
|
||||
textfieldHintColor: mainTextColor
|
||||
toolbarIconColor: settings # whiteishPurple
|
||||
topbarColor: header # darkGreyPurple
|
||||
sendHintTextColor: userBubble
|
||||
chatReactionIconColor: reaction
|
||||
defaultButtonTextColor: 0x281831
|
||||
chatImage: Neon1.png
|
||||
chatImageColor: 0x4f3060
|
||||
snackbarBackgroundColor: accent
|
||||
snackbarTextColor: background
|
||||
messageSelectionColor: 0x775F84
|
||||
textfieldSelectionColor: 0x775F84
|
||||
menuBackgroundColor: 0x775F84
|
||||
light:
|
||||
colors:
|
||||
background: 0xFBF3FF
|
||||
header: 0x56DCD8
|
||||
userBubble: 0x56DCD8
|
||||
peerBubble: 0xF5E1FF
|
||||
font: 0x281831
|
||||
settings: 0x281831
|
||||
accent: 0xD891FF
|
||||
reaction: 0xD891FF
|
||||
theme:
|
||||
backgroundMainColor: background # whitePurple
|
||||
backgroundPaneColor: background # whitePurple
|
||||
defaultButtonColor: accent # hotPink
|
||||
dropShadowColor: userBubble
|
||||
mainTextColor: settings
|
||||
messageFromMeBackgroundColor: userBubble # brightPurple
|
||||
messageFromMeTextColor: font # mainTextColor
|
||||
messageFromOtherBackgroundColor: peerBubble # purple
|
||||
messageFromOtherTextColor: font # darkPurple
|
||||
portraitOfflineBorderColor: 0xeac1ff
|
||||
portraitOnlineBorderColor: font
|
||||
portraitContactBadgeColor: accent
|
||||
portraitContactBadgeTextColor: font
|
||||
portraitProfileBadgeColor: accent
|
||||
portraitProfileBadgeTextColor: font
|
||||
scrollbarDefaultColor: accent
|
||||
textfieldBackgroundColor: peerBubble
|
||||
textfieldBorderColor: userBubble
|
||||
textfieldHintColor: font
|
||||
toolbarIconColor: settings # darkPurple
|
||||
topbarColor: header # softPurple
|
||||
sendHintTextColor: 0xeac1ff
|
||||
chatReactionIconColor: reaction
|
||||
chatImage: Neon1.png
|
||||
chatImageColor: 0xeac1ff
|
||||
defaultButtonTextColor: font
|
||||
snackbarBackgroundColor: accent
|
||||
snackbarTextColor: font
|
||||
messageSelectionColor: accent
|
||||
textfieldSelectionColor: accent
|
||||
menuBackgroundColor: accent
|
Before Width: | Height: | Size: 17 KiB |
|
@ -1,83 +0,0 @@
|
|||
---
|
||||
|
||||
themes:
|
||||
name: neon2
|
||||
dark:
|
||||
colors:
|
||||
background: 0x281831
|
||||
header: 0x281831
|
||||
userBubble: 0x7F00C5
|
||||
peerBubble: 0x422850
|
||||
font: 0xFBF3FF
|
||||
settings: 0x281831
|
||||
accent: 0x90EE02
|
||||
reaction: 0xD891FF
|
||||
theme:
|
||||
backgroundMainColor: background # darkGreyPurple
|
||||
backgroundPaneColor: header # darkGreyPurple
|
||||
defaultButtonColor: accent # hotPink
|
||||
mainTextColor: font # whiteishPurple
|
||||
messageFromMeBackgroundColor: userBubble # mauvePurple
|
||||
messageFromMeTextColor: font # whiteishPurple
|
||||
messageFromOtherBackgroundColor: peerBubble # deepPurple
|
||||
messageFromOtherTextColor: font # whiteishPurple
|
||||
portraitContactBadgeColor: accent
|
||||
portraitContactBadgeTextColor: 0x281831
|
||||
portraitProfileBadgeColor: accent
|
||||
portraitProfileBadgeTextColor: 0x281831
|
||||
scrollbarDefaultColor: accent
|
||||
textfieldHintColor: mainTextColor
|
||||
toolbarIconColor: settings # whiteishPurple
|
||||
topbarColor: header # darkGreyPurple
|
||||
sendHintTextColor: userBubble
|
||||
chatReactionIconColor: reaction
|
||||
defaultButtonTextColor: background
|
||||
chatImage: Neon2.png
|
||||
chatImageColor: 0x573569
|
||||
snackbarBackgroundColor: accent
|
||||
snackbarTextColor: background
|
||||
messageSelectionColor: 0x775F84
|
||||
textfieldSelectionColor: 0x775F84
|
||||
menuBackgroundColor: 0x775F84
|
||||
light:
|
||||
colors:
|
||||
paleGreen: 0xE7F6F6
|
||||
background: 0xFBFFF6
|
||||
header: 0x90EE02
|
||||
userBubble: 0x90EE02
|
||||
peerBubble: 0xF3FFE4
|
||||
font: 0x281831
|
||||
settings: 0x281831
|
||||
accent: 0x7F00C5
|
||||
reaction: 0x7F00C5
|
||||
theme:
|
||||
backgroundMainColor: background # whitePurple
|
||||
backgroundPaneColor: background # whitePurple
|
||||
defaultButtonColor: accent # hotPink
|
||||
dropShadowColor: userBubble
|
||||
mainTextColor: settings
|
||||
messageFromMeBackgroundColor: userBubble # brightPurple
|
||||
messageFromMeTextColor: font # mainTextColor
|
||||
messageFromOtherBackgroundColor: peerBubble # purple
|
||||
messageFromOtherTextColor: font # darkPurple
|
||||
portraitOfflineBorderColor: 0x775F84
|
||||
portraitOnlineBorderColor: font
|
||||
portraitContactBadgeColor: accent
|
||||
portraitContactBadgeTextColor: background
|
||||
portraitProfileBadgeColor: accent
|
||||
portraitProfileBadgeTextColor: background
|
||||
portraitBackgroundColor: background
|
||||
scrollbarDefaultColor: accent
|
||||
textfieldBackgroundColor: paleGreen
|
||||
textfieldBorderColor: peerBubble
|
||||
textfieldHintColor: font
|
||||
toolbarIconColor: background # darkPurple
|
||||
topbarColor: header # softPurple
|
||||
chatReactionIconColor: accent
|
||||
chatImage: Neon2.png
|
||||
chatImageColor: 0xd9ffa8
|
||||
snackbarBackgroundColor: accent
|
||||
snackbarTextColor: background
|
||||
messageSelectionColor: 0xd9ffa8
|
||||
textfieldSelectionColor: 0xd9ffa8
|
||||
menuBackgroundColor: 0xd9ffa8
|
Before Width: | Height: | Size: 19 KiB |
|
@ -1,84 +0,0 @@
|
|||
---
|
||||
|
||||
themes:
|
||||
name: pumpkin
|
||||
dark:
|
||||
colors:
|
||||
background: 0x281831
|
||||
header: 0x281831
|
||||
userBubble: 0x873C14
|
||||
peerBubble: 0x422850
|
||||
font: 0xFFFAF2
|
||||
settings: 0xFFFAF2
|
||||
accent: 0x873C14
|
||||
reaction: 0x873C14
|
||||
theme:
|
||||
backgroundMainColor: background # darkGreyPurple
|
||||
backgroundPaneColor: header # darkGreyPurple
|
||||
defaultButtonColor: accent # hotPink
|
||||
mainTextColor: font # whiteishPurple
|
||||
messageFromMeBackgroundColor: userBubble # mauvePurple
|
||||
messageFromMeTextColor: font # whiteishPurple
|
||||
messageFromOtherBackgroundColor: peerBubble # deepPurple
|
||||
messageFromOtherTextColor: font # whiteishPurple
|
||||
scrollbarDefaultColor: accent
|
||||
portraitContactBadgeColor: accent
|
||||
portraitContactBadgeTextColor: 0xFFFAF2
|
||||
portraitProfileBadgeColor: accent
|
||||
portraitProfileBadgeTextColor: 0xFFFAF2
|
||||
portraitOfflineBorderColor: 0x775F84
|
||||
portraitOnlineBorderColor: font
|
||||
textfieldHintColor: mainTextColor
|
||||
toolbarIconColor: settings # whiteishPurple
|
||||
topbarColor: header # darkGreyPurple
|
||||
sendHintTextColor: peerBubble
|
||||
chatReactionIconColor: reaction
|
||||
chatImage: Pumpkin.png
|
||||
chatImageColor: 0x573569
|
||||
snackbarBackgroundColor: accent
|
||||
snackbarTextColor: 0xFFFAF2
|
||||
messageSelectionColor: 0x775F84
|
||||
textfieldSelectionColor: 0x775F84
|
||||
menuBackgroundColor: 0x775F84
|
||||
light:
|
||||
colors:
|
||||
background: 0xFFFAF2
|
||||
header: 0xFF9800
|
||||
userBubble: 0xFF9800
|
||||
peerBubble: 0xFFF3E0
|
||||
font: 0x281831
|
||||
settings: 0x281831
|
||||
accent: 0x422850
|
||||
reaction: 0xFF9800
|
||||
theme:
|
||||
backgroundHilightElementColor: peerBubble
|
||||
backgroundMainColor: background # whitePurple
|
||||
backgroundPaneColor: background # whitePurple
|
||||
defaultButtonColor: accent # hotPink
|
||||
dropShadowColor: peerBubble
|
||||
mainTextColor: settings
|
||||
messageFromMeBackgroundColor: userBubble # brightPurple
|
||||
messageFromMeTextColor: font # mainTextColor
|
||||
messageFromOtherBackgroundColor: peerBubble # purple
|
||||
messageFromOtherTextColor: font # darkPurple
|
||||
portraitContactBadgeColor: accent
|
||||
portraitContactBadgeTextColor: 0xFFFAF2
|
||||
portraitProfileBadgeColor: accent
|
||||
portraitProfileBadgeTextColor: 0xFFFAF2
|
||||
portraitOfflineBorderColor: 0x775F84
|
||||
portraitOnlineBorderColor: font
|
||||
scrollbarDefaultColor: accent
|
||||
textfieldBackgroundColor: background
|
||||
textfieldBorderColor: userBubble
|
||||
textfieldHintColor: mainTextColor
|
||||
toolbarIconColor: background # darkPurple
|
||||
topbarColor: header # softPurple
|
||||
sendHintTextColor: 0xffd494
|
||||
chatReactionIconColor: reaction
|
||||
chatImage: Pumpkin.png
|
||||
chatImageColor: 0xFFDCA8
|
||||
snackbarBackgroundColor: accent
|
||||
snackbarTextColor: background
|
||||
messageSelectionColor: 0xFFDCA8
|
||||
textfieldSelectionColor: 0xFFDCA8
|
||||
menuBackgroundColor: 0xFFDCA8
|
Before Width: | Height: | Size: 20 KiB |
|
@ -1,85 +0,0 @@
|
|||
---
|
||||
|
||||
themes:
|
||||
name: vampire
|
||||
dark:
|
||||
colors:
|
||||
background: 0x27141B
|
||||
header: 0x27141B
|
||||
userBubble: 0x422850
|
||||
peerBubble: 0x502033
|
||||
font: 0xFBF4F7
|
||||
settings: 0xFBF4F7
|
||||
accent: 0x502033
|
||||
reaction: 0xC86B89
|
||||
theme:
|
||||
backgroundMainColor: background # darkGreyPurple
|
||||
backgroundPaneColor: header # darkGreyPurple
|
||||
defaultButtonColor: accent # hotPink
|
||||
mainTextColor: font # whiteishPurple
|
||||
messageFromMeBackgroundColor: userBubble # mauvePurple
|
||||
messageFromMeTextColor: font # whiteishPurple
|
||||
messageFromOtherBackgroundColor: peerBubble # deepPurple
|
||||
messageFromOtherTextColor: font # whiteishPurple
|
||||
portraitContactBadgeColor: 0x863655
|
||||
portraitContactBadgeTextColor: 0xFBF4F7
|
||||
portraitProfileBadgeColor: 0x863655
|
||||
portraitProfileBadgeTextColor: 0xFBF4F7
|
||||
portraitBackgroundColor: peerBubble
|
||||
portraitOfflineBorderColor: 0x863655
|
||||
portraitOnlineBorderColor: font
|
||||
scrollbarDefaultColor: accent
|
||||
textfieldHintColor: mainTextColor
|
||||
toolbarIconColor: settings # whiteishPurple
|
||||
topbarColor: header # darkGreyPurple
|
||||
sendHintTextColor: peerBubble
|
||||
chatReactionIconColor: reaction
|
||||
chatImage: Vampire.png
|
||||
chatImageColor: peerBubble
|
||||
snackbarBackgroundColor: accent
|
||||
snackbarTextColor: 0xFBF4F7
|
||||
messageSelectionColor: 0x863655
|
||||
textfieldSelectionColor: 0x863655
|
||||
menuBackgroundColor: 0x863655
|
||||
light:
|
||||
colors:
|
||||
background: 0xFBF4F7
|
||||
header: 0xC86B89
|
||||
userBubble: 0xDA94A9
|
||||
peerBubble: 0xF7EAF0
|
||||
font: 0x27141B
|
||||
settings: 0xFBF4F7
|
||||
accent: 0x502033
|
||||
reaction: 0xDA94A9
|
||||
theme:
|
||||
backgroundMainColor: background # whitePurple
|
||||
backgroundPaneColor: background # whitePurple
|
||||
defaultButtonColor: accent # hotPink
|
||||
dropShadowColor: userBubble
|
||||
mainTextColor: font
|
||||
messageFromMeBackgroundColor: userBubble # brightPurple
|
||||
messageFromMeTextColor: font # mainTextColor
|
||||
messageFromOtherBackgroundColor: peerBubble # purple
|
||||
messageFromOtherTextColor: font # darkPurple
|
||||
portraitContactBadgeColor: accent
|
||||
portraitContactBadgeTextColor: 0xFBF4F7
|
||||
portraitProfileBadgeColor: accent
|
||||
portraitProfileBadgeTextColor: 0xFBF4F7
|
||||
portraitOfflineBorderColor: 0x775F84
|
||||
portraitOnlineBorderColor: font
|
||||
portraitBackgroundColor: background
|
||||
scrollbarDefaultColor: accent
|
||||
textfieldBackgroundColor: peerBubble
|
||||
textfieldBorderColor: userBubble
|
||||
textfieldHintColor: font
|
||||
toolbarIconColor: settings # darkPurple
|
||||
topbarColor: header # softPurple
|
||||
sendHintTextColor: userBubble
|
||||
chatReactionIconColor: reaction
|
||||
chatImage: Vampire.png
|
||||
chatImageColor: 0xE9BFCD
|
||||
snackbarBackgroundColor: accent
|
||||
snackbarTextColor: background
|
||||
messageSelectionColor: header
|
||||
textfieldSelectionColor: header
|
||||
menuBackgroundColor: header
|
Before Width: | Height: | Size: 26 KiB |
|
@ -1,86 +0,0 @@
|
|||
---
|
||||
|
||||
themes:
|
||||
name: witch
|
||||
dark:
|
||||
colors:
|
||||
background: 0x111b11
|
||||
header: 0x0E1E0E
|
||||
userBubble: 0x3B5132
|
||||
peerBubble: 0x152716
|
||||
font: 0xF1F3EC
|
||||
settings: 0xE3ECD3
|
||||
accent: 0x8E64A5
|
||||
reaction: 0x97AF6E
|
||||
theme:
|
||||
backgroundHilightElementColor: peerBubble
|
||||
backgroundMainColor: background # darkGreyPurple
|
||||
backgroundPaneColor: header # darkGreyPurple
|
||||
defaultButtonColor: accent # hotPink
|
||||
mainTextColor: font # whiteishPurple
|
||||
messageFromMeBackgroundColor: userBubble # mauvePurple
|
||||
messageFromMeTextColor: font # whiteishPurple
|
||||
messageFromOtherBackgroundColor: peerBubble # deepPurple
|
||||
messageFromOtherTextColor: font # whiteishPurple
|
||||
portraitContactBadgeColor: accent
|
||||
portraitContactBadgeTextColor: 0xF1F3EC
|
||||
portraitProfileBadgeColor: accent
|
||||
portraitProfileBadgeTextColor: 0xF1F3EC
|
||||
portraitOfflineBorderColor: 0x355934
|
||||
portraitOnlineBorderColor: font
|
||||
portraitBackgroundColor: peerBubble
|
||||
scrollbarDefaultColor: accent
|
||||
textfieldBackgroundColor: peerBubble
|
||||
textfieldBorderColor: userBubble
|
||||
textfieldHintColor: mainTextColor
|
||||
toolbarIconColor: settings # whiteishPurple
|
||||
topbarColor: header # darkGreyPurple
|
||||
chatReactionIconColor: reaction
|
||||
chatImage: Witch.png
|
||||
chatImageColor: 0x1E321D
|
||||
snackbarBackgroundColor: accent
|
||||
snackbarTextColor: 0xF1F3EC
|
||||
messageSelectionColor: accent
|
||||
textfieldSelectionColor: accent
|
||||
menuBackgroundColor: accent
|
||||
light:
|
||||
colors:
|
||||
background: 0xF1F3EC
|
||||
header: 0x97af6e
|
||||
userBubble: 0x97AF6E
|
||||
peerBubble: 0xE3ECD3
|
||||
font: 0x111b11
|
||||
settings: 0x0E1E0E
|
||||
accent: 0x8E64A5
|
||||
reaction: 0x97AF6E
|
||||
theme:
|
||||
backgroundHilightElementColor: peerBubble
|
||||
backgroundMainColor: background # whitePurple
|
||||
backgroundPaneColor: background # whitePurple
|
||||
defaultButtonColor: accent # hotPink
|
||||
mainTextColor: settings
|
||||
messageFromMeBackgroundColor: userBubble # brightPurple
|
||||
messageFromMeTextColor: font # mainTextColor
|
||||
messageFromOtherBackgroundColor: peerBubble # purple
|
||||
messageFromOtherTextColor: font # darkPurple
|
||||
portraitContactBadgeColor: accent
|
||||
portraitContactBadgeTextColor: 0xF1F3EC
|
||||
portraitProfileBadgeColor: accent
|
||||
portraitProfileBadgeTextColor: 0xF1F3EC
|
||||
portraitOfflineBorderColor: userBubble
|
||||
portraitOnlineBorderColor: font
|
||||
portraitBackgroundColor: background
|
||||
scrollbarDefaultColor: accent
|
||||
textfieldBackgroundColor: background
|
||||
textfieldBorderColor: userBubble
|
||||
textfieldHintColor: font
|
||||
toolbarIconColor: settings # darkPurple
|
||||
topbarColor: header # softPurple
|
||||
chatReactionIconColor: reaction
|
||||
chatImage: Witch.png
|
||||
chatImageColor: 0xD0DDBA
|
||||
snackbarBackgroundColor: accent
|
||||
snackbarTextColor: background
|
||||
messageSelectionColor: accent
|
||||
textfieldSelectionColor: accent
|
||||
menuBackgroundColor: accent
|
241
elf_x86_64.x
|
@ -1,241 +0,0 @@
|
|||
/* Slightly Modified Default linker script, for normal executables */
|
||||
/* The only difference is that this version suppresses the .comment section. See DISCARD section`
|
||||
/* Copyright (C) 2014-2022 Free Software Foundation, Inc.
|
||||
Copying and distribution of this script, with or without modification,
|
||||
are permitted in any medium without royalty provided the copyright
|
||||
notice and this notice are preserved. */
|
||||
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64",
|
||||
"elf64-x86-64")
|
||||
OUTPUT_ARCH(i386:x86-64)
|
||||
ENTRY(_start)
|
||||
SEARCH_DIR("=/usr/local/lib/x86_64-linux-gnu"); SEARCH_DIR("=/lib/x86_64-linux-gnu"); SEARCH_DIR("=/usr/lib/x86_64-linux-gnu"); SEARCH_DIR("=/usr/lib/x86_64-linux-gnu64"); SEARCH_DIR("=/usr/local/lib64"); SEARCH_DIR("=/lib64"); SEARCH_DIR("=/usr/lib64"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib"); SEARCH_DIR("=/usr/x86_64-linux-gnu/lib64"); SEARCH_DIR("=/usr/x86_64-linux-gnu/lib");
|
||||
SECTIONS
|
||||
{
|
||||
/* Read-only sections, merged into text segment: */
|
||||
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
|
||||
.interp : { *(.interp) }
|
||||
.note.gnu.build-id : { *(.note.gnu.build-id) }
|
||||
.hash : { *(.hash) }
|
||||
.gnu.hash : { *(.gnu.hash) }
|
||||
.dynsym : { *(.dynsym) }
|
||||
.dynstr : { *(.dynstr) }
|
||||
.gnu.version : { *(.gnu.version) }
|
||||
.gnu.version_d : { *(.gnu.version_d) }
|
||||
.gnu.version_r : { *(.gnu.version_r) }
|
||||
.rela.init : { *(.rela.init) }
|
||||
.rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
|
||||
.rela.fini : { *(.rela.fini) }
|
||||
.rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
|
||||
.rela.data.rel.ro : { *(.rela.data.rel.ro .rela.data.rel.ro.* .rela.gnu.linkonce.d.rel.ro.*) }
|
||||
.rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
|
||||
.rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
|
||||
.rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
|
||||
.rela.ctors : { *(.rela.ctors) }
|
||||
.rela.dtors : { *(.rela.dtors) }
|
||||
.rela.got : { *(.rela.got) }
|
||||
.rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
|
||||
.rela.ldata : { *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*) }
|
||||
.rela.lbss : { *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*) }
|
||||
.rela.lrodata : { *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*) }
|
||||
.rela.ifunc : { *(.rela.ifunc) }
|
||||
.rela.plt :
|
||||
{
|
||||
*(.rela.plt)
|
||||
PROVIDE_HIDDEN (__rela_iplt_start = .);
|
||||
*(.rela.iplt)
|
||||
PROVIDE_HIDDEN (__rela_iplt_end = .);
|
||||
}
|
||||
.relr.dyn : { *(.relr.dyn) }
|
||||
.init :
|
||||
{
|
||||
KEEP (*(SORT_NONE(.init)))
|
||||
}
|
||||
.plt : { *(.plt) *(.iplt) }
|
||||
.plt.got : { *(.plt.got) }
|
||||
.plt.sec : { *(.plt.sec) }
|
||||
.text :
|
||||
{
|
||||
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
|
||||
*(.text.exit .text.exit.*)
|
||||
*(.text.startup .text.startup.*)
|
||||
*(.text.hot .text.hot.*)
|
||||
*(SORT(.text.sorted.*))
|
||||
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||
/* .gnu.warning sections are handled specially by elf.em. */
|
||||
*(.gnu.warning)
|
||||
}
|
||||
.fini :
|
||||
{
|
||||
KEEP (*(SORT_NONE(.fini)))
|
||||
}
|
||||
PROVIDE (__etext = .);
|
||||
PROVIDE (_etext = .);
|
||||
PROVIDE (etext = .);
|
||||
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
|
||||
.rodata1 : { *(.rodata1) }
|
||||
.eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }
|
||||
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) }
|
||||
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
|
||||
.gnu_extab : ONLY_IF_RO { *(.gnu_extab*) }
|
||||
/* These sections are generated by the Sun/Oracle C++ compiler. */
|
||||
.exception_ranges : ONLY_IF_RO { *(.exception_ranges*) }
|
||||
/* Adjust the address for the data segment. We want to adjust up to
|
||||
the same address within the page on the next page up. */
|
||||
. = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
|
||||
/* Exception handling */
|
||||
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) }
|
||||
.gnu_extab : ONLY_IF_RW { *(.gnu_extab) }
|
||||
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
|
||||
.exception_ranges : ONLY_IF_RW { *(.exception_ranges*) }
|
||||
/* Thread Local Storage sections */
|
||||
.tdata :
|
||||
{
|
||||
PROVIDE_HIDDEN (__tdata_start = .);
|
||||
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||
}
|
||||
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
|
||||
.preinit_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
}
|
||||
.init_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
}
|
||||
.fini_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
}
|
||||
.ctors :
|
||||
{
|
||||
/* gcc uses crtbegin.o to find the start of
|
||||
the constructors, so we make sure it is
|
||||
first. Because this is a wildcard, it
|
||||
doesn't matter if the user does not
|
||||
actually link against crtbegin.o; the
|
||||
linker won't look for a file to match a
|
||||
wildcard. The wildcard also means that it
|
||||
doesn't matter which directory crtbegin.o
|
||||
is in. */
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
KEEP (*crtbegin?.o(.ctors))
|
||||
/* We don't want to include the .ctor section from
|
||||
the crtend.o file until after the sorted ctors.
|
||||
The .ctor section from the crtend file contains the
|
||||
end of ctors marker and it must be last */
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
}
|
||||
.dtors :
|
||||
{
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*crtbegin?.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
}
|
||||
.jcr : { KEEP (*(.jcr)) }
|
||||
.data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
|
||||
.dynamic : { *(.dynamic) }
|
||||
.got : { *(.got) *(.igot) }
|
||||
. = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 24 ? 24 : 0, .);
|
||||
.got.plt : { *(.got.plt) *(.igot.plt) }
|
||||
.data :
|
||||
{
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
SORT(CONSTRUCTORS)
|
||||
}
|
||||
.data1 : { *(.data1) }
|
||||
_edata = .; PROVIDE (edata = .);
|
||||
. = .;
|
||||
__bss_start = .;
|
||||
.bss :
|
||||
{
|
||||
*(.dynbss)
|
||||
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
/* Align here to ensure that the .bss section occupies space up to
|
||||
_end. Align after .bss to ensure correct alignment even if the
|
||||
.bss section disappears because there are no input sections.
|
||||
FIXME: Why do we need it? When there is no .bss section, we do not
|
||||
pad the .data section. */
|
||||
. = ALIGN(. != 0 ? 64 / 8 : 1);
|
||||
}
|
||||
.lbss :
|
||||
{
|
||||
*(.dynlbss)
|
||||
*(.lbss .lbss.* .gnu.linkonce.lb.*)
|
||||
*(LARGE_COMMON)
|
||||
}
|
||||
. = ALIGN(64 / 8);
|
||||
. = SEGMENT_START("ldata-segment", .);
|
||||
.lrodata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
|
||||
{
|
||||
*(.lrodata .lrodata.* .gnu.linkonce.lr.*)
|
||||
}
|
||||
.ldata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
|
||||
{
|
||||
*(.ldata .ldata.* .gnu.linkonce.l.*)
|
||||
. = ALIGN(. != 0 ? 64 / 8 : 1);
|
||||
}
|
||||
. = ALIGN(64 / 8);
|
||||
_end = .; PROVIDE (end = .);
|
||||
. = DATA_SEGMENT_END (.);
|
||||
/* Stabs debugging sections. */
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
|
||||
.gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
|
||||
/* DWARF debug sections.
|
||||
Symbols in the DWARF debugging sections are relative to the beginning
|
||||
of the section so we begin them at 0. */
|
||||
/* DWARF 1. */
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
/* GNU DWARF 1 extensions. */
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
/* DWARF 1.1 and DWARF 2. */
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
/* DWARF 2. */
|
||||
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
/* SGI/MIPS DWARF 2 extensions. */
|
||||
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||
.debug_typenames 0 : { *(.debug_typenames) }
|
||||
.debug_varnames 0 : { *(.debug_varnames) }
|
||||
/* DWARF 3. */
|
||||
.debug_pubtypes 0 : { *(.debug_pubtypes) }
|
||||
.debug_ranges 0 : { *(.debug_ranges) }
|
||||
/* DWARF 5. */
|
||||
.debug_addr 0 : { *(.debug_addr) }
|
||||
.debug_line_str 0 : { *(.debug_line_str) }
|
||||
.debug_loclists 0 : { *(.debug_loclists) }
|
||||
.debug_macro 0 : { *(.debug_macro) }
|
||||
.debug_names 0 : { *(.debug_names) }
|
||||
.debug_rnglists 0 : { *(.debug_rnglists) }
|
||||
.debug_str_offsets 0 : { *(.debug_str_offsets) }
|
||||
.debug_sup 0 : { *(.debug_sup) }
|
||||
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
|
||||
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) *(.comment) }
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
#!/bin/sh
|
||||
|
||||
VERSION=`cat LIBCWTCH-GO.version`
|
||||
VERSION=`cat LIBCWTCH-GO-MACOS.version`
|
||||
echo $VERSION
|
||||
|
||||
curl --fail https://build.openprivacy.ca/files/libCwtch-autobindings-$VERSION/macos/libCwtch.x64.dylib --output libCwtch.x64.dylib
|
||||
curl --fail https://build.openprivacy.ca/files/libCwtch-autobindings-$VERSION/macos/libCwtch.arm64.dylib --output libCwtch.arm64.dylib
|
||||
curl --fail https://build.openprivacy.ca/files/libCwtch-go-macos-$VERSION/libCwtch.x64.dylib --output libCwtch.x64.dylib
|
||||
curl --fail https://build.openprivacy.ca/files/libCwtch-go-macos-$VERSION/libCwtch.arm64.dylib --output libCwtch.arm64.dylib
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ $Env:VERSION = type LIBCWTCH-GO.version
|
|||
echo $Env:VERSION
|
||||
|
||||
# This should automatically fail on error...
|
||||
Invoke-WebRequest -Uri https://build.openprivacy.ca/files/libCwtch-autobindings-$Env:VERSION/windows/libCwtch.dll -OutFile windows/libCwtch.dll
|
||||
Invoke-WebRequest -Uri https://build.openprivacy.ca/files/libCwtch-go-$Env:VERSION/libCwtch.dll -OutFile windows/libCwtch.dll
|
||||
|
||||
#Invoke-WebRequest -Uri https://build.openprivacy.ca/files/libCwtch-go-$Env:VERSION/cwtch.aar -OutFile android/cwtch/cwtch.aar
|
||||
#Invoke-WebRequest -Uri https://build.openprivacy.ca/files/libCwtch-go-$Env:VERSION/libCwtch.so -Outfile linux/libCwtch.so
|
||||
|
|
|
@ -3,6 +3,5 @@
|
|||
VERSION=`cat LIBCWTCH-GO.version`
|
||||
echo $VERSION
|
||||
|
||||
curl --fail https://build.openprivacy.ca/files/libCwtch-autobindings-$VERSION/android/cwtch.aar --output android/app/cwtch/cwtch.aar
|
||||
# FIXME...at some point we need to support different linux architectures...for now rely on existing expectations and rename x64 lib
|
||||
curl --fail https://build.openprivacy.ca/files/libCwtch-autobindings-$VERSION/linux/libCwtch.x64.so --output linux/libCwtch.so
|
||||
curl --fail https://build.openprivacy.ca/files/libCwtch-go-$VERSION/cwtch.aar --output android/cwtch/cwtch.aar
|
||||
curl --fail https://build.openprivacy.ca/files/libCwtch-go-$VERSION/libCwtch.so --output linux/libCwtch.so
|
|
@ -1,7 +1,7 @@
|
|||
#!/bin/sh
|
||||
|
||||
cd macos
|
||||
curl https://git.openprivacy.ca/openprivacy/buildfiles/raw/branch/master/tor/tor-0.4.8.9-macos.tar.gz --output tor.tar.gz
|
||||
curl https://git.openprivacy.ca/openprivacy/buildfiles/raw/branch/master/tor/tor-macos-0.4.7.8.tar.gz --output tor.tar.gz
|
||||
tar -xzf tor.tar.gz
|
||||
chmod a+x Tor/tor.real
|
||||
cd ..
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
Invoke-WebRequest -Uri https://git.openprivacy.ca/openprivacy/buildfiles/raw/branch/master/tor/tor-0.4.8.9-win64.zip -OutFile tor.zip
|
||||
Invoke-WebRequest -Uri https://git.openprivacy.ca/openprivacy/buildfiles/raw/branch/master/tor/tor-win64-0.4.7.8.zip -OutFile tor.zip
|
||||
|
||||
if ((Get-FileHash tor.zip -Algorithm sha512).Hash -ne 'a1c90d9a2f82df5f3d973e260bbfec76e413417cfa276fb70d1668214e2e607cf65be86a25e30c6f7814261dc154a02568459945f31389ae6a22e03d6d0d3c4c' ) { Write-Error 'tor.zip sha512sum mismatch' }
|
||||
if ((Get-FileHash tor.zip -Algorithm sha512).Hash -ne '5b8f900a37f6e90d7a945b3903d769383c7478042cb43b2105d2374186e1a536f1a4758a2823d1d5be71d53a81dcfd8243293e04f82812d355983df322823cf4' ) { Write-Error 'tor.zip sha512sum mismatch' }
|
||||
|
||||
Expand-Archive -Path tor.zip -DestinationPath Tor
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
#!/bin/sh
|
||||
|
||||
cd linux
|
||||
wget https://git.openprivacy.ca/openprivacy/buildfiles/raw/branch/master/tor/tor-0.4.8.9-linux-x86_64.tar.gz -O tor.tar.gz
|
||||
wget https://git.openprivacy.ca/openprivacy/buildfiles/raw/branch/master/tor/tor-0.4.7.8-linux-x86_64.tar.gz -O tor.tar.gz
|
||||
tar -xzf tor.tar.gz
|
||||
cd ..
|
||||
|
||||
mkdir -p android/app/src/main/jniLibs/arm64-v8a
|
||||
wget https://git.openprivacy.ca/openprivacy/buildfiles/raw/branch/master/tor/tor-0.4.8.9-android-arm64 -O android/app/src/main/jniLibs/arm64-v8a/libtor.so
|
||||
wget https://git.openprivacy.ca/openprivacy/buildfiles/raw/branch/master/tor/tor-0.4.7.10-arm64 -O android/app/src/main/jniLibs/arm64-v8a/libtor.so
|
||||
chmod a+x android/app/src/main/jniLibs/arm64-v8a/libtor.so
|
||||
|
||||
mkdir -p android/app/src/main/jniLibs/armeabi-v7a
|
||||
wget https://git.openprivacy.ca/openprivacy/buildfiles/raw/branch/master/tor/tor-0.4.8.9-android-arm7 -O android/app/src/main/jniLibs/armeabi-v7a/libtor.so
|
||||
wget https://git.openprivacy.ca/openprivacy/buildfiles/raw/branch/master/tor/tor-0.4.7.10-arm7 -O android/app/src/main/jniLibs/armeabi-v7a/libtor.so
|
||||
chmod a+x android/app/src/main/jniLibs/armeabi-v7a/libtor.so
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# A basic script to redirect https://build.openprivacy.ca/cwtch-nightly.html to the latest nightly.
|
||||
# In the future we may want to make this page nicer...
|
||||
echo "<html><head><title>Cwtch Nightly</title><meta http-equiv=\"refresh\" content=\"0;URL='https://build.openprivacy.ca/files/$1'\" /> s</head></html>" > cwtch-nightly.html
|
|
@ -1,14 +1,12 @@
|
|||
@env:clean
|
||||
Feature: Splash screen displays and then closes
|
||||
Scenario: splash screen appears
|
||||
Then I expect the widget 'SplashView' to be present within 10 seconds
|
||||
Then I expect the widget 'ProfileManagerView' to be present within 10 seconds
|
||||
# first-run of cwtch creates expected files and folders
|
||||
|
||||
Then I expect the folder 'integration_test/env/temp' to exist
|
||||
And I expect the folder 'integration_test/env/temp/dev' to exist
|
||||
And I expect the file 'integration_test/env/temp/dev/SALT' to exist
|
||||
Then I wait for the file 'integration_test/env/temp/dev/ui.globals' to exist
|
||||
And I expect the file 'integration_test/env/temp/dev/ui.globals' to exist
|
||||
And I expect the folder 'integration_test/env/temp/dev/tor' to exist
|
||||
And I expect the file 'integration_test/env/temp/dev/tor/torrc' to exist
|
||||
And I wait for 5 seconds
|
||||
And I expect the file 'integration_test/env/temp/dev/tor/torrc' to exist
|
|
@ -5,23 +5,15 @@ Feature: Settings pane opens and can save settings persistently
|
|||
And I tap the 'OpenSettingsView' button
|
||||
And I wait until the text 'Cwtch Settings' is present
|
||||
And I take a screenshot
|
||||
And I wait for 5 seconds
|
||||
|
||||
Scenario: Change every setting (except Language)
|
||||
Given I wait until the widget with type 'ProfileMgrView' is present
|
||||
Given I tap the 'OpenSettingsView' button
|
||||
And I wait until the text 'Use Light Themes' is present
|
||||
When I tap the widget that contains the text "Use Light Themes"
|
||||
And I tap the widget that contains the text "Block Unknown Contacts"
|
||||
And I tap the widget that contains the text "Streamer/Presentation Mode"
|
||||
And I expect the switch that contains the text "Streamer/Presentation Mode" to be checked
|
||||
Then I expect the switch that contains the text "Use Light Themes" to be checked
|
||||
When I tap the 'OpenSettingsBehaviour' button
|
||||
And I wait until the text 'Notification Policy' is present
|
||||
When I tap the widget that contains the text "Block Unknown Contacts"
|
||||
And I expect the switch that contains the text "Block Unknown Contacts" to be checked
|
||||
When I tap the 'OpenSettingsExperiments' button
|
||||
And I wait until the text 'Enable Experiments' is present
|
||||
When I tap the widget that contains the text "Enable Experiments"
|
||||
And I tap the widget that contains the text "Enable Experiments"
|
||||
Then I wait until the text 'Enable Group Chat' is present
|
||||
And I tap the widget that contains the text "Enable Group Chat"
|
||||
And I tap the widget that contains the text "Hosting Servers"
|
||||
|
@ -31,11 +23,12 @@ Feature: Settings pane opens and can save settings persistently
|
|||
And I wait until the text 'Download Folder' is present
|
||||
And I fill the "DownloadFolderPicker" field with "/this/is/a/test"
|
||||
And I tap the widget that contains the text "Enable Clickable Links"
|
||||
Then I expect the switch that contains the text "Use Light Themes" to be checked
|
||||
And I expect the switch that contains the text "Block Unknown Contacts" to be checked
|
||||
And I expect the switch that contains the text "Streamer/Presentation Mode" to be checked
|
||||
And I expect the switch that contains the text "Enable Experiments" to be checked
|
||||
And I expect the switch that contains the text "Enable Group Chat" to be checked
|
||||
# Not every version of Cwtch Supports Hosting Servers..
|
||||
# Leaving this undeleted for future documentation / interest
|
||||
# And I expect the switch that contains the text "Hosting Servers" to be checked
|
||||
And I expect the switch that contains the text "Hosting Servers" to be checked
|
||||
And I expect the switch that contains the text "File Sharing" to be checked
|
||||
And I expect the switch that contains the text "Image Previews and Profile Pictures" to be checked
|
||||
And I expect the "DownloadFolderPicker" to be "/this/is/a/test"
|
||||
|
@ -46,17 +39,11 @@ Feature: Settings pane opens and can save settings persistently
|
|||
Given I tap the 'OpenSettingsView' button
|
||||
And I wait until the text 'Use Light Themes' is present
|
||||
Then I expect the switch that contains the text "Use Light Themes" to be checked
|
||||
And I expect the switch that contains the text "Block Unknown Contacts" to be checked
|
||||
And I expect the switch that contains the text "Streamer/Presentation Mode" to be checked
|
||||
When I tap the 'OpenSettingsBehaviour' button
|
||||
And I wait until the text 'Notification Policy' is present
|
||||
And I expect the switch that contains the text "Block Unknown Contacts" to be checked
|
||||
And I expect the switch that contains the text "Block Unknown Contacts" to be checked
|
||||
When I tap the 'OpenSettingsExperiments' button
|
||||
And I wait until the text 'Enable Experiments' is present
|
||||
And I wait until the text 'Enable Experiments' is present
|
||||
And I expect the switch that contains the text "Enable Experiments" to be checked
|
||||
And I expect the switch that contains the text "Enable Group Chat" to be checked
|
||||
# And I expect the switch that contains the text "Hosting Servers" to be checked
|
||||
And I expect the switch that contains the text "Hosting Servers" to be checked
|
||||
And I expect the switch that contains the text "File Sharing" to be checked
|
||||
And I expect the switch that contains the text "Image Previews and Profile Pictures" to be checked
|
||||
And I expect the "DownloadFolderPicker" to be "/this/is/a/test"
|
||||
|
|
|
@ -2,6 +2,7 @@ Feature: Tor initializes correctly
|
|||
Scenario: Check the Tor version
|
||||
Given I wait until the widget with type 'ProfileMgrView' is present
|
||||
And I tap the icon with type "TorIcon"
|
||||
Then I expect the Tor version to be present
|
||||
And I expect the string 'Online' to be present within 120 seconds
|
||||
|
||||
Scenario: Reset Tor
|
|
@ -1,9 +1,8 @@
|
|||
#Feature: Shutdown Cwtch button works correctly
|
||||
# Scenario: Clicking 'Shutdown Cwtch' shuts down Cwtch
|
||||
# Given I wait until the widget with type 'ProfileMgrView' is present
|
||||
# And I tap the button with tooltip 'Shutdown Cwtch'
|
||||
# Then I expect the text 'Shutdown Cwtch?' to be present
|
||||
# And I wait for 5 seconds
|
||||
Feature: Shutdown Cwtch button works correctly
|
||||
Scenario: Clicking 'Shutdown Cwtch' shuts down Cwtch
|
||||
Given I wait until the widget with type 'ProfileMgrView' is present
|
||||
And I tap the button with tooltip 'Shutdown Cwtch'
|
||||
Then I expect the text 'Shutdown Cwtch?' to be present
|
||||
#this also kills the testing framework sadly. will have to find a workaround
|
||||
#And I tap the button that contains the text 'Shutdown Cwtch'
|
||||
#Then I wait until the widget with type 'ProfileMgrView' is absent
|
||||
|
|
|
@ -3,8 +3,6 @@ Feature: Block unknown contacts setting
|
|||
Scenario: Carol adds Alice but Alice doesn't see it because Block Unknowns is enabled
|
||||
Given I wait until the widget with type 'ProfileMgrView' is present
|
||||
Given I tap the 'OpenSettingsView' button
|
||||
And I wait until the text "Behaviour" is present
|
||||
When I tap the 'OpenSettingsBehaviour button
|
||||
And I wait until the text "Block Unknown Contacts" is present
|
||||
When I tap the widget that contains the text "Block Unknown Contacts"
|
||||
Then I expect the switch that contains the text "Block Unknown Contacts" to be checked
|
||||
|
|
|
@ -2,9 +2,8 @@
|
|||
Feature: Basic Profile Management
|
||||
Scenario: Error on Creating a Profile without a Display Name
|
||||
Given I wait until the widget with type 'ProfileMgrView' is present
|
||||
And I tap a button with tooltip "Add new profile"
|
||||
And I tap the "addNewProfileActual" button
|
||||
And I wait until the text 'Display Name' is present
|
||||
And I tap the button with tooltip "Add new profile"
|
||||
Then I expect the text 'Display Name' to be present
|
||||
And I expect the text 'New Password' to be present
|
||||
And I expect the text 'Please enter a display name' to be absent
|
||||
Then I tap the "button" widget with label "Add new profile"
|
||||
|
@ -13,13 +12,12 @@ Feature: Basic Profile Management
|
|||
|
||||
Scenario: Create Unencrypted Profile
|
||||
Given I wait until the widget with type 'ProfileMgrView' is present
|
||||
And I tap a button with tooltip "Add new profile"
|
||||
And I tap the "addNewProfileActual" button
|
||||
And I wait until the text 'Display Name' is present
|
||||
And I tap the button with tooltip "Add new profile"
|
||||
Then I expect the text 'Display Name' to be present
|
||||
And I expect the text 'New Password' to be present
|
||||
And I take a screenshot
|
||||
Then I tap the "passwordCheckBox" widget
|
||||
And I expect the text 'New Password' to be absent within 2 seconds
|
||||
And I expect the text 'New Password' to be absent
|
||||
And I take a screenshot
|
||||
Then I fill the "displayNameFormElement" field with "Alice (Unencrypted)"
|
||||
Then I tap the "button" widget with label "Add new profile"
|
||||
|
@ -32,15 +30,11 @@ Feature: Basic Profile Management
|
|||
Scenario: Load Unencrypted Profile
|
||||
Given I wait until the widget with type 'ProfileMgrView' is present
|
||||
Then I expect a "ProfileRow" widget with text "Alice (Unencrypted)"
|
||||
# This test is too short...if the test finishes before flutter has finished initializing then
|
||||
# the framework gets very confused...
|
||||
And I wait for 2 seconds
|
||||
|
||||
Scenario: Create Encrypted Profile
|
||||
Given I wait until the widget with type 'ProfileMgrView' is present
|
||||
And I tap a button with tooltip "Add new profile"
|
||||
And I tap the "addNewProfileActual" button
|
||||
And I wait until the text 'Display Name' is present
|
||||
And I tap the button with tooltip "Add new profile"
|
||||
Then I expect the text 'Display Name' to be present
|
||||
And I expect the text 'New Password' to be present
|
||||
And I take a screenshot
|
||||
Then I fill the "displayNameFormElement" field with "Alice (Encrypted)"
|
||||
|
@ -57,7 +51,7 @@ Feature: Basic Profile Management
|
|||
Scenario: Load an Encrypted Profile by Unlocking it with a Password
|
||||
Given I wait until the widget with type 'ProfileMgrView' is present
|
||||
Then I expect the text 'Enter a password to view your profiles' to be absent
|
||||
And I tap a button with tooltip "Unlock encrypted profiles by entering their password."
|
||||
And I tap the button with tooltip "Unlock encrypted profiles by entering their password."
|
||||
Then I expect the text 'Enter a password to view your profiles' to be present
|
||||
When I fill the "unlockPasswordProfileElement" field with "password1"
|
||||
And I tap the "button" widget with label "Unlock"
|
||||
|
@ -66,7 +60,7 @@ Feature: Basic Profile Management
|
|||
Scenario: Load an Encrypted Profile by Unlocking it with a Password and Change the Name
|
||||
Given I wait until the widget with type 'ProfileMgrView' is present
|
||||
Then I expect the text 'Enter a password to view your profiles' to be absent
|
||||
And I tap a button with tooltip "Unlock encrypted profiles by entering their password."
|
||||
And I tap the button with tooltip "Unlock encrypted profiles by entering their password."
|
||||
Then I expect the text 'Enter a password to view your profiles' to be present
|
||||
When I fill the "unlockPasswordProfileElement" field with "password1"
|
||||
And I tap the "button" widget with label "Unlock"
|
||||
|
@ -74,14 +68,14 @@ Feature: Basic Profile Management
|
|||
When I tap the "IconButton" widget with tooltip "Edit Profile Alice (Encrypted)"
|
||||
Then I expect the text 'Display Name' to be present
|
||||
Then I fill the "displayNameFormElement" field with "Carol (Encrypted)"
|
||||
And I tap the widget that contains the text "Save Profile"
|
||||
And I tap the "button" widget with label "Save Profile"
|
||||
And I wait until the widget with type 'ProfileMgrView' is present
|
||||
Then I expect a "ProfileRow" widget with text "Carol (Encrypted)"
|
||||
|
||||
Scenario: Delete an Encrypted Profile
|
||||
Given I wait until the widget with type 'ProfileMgrView' is present
|
||||
Then I expect the text 'Enter a password to view your profiles' to be absent
|
||||
And I tap a button with tooltip "Unlock encrypted profiles by entering their password."
|
||||
And I tap the button with tooltip "Unlock encrypted profiles by entering their password."
|
||||
Then I expect the text 'Enter a password to view your profiles' to be present
|
||||
When I fill the "unlockPasswordProfileElement" field with "password1"
|
||||
And I tap the "button" widget with label "Unlock"
|
||||
|
@ -89,9 +83,8 @@ Feature: Basic Profile Management
|
|||
And I take a screenshot
|
||||
When I tap the "IconButton" widget with tooltip "Edit Profile Carol (Encrypted)"
|
||||
Then I expect the text 'Display Name' to be present
|
||||
Then I fill the "currentPasswordFormElement" field with "password1"
|
||||
And I tap the widget that contains the text "Delete"
|
||||
Then I wait for 2 seconds
|
||||
When I tap the button that contains the text "Delete"
|
||||
Then I expect the text "Really Delete Profile" to be present
|
||||
When I tap the "button" widget with label "Really Delete Profile"
|
||||
And I wait until the widget with type 'ProfileMgrView' is present
|
||||
Then I expect a "ProfileRow" widget with text "Carol (Encrypted)" to be absent
|
||||
|
|
|
@ -52,11 +52,9 @@ void main() async {
|
|||
// text
|
||||
TorVersionPresent(),
|
||||
TooltipTap(),
|
||||
TooltipTapAny(),
|
||||
// files
|
||||
FolderExists(),
|
||||
FileExists(),
|
||||
WaitFileExists(),
|
||||
];
|
||||
|
||||
var sb = StringBuffer();
|
||||
|
|
|
@ -1,8 +1,17 @@
|
|||
import 'package:cwtch/main.dart';
|
||||
import 'package:cwtch/widgets/messagebubble.dart';
|
||||
import 'package:cwtch/widgets/profilerow.dart';
|
||||
import 'package:cwtch/widgets/quotedmessage.dart';
|
||||
import 'package:cwtch/widgets/tor_icon.dart';
|
||||
import 'package:cwtch/views/profilemgrview.dart';
|
||||
import 'package:flutter_gherkin/flutter_gherkin.dart';
|
||||
import 'package:flutter_gherkin/src/flutter/parameters/existence_parameter.dart';
|
||||
import 'package:flutter_gherkin/src/flutter/parameters/swipe_direction_parameter.dart';
|
||||
import 'package:gherkin/gherkin.dart';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'overrides.dart';
|
||||
|
||||
StepDefinitionGeneric ExpectReply() {
|
||||
return given3<String, String, int, FlutterWorld>(
|
||||
|
|
|
@ -19,16 +19,3 @@ StepDefinitionGeneric FileExists() {
|
|||
},
|
||||
);
|
||||
}
|
||||
|
||||
StepDefinitionGeneric WaitFileExists() {
|
||||
return then1<String, FlutterWorld>(
|
||||
RegExp(r'I wait for the file {string} to exist'),
|
||||
(input1, context) async {
|
||||
await context.world.appDriver.waitUntil(
|
||||
() async {
|
||||
await context.world.appDriver.waitForAppToSettle();
|
||||
return File(input1).existsSync();
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_driver/flutter_driver.dart';
|
||||
import 'package:flutter_gherkin/flutter_gherkin.dart';
|
||||
import 'package:gherkin/gherkin.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
|
||||
enum SwitchState { checked, unchecked }
|
||||
|
||||
|
@ -14,7 +17,6 @@ class SwitchStateParameter extends CustomParameter<SwitchState> {
|
|||
case "unchecked":
|
||||
return SwitchState.unchecked;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -11,14 +11,6 @@ StepDefinitionGeneric TooltipTap() {
|
|||
});
|
||||
}
|
||||
|
||||
StepDefinitionGeneric TooltipTapAny() {
|
||||
return given1<String, FlutterWorld>(RegExp(r'I tap a button with tooltip {string}'), (input1, context) async {
|
||||
final finder = context.world.appDriver.findBy(input1, FindType.tooltip).first;
|
||||
await context.world.appDriver.tap(finder);
|
||||
await context.world.appDriver.waitForAppToSettle();
|
||||
});
|
||||
}
|
||||
|
||||
StepDefinitionGeneric TorVersionPresent() {
|
||||
return given<FlutterWorld>(
|
||||
RegExp(r'I expect the Tor version to be present$'),
|
||||
|
@ -33,6 +25,7 @@ StepDefinitionGeneric TorVersionPresent() {
|
|||
break;
|
||||
}
|
||||
}
|
||||
print('File is now closed.');
|
||||
} catch (e) {
|
||||
print('Error: $e');
|
||||
}
|
||||
|
@ -40,18 +33,15 @@ StepDefinitionGeneric TorVersionPresent() {
|
|||
context.expect(versionString, "#.#.#", reason: "error reading version string from fetch-tor.sh");
|
||||
return;
|
||||
}
|
||||
context.world.attach(versionString.substring(0, 4), "text/plain", "Then I expect the Tor version to be present");
|
||||
context.world.attach(versionString, "text/plain", "Then I expect the Tor version to be present");
|
||||
//context.reporter.message("test!!!", MessageLevel.info);
|
||||
print("looking for version string $versionString");
|
||||
|
||||
return await context.world.appDriver.waitUntil(() async {
|
||||
context.world.appDriver.waitForAppToSettle();
|
||||
final finder = context.world.appDriver.findBy(
|
||||
versionString.substring(0, 4),
|
||||
FindType.text,
|
||||
);
|
||||
return await context.world.appDriver.isPresent(finder);
|
||||
});
|
||||
final finder = context.world.appDriver.findBy(
|
||||
versionString,
|
||||
FindType.text,
|
||||
);
|
||||
final isP = await context.world.appDriver.isPresent(finder);
|
||||
context.expect(isP, true);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -19,4 +19,3 @@ StepDefinitionGeneric TakeScreenshot() {
|
|||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
||||
#include "Generated.xcconfig"
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
||||
#include "Generated.xcconfig"
|
||||
|
|
|
@ -10,8 +10,7 @@ class EnvironmentConfig {
|
|||
|
||||
static void debugLog(String log) {
|
||||
if (EnvironmentConfig.BUILD_VER == dev_version) {
|
||||
String datetime = DateTime.now().toIso8601String();
|
||||
print("$datetime $log");
|
||||
print(log);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,16 @@
|
|||
import 'package:cwtch/themes/opaque.dart';
|
||||
import 'package:cwtch/third_party/linkify/linkify.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
|
||||
import '../settings.dart';
|
||||
|
||||
void modalOpenLink(BuildContext ctx, LinkableElement link) {
|
||||
showModalBottomSheet<void>(
|
||||
context: ctx,
|
||||
builder: (BuildContext bcontext) {
|
||||
return Container(
|
||||
height: 200,
|
||||
height: 200, // bespoke value courtesy of the [TextField] docs
|
||||
child: Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(30.0),
|
||||
|
@ -21,24 +18,17 @@ void modalOpenLink(BuildContext ctx, LinkableElement link) {
|
|||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
AppLocalizations.of(bcontext)!.clickableLinksWarning,
|
||||
style: Provider.of<Settings>(bcontext).scaleFonts(defaultTextStyle),
|
||||
),
|
||||
Text(AppLocalizations.of(bcontext)!.clickableLinksWarning),
|
||||
Flex(direction: Axis.horizontal, mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
|
||||
Container(
|
||||
margin: EdgeInsets.symmetric(vertical: 20, horizontal: 10),
|
||||
child: ElevatedButton(
|
||||
child: Text(AppLocalizations.of(bcontext)!.clickableLinksCopy,
|
||||
style: Provider.of<Settings>(bcontext).scaleFonts(defaultTextButtonStyle), semanticsLabel: AppLocalizations.of(bcontext)!.clickableLinksCopy),
|
||||
child: Text(AppLocalizations.of(bcontext)!.clickableLinksCopy, semanticsLabel: AppLocalizations.of(bcontext)!.clickableLinksCopy),
|
||||
onPressed: () {
|
||||
Clipboard.setData(new ClipboardData(text: link.url));
|
||||
|
||||
final snackBar = SnackBar(
|
||||
content: Text(
|
||||
AppLocalizations.of(bcontext)!.copiedToClipboardNotification,
|
||||
style: Provider.of<Settings>(bcontext, listen: false).scaleFonts(defaultTextButtonStyle),
|
||||
),
|
||||
content: Text(AppLocalizations.of(bcontext)!.copiedToClipboardNotification),
|
||||
);
|
||||
|
||||
Navigator.pop(bcontext);
|
||||
|
@ -49,14 +39,15 @@ void modalOpenLink(BuildContext ctx, LinkableElement link) {
|
|||
Container(
|
||||
margin: EdgeInsets.symmetric(vertical: 20, horizontal: 10),
|
||||
child: ElevatedButton(
|
||||
child: Text(AppLocalizations.of(bcontext)!.clickableLinkOpen,
|
||||
style: Provider.of<Settings>(bcontext).scaleFonts(defaultTextButtonStyle), semanticsLabel: AppLocalizations.of(bcontext)!.clickableLinkOpen),
|
||||
child: Text(AppLocalizations.of(bcontext)!.clickableLinkOpen, semanticsLabel: AppLocalizations.of(bcontext)!.clickableLinkOpen),
|
||||
onPressed: () async {
|
||||
if (await canLaunchUrlString(link.url)) {
|
||||
await launchUrlString(link.url);
|
||||
if (await canLaunch(link.url)) {
|
||||
await launch(link.url);
|
||||
Navigator.pop(bcontext);
|
||||
} else {
|
||||
final snackBar = SnackBar(content: Text(AppLocalizations.of(bcontext)!.clickableLinkError, style: Provider.of<Settings>(bcontext).scaleFonts(defaultTextButtonStyle)));
|
||||
final snackBar = SnackBar(
|
||||
content: Text(AppLocalizations.of(bcontext)!.clickableLinkError),
|
||||
);
|
||||
ScaffoldMessenger.of(bcontext).showSnackBar(snackBar);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,20 +1,14 @@
|
|||
// To handle profiles that are "unencrypted" (i.e don't require a password to open) we currently create a profile with a defacto, hardcoded password.
|
||||
// Details: https://docs.openprivacy.ca/cwtch-security-handbook/profile_encryption_and_storage.html
|
||||
import 'dart:collection';
|
||||
|
||||
const DefaultPassword = "be gay do crime";
|
||||
|
||||
const LastMessageSeenTimeKey = "profile.lastMessageSeenTime";
|
||||
|
||||
abstract class Cwtch {
|
||||
Future<HashMap<String, String>> PlatformChannelInfo();
|
||||
|
||||
// ignore: non_constant_identifier_names
|
||||
Future<void> Start();
|
||||
|
||||
Future<String> getCwtchDir();
|
||||
|
||||
String getAssetsDir();
|
||||
// ignore: non_constant_identifier_names
|
||||
Future<void> ReconnectCwtchForeground();
|
||||
|
||||
// ignore: non_constant_identifier_names
|
||||
void CreateProfile(String nick, String pass, bool autostart);
|
||||
|
@ -38,7 +32,12 @@ abstract class Cwtch {
|
|||
|
||||
// ignore: non_constant_identifier_names
|
||||
void ResetTor();
|
||||
void UpdateSettings(String json);
|
||||
|
||||
// todo: remove these
|
||||
// ignore: non_constant_identifier_names
|
||||
void SendProfileEvent(String onion, String jsonEvent);
|
||||
// ignore: non_constant_identifier_names
|
||||
void SendAppEvent(String jsonEvent);
|
||||
|
||||
// ignore: non_constant_identifier_names
|
||||
void AcceptContact(String profileOnion, int contactHandle);
|
||||
|
@ -47,11 +46,6 @@ abstract class Cwtch {
|
|||
// ignore: non_constant_identifier_names
|
||||
void UnblockContact(String profileOnion, int contactHandle);
|
||||
|
||||
void AttemptReconnection(String profileOnion, String onion);
|
||||
void AttemptReconnectionServer(String profileOnion, String onion);
|
||||
void DisconnectFromPeer(String profileOnion, String onion);
|
||||
void DisconnectFromServer(String profileOnion, String onion);
|
||||
|
||||
// ignore: non_constant_identifier_names
|
||||
Future<dynamic> GetMessage(String profile, int handle, int index);
|
||||
|
||||
|
@ -85,7 +79,7 @@ abstract class Cwtch {
|
|||
void DownloadFile(String profile, int handle, String filepath, String manifestpath, String filekey);
|
||||
// android-only
|
||||
// ignore: non_constant_identifier_names
|
||||
void CreateDownloadableFile(String profile, int handle, String filenameSuggestion, String filekey, String manifestPath);
|
||||
void CreateDownloadableFile(String profile, int handle, String filenameSuggestion, String filekey);
|
||||
// ignore: non_constant_identifier_names
|
||||
void CheckDownloadStatus(String profile, String fileKey);
|
||||
// ignore: non_constant_identifier_names
|
||||
|
@ -106,12 +100,9 @@ abstract class Cwtch {
|
|||
Future<dynamic> ImportBundle(String profile, String bundle);
|
||||
// ignore: non_constant_identifier_names
|
||||
void SetProfileAttribute(String profile, String key, String val);
|
||||
Future<String?> GetProfileAttribute(String profile, String key);
|
||||
// ignore: non_constant_identifier_names
|
||||
void SetConversationAttribute(String profile, int conversation, String key, String val);
|
||||
// ignore: non_constant_identifier_names
|
||||
Future<String?> GetConversationAttribute(String profile, int identifier, String s);
|
||||
// ignore: non_constant_identifier_names
|
||||
void SetMessageAttribute(String profile, int conversation, int channel, int message, String key, String val);
|
||||
// ignore: non_constant_identifier_names
|
||||
void LoadServers(String password);
|
||||
|
@ -145,19 +136,4 @@ abstract class Cwtch {
|
|||
void dispose();
|
||||
|
||||
Future<dynamic> GetDebugInfo();
|
||||
|
||||
bool IsServersCompiled();
|
||||
|
||||
Future<String> SummarizeConversation(String profile, int conversation);
|
||||
Future<String> TranslateMessage(String profile, int conversation, int message, String language);
|
||||
|
||||
bool IsBlodeuweddSupported();
|
||||
|
||||
// ignore: non_constant_identifier_names
|
||||
Future<String> SearchConversations(String profile, String pattern);
|
||||
void DeleteServerInfo(String profile, String handle);
|
||||
void PublishServerUpdate(String onion);
|
||||
Future<void> ConfigureConnections(String onion, bool listen, bool peers, bool servers);
|
||||
|
||||
bool IsLoaded();
|
||||
}
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
import 'dart:convert';
|
||||
import 'package:cwtch/cwtch/cwtch.dart';
|
||||
import 'package:cwtch/main.dart';
|
||||
import 'package:cwtch/models/appstate.dart';
|
||||
import 'package:cwtch/models/contact.dart';
|
||||
import 'package:cwtch/models/message.dart';
|
||||
import 'package:cwtch/models/profilelist.dart';
|
||||
import 'package:cwtch/models/profileservers.dart';
|
||||
import 'package:cwtch/models/remoteserver.dart';
|
||||
import 'package:cwtch/models/servers.dart';
|
||||
import 'package:cwtch/notification_manager.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:cwtch/torstatus.dart';
|
||||
|
||||
|
@ -26,15 +30,14 @@ class CwtchNotifier {
|
|||
late NotificationsManager notificationManager;
|
||||
late AppState appState;
|
||||
late ServerListState serverListState;
|
||||
late FlwtchState flwtchState;
|
||||
|
||||
String? notificationSimple;
|
||||
String? notificationConversationInfo;
|
||||
|
||||
SeenMessageCallback? seenMessageCallback;
|
||||
|
||||
CwtchNotifier(ProfileListState pcn, Settings settingsCN, ErrorHandler errorCN, TorStatus torStatusCN, NotificationsManager notificationManagerP, AppState appStateCN,
|
||||
ServerListState serverListStateCN, FlwtchState flwtchStateCN) {
|
||||
CwtchNotifier(
|
||||
ProfileListState pcn, Settings settingsCN, ErrorHandler errorCN, TorStatus torStatusCN, NotificationsManager notificationManagerP, AppState appStateCN, ServerListState serverListStateCN) {
|
||||
profileCN = pcn;
|
||||
settings = settingsCN;
|
||||
error = errorCN;
|
||||
|
@ -42,7 +45,6 @@ class CwtchNotifier {
|
|||
notificationManager = notificationManagerP;
|
||||
appState = appStateCN;
|
||||
serverListState = serverListStateCN;
|
||||
flwtchState = flwtchStateCN;
|
||||
}
|
||||
|
||||
void l10nInit(String notificationSimple, String notificationConversationInfo) {
|
||||
|
@ -55,53 +57,23 @@ class CwtchNotifier {
|
|||
}
|
||||
|
||||
void handleMessage(String type, dynamic data) {
|
||||
// EnvironmentConfig.debugLog("NewEvent $type $data");
|
||||
//EnvironmentConfig.debugLog("NewEvent $type $data");
|
||||
switch (type) {
|
||||
case "CwtchStarted":
|
||||
if (data["Reload"] == "true" && profileCN.num > 0) {
|
||||
// don't reload...
|
||||
// unless we have loaded no profiles...then there isnt a risk and this
|
||||
// might be a first time (e.g. new apk, existing service)
|
||||
} else {
|
||||
flwtchState.cwtch.LoadProfiles(DefaultPassword);
|
||||
}
|
||||
|
||||
appState.SetCwtchInit();
|
||||
break;
|
||||
case "CwtchStartError":
|
||||
appState.SetAppError(data["Error"]);
|
||||
break;
|
||||
case "NewPeer":
|
||||
// EnvironmentConfig.debugLog("NewPeer $data");
|
||||
// empty events can be caused by the testing framework
|
||||
if (data["Online"] == null) {
|
||||
break;
|
||||
}
|
||||
EnvironmentConfig.debugLog("NewPeer $data");
|
||||
// if tag != v1-defaultPassword then it is either encrypted OR it is an unencrypted account created during pre-beta...
|
||||
profileCN.add(
|
||||
data["Identity"],
|
||||
data["name"],
|
||||
data["picture"],
|
||||
data["defaultPicture"],
|
||||
data["ContactsJson"],
|
||||
data["ServerList"],
|
||||
data["Online"] == "true",
|
||||
data["autostart"] == "true",
|
||||
data["tag"] != "v1-defaultPassword",
|
||||
data["appearOffline"] == "true",
|
||||
);
|
||||
|
||||
// Update Profile Attributes
|
||||
EnvironmentConfig.debugLog("Looking up Profile Attributes ${data["Identity"]} ${profileCN.getProfile(data["Identity"])}");
|
||||
flwtchState.cwtch.GetProfileAttribute(data["Identity"], "profile.profile-attribute-1").then((value) => profileCN.getProfile(data["Identity"])?.setAttribute(0, value));
|
||||
flwtchState.cwtch.GetProfileAttribute(data["Identity"], "profile.profile-attribute-2").then((value) => profileCN.getProfile(data["Identity"])?.setAttribute(1, value));
|
||||
flwtchState.cwtch.GetProfileAttribute(data["Identity"], "profile.profile-attribute-3").then((value) => profileCN.getProfile(data["Identity"])?.setAttribute(2, value));
|
||||
flwtchState.cwtch.GetProfileAttribute(data["Identity"], "profile.profile-status").then((value) => profileCN.getProfile(data["Identity"])?.setAvailabilityStatus(value ?? ""));
|
||||
|
||||
EnvironmentConfig.debugLog("Looking up Profile Information for Contact...");
|
||||
profileCN.getProfile(data["Identity"])?.contactList.contacts.forEach((contact) {
|
||||
flwtchState.cwtch.GetConversationAttribute(data["Identity"], contact.identifier, "public.profile.profile-attribute-1").then((value) => contact.setAttribute(0, value));
|
||||
flwtchState.cwtch.GetConversationAttribute(data["Identity"], contact.identifier, "public.profile.profile-attribute-2").then((value) => contact.setAttribute(1, value));
|
||||
flwtchState.cwtch.GetConversationAttribute(data["Identity"], contact.identifier, "public.profile.profile-attribute-3").then((value) => contact.setAttribute(2, value));
|
||||
flwtchState.cwtch.GetConversationAttribute(data["Identity"], contact.identifier, "public.profile.profile-status").then((value) => contact.setAvailabilityStatus(value ?? ""));
|
||||
});
|
||||
|
||||
profileCN.add(data["Identity"], data["name"], data["picture"], data["defaultPicture"], data["ContactsJson"], data["ServerList"], data["Online"] == "true", data["autostart"] == "true",
|
||||
data["tag"] != "v1-defaultPassword");
|
||||
break;
|
||||
case "ContactCreated":
|
||||
EnvironmentConfig.debugLog("ContactCreated $data");
|
||||
|
@ -160,7 +132,7 @@ class CwtchNotifier {
|
|||
lastMessageTime: DateTime.now(),
|
||||
notificationPolicy: data["notificationPolicy"] ?? "ConversationNotificationPolicy.Default"));
|
||||
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.updateLastMessageReceivedTime(int.parse(data["ConversationID"]), DateTime.now());
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.updateLastMessageTime(int.parse(data["ConversationID"]), DateTime.now());
|
||||
}
|
||||
break;
|
||||
case "PeerDeleted":
|
||||
|
@ -175,8 +147,10 @@ class CwtchNotifier {
|
|||
}
|
||||
break;
|
||||
case "DeleteContact":
|
||||
var identifier = int.parse(data["ConversationID"]);
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.removeContact(identifier);
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.removeContact(data["ConversationID"]);
|
||||
break;
|
||||
case "DeleteGroup":
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.removeContact(data["ConversationID"]);
|
||||
break;
|
||||
case "PeerStateChange":
|
||||
ContactInfoState? contact = profileCN.getProfile(data["ProfileOnion"])?.contactList.findContact(data["RemotePeer"]);
|
||||
|
@ -195,9 +169,21 @@ class CwtchNotifier {
|
|||
var senderImage = data['picture'];
|
||||
var isAuto = data['Auto'] == "true";
|
||||
String contenthash = data['ContentHash'];
|
||||
|
||||
var selectedProfile = appState.selectedProfile == data["ProfileOnion"];
|
||||
var selectedConversation = selectedProfile && appState.selectedConversation == identifier;
|
||||
var notification = data["notification"];
|
||||
|
||||
if (selectedConversation && seenMessageCallback != null) {
|
||||
seenMessageCallback!(data["ProfileOnion"]!, identifier, DateTime.now().toUtc());
|
||||
}
|
||||
|
||||
if (notification == "SimpleEvent") {
|
||||
notificationManager.notify(notificationSimple ?? "New Message", "", 0);
|
||||
} else if (notification == "ContactInfo") {
|
||||
var contact = profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier);
|
||||
notificationManager.notify((notificationConversationInfo ?? "New Message from %1").replaceFirst("%1", (contact?.nickname ?? senderHandle.toString())), data["ProfileOnion"], identifier);
|
||||
}
|
||||
|
||||
profileCN.getProfile(data["ProfileOnion"])?.newMessage(
|
||||
identifier,
|
||||
messageID,
|
||||
|
@ -210,19 +196,6 @@ class CwtchNotifier {
|
|||
selectedProfile,
|
||||
selectedConversation,
|
||||
);
|
||||
|
||||
// Now perform the notification logic...
|
||||
var notification = data["notification"];
|
||||
if (selectedConversation && seenMessageCallback != null) {
|
||||
seenMessageCallback!(data["ProfileOnion"]!, identifier, DateTime.now().toUtc());
|
||||
}
|
||||
|
||||
if (notification == "SimpleEvent") {
|
||||
notificationManager.notify(notificationSimple ?? "New Message", "", 0);
|
||||
} else if (notification == "ContactInfo") {
|
||||
var contact = profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier);
|
||||
notificationManager.notify((notificationConversationInfo ?? "New Message from %1").replaceFirst("%1", (contact?.nickname ?? senderHandle.toString())), data["ProfileOnion"], identifier);
|
||||
}
|
||||
appState.notifyProfileUnread();
|
||||
break;
|
||||
case "PeerAcknowledgement":
|
||||
|
@ -257,7 +230,7 @@ class CwtchNotifier {
|
|||
var notification = data["notification"];
|
||||
|
||||
// Only bother to do anything if we know about the group and the provided index is greater than our current total...
|
||||
if (idx >= currentTotal) {
|
||||
if (currentTotal != null && idx >= currentTotal) {
|
||||
// TODO: There are 2 timestamps associated with a new group message - time sent and time received.
|
||||
// Sent refers to the time a profile alleges they sent a message
|
||||
// Received refers to the time we actually saw the message from the server
|
||||
|
@ -305,7 +278,6 @@ class CwtchNotifier {
|
|||
break;
|
||||
case "UpdateGlobalSettings":
|
||||
settings.handleUpdate(jsonDecode(data["Data"]));
|
||||
appState.settingsLoaded = true;
|
||||
break;
|
||||
case "UpdatedProfileAttribute":
|
||||
if (data["Key"] == "public.profile.name") {
|
||||
|
@ -319,10 +291,6 @@ class CwtchNotifier {
|
|||
profileCN.getProfile(data["ProfileOnion"])?.downloadSetPathForSender(filekey, data["Data"]);
|
||||
}
|
||||
}
|
||||
} else if (data["Key"].toString().startsWith("public.profile.profile-attribute")) {
|
||||
// ignore these events...
|
||||
} else if (data["Key"].toString().startsWith("public.profile.profile-status")) {
|
||||
profileCN.getProfile(data["ProfileOnion"])?.setAvailabilityStatus(data["Data"]);
|
||||
} else {
|
||||
EnvironmentConfig.debugLog("unhandled set attribute event: ${data['Key']}");
|
||||
}
|
||||
|
@ -340,7 +308,6 @@ class CwtchNotifier {
|
|||
torStatus.updateVersion(data["Data"]);
|
||||
break;
|
||||
case "UpdateServerInfo":
|
||||
EnvironmentConfig.debugLog("NewEvent UpdateServerInfo $type $data");
|
||||
profileCN.getProfile(data["ProfileOnion"])?.replaceServers(data["ServerList"]);
|
||||
break;
|
||||
case "TokenManagerInfo":
|
||||
|
@ -350,7 +317,7 @@ class CwtchNotifier {
|
|||
associatedGroups.forEach((identifier) {
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(int.parse(identifier.toString()))!.antispamTickets = count;
|
||||
});
|
||||
EnvironmentConfig.debugLog("update server token count for $associatedGroups, $count");
|
||||
EnvironmentConfig.debugLog("update server token count for ${associatedGroups}, $count");
|
||||
} catch (e) {
|
||||
// No tokens in data...
|
||||
}
|
||||
|
@ -379,13 +346,8 @@ class CwtchNotifier {
|
|||
status: status,
|
||||
isGroup: true,
|
||||
lastMessageTime: DateTime.now()));
|
||||
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.updateLastMessageReceivedTime(identifier, DateTime.fromMillisecondsSinceEpoch(0));
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.updateLastMessageTime(identifier, DateTime.fromMillisecondsSinceEpoch(0));
|
||||
}
|
||||
// request a new server update...
|
||||
// NOTE: In the future this should also update the TokenManagerInfo
|
||||
// This is not currently communicated by ServerUpdateInfo (but it probably should be)git
|
||||
flwtchState.cwtch.PublishServerUpdate(data["ProfileOnion"]);
|
||||
}
|
||||
break;
|
||||
case "ServerStateChange":
|
||||
|
@ -398,8 +360,8 @@ class CwtchNotifier {
|
|||
});
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.resort();
|
||||
break;
|
||||
case "UpdatedConversationAttribute":
|
||||
if (data["Path"] == "profile.name") {
|
||||
case "NewRetValMessageFromPeer":
|
||||
if (data["Path"] == "profile.name" && data["Exists"] == "true") {
|
||||
if (data["Data"].toString().trim().length > 0) {
|
||||
// Update locally on the UI...
|
||||
if (profileCN.getProfile(data["ProfileOnion"])?.contactList.findContact(data["RemotePeer"]) != null) {
|
||||
|
@ -407,33 +369,14 @@ class CwtchNotifier {
|
|||
}
|
||||
}
|
||||
} else if (data['Path'] == "profile.custom-profile-image") {
|
||||
EnvironmentConfig.debugLog("received ret val of custom profile image: $data");
|
||||
String fileKey = data['Data'];
|
||||
var contact = profileCN.getProfile(data["ProfileOnion"])?.contactList.findContact(data["RemotePeer"]);
|
||||
if (contact != null) {
|
||||
EnvironmentConfig.debugLog("waiting for download from $contact");
|
||||
profileCN.getProfile(data["ProfileOnion"])?.waitForDownloadComplete(contact.identifier, fileKey);
|
||||
}
|
||||
} else if (data['Path'] == "profile.profile-attribute-1" || data['Path'] == "profile.profile-attribute-2" || data['Path'] == "profile.profile-attribute-3") {
|
||||
var contact = profileCN.getProfile(data["ProfileOnion"])?.contactList.findContact(data["RemotePeer"]);
|
||||
if (contact != null) {
|
||||
switch (data['Path']) {
|
||||
case "profile.profile-attribute-1":
|
||||
contact.setAttribute(0, data["Data"]);
|
||||
break;
|
||||
case "profile.profile-attribute-2":
|
||||
contact.setAttribute(1, data["Data"]);
|
||||
break;
|
||||
case "profile.profile-attribute-3":
|
||||
contact.setAttribute(2, data["Data"]);
|
||||
break;
|
||||
if (data["Exists"] == "true") {
|
||||
EnvironmentConfig.debugLog("received ret val of custom profile image: $data");
|
||||
String fileKey = data['Data'];
|
||||
var contact = profileCN.getProfile(data["ProfileOnion"])?.contactList.findContact(data["RemotePeer"]);
|
||||
if (contact != null) {
|
||||
profileCN.getProfile(data["ProfileOnion"])?.waitForDownloadComplete(contact.identifier, fileKey);
|
||||
}
|
||||
}
|
||||
} else if (data['Path'] == "profile.profile-status") {
|
||||
var contact = profileCN.getProfile(data["ProfileOnion"])?.contactList.findContact(data["RemotePeer"]);
|
||||
if (contact != null) {
|
||||
contact.setAvailabilityStatus(data['Data']);
|
||||
}
|
||||
} else {
|
||||
EnvironmentConfig.debugLog("unhandled ret val event: ${data['Path']}");
|
||||
}
|
||||
|
@ -465,16 +408,6 @@ class CwtchNotifier {
|
|||
case "DoneStorageMigration":
|
||||
appState.SetModalState(ModalState.none);
|
||||
break;
|
||||
case "BlodeuweddSummary":
|
||||
var identifier = int.parse(data["ConversationID"]);
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)?.updateSummaryEvent(data["Summary"]);
|
||||
break;
|
||||
case "BlodeuweddTranslation":
|
||||
var identifier = int.parse(data["ConversationID"]);
|
||||
var mid = int.parse(data["Index"]);
|
||||
EnvironmentConfig.debugLog("received translation event: $identifier $mid $data");
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)?.updateTranslationEvent(mid, data["Translation"]);
|
||||
break;
|
||||
case "ACNInfo":
|
||||
var key = data["Key"];
|
||||
var handle = data["Handle"];
|
||||
|
@ -482,12 +415,6 @@ class CwtchNotifier {
|
|||
profileCN.getProfile(data["ProfileOnion"])?.contactList.findContact(handle)?.acnCircuit = data["Data"];
|
||||
}
|
||||
break;
|
||||
case "SearchResult":
|
||||
String searchID = data["SearchID"];
|
||||
var conversationIdentifier = int.parse(data["ConversationID"]);
|
||||
var messageIndex = int.parse(data["RowIndex"]);
|
||||
profileCN.getProfile(data["ProfileOnion"])?.handleSearchResult(searchID, conversationIdentifier, messageIndex);
|
||||
break;
|
||||
default:
|
||||
EnvironmentConfig.debugLog("unhandled event: $type");
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import 'dart:collection';
|
||||
import 'dart:convert';
|
||||
import 'dart:ffi';
|
||||
import 'dart:io';
|
||||
import 'dart:isolate';
|
||||
import 'dart:io' show Platform;
|
||||
import 'package:cwtch/cwtch/cwtchNotifier.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
|
@ -12,6 +12,7 @@ import 'package:cwtch/cwtch/cwtch.dart';
|
|||
import '../config.dart';
|
||||
|
||||
import "package:path/path.dart" show dirname, join;
|
||||
import 'dart:io' show Platform;
|
||||
|
||||
/////////////////////
|
||||
/// Cwtch API ///
|
||||
|
@ -28,7 +29,6 @@ typedef FreeFn = void Function(Pointer<Utf8>);
|
|||
|
||||
typedef void_from_string_string_function = Void Function(Pointer<Utf8>, Int32, Pointer<Utf8>, Int32);
|
||||
typedef VoidFromStringStringFn = void Function(Pointer<Utf8>, int, Pointer<Utf8>, int);
|
||||
typedef VoidFromStringFn = void Function(Pointer<Utf8>, int);
|
||||
|
||||
typedef void_from_string_string_string_function = Void Function(Pointer<Utf8>, Int32, Pointer<Utf8>, Int32, Pointer<Utf8>, Int32);
|
||||
typedef VoidFromStringStringStringFn = void Function(Pointer<Utf8>, int, Pointer<Utf8>, int, Pointer<Utf8>, int);
|
||||
|
@ -43,9 +43,6 @@ typedef VoidFromStringIntStringStringStringFn = void Function(Pointer<Utf8>, int
|
|||
typedef void_from_string_string_int_int_function = Void Function(Pointer<Utf8>, Int32, Pointer<Utf8>, Int32, Int64, Int64);
|
||||
typedef VoidFromStringStringIntIntFn = void Function(Pointer<Utf8>, int, Pointer<Utf8>, int, int, int);
|
||||
|
||||
typedef void_from_string_bool_bool_bool = Void Function(Pointer<Utf8>, Int32, Bool, Bool, Bool);
|
||||
typedef VoidFromStringBoolBoolBool = void Function(Pointer<Utf8>, int, bool, bool, bool);
|
||||
|
||||
typedef void_from_string_string_byte_function = Void Function(Pointer<Utf8>, Int32, Pointer<Utf8>, Int32, Int8);
|
||||
typedef VoidFromStringStringByteFn = void Function(Pointer<Utf8>, int, Pointer<Utf8>, int, int);
|
||||
|
||||
|
@ -74,19 +71,6 @@ typedef GetJsonBlobFromStrStrIntFn = Pointer<Utf8> Function(Pointer<Utf8>, int,
|
|||
typedef get_json_blob_from_str_int_function = Pointer<Utf8> Function(Pointer<Utf8>, Int32, Int32);
|
||||
typedef GetJsonBlobFromStrIntFn = Pointer<Utf8> Function(Pointer<Utf8>, int, int);
|
||||
|
||||
typedef get_json_blob_from_str_str_function = Pointer<Utf8> Function(Pointer<Utf8>, Int32, Pointer<Utf8>, Int32);
|
||||
typedef GetJsonBlobFromStrStrFn = Pointer<Utf8> Function(Pointer<Utf8>, int, Pointer<Utf8>, int);
|
||||
|
||||
typedef get_json_blob_from_str_int_int_str_function = Pointer<Utf8> Function(Pointer<Utf8>, Int32, Int32, Int32, Pointer<Utf8>, Int32);
|
||||
typedef GetJsonBlobFromStrIntIntStrFn = Pointer<Utf8> Function(
|
||||
Pointer<Utf8>,
|
||||
int,
|
||||
int,
|
||||
int,
|
||||
Pointer<Utf8>,
|
||||
int,
|
||||
);
|
||||
|
||||
typedef get_json_blob_from_str_int_int_function = Pointer<Utf8> Function(Pointer<Utf8>, Int32, Int32, Int32);
|
||||
typedef GetJsonBlobFromStrIntIntFn = Pointer<Utf8> Function(Pointer<Utf8>, int, int, int);
|
||||
|
||||
|
@ -132,8 +116,6 @@ class CwtchFfi implements Cwtch {
|
|||
late Isolate cwtchIsolate;
|
||||
ReceivePort _receivePort = ReceivePort();
|
||||
bool _isL10nInit = false;
|
||||
String _assetsDir = path.join(Directory.current.path, "data", "flutter_assets");
|
||||
String _cwtchDir = "";
|
||||
|
||||
static String getLibraryPath() {
|
||||
if (Platform.isWindows) {
|
||||
|
@ -168,58 +150,54 @@ class CwtchFfi implements Cwtch {
|
|||
String home = "";
|
||||
String bundledTor = "";
|
||||
Map<String, String> envVars = Platform.environment;
|
||||
String cwtchDir = "";
|
||||
if (Platform.isLinux) {
|
||||
home = envVars['HOME'] ?? "";
|
||||
if (EnvironmentConfig.TEST_MODE) {
|
||||
_cwtchDir = envVars['CWTCH_HOME']!;
|
||||
cwtchDir = envVars['CWTCH_HOME']!;
|
||||
} else {
|
||||
_cwtchDir = envVars['CWTCH_HOME'] ?? path.join(envVars['HOME']!, ".cwtch");
|
||||
cwtchDir = envVars['CWTCH_HOME'] ?? path.join(envVars['HOME']!, ".cwtch");
|
||||
}
|
||||
|
||||
|
||||
if (await File("linux/Tor/tor").exists()) {
|
||||
bundledTor = "linux/Tor/tor";
|
||||
} else if (await File("lib/Tor/tor").exists()) {
|
||||
bundledTor = "lib/Tor/tor";
|
||||
} else if (await File(path.join(home, ".local/lib/cwtch/Tor/tor")).exists()) {
|
||||
bundledTor = path.join(home, ".local/lib/cwtch/Tor/tor");
|
||||
_assetsDir = path.join(home, ".local", "share", "cwtch", "data", "flutter_assets");
|
||||
} else if (await File("/usr/lib/cwtch/Tor/tor").exists()) {
|
||||
bundledTor = "/usr/lib/cwtch/Tor/tor";
|
||||
_assetsDir = path.join("usr", "share", "cwtch", "data", "flutter_assets");
|
||||
} else {
|
||||
bundledTor = "tor";
|
||||
}
|
||||
} else if (Platform.isWindows) {
|
||||
_cwtchDir = envVars['CWTCH_DIR'] ?? path.join(envVars['UserProfile']!, ".cwtch");
|
||||
cwtchDir = envVars['CWTCH_DIR'] ?? path.join(envVars['UserProfile']!, ".cwtch");
|
||||
String currentTor = path.join(Directory.current.absolute.path, "Tor\\Tor\\tor.exe");
|
||||
if (await File(currentTor).exists()) {
|
||||
bundledTor = currentTor;
|
||||
_assetsDir = path.join(Directory.current.absolute.path, "data", "flutter_assets");
|
||||
} else {
|
||||
String exeDir = path.dirname(Platform.resolvedExecutable);
|
||||
bundledTor = path.join(exeDir, "Tor\\Tor\\tor.exe");
|
||||
_assetsDir = path.join(exeDir, "data", "flutter_assets");
|
||||
}
|
||||
} else if (Platform.isMacOS) {
|
||||
_cwtchDir = envVars['CWTCH_HOME'] ?? path.join(envVars['HOME']!, "Library/Application Support/Cwtch");
|
||||
_assetsDir = "/Applications/Cwtch.app/Contents/Frameworks/App.framework/Versions/Current/Resources/flutter_assets/";
|
||||
if (await File("Cwtch.app/Contents/MacOS/Tor/tor").exists()) {
|
||||
bundledTor = "Cwtch.app/Contents/MacOS/Tor/tor";
|
||||
_assetsDir = "Cwtch.app/Contents/Frameworks/App.framework/Versions/Current/Resources/flutter_assets/";
|
||||
} else if (await File("/Applications/Cwtch.app/Contents/MacOS/Tor/tor").exists()) {
|
||||
bundledTor = "/Applications/Cwtch.app/Contents/MacOS/Tor/tor";
|
||||
} else if (await File("/Volumes/Cwtch/Cwtch.app/Contents/MacOS/Tor/tor").exists()) {
|
||||
bundledTor = "/Volumes/Cwtch/Cwtch.app/Contents/MacOS/Tor/tor";
|
||||
} else if (await File("/Applications/Tor Browser.app/Contents/MacOS/Tor/tor").exists()) {
|
||||
bundledTor = "/Applications/Tor Browser.app/Contents/MacOS/Tor/tor";
|
||||
cwtchDir = envVars['CWTCH_HOME'] ?? path.join(envVars['HOME']!, "Library/Application Support/Cwtch");
|
||||
if (await File("Cwtch.app/Contents/MacOS/Tor/tor.real").exists()) {
|
||||
bundledTor = "Cwtch.app/Contents/MacOS/Tor/tor.real";
|
||||
} else if (await File("/Applications/Cwtch.app/Contents/MacOS/Tor/tor.real").exists()) {
|
||||
bundledTor = "/Applications/Cwtch.app/Contents/MacOS/Tor/tor.real";
|
||||
} else if (await File("/Volumes/Cwtch/Cwtch.app/Contents/MacOS/Tor/tor.real").exists()) {
|
||||
bundledTor = "/Volumes/Cwtch/Cwtch.app/Contents/MacOS/Tor/tor.real";
|
||||
} else if (await File("/Applications/Tor Browser.app/Contents/MacOS/Tor/tor.real").exists()) {
|
||||
bundledTor = "/Applications/Tor Browser.app/Contents/MacOS/Tor/tor.real";
|
||||
print("We couldn't find Tor in the Cwtch app directory, however we can fall back to the Tor Browser binary");
|
||||
} else {
|
||||
var splitPath = path.split(dirname(Platform.script.path));
|
||||
if (splitPath[0] == "/" && splitPath[1] == "Applications") {
|
||||
var appName = splitPath[2];
|
||||
print("We're running in /Applications in a non standard app name: $appName");
|
||||
if (await File("/Applications/$appName/Contents/MacOS/Tor/tor").exists()) {
|
||||
bundledTor = "/Applications/$appName/Contents/MacOS/Tor/tor";
|
||||
if (await File("/Applications/$appName/Contents/MacOS/Tor/tor.real").exists()) {
|
||||
bundledTor = "/Applications/$appName/Contents/MacOS/Tor/tor.real";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -230,27 +208,27 @@ class CwtchFfi implements Cwtch {
|
|||
// if macOs and release build and no profile and is dev profile
|
||||
// copy dev profile to release profile
|
||||
if (Platform.isMacOS && EnvironmentConfig.BUILD_VER != dev_version) {
|
||||
var devProfileExists = await Directory(path.join(_cwtchDir, "dev", "profiles")).exists();
|
||||
var releaseProfileExists = await Directory(path.join(_cwtchDir, "profiles")).exists();
|
||||
var devProfileExists = await Directory(path.join(cwtchDir, "dev", "profiles")).exists();
|
||||
var releaseProfileExists = await Directory(path.join(cwtchDir, "profiles")).exists();
|
||||
if (devProfileExists && !releaseProfileExists) {
|
||||
print("MacOS one time dev -> release profile migration...");
|
||||
await Process.run("cp", ["-r", "-p", path.join(_cwtchDir, "dev", "profiles"), _cwtchDir]);
|
||||
await Process.run("cp", ["-r", "-p", path.join(_cwtchDir, "dev", "SALT"), _cwtchDir]);
|
||||
await Process.run("cp", ["-r", "-p", path.join(_cwtchDir, "dev", "ui.globals"), _cwtchDir]);
|
||||
await Process.run("cp", ["-r", "-p", path.join(cwtchDir, "dev", "profiles"), cwtchDir]);
|
||||
await Process.run("cp", ["-r", "-p", path.join(cwtchDir, "dev", "SALT"), cwtchDir]);
|
||||
await Process.run("cp", ["-r", "-p", path.join(cwtchDir, "dev", "ui.globals"), cwtchDir]);
|
||||
}
|
||||
}
|
||||
|
||||
if (EnvironmentConfig.BUILD_VER == dev_version) {
|
||||
_cwtchDir = path.join(_cwtchDir, "dev");
|
||||
cwtchDir = path.join(cwtchDir, "dev");
|
||||
}
|
||||
|
||||
print("StartCwtch( cwtchdir: $_cwtchDir, torPath: $bundledTor )");
|
||||
print("StartCwtch( cwtchdir: $cwtchDir, torPath: $bundledTor )");
|
||||
|
||||
var startCwtchC = library.lookup<NativeFunction<start_cwtch_function>>("c_StartCwtch");
|
||||
// ignore: non_constant_identifier_names
|
||||
final StartCwtch = startCwtchC.asFunction<StartCwtchFn>();
|
||||
|
||||
final utf8CwtchDir = _cwtchDir.toNativeUtf8();
|
||||
final utf8CwtchDir = cwtchDir.toNativeUtf8();
|
||||
StartCwtch(utf8CwtchDir, utf8CwtchDir.length, bundledTor.toNativeUtf8(), bundledTor.length);
|
||||
malloc.free(utf8CwtchDir);
|
||||
|
||||
|
@ -262,19 +240,17 @@ class CwtchFfi implements Cwtch {
|
|||
});
|
||||
}
|
||||
|
||||
String getAssetsDir() {
|
||||
return _assetsDir;
|
||||
}
|
||||
|
||||
Future<String> getCwtchDir() async {
|
||||
return _cwtchDir;
|
||||
// ignore: non_constant_identifier_names
|
||||
Future<void> ReconnectCwtchForeground() async {
|
||||
var reconnectCwtch = library.lookup<NativeFunction<Void Function()>>("c_ReconnectCwtchForeground");
|
||||
// ignore: non_constant_identifier_names
|
||||
final ReconnectCwtchForeground = reconnectCwtch.asFunction<void Function()>();
|
||||
ReconnectCwtchForeground();
|
||||
}
|
||||
|
||||
// Called on object being disposed to (presumably on app close) to close the isolate that's listening to libcwtch-go events
|
||||
@override
|
||||
void dispose() {
|
||||
EnvironmentConfig.debugLog("tearing down cwtch FFI isolate");
|
||||
library.close();
|
||||
cwtchIsolate.kill(priority: Isolate.immediate);
|
||||
}
|
||||
|
||||
|
@ -386,6 +362,30 @@ class CwtchFfi implements Cwtch {
|
|||
return jsonMessage;
|
||||
}
|
||||
|
||||
@override
|
||||
// ignore: non_constant_identifier_names
|
||||
void SendProfileEvent(String onion, String json) {
|
||||
var sendAppBusEvent = library.lookup<NativeFunction<string_string_to_void_function>>("c_SendProfileEvent");
|
||||
// ignore: non_constant_identifier_names
|
||||
final SendAppBusEvent = sendAppBusEvent.asFunction<StringStringFn>();
|
||||
final utf8onion = onion.toNativeUtf8();
|
||||
final utf8json = json.toNativeUtf8();
|
||||
SendAppBusEvent(utf8onion, utf8onion.length, utf8json, utf8json.length);
|
||||
malloc.free(utf8onion);
|
||||
malloc.free(utf8json);
|
||||
}
|
||||
|
||||
@override
|
||||
// ignore: non_constant_identifier_names
|
||||
void SendAppEvent(String json) {
|
||||
var sendAppBusEvent = library.lookup<NativeFunction<string_to_void_function>>("c_SendAppEvent");
|
||||
// ignore: non_constant_identifier_names
|
||||
final SendAppBusEvent = sendAppBusEvent.asFunction<StringFn>();
|
||||
final utf8json = json.toNativeUtf8();
|
||||
SendAppBusEvent(utf8json, utf8json.length);
|
||||
malloc.free(utf8json);
|
||||
}
|
||||
|
||||
@override
|
||||
// ignore: non_constant_identifier_names
|
||||
void AcceptContact(String profileOnion, int contactHandle) {
|
||||
|
@ -400,7 +400,7 @@ class CwtchFfi implements Cwtch {
|
|||
@override
|
||||
// ignore: non_constant_identifier_names
|
||||
void BlockContact(String profileOnion, int contactHandle) {
|
||||
var blockContact = library.lookup<NativeFunction<string_int_to_void_function>>("c_BlockConversation");
|
||||
var blockContact = library.lookup<NativeFunction<string_int_to_void_function>>("c_BlockContact");
|
||||
// ignore: non_constant_identifier_names
|
||||
final BlockContact = blockContact.asFunction<VoidFromStringIntFn>();
|
||||
final u1 = profileOnion.toNativeUtf8();
|
||||
|
@ -411,7 +411,7 @@ class CwtchFfi implements Cwtch {
|
|||
@override
|
||||
// ignore: non_constant_identifier_names
|
||||
void UnblockContact(String profileOnion, int contactHandle) {
|
||||
var unblockContact = library.lookup<NativeFunction<string_int_to_void_function>>("c_UnblockConversation");
|
||||
var unblockContact = library.lookup<NativeFunction<string_int_to_void_function>>("c_UnblockContact");
|
||||
// ignore: non_constant_identifier_names
|
||||
final UnblockContact = unblockContact.asFunction<VoidFromStringIntFn>();
|
||||
final u1 = profileOnion.toNativeUtf8();
|
||||
|
@ -438,7 +438,7 @@ class CwtchFfi implements Cwtch {
|
|||
@override
|
||||
// ignore: non_constant_identifier_names
|
||||
Future<dynamic> SendInvitation(String profileOnion, int contactHandle, int target) async {
|
||||
var sendInvitation = library.lookup<NativeFunction<get_json_blob_from_str_int_int_function>>("c_SendInviteMessage");
|
||||
var sendInvitation = library.lookup<NativeFunction<get_json_blob_from_str_int_int_function>>("c_SendInvitation");
|
||||
// ignore: non_constant_identifier_names
|
||||
final SendInvitation = sendInvitation.asFunction<GetJsonBlobFromStrIntIntFn>();
|
||||
final u1 = profileOnion.toNativeUtf8();
|
||||
|
@ -468,7 +468,7 @@ class CwtchFfi implements Cwtch {
|
|||
@override
|
||||
// ignore: non_constant_identifier_names
|
||||
void DownloadFile(String profileOnion, int contactHandle, String filepath, String manifestpath, String filekey) {
|
||||
var dlFile = library.lookup<NativeFunction<void_from_string_int_string_string_string_function>>("c_DownloadFileDefaultLimit");
|
||||
var dlFile = library.lookup<NativeFunction<void_from_string_int_string_string_string_function>>("c_DownloadFile");
|
||||
// ignore: non_constant_identifier_names
|
||||
final DownloadFile = dlFile.asFunction<VoidFromStringIntStringStringStringFn>();
|
||||
final u1 = profileOnion.toNativeUtf8();
|
||||
|
@ -484,7 +484,7 @@ class CwtchFfi implements Cwtch {
|
|||
|
||||
@override
|
||||
// ignore: non_constant_identifier_names
|
||||
void CreateDownloadableFile(String profileOnion, int contactHandle, String filenameSuggestion, String filekey, String manifestPath) {
|
||||
void CreateDownloadableFile(String profileOnion, int contactHandle, String filenameSuggestion, String filekey) {
|
||||
// android only - do nothing
|
||||
}
|
||||
|
||||
|
@ -509,7 +509,7 @@ class CwtchFfi implements Cwtch {
|
|||
@override
|
||||
// ignore: non_constant_identifier_names
|
||||
void VerifyOrResumeDownload(String profileOnion, int contactHandle, String filekey) {
|
||||
var fn = library.lookup<NativeFunction<void_from_string_int_string_function>>("c_VerifyOrResumeDownloadDefaultLimit");
|
||||
var fn = library.lookup<NativeFunction<void_from_string_int_string_function>>("c_VerifyOrResumeDownload");
|
||||
// ignore: non_constant_identifier_names
|
||||
final VerifyOrResumeDownload = fn.asFunction<VoidFromStringIntStringFn>();
|
||||
final u1 = profileOnion.toNativeUtf8();
|
||||
|
@ -547,12 +547,12 @@ class CwtchFfi implements Cwtch {
|
|||
@override
|
||||
// ignore: non_constant_identifier_names
|
||||
void CreateGroup(String profileOnion, String server, String groupName) {
|
||||
var createGroup = library.lookup<NativeFunction<void_from_string_string_string_function>>("c_StartGroup");
|
||||
var createGroup = library.lookup<NativeFunction<void_from_string_string_string_function>>("c_CreateGroup");
|
||||
// ignore: non_constant_identifier_names
|
||||
final CreateGroup = createGroup.asFunction<VoidFromStringStringStringFn>();
|
||||
final u1 = profileOnion.toNativeUtf8();
|
||||
final u3 = server.toNativeUtf8();
|
||||
final u2 = groupName.toNativeUtf8();
|
||||
final u2 = server.toNativeUtf8();
|
||||
final u3 = groupName.toNativeUtf8();
|
||||
CreateGroup(u1, u1.length, u2, u2.length, u3, u3.length);
|
||||
|
||||
malloc.free(u1);
|
||||
|
@ -574,7 +574,7 @@ class CwtchFfi implements Cwtch {
|
|||
@override
|
||||
// ignore: non_constant_identifier_names
|
||||
void DeleteContact(String profileOnion, int handle) {
|
||||
var deleteContact = library.lookup<NativeFunction<string_int_to_void_function>>("c_DeleteConversation");
|
||||
var deleteContact = library.lookup<NativeFunction<string_int_to_void_function>>("c_DeleteContact");
|
||||
// ignore: non_constant_identifier_names
|
||||
final DeleteContact = deleteContact.asFunction<VoidFromStringIntFn>();
|
||||
final u1 = profileOnion.toNativeUtf8();
|
||||
|
@ -628,7 +628,7 @@ class CwtchFfi implements Cwtch {
|
|||
@override
|
||||
// ignore: non_constant_identifier_names
|
||||
void SetMessageAttribute(String profile, int conversation, int channel, int message, String key, String val) {
|
||||
var setMessageAttribute = library.lookup<NativeFunction<void_from_string_int_int_int_string_string_function>>("c_UpdateMessageAttribute");
|
||||
var setMessageAttribute = library.lookup<NativeFunction<void_from_string_int_int_int_string_string_function>>("c_SetMessageAttribute");
|
||||
// ignore: non_constant_identifier_names
|
||||
final SetMessageAttribute = setMessageAttribute.asFunction<VoidFromStringIntIntIntStringStringFn>();
|
||||
final u1 = profile.toNativeUtf8();
|
||||
|
@ -763,7 +763,7 @@ class CwtchFfi implements Cwtch {
|
|||
@override
|
||||
// ignore: non_constant_identifier_names
|
||||
Future GetMessageByContentHash(String profile, int handle, String contentHash) async {
|
||||
var getMessagesByContentHashC = library.lookup<NativeFunction<get_json_blob_from_str_int_string_function>>("c_GetMessageByContentHash");
|
||||
var getMessagesByContentHashC = library.lookup<NativeFunction<get_json_blob_from_str_int_string_function>>("c_GetMessagesByContentHash");
|
||||
// ignore: non_constant_identifier_names
|
||||
final GetMessagesByContentHash = getMessagesByContentHashC.asFunction<GetJsonBlobFromStrIntStringFn>();
|
||||
final utf8profile = profile.toNativeUtf8();
|
||||
|
@ -788,6 +788,7 @@ class CwtchFfi implements Cwtch {
|
|||
|
||||
@override
|
||||
String? defaultDownloadPath() {
|
||||
|
||||
Map<String, String> envVars = Platform.environment;
|
||||
String nominalPath = path.join(envVars[Platform.isWindows ? 'UserProfile' : 'HOME']!, "Downloads");
|
||||
if (Directory(nominalPath).existsSync() == false) {
|
||||
|
@ -799,7 +800,7 @@ class CwtchFfi implements Cwtch {
|
|||
@override
|
||||
// ignore: non_constant_identifier_names
|
||||
Future<String> GetMessageByID(String profile, int handle, int index) async {
|
||||
var getMessageC = library.lookup<NativeFunction<get_json_blob_from_str_int_int_function>>("c_GetMessageById");
|
||||
var getMessageC = library.lookup<NativeFunction<get_json_blob_from_str_int_int_function>>("c_GetMessageByID");
|
||||
// ignore: non_constant_identifier_names
|
||||
final GetMessage = getMessageC.asFunction<GetJsonBlobFromStrIntIntFn>();
|
||||
final utf8profile = profile.toNativeUtf8();
|
||||
|
@ -891,7 +892,7 @@ class CwtchFfi implements Cwtch {
|
|||
|
||||
@override
|
||||
void RestartSharing(String profile, String filekey) {
|
||||
var restartSharingC = library.lookup<NativeFunction<void_from_string_string_function>>("c_RestartFileShare");
|
||||
var restartSharingC = library.lookup<NativeFunction<void_from_string_string_function>>("c_RestartSharing");
|
||||
// ignore: non_constant_identifier_names
|
||||
final RestartSharing = restartSharingC.asFunction<VoidFromStringStringFn>();
|
||||
final utf8profile = profile.toNativeUtf8();
|
||||
|
@ -903,7 +904,7 @@ class CwtchFfi implements Cwtch {
|
|||
|
||||
@override
|
||||
void StopSharing(String profile, String filekey) {
|
||||
var stopSharingC = library.lookup<NativeFunction<void_from_string_string_function>>("c_StopFileShare");
|
||||
var stopSharingC = library.lookup<NativeFunction<void_from_string_string_function>>("c_StopSharing");
|
||||
// ignore: non_constant_identifier_names
|
||||
final StopSharing = stopSharingC.asFunction<VoidFromStringStringFn>();
|
||||
final utf8profile = profile.toNativeUtf8();
|
||||
|
@ -912,227 +913,4 @@ class CwtchFfi implements Cwtch {
|
|||
malloc.free(utf8profile);
|
||||
malloc.free(ut8filekey);
|
||||
}
|
||||
|
||||
@override
|
||||
void DeleteServerInfo(String profile, String handle) {
|
||||
var deleteServerInfoC = library.lookup<NativeFunction<void_from_string_string_function>>("c_DeleteServerInfo");
|
||||
// ignore: non_constant_identifier_names
|
||||
final StopSharing = deleteServerInfoC.asFunction<VoidFromStringStringFn>();
|
||||
final utf8profile = profile.toNativeUtf8();
|
||||
final ut8handle = handle.toNativeUtf8();
|
||||
StopSharing(utf8profile, utf8profile.length, ut8handle, ut8handle.length);
|
||||
malloc.free(utf8profile);
|
||||
malloc.free(ut8handle);
|
||||
}
|
||||
|
||||
@override
|
||||
void UpdateSettings(String json) {
|
||||
var updateSettings = library.lookup<NativeFunction<string_to_void_function>>("c_UpdateSettings");
|
||||
// ignore: non_constant_identifier_names
|
||||
final UpdateSettingsFn = updateSettings.asFunction<VoidFromStringFn>();
|
||||
final u1 = json.toNativeUtf8();
|
||||
UpdateSettingsFn(u1, u1.length);
|
||||
malloc.free(u1);
|
||||
}
|
||||
|
||||
@override
|
||||
bool IsServersCompiled() {
|
||||
return library.providesSymbol("c_LoadServers");
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> SummarizeConversation(String profile, int conversation) async {
|
||||
if (!library.providesSymbol("c_Summarize")) {
|
||||
return Future.value("");
|
||||
}
|
||||
var summarize = library.lookup<NativeFunction<get_json_blob_from_str_int_function>>("c_Summarize");
|
||||
// ignore: non_constant_identifier_names
|
||||
final SummarizeFn = summarize.asFunction<GetJsonBlobFromStrIntFn>();
|
||||
final utf8profile = profile.toNativeUtf8();
|
||||
Pointer<Utf8> jsonMessageBytes = SummarizeFn(utf8profile, utf8profile.length, conversation);
|
||||
String jsonMessage = jsonMessageBytes.toDartString();
|
||||
_UnsafeFreePointerAnyUseOfThisFunctionMustBeDoubleApproved(jsonMessageBytes);
|
||||
malloc.free(utf8profile);
|
||||
return jsonMessage;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> TranslateMessage(String profile, int conversation, int message, String language) async {
|
||||
if (!library.providesSymbol("c_Translate")) {
|
||||
return Future.value("");
|
||||
}
|
||||
var translate = library.lookup<NativeFunction<get_json_blob_from_str_int_int_str_function>>("c_Translate");
|
||||
// ignore: non_constant_identifier_names
|
||||
final TranslateFn = translate.asFunction<GetJsonBlobFromStrIntIntStrFn>();
|
||||
final utf8profile = profile.toNativeUtf8();
|
||||
final utf8lang = language.toNativeUtf8();
|
||||
Pointer<Utf8> jsonMessageBytes = TranslateFn(
|
||||
utf8profile,
|
||||
utf8profile.length,
|
||||
conversation,
|
||||
message,
|
||||
utf8lang,
|
||||
utf8lang.length,
|
||||
);
|
||||
String jsonMessage = jsonMessageBytes.toDartString();
|
||||
_UnsafeFreePointerAnyUseOfThisFunctionMustBeDoubleApproved(jsonMessageBytes);
|
||||
malloc.free(utf8profile);
|
||||
malloc.free(utf8lang);
|
||||
return jsonMessage;
|
||||
}
|
||||
|
||||
@override
|
||||
bool IsBlodeuweddSupported() {
|
||||
if (library.providesSymbol("c_Translate")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String?> GetProfileAttribute(String profile, String key) {
|
||||
var getProfileAttributeC = library.lookup<NativeFunction<get_json_blob_from_str_str_function>>("c_GetProfileAttribute");
|
||||
// ignore: non_constant_identifier_names
|
||||
final GetProfileAttribute = getProfileAttributeC.asFunction<GetJsonBlobFromStrStrFn>();
|
||||
final utf8profile = profile.toNativeUtf8();
|
||||
final utf8key = key.toNativeUtf8();
|
||||
Pointer<Utf8> jsonMessageBytes = GetProfileAttribute(utf8profile, utf8profile.length, utf8key, utf8key.length);
|
||||
String jsonMessage = jsonMessageBytes.toDartString();
|
||||
_UnsafeFreePointerAnyUseOfThisFunctionMustBeDoubleApproved(jsonMessageBytes);
|
||||
malloc.free(utf8profile);
|
||||
malloc.free(utf8key);
|
||||
|
||||
try {
|
||||
dynamic attributeResult = json.decode(jsonMessage);
|
||||
if (attributeResult["Exists"]) {
|
||||
return Future.value(attributeResult["Value"]);
|
||||
}
|
||||
} catch (e) {
|
||||
EnvironmentConfig.debugLog("error getting profile attribute: $e");
|
||||
}
|
||||
|
||||
return Future.value(null);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String?> GetConversationAttribute(String profile, int conversation, String key) {
|
||||
var getConversationAttributeC = library.lookup<NativeFunction<get_json_blob_from_str_int_string_function>>("c_GetConversationAttribute");
|
||||
// ignore: non_constant_identifier_names
|
||||
final GetConversationAttribute = getConversationAttributeC.asFunction<GetJsonBlobFromStrIntStringFn>();
|
||||
final utf8profile = profile.toNativeUtf8();
|
||||
final utf8key = key.toNativeUtf8();
|
||||
Pointer<Utf8> jsonMessageBytes = GetConversationAttribute(utf8profile, utf8profile.length, conversation, utf8key, utf8key.length);
|
||||
String jsonMessage = jsonMessageBytes.toDartString();
|
||||
_UnsafeFreePointerAnyUseOfThisFunctionMustBeDoubleApproved(jsonMessageBytes);
|
||||
malloc.free(utf8profile);
|
||||
malloc.free(utf8key);
|
||||
|
||||
try {
|
||||
dynamic attributeResult = json.decode(jsonMessage);
|
||||
if (attributeResult["Exists"]) {
|
||||
return Future.value(attributeResult["Value"]);
|
||||
}
|
||||
} catch (e) {
|
||||
EnvironmentConfig.debugLog("error getting profile attribute: $e");
|
||||
}
|
||||
|
||||
return Future.value(null);
|
||||
}
|
||||
|
||||
@override
|
||||
void AttemptReconnection(String profile, String onion) {
|
||||
// ignore: non_constant_identifier_names
|
||||
var peerWithOnionC = library.lookup<NativeFunction<void_from_string_string_function>>("c_PeerWithOnion");
|
||||
final PeerWithOnionF = peerWithOnionC.asFunction<VoidFromStringStringFn>();
|
||||
final utf8profile = profile.toNativeUtf8();
|
||||
final utf8onion = onion.toNativeUtf8();
|
||||
PeerWithOnionF(utf8profile, utf8profile.length, utf8onion, utf8onion.length);
|
||||
malloc.free(utf8profile);
|
||||
malloc.free(utf8onion);
|
||||
}
|
||||
|
||||
@override
|
||||
void AttemptReconnectionServer(String profile, String onion) {
|
||||
// ignore: non_constant_identifier_names
|
||||
var queueJoinServerC = library.lookup<NativeFunction<void_from_string_string_function>>("c_QueueJoinServer");
|
||||
final QueueJoinServerC = queueJoinServerC.asFunction<VoidFromStringStringFn>();
|
||||
final utf8profile = profile.toNativeUtf8();
|
||||
final utf8onion = onion.toNativeUtf8();
|
||||
QueueJoinServerC(utf8profile, utf8profile.length, utf8onion, utf8onion.length);
|
||||
malloc.free(utf8profile);
|
||||
malloc.free(utf8onion);
|
||||
}
|
||||
|
||||
@override
|
||||
void DisconnectFromPeer(String profile, String onion) {
|
||||
// ignore: non_constant_identifier_names
|
||||
var disconnectFromPeerC = library.lookup<NativeFunction<void_from_string_string_function>>("c_DisconnectFromPeer");
|
||||
final DisconnectFromPeerC = disconnectFromPeerC.asFunction<VoidFromStringStringFn>();
|
||||
final utf8profile = profile.toNativeUtf8();
|
||||
final utf8onion = onion.toNativeUtf8();
|
||||
DisconnectFromPeerC(utf8profile, utf8profile.length, utf8onion, utf8onion.length);
|
||||
malloc.free(utf8profile);
|
||||
malloc.free(utf8onion);
|
||||
}
|
||||
|
||||
@override
|
||||
void DisconnectFromServer(String profile, String onion) {
|
||||
// ignore: non_constant_identifier_names
|
||||
var disconnectFromServerC = library.lookup<NativeFunction<void_from_string_string_function>>("c_DisconnectFromServer");
|
||||
final DisconnectFromServerC = disconnectFromServerC.asFunction<VoidFromStringStringFn>();
|
||||
final utf8profile = profile.toNativeUtf8();
|
||||
final utf8onion = onion.toNativeUtf8();
|
||||
DisconnectFromServerC(utf8profile, utf8profile.length, utf8onion, utf8onion.length);
|
||||
malloc.free(utf8profile);
|
||||
malloc.free(utf8onion);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> SearchConversations(String profile, String pattern) async {
|
||||
var searchConversationsC = library.lookup<NativeFunction<string_string_to_string_function>>("c_SearchConversations");
|
||||
// ignore: non_constant_identifier_names
|
||||
final SearchConversations = searchConversationsC.asFunction<StringFromStringStringFn>();
|
||||
final utf8profile = profile.toNativeUtf8();
|
||||
final utf8pattern = pattern.toNativeUtf8();
|
||||
EnvironmentConfig.debugLog("Searching for $profile $pattern");
|
||||
Pointer<Utf8> searchIDRaw = SearchConversations(utf8profile, utf8profile.length, utf8pattern, utf8pattern.length);
|
||||
String searchID = searchIDRaw.toDartString();
|
||||
_UnsafeFreePointerAnyUseOfThisFunctionMustBeDoubleApproved(searchIDRaw);
|
||||
malloc.free(utf8profile);
|
||||
malloc.free(utf8pattern);
|
||||
return searchID;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<HashMap<String, String>> PlatformChannelInfo() {
|
||||
return Future.value(HashMap<String, String>());
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> ConfigureConnections(String profile, bool listen, bool peers, bool servers) async {
|
||||
var configureConnections = library.lookup<NativeFunction<void_from_string_bool_bool_bool>>("c_ConfigureConnections");
|
||||
// ignore: non_constant_identifier_names
|
||||
final ConfigureConnections = configureConnections.asFunction<VoidFromStringBoolBoolBool>();
|
||||
final utf8profile = profile.toNativeUtf8();
|
||||
ConfigureConnections(utf8profile, utf8profile.length, listen, peers, servers);
|
||||
malloc.free(utf8profile);
|
||||
return;
|
||||
}
|
||||
|
||||
@override
|
||||
void PublishServerUpdate(String profile) {
|
||||
var publishServerUpdate = library.lookup<NativeFunction<string_to_void_function>>("c_PublishServerUpdate");
|
||||
// ignore: non_constant_identifier_names
|
||||
final PublishServerUpdate = publishServerUpdate.asFunction<StringFn>();
|
||||
final utf8profile = profile.toNativeUtf8();
|
||||
PublishServerUpdate(utf8profile, utf8profile.length);
|
||||
malloc.free(utf8profile);
|
||||
}
|
||||
|
||||
@override
|
||||
bool IsLoaded() {
|
||||
bool check = library.providesSymbol("c_UpdateSettings");
|
||||
EnvironmentConfig.debugLog("Checking that the FFI Interface is Correctly Loaded... $check");
|
||||
return check;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import 'dart:collection';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:cwtch/config.dart';
|
||||
|
@ -30,27 +29,9 @@ class CwtchGomobile implements Cwtch {
|
|||
late Future<dynamic> androidLibraryDir;
|
||||
late Future<dynamic> androidHomeDirectory;
|
||||
String androidHomeDirectoryStr = "";
|
||||
String _cwtchDir = "";
|
||||
late CwtchNotifier cwtchNotifier;
|
||||
bool _isL10nInit = false;
|
||||
|
||||
@override
|
||||
Future<HashMap<String, String>> PlatformChannelInfo() async {
|
||||
HashMap<String, String> info = HashMap<String, String>();
|
||||
|
||||
info.addAll({"appInfoPlatform.name": appInfoPlatform.name});
|
||||
info.addAll({"appInfoPlatform.codec": appInfoPlatform.codec.toString()});
|
||||
EnvironmentConfig.debugLog("getting foreground service info...");
|
||||
appInfoPlatform.invokeMapMethod('getForegroundServiceInfo').then((foregroundServiceInfoMap) {
|
||||
EnvironmentConfig.debugLog("parsing foreground service info...");
|
||||
foregroundServiceInfoMap?.entries.forEach((element) {
|
||||
info.addAll({element.key.toString(): element.value.toString()});
|
||||
});
|
||||
});
|
||||
EnvironmentConfig.debugLog("returning foreground service info...");
|
||||
return info;
|
||||
}
|
||||
|
||||
CwtchGomobile(CwtchNotifier _cwtchNotifier) {
|
||||
print("gomobile.dart: CwtchGomobile()");
|
||||
cwtchNotifier = _cwtchNotifier;
|
||||
|
@ -63,27 +44,23 @@ class CwtchGomobile implements Cwtch {
|
|||
appbusEventChannel.setMethodCallHandler(this._handleAppbusEvent);
|
||||
}
|
||||
|
||||
String getAssetsDir() {
|
||||
// TODO
|
||||
return "";
|
||||
}
|
||||
|
||||
// Requires Start() to have been run to initialize
|
||||
Future<String> getCwtchDir() async {
|
||||
return _cwtchDir;
|
||||
}
|
||||
|
||||
// ignore: non_constant_identifier_names
|
||||
Future<void> Start() async {
|
||||
print("gomobile.dart: Start()...");
|
||||
androidHomeDirectoryStr = (await androidHomeDirectory).path;
|
||||
_cwtchDir = path.join(androidHomeDirectoryStr, ".cwtch");
|
||||
var cwtchDir = path.join(androidHomeDirectoryStr, ".cwtch");
|
||||
if (EnvironmentConfig.BUILD_VER == dev_version) {
|
||||
_cwtchDir = path.join(_cwtchDir, "dev");
|
||||
cwtchDir = path.join(cwtchDir, "dev");
|
||||
}
|
||||
String torPath = path.join(await androidLibraryDir, "libtor.so");
|
||||
print("gomobile.dart: Start invokeMethod Start($_cwtchDir, $torPath)...");
|
||||
cwtchPlatform.invokeMethod("Start", {"appDir": _cwtchDir, "torPath": torPath});
|
||||
print("gomobile.dart: Start invokeMethod Start($cwtchDir, $torPath)...");
|
||||
return cwtchPlatform.invokeMethod("Start", {"appDir": cwtchDir, "torPath": torPath});
|
||||
}
|
||||
|
||||
@override
|
||||
// ignore: non_constant_identifier_names
|
||||
Future<void> ReconnectCwtchForeground() async {
|
||||
cwtchPlatform.invokeMethod("ReconnectCwtchForeground", {});
|
||||
}
|
||||
|
||||
// Handle libcwtch-go events (received via kotlin) and dispatch to the cwtchNotifier
|
||||
|
@ -191,9 +168,8 @@ class CwtchGomobile implements Cwtch {
|
|||
}
|
||||
|
||||
// ignore: non_constant_identifier_names
|
||||
void CreateDownloadableFile(String profileOnion, int conversation, String filenameSuggestion, String filekey, String manifestpath) {
|
||||
cwtchPlatform
|
||||
.invokeMethod("CreateDownloadableFile", {"ProfileOnion": profileOnion, "conversation": conversation, "manifestpath": manifestpath, "filename": filenameSuggestion, "filekey": filekey});
|
||||
void CreateDownloadableFile(String profileOnion, int conversation, String filenameSuggestion, String filekey) {
|
||||
cwtchPlatform.invokeMethod("CreateDownloadableFile", {"ProfileOnion": profileOnion, "conversation": conversation, "filename": filenameSuggestion, "filekey": filekey});
|
||||
}
|
||||
|
||||
// ignore: non_constant_identifier_names
|
||||
|
@ -375,108 +351,11 @@ class CwtchGomobile implements Cwtch {
|
|||
|
||||
@override
|
||||
void RestartSharing(String profile, String filekey) {
|
||||
cwtchPlatform.invokeMethod("RestartFileShare", {"ProfileOnion": profile, "filekey": filekey});
|
||||
cwtchPlatform.invokeMethod("RestartSharing", {"ProfileOnion": profile, "filekey": filekey});
|
||||
}
|
||||
|
||||
@override
|
||||
void StopSharing(String profile, String filekey) {
|
||||
cwtchPlatform.invokeMethod("StopSharing", {"ProfileOnion": profile, "filekey": filekey});
|
||||
}
|
||||
|
||||
@override
|
||||
void DeleteServerInfo(String profile, String handle) {
|
||||
cwtchPlatform.invokeMethod("DeleteServerInfo", {"ProfileOnion": profile, "handle": handle});
|
||||
}
|
||||
|
||||
@override
|
||||
void UpdateSettings(String json) {
|
||||
cwtchPlatform.invokeMethod("UpdateSettings", {"json": json});
|
||||
}
|
||||
|
||||
@override
|
||||
bool IsServersCompiled() {
|
||||
// never for android builds...
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> SummarizeConversation(String profile, int conversation) {
|
||||
// TODO: implement SummarizeConversation
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> TranslateMessage(String profile, int conversation, int message, String language) {
|
||||
// TODO: implement TranslateMessage
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
bool IsBlodeuweddSupported() {
|
||||
// Blodeuwedd is not currently supported on lower end devices.
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String?> GetProfileAttribute(String profile, String key) async {
|
||||
return await cwtchPlatform.invokeMethod("GetProfileAttribute", {"ProfileOnion": profile, "key": key}).then((dynamic json) {
|
||||
var value = jsonDecode(json);
|
||||
if (value["Exists"]) {
|
||||
return value["Value"];
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String?> GetConversationAttribute(String profile, int conversation, String key) async {
|
||||
return await cwtchPlatform.invokeMethod("GetConversationAttribute", {"ProfileOnion": profile, "conversation": conversation, "key": key}).then((dynamic json) {
|
||||
var value = jsonDecode(json);
|
||||
if (value["Exists"]) {
|
||||
return value["Value"];
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void AttemptReconnection(String profile, String onion) {
|
||||
cwtchPlatform.invokeMethod("PeerWithOnion", {"ProfileOnion": profile, "onion": onion});
|
||||
}
|
||||
|
||||
@override
|
||||
void AttemptReconnectionServer(String profile, String onion) {
|
||||
cwtchPlatform.invokeMethod("QueueJoinServer", {"ProfileOnion": profile, "onion": onion});
|
||||
}
|
||||
|
||||
@override
|
||||
void DisconnectFromPeer(String profile, String onion) {
|
||||
cwtchPlatform.invokeMethod("DisconnectFromPeer", {"ProfileOnion": profile, "onion": onion});
|
||||
}
|
||||
|
||||
@override
|
||||
void DisconnectFromServer(String profile, String onion) {
|
||||
cwtchPlatform.invokeMethod("DisconnectFromServer", {"ProfileOnion": profile, "onion": onion});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> SearchConversations(String profile, String pattern) async {
|
||||
return await cwtchPlatform.invokeMethod("SearchConversations", {"ProfileOnion": profile, "pattern": pattern});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> ConfigureConnections(String profile, bool listen, bool peers, bool servers) async {
|
||||
cwtchPlatform.invokeMethod("ConfigureConnections", {"ProfileOnion": profile, "listen": listen, "peers": peers, "servers": servers});
|
||||
return;
|
||||
}
|
||||
|
||||
@override
|
||||
void PublishServerUpdate(String profile) {
|
||||
cwtchPlatform.invokeMethod("PublishServerUpdate", {"ProfileOnion": profile});
|
||||
}
|
||||
|
||||
@override
|
||||
bool IsLoaded() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/// Flutter icons Cwtch
|
||||
/// Copyright (C) 2021-2023 by Open Privacy Research Society
|
||||
/// Copyright (C) 2021-2022 by Open Privacy Research Society
|
||||
/// This font was generated by FlutterIcon.com, which is derived from Fontello.
|
||||
///
|
||||
/// To use this font, place it in your fonts/ directory and include the
|
||||
|
@ -124,7 +124,6 @@ class CwtchIcons {
|
|||
static const IconData view_replies = IconData(0xe869, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData anti_spam_2 = IconData(0xe86b, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData manage_files = IconData(0xe86c, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData attached_file_2 = IconData(0xe86d, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData anti_spam_3 = IconData(0xe86e, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData attached_file_3 = IconData(0xe86f, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData disconnect_from_contact = IconData(0xe870, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
}
|
||||
|
|
|
@ -622,46 +622,4 @@ class MaterialLocalizationLu extends MaterialLocalizations {
|
|||
@override
|
||||
// TODO: implement menuBarMenuLabel
|
||||
String get menuBarMenuLabel => throw UnimplementedError();
|
||||
|
||||
@override
|
||||
// TODO: implement bottomSheetLabel
|
||||
String get bottomSheetLabel => throw UnimplementedError();
|
||||
|
||||
@override
|
||||
// TODO: implement currentDateLabel
|
||||
String get currentDateLabel => throw UnimplementedError();
|
||||
|
||||
@override
|
||||
// TODO: implement keyboardKeyShift
|
||||
String get keyboardKeyShift => throw UnimplementedError();
|
||||
|
||||
@override
|
||||
// TODO: implement scrimLabel
|
||||
String get scrimLabel => throw UnimplementedError();
|
||||
|
||||
@override
|
||||
String scrimOnTapHint(String modalRouteContentName) {
|
||||
// TODO: implement scrimOnTapHint
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
// TODO: implement scanTextButtonLabel
|
||||
String get scanTextButtonLabel => throw UnimplementedError();
|
||||
|
||||
@override
|
||||
// TODO: implement lookUpButtonLabel
|
||||
String get lookUpButtonLabel => throw UnimplementedError();
|
||||
|
||||
@override
|
||||
// TODO: implement menuDismissLabel
|
||||
String get menuDismissLabel => throw UnimplementedError();
|
||||
|
||||
@override
|
||||
// TODO: implement searchWebButtonLabel
|
||||
String get searchWebButtonLabel => throw UnimplementedError();
|
||||
|
||||
@override
|
||||
// TODO: implement shareButtonLabel
|
||||
String get shareButtonLabel => throw UnimplementedError();
|
||||
}
|
||||
|
|
|
@ -1,64 +1,8 @@
|
|||
{
|
||||
"@@locale": "cy",
|
||||
"@@last_modified": "2024-02-12T08:05:24+01:00",
|
||||
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
|
||||
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
|
||||
"settingsImportThemeButton": "Import Theme",
|
||||
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
|
||||
"settingsImportThemeTitle": "Import Theme",
|
||||
"settingsThemeErrorInvalid": "Error: Could not import $themeName, theme.yml missing, not a theme directory",
|
||||
"settingThemeOverwriteQuestion": "Theme $themeName already exists, confirm overwrite?",
|
||||
"settingThemeOverwriteConfirm": "Confirm",
|
||||
"settingsThemeImagesDescription": "Enable display of images from themes",
|
||||
"settingsThemeImages": "Theme Images",
|
||||
"settingsGroupAbout": "About",
|
||||
"localeUzbek": "Uzbek \/ Oʻzbekcha",
|
||||
"profileOfflineAtStart": "Appear Offline at Startup",
|
||||
"now": "Now",
|
||||
"xSecondsAgo": "$seconds seconds ago",
|
||||
"xMinutesAgo": "$minutes minutes ago",
|
||||
"xHoursAgo": "$hours hours ago",
|
||||
"xDaysAgo": "$days days ago",
|
||||
"profileAllowUnknownContacts": "Allow Unknown Contacts",
|
||||
"profileBlockUnknownContacts": "Block Unknown Contacts",
|
||||
"profileDisableProfile": "Disable Profile",
|
||||
"profileEnableProfile": "Enable Profile",
|
||||
"profileAppearOnline": "Appear Online",
|
||||
"contactDisconnect": "Disconnect from Contact (if you do not have Appear Offline set this contact may still be able to reestablish a connection to you)",
|
||||
"profileAppearOfflineDescription": "By default, when Cwtch profile is enabled it automatically attempts to connect to know contacts, and allows inbound connections. This settings disables those actions and allows you to choose, manually, which contacts to connect to.",
|
||||
"profileAppearOffline": "Appear Offline",
|
||||
"deleteServerConfirmBtn": "Mewn gwirionedd dileu gweinydd",
|
||||
"cannotDeleteServerIfActiveGroups": "There are active groups associated with this Cwtch Server. Please delete them prior to deleting this Cwtch Server entry.",
|
||||
"groupsOnThisServerLabel": "Grwpiau rydw i'n eu cynnal ar y gweinydd hwn",
|
||||
"serverinfoNoGroupInfo": "There are no groups associated with this Cwtch Server.",
|
||||
"preserveHistorySettingDescription": "By default, Cwtch will purge conversation history when Cwtch is shutdown. If this setting is enabled, Cwtch will preserve the conversation history of peer conversations.",
|
||||
"defaultPreserveHistorySetting": "Preserve Conversation History",
|
||||
"localeUk": "Ukrainian \/ українською",
|
||||
"profileEnabledDescription": "Activate or Deactivate the profile.",
|
||||
"localeSw": "Swahili \/ Kiswahili",
|
||||
"localeSv": "Swedish \/ Svenska",
|
||||
"fontScalingDescription": "Adjust the relative font scaling factor applied to text and widgets.",
|
||||
"defaultScalingText": "Testun maint rhagosodedig (ffactor graddfa:",
|
||||
"localeJa": "Japanese \/ 日本語",
|
||||
"retryConnectionTooltip": "Cwtch retries peers regularly, but you can tell Cwtch to try sooner by pushing this button.",
|
||||
"retryConnection": "Retry",
|
||||
"availabilityStatusTooltip": "Set your availability status",
|
||||
"profileInfoHint3": "Contacts will be able to see this information in Conversation Settings ",
|
||||
"profileInfoHint2": "You can add up to 3 fields.",
|
||||
"profileInfoHint": "Add some public information about yourself here e.g. blog, websites, brief bio.",
|
||||
"availabilityStatusBusy": "Busy",
|
||||
"availabilityStatusAway": "Away",
|
||||
"availabilityStatusAvailable": "Available",
|
||||
"blodeuweddWarning": "Blodeuwedd uses a local language model and a set of small auxiliary models to power its functionality. These techniques are often very effective they are not without error. \n\nWhile we have taken efforts to minimize the risk, there is still the possibility that Blodeuwedd outputs will be incorrect, hallucinated and\/or offensive.\n\nBecause of that Blodeuwedd requires downloading two additional components separate from Cwtch, the Blodeuwedd Model (or a compatible model) and the Blodeuwedd Runner. \n\nSee https:\/\/docs.cwtch.im\/docs\/settings\/experiments\/blodeuwedd for more information on obtaining these components and setting them up.",
|
||||
"blodeuweddProcessing": "Blodeuwedd is processing...",
|
||||
"blodeuweddTranslate": "Translate Message",
|
||||
"blodeuweddSummarize": "Summarize Conversation",
|
||||
"blodeuweddPath": "The directory where the Blodeuwedd is located on your computer.",
|
||||
"blodeuweddNotSupported": "This version of Cwtch has been compiled without support for the Blodeuwedd Assistant.",
|
||||
"blodeuweddDescription": "The Blodeuwedd assistant adds new features to Cwtch such as chat transcript summarization and message translation via a locally hosted language model.",
|
||||
"blodeuweddExperimentEnable": "Blodeuwedd Assistant",
|
||||
"localeKo": "Korean \/ 한국어",
|
||||
"@@last_modified": "2023-02-07T01:58:40+01:00",
|
||||
"localeSk": "Slovak \/ Slovák",
|
||||
"profileEnabledDescription": "Start or stop the profile",
|
||||
"profileAutostartDescription": "Controls if the profile will be automatically launched on startup",
|
||||
"profileEnabled": "Enable",
|
||||
"profileAutostartLabel": "Autostart",
|
||||
|
@ -129,6 +73,7 @@
|
|||
"serverMetricsLabel": "Metrigau Gweinydd",
|
||||
"manageKnownServersLong": "Rheoli Gweinyddwyr Hysbys",
|
||||
"manageKnownServersButton": "Rheoli Gweinyddwyr Hysbys",
|
||||
"groupsOnThisServerLabel": "Grwpiau rydw i'n eu cynnal ar y gweinydd hwn",
|
||||
"importLocalServerSelectText": "Dewiswch Gweinyddwr Lleol",
|
||||
"importLocalServerLabel": "Mewnforio gweinydd a letyir yn lleol",
|
||||
"enterCurrentPasswordForDeleteServer": "Rhowch y cyfrinair cyfredol i ddileu'r gweinydd hwn",
|
||||
|
@ -139,11 +84,13 @@
|
|||
"settingUIColumnLandscape": "Colofnau UI yn y Modd Tirwedd",
|
||||
"settingUIColumnPortrait": "Colofnau UI yn y Modd Portread",
|
||||
"addNewItem": "Ychwanegu eitem newydd at y rhestr",
|
||||
"defaultScalingText": "Testun maint rhagosodedig (ffactor graddfa:",
|
||||
"zoomLabel": "Chwyddo rhyngwyneb (yn effeithio ar faint testun a botymau yn bennaf)",
|
||||
"torSettingsEnabledAdvancedDescription": "Defnyddiwch wasanaeth Tor presennol ar eich system, neu newidiwch baramedrau Gwasanaeth Cwtch Tor",
|
||||
"torSettingsCustomControlPortDescription": "Defnyddiwch borthladd wedi'i deilwra ar gyfer cysylltiadau rheoli i'r dirprwy Tor",
|
||||
"torSettingsUseCustomTorServiceConfiguration": "Defnyddiwch Ffurfweddiad Gwasanaeth Custom Tor (torrc)",
|
||||
"fileSharingSettingsDownloadFolderDescription": "Pan fydd ffeiliau'n cael eu llwytho i lawr yn awtomatig (ee ffeiliau delwedd, pan fydd rhagolygon delwedd yn cael eu galluogi) mae angen lleoliad rhagosodedig i lawrlwytho'r ffeiliau iddo.",
|
||||
"deleteServerConfirmBtn": "Mewn gwirionedd dileu gweinydd",
|
||||
"deleteServerSuccess": "Wedi dileu gweinydd yn llwyddiannus",
|
||||
"enterServerPassword": "Rhowch gyfrinair i ddatgloi gweinydd",
|
||||
"unlockProfileTip": "Crëwch neu ddatgloi proffil i ddechrau!",
|
||||
|
|
|
@ -1,64 +1,8 @@
|
|||
{
|
||||
"@@locale": "da",
|
||||
"@@last_modified": "2024-02-12T08:05:24+01:00",
|
||||
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
|
||||
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
|
||||
"settingsImportThemeButton": "Import Theme",
|
||||
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
|
||||
"settingsImportThemeTitle": "Import Theme",
|
||||
"settingsThemeErrorInvalid": "Error: Could not import $themeName, theme.yml missing, not a theme directory",
|
||||
"settingThemeOverwriteQuestion": "Theme $themeName already exists, confirm overwrite?",
|
||||
"settingThemeOverwriteConfirm": "Confirm",
|
||||
"settingsThemeImagesDescription": "Enable display of images from themes",
|
||||
"settingsThemeImages": "Theme Images",
|
||||
"settingsGroupAbout": "About",
|
||||
"localeUzbek": "Uzbek \/ Oʻzbekcha",
|
||||
"profileOfflineAtStart": "Appear Offline at Startup",
|
||||
"now": "Now",
|
||||
"xSecondsAgo": "$seconds seconds ago",
|
||||
"xMinutesAgo": "$minutes minutes ago",
|
||||
"xHoursAgo": "$hours hours ago",
|
||||
"xDaysAgo": "$days days ago",
|
||||
"profileAllowUnknownContacts": "Allow Unknown Contacts",
|
||||
"profileBlockUnknownContacts": "Block Unknown Contacts",
|
||||
"profileDisableProfile": "Disable Profile",
|
||||
"profileEnableProfile": "Enable Profile",
|
||||
"profileAppearOnline": "Appear Online",
|
||||
"contactDisconnect": "Disconnect from Contact (if you do not have Appear Offline set this contact may still be able to reestablish a connection to you)",
|
||||
"profileAppearOfflineDescription": "By default, when Cwtch profile is enabled it automatically attempts to connect to know contacts, and allows inbound connections. This settings disables those actions and allows you to choose, manually, which contacts to connect to.",
|
||||
"profileAppearOffline": "Appear Offline",
|
||||
"deleteServerConfirmBtn": "Ja fjern server",
|
||||
"cannotDeleteServerIfActiveGroups": "There are active groups associated with this Cwtch Server. Please delete them prior to deleting this Cwtch Server entry.",
|
||||
"groupsOnThisServerLabel": "Grupper som jeg er vært for på denne server",
|
||||
"serverinfoNoGroupInfo": "There are no groups associated with this Cwtch Server.",
|
||||
"preserveHistorySettingDescription": "By default, Cwtch will purge conversation history when Cwtch is shutdown. If this setting is enabled, Cwtch will preserve the conversation history of peer conversations.",
|
||||
"defaultPreserveHistorySetting": "Preserve Conversation History",
|
||||
"localeUk": "Ukrainian \/ українською",
|
||||
"profileEnabledDescription": "Activate or Deactivate the profile.",
|
||||
"localeSw": "Swahili \/ Kiswahili",
|
||||
"localeSv": "Swedish \/ Svenska",
|
||||
"fontScalingDescription": "Adjust the relative font scaling factor applied to text and widgets.",
|
||||
"defaultScalingText": "Standard størrelse tekst (skaleringsfaktor:",
|
||||
"localeJa": "Japanese \/ 日本語",
|
||||
"retryConnectionTooltip": "Cwtch retries peers regularly, but you can tell Cwtch to try sooner by pushing this button.",
|
||||
"retryConnection": "Retry",
|
||||
"availabilityStatusTooltip": "Set your availability status",
|
||||
"profileInfoHint3": "Contacts will be able to see this information in Conversation Settings ",
|
||||
"profileInfoHint2": "You can add up to 3 fields.",
|
||||
"profileInfoHint": "Add some public information about yourself here e.g. blog, websites, brief bio.",
|
||||
"availabilityStatusBusy": "Busy",
|
||||
"availabilityStatusAway": "Away",
|
||||
"availabilityStatusAvailable": "Available",
|
||||
"blodeuweddWarning": "Blodeuwedd uses a local language model and a set of small auxiliary models to power its functionality. These techniques are often very effective they are not without error. \n\nWhile we have taken efforts to minimize the risk, there is still the possibility that Blodeuwedd outputs will be incorrect, hallucinated and\/or offensive.\n\nBecause of that Blodeuwedd requires downloading two additional components separate from Cwtch, the Blodeuwedd Model (or a compatible model) and the Blodeuwedd Runner. \n\nSee https:\/\/docs.cwtch.im\/docs\/settings\/experiments\/blodeuwedd for more information on obtaining these components and setting them up.",
|
||||
"blodeuweddProcessing": "Blodeuwedd is processing...",
|
||||
"blodeuweddTranslate": "Translate Message",
|
||||
"blodeuweddSummarize": "Summarize Conversation",
|
||||
"blodeuweddPath": "The directory where the Blodeuwedd is located on your computer.",
|
||||
"blodeuweddNotSupported": "This version of Cwtch has been compiled without support for the Blodeuwedd Assistant.",
|
||||
"blodeuweddDescription": "The Blodeuwedd assistant adds new features to Cwtch such as chat transcript summarization and message translation via a locally hosted language model.",
|
||||
"blodeuweddExperimentEnable": "Blodeuwedd Assistant",
|
||||
"localeKo": "Korean \/ 한국어",
|
||||
"@@last_modified": "2023-02-07T01:58:40+01:00",
|
||||
"localeSk": "Slovak \/ Slovák",
|
||||
"profileEnabledDescription": "Start or stop the profile",
|
||||
"profileAutostartDescription": "Controls if the profile will be automatically launched on startup",
|
||||
"profileEnabled": "Enable",
|
||||
"profileAutostartLabel": "Autostart",
|
||||
|
@ -191,6 +135,7 @@
|
|||
"displayNameTooltip": "Vælg et navn til præsentation",
|
||||
"manageKnownServersButton": "Administrer kendte Servere",
|
||||
"fieldDescriptionLabel": "Beskrivelse",
|
||||
"groupsOnThisServerLabel": "Grupper som jeg er vært for på denne server",
|
||||
"importLocalServerButton": "Importer %1",
|
||||
"importLocalServerSelectText": "Vælg lokal Server",
|
||||
"importLocalServerLabel": "Importer en lokalt administreret server",
|
||||
|
@ -202,6 +147,7 @@
|
|||
"fileSavedTo": "Gemt på",
|
||||
"encryptedServerDescription": "Ved at kryptere en server med et password beskytter du mod angreb fra andre brugere af denne enhed. Krypterede servere kan ikke tilgås, aflæses eller vises før det korrekte password er blevet brugt til at åbne dem.",
|
||||
"plainServerDescription": "Vi anbefaler at du beskytter dine Cwtch servere med et password. Hvis ikke du sætter et password kan alle med adgang til denne enhed indsamle information om denne server samt hente beskyttede krypteringsnøgler.",
|
||||
"deleteServerConfirmBtn": "Ja fjern server",
|
||||
"deleteServerSuccess": "Fjernede server",
|
||||
"enterCurrentPasswordForDeleteServer": "Indtast nuværende password for at fjerne denne server",
|
||||
"copyAddress": "Kopier Adresse",
|
||||
|
@ -317,6 +263,7 @@
|
|||
"viewGroupMembershipTooltip": "Se gruppe-medlemsskab",
|
||||
"loadingTor": "Åbner Tor...",
|
||||
"smallTextLabel": "Lille",
|
||||
"defaultScalingText": "Standard størrelse tekst (skaleringsfaktor:",
|
||||
"builddate": "Bygget den: %2",
|
||||
"version": "Version %1",
|
||||
"versionTor": "Version %1 med tor %2",
|
||||
|
|
|
@ -1,67 +1,11 @@
|
|||
{
|
||||
"@@locale": "de",
|
||||
"@@last_modified": "2024-02-12T08:05:24+01:00",
|
||||
"settingsExperimentsShowPerformanceTitle": "Leistungs-Overlay anzeigen",
|
||||
"settingsExperimentsShowPerformanceDescription": "Zeigt ein Overlay-Diagramm der Renderzeit an.",
|
||||
"defaultScalingText": "Text in Standardgröße (Skalierungsfaktor:",
|
||||
"deleteServerConfirmBtn": "Server wirklich löschen",
|
||||
"groupsOnThisServerLabel": "Gruppen, in denen ich bin, werden auf diesem Server gehostet",
|
||||
"profileEnabledDescription": "Starten oder Stoppen des Profils",
|
||||
"defaultPreserveHistorySetting": "Konversationsverlauf bewahren",
|
||||
"preserveHistorySettingDescription": "Standardmäßig löscht Cwtch den Gesprächsverlauf, wenn Cwtch heruntergefahren wird. Wenn diese Einstellung aktiviert ist, bewahrt Cwtch den Gesprächsverlauf von Peer-Unterhaltungen auf.",
|
||||
"serverinfoNoGroupInfo": "Es gibt keine Gruppen, die mit diesem Cwtch Server verbunden sind.",
|
||||
"cannotDeleteServerIfActiveGroups": "Es gibt aktive Gruppen, die mit diesem Cwtch Server verbunden sind. Bitte lösche diese, bevor du diesen Cwtch-Server-Eintrag löschst.",
|
||||
"profileAppearOnline": "Online erscheinen",
|
||||
"profileAppearOffline": "Offline erscheinen",
|
||||
"profileAppearOfflineDescription": "Standardmäßig wird bei aktiviertem Cwtch-Profil automatisch versucht, eine Verbindung zu bekannten Kontakten herzustellen und es werden eingehende Verbindungen zugelassen. Mit dieser Einstellung werden diese Aktionen deaktiviert und du kannst manuell auswählen, mit welchen Kontakten eine Verbindung hergestellt werden soll.",
|
||||
"contactDisconnect": "Trenne die Verbindung mit dem Kontakt (wenn du die Funktion Offline erscheinen nicht aktiviert habst, kann der Kontakt trotzdem eine Verbindung zu dir herstellen)",
|
||||
"profileEnableProfile": "Profil aktivieren",
|
||||
"profileDisableProfile": "Profil deaktivieren",
|
||||
"profileBlockUnknownContacts": "Unbekannte Kontakte blockieren",
|
||||
"profileAllowUnknownContacts": "Unbekannte Kontakte zulassen",
|
||||
"profileOfflineAtStart": "Beim Start offline erscheinen",
|
||||
"xDaysAgo": "vor $days Tagen",
|
||||
"xHoursAgo": "vor $hours Stunden",
|
||||
"xMinutesAgo": "vor $minutes Minuten",
|
||||
"xSecondsAgo": "vor $seconds Sekunden",
|
||||
"now": "Jetzt",
|
||||
"localeUzbek": "Usbekisch \/ Oʻzbekcha",
|
||||
"settingsGroupAbout": "Über",
|
||||
"settingsThemeImages": "Theme Bilder",
|
||||
"settingsThemeImagesDescription": "Aktiviere die Anzeige von Bildern aus Themes",
|
||||
"settingThemeOverwriteConfirm": "Bestätigen",
|
||||
"settingThemeOverwriteQuestion": "Theme $themeName existiert bereits, Überschreiben bestätigen?",
|
||||
"settingsThemeErrorInvalid": "Fehler: Konnte $themeName nicht importieren, theme.yml fehlt, kein Theme-Verzeichnis",
|
||||
"settingsImportThemeTitle": "Theme importieren",
|
||||
"settingsImportThemeDescription": "Wähle das Theme-Verzeichnis aus, das zur Verwendung in Cwtch importiert werden soll",
|
||||
"settingsImportThemeButton": "Theme importieren",
|
||||
"retryConnection": "Wiederholen",
|
||||
"retryConnectionTooltip": "Cwtch wiederholt die Versuche regelmäßig, aber du kannst Cwtch anweisen, es früher zu versuchen, indem du diese Taste drückst.",
|
||||
"localeJa": "Japanisch \/ 日本語",
|
||||
"fontScalingDescription": "Passe den relativen Skalierungsfaktor der Schrift an, der auf Text und Widgets angewendet wird.",
|
||||
"localeSv": "Schwedisch \/ Svenska",
|
||||
"localeSw": "Suaheli \/ Kiswahili",
|
||||
"localeUk": "Ukrainisch \/ українською",
|
||||
"blodeuweddExperimentEnable": "Blodeuwedd Assistent",
|
||||
"blodeuweddDescription": "Der Blodeuwedd-Assistent erweitert Cwtch um neue Funktionen wie die Zusammenfassung von Chat-Transkripten und die Übersetzung von Nachrichten über ein lokal gehostetes Sprachmodell.",
|
||||
"blodeuweddNotSupported": "Diese Version von Cwtch wurde ohne Unterstützung für den Blodeuwedd-Assistenten kompiliert.",
|
||||
"blodeuweddPath": "Das Verzeichnis, in dem sich der Blodeuwedd auf deinem Computer befindet.",
|
||||
"blodeuweddSummarize": "Konversationszusammenfassung",
|
||||
"blodeuweddTranslate": "Nachricht übersetzen",
|
||||
"blodeuweddProcessing": "Blodeuwedd verarbeitet...",
|
||||
"blodeuweddWarning": "Blodeuwedd verwendet ein lokales Sprachmodell und eine Reihe von kleinen Hilfsmodellen, um seine Funktionalität zu gewährleisten. Diese Techniken sind oft sehr effektiv, aber nicht fehlerfrei. \n\nObwohl wir uns bemüht haben, das Risiko zu minimieren, besteht immer noch die Möglichkeit, dass die Ausgaben von Blodeuwedd falsch, halluziniert und\/oder beleidigend sind.\n\nAus diesem Grund müssen für Blodeuwedd zwei zusätzliche Komponenten separat von Cwtch heruntergeladen werden: das Blodeuwedd-Modell (oder ein kompatibles Modell) und der Blodeuwedd-Runner. \n\nUnter https:\/\/docs.cwtch.im\/docs\/settings\/experiments\/blodeuwedd findest du weitere Informationen über den Bezug dieser Komponenten und deren Einrichtung.",
|
||||
"availabilityStatusAvailable": "Verfügbar",
|
||||
"availabilityStatusAway": "Abwesend",
|
||||
"availabilityStatusBusy": "Beschäftigt",
|
||||
"availabilityStatusTooltip": "Stelle deinen Verfügbarkeitsstatus ein",
|
||||
"profileInfoHint": "Füge hier einige öffentliche Informationen über dich selbst hinzu, z. B. Blog, Websites, Kurzbiografie.",
|
||||
"profileInfoHint3": "Kontakte können diese Informationen in den Konversationseinstellungen sehen.",
|
||||
"profileInfoHint2": "Du kannst bis zu 3 Felder hinzufügen.",
|
||||
"localeSk": "Slowakisch \/ Slovák",
|
||||
"localeKo": "Koreanisch \/ 한국어",
|
||||
"@@last_modified": "2023-02-07T01:58:40+01:00",
|
||||
"localeSk": "Slovak \/ Slovák",
|
||||
"profileAutostartLabel": "Autostart",
|
||||
"profileEnabled": "Aktivieren",
|
||||
"profileAutostartDescription": "Legt fest, ob das Profil beim Starten automatisch gestartet wird",
|
||||
"profileEnabledDescription": "Starten oder Stoppen des Profils",
|
||||
"acquiringTicketsFromServer": "Antispam-Herausforderung meistern",
|
||||
"acquiredTicketsFromServer": "Antispam-Herausforderung abgeschlossen",
|
||||
"shareProfileMenuTooltop": "Profil teilen über...",
|
||||
|
@ -200,6 +144,7 @@
|
|||
"version": "Version %1",
|
||||
"versionTor": "Version %1 mit Tor %2",
|
||||
"builddate": "Erstellt am: %2",
|
||||
"defaultScalingText": "Text in Standardgröße (Skalierungsfaktor:",
|
||||
"smallTextLabel": "Klein",
|
||||
"viewGroupMembershipTooltip": "Gruppenmitgliedschaft anzeigen",
|
||||
"loadingTor": "Tor wird geladen...",
|
||||
|
@ -317,6 +262,7 @@
|
|||
"copyAddress": "Adresse kopieren",
|
||||
"enterCurrentPasswordForDeleteServer": "Bitte gib das aktuelle Passwort ein, um diesen Server zu löschen",
|
||||
"deleteServerSuccess": "Server erfolgreich gelöscht",
|
||||
"deleteServerConfirmBtn": "Server wirklich löschen",
|
||||
"plainServerDescription": "Wir empfehlen, dass du deinen Cwtch-Server mit einem Passwort schützst. Wenn Du diesen Server nicht mit einem Kennwort versiehst, kann jeder, der Zugang zu diesem Gerät hat, auf Informationen über diesen Server zugreifen, einschließlich sensibler kryptografischer Schlüssel.",
|
||||
"encryptedServerDescription": "Das Verschlüsseln eines Servers mit einem Kennwort schützt ihn vor anderen Personen, die dieses Gerät ebenfalls benutzen könnten. Verschlüsselte Server können nicht entschlüsselt, angezeigt oder aufgerufen werden, bis das richtige Kennwort eingegeben wird, um sie zu entsperren.",
|
||||
"fileSavedTo": "Gesichert in",
|
||||
|
@ -328,6 +274,7 @@
|
|||
"importLocalServerLabel": "Importieren eines lokal gehosteten Servers",
|
||||
"importLocalServerSelectText": "Lokalen Server auswählen",
|
||||
"importLocalServerButton": "%1 importieren",
|
||||
"groupsOnThisServerLabel": "Gruppen, in denen ich bin, werden auf diesem Server gehostet",
|
||||
"fieldDescriptionLabel": "Beschreibung",
|
||||
"manageKnownServersButton": "Bekannte Server verwalten",
|
||||
"displayNameTooltip": "Bitte gib einen Anzeigenamen ein",
|
||||
|
|
|
@ -1,64 +1,8 @@
|
|||
{
|
||||
"@@locale": "el",
|
||||
"@@last_modified": "2024-02-12T08:05:24+01:00",
|
||||
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
|
||||
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
|
||||
"settingsImportThemeButton": "Import Theme",
|
||||
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
|
||||
"settingsImportThemeTitle": "Import Theme",
|
||||
"settingsThemeErrorInvalid": "Error: Could not import $themeName, theme.yml missing, not a theme directory",
|
||||
"settingThemeOverwriteQuestion": "Theme $themeName already exists, confirm overwrite?",
|
||||
"settingThemeOverwriteConfirm": "Confirm",
|
||||
"settingsThemeImagesDescription": "Enable display of images from themes",
|
||||
"settingsThemeImages": "Theme Images",
|
||||
"settingsGroupAbout": "About",
|
||||
"localeUzbek": "Uzbek \/ Oʻzbekcha",
|
||||
"profileOfflineAtStart": "Appear Offline at Startup",
|
||||
"now": "Now",
|
||||
"xSecondsAgo": "$seconds seconds ago",
|
||||
"xMinutesAgo": "$minutes minutes ago",
|
||||
"xHoursAgo": "$hours hours ago",
|
||||
"xDaysAgo": "$days days ago",
|
||||
"profileAllowUnknownContacts": "Allow Unknown Contacts",
|
||||
"profileBlockUnknownContacts": "Block Unknown Contacts",
|
||||
"profileDisableProfile": "Disable Profile",
|
||||
"profileEnableProfile": "Enable Profile",
|
||||
"profileAppearOnline": "Appear Online",
|
||||
"contactDisconnect": "Disconnect from Contact (if you do not have Appear Offline set this contact may still be able to reestablish a connection to you)",
|
||||
"profileAppearOfflineDescription": "By default, when Cwtch profile is enabled it automatically attempts to connect to know contacts, and allows inbound connections. This settings disables those actions and allows you to choose, manually, which contacts to connect to.",
|
||||
"profileAppearOffline": "Appear Offline",
|
||||
"deleteServerConfirmBtn": "Really Delete Server?",
|
||||
"cannotDeleteServerIfActiveGroups": "There are active groups associated with this Cwtch Server. Please delete them prior to deleting this Cwtch Server entry.",
|
||||
"groupsOnThisServerLabel": "Known Groups on this Cwtch Server",
|
||||
"serverinfoNoGroupInfo": "There are no groups associated with this Cwtch Server.",
|
||||
"preserveHistorySettingDescription": "By default, Cwtch will purge conversation history when Cwtch is shutdown. If this setting is enabled, Cwtch will preserve the conversation history of peer conversations.",
|
||||
"defaultPreserveHistorySetting": "Preserve Conversation History",
|
||||
"localeUk": "Ukrainian \/ українською",
|
||||
"profileEnabledDescription": "Activate or Deactivate the profile.",
|
||||
"localeSw": "Swahili \/ Kiswahili",
|
||||
"localeSv": "Swedish \/ Svenska",
|
||||
"fontScalingDescription": "Adjust the relative font scaling factor applied to text and widgets.",
|
||||
"defaultScalingText": "Font Scaling",
|
||||
"localeJa": "Japanese \/ 日本語",
|
||||
"retryConnectionTooltip": "Cwtch retries peers regularly, but you can tell Cwtch to try sooner by pushing this button.",
|
||||
"retryConnection": "Retry",
|
||||
"availabilityStatusTooltip": "Set your availability status",
|
||||
"profileInfoHint3": "Contacts will be able to see this information in Conversation Settings ",
|
||||
"profileInfoHint2": "You can add up to 3 fields.",
|
||||
"profileInfoHint": "Add some public information about yourself here e.g. blog, websites, brief bio.",
|
||||
"availabilityStatusBusy": "Busy",
|
||||
"availabilityStatusAway": "Away",
|
||||
"availabilityStatusAvailable": "Available",
|
||||
"blodeuweddWarning": "Blodeuwedd uses a local language model and a set of small auxiliary models to power its functionality. These techniques are often very effective they are not without error. \n\nWhile we have taken efforts to minimize the risk, there is still the possibility that Blodeuwedd outputs will be incorrect, hallucinated and\/or offensive.\n\nBecause of that Blodeuwedd requires downloading two additional components separate from Cwtch, the Blodeuwedd Model (or a compatible model) and the Blodeuwedd Runner. \n\nSee https:\/\/docs.cwtch.im\/docs\/settings\/experiments\/blodeuwedd for more information on obtaining these components and setting them up.",
|
||||
"blodeuweddProcessing": "Blodeuwedd is processing...",
|
||||
"blodeuweddTranslate": "Translate Message",
|
||||
"blodeuweddSummarize": "Summarize Conversation",
|
||||
"blodeuweddPath": "The directory where the Blodeuwedd is located on your computer.",
|
||||
"blodeuweddNotSupported": "This version of Cwtch has been compiled without support for the Blodeuwedd Assistant.",
|
||||
"blodeuweddDescription": "The Blodeuwedd assistant adds new features to Cwtch such as chat transcript summarization and message translation via a locally hosted language model.",
|
||||
"blodeuweddExperimentEnable": "Blodeuwedd Assistant",
|
||||
"localeKo": "Korean \/ 한국어",
|
||||
"@@last_modified": "2023-02-07T01:58:40+01:00",
|
||||
"localeSk": "Slovak \/ Slovák",
|
||||
"profileEnabledDescription": "Start or stop the profile",
|
||||
"profileAutostartDescription": "Controls if the profile will be automatically launched on startup",
|
||||
"profileEnabled": "Enable",
|
||||
"profileAutostartLabel": "Autostart",
|
||||
|
@ -234,9 +178,11 @@
|
|||
"experimentClickableLinksDescription": "The clickable links experiment allows you to click on URLs shared in messages",
|
||||
"enableExperimentClickableLinks": "Enable Clickable Links",
|
||||
"serverMetricsLabel": "Server Metrics",
|
||||
"groupsOnThisServerLabel": "Groups I am in hosted on this server",
|
||||
"importLocalServerButton": "Import %1",
|
||||
"encryptedServerDescription": "Encrypting a server with a password protects it from other people who may also use this device. Encrypted servers cannot be decrypted, displayed or accessed until the correct password is entered to unlock them.",
|
||||
"plainServerDescription": "We recommend that you protect your Cwtch servers with a password. If you do not set a password on this server then anyone who has access to this device may be able to access information about this server, including sensitive cryptographic keys.",
|
||||
"deleteServerConfirmBtn": "Really delete server",
|
||||
"settingServersDescription": "The hosting servers experiment enables hosting and managing Cwtch servers",
|
||||
"settingServers": "Hosting Servers",
|
||||
"unlockProfileTip": "Please create or unlock a profile to begin!",
|
||||
|
@ -321,6 +267,7 @@
|
|||
"viewGroupMembershipTooltip": "View Group Membership",
|
||||
"loadingTor": "Loading tor...",
|
||||
"smallTextLabel": "Small",
|
||||
"defaultScalingText": "Default size text (scale factor:",
|
||||
"builddate": "Built on: %2",
|
||||
"version": "Version %1",
|
||||
"versionTor": "Version %1 with tor %2",
|
||||
|
|