Compare commits

..

5 Commits

Author SHA1 Message Date
Dan Ballard 5ee6a121d7 fix PRODUCT_BUNDLE_IDENTIFIER to im.cwtch.ui 2021-08-12 17:14:52 -07:00
Dan Ballard de1d74a6c3 README update about Mac 2021-08-06 19:16:30 -07:00
Linus Gasser 3ea37d6c1f Thanks @Pleurinae for pointing out it's a static library... And it needs to be included somewhere in a call. 2021-08-06 19:13:05 -07:00
Linus Gasser 17f3bcbace dan's comment. Also added Makefile and ios/Podfile* 2021-08-06 19:12:55 -07:00
Linus Gasser 9034e3e73d First try at getting an iOS build ready
This is a draft PR!

It allows anybody interested to help me debug why I get `no matching architecture in universal wrapper`
2021-08-06 19:05:30 -07:00
37 changed files with 438 additions and 408 deletions

View File

@ -24,7 +24,7 @@ steps:
- git checkout $DRONE_COMMIT
- name: fetch
image: cirrusci/flutter:2.5.0-6.0.pre
image: cirrusci/flutter:dev
volumes:
- name: deps
path: /root/.pub-cache
@ -47,7 +47,7 @@ steps:
# #Todo: fix all the lint errors and add `-set_exit_status` above to enforce linting
- name: build-linux
image: openpriv/flutter-desktop:linux-fdev2.5rc
image: openpriv/flutter-desktop:linux-dev
volumes:
- name: deps
path: /root/.pub-cache
@ -61,7 +61,7 @@ steps:
- rm -r cwtch
- name: test-build-android
image: cirrusci/flutter:2.5.0-6.0.pre
image: cirrusci/flutter:dev
when:
event: pull_request
volumes:
@ -71,7 +71,7 @@ steps:
- flutter build apk --debug
- name: build-android
image: cirrusci/flutter:2.5.0-6.0.pre
image: cirrusci/flutter:dev
when:
event: push
environment:
@ -95,7 +95,7 @@ steps:
#- cp build/app/outputs/flutter-apk/app-debug.apk deploy/android
- name: widget-tests
image: cirrusci/flutter:2.5.0-6.0.pre
image: cirrusci/flutter:dev
volumes:
- name: deps
path: /root/.pub-cache
@ -126,7 +126,7 @@ steps:
- mv ./../sha256s.txt .
- cd ..
# TODO: do deployment once files actaully compile
- scp -r -o StrictHostKeyChecking=no -i ~/id_rsa $DIR buildfiles@build.openprivacy.ca:/home/buildfiles/buildfiles/
- scp -r -o StrictHostKeyChecking=no -i ~/id_rsa $DIR buildfiles@openprivacy.ca:/home/buildfiles/buildfiles/
- name: notify-email
image: drillster/drone-email
@ -175,7 +175,7 @@ clone:
steps:
- name: clone
image: openpriv/flutter-desktop:windows-sdk30-fdev2.5rc
image: openpriv/flutter-desktop:windows-sdk30-fdev2.3rc
environment:
buildbot_key_b64:
from_secret: buildbot_key_b64
@ -193,16 +193,16 @@ steps:
- git checkout $Env:DRONE_COMMIT
- name: fetch
image: openpriv/flutter-desktop:windows-sdk30-fdev2.5rc
image: openpriv/flutter-desktop:windows-sdk30-fdev2.3rc
commands:
- powershell -command "Invoke-WebRequest -Uri https://git.openprivacy.ca/openprivacy/buildfiles/raw/branch/master/tor/tor-win64-0.4.6.5.zip -OutFile tor.zip"
- powershell -command "Invoke-WebRequest -Uri https://dist.torproject.org/torbrowser/10.5a17/tor-win64-0.4.6.5.zip -OutFile tor.zip"
- powershell -command "if ((Get-FileHash tor.zip -Algorithm sha512).Hash -ne '7917561a7a063440a1ddfa9cb544ab9ffd09de84cea3dd66e3cc9cd349dd9f85b74a522ec390d7a974bc19b424c4d53af60e57bbc47e763d13cab6a203c4592f' ) { Write-Error 'tor.zip sha512sum mismatch' }"
- git describe --tags --abbrev=1 > VERSION
- powershell -command "Get-Date -Format 'yyyy-MM-dd-HH-mm'" > BUILDDATE
- .\fetch-libcwtch-go.ps1
- name: build-windows
image: openpriv/flutter-desktop:windows-sdk30-fdev2.5rc
image: openpriv/flutter-desktop:windows-sdk30-fdev2.3rc
commands:
- flutter pub get
- $Env:version += type .\VERSION
@ -213,9 +213,9 @@ steps:
# 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:\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 C:\BuildTools\VC\Redist\MSVC\14.29.30036\x64\Microsoft.VC142.CRT\vcruntime140.dll $Env:releasedir
- copy C:\BuildTools\VC\Redist\MSVC\14.29.30036\x64\Microsoft.VC142.CRT\vcruntime140_1.dll $Env:releasedir
- copy C:\BuildTools\VC\Redist\MSVC\14.29.30036\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"
@ -258,7 +258,7 @@ steps:
- move *.sha512 deploy\$Env:builddir
- name: deploy-windows
image: openpriv/flutter-desktop:windows-sdk30-fdev2.5rc
image: openpriv/flutter-desktop:windows-sdk30-fdev2.3rc
when:
event: push
status: [ success ]
@ -268,7 +268,7 @@ steps:
commands:
- echo $Env:BUILDFILES_KEY > id_rsab64
- certutil -decode id_rsab64 id_rsa
- scp -r -o StrictHostKeyChecking=no -i id_rsa deploy\\* buildfiles@build.openprivacy.ca:/home/buildfiles/buildfiles/
- scp -r -o StrictHostKeyChecking=no -i id_rsa deploy\\* buildfiles@openprivacy.ca:/home/buildfiles/buildfiles/
trigger:
repo: cwtch.im/cwtch-ui

4
.gitignore vendored
View File

@ -44,4 +44,6 @@ libCwtch.so
android/cwtch/cwtch.aar
coverage
test/failures
.gradle
.gradle
libcwtch-go
ios/cwtch.a

View File

@ -1 +1 @@
v1.1.1-16-g7376218-2021-08-25-16-54
v1.1.0-2021-07-15-19-15

View File

@ -46,6 +46,23 @@ You will probably want to disable Analytics on the Flutter Tool: `flutter config
- Follow the steps above to fetch `libCwtch-go` and `tor` (these will fetch Android versions of these binaries also)
- run `flutter run` with an Android phone connect via USB (or some other valid debug mode)
### Building on Mac (for Mac)
Currently unsupported but we are investigating support for this platform.
### Building Experimental iOS
iOS builds of cwtch-ui is currently experimental and does not have the full support other platforms do. We are working on making it buildable for developers to experiment with for now.
We currently do not auto build iOS libCwtch-go libraries so you'll need to make your own:
- `git clone https://git.openprivacy.ca/cwtch.im/libcwtch-go.git`
- `cd libcwtch-go`
- `make ios`
- `cp ios/cwtch.a ../ios`
then you should be able to build with flutter in the project root
### Known Platform Issues
- **Windows**: Flutter engine has a [known bug](https://github.com/flutter/flutter/issues/75675) around the Right Shift key being sticky.

View File

@ -1,6 +1,6 @@
Invoke-WebRequest -Uri https://git.openprivacy.ca/openprivacy/buildfiles/raw/branch/master/tor/tor-win64-0.4.6.5.zip -OutFile tor.zip
Invoke-WebRequest -Uri https://dist.torproject.org/torbrowser/10.0.18/tor-win64-0.4.5.9.zip -OutFile tor.zip
if ((Get-FileHash tor.zip -Algorithm sha512).Hash -ne '7917561a7a063440a1ddfa9cb544ab9ffd09de84cea3dd66e3cc9cd349dd9f85b74a522ec390d7a974bc19b424c4d53af60e57bbc47e763d13cab6a203c4592f' ) { Write-Error 'tor.zip sha512sum mismatch' }
if ((Get-FileHash tor.zip -Algorithm sha512).Hash -ne '72764eb07ad8ab511603aba0734951ca003989f5f4686af91ba220217b4a8a4bcc5f571b59f52c847932f6efedf847b111621983050fcddbb8099d43ca66fb07' ) { Write-Error 'tor.zip sha512sum mismatch' }
Expand-Archive -Path tor.zip -DestinationPath Tor

View File

@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"

View File

@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"

41
ios/Podfile Normal file
View File

@ -0,0 +1,41 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '9.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}
def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end
File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
flutter_ios_podfile_setup
target 'Runner' do
use_frameworks!
use_modular_headers!
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
end
end

34
ios/Podfile.lock Normal file
View File

@ -0,0 +1,34 @@
PODS:
- Flutter (1.0.0)
- integration_test (0.0.1):
- Flutter
- package_info_plus (0.4.5):
- Flutter
- path_provider (0.0.1):
- Flutter
DEPENDENCIES:
- Flutter (from `Flutter`)
- integration_test (from `.symlinks/plugins/integration_test/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider (from `.symlinks/plugins/path_provider/ios`)
EXTERNAL SOURCES:
Flutter:
:path: Flutter
integration_test:
:path: ".symlinks/plugins/integration_test/ios"
package_info_plus:
:path: ".symlinks/plugins/package_info_plus/ios"
path_provider:
:path: ".symlinks/plugins/path_provider/ios"
SPEC CHECKSUMS:
Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c
integration_test: 5ed24a436eb7ec17b6a13046e9bf7ca4a404e59e
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
COCOAPODS: 1.10.1

View File

@ -3,16 +3,19 @@
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objectVersion = 51;
objects = {
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
57A4E41C4075DFE2289DBB05 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 261C176807F4755F8CA98C09 /* Pods_Runner.framework */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
F40D366C264E52D500E39EB5 /* cwtch.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F40D366B264E52D500E39EB5 /* cwtch.a */; };
F40D366D264E52E000E39EB5 /* cwtch.a in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = F40D366B264E52D500E39EB5 /* cwtch.a */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
@ -22,6 +25,7 @@
dstPath = "";
dstSubfolderSpec = 10;
files = (
F40D366D264E52E000E39EB5 /* cwtch.a in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
@ -31,10 +35,14 @@
/* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
261C176807F4755F8CA98C09 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
64918BCEC462F1E92AB7F67B /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
740C510F980AE42EF566C125 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
7FA189B93C9B7C07B497D28E /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
@ -42,6 +50,9 @@
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
F40D366B264E52D500E39EB5 /* cwtch.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = cwtch.a; path = "../libcwtch-go/ios/cwtch.a"; sourceTree = "<group>"; };
F46DFE4E2648741800B3B0AF /* x86_64.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = x86_64.a; path = "../../libcwtch-go/ios/x86_64.a"; sourceTree = "<group>"; };
F46DFE552648764D00B3B0AF /* cwtch.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = cwtch.h; path = "../../../libcwtch-go/ios/cwtch.h"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -49,12 +60,24 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
57A4E41C4075DFE2289DBB05 /* Pods_Runner.framework in Frameworks */,
F40D366C264E52D500E39EB5 /* cwtch.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
2138F07C93FA9B782F154211 /* Pods */ = {
isa = PBXGroup;
children = (
7FA189B93C9B7C07B497D28E /* Pods-Runner.debug.xcconfig */,
64918BCEC462F1E92AB7F67B /* Pods-Runner.release.xcconfig */,
740C510F980AE42EF566C125 /* Pods-Runner.profile.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
@ -69,9 +92,12 @@
97C146E51CF9000F007C117D = {
isa = PBXGroup;
children = (
F40D366B264E52D500E39EB5 /* cwtch.a */,
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
2138F07C93FA9B782F154211 /* Pods */,
F100A7439BFD0DC2EBAE6F27 /* Frameworks */,
);
sourceTree = "<group>";
};
@ -86,6 +112,7 @@
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
F46DFE552648764D00B3B0AF /* cwtch.h */,
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
@ -98,6 +125,15 @@
path = Runner;
sourceTree = "<group>";
};
F100A7439BFD0DC2EBAE6F27 /* Frameworks */ = {
isa = PBXGroup;
children = (
F46DFE4E2648741800B3B0AF /* x86_64.a */,
261C176807F4755F8CA98C09 /* Pods_Runner.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@ -105,12 +141,14 @@
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
E78347C5305EEDBB6E990583 /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
6A2F1B96AB8B734802E64441 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
@ -127,7 +165,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1020;
LastUpgradeCheck = 1250;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
@ -183,6 +221,23 @@
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
};
6A2F1B96AB8B734802E64441 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@ -197,6 +252,28 @@
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
E78347C5305EEDBB6E990583 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@ -254,6 +331,7 @@
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
@ -272,7 +350,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@ -285,6 +363,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ARCHS = x86_64;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
@ -294,15 +373,21 @@
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
"$(PROJECT_DIR)",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.flutterApp;
PRODUCT_BUNDLE_IDENTIFIER = im.cwtch.ui;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_WORKSPACE = YES;
VERSIONING_SYSTEM = "apple-generic";
};
name = Profile;
@ -330,6 +415,7 @@
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
@ -354,7 +440,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@ -385,6 +471,7 @@
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
@ -403,11 +490,12 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
@ -417,6 +505,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ARCHS = x86_64;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
@ -426,16 +515,22 @@
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
"$(PROJECT_DIR)",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.flutterApp;
PRODUCT_BUNDLE_IDENTIFIER = im.cwtch.ui;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_WORKSPACE = YES;
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
@ -444,6 +539,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ARCHS = x86_64;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
@ -453,15 +549,21 @@
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
"$(PROJECT_DIR)",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.flutterApp;
PRODUCT_BUNDLE_IDENTIFIER = im.cwtch.ui;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_WORKSPACE = YES;
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;

View File

@ -2,6 +2,6 @@
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
location = "self:">
</FileRef>
</Workspace>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1020"
LastUpgradeVersion = "1250"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@ -27,8 +27,6 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
@ -38,8 +36,8 @@
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
@ -61,8 +59,6 @@
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Profile"
@ -88,4 +84,4 @@
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
</Scheme>

View File

@ -4,4 +4,7 @@
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

View File

@ -10,4 +10,10 @@ import Flutter
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
// this is never called, but otherwise Xcode will optimize away the cwtch.a library
// and not include it in the final binary...
public func dummyMethod(){
c_ACNEvents()
}
}

View File

@ -1 +1,2 @@
#import "GeneratedPluginRegistrant.h"
#import "cwtch.h"

View File

@ -4,6 +4,7 @@ import 'dart:io';
import 'dart:isolate';
import 'dart:io' show Platform;
import 'package:cwtch/cwtch/cwtchNotifier.dart';
import 'package:flutter/src/services/text_input.dart';
import 'package:path/path.dart' as path;
import 'package:ffi/ffi.dart';
@ -21,9 +22,6 @@ typedef StartCwtchFn = int Function(Pointer<Utf8> dir, int len, Pointer<Utf8> to
typedef void_from_void_funtion = Void Function();
typedef VoidFromVoidFunction = void Function();
typedef free_function = Void Function(Pointer<Utf8>);
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);
@ -36,15 +34,25 @@ typedef VoidFromStringStringStringStringFn = void Function(Pointer<Utf8>, int, P
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 access_cwtch_eventbus_function = Void Function();
typedef NextEventFn = void Function();
typedef string_to_void_function = Void Function(Pointer<Utf8> str, Int32 length);
typedef StringFn = void Function(Pointer<Utf8> dir, int);
typedef string_string_to_void_function = Void Function(Pointer<Utf8> str, Int32 length, Pointer<Utf8> str2, Int32 length2);
typedef StringStringFn = void Function(Pointer<Utf8>, int, Pointer<Utf8>, int);
typedef get_json_blob_void_function = Pointer<Utf8> Function();
typedef GetJsonBlobVoidFn = Pointer<Utf8> Function();
typedef get_json_blob_string_function = Pointer<Utf8> Function(Pointer<Utf8> str, Int32 length);
typedef GetJsonBlobStringFn = Pointer<Utf8> Function(Pointer<Utf8> str, int len);
//func NumMessages(profile_ptr *C.char, profile_len C.int, handle_ptr *C.char, handle_len C.int) (n C.int) {
typedef get_int_from_str_str_function = Int32 Function(Pointer<Utf8>, Int32, Pointer<Utf8>, Int32);
typedef GetIntFromStrStrFn = int Function(Pointer<Utf8>, int, Pointer<Utf8>, int);
//func GetMessage(profile_ptr *C.char, profile_len C.int, handle_ptr *C.char, handle_len C.int, message_index C.int) *C.char {
typedef get_json_blob_from_str_str_int_function = Pointer<Utf8> Function(Pointer<Utf8>, Int32, Pointer<Utf8>, Int32, Int32);
typedef GetJsonBlobFromStrStrIntFn = Pointer<Utf8> Function(Pointer<Utf8>, int, Pointer<Utf8>, int, int);
@ -67,6 +75,8 @@ class CwtchFfi implements Cwtch {
library = DynamicLibrary.open("libCwtch.dll");
} else if (Platform.isLinux) {
library = DynamicLibrary.open("libCwtch.so");
} else if (Platform.isIOS) {
library = DynamicLibrary.process();
} else {
print("OS ${Platform.operatingSystem} not supported by cwtch/ffi");
// emergency, ideally the app stays on splash and just posts the error till user closes
@ -130,7 +140,9 @@ class CwtchFfi implements Cwtch {
// Called on object being disposed to (presumably on app close) to close the isolate that's listening to libcwtch-go events
@override
void dispose() {
cwtchIsolate.kill(priority: Isolate.immediate);
if (cwtchIsolate != null) {
cwtchIsolate.kill(priority: Isolate.immediate);
}
}
// Entry point for an isolate to listen to a stream of events pulled from libcwtch-go and return them on the sendPort
@ -155,21 +167,9 @@ class CwtchFfi implements Cwtch {
// ignore: non_constant_identifier_names
final GetAppbusEvent = getAppbusEventC.asFunction<AppbusEventsFn>();
// Embedded Version of _UnsafeFreePointerAnyUseOfThisFunctionMustBeDoubleApproved
var free = library.lookup<NativeFunction<free_function>>("c_FreePointer");
final Free = free.asFunction<FreeFn>();
// ignore: non_constant_identifier_names
final GetAppBusEvent = () {
// ignore: non_constant_identifier_names
while (true) {
Pointer<Utf8> result = GetAppbusEvent();
String event = result.toDartString();
Free(result);
return event;
};
while (true) {
final event = GetAppBusEvent();
if (event.startsWith("{\"EventType\":\"Shutdown\"")) {
print("Shutting down isolate thread: $event");
@ -186,7 +186,6 @@ class CwtchFfi implements Cwtch {
final SelectProfile = selectProfileC.asFunction<GetJsonBlobStringFn>();
final ut8Onion = onion.toNativeUtf8();
SelectProfile(ut8Onion, ut8Onion.length);
malloc.free(ut8Onion);
}
// ignore: non_constant_identifier_names
@ -197,8 +196,6 @@ class CwtchFfi implements Cwtch {
final utf8nick = nick.toNativeUtf8();
final ut8pass = pass.toNativeUtf8();
CreateProfile(utf8nick, utf8nick.length, ut8pass, ut8pass.length);
malloc.free(utf8nick);
malloc.free(ut8pass);
}
// ignore: non_constant_identifier_names
@ -208,7 +205,6 @@ class CwtchFfi implements Cwtch {
final LoadProfiles = loadProfileC.asFunction<StringFn>();
final ut8pass = pass.toNativeUtf8();
LoadProfiles(ut8pass, ut8pass.length);
malloc.free(ut8pass);
}
// ignore: non_constant_identifier_names
@ -220,9 +216,6 @@ class CwtchFfi implements Cwtch {
final utf8handle = handle.toNativeUtf8();
Pointer<Utf8> jsonMessageBytes = GetMessage(utf8profile, utf8profile.length, utf8handle, utf8handle.length, index);
String jsonMessage = jsonMessageBytes.toDartString();
_UnsafeFreePointerAnyUseOfThisFunctionMustBeDoubleApproved(jsonMessageBytes);
malloc.free(utf8profile);
malloc.free(utf8handle);
return jsonMessage;
}
@ -235,8 +228,6 @@ class CwtchFfi implements Cwtch {
final utf8onion = onion.toNativeUtf8();
final utf8json = json.toNativeUtf8();
SendAppBusEvent(utf8onion, utf8onion.length, utf8json, utf8json.length);
malloc.free(utf8onion);
malloc.free(utf8json);
}
@override
@ -247,7 +238,6 @@ class CwtchFfi implements Cwtch {
final SendAppBusEvent = sendAppBusEvent.asFunction<StringFn>();
final utf8json = json.toNativeUtf8();
SendAppBusEvent(utf8json, utf8json.length);
malloc.free(utf8json);
}
@override
@ -259,8 +249,6 @@ class CwtchFfi implements Cwtch {
final u1 = profileOnion.toNativeUtf8();
final u2 = contactHandle.toNativeUtf8();
AcceptContact(u1, u1.length, u2, u2.length);
malloc.free(u1);
malloc.free(u2);
}
@override
@ -272,8 +260,6 @@ class CwtchFfi implements Cwtch {
final u1 = profileOnion.toNativeUtf8();
final u2 = contactHandle.toNativeUtf8();
BlockContact(u1, u1.length, u2, u2.length);
malloc.free(u1);
malloc.free(u2);
}
@override
@ -286,9 +272,6 @@ class CwtchFfi implements Cwtch {
final u2 = contactHandle.toNativeUtf8();
final u3 = message.toNativeUtf8();
SendMessage(u1, u1.length, u2, u2.length, u3, u3.length);
malloc.free(u1);
malloc.free(u2);
malloc.free(u3);
}
@override
@ -301,9 +284,6 @@ class CwtchFfi implements Cwtch {
final u2 = contactHandle.toNativeUtf8();
final u3 = target.toNativeUtf8();
SendInvitation(u1, u1.length, u2, u2.length, u3, u3.length);
malloc.free(u1);
malloc.free(u2);
malloc.free(u3);
}
@override
@ -324,8 +304,6 @@ class CwtchFfi implements Cwtch {
final u1 = profileOnion.toNativeUtf8();
final u2 = bundle.toNativeUtf8();
ImportBundle(u1, u1.length, u2, u2.length);
malloc.free(u1);
malloc.free(u2);
}
@override
@ -339,10 +317,6 @@ class CwtchFfi implements Cwtch {
final u3 = key.toNativeUtf8();
final u4 = value.toNativeUtf8();
SetGroupAttribute(u1, u1.length, u2, u2.length, u3, u3.length, u4, u4.length);
malloc.free(u1);
malloc.free(u2);
malloc.free(u3);
malloc.free(u4);
}
@override
@ -354,12 +328,9 @@ class CwtchFfi implements Cwtch {
final u1 = profileOnion.toNativeUtf8();
final u2 = groupHandle.toNativeUtf8();
RejectInvite(u1, u1.length, u2, u2.length);
malloc.free(u1);
malloc.free(u2);
}
@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_CreateGroup");
// ignore: non_constant_identifier_names
@ -368,10 +339,6 @@ class CwtchFfi implements Cwtch {
final u2 = server.toNativeUtf8();
final u3 = groupName.toNativeUtf8();
CreateGroup(u1, u1.length, u2, u2.length, u3, u3.length);
malloc.free(u1);
malloc.free(u2);
malloc.free(u3);
}
@override
@ -383,8 +350,6 @@ class CwtchFfi implements Cwtch {
final u1 = profileOnion.toNativeUtf8();
final u2 = handle.toNativeUtf8();
LeaveConversation(u1, u1.length, u2, u2.length);
malloc.free(u1);
malloc.free(u2);
}
@override
@ -396,12 +361,9 @@ class CwtchFfi implements Cwtch {
final u1 = profileOnion.toNativeUtf8();
final u2 = groupHandle.toNativeUtf8();
LeaveGroup(u1, u1.length, u2, u2.length);
malloc.free(u1);
malloc.free(u2);
}
@override
// ignore: non_constant_identifier_names
void UpdateMessageFlags(String profile, String handle, int index, int flags) {
var updateMessageFlagsC = library.lookup<NativeFunction<void_from_string_string_int_int_function>>("c_UpdateMessageFlags");
// ignore: non_constant_identifier_names
@ -409,8 +371,6 @@ class CwtchFfi implements Cwtch {
final utf8profile = profile.toNativeUtf8();
final utf8handle = handle.toNativeUtf8();
updateMessageFlags(utf8profile, utf8profile.length, utf8handle, utf8handle.length, index, flags);
malloc.free(utf8profile);
malloc.free(utf8handle);
}
@override
@ -422,18 +382,14 @@ class CwtchFfi implements Cwtch {
final u1 = onion.toNativeUtf8();
final u2 = currentPassword.toNativeUtf8();
DeleteProfile(u1, u1.length, u2, u2.length);
malloc.free(u1);
malloc.free(u2);
}
@override
// ignore: non_constant_identifier_names
Future<void> Shutdown() async {
var shutdown = library.lookup<NativeFunction<void_from_void_funtion>>("c_ShutdownCwtch");
// ignore: non_constant_identifier_names
// Shutdown Cwtch + Tor...
// ignore: non_constant_identifier_names
final Shutdown = shutdown.asFunction<VoidFromVoidFunction>();
Shutdown();
@ -446,7 +402,6 @@ class CwtchFfi implements Cwtch {
}
@override
// ignore: non_constant_identifier_names
Future GetMessageByContentHash(String profile, String handle, String contentHash) async {
var getMessagesByContentHashC = library.lookup<NativeFunction<get_json_blob_from_str_str_str_function>>("c_GetMessagesByContentHash");
// ignore: non_constant_identifier_names
@ -456,20 +411,6 @@ class CwtchFfi implements Cwtch {
final utf8contentHash = contentHash.toNativeUtf8();
Pointer<Utf8> jsonMessageBytes = GetMessagesByContentHash(utf8profile, utf8profile.length, utf8handle, utf8handle.length, utf8contentHash, utf8contentHash.length);
String jsonMessage = jsonMessageBytes.toDartString();
_UnsafeFreePointerAnyUseOfThisFunctionMustBeDoubleApproved(jsonMessageBytes);
malloc.free(utf8profile);
malloc.free(utf8handle);
malloc.free(utf8contentHash);
return jsonMessage;
}
// ignore: non_constant_identifier_names
// Incredibly dangerous function which invokes a free in libCwtch, should only be used
// as documented in `MEMORY.md` in libCwtch repo.
void _UnsafeFreePointerAnyUseOfThisFunctionMustBeDoubleApproved(Pointer<Utf8> ptr) {
var free = library.lookup<NativeFunction<free_function>>("c_FreePointer");
final Free = free.asFunction<FreeFn>();
Free(ptr);
}
}

View File

@ -1,20 +1,6 @@
{
"@@locale": "de",
"@@last_modified": "2021-08-26T23:44:51+02:00",
"profileOnionLabel": "Senden Sie diese Adresse an Peers, mit denen Sie sich verbinden möchten",
"addPeerTab": "Einen anderen Nutzer hinzufügen",
"addPeer": "Anderen Nutzer hinzufügen",
"peerNotOnline": "Der andere Nutzer ist offline. Die App kann momentan nicht verwendet werden.",
"peerBlockedMessage": "Anderer Nutzer ist blockiert",
"peerOfflineMessage": "Anderer Nutzer ist offline, Nachrichten können derzeit nicht zugestellt werden",
"blockBtn": "Anderen Nutzer blockieren",
"savePeerHistory": "Peer-Verlauf speichern",
"savePeerHistoryDescription": "Legt fest, ob ein mit dem anderen Nutzer verknüpfter Verlauf gelöscht werden soll oder nicht.",
"dontSavePeerHistory": "Verlauf mit anderem Nutzer löschen",
"unblockBtn": "Anderen Nutzer entsperren",
"blockUnknownLabel": "Unbekannte Peers blockieren",
"blockUnknownConnectionsEnabledDescription": "Connections from unknown contacts are blocked. You can change this in Settings",
"networkStatusConnecting": "Verbinde zu Netzwerk und Peers ...",
"@@last_modified": "2021-07-14T23:49:07+02:00",
"showMessageButton": "Show Message",
"blockedMessageMessage": "This message is from a profile you have blocked.",
"placeholderEnterMessage": "Type a message...",
@ -98,6 +84,7 @@
"todoPlaceholder": "noch zu erledigen",
"newConnectionPaneTitle": "Neue Verbindung",
"networkStatusOnline": "Online",
"networkStatusConnecting": "Verbinde zu Netzwerk und Peers ...",
"networkStatusAttemptingTor": "Versuche, eine Verbindung mit dem Tor-Netzwerk herzustellen",
"networkStatusDisconnected": "Vom Internet getrennt, überprüfe deine Verbindung",
"viewGroupMembershipTooltip": "Gruppenmitgliedschaft anzeigen",
@ -117,6 +104,7 @@
"localeFr": "Frances",
"localeEn": "English",
"settingLanguage": "Sprache",
"blockUnknownLabel": "Unbekannte Peers blockieren",
"zoomLabel": "Benutzeroberflächen-Zoom (betriftt hauptsächlich Text- und Knopgrößen)",
"versionBuilddate": "Version: %1 Aufgebaut auf: %2",
"cwtchSettingsTitle": "Cwtch Einstellungen",
@ -140,6 +128,7 @@
"password1Label": "Passwort",
"currentPasswordLabel": "aktuelles Passwort",
"yourDisplayName": "Dein Anzeigename",
"profileOnionLabel": "Senden Sie diese Adresse an Peers, mit denen Sie sich verbinden möchten",
"noPasswordWarning": "Wenn für dieses Konto kein Passwort verwendet wird, bedeutet dies, dass alle lokal gespeicherten Daten nicht verschlüsselt werden.",
"radioNoPassword": "Unverschlüsselt (kein Passwort)",
"radioUsePassword": "Passwort",
@ -152,6 +141,11 @@
"editProfileTitle": "Profil bearbeiten",
"addProfileTitle": "Neues Profil hinzufügen",
"deleteBtn": "Löschen",
"unblockBtn": "Anderen Nutzer entsperren",
"dontSavePeerHistory": "Verlauf mit anderem Nutzer löschen",
"savePeerHistoryDescription": "Legt fest, ob ein mit dem anderen Nutzer verknüpfter Verlauf gelöscht werden soll oder nicht.",
"savePeerHistory": "Peer-Verlauf speichern",
"blockBtn": "Anderen Nutzer blockieren",
"saveBtn": "Speichern",
"displayNameLabel": "Angezeigename",
"addressLabel": "Adresse",
@ -164,12 +158,15 @@
"acceptGroupInviteLabel": "Möchtest Du die Einladung annehmen",
"newGroupBtn": "Neue Gruppe anlegen",
"copiedClipboardNotification": "in die Zwischenablage kopiert",
"peerOfflineMessage": "Anderer Nutzer ist offline, Nachrichten können derzeit nicht zugestellt werden",
"peerBlockedMessage": "Anderer Nutzer ist blockiert",
"pendingLabel": "Bestätigung ausstehend",
"acknowledgedLabel": "bestätigt",
"couldNotSendMsgError": "Nachricht konnte nicht gesendet werden",
"dmTooltip": "Klicken, um Direktnachricht zu senden",
"membershipDescription": "Unten steht eine Liste der Benutzer, die Nachrichten an die Gruppe gesendet haben. Möglicherweise enthält diese Benutzerzliste nicht alle, die Zugang zur Gruppe haben.",
"addListItemBtn": "Element hinzufügen",
"peerNotOnline": "Der andere Nutzer ist offline. Die App kann momentan nicht verwendet werden.",
"searchList": "Liste durchsuchen",
"update": "Update",
"inviteBtn": "Einladen",
@ -195,6 +192,7 @@
"newBulletinLabel": "Neue Meldung",
"joinGroup": "Gruppe beitreten",
"createGroup": "Gruppe erstellen",
"addPeer": "Anderen Nutzer hinzufügen",
"groupAddr": "Adresse",
"invitation": "Einladung",
"server": "Server",
@ -203,6 +201,7 @@
"peerAddress": "Adresse",
"joinGroupTab": "Einer Gruppe beitreten",
"createGroupTab": "Eine Gruppe erstellen",
"addPeerTab": "Einen anderen Nutzer hinzufügen",
"createGroupBtn": "Anlegen",
"defaultGroupName": "Tolle Gruppe",
"createGroupTitle": "Gruppe Anlegen"

View File

@ -1,20 +1,6 @@
{
"@@locale": "en",
"@@last_modified": "2021-08-26T23:44:51+02:00",
"profileOnionLabel": "Send this address to people you want to connect with",
"addPeerTab": "Add a contact",
"addPeer": "Add Contact",
"peerNotOnline": "Contact is offline. Applications cannot be used right now.",
"peerBlockedMessage": "Contact is blocked",
"peerOfflineMessage": "Contact is offline, messages can't be delivered right now",
"blockBtn": "Block Contact",
"savePeerHistory": "Save History",
"savePeerHistoryDescription": "Determines whether or not to delete any history associated with the contact.",
"dontSavePeerHistory": "Delete History",
"unblockBtn": "Unblock Contact",
"blockUnknownLabel": "Block Unknown Contacts",
"blockUnknownConnectionsEnabledDescription": "Connections from unknown contacts are blocked. You can change this in Settings",
"networkStatusConnecting": "Connecting to network and contacts...",
"@@last_modified": "2021-07-14T23:49:07+02:00",
"showMessageButton": "Show Message",
"blockedMessageMessage": "This message is from a profile you have blocked.",
"placeholderEnterMessage": "Type a message...",
@ -98,6 +84,7 @@
"todoPlaceholder": "Todo...",
"newConnectionPaneTitle": "New Connection",
"networkStatusOnline": "Online",
"networkStatusConnecting": "Connecting to network and peers...",
"networkStatusAttemptingTor": "Attempting to connect to Tor network",
"networkStatusDisconnected": "Disconnected from the internet, check your connection",
"viewGroupMembershipTooltip": "View Group Membership",
@ -117,6 +104,7 @@
"localeFr": "Frances",
"localeEn": "English",
"settingLanguage": "Language",
"blockUnknownLabel": "Block Unknown Peers",
"zoomLabel": "Interface zoom (mostly affects text and button sizes)",
"versionBuilddate": "Version: %1 Built on: %2",
"cwtchSettingsTitle": "Cwtch Settings",
@ -140,6 +128,7 @@
"password1Label": "Password",
"currentPasswordLabel": "Current Password",
"yourDisplayName": "Your Display Name",
"profileOnionLabel": "Send this address to peers you want to connect with",
"noPasswordWarning": "Not using a password on this account means that all data stored locally will not be encrypted",
"radioNoPassword": "Unencrypted (No password)",
"radioUsePassword": "Password",
@ -152,6 +141,11 @@
"editProfileTitle": "Edit Profile",
"addProfileTitle": "Add new profile",
"deleteBtn": "Delete",
"unblockBtn": "Unblock Peer",
"dontSavePeerHistory": "Delete Peer History",
"savePeerHistoryDescription": "Determines whether or not to delete any history associated with the peer.",
"savePeerHistory": "Save Peer History",
"blockBtn": "Block Peer",
"saveBtn": "Save",
"displayNameLabel": "Display Name",
"addressLabel": "Address",
@ -164,12 +158,15 @@
"acceptGroupInviteLabel": "Do you want to accept the invitation to",
"newGroupBtn": "Create new group",
"copiedClipboardNotification": "Copied to clipboard",
"peerOfflineMessage": "Peer is offline, messages can't be delivered right now",
"peerBlockedMessage": "Peer is blocked",
"pendingLabel": "Pending",
"acknowledgedLabel": "Acknowledged",
"couldNotSendMsgError": "Could not send this message",
"dmTooltip": "Click to DM",
"membershipDescription": "Below is a list of users who have sent messages to the group. This list may not reflect all users who have access to the group.",
"addListItemBtn": "Add Item",
"peerNotOnline": "Peer is Offline. Applications cannot be used right now.",
"searchList": "Search List",
"update": "Update",
"inviteBtn": "Invite",
@ -195,6 +192,7 @@
"newBulletinLabel": "New Bulletin",
"joinGroup": "Join group",
"createGroup": "Create group",
"addPeer": "Add Peer",
"groupAddr": "Address",
"invitation": "Invitation",
"server": "Server",
@ -203,6 +201,7 @@
"peerAddress": "Address",
"joinGroupTab": "Join a group",
"createGroupTab": "Create a group",
"addPeerTab": "Add a peer",
"createGroupBtn": "Create",
"defaultGroupName": "Awesome Group",
"createGroupTitle": "Create Group"

View File

@ -1,20 +1,6 @@
{
"@@locale": "es",
"@@last_modified": "2021-08-26T23:44:51+02:00",
"profileOnionLabel": "Envía esta dirección a los contactos con los que quieras conectarte",
"addPeerTab": "Agregar Contacto",
"addPeer": "Agregar Contacto",
"peerNotOnline": "Este contacto no está en línea, la aplicación no puede ser usada en este momento",
"peerBlockedMessage": "Contacto bloqueado",
"peerOfflineMessage": "Este contacto no está en línea, los mensajes no pueden ser entregados en este momento",
"blockBtn": "Bloquear contacto",
"savePeerHistory": "Guardar el historial con contacto",
"savePeerHistoryDescription": "Determina si eliminar o no el historial asociado con el contacto.",
"dontSavePeerHistory": "Eliminar historial de contacto",
"unblockBtn": "Desbloquear contacto",
"blockUnknownLabel": "Bloquear conexiones desconocidas",
"blockUnknownConnectionsEnabledDescription": "Connections from unknown contacts are blocked. You can change this in Settings",
"networkStatusConnecting": "Conectando a la red y a los contactos...",
"@@last_modified": "2021-07-14T23:49:07+02:00",
"showMessageButton": "Show Message",
"blockedMessageMessage": "This message is from a profile you have blocked.",
"placeholderEnterMessage": "Type a message...",
@ -98,6 +84,7 @@
"todoPlaceholder": "Por hacer...",
"newConnectionPaneTitle": "Nueva conexión",
"networkStatusOnline": "En línea",
"networkStatusConnecting": "Conectando a la red y a los contactos...",
"networkStatusAttemptingTor": "Intentando conectarse a la red Tor",
"networkStatusDisconnected": "Sin conexión, comprueba tu conexión",
"viewGroupMembershipTooltip": "Ver membresía del grupo",
@ -117,6 +104,7 @@
"localeFr": "Francés",
"localeEn": "Inglés",
"settingLanguage": "Idioma",
"blockUnknownLabel": "Bloquear conexiones desconocidas",
"zoomLabel": "Zoom de la interfaz (afecta principalmente el tamaño del texto y de los botones)",
"versionBuilddate": "Versión: %1 Basado en %2",
"cwtchSettingsTitle": "Configuración de Cwtch",
@ -140,6 +128,7 @@
"password1Label": "Contraseña",
"currentPasswordLabel": "Contraseña actual",
"yourDisplayName": "Tu nombre de usuario",
"profileOnionLabel": "Envía esta dirección a los contactos con los que quieras conectarte",
"noPasswordWarning": "No usar una contraseña para esta cuenta significa que los datos almacenados localmente no serán encriptados",
"radioNoPassword": "Sin cifrado (sin contraseña)",
"radioUsePassword": "Contraseña",
@ -152,6 +141,11 @@
"editProfileTitle": "Editar perfil",
"addProfileTitle": "Agregar nuevo perfil",
"deleteBtn": "Eliminar",
"unblockBtn": "Desbloquear contacto",
"dontSavePeerHistory": "Eliminar historial de contacto",
"savePeerHistoryDescription": "Determina si eliminar o no el historial asociado con el contacto.",
"savePeerHistory": "Guardar el historial con contacto",
"blockBtn": "Bloquear contacto",
"saveBtn": "Guardar",
"displayNameLabel": "Nombre de Usuario",
"addressLabel": "Dirección",
@ -164,12 +158,15 @@
"acceptGroupInviteLabel": "¿Quieres aceptar la invitación a ",
"newGroupBtn": "Crear un nuevo grupo de chat",
"copiedClipboardNotification": "Copiado al portapapeles",
"peerOfflineMessage": "Este contacto no está en línea, los mensajes no pueden ser entregados en este momento",
"peerBlockedMessage": "Contacto bloqueado",
"pendingLabel": "Pendiente",
"acknowledgedLabel": "Reconocido",
"couldNotSendMsgError": "No se pudo enviar este mensaje",
"dmTooltip": "Haz clic para enviar mensaje directo",
"membershipDescription": "La lista a continuación solo muestra los miembros que han enviado mensajes al grupo, no incluye a todos los usuarios dentro del grupo",
"addListItemBtn": "Agregar artículo",
"peerNotOnline": "Este contacto no está en línea, la aplicación no puede ser usada en este momento",
"searchList": "Buscar en la lista",
"update": "Actualizar",
"inviteBtn": "Invitar",
@ -195,6 +192,7 @@
"newBulletinLabel": "Nuevo Boletín",
"joinGroup": "Únete al grupo",
"createGroup": "Crear perfil",
"addPeer": "Agregar Contacto",
"groupAddr": "Dirección",
"invitation": "Invitación",
"server": "Servidor",
@ -203,6 +201,7 @@
"peerAddress": "Dirección",
"joinGroupTab": "Únete a un grupo",
"createGroupTab": "Crear un grupo",
"addPeerTab": "Agregar Contacto",
"createGroupBtn": "Crear",
"defaultGroupName": "El Grupo Asombroso",
"createGroupTitle": "Crear un grupo"

View File

@ -1,20 +1,6 @@
{
"@@locale": "fr",
"@@last_modified": "2021-08-26T23:44:51+02:00",
"profileOnionLabel": "Envoyez cette adresse aux personnes avec lesquelles vous souhaitez entrer en contact.",
"addPeerTab": "Ajouter un pair",
"addPeer": "Ajouter un pair",
"peerNotOnline": "Le pair est hors ligne, les messages ne peuvent pas être remis pour le moment",
"peerBlockedMessage": "Le pair est bloqué",
"peerOfflineMessage": "Le pair est hors ligne, les messages ne peuvent pas être remis pour le moment",
"blockBtn": "Bloquer le pair",
"savePeerHistory": "Sauvegarder l'historique des pairs",
"savePeerHistoryDescription": "Détermine s'il faut ou non supprimer tout historique associé au pair.",
"dontSavePeerHistory": "Supprimer l'historique des pairs",
"unblockBtn": "Débloquer le pair",
"blockUnknownLabel": "Bloquer les pairs inconnus",
"blockUnknownConnectionsEnabledDescription": "Connections from unknown contacts are blocked. You can change this in Settings",
"networkStatusConnecting": "Se connecter au réseau et aux pairs...",
"@@last_modified": "2021-07-14T23:49:07+02:00",
"showMessageButton": "Afficher le message",
"blockedMessageMessage": "Ce message provient d'un profil que vous avez bloqué.",
"placeholderEnterMessage": "saisissez un message",
@ -98,6 +84,7 @@
"todoPlaceholder": "À faire...",
"newConnectionPaneTitle": "Nouvelle connexion",
"networkStatusOnline": "En ligne",
"networkStatusConnecting": "Se connecter au réseau et aux pairs...",
"networkStatusAttemptingTor": "Tentative de connexion au réseau Tor",
"networkStatusDisconnected": "Déconnecté d'Internet, vérifiez votre connexion",
"viewGroupMembershipTooltip": "Afficher les membres du groupe",
@ -117,6 +104,7 @@
"localeFr": "Français",
"localeEn": "Anglais",
"settingLanguage": "Langue",
"blockUnknownLabel": "Bloquer les pairs inconnus",
"zoomLabel": "Zoom de l'interface (affecte principalement la taille du texte et des boutons)",
"versionBuilddate": "Version : %1 Construite le : %2",
"cwtchSettingsTitle": "Préférences Cwtch",
@ -140,6 +128,7 @@
"password1Label": "Mot de passe",
"currentPasswordLabel": "Mot de passe actuel",
"yourDisplayName": "Pseudo",
"profileOnionLabel": "Envoyez cette adresse aux personnes avec lesquelles vous souhaitez entrer en contact.",
"noPasswordWarning": "Ne pas utiliser de mot de passe sur ce compte signifie que toutes les données stockées localement ne seront pas chiffrées.",
"radioNoPassword": "Non chiffré (pas de mot de passe)",
"radioUsePassword": "Mot de passe",
@ -152,6 +141,11 @@
"editProfileTitle": "Modifier le profil",
"addProfileTitle": "Ajouter un nouveau profil",
"deleteBtn": "Effacer",
"unblockBtn": "Débloquer le pair",
"dontSavePeerHistory": "Supprimer l'historique des pairs",
"savePeerHistoryDescription": "Détermine s'il faut ou non supprimer tout historique associé au pair.",
"savePeerHistory": "Sauvegarder l'historique des pairs",
"blockBtn": "Bloquer le pair",
"saveBtn": "Sauvegarder",
"displayNameLabel": "Pseudo",
"addressLabel": "Adresse",
@ -164,12 +158,15 @@
"acceptGroupInviteLabel": "Voulez-vous accepter l'invitation au groupe",
"newGroupBtn": "Créer un nouveau groupe",
"copiedClipboardNotification": "Copié dans le presse-papier",
"peerOfflineMessage": "Le pair est hors ligne, les messages ne peuvent pas être remis pour le moment",
"peerBlockedMessage": "Le pair est bloqué",
"pendingLabel": "En attente",
"acknowledgedLabel": "Accusé de réception",
"couldNotSendMsgError": "Impossible d'envoyer ce message",
"dmTooltip": "Envoyer un message privé",
"membershipDescription": "Liste des utilisateurs ayant envoyés un ou plusieurs messages au groupe. Cette liste peut ne pas être représentatives de l'ensemble des membres du groupe.",
"addListItemBtn": "Ajouter un élément",
"peerNotOnline": "Le pair est hors ligne, les messages ne peuvent pas être remis pour le moment",
"searchList": "Liste de recherche",
"update": "Mise à jour",
"inviteBtn": "Invitation",
@ -195,6 +192,7 @@
"newBulletinLabel": "Nouveau bulletin",
"joinGroup": "Rejoindre le groupe",
"createGroup": "Créer un groupe",
"addPeer": "Ajouter un pair",
"groupAddr": "Adresse",
"invitation": "Invitation",
"server": "Serveur",
@ -203,6 +201,7 @@
"peerAddress": "Adresse",
"joinGroupTab": "Rejoindre un groupe",
"createGroupTab": "Créer un groupe",
"addPeerTab": "Ajouter un pair",
"createGroupBtn": "Créer",
"defaultGroupName": "Un groupe génial",
"createGroupTitle": "Créer un groupe"

View File

@ -1,20 +1,6 @@
{
"@@locale": "it",
"@@last_modified": "2021-08-26T23:44:51+02:00",
"profileOnionLabel": "Inviare questo indirizzo ai peer con cui si desidera connettersi",
"addPeerTab": "Aggiungi un peer",
"addPeer": "Aggiungi peer",
"peerNotOnline": "Il peer è offline. Le applicazioni non possono essere utilizzate in questo momento.",
"peerBlockedMessage": "Il peer è bloccato",
"peerOfflineMessage": "Il peer è offline, i messaggi non possono essere recapitati in questo momento",
"blockBtn": "Blocca il peer",
"savePeerHistory": "Salva cronologia peer",
"savePeerHistoryDescription": "Determina se eliminare o meno ogni cronologia eventualmente associata al peer.",
"dontSavePeerHistory": "Elimina cronologia dei peer",
"unblockBtn": "Sblocca il peer",
"blockUnknownLabel": "Blocca peer sconosciuti",
"blockUnknownConnectionsEnabledDescription": "Connections from unknown contacts are blocked. You can change this in Settings",
"networkStatusConnecting": "Connessione alla rete e ai peer ...",
"@@last_modified": "2021-07-14T23:49:07+02:00",
"showMessageButton": "Show Message",
"blockedMessageMessage": "This message is from a profile you have blocked.",
"placeholderEnterMessage": "Type a message...",
@ -98,6 +84,7 @@
"todoPlaceholder": "Da fare...",
"newConnectionPaneTitle": "Nuova connessione",
"networkStatusOnline": "Online",
"networkStatusConnecting": "Connessione alla rete e ai peer ...",
"networkStatusAttemptingTor": "Tentativo di connessione alla rete Tor",
"networkStatusDisconnected": "Disconnesso da Internet, controlla la tua connessione",
"viewGroupMembershipTooltip": "Visualizza i membri del gruppo",
@ -117,6 +104,7 @@
"localeFr": "Francese",
"localeEn": "Inglese",
"settingLanguage": "Lingua",
"blockUnknownLabel": "Blocca peer sconosciuti",
"zoomLabel": "Zoom dell'interfaccia (influisce principalmente sulle dimensioni del testo e dei pulsanti)",
"versionBuilddate": "Versione: %1 Costruito il: %2",
"cwtchSettingsTitle": "Impostazioni di Cwtch",
@ -140,6 +128,7 @@
"password1Label": "Password",
"currentPasswordLabel": "Password corrente",
"yourDisplayName": "Il tuo nome visualizzato",
"profileOnionLabel": "Inviare questo indirizzo ai peer con cui si desidera connettersi",
"noPasswordWarning": "Non utilizzare una password su questo account significa che tutti i dati archiviati localmente non verranno criptati",
"radioNoPassword": "Non criptato (senza password)",
"radioUsePassword": "Password",
@ -152,6 +141,11 @@
"editProfileTitle": "Modifica profilo",
"addProfileTitle": "Aggiungi nuovo profilo",
"deleteBtn": "Elimina",
"unblockBtn": "Sblocca il peer",
"dontSavePeerHistory": "Elimina cronologia dei peer",
"savePeerHistoryDescription": "Determina se eliminare o meno ogni cronologia eventualmente associata al peer.",
"savePeerHistory": "Salva cronologia peer",
"blockBtn": "Blocca il peer",
"saveBtn": "Salva",
"displayNameLabel": "Nome visualizzato",
"addressLabel": "Indirizzo",
@ -164,12 +158,15 @@
"acceptGroupInviteLabel": "Vuoi accettare l'invito a",
"newGroupBtn": "Crea un nuovo gruppo",
"copiedClipboardNotification": "Copiato negli Appunti",
"peerOfflineMessage": "Il peer è offline, i messaggi non possono essere recapitati in questo momento",
"peerBlockedMessage": "Il peer è bloccato",
"pendingLabel": "In corso",
"acknowledgedLabel": "Riconosciuto",
"couldNotSendMsgError": "Impossibile inviare questo messaggio",
"dmTooltip": "Clicca per inviare un Messagio Diretto",
"membershipDescription": "Di seguito è riportato un elenco di utenti che hanno inviato messaggi al gruppo. Questo elenco potrebbe non corrispondere a tutti gli utenti che hanno accesso al gruppo.",
"addListItemBtn": "Aggiungi elemento",
"peerNotOnline": "Il peer è offline. Le applicazioni non possono essere utilizzate in questo momento.",
"searchList": "Cerca nella lista",
"update": "Aggiornamento",
"inviteBtn": "Invitare",
@ -195,6 +192,7 @@
"newBulletinLabel": "Nuovo bollettino",
"joinGroup": "Unisciti al gruppo",
"createGroup": "Crea un gruppo",
"addPeer": "Aggiungi peer",
"groupAddr": "Indirizzo",
"invitation": "Invito",
"server": "Server",
@ -203,6 +201,7 @@
"peerAddress": "Indirizzo",
"joinGroupTab": "Unisciti a un gruppo",
"createGroupTab": "Crea un gruppo",
"addPeerTab": "Aggiungi un peer",
"createGroupBtn": "Crea",
"defaultGroupName": "Gruppo fantastico",
"createGroupTitle": "Crea un gruppo"

View File

@ -1,20 +1,6 @@
{
"@@locale": "pt",
"@@last_modified": "2021-08-26T23:44:51+02:00",
"profileOnionLabel": "Send this address to contacts you want to connect with",
"addPeerTab": "Add a contact",
"addPeer": "Add Contact",
"peerNotOnline": "Contact is offline. Applications cannot be used right now.",
"peerBlockedMessage": "Contact is blocked",
"peerOfflineMessage": "Contact is offline, messages can't be delivered right now",
"blockBtn": "Block Contact",
"savePeerHistory": "Save History",
"savePeerHistoryDescription": "Determines whether or not to delete any history associated with the contact.",
"dontSavePeerHistory": "Delete History",
"unblockBtn": "Unblock Contact",
"blockUnknownLabel": "Block Unknown Contacts",
"blockUnknownConnectionsEnabledDescription": "Connections from unknown contacts are blocked. You can change this in Settings",
"networkStatusConnecting": "Connecting to network and contacts...",
"@@last_modified": "2021-07-14T23:49:07+02:00",
"showMessageButton": "Show Message",
"blockedMessageMessage": "This message is from a profile you have blocked.",
"placeholderEnterMessage": "Type a message...",
@ -98,6 +84,7 @@
"todoPlaceholder": "Afazer…",
"newConnectionPaneTitle": "New Connection",
"networkStatusOnline": "Online",
"networkStatusConnecting": "Connecting to network and peers...",
"networkStatusAttemptingTor": "Attempting to connect to Tor network",
"networkStatusDisconnected": "Disconnected from the internet, check your connection",
"viewGroupMembershipTooltip": "View Group Membership",
@ -117,6 +104,7 @@
"localeFr": "Frances",
"localeEn": "English",
"settingLanguage": "Language",
"blockUnknownLabel": "Block Unknown Peers",
"zoomLabel": "Zoom da interface (afeta principalmente tamanho de texto e botões)",
"versionBuilddate": "Version: %1 Built on: %2",
"cwtchSettingsTitle": "Configurações do Cwtch",
@ -140,6 +128,7 @@
"password1Label": "Password",
"currentPasswordLabel": "Current Password",
"yourDisplayName": "Your Display Name",
"profileOnionLabel": "Send this address to peers you want to connect with",
"noPasswordWarning": "Not using a password on this account means that all data stored locally will not be encrypted",
"radioNoPassword": "Unencrypted (No password)",
"radioUsePassword": "Password",
@ -152,6 +141,11 @@
"editProfileTitle": "Edit Profile",
"addProfileTitle": "Add new profile",
"deleteBtn": "Deletar",
"unblockBtn": "Unblock Peer",
"dontSavePeerHistory": "Delete Peer History",
"savePeerHistoryDescription": "Determines whether or not to delete any history associated with the peer.",
"savePeerHistory": "Save Peer History",
"blockBtn": "Block Peer",
"saveBtn": "Salvar",
"displayNameLabel": "Nome de Exibição",
"addressLabel": "Endereço",
@ -164,12 +158,15 @@
"acceptGroupInviteLabel": "Você quer aceitar o convite para",
"newGroupBtn": "Criar novo grupo",
"copiedClipboardNotification": "Copiado",
"peerOfflineMessage": "Peer is offline, messages can't be delivered right now",
"peerBlockedMessage": "Peer is blocked",
"pendingLabel": "Pendente",
"acknowledgedLabel": "Confirmada",
"couldNotSendMsgError": "Não deu para enviar esta mensagem",
"dmTooltip": "Clique para DM",
"membershipDescription": "A lista abaixo é de usuários que enviaram mensagens ao grupo. Essa lista pode não refletir todos os usuários que têm acesso ao grupo.",
"addListItemBtn": "Add Item",
"peerNotOnline": "Peer is Offline. Applications cannot be used right now.",
"searchList": "Search List",
"update": "Update",
"inviteBtn": "Convidar",
@ -195,6 +192,7 @@
"newBulletinLabel": "Novo Boletim",
"joinGroup": "Join group",
"createGroup": "Create group",
"addPeer": "Add Peer",
"groupAddr": "Address",
"invitation": "Invitation",
"server": "Server",
@ -203,6 +201,7 @@
"peerAddress": "Address",
"joinGroupTab": "Join a group",
"createGroupTab": "Create a group",
"addPeerTab": "Add a peer",
"createGroupBtn": "Criar",
"defaultGroupName": "Grupo incrível",
"createGroupTitle": "Criar Grupo"

View File

@ -169,7 +169,7 @@ class FlwtchState extends State<Flwtch> {
var args = jsonDecode(call.arguments);
var profile = profs.getProfile(args["ProfileOnion"])!;
var convo = profile.contactList.getContact(args["Handle"])!;
Provider.of<AppState>(navKey.currentContext!, listen: false).initialScrollIndex = convo.unreadMessages;
var initialIndex = convo.unreadMessages;
convo.unreadMessages = 0;
// single pane mode pushes; double pane mode reads AppState.selectedProfile/Conversation
@ -187,7 +187,7 @@ class FlwtchState extends State<Flwtch> {
ChangeNotifierProvider.value(value: profile),
ChangeNotifierProvider.value(value: convo),
],
builder: (context, child) => MessageView(),
builder: (context, child) => MessageView(initialIndex),
);
},
),

View File

@ -30,7 +30,6 @@ class AppState extends ChangeNotifier {
String appError = "";
String? _selectedProfile;
String? _selectedConversation;
int _initialScrollIndex = 0;
int? _selectedIndex;
bool _unreadMessagesBelow = false;
@ -68,12 +67,6 @@ class AppState extends ChangeNotifier {
notifyListeners();
}
int get initialScrollIndex => _initialScrollIndex;
set initialScrollIndex(int newVal) {
this._initialScrollIndex = newVal;
notifyListeners();
}
bool isLandscape(BuildContext c) => MediaQuery.of(c).size.width > MediaQuery.of(c).size.height;
}

View File

@ -23,19 +23,18 @@ class ContactsView extends StatefulWidget {
// selectConversation can be called from anywhere to set the active conversation
void selectConversation(BuildContext context, String handle) {
// requery instead of using contactinfostate directly because sometimes listview gets confused about data that resorts
var initialIndex = Provider.of<ProfileInfoState>(context, listen: false).contactList.getContact(handle)!.unreadMessages;
// requery instead of using contactinfostate directly because sometimes listview gets confused about data that resorts
Provider.of<ProfileInfoState>(context, listen: false).contactList.getContact(handle)!.unreadMessages = 0;
// triggers update in Double/TripleColumnView
Provider.of<AppState>(context, listen: false).initialScrollIndex = initialIndex;
Provider.of<AppState>(context, listen: false).selectedConversation = handle;
Provider.of<AppState>(context, listen: false).selectedIndex = null;
// if in singlepane mode, push to the stack
var isLandscape = Provider.of<AppState>(context, listen: false).isLandscape(context);
if (Provider.of<Settings>(context, listen: false).uiColumns(isLandscape).length == 1) _pushMessageView(context, handle);
if (Provider.of<Settings>(context, listen: false).uiColumns(isLandscape).length == 1) _pushMessageView(context, handle, initialIndex);
}
void _pushMessageView(BuildContext context, String handle) {
void _pushMessageView(BuildContext context, String handle, int initialIndex) {
var profileOnion = Provider.of<ProfileInfoState>(context, listen: false).onion;
Navigator.of(context).push(
MaterialPageRoute<void>(
@ -48,7 +47,7 @@ void _pushMessageView(BuildContext context, String handle) {
ChangeNotifierProvider.value(value: profile),
ChangeNotifierProvider.value(value: profile.contactList.getContact(handle)!),
],
builder: (context, child) => MessageView(),
builder: (context, child) => MessageView(initialIndex),
);
},
),
@ -87,7 +86,18 @@ class _ContactsViewState extends State<ContactsView> {
child: Text("%1 » %2".replaceAll("%1", Provider.of<ProfileInfoState>(context).nickname).replaceAll("%2", AppLocalizations.of(context)!.titleManageContacts),
overflow: TextOverflow.ellipsis, style: TextStyle(color: Provider.of<Settings>(context).current().mainTextColor()))),
])),
actions: getActions(context),
actions: [
IconButton(icon: TorIcon(), onPressed: _pushTorStatus),
IconButton(
// need both conditions for displaying initial empty textfield and also allowing filters to be cleared if this widget gets lost/reset
icon: Icon(showSearchBar || Provider.of<ContactListState>(context).isFiltered ? Icons.search_off : Icons.search),
onPressed: () {
Provider.of<ContactListState>(context, listen: false).filter = "";
setState(() {
showSearchBar = !showSearchBar;
});
})
],
),
floatingActionButton: FloatingActionButton(
onPressed: _pushAddContact,
@ -97,26 +107,6 @@ class _ContactsViewState extends State<ContactsView> {
body: showSearchBar || Provider.of<ContactListState>(context).isFiltered ? _buildFilterable() : _buildContactList());
}
List<Widget> getActions(context) {
var actions = List<Widget>.empty(growable: true);
if (Provider.of<Settings>(context).blockUnknownConnections) {
actions.add(Tooltip(message: AppLocalizations.of(context)!.blockUnknownConnectionsEnabledDescription, child: Icon(CwtchIcons.block_unknown)));
}
actions.add(
IconButton(icon: TorIcon(), onPressed: _pushTorStatus),
);
actions.add(IconButton(
// need both conditions for displaying initial empty textfield and also allowing filters to be cleared if this widget gets lost/reset
icon: Icon(showSearchBar || Provider.of<ContactListState>(context).isFiltered ? Icons.search_off : Icons.search),
onPressed: () {
Provider.of<ContactListState>(context, listen: false).filter = "";
setState(() {
showSearchBar = !showSearchBar;
});
}));
return actions;
}
Widget _buildFilterable() {
Widget txtfield = CwtchTextField(
controller: ctrlrFilter,

View File

@ -17,6 +17,7 @@ class _DoubleColumnViewState extends State<DoubleColumnView> {
Widget build(BuildContext context) {
var flwtch = Provider.of<AppState>(context);
var cols = Provider.of<Settings>(context).uiColumns(true);
var initialIndex = flwtch.selectedConversation == null ? 0 : Provider.of<ProfileInfoState>(context, listen: false).contactList.getContact(flwtch.selectedConversation!)!.unreadMessages;
return Flex(
direction: Axis.horizontal,
children: <Widget>[
@ -35,7 +36,7 @@ class _DoubleColumnViewState extends State<DoubleColumnView> {
ChangeNotifierProvider.value(value: Provider.of<ProfileInfoState>(context)),
ChangeNotifierProvider.value(
value: flwtch.selectedConversation != null ? Provider.of<ProfileInfoState>(context).contactList.getContact(flwtch.selectedConversation!)! : ContactInfoState("", "")),
], child: Container(child: MessageView())),
], child: Container(child: MessageView(initialIndex))),
),
],
);

View File

@ -22,6 +22,9 @@ import '../widgets/messagelist.dart';
import 'groupsettingsview.dart';
class MessageView extends StatefulWidget {
int initialIndex;
MessageView(this.initialIndex);
@override
_MessageViewState createState() => _MessageViewState();
}
@ -35,31 +38,24 @@ class _MessageViewState extends State<MessageView> {
@override
void initState() {
// using "8" because "# of messages that fit on one screen" isnt trivial to calculate at this point
if (widget.initialIndex > 8) {
WidgetsFlutterBinding.ensureInitialized().addPostFrameCallback((timeStamp) {
Provider.of<AppState>(context, listen: false).unreadMessagesBelow = true;
});
}
scrollListener.itemPositions.addListener(() {
var first = scrollListener.itemPositions.value.first.index;
var last = scrollListener.itemPositions.value.last.index;
// sometimes these go hi->lo and sometimes they go lo->hi because [who tf knows]
if ((first == 0 || last == 0) && Provider.of<AppState>(context, listen: false).unreadMessagesBelow == true) {
Provider.of<AppState>(context, listen: false).initialScrollIndex = 0;
if (first == 0 || last == 0) {
Provider.of<AppState>(context, listen: false).unreadMessagesBelow = false;
}
});
super.initState();
}
@override
void didChangeDependencies() {
var appState = Provider.of<AppState>(context, listen: false);
// using "8" because "# of messages that fit on one screen" isnt trivial to calculate at this point
if (appState.initialScrollIndex > 8 && appState.unreadMessagesBelow == false) {
WidgetsFlutterBinding.ensureInitialized().addPostFrameCallback((timeStamp) {
appState.unreadMessagesBelow = true;
});
}
super.didChangeDependencies();
}
@override
void dispose() {
focusNode.dispose();
@ -78,13 +74,9 @@ class _MessageViewState extends State<MessageView> {
return WillPopScope(
onWillPop: _onWillPop,
child: Scaffold(
floatingActionButton: appState.unreadMessagesBelow
? FloatingActionButton(
child: Icon(Icons.arrow_downward),
onPressed: () {
scrollController.scrollTo(index: 0, duration: Duration(milliseconds: 600));
})
: null,
floatingActionButton: appState.unreadMessagesBelow ? FloatingActionButton(child: Icon(Icons.arrow_downward), onPressed: (){
scrollController.scrollTo(index: 0, duration: Duration(milliseconds: 600));
}) : null,
appBar: AppBar(
// setting leading to null makes it do the default behaviour; container() hides it
leading: Provider.of<Settings>(context).uiColumns(appState.isLandscape(context)).length > 1 ? Container() : null,
@ -109,19 +101,13 @@ class _MessageViewState extends State<MessageView> {
//IconButton(icon: Icon(Icons.chat), onPressed: _pushContactSettings),
//IconButton(icon: Icon(Icons.list), onPressed: _pushContactSettings),
//IconButton(icon: Icon(Icons.push_pin), onPressed: _pushContactSettings),
IconButton(
icon: Icon(CwtchIcons.send_invite, size: 24),
tooltip: AppLocalizations.of(context)!.sendInvite,
onPressed: () {
_modalSendInvitation(context);
}),
IconButton(
icon: Provider.of<ContactInfoState>(context, listen: false).isGroup == true ? Icon(CwtchIcons.group_settings_24px) : Icon(CwtchIcons.peer_settings_24px),
tooltip: AppLocalizations.of(context)!.conversationSettings,
onPressed: _pushContactSettings),
],
),
body: Padding(padding: EdgeInsets.fromLTRB(8.0, 8.0, 8.0, 108.0), child: MessageList(scrollController, scrollListener)),
body: Padding(padding: EdgeInsets.fromLTRB(8.0, 8.0, 8.0, 108.0), child: MessageList(widget.initialIndex, scrollController, scrollListener)),
bottomSheet: _buildComposeBox(),
));
}
@ -210,37 +196,42 @@ class _MessageViewState extends State<MessageView> {
child: Row(
children: <Widget>[
Expanded(
child: Container(
decoration: BoxDecoration(border: Border(top: BorderSide(color: Provider.of<Settings>(context).theme.defaultButtonActiveColor()))),
child: RawKeyboardListener(
focusNode: FocusNode(),
onKey: handleKeyPress,
child: Padding(
padding: EdgeInsets.all(8),
child: TextFormField(
key: Key('txtCompose'),
controller: ctrlrCompose,
focusNode: focusNode,
autofocus: !Platform.isAndroid,
textInputAction: TextInputAction.newline,
keyboardType: TextInputType.multiline,
enableIMEPersonalizedLearning: false,
minLines: 1,
maxLines: null,
onFieldSubmitted: _sendMessage,
enabled: !isOffline,
decoration: InputDecoration(
hintText: isOffline ? "" : AppLocalizations.of(context)!.placeholderEnterMessage,
hintStyle: TextStyle(color: Provider.of<Settings>(context).theme.altTextColor()),
enabledBorder: InputBorder.none,
focusedBorder: InputBorder.none,
enabled: true,
suffixIcon: ElevatedButton(
style: ElevatedButton.styleFrom(primary: Provider.of<Settings>(context).theme.defaultButtonColor()),
child: Icon(CwtchIcons.send_24px, size: 24, color: Provider.of<Settings>(context).theme.mainTextColor()),
onPressed: isOffline ? null : _sendMessage,
))),
)))),
child: Container(
decoration: BoxDecoration(border: Border(top: BorderSide(color: Provider.of<Settings>(context).theme.defaultButtonActiveColor()))),
child: RawKeyboardListener(
focusNode: FocusNode(),
onKey: handleKeyPress,
child: TextFormField(
key: Key('txtCompose'),
controller: ctrlrCompose,
focusNode: focusNode,
autofocus: !Platform.isAndroid,
textInputAction: TextInputAction.newline,
keyboardType: TextInputType.multiline,
minLines: 1,
maxLines: null,
onFieldSubmitted: _sendMessage,
enabled: !isOffline,
decoration: InputDecoration(
hintText: isOffline ? "" : AppLocalizations.of(context)!.placeholderEnterMessage,
hintStyle: TextStyle(color: Provider.of<Settings>(context).theme.altTextColor()),
enabledBorder: InputBorder.none,
focusedBorder: InputBorder.none,
enabled: true,
prefixIcon: IconButton(
icon: Icon(CwtchIcons.send_invite, size: 24, color: Provider.of<Settings>(context).theme.mainTextColor()),
tooltip: AppLocalizations.of(context)!.sendInvite,
enableFeedback: true,
splashColor: Provider.of<Settings>(context).theme.defaultButtonActiveColor(),
hoverColor: Provider.of<Settings>(context).theme.defaultButtonActiveColor(),
onPressed: () => _modalSendInvitation(context)),
suffixIcon: IconButton(
icon: Icon(CwtchIcons.send_24px, size: 24, color: Provider.of<Settings>(context).theme.mainTextColor()),
tooltip: AppLocalizations.of(context)!.sendMessage,
onPressed: isOffline ? null : _sendMessage,
),
)))),
),
],
),
);

View File

@ -35,7 +35,7 @@ class _TripleColumnViewState extends State<TripleColumnView> {
child: appState.selectedConversation == null
? Center(child: Text(AppLocalizations.of(context)!.addContactFirst))
: //dev
Container(child: MessageView()),
Container(child: MessageView(0/*todo:setme*/)),
),
]);
}

View File

@ -37,7 +37,6 @@ class _CwtchButtonTextFieldState extends State<CwtchButtonTextField> {
readOnly: widget.readonly,
showCursor: !widget.readonly,
focusNode: _focusNode,
enableIMEPersonalizedLearning: false,
decoration: InputDecoration(
suffixIcon: IconButton(
onPressed: widget.onPressed,

View File

@ -1,5 +1,3 @@
import 'dart:io';
import 'package:cwtch/views/contactsview.dart';
import 'package:flutter/material.dart';
import 'package:flutter/painting.dart';
@ -129,9 +127,9 @@ class _ContactRowState extends State<ContactRow> {
}
// If the last message was over a day ago, just state the date
if (DateTime.now().difference(date).inDays > 1) {
return DateFormat.yMd(Platform.localeName).format(date.toLocal());
return DateFormat.yMd().format(date.toLocal());
}
// Otherwise just state the time.
return DateFormat.Hm(Platform.localeName).format(date.toLocal());
return DateFormat.Hm().format(date.toLocal());
}
}

View File

@ -1,5 +1,4 @@
import 'dart:convert';
import 'dart:io';
import 'package:cwtch/cwtch_icons_icons.dart';
import 'package:cwtch/models/message.dart';
@ -40,7 +39,7 @@ class InvitationBubbleState extends State<InvitationBubble> {
var borderRadiousEh = 15.0;
var showGroupInvite = Provider.of<Settings>(context).isExperimentEnabled(TapirGroupsExperiment);
rejected = Provider.of<MessageMetadata>(context).flags & 0x01 == 0x01;
var prettyDate = DateFormat.yMd(Platform.localeName).add_jm().format(Provider.of<MessageMetadata>(context).timestamp);
var prettyDate = DateFormat.yMd().add_jm().format(Provider.of<MessageMetadata>(context).timestamp);
// If the sender is not us, then we want to give them a nickname...
var senderDisplayStr = "";

View File

@ -1,5 +1,3 @@
import 'dart:io';
import 'package:cwtch/models/message.dart';
import 'package:cwtch/widgets/malformedbubble.dart';
import 'package:flutter/material.dart';
@ -30,7 +28,7 @@ class MessageBubbleState extends State<MessageBubble> {
// var myKey = Provider.of<MessageState>(context).profileOnion + "::" + Provider.of<MessageState>(context).contactHandle + "::" + Provider.of<MessageState>(context).messageIndex.toString();
DateTime messageDate = Provider.of<MessageMetadata>(context).timestamp;
prettyDate = DateFormat.yMd(Platform.localeName).add_jm().format(messageDate.toLocal());
prettyDate = DateFormat.yMd().add_jm().format(messageDate.toLocal());
// If the sender is not us, then we want to give them a nickname...
var senderDisplayStr = "";

View File

@ -9,9 +9,10 @@ import '../model.dart';
import '../settings.dart';
class MessageList extends StatefulWidget {
int initialIndex;
ItemScrollController scrollController;
ItemPositionsListener scrollListener;
MessageList(this.scrollController, this.scrollListener);
MessageList(this.initialIndex, this.scrollController, this.scrollListener);
@override
_MessageListState createState() => _MessageListState();
@ -20,7 +21,6 @@ class MessageList extends StatefulWidget {
class _MessageListState extends State<MessageList> {
@override
Widget build(BuildContext outerContext) {
var initi = Provider.of<AppState>(outerContext, listen: false).initialScrollIndex;
bool isP2P = !Provider.of<ContactInfoState>(context).isGroup;
bool isGroupAndSyncing = Provider.of<ContactInfoState>(context).isGroup == true && Provider.of<ContactInfoState>(context).status == "Authenticated";
bool isGroupAndSynced = Provider.of<ContactInfoState>(context).isGroup && Provider.of<ContactInfoState>(context).status == "Synced";
@ -72,7 +72,7 @@ class _MessageListState extends State<MessageList> {
? ScrollablePositionedList.builder(
itemPositionsListener: widget.scrollListener,
itemScrollController: widget.scrollController,
initialScrollIndex: Provider.of<AppState>(outerContext, listen: false).initialScrollIndex,
initialScrollIndex: widget.initialIndex,
itemCount: Provider.of<ContactInfoState>(outerContext).totalMessages,
reverse: true, // NOTE: There seems to be a bug in flutter that corrects the mouse wheel scroll, but not the drag direction...
itemBuilder: (itemBuilderContext, index) {

View File

@ -5,7 +5,6 @@ import 'package:cwtch/models/message.dart';
import 'package:cwtch/views/contactsview.dart';
import 'package:flutter/material.dart';
import 'package:cwtch/widgets/profileimage.dart';
import 'package:flutter/physics.dart';
import 'package:provider/provider.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
@ -21,31 +20,9 @@ class MessageRow extends StatefulWidget {
MessageRowState createState() => MessageRowState();
}
class MessageRowState extends State<MessageRow> with SingleTickerProviderStateMixin {
class MessageRowState extends State<MessageRow> {
bool showMenu = false;
bool showBlockedMessage = false;
late AnimationController _controller;
late Animation<Alignment> _animation;
late Alignment _dragAlignment = Alignment.center;
Alignment _dragAffinity = Alignment.center;
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this);
_controller.addListener(() {
setState(() {
_dragAlignment = _animation.value;
});
});
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
var fromMe = Provider.of<MessageMetadata>(context).senderHandle == Provider.of<ProfileInfoState>(context).onion;
@ -53,12 +30,6 @@ class MessageRowState extends State<MessageRow> with SingleTickerProviderStateMi
var isBlocked = isContact ? Provider.of<ProfileInfoState>(context).contactList.getContact(Provider.of<MessageMetadata>(context).senderHandle)!.isBlocked : false;
var actualMessage = Flexible(flex: 3, fit: FlexFit.loose, child: widget.child);
_dragAffinity = fromMe ? Alignment.centerRight : Alignment.centerLeft;
if (_dragAlignment == Alignment.center) {
_dragAlignment = fromMe ? Alignment.centerRight : Alignment.centerLeft;
}
var senderDisplayStr = "";
if (!fromMe) {
ContactInfoState? contact = Provider.of<ProfileInfoState>(context).contactList.getContact(Provider.of<MessageMetadata>(context).senderHandle);
@ -81,7 +52,7 @@ class MessageRowState extends State<MessageRow> with SingleTickerProviderStateMi
Provider.of<AppState>(context, listen: false).selectedIndex = Provider.of<MessageMetadata>(context, listen: false).messageIndex;
},
icon: Icon(Icons.reply, color: Provider.of<Settings>(context).theme.dropShadowColor())));
Widget wdgSpacer = Flexible(child: SizedBox(width: 60, height: 10));
Widget wdgSpacer = Expanded(child: SizedBox(width: 60, height: 10));
var widgetRow = <Widget>[];
if (fromMe) {
@ -160,9 +131,10 @@ class MessageRowState extends State<MessageRow> with SingleTickerProviderStateMi
wdgSpacer,
];
}
var size = MediaQuery.of(context).size;
return MouseRegion(
// For desktop...
onHover: (event) {
setState(() {
this.showMenu = true;
@ -174,55 +146,14 @@ class MessageRowState extends State<MessageRow> with SingleTickerProviderStateMi
});
},
child: GestureDetector(
onPanUpdate: (details) {
setState(() {
_dragAlignment += Alignment(
details.delta.dx / (size.width * 0.5),
0,
);
});
},
onPanDown: (details) {
_controller.stop();
},
onPanEnd: (details) {
_runAnimation(details.velocity.pixelsPerSecond, size);
Provider.of<AppState>(context, listen: false).selectedIndex = Provider.of<MessageMetadata>(context, listen: false).messageIndex;
},
child: Padding(
padding: EdgeInsets.all(2),
child: Align(
widthFactor: 1,
alignment: _dragAlignment,
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: widgetRow,
)))));
}
void _runAnimation(Offset pixelsPerSecond, Size size) {
_animation = _controller.drive(
AlignmentTween(
begin: _dragAlignment,
end: _dragAffinity,
),
);
// Calculate the velocity relative to the unit interval, [0,1],
// used by the animation controller.
final unitsPerSecondX = pixelsPerSecond.dx / size.width;
final unitsPerSecondY = pixelsPerSecond.dy / size.height;
final unitsPerSecond = Offset(unitsPerSecondX, unitsPerSecondY);
final unitVelocity = unitsPerSecond.distance;
const spring = SpringDescription(
mass: 30,
stiffness: 1,
damping: 1,
);
final simulation = SpringSimulation(spring, 0, 1, -unitVelocity);
_controller.animateWith(simulation);
// Swipe to quote on Android
onHorizontalDragEnd: Platform.isAndroid
? (details) {
Provider.of<AppState>(context, listen: false).selectedIndex = Provider.of<MessageMetadata>(context, listen: false).messageIndex;
}
: null,
child: Padding(padding: EdgeInsets.all(2), child: Row(mainAxisAlignment: fromMe ? MainAxisAlignment.end : MainAxisAlignment.start, children: widgetRow))));
}
void _btnGoto() {

View File

@ -37,7 +37,6 @@ class _CwtchTextFieldState extends State<CwtchPasswordField> {
controller: widget.controller,
validator: widget.validator,
obscureText: obscureText,
enableIMEPersonalizedLearning: false,
autofillHints: widget.autoFillHints,
autovalidateMode: AutovalidateMode.always,
onFieldSubmitted: widget.action,

View File

@ -39,7 +39,6 @@ class _CwtchTextFieldState extends State<CwtchTextField> {
validator: widget.validator,
onChanged: widget.onChanged,
autofocus: widget.autofocus,
enableIMEPersonalizedLearning: false,
focusNode: _focusNode,
decoration: InputDecoration(
labelText: widget.labelText,

View File

@ -21,7 +21,7 @@ packages:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.8.1"
version: "2.7.0"
boolean_selector:
dependency: transitive
description:
@ -181,7 +181,7 @@ packages:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.0"
version: "1.4.0"
msix:
dependency: "direct dev"
description:
@ -329,13 +329,6 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "5.0.0"
scrollable_positioned_list:
dependency: "direct main"
description:
name: scrollable_positioned_list
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.0-nullsafety.0"
sky_engine:
dependency: transitive
description: flutter
@ -382,7 +375,7 @@ packages:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.2"
version: "0.4.1"
typed_data:
dependency: transitive
description: