Compare commits
57 Commits
Author | SHA1 | Date |
---|---|---|
Sarah Jamie Lewis | e019f5f52d | |
Sarah Jamie Lewis | a36a5ea2fe | |
Sarah Jamie Lewis | 8e5074ec98 | |
Sarah Jamie Lewis | afb00e9295 | |
Dan Ballard | e249492641 | |
Dan Ballard | cead758f78 | |
Sarah Jamie Lewis | 75b7e77bc1 | |
Sarah Jamie Lewis | ad215635d2 | |
Sarah Jamie Lewis | a937301d59 | |
Sarah Jamie Lewis | b19724036d | |
Sarah Jamie Lewis | 70914c7a87 | |
Sarah Jamie Lewis | 4577541e23 | |
Sarah Jamie Lewis | 35da8daed6 | |
Sarah Jamie Lewis | 45a0b8b767 | |
Sarah Jamie Lewis | 3e6c3faeda | |
Sarah Jamie Lewis | 81f2d171aa | |
Sarah Jamie Lewis | 388257bbff | |
Sarah Jamie Lewis | 1b35f8a32b | |
Sarah Jamie Lewis | dee5752d38 | |
Sarah Jamie Lewis | 6188dffbc0 | |
Sarah Jamie Lewis | 3d9d707b83 | |
Sarah Jamie Lewis | baccdee90e | |
Sarah Jamie Lewis | e55f7af49c | |
Sarah Jamie Lewis | 632764b407 | |
Sarah Jamie Lewis | 3148a8e064 | |
Sarah Jamie Lewis | cc4403261e | |
Sarah Jamie Lewis | c305f7ba23 | |
Sarah Jamie Lewis | 49fcbdf9aa | |
Sarah Jamie Lewis | 2ab0456dd5 | |
Sarah Jamie Lewis | 5afd7c8dd8 | |
Sarah Jamie Lewis | cccd669608 | |
Sarah Jamie Lewis | 7f7e4536f2 | |
Sarah Jamie Lewis | 4a3770d0ec | |
Sarah Jamie Lewis | c3cd8d5d66 | |
Sarah Jamie Lewis | e416638e65 | |
Sarah Jamie Lewis | 040692c01e | |
Dan Ballard | af8ed5ac78 | |
Sarah Jamie Lewis | 59c5004153 | |
Sarah Jamie Lewis | b183966980 | |
Sarah Jamie Lewis | a69f3cb46e | |
Sarah Jamie Lewis | aedc033df9 | |
Sarah Jamie Lewis | 3f262afcac | |
Sarah Jamie Lewis | 2d18089721 | |
Sarah Jamie Lewis | 103c1e08b5 | |
Sarah Jamie Lewis | ea701546e7 | |
Sarah Jamie Lewis | a2a09966e6 | |
Sarah Jamie Lewis | ea22864341 | |
Sarah Jamie Lewis | 67a99c903a | |
Sarah Jamie Lewis | 01b5c41208 | |
Sarah Jamie Lewis | 22bf5cfe92 | |
Dan Ballard | 7f50036968 | |
Sarah Jamie Lewis | 0687718803 | |
Dan Ballard | 90625eacb5 | |
Dan Ballard | 81d62a06e3 | |
Dan Ballard | 38ec143ef6 | |
Sarah Jamie Lewis | 7237318c53 | |
Dan Ballard | 471ab96743 |
35
.drone.yml
|
@ -8,7 +8,7 @@ clone:
|
|||
|
||||
steps:
|
||||
- name: clone
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.7.1
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.10.2
|
||||
environment:
|
||||
buildbot_key_b64:
|
||||
from_secret: buildbot_key_b64
|
||||
|
@ -24,7 +24,7 @@ steps:
|
|||
- git checkout $DRONE_COMMIT
|
||||
|
||||
- name: fetch
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.7.1
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.10.2
|
||||
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-fstable-3.7.1
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.10.2
|
||||
volumes:
|
||||
- name: deps
|
||||
path: /root/.pub-cache
|
||||
|
@ -57,20 +57,21 @@ steps:
|
|||
- mkdir -p deploy/cwtch
|
||||
- cp -r build/linux/x64/release/bundle/* deploy/cwtch
|
||||
- cd deploy
|
||||
- tar -czf cwtch-`cat ../VERSION`.tar.gz cwtch
|
||||
# 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
|
||||
- rm -r cwtch
|
||||
|
||||
- name: linux-ui-tests
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.7.1
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.10.2
|
||||
volumes:
|
||||
- name: deps
|
||||
path: /root/.pub-cache
|
||||
commands:
|
||||
# Run 01_general, 02_global_settings, and 04_profile_mgmt features...
|
||||
- ./run-tests-headless.sh "01_general|02_global_settings|04_profile_mgmt"
|
||||
# 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"
|
||||
|
||||
- name: test-build-android
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.7.1
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.10.2
|
||||
when:
|
||||
event: pull_request
|
||||
volumes:
|
||||
|
@ -80,7 +81,7 @@ steps:
|
|||
- flutter build apk --debug
|
||||
|
||||
- name: build-android
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.7.1
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.10.2
|
||||
when:
|
||||
event: push
|
||||
environment:
|
||||
|
@ -104,7 +105,7 @@ steps:
|
|||
#- cp build/app/outputs/flutter-apk/app-debug.apk deploy/android
|
||||
|
||||
- name: widget-tests
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.7.1
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.10.2
|
||||
volumes:
|
||||
- name: deps
|
||||
path: /root/.pub-cache
|
||||
|
@ -177,7 +178,7 @@ clone:
|
|||
|
||||
steps:
|
||||
- name: clone
|
||||
image: openpriv/flutter-desktop:windows-sdk30-fstable-3.7.1
|
||||
image: openpriv/flutter-desktop:windows-sdk30-fstable-3.10.2
|
||||
environment:
|
||||
buildbot_key_b64:
|
||||
from_secret: buildbot_key_b64
|
||||
|
@ -195,7 +196,7 @@ steps:
|
|||
- git checkout $Env:DRONE_COMMIT
|
||||
|
||||
- name: fetch
|
||||
image: openpriv/flutter-desktop:windows-sdk30-fstable-3.7.1
|
||||
image: openpriv/flutter-desktop:windows-sdk30-fstable-3.10.2
|
||||
commands:
|
||||
- git describe --tags --abbrev=1 > VERSION
|
||||
- git log -1 --format=%cd --date=format:'%Y-%m-%d-%H-%M' > COMMIT_DATE
|
||||
|
@ -203,7 +204,7 @@ steps:
|
|||
- .\fetch-libcwtch-go.ps1
|
||||
|
||||
- name: build-windows
|
||||
image: openpriv/flutter-desktop:windows-sdk30-fstable-3.7.1
|
||||
image: openpriv/flutter-desktop:windows-sdk30-fstable-3.10.2
|
||||
commands:
|
||||
- flutter pub get
|
||||
- $Env:version += type .\VERSION
|
||||
|
@ -214,9 +215,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:\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 README.md $Env:releasedir\
|
||||
- copy windows\*.bat $Env:releasedir\
|
||||
- powershell -command "Expand-Archive -Path tor.zip -DestinationPath $Env:releasedir\Tor"
|
||||
|
@ -260,7 +261,7 @@ steps:
|
|||
- move *.sha512.txt deploy\$Env:builddir
|
||||
|
||||
- name: deploy-windows
|
||||
image: openpriv/flutter-desktop:windows-sdk30-fstable-3.7.1
|
||||
image: openpriv/flutter-desktop:windows-sdk30-fstable-3.10.2
|
||||
when:
|
||||
event: push
|
||||
status: [ success ]
|
||||
|
|
24
.metadata
|
@ -1,10 +1,30 @@
|
|||
# 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 and should not be manually edited.
|
||||
# This file should be version controlled.
|
||||
|
||||
version:
|
||||
revision: 78910062997c3a836feee883712c241a5fd22983
|
||||
revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf
|
||||
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'
|
||||
|
|
|
@ -1 +1 @@
|
|||
2023-05-09-13-30-v0.0.3-24-g5b2f3cf
|
||||
2023-08-22-14-06-v0.0.6
|
15
README.md
|
@ -21,6 +21,13 @@ 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
|
||||
|
@ -64,10 +71,14 @@ To build a release version and load normal profiles, use `build-release.sh X` in
|
|||
|
||||
### Building on MacOS
|
||||
|
||||
- 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
|
||||
- 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"
|
||||
- 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
|
||||
|
||||
|
|
|
@ -84,6 +84,7 @@ 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
|
||||
|
@ -167,32 +168,36 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) :
|
|||
val title = data.getString("NameSuggestion");
|
||||
val progress = data.getString("Progress").toInt();
|
||||
val progressMax = data.getString("FileSizeInChunks").toInt();
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.d("FlwtchWorker->FileDownloadProgressUpdate", e.toString() + " :: " + e.getStackTrace());
|
||||
|
@ -216,6 +221,8 @@ 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);
|
||||
}
|
||||
|
|
|
@ -343,7 +343,7 @@ class MainActivity: FlutterActivity() {
|
|||
return
|
||||
}
|
||||
|
||||
"RestartSharing" -> {
|
||||
"RestartFileShare" -> {
|
||||
val profile: String = call.argument("ProfileOnion") ?: ""
|
||||
val filepath: String = call.argument("filekey") ?: ""
|
||||
result.success(Cwtch.restartFileShare(profile, filepath))
|
||||
|
@ -357,11 +357,17 @@ class MainActivity: FlutterActivity() {
|
|||
return
|
||||
}
|
||||
|
||||
"DeleteServerInfo" -> {
|
||||
val profile: String = call.argument("ProfileOnion") ?: ""
|
||||
val handle: String = call.argument("handle") ?: ""
|
||||
result.success(Cwtch.deleteServerInfo(profile, handle))
|
||||
return
|
||||
}
|
||||
|
||||
"PeerWithOnion" -> {
|
||||
val profile: String = call.argument("ProfileOnion") ?: ""
|
||||
val onion: String = call.argument("onion") ?: ""
|
||||
result.success(Cwtch.peerWithOnion(profile, onion))
|
||||
return
|
||||
Cwtch.peerWithOnion(profile, onion)
|
||||
}
|
||||
|
||||
|
||||
|
@ -493,14 +499,17 @@ class MainActivity: FlutterActivity() {
|
|||
}
|
||||
"GetProfileAttribute" -> {
|
||||
val profile: String = call.argument("ProfileOnion") ?: ""
|
||||
val key: String = call.argument("Key") ?: ""
|
||||
Data.Builder().putString("result", Cwtch.getProfileAttribute(profile, key)).build()
|
||||
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") ?: ""
|
||||
Data.Builder().putString("result", Cwtch.getConversationAttribute(profile, conversation.toLong(), key)).build()
|
||||
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") ?: ""
|
||||
|
@ -512,7 +521,14 @@ class MainActivity: FlutterActivity() {
|
|||
"ImportProfile" -> {
|
||||
val file: String = call.argument("file") ?: ""
|
||||
val pass: String = call.argument("pass") ?: ""
|
||||
Data.Builder().putString("result", Cwtch.importProfile(file, pass)).build()
|
||||
result.success(Cwtch.importProfile(file, pass))
|
||||
return
|
||||
}
|
||||
"SearchConversations" -> {
|
||||
val profile: String = call.argument("ProfileOnion") ?: ""
|
||||
val pattern: String = call.argument("pattern") ?: ""
|
||||
result.success(Cwtch.searchConversations(profile, pattern))
|
||||
return
|
||||
}
|
||||
"ReconnectCwtchForeground" -> {
|
||||
Cwtch.reconnectCwtchForeground()
|
||||
|
|
|
@ -0,0 +1,241 @@
|
|||
/* 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) }
|
||||
}
|
|
@ -4,4 +4,5 @@ VERSION=`cat LIBCWTCH-GO.version`
|
|||
echo $VERSION
|
||||
|
||||
curl --fail https://build.openprivacy.ca/files/libCwtch-autobindings-$VERSION/android/cwtch.aar --output android/cwtch/cwtch.aar
|
||||
curl --fail https://build.openprivacy.ca/files/libCwtch-autobindings-$VERSION/linux/libCwtch.so --output linux/libCwtch.so
|
||||
# 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
|
|
@ -5,6 +5,7 @@ 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
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
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
|
||||
#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
|
||||
#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
|
||||
|
|
|
@ -2,7 +2,6 @@ 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,12 +1,14 @@
|
|||
@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 expect the file 'integration_test/env/temp/dev/tor/torrc' to exist
|
||||
And I wait for 5 seconds
|
|
@ -32,6 +32,9 @@ 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
|
||||
|
|
|
@ -56,6 +56,7 @@ void main() async {
|
|||
// files
|
||||
FolderExists(),
|
||||
FileExists(),
|
||||
WaitFileExists(),
|
||||
];
|
||||
|
||||
var sb = StringBuffer();
|
||||
|
|
|
@ -19,3 +19,16 @@ 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();
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -33,7 +33,6 @@ StepDefinitionGeneric TorVersionPresent() {
|
|||
break;
|
||||
}
|
||||
}
|
||||
print('File is now closed.');
|
||||
} catch (e) {
|
||||
print('Error: $e');
|
||||
}
|
||||
|
@ -41,15 +40,18 @@ StepDefinitionGeneric TorVersionPresent() {
|
|||
context.expect(versionString, "#.#.#", reason: "error reading version string from fetch-tor.sh");
|
||||
return;
|
||||
}
|
||||
context.world.attach(versionString, "text/plain", "Then I expect the Tor version to be present");
|
||||
context.world.attach( versionString.substring(0,4), "text/plain", "Then I expect the Tor version to be present");
|
||||
//context.reporter.message("test!!!", MessageLevel.info);
|
||||
print("looking for version string $versionString");
|
||||
final finder = context.world.appDriver.findBy(
|
||||
versionString,
|
||||
FindType.text,
|
||||
);
|
||||
final isP = await context.world.appDriver.isPresent(finder);
|
||||
context.expect(isP, true);
|
||||
|
||||
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);
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -19,3 +19,4 @@ StepDefinitionGeneric TakeScreenshot() {
|
|||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
||||
#include "Generated.xcconfig"
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
||||
#include "Generated.xcconfig"
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
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, // bespoke value courtesy of the [TextField] docs
|
||||
height: 200,
|
||||
child: Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(30.0),
|
||||
|
@ -18,17 +22,24 @@ void modalOpenLink(BuildContext ctx, LinkableElement link) {
|
|||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
Text(AppLocalizations.of(bcontext)!.clickableLinksWarning),
|
||||
Text(
|
||||
AppLocalizations.of(bcontext)!.clickableLinksWarning,
|
||||
style: Provider.of<Settings>(bcontext).scaleFonts(defaultTextStyle),
|
||||
),
|
||||
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, semanticsLabel: AppLocalizations.of(bcontext)!.clickableLinksCopy),
|
||||
child: Text(AppLocalizations.of(bcontext)!.clickableLinksCopy,
|
||||
style: Provider.of<Settings>(bcontext).scaleFonts(defaultTextButtonStyle), semanticsLabel: AppLocalizations.of(bcontext)!.clickableLinksCopy),
|
||||
onPressed: () {
|
||||
Clipboard.setData(new ClipboardData(text: link.url));
|
||||
|
||||
final snackBar = SnackBar(
|
||||
content: Text(AppLocalizations.of(bcontext)!.copiedToClipboardNotification),
|
||||
content: Text(
|
||||
AppLocalizations.of(bcontext)!.copiedToClipboardNotification,
|
||||
style: Provider.of<Settings>(bcontext).scaleFonts(defaultTextButtonStyle),
|
||||
),
|
||||
);
|
||||
|
||||
Navigator.pop(bcontext);
|
||||
|
@ -39,15 +50,14 @@ void modalOpenLink(BuildContext ctx, LinkableElement link) {
|
|||
Container(
|
||||
margin: EdgeInsets.symmetric(vertical: 20, horizontal: 10),
|
||||
child: ElevatedButton(
|
||||
child: Text(AppLocalizations.of(bcontext)!.clickableLinkOpen, semanticsLabel: AppLocalizations.of(bcontext)!.clickableLinkOpen),
|
||||
child: Text(AppLocalizations.of(bcontext)!.clickableLinkOpen,
|
||||
style: Provider.of<Settings>(bcontext).scaleFonts(defaultTextButtonStyle), semanticsLabel: AppLocalizations.of(bcontext)!.clickableLinkOpen),
|
||||
onPressed: () async {
|
||||
if (await canLaunch(link.url)) {
|
||||
await launch(link.url);
|
||||
if (await canLaunchUrlString(link.url)) {
|
||||
await launchUrlString(link.url);
|
||||
Navigator.pop(bcontext);
|
||||
} else {
|
||||
final snackBar = SnackBar(
|
||||
content: Text(AppLocalizations.of(bcontext)!.clickableLinkError),
|
||||
);
|
||||
final snackBar = SnackBar(content: Text(AppLocalizations.of(bcontext)!.clickableLinkError, style: Provider.of<Settings>(bcontext).scaleFonts(defaultTextButtonStyle)));
|
||||
ScaffoldMessenger.of(bcontext).showSnackBar(snackBar);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -97,11 +97,11 @@ abstract class Cwtch {
|
|||
Future<dynamic> ImportBundle(String profile, String bundle);
|
||||
// ignore: non_constant_identifier_names
|
||||
void SetProfileAttribute(String profile, String key, String val);
|
||||
String? GetProfileAttribute(String profile, String key);
|
||||
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
|
||||
String? GetConversationAttribute(String profile, int identifier, String s);
|
||||
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
|
||||
|
@ -143,4 +143,8 @@ abstract class Cwtch {
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ class CwtchNotifier {
|
|||
}
|
||||
|
||||
void handleMessage(String type, dynamic data) {
|
||||
//EnvironmentConfig.debugLog("NewEvent $type $data");
|
||||
// EnvironmentConfig.debugLog("NewEvent $type $data");
|
||||
switch (type) {
|
||||
case "CwtchStarted":
|
||||
appState.SetCwtchInit();
|
||||
|
@ -68,25 +68,24 @@ class CwtchNotifier {
|
|||
appState.SetAppError(data["Error"]);
|
||||
break;
|
||||
case "NewPeer":
|
||||
// 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");
|
||||
|
||||
// Update Profile Attributes
|
||||
profileCN.getProfile(data["Identity"])?.setAttribute(0, flwtchState.cwtch.GetProfileAttribute(data["Identity"], "profile.profile-attribute-1"));
|
||||
profileCN.getProfile(data["Identity"])?.setAttribute(1, flwtchState.cwtch.GetProfileAttribute(data["Identity"], "profile.profile-attribute-2"));
|
||||
profileCN.getProfile(data["Identity"])?.setAttribute(2, flwtchState.cwtch.GetProfileAttribute(data["Identity"], "profile.profile-attribute-3"));
|
||||
profileCN.getProfile(data["Identity"])?.setAvailabilityStatus(flwtchState.cwtch.GetProfileAttribute(data["Identity"], "profile.profile-status") ?? "");
|
||||
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) {
|
||||
contact.setAttribute(0, flwtchState.cwtch.GetConversationAttribute(data["Identity"], contact.identifier, "public.profile.profile-attribute-1"));
|
||||
contact.setAttribute(1, flwtchState.cwtch.GetConversationAttribute(data["Identity"], contact.identifier, "public.profile.profile-attribute-2"));
|
||||
contact.setAttribute(2, flwtchState.cwtch.GetConversationAttribute(data["Identity"], contact.identifier, "public.profile.profile-attribute-3"));
|
||||
contact.setAvailabilityStatus(flwtchState.cwtch.GetConversationAttribute(data["Identity"], contact.identifier, "public.profile.profile-status") ?? "");
|
||||
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 ?? ""));
|
||||
});
|
||||
|
||||
break;
|
||||
|
@ -162,10 +161,8 @@ class CwtchNotifier {
|
|||
}
|
||||
break;
|
||||
case "DeleteContact":
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.removeContact(data["ConversationID"]);
|
||||
break;
|
||||
case "DeleteGroup":
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.removeContact(data["ConversationID"]);
|
||||
var identifier = int.parse(data["ConversationID"]);
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.removeContact(identifier);
|
||||
break;
|
||||
case "PeerStateChange":
|
||||
ContactInfoState? contact = profileCN.getProfile(data["ProfileOnion"])?.contactList.findContact(data["RemotePeer"]);
|
||||
|
@ -327,6 +324,7 @@ 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":
|
||||
|
@ -392,6 +390,7 @@ class CwtchNotifier {
|
|||
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") {
|
||||
|
@ -462,6 +461,12 @@ 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");
|
||||
}
|
||||
|
|
|
@ -563,7 +563,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_DeleteContact");
|
||||
var deleteContact = library.lookup<NativeFunction<string_int_to_void_function>>("c_DeleteConversation");
|
||||
// ignore: non_constant_identifier_names
|
||||
final DeleteContact = deleteContact.asFunction<VoidFromStringIntFn>();
|
||||
final u1 = profileOnion.toNativeUtf8();
|
||||
|
@ -788,7 +788,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();
|
||||
|
@ -880,7 +880,7 @@ class CwtchFfi implements Cwtch {
|
|||
|
||||
@override
|
||||
void RestartSharing(String profile, String filekey) {
|
||||
var restartSharingC = library.lookup<NativeFunction<void_from_string_string_function>>("c_RestartSharing");
|
||||
var restartSharingC = library.lookup<NativeFunction<void_from_string_string_function>>("c_RestartFileShare");
|
||||
// ignore: non_constant_identifier_names
|
||||
final RestartSharing = restartSharingC.asFunction<VoidFromStringStringFn>();
|
||||
final utf8profile = profile.toNativeUtf8();
|
||||
|
@ -902,6 +902,18 @@ class CwtchFfi implements Cwtch {
|
|||
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");
|
||||
|
@ -912,6 +924,9 @@ class CwtchFfi implements Cwtch {
|
|||
malloc.free(u1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool IsServersCompiled() {
|
||||
return library.providesSymbol("c_LoadServers");
|
||||
|
@ -967,7 +982,7 @@ class CwtchFfi implements Cwtch {
|
|||
}
|
||||
|
||||
@override
|
||||
String? GetProfileAttribute(String profile, String key) {
|
||||
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>();
|
||||
|
@ -982,17 +997,17 @@ class CwtchFfi implements Cwtch {
|
|||
try {
|
||||
dynamic attributeResult = json.decode(jsonMessage);
|
||||
if (attributeResult["Exists"]) {
|
||||
return attributeResult["Value"];
|
||||
return Future.value(attributeResult["Value"]);
|
||||
}
|
||||
} catch (e) {
|
||||
EnvironmentConfig.debugLog("error getting profile attribute: $e");
|
||||
}
|
||||
|
||||
return null;
|
||||
return Future.value(null);
|
||||
}
|
||||
|
||||
@override
|
||||
String? GetConversationAttribute(String profile, int conversation, String key) {
|
||||
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>();
|
||||
|
@ -1007,13 +1022,13 @@ class CwtchFfi implements Cwtch {
|
|||
try {
|
||||
dynamic attributeResult = json.decode(jsonMessage);
|
||||
if (attributeResult["Exists"]) {
|
||||
return attributeResult["Value"];
|
||||
return Future.value(attributeResult["Value"]);
|
||||
}
|
||||
} catch (e) {
|
||||
EnvironmentConfig.debugLog("error getting profile attribute: $e");
|
||||
}
|
||||
|
||||
return null;
|
||||
return Future.value(null);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -1027,4 +1042,20 @@ class CwtchFfi implements Cwtch {
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -352,7 +352,7 @@ class CwtchGomobile implements Cwtch {
|
|||
|
||||
@override
|
||||
void RestartSharing(String profile, String filekey) {
|
||||
cwtchPlatform.invokeMethod("RestartSharing", {"ProfileOnion": profile, "filekey": filekey});
|
||||
cwtchPlatform.invokeMethod("RestartFileShare", {"ProfileOnion": profile, "filekey": filekey});
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -360,6 +360,12 @@ class CwtchGomobile implements Cwtch {
|
|||
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});
|
||||
|
@ -390,25 +396,34 @@ class CwtchGomobile implements Cwtch {
|
|||
}
|
||||
|
||||
@override
|
||||
String? GetProfileAttribute(String profile, String key) {
|
||||
dynamic attributeResult = cwtchPlatform.invokeMethod("GetProfileAttribute", {"ProfileOnion": profile, "key": key});
|
||||
if (attributeResult["Exists"]) {
|
||||
return attributeResult["Value"];
|
||||
}
|
||||
return null;
|
||||
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
|
||||
String? GetConversationAttribute(String profile, int conversation, String key) {
|
||||
dynamic attributeResult = cwtchPlatform.invokeMethod("GetProfileAttribute", {"ProfileOnion": profile, "conversation": conversation, "key": key});
|
||||
if (attributeResult["Exists"]) {
|
||||
return attributeResult["Value"];
|
||||
}
|
||||
return null;
|
||||
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
|
||||
Future<String> SearchConversations(String profile, String pattern) async {
|
||||
return await cwtchPlatform.invokeMethod("SearchConversations", {"ProfileOnion": profile, "pattern": pattern});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,16 @@
|
|||
{
|
||||
"@@locale": "cy",
|
||||
"@@last_modified": "2023-05-15T21:16:36+02:00",
|
||||
"@@last_modified": "2023-08-21T19:40:19+02:00",
|
||||
"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 \/ 日本語",
|
||||
|
@ -23,7 +33,6 @@
|
|||
"blodeuweddExperimentEnable": "Blodeuwedd Assistant",
|
||||
"localeKo": "Korean \/ 한국어",
|
||||
"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",
|
||||
|
@ -94,7 +103,6 @@
|
|||
"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",
|
||||
|
@ -110,7 +118,6 @@
|
|||
"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,6 +1,16 @@
|
|||
{
|
||||
"@@locale": "da",
|
||||
"@@last_modified": "2023-05-15T21:16:36+02:00",
|
||||
"@@last_modified": "2023-08-21T19:40:19+02:00",
|
||||
"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 \/ 日本語",
|
||||
|
@ -23,7 +33,6 @@
|
|||
"blodeuweddExperimentEnable": "Blodeuwedd Assistant",
|
||||
"localeKo": "Korean \/ 한국어",
|
||||
"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",
|
||||
|
@ -156,7 +165,6 @@
|
|||
"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",
|
||||
|
@ -168,7 +176,6 @@
|
|||
"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",
|
||||
|
|
|
@ -1,11 +1,21 @@
|
|||
{
|
||||
"@@locale": "de",
|
||||
"@@last_modified": "2023-05-15T21:16:36+02:00",
|
||||
"fontScalingDescription": "Adjust the relative font scaling factor applied to text and widgets.",
|
||||
"@@last_modified": "2023-08-21T19:40:19+02:00",
|
||||
"deleteServerConfirmBtn": "Server wirklich löschen",
|
||||
"cannotDeleteServerIfActiveGroups": "There are active groups associated with this Cwtch Server. Please delete them prior to deleting this Cwtch Server entry.",
|
||||
"groupsOnThisServerLabel": "Gruppen, in denen ich bin, werden auf diesem Server gehostet",
|
||||
"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",
|
||||
"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 \/ українською",
|
||||
"profileEnabledDescription": "Starten oder Stoppen des Profils",
|
||||
"defaultScalingText": "Text in Standardgröße (Skalierungsfaktor:",
|
||||
"localeJa": "Japanese \/ 日本語",
|
||||
"retryConnectionTooltip": "Cwtch retries peers regularly, but you can tell Cwtch to try sooner by pushing this button.",
|
||||
"retryConnection": "Retry",
|
||||
"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.",
|
||||
|
@ -26,7 +36,6 @@
|
|||
"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...",
|
||||
|
@ -282,7 +291,6 @@
|
|||
"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",
|
||||
|
@ -294,7 +302,6 @@
|
|||
"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,6 +1,16 @@
|
|||
{
|
||||
"@@locale": "el",
|
||||
"@@last_modified": "2023-05-15T21:16:36+02:00",
|
||||
"@@last_modified": "2023-08-21T19:40:19+02:00",
|
||||
"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 \/ 日本語",
|
||||
|
@ -23,7 +33,6 @@
|
|||
"blodeuweddExperimentEnable": "Blodeuwedd Assistant",
|
||||
"localeKo": "Korean \/ 한국어",
|
||||
"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",
|
||||
|
@ -199,11 +208,9 @@
|
|||
"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!",
|
||||
|
|
|
@ -1,6 +1,16 @@
|
|||
{
|
||||
"@@locale": "en",
|
||||
"@@last_modified": "2023-05-15T21:16:36+02:00",
|
||||
"@@last_modified": "2023-08-21T19:40:19+02:00",
|
||||
"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 \/ 日本語",
|
||||
|
@ -23,7 +33,6 @@
|
|||
"blodeuweddExperimentEnable": "Blodeuwedd Assistant",
|
||||
"localeKo": "Korean \/ 한국어",
|
||||
"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",
|
||||
|
@ -154,7 +163,6 @@
|
|||
"displayNameTooltip": "Please enter a display name",
|
||||
"manageKnownServersButton": "Manage Known Servers",
|
||||
"fieldDescriptionLabel": "Description",
|
||||
"groupsOnThisServerLabel": "Groups I am in hosted on this server",
|
||||
"importLocalServerButton": "Import %1",
|
||||
"importLocalServerSelectText": "Select Local Server",
|
||||
"importLocalServerLabel": "Import a locally hosted server",
|
||||
|
@ -167,7 +175,6 @@
|
|||
"fileSavedTo": "Saved to",
|
||||
"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.",
|
||||
"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.",
|
||||
"deleteServerConfirmBtn": "Really delete server",
|
||||
"deleteServerSuccess": "Successfully deleted server",
|
||||
"enterCurrentPasswordForDeleteServer": "Please enter current password to delete this server",
|
||||
"copyAddress": "Copy Address",
|
||||
|
|
|
@ -1,6 +1,16 @@
|
|||
{
|
||||
"@@locale": "es",
|
||||
"@@last_modified": "2023-05-15T21:16:36+02:00",
|
||||
"@@last_modified": "2023-08-21T19:40:19+02:00",
|
||||
"deleteServerConfirmBtn": "Realmente eliminar el servidor",
|
||||
"cannotDeleteServerIfActiveGroups": "There are active groups associated with this Cwtch Server. Please delete them prior to deleting this Cwtch Server entry.",
|
||||
"groupsOnThisServerLabel": "Grupos alojados en este servidor en los que estoy",
|
||||
"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": "Tamaño predeterminado de texto (factor de escala:",
|
||||
"localeJa": "Japanese \/ 日本語",
|
||||
|
@ -23,7 +33,6 @@
|
|||
"blodeuweddExperimentEnable": "Blodeuwedd Assistant",
|
||||
"localeKo": "Korean \/ 한국어",
|
||||
"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,8 +138,6 @@
|
|||
"torSettingsCustomControlPort": "Puerto de control personalizado",
|
||||
"torSettingsCustomSocksPortDescription": "Usar un puerto personalizad para conexiones de datos al proxy Tor",
|
||||
"serverMetricsLabel": "Métricas del servidor",
|
||||
"groupsOnThisServerLabel": "Grupos alojados en este servidor en los que estoy",
|
||||
"deleteServerConfirmBtn": "Realmente eliminar el servidor",
|
||||
"settingServersDescription": "El experimento de alojar servidores permite alojar y administrar servidores de Cwtch",
|
||||
"settingServers": "Alojar Servidores",
|
||||
"unlockProfileTip": "Crea o desbloquea un perfil para comenzar!",
|
||||
|
|
|
@ -1,6 +1,16 @@
|
|||
{
|
||||
"@@locale": "fr",
|
||||
"@@last_modified": "2023-05-15T21:16:36+02:00",
|
||||
"@@last_modified": "2023-08-21T19:40:19+02:00",
|
||||
"deleteServerConfirmBtn": "Supprimer vraiment le serveur",
|
||||
"cannotDeleteServerIfActiveGroups": "There are active groups associated with this Cwtch Server. Please delete them prior to deleting this Cwtch Server entry.",
|
||||
"groupsOnThisServerLabel": "Les groupes dont je fais partie sont hébergés sur ce serveur",
|
||||
"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": "Taille par défaut du texte (échelle:",
|
||||
"localeJa": "Japanese \/ 日本語",
|
||||
|
@ -23,7 +33,6 @@
|
|||
"blodeuweddExperimentEnable": "Blodeuwedd Assistant",
|
||||
"localeKo": "Korean \/ 한국어",
|
||||
"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",
|
||||
|
@ -165,7 +174,6 @@
|
|||
"importLocalServerSelectText": "Sélectionnez le serveur local",
|
||||
"importLocalServerLabel": "Importer un serveur hébergé localement",
|
||||
"importLocalServerButton": "Importer %1",
|
||||
"groupsOnThisServerLabel": "Les groupes dont je fais partie sont hébergés sur ce serveur",
|
||||
"fieldDescriptionLabel": "Description",
|
||||
"savePeerHistoryDescription": "Détermine s'il faut ou non supprimer tout historique associé au contact.",
|
||||
"newMessagesLabel": "Nouveaux messages",
|
||||
|
@ -178,7 +186,6 @@
|
|||
"enterCurrentPasswordForDeleteServer": "Veuillez saisir le mot de passe actuel pour supprimer ce serveur",
|
||||
"encryptedServerDescription": "Le chiffrement d’un serveur avec un mot de passe le protège des autres personnes qui peuvent également utiliser cet appareil. Les serveurs cryptés ne peuvent pas être déchiffrés, affichés ou accessibles tant que le mot de passe correct n’est pas entré pour les déverrouiller.",
|
||||
"deleteServerSuccess": "Le serveur a été supprimé avec succès",
|
||||
"deleteServerConfirmBtn": "Supprimer vraiment le serveur",
|
||||
"unlockServerTip": "Veuillez créer ou déverrouiller un serveur pour commencer !",
|
||||
"unlockProfileTip": "Veuillez créer ou déverrouiller un profil pour commencer !",
|
||||
"settingServersDescription": "L'expérience des serveurs d'hébergement permet d'héberger et de gérer les serveurs Cwtch.",
|
||||
|
|
|
@ -1,34 +1,43 @@
|
|||
{
|
||||
"@@locale": "it",
|
||||
"@@last_modified": "2023-05-15T21:16:36+02:00",
|
||||
"fontScalingDescription": "Adjust the relative font scaling factor applied to text and widgets.",
|
||||
"@@last_modified": "2023-08-21T19:40:19+02:00",
|
||||
"deleteServerConfirmBtn": "Elimina davvero il server",
|
||||
"cannotDeleteServerIfActiveGroups": "There are active groups associated with this Cwtch Server. Please delete them prior to deleting this Cwtch Server entry.",
|
||||
"groupsOnThisServerLabel": "Gruppi di cui sono parte su questo 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",
|
||||
"retryConnectionTooltip": "Cwtch riprova i peer regolarmente, ma puoi dire a Cwtch di provare prima premendo questo pulsante.",
|
||||
"localeJa": "Giapponese \/ 日本語",
|
||||
"fontScalingDescription": "Regola il fattore di scala relativo dei caratteri applicato al testo e ai widget.",
|
||||
"localeSv": "Svedese \/ Svenska",
|
||||
"localeSw": "Swahili \/ Kiswahili",
|
||||
"localeUk": "Ucraino \/українською",
|
||||
"localeNl": "Olandese \/ Dutch",
|
||||
"localePtBr": "Portoghese brasiliano \/ Português do Brasil",
|
||||
"profileAutostartLabel": "Avvio automatico",
|
||||
"profileEnabled": "Abilita",
|
||||
"profileAutostartDescription": "Controlla se il profilo verrà lanciato automaticamente all'avvio.",
|
||||
"profileEnabledDescription": "Attiva o disattiva il profilo.",
|
||||
"localeSk": "Slovacco \/ Slovák",
|
||||
"localeKo": "Coreano \/ 한국어",
|
||||
"blodeuweddExperimentEnable": "Assistente Blodeuwedd",
|
||||
"blodeuweddDescription": "L'assistente Blodeuwedd aggiunge nuove funzionalità a Cwtch come il riepilogo della trascrizione della chat e la traduzione dei messaggi tramite un modello linguistico ospitato localmente.",
|
||||
"blodeuweddNotSupported": "Questa versione di Cwtch è stata compilata senza il supporto per l'assistente Blodeuwedd.",
|
||||
"blodeuweddPath": "La directory in cui si trova Blodeuwedd sul tuo computer.",
|
||||
"blodeuweddSummarize": "Riassumi la conversazione",
|
||||
"blodeuweddTranslate": "Traduci il messaggio",
|
||||
"blodeuweddProcessing": "Blodeuwedd sta elaborando...",
|
||||
"blodeuweddWarning": "Blodeuwedd utilizza un modello linguistico locale e una serie di piccoli modelli ausiliari per alimentare la sua funzionalità. Queste tecniche sono spesso molto efficaci ma non prive di errori. \n\nSebbene ci siamo impegnati per ridurre al minimo il rischio, esiste ancora la possibilità che i risultati di Blodeuwedd siano errati, allucinati e\/o offensivi. \n\nPer questo Blodeuwedd richiede il download di due componenti aggiuntivi separati da Cwtch, il Blodeuwedd Model (o un modello compatibile) e il Blodeuwedd Runner. \n\nVedere https:\/\/docs.cwtch.im\/docs\/settings\/experiments\/blodeuwedd per ulteriori informazioni su come ottenere questi componenti e configurarli.",
|
||||
"availabilityStatusAvailable": "Disponibile",
|
||||
"availabilityStatusAway": "Assente",
|
||||
"availabilityStatusBusy": "Non disponibile",
|
||||
"availabilityStatusTooltip": "Imposta il tuo stato di disponibilità",
|
||||
"profileInfoHint": "Aggiungi qui alcune informazioni personali pubbliche, ad esempio blog, siti web, breve biografia.",
|
||||
"profileInfoHint2": "È possibile aggiungere fino a 3 campi.",
|
||||
"profileInfoHint3": "I contatti potranno vedere queste informazioni nelle Impostazioni di conversazione. ",
|
||||
"retryConnection": "Riprova",
|
||||
"defaultScalingText": "Testo di dimensioni predefinite (fattore di scala:",
|
||||
"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 \/ 한국어",
|
||||
"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",
|
||||
"localePtBr": "Brazilian Portuguese \/ Português do Brasil",
|
||||
"localeNl": "Dutch \/ Dutch",
|
||||
"tooltipPinConversation": "Aggiungi la conversazione in cima alla lista \"Conversazioni\"",
|
||||
"tooltipUnpinConversation": "Rimuovi la conversazione dalla cima della lista \"Conversazioni\"",
|
||||
"errorDownloadDirectoryDoesNotExist": "La condivisione file non può essere abilitata perché la destinazione dei download non è stata impostata o è impostata su una cartella che non esiste.",
|
||||
|
@ -203,7 +212,6 @@
|
|||
"profileOnionLabel": "Invia questo indirizzo ai contatti con cui vuoi connetterti",
|
||||
"importLocalServerLabel": "Importa un server ospitato localmente",
|
||||
"importLocalServerButton": "Importa %1",
|
||||
"groupsOnThisServerLabel": "Gruppi di cui sono parte su questo server",
|
||||
"fieldDescriptionLabel": "Descrizione",
|
||||
"displayNameTooltip": "Inserisci un nome visualizzato",
|
||||
"manageKnownServersShort": "Server",
|
||||
|
@ -265,7 +273,6 @@
|
|||
"copyAddress": "Copia indirizzo",
|
||||
"enterCurrentPasswordForDeleteServer": "Inserisci la password attuale per eliminare questo server",
|
||||
"deleteServerSuccess": "Server eliminato con successo",
|
||||
"deleteServerConfirmBtn": "Elimina davvero il server",
|
||||
"encryptedServerDescription": "Criptare un server con una password lo protegge da altre persone che potrebbero usare questo dispositivo. I server criptati non possono essere decriptati, visualizzati o accessibili finché non viene inserita la password corretta per sbloccarli.",
|
||||
"fileSavedTo": "Salvato in",
|
||||
"fileInterrupted": "Interrotto",
|
||||
|
|
|
@ -1,6 +1,16 @@
|
|||
{
|
||||
"@@locale": "ja",
|
||||
"@@last_modified": "2023-05-15T21:16:36+02:00",
|
||||
"@@last_modified": "2023-08-21T19:40:19+02:00",
|
||||
"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 \/ 日本語",
|
||||
|
@ -64,7 +74,6 @@
|
|||
"profileInfoHint": "ブログ、ウェブサイト、簡単な経歴など、ご自身に関する公開情報をここに追加してください。",
|
||||
"localeKo": "Korean \/ 한국어",
|
||||
"localeSk": "Slovak \/ Slovák",
|
||||
"profileEnabledDescription": "Start or stop the profile",
|
||||
"profileEnabled": "Enable",
|
||||
"localeNl": "Dutch \/ Dutch",
|
||||
"experimentQRCodeDescription": "QR Code support allows sharing data (such as profile identity) by QR Codes",
|
||||
|
@ -183,7 +192,6 @@
|
|||
"displayNameTooltip": "Please enter a display name",
|
||||
"manageKnownServersButton": "Manage Known Servers",
|
||||
"fieldDescriptionLabel": "Description",
|
||||
"groupsOnThisServerLabel": "Groups I am in hosted on this server",
|
||||
"importLocalServerButton": "Import %1",
|
||||
"importLocalServerSelectText": "Select Local Server",
|
||||
"importLocalServerLabel": "Import a locally hosted server",
|
||||
|
@ -193,7 +201,6 @@
|
|||
"fileCheckingStatus": "Checking download status",
|
||||
"fileInterrupted": "Interrupted",
|
||||
"fileSavedTo": "Saved to",
|
||||
"deleteServerConfirmBtn": "Really delete server",
|
||||
"deleteServerSuccess": "Successfully deleted server",
|
||||
"enterCurrentPasswordForDeleteServer": "Please enter current password to delete this server",
|
||||
"copyAddress": "Copy Address",
|
||||
|
|
|
@ -1,6 +1,138 @@
|
|||
{
|
||||
"@@locale": "ko",
|
||||
"@@last_modified": "2023-05-15T21:16:36+02:00",
|
||||
"@@last_modified": "2023-08-21T19:40:19+02:00",
|
||||
"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",
|
||||
"showMessageButton": "메시지 표시",
|
||||
"addContactConfirm": "연락처 %1 추가",
|
||||
"addContact": "연락처 추가",
|
||||
"sendMessage": "메시지 보내기",
|
||||
"cancel": "취소",
|
||||
"rejected": "거부!",
|
||||
"accepted": "수락!",
|
||||
"localeIt": "이탈리아어 \/ Italiano",
|
||||
"localeEs": "스페인어 \/ Español",
|
||||
"yourProfiles": "내 프로필",
|
||||
"addNewProfileBtn": "새 프로필 추가",
|
||||
"copiedToClipboardNotification": "클립보드에 복사됨",
|
||||
"tooltipHidePassword": "비밀번호 숨기기",
|
||||
"tooltipShowPassword": "비밀번호 표시",
|
||||
"enterCurrentPasswordForDelete": "이 프로파일을 삭제하려면 현재 비밀번호를 입력하십시오.",
|
||||
"password": "비밀번호",
|
||||
"passwordErrorMatch": "비밀번호가 일치하지 않습니다.",
|
||||
"passwordErrorEmpty": "비밀번호는 비워 둘 수 없습니다.",
|
||||
"password2Label": "비밀번호를 다시 입력하세요",
|
||||
"password1Label": "비밀번호",
|
||||
"currentPasswordLabel": "현제 비밀번호",
|
||||
"noPasswordWarning": "이 계정에서 비밀번호를 사용하지 않으면 로컬에 저장된 모든 데이터가 암호화되지 않습니다",
|
||||
"radioNoPassword": "암호화되지 않음(비밀번호 없음)",
|
||||
"radioUsePassword": "비밀번호",
|
||||
"newPassword": "새 비밀번호",
|
||||
"yesLeave": "이 대화에서 나가기 확인",
|
||||
"leaveConversation": "이 대화에서 나가기",
|
||||
"shutdownCwtchAction": "Cwtch (크치)를 종료",
|
||||
"shutdownCwtchTooltip": "Cwtch (크치)를 종료",
|
||||
"shutdownCwtchDialogTitle": "Cwtch (크치)를 종료하시겠습니까?",
|
||||
"successfullAddedContact": "성공적으로 추가되었습니다.",
|
||||
"titleManageServers": "서버 관리",
|
||||
"cwtchSettingsTitle": "Cwtch (크치) 설정",
|
||||
"titleManageProfiles": "Cwtch (크치) 프로파일 관리",
|
||||
"tooltipAddContact": "새 연락처 또는 대화 추가",
|
||||
"tooltipOpenSettings": "설정 창 열기",
|
||||
"contactAlreadyExists": "연락처가 이미 있음",
|
||||
"conversationSettings": "대화 설정",
|
||||
"titleManageContacts": "대화",
|
||||
"enableGroups": "그룹 채팅 사용",
|
||||
"zoomLabel": "인터페이스 확대\/축소(주로 텍스트 및 버튼 크기에 영향을 줌)",
|
||||
"blockUnknownLabel": "알 수 없는 연락처 차단",
|
||||
"unlock": "잠금 해제",
|
||||
"acceptGroupInviteLabel": "초대를 수락하시겠습니까?",
|
||||
"bulletinsBtn": "게시판",
|
||||
"update": "업데이트",
|
||||
"serverNotSynced": "새 메시지 동기화 중(시간이 걸릴 수 있음)...",
|
||||
"serverConnectivityDisconnected": "서버 연결 끊김",
|
||||
"search": "검색...",
|
||||
"postNewBulletinLabel": "새 게시판 게시",
|
||||
"newBulletinLabel": "새 게시판",
|
||||
"joinGroup": "그룹 가입",
|
||||
"invitation": "초대",
|
||||
"joinGroupTab": "그룹 가입",
|
||||
"displayNameLabel": "표시 이름",
|
||||
"puzzleGameBtn": "퍼즐 게임",
|
||||
"searchList": "목록 검색",
|
||||
"inviteBtn": "초대",
|
||||
"inviteToGroupLabel": "그룹에 초대",
|
||||
"groupNameLabel": "그룹 이름",
|
||||
"viewServerInfo": "서버 정보",
|
||||
"titlePlaceholder": "자격",
|
||||
"addProfileTitle": "새 프로필 추가",
|
||||
"newProfile": "새 프로필",
|
||||
"newConnectionPaneTitle": "새로운 연결",
|
||||
"networkStatusOnline": "온라인",
|
||||
"smallTextLabel": "작은",
|
||||
"themeLight": "밝음",
|
||||
"settingTheme": "밝은 테마 사용",
|
||||
"themeDark": "어둠",
|
||||
"largeTextLabel": "큰",
|
||||
"localeDe": "독일어 \/ Deutsch",
|
||||
"localePt": "포르투갈어 \/ Português",
|
||||
"localeFr": "프랑스어 \/ Français",
|
||||
"localeEn": "영어 \/ English",
|
||||
"settingLanguage": "언어",
|
||||
"yourServers": "서버",
|
||||
"deleteBtn": "삭제",
|
||||
"saveBtn": "저장",
|
||||
"serverSynced": "동기화",
|
||||
"serverConnectivityConnected": "서버 연결됨",
|
||||
"serverInfo": "서버 정보",
|
||||
"invitationLabel": "초대",
|
||||
"serverLabel": "서버",
|
||||
"blocked": "차단됨",
|
||||
"createGroup": "그룹 만들기",
|
||||
"addPeer": "연락처 추가",
|
||||
"groupAddr": "주소",
|
||||
"server": "서버",
|
||||
"peerName": "이름",
|
||||
"peerAddress": "주소",
|
||||
"builddate": "Built on: %2",
|
||||
"deleteProfileConfirmBtn": "프로필 삭제 확인",
|
||||
"deleteConfirmLabel": "DELETE를 입력하여 확인",
|
||||
"deleteProfileBtn": "프로필 삭제",
|
||||
"saveProfileBtn": "프로필 저장",
|
||||
"createProfileBtn": "프로필 만들기",
|
||||
"yourDisplayName": "표시 이름",
|
||||
"profileOnionLabel": "연결하려는 연락처에 이 주소를 보냅니다.",
|
||||
"editProfile": "프로필 편집",
|
||||
"defaultProfileName": "앨리스",
|
||||
"profileName": "표시 이름",
|
||||
"editProfileTitle": "프로필 편집",
|
||||
"dontSavePeerHistory": "기록 삭제",
|
||||
"savePeerHistory": "기록 저장",
|
||||
"blockBtn": "연락처 차단",
|
||||
"addressLabel": "주소",
|
||||
"listsBtn": "목록",
|
||||
"chatBtn": "채팅",
|
||||
"acceptGroupBtn": "동의",
|
||||
"rejectGroupBtn": "거부",
|
||||
"newGroupBtn": "새 그룹 만들기",
|
||||
"copyBtn": "복사",
|
||||
"peerOfflineMessage": "연락처가 오프라인 상태이므로 지금은 메시지를 전달할 수 없습니다.",
|
||||
"peerBlockedMessage": "연락처가 차단되었습니다.",
|
||||
"pendingLabel": "보류 중",
|
||||
"acknowledgedLabel": "인정됨",
|
||||
"couldNotSendMsgError": "이 메시지를 보낼 수 없습니다.",
|
||||
"dmTooltip": "DM으로 클릭하세요.",
|
||||
"membershipDescription": "다음은 그룹에 메시지를 보낸 사용자 목록입니다. 이 목록에는 그룹에 액세스할 수 있는 모든 사용자가 표시되지 않을 수 있습니다.",
|
||||
"addListItemBtn": "아이템 추가",
|
||||
"peerNotOnline": "연락처가 오프라인 상태입니다. 지금은 응용 프로그램을 사용할 수 없습니다.",
|
||||
"localeUk": "Ukrainian \/ українською",
|
||||
"profileEnabledDescription": "프로필 시각 또는 중지",
|
||||
"localeSw": "Swahili \/ Kiswahili",
|
||||
"localeSv": "Swedish \/ Svenska",
|
||||
"fontScalingDescription": "Adjust the relative font scaling factor applied to text and widgets.",
|
||||
"defaultScalingText": "Font Scaling",
|
||||
"localeJa": "Japanese \/ 日本語",
|
||||
|
@ -10,7 +142,6 @@
|
|||
"addPeerTab": "연락처 추가",
|
||||
"createGroupBtn": "창조",
|
||||
"defaultGroupName": "굉장한 그룹",
|
||||
"serverLabel": "Server",
|
||||
"createGroupTitle": "그룹 만들기",
|
||||
"availabilityStatusAway": "자리 비움",
|
||||
"availabilityStatusBusy": "바쁘다",
|
||||
|
@ -59,8 +190,6 @@
|
|||
"notificationContentContactInfo": "대화 정보",
|
||||
"newMessageNotificationConversationInfo": "%1의 새로운 메시지",
|
||||
"localePl": "폴란드어 \/ Polski",
|
||||
"addContact": "Add contact",
|
||||
"addContactConfirm": "Add contact %1",
|
||||
"downloadFileButton": "다운로드",
|
||||
"labelFilesize": "크기",
|
||||
"messageFileSent": "파일을 보냈습니다.",
|
||||
|
@ -124,7 +253,6 @@
|
|||
"profileAutostartDescription": "시작 시 프로필이 자동으로 시작되는지 여부를 제어합니다.",
|
||||
"profileAutostartLabel": "자동 시작",
|
||||
"profileEnabled": "허락",
|
||||
"profileEnabledDescription": "프로필 시각 또는 중지",
|
||||
"replyingTo": "%1에 회신",
|
||||
"tooltipCode": "Code \/ Monospace",
|
||||
"tooltipStrikethrough": "Strikethrough",
|
||||
|
@ -169,7 +297,6 @@
|
|||
"serverTotalMessagesLabel": "Total Messages",
|
||||
"displayNameTooltip": "Please enter a display name",
|
||||
"fieldDescriptionLabel": "Description",
|
||||
"groupsOnThisServerLabel": "Groups I am in hosted on this server",
|
||||
"importLocalServerSelectText": "Select Local Server",
|
||||
"importLocalServerLabel": "Import a locally hosted server",
|
||||
"copyServerKeys": "Copy keys",
|
||||
|
@ -179,7 +306,6 @@
|
|||
"fileSavedTo": "Saved to",
|
||||
"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",
|
||||
"enterCurrentPasswordForDeleteServer": "Please enter current password to delete this server",
|
||||
"settingServersDescription": "The hosting servers experiment enables hosting and managing Cwtch servers",
|
||||
"enterServerPassword": "Enter password to unlock server",
|
||||
|
@ -204,7 +330,6 @@
|
|||
"streamerModeLabel": "Streamer\/Presentation Mode",
|
||||
"archiveConversation": "Archive this Conversation",
|
||||
"blockUnknownConnectionsEnabledDescription": "Connections from unknown contacts are blocked. You can change this in Settings",
|
||||
"showMessageButton": "Show Message",
|
||||
"blockedMessageMessage": "This message is from a profile you have blocked.",
|
||||
"placeholderEnterMessage": "Type a message...",
|
||||
"plainProfileDescription": "We recommend that you protect your Cwtch profiles with a password. If you do not set a password on this profile then anyone who has access to this device may be able to access information about this profile, including contacts, messages and sensitive cryptographic keys.",
|
||||
|
@ -222,13 +347,8 @@
|
|||
"tooltipAcceptContactRequest": "Accept this contact request.",
|
||||
"notificationNewMessageFromGroup": "New message in a group!",
|
||||
"notificationNewMessageFromPeer": "New message from a contact!",
|
||||
"tooltipHidePassword": "Hide Password",
|
||||
"tooltipShowPassword": "Show Password",
|
||||
"groupInviteSettingsWarning": "You have been invited to join a group! Please enable the Group Chat Experiment in Settings to view this Invitation.",
|
||||
"shutdownCwtchAction": "Shutdown Cwtch",
|
||||
"shutdownCwtchDialog": "Are you sure you want to shutdown Cwtch? This will close all connections, and exit the application.",
|
||||
"shutdownCwtchDialogTitle": "Shutdown Cwtch?",
|
||||
"shutdownCwtchTooltip": "Shutdown Cwtch",
|
||||
"malformedMessage": "Malformed message",
|
||||
"profileDeleteSuccess": "Successfully deleted profile",
|
||||
"debugLog": "Turn on console debug logging",
|
||||
|
@ -239,150 +359,37 @@
|
|||
"addServerFirst": "You need to add a server before you can create a group",
|
||||
"deleteProfileSuccess": "Successfully deleted profile",
|
||||
"sendInvite": "Send a contact or group invite",
|
||||
"sendMessage": "Send Message",
|
||||
"cancel": "Cancel",
|
||||
"resetTor": "Reset",
|
||||
"torStatus": "Tor Status",
|
||||
"torVersion": "Tor Version",
|
||||
"sendAnInvitation": "You sent an invitation for: ",
|
||||
"contactSuggestion": "This is a contact suggestion for: ",
|
||||
"rejected": "Rejected!",
|
||||
"accepted": "Accepted!",
|
||||
"chatHistoryDefault": "This conversation will be deleted when Cwtch is closed! Message history can be enabled per-conversation via the Settings menu in the upper right.",
|
||||
"newPassword": "New Password",
|
||||
"yesLeave": "Yes, Leave This Conversation",
|
||||
"reallyLeaveThisGroupPrompt": "Are you sure you want to leave this conversation? All messages and attributes will be deleted.",
|
||||
"leaveConversation": "Leave This Conversation",
|
||||
"inviteToGroup": "You have been invited to join a group:",
|
||||
"titleManageServers": "Manage Servers",
|
||||
"successfullAddedContact": "Successfully added ",
|
||||
"descriptionBlockUnknownConnections": "If turned on, this option will automatically close connections from Cwtch users that have not been added to your contact list.",
|
||||
"descriptionExperimentsGroups": "The group experiment allows Cwtch to connect with untrusted server infrastructure to facilitate communication with more than one contact.",
|
||||
"descriptionExperiments": "Cwtch experiments are optional, opt-in features that add additional functionality to Cwtch that may have different privacy considerations than traditional 1:1 metadata resistant chat e.g. group chat, bot integration etc.",
|
||||
"titleManageProfiles": "Manage Cwtch Profiles",
|
||||
"tooltipUnlockProfiles": "Unlock encrypted profiles by entering their password.",
|
||||
"titleManageContacts": "Conversations",
|
||||
"tooltipAddContact": "Add a new contact or conversation",
|
||||
"tooltipOpenSettings": "Open the settings pane",
|
||||
"contactAlreadyExists": "Contact Already Exists",
|
||||
"invalidImportString": "Invalid import string",
|
||||
"conversationSettings": "Conversation Settings",
|
||||
"enterCurrentPasswordForDelete": "Please enter current password to delete this profile.",
|
||||
"enableGroups": "Enable Group Chat",
|
||||
"localeIt": "Italian \/ Italiano",
|
||||
"localeEs": "Spanish \/ Español",
|
||||
"todoPlaceholder": "Todo...",
|
||||
"addNewItem": "Add a new item to the list",
|
||||
"addListItem": "Add a New List Item",
|
||||
"newConnectionPaneTitle": "New Connection",
|
||||
"networkStatusOnline": "Online",
|
||||
"networkStatusConnecting": "Connecting to network and contacts...",
|
||||
"networkStatusAttemptingTor": "Attempting to connect to Tor network",
|
||||
"networkStatusDisconnected": "Disconnected from the internet, check your connection",
|
||||
"viewGroupMembershipTooltip": "View Group Membership",
|
||||
"loadingTor": "Loading tor...",
|
||||
"smallTextLabel": "Small",
|
||||
"builddate": "Built on: %2",
|
||||
"version": "Version %1",
|
||||
"versionTor": "Version %1 with tor %2",
|
||||
"experimentsEnabled": "Enable Experiments",
|
||||
"themeDark": "Dark",
|
||||
"themeLight": "Light",
|
||||
"settingTheme": "Use Light Themes",
|
||||
"largeTextLabel": "Large",
|
||||
"settingInterfaceZoom": "Zoom level",
|
||||
"localeDe": "German \/ Deutsch",
|
||||
"localePt": "Portuguese \/ Portuguesa",
|
||||
"localeFr": "French \/ Français",
|
||||
"localeEn": "English \/ English",
|
||||
"settingLanguage": "Language",
|
||||
"blockUnknownLabel": "Block Unknown Contacts",
|
||||
"zoomLabel": "Interface zoom (mostly affects text and button sizes)",
|
||||
"versionBuilddate": "Version: %1 Built on: %2",
|
||||
"cwtchSettingsTitle": "Cwtch Settings",
|
||||
"unlock": "Unlock",
|
||||
"yourServers": "Your Servers",
|
||||
"yourProfiles": "Your Profiles",
|
||||
"error0ProfilesLoadedForPassword": "0 profiles loaded with that password",
|
||||
"password": "Password",
|
||||
"enterProfilePassword": "Enter a password to view your profiles",
|
||||
"addNewProfileBtn": "Add new profile",
|
||||
"deleteConfirmText": "DELETE",
|
||||
"deleteProfileConfirmBtn": "Really Delete Profile",
|
||||
"deleteConfirmLabel": "Type DELETE to confirm",
|
||||
"deleteProfileBtn": "Delete Profile",
|
||||
"passwordChangeError": "Error changing password: Supplied password rejected",
|
||||
"passwordErrorMatch": "Passwords do not match",
|
||||
"saveProfileBtn": "Save Profile",
|
||||
"createProfileBtn": "Create Profile",
|
||||
"passwordErrorEmpty": "Password cannot be empty",
|
||||
"password2Label": "Reenter password",
|
||||
"password1Label": "Password",
|
||||
"currentPasswordLabel": "Current Password",
|
||||
"yourDisplayName": "Your Display Name",
|
||||
"profileOnionLabel": "Send this address to contacts 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",
|
||||
"editProfile": "Edit Profile",
|
||||
"newProfile": "New Profile",
|
||||
"defaultProfileName": "Alice",
|
||||
"profileName": "Display name",
|
||||
"editProfileTitle": "Edit Profile",
|
||||
"addProfileTitle": "Add new profile",
|
||||
"deleteBtn": "Delete",
|
||||
"unblockBtn": "Unblock Contact",
|
||||
"dontSavePeerHistory": "Delete History",
|
||||
"savePeerHistoryDescription": "Determines whether to delete any history associated with the contact.",
|
||||
"savePeerHistory": "Save History",
|
||||
"blockBtn": "Block Contact",
|
||||
"saveBtn": "Save",
|
||||
"displayNameLabel": "Display Name",
|
||||
"copiedToClipboardNotification": "Copied to Clipboard",
|
||||
"addressLabel": "Address",
|
||||
"puzzleGameBtn": "Puzzle Game",
|
||||
"bulletinsBtn": "Bulletins",
|
||||
"listsBtn": "Lists",
|
||||
"chatBtn": "Chat",
|
||||
"rejectGroupBtn": "Reject",
|
||||
"acceptGroupBtn": "Accept",
|
||||
"acceptGroupInviteLabel": "Do you want to accept the invitation to",
|
||||
"newGroupBtn": "Create new group",
|
||||
"copyBtn": "Copy",
|
||||
"peerOfflineMessage": "Contact is offline, messages can't be delivered right now",
|
||||
"peerBlockedMessage": "Contact 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": "Contact is offline. Applications cannot be used right now.",
|
||||
"searchList": "Search List",
|
||||
"update": "Update",
|
||||
"inviteBtn": "Invite",
|
||||
"inviteToGroupLabel": "Invite to group",
|
||||
"groupNameLabel": "Group Name",
|
||||
"viewServerInfo": "Server Info",
|
||||
"serverNotSynced": "Syncing New Messages (This can take some time)...",
|
||||
"serverSynced": "Synced",
|
||||
"serverConnectivityDisconnected": "Server Disconnected",
|
||||
"serverConnectivityConnected": "Server Connected",
|
||||
"serverInfo": "Server Information",
|
||||
"invitationLabel": "Invitation",
|
||||
"search": "Search...",
|
||||
"blocked": "Blocked",
|
||||
"pasteAddressToAddContact": "Paste a cwtch address, invitation or key bundle here to add a new conversation",
|
||||
"titlePlaceholder": "title...",
|
||||
"postNewBulletinLabel": "Post new bulletin",
|
||||
"newBulletinLabel": "New Bulletin",
|
||||
"joinGroup": "Join group",
|
||||
"createGroup": "Create group",
|
||||
"addPeer": "Add Contact",
|
||||
"groupAddr": "Address",
|
||||
"invitation": "Invitation",
|
||||
"server": "Server",
|
||||
"peerName": "Name",
|
||||
"peerAddress": "Address",
|
||||
"joinGroupTab": "Join a group"
|
||||
"pasteAddressToAddContact": "Paste a cwtch address, invitation or key bundle here to add a new conversation"
|
||||
}
|
|
@ -1,6 +1,16 @@
|
|||
{
|
||||
"@@locale": "lb",
|
||||
"@@last_modified": "2023-05-15T21:16:36+02:00",
|
||||
"@@last_modified": "2023-08-21T19:40:19+02:00",
|
||||
"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 \/ 日本語",
|
||||
|
@ -23,7 +33,6 @@
|
|||
"blodeuweddExperimentEnable": "Blodeuwedd Assistant",
|
||||
"localeKo": "Korean \/ 한국어",
|
||||
"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",
|
||||
|
@ -247,7 +256,6 @@
|
|||
"displayNameTooltip": "Please enter a display name",
|
||||
"manageKnownServersButton": "Manage Known Servers",
|
||||
"fieldDescriptionLabel": "Description",
|
||||
"groupsOnThisServerLabel": "Groups I am in hosted on this server",
|
||||
"importLocalServerButton": "Import %1",
|
||||
"importLocalServerSelectText": "Select Local Server",
|
||||
"importLocalServerLabel": "Import a locally hosted server",
|
||||
|
@ -259,7 +267,6 @@
|
|||
"fileSavedTo": "Saved to",
|
||||
"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",
|
||||
"deleteServerSuccess": "Successfully deleted server",
|
||||
"enterCurrentPasswordForDeleteServer": "Please enter current password to delete this server",
|
||||
"copyAddress": "Copy Address",
|
||||
|
|
|
@ -1,31 +1,40 @@
|
|||
{
|
||||
"@@locale": "nl",
|
||||
"@@last_modified": "2023-05-15T21:16:36+02:00",
|
||||
"@@last_modified": "2023-08-21T19:40:19+02:00",
|
||||
"deleteServerConfirmBtn": "Server echt verwijderen",
|
||||
"cannotDeleteServerIfActiveGroups": "There are active groups associated with this Cwtch Server. Please delete them prior to deleting this Cwtch Server entry.",
|
||||
"groupsOnThisServerLabel": "Groepen waarin ik zit gehost op deze 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",
|
||||
"profileEnabledDescription": "Activeer of deactiveer het profiel.",
|
||||
"defaultScalingText": "Lettertype schalen",
|
||||
"blodeuweddSummarize": "Gesprek samenvatten",
|
||||
"blodeuweddTranslate": "Bericht vertalen",
|
||||
"blodeuweddProcessing": "Blodeuwedd is aan het verwerken...",
|
||||
"blodeuweddPath": "De map waar de Blodeuwedd zich bevindt op je computer.",
|
||||
"blodeuweddNotSupported": "Deze versie van Cwtch is gecompileerd zonder ondersteuning voor de Blodeuwedd Assistant.",
|
||||
"blodeuweddExperimentEnable": "Blodeuwedd Assistent",
|
||||
"localeKo": "Koreaans \/ 한국어",
|
||||
"fontScalingDescription": "Adjust the relative font scaling factor applied to text and widgets.",
|
||||
"defaultScalingText": "Standaardtekstgrootte (schaalfactor:",
|
||||
"localeJa": "Japanese \/ 日本語",
|
||||
"availabilityStatusTooltip": "Stel je beschikbaarheidsstatus in",
|
||||
"profileInfoHint2": "Je kunt maximaal 3 velden toevoegen.",
|
||||
"availabilityStatusBusy": "Bezig",
|
||||
"availabilityStatusAway": "Afwezig",
|
||||
"availabilityStatusAvailable": "Beschikbaar",
|
||||
"retryConnection": "Opnieuw",
|
||||
"localeJa": "Japans \/ 日本語",
|
||||
"localeSv": "Zweeds \/ Svenska",
|
||||
"localeSw": "Swahili \/ Kiswahili",
|
||||
"localeUk": "Oekraïens \/ українською",
|
||||
"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 \/ 한국어",
|
||||
"profileAutostartDescription": "Regelt of het profiel automatisch wordt gestart bij het opstarten",
|
||||
"profileAutostartLabel": "Automatisch starten",
|
||||
"profileEnabled": "Inschakelen",
|
||||
"profileEnabledDescription": "Start of stop het profiel",
|
||||
"localeSk": "Slowaaks \/ Slovák",
|
||||
"localePtBr": "Braziliaans Portugees \/ Português do Brasil",
|
||||
"acquiredTicketsFromServer": "Anti-spam uitdaging voltooid",
|
||||
|
@ -74,7 +83,6 @@
|
|||
"addContactFirst": "Voeg een contact toe of kies een contact om te beginnen met chatten.",
|
||||
"experimentClickableLinksDescription": "Het klikbare links experiment maakt het mogelijk op URLs te klikken in berichten",
|
||||
"enableExperimentClickableLinks": "Klikbare links inschakelen",
|
||||
"groupsOnThisServerLabel": "Groepen waarin ik zit gehost op deze server",
|
||||
"displayNameTooltip": "Voer een weergavenaam in",
|
||||
"tooltipBackToMessageEditing": "Terug naar bericht bewerken",
|
||||
"editServerTitle": "Server bewerken",
|
||||
|
@ -144,7 +152,6 @@
|
|||
"fileCheckingStatus": "Downloadstatus controleren",
|
||||
"fileInterrupted": "Onderbroken",
|
||||
"fileSavedTo": "Opgeslagen in",
|
||||
"deleteServerConfirmBtn": "Server echt verwijderen",
|
||||
"deleteServerSuccess": "Server succesvol verwijderd",
|
||||
"enterCurrentPasswordForDeleteServer": "Voer huidige wachtwoord in om deze server te verwijderen",
|
||||
"settingServersDescription": "Het servers hosten experiment maakt het mogelijk Cwtch-servers te hosten en te beheren",
|
||||
|
|
|
@ -1,6 +1,16 @@
|
|||
{
|
||||
"@@locale": "no",
|
||||
"@@last_modified": "2023-05-15T21:16:36+02:00",
|
||||
"@@last_modified": "2023-08-21T19:40:19+02:00",
|
||||
"deleteServerConfirmBtn": "Slette tjener",
|
||||
"cannotDeleteServerIfActiveGroups": "There are active groups associated with this Cwtch Server. Please delete them prior to deleting this Cwtch Server entry.",
|
||||
"groupsOnThisServerLabel": "Grupper jeg er vert for på denne tjeneren",
|
||||
"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 tekststørrelse (skaleringsfaktor:",
|
||||
"localeJa": "Japanese \/ 日本語",
|
||||
|
@ -23,7 +33,6 @@
|
|||
"blodeuweddExperimentEnable": "Blodeuwedd Assistant",
|
||||
"localeKo": "Korean \/ 한국어",
|
||||
"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",
|
||||
|
@ -157,7 +166,6 @@
|
|||
"displayNameTooltip": "Oppgi visningsnavn",
|
||||
"manageKnownServersButton": "Tilpass kjente tjenere",
|
||||
"fieldDescriptionLabel": "Beskrivelse",
|
||||
"groupsOnThisServerLabel": "Grupper jeg er vert for på denne tjeneren",
|
||||
"importLocalServerButton": "Importér %1",
|
||||
"importLocalServerSelectText": "Velg lokal tjener",
|
||||
"importLocalServerLabel": "Importér en lokal tjener",
|
||||
|
@ -169,7 +177,6 @@
|
|||
"fileSavedTo": "Lagret til",
|
||||
"encryptedServerDescription": "Kryptering av en tjener med passord beskytter den mot andre som også bruker dette systemet. Krytperte tjenere må låses opp med det korrekte passordet før de kan dekrypteres, vises eller benyttes.",
|
||||
"plainServerDescription": "Vi anbefaler at du beskyter Cwetch-tjenere med et passord. Dersom du ikke setter et passord for tjeneren så kan hvem som helst med tilgang til enheten få fult innsyn i informasjon om tjeneren, inklusive kryptonøkler.",
|
||||
"deleteServerConfirmBtn": "Slette tjener",
|
||||
"deleteServerSuccess": "Tjener slettet",
|
||||
"enterCurrentPasswordForDeleteServer": "Oppgi passord for å slette tjener",
|
||||
"copyAddress": "Kopiér adresse",
|
||||
|
|
|
@ -1,6 +1,16 @@
|
|||
{
|
||||
"@@locale": "pl",
|
||||
"@@last_modified": "2023-05-15T21:16:36+02:00",
|
||||
"@@last_modified": "2023-08-21T19:40:19+02:00",
|
||||
"deleteServerConfirmBtn": "Usuń",
|
||||
"cannotDeleteServerIfActiveGroups": "There are active groups associated with this Cwtch Server. Please delete them prior to deleting this Cwtch Server entry.",
|
||||
"groupsOnThisServerLabel": "Grupy na tym serwerze, których jesteś członkiem",
|
||||
"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": "Domyślny rozmiar tekstu (skalowanie:",
|
||||
"localeJa": "Japanese \/ 日本語",
|
||||
|
@ -23,7 +33,6 @@
|
|||
"blodeuweddExperimentEnable": "Blodeuwedd Assistant",
|
||||
"localeKo": "Korean \/ 한국어",
|
||||
"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",
|
||||
|
@ -258,7 +267,6 @@
|
|||
"displayNameTooltip": "Wprowadź nazwę",
|
||||
"manageKnownServersButton": "Zarządzaj znanymi serwerami",
|
||||
"fieldDescriptionLabel": "Opis",
|
||||
"groupsOnThisServerLabel": "Grupy na tym serwerze, których jesteś członkiem",
|
||||
"importLocalServerButton": "Importuj %1",
|
||||
"importLocalServerSelectText": "Wybierz lokalny serwer",
|
||||
"importLocalServerLabel": "Importuj lokalnie hostowany serwer",
|
||||
|
@ -266,7 +274,6 @@
|
|||
"fileInterrupted": "Przerwano",
|
||||
"encryptedServerDescription": "Zaszyfrowanie serwera hasłem chroni go przed dostępem innych osób korzystających z tego urządzenia.",
|
||||
"plainServerDescription": "Zalecamy ustawienie hasła dla Cwtch. Jeśli hasło nie zostanie ustawione, każdy z dostępem do tego urządzenia uzyska dostęp do tego serwera, w tym do wrażliwych kluczy kryptograficznych.",
|
||||
"deleteServerConfirmBtn": "Usuń",
|
||||
"deleteServerSuccess": "Usunięto serwer",
|
||||
"settingServersDescription": "Hostowanie serwerów (eksperymentalne) umożliwia tworzenie i zarządzanie serwerami Cwtch",
|
||||
"settingServers": "Hostowanie serwerów",
|
||||
|
|
|
@ -1,6 +1,16 @@
|
|||
{
|
||||
"@@locale": "pt",
|
||||
"@@last_modified": "2023-05-15T21:16:36+02:00",
|
||||
"@@last_modified": "2023-08-21T19:40:19+02:00",
|
||||
"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": "Texto tamanho padrão (fator de escala: ",
|
||||
"localeJa": "Japanese \/ 日本語",
|
||||
|
@ -23,7 +33,6 @@
|
|||
"blodeuweddExperimentEnable": "Blodeuwedd Assistant",
|
||||
"localeKo": "Korean \/ 한국어",
|
||||
"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",
|
||||
|
@ -152,7 +161,6 @@
|
|||
"displayNameTooltip": "Please enter a display name",
|
||||
"manageKnownServersButton": "Manage Known Servers",
|
||||
"fieldDescriptionLabel": "Description",
|
||||
"groupsOnThisServerLabel": "Groups I am in hosted on this server",
|
||||
"importLocalServerButton": "Import %1",
|
||||
"importLocalServerSelectText": "Select Local Server",
|
||||
"importLocalServerLabel": "Import a locally hosted server",
|
||||
|
@ -164,7 +172,6 @@
|
|||
"fileSavedTo": "Saved to",
|
||||
"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",
|
||||
"deleteServerSuccess": "Successfully deleted server",
|
||||
"enterCurrentPasswordForDeleteServer": "Please enter current password to delete this server",
|
||||
"copyAddress": "Copy Address",
|
||||
|
|
|
@ -1,6 +1,16 @@
|
|||
{
|
||||
"@@locale": "pt_BR",
|
||||
"@@last_modified": "2023-05-15T21:16:36+02:00",
|
||||
"@@last_modified": "2023-08-21T19:40:19+02:00",
|
||||
"deleteServerConfirmBtn": "Realmente excluir servidor",
|
||||
"cannotDeleteServerIfActiveGroups": "There are active groups associated with this Cwtch Server. Please delete them prior to deleting this Cwtch Server entry.",
|
||||
"groupsOnThisServerLabel": "Grupos nos quais estou hospedado neste servidor",
|
||||
"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": "Texto tamanho padrão (fator de escala: ",
|
||||
"localeJa": "Japanese \/ 日本語",
|
||||
|
@ -23,7 +33,6 @@
|
|||
"blodeuweddExperimentEnable": "Blodeuwedd Assistant",
|
||||
"localeKo": "Korean \/ 한국어",
|
||||
"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",
|
||||
|
@ -144,7 +153,6 @@
|
|||
"displayNameTooltip": "Por favor, digite um nome de exibição",
|
||||
"manageKnownServersButton": "Gerenciar Servidores Conhecidos",
|
||||
"fieldDescriptionLabel": "Descrição",
|
||||
"groupsOnThisServerLabel": "Grupos nos quais estou hospedado neste servidor",
|
||||
"importLocalServerButton": "Importar %1",
|
||||
"importLocalServerSelectText": "Selecione Servidor Local",
|
||||
"importLocalServerLabel": "Importar um servidor hospedado localmente",
|
||||
|
@ -157,7 +165,6 @@
|
|||
"fileSavedTo": "Salvar em",
|
||||
"encryptedServerDescription": "Criptografar um servidor com uma senha o protege de outras pessoas que também podem usar este dispositivo. Os servidores criptografados não podem ser descriptografados, exibidos ou acessados até que a senha correta seja inserida para desbloqueá-los.",
|
||||
"plainServerDescription": "Recomendamos que você proteja seus servidores Cwtch com uma senha. Se você não definir uma senha neste servidor, qualquer pessoa que tenha acesso a este dispositivo poderá acessar informações sobre este servidor, incluindo chaves criptográficas sensíveis.",
|
||||
"deleteServerConfirmBtn": "Realmente excluir servidor",
|
||||
"deleteServerSuccess": "Servidor excluído com sucesso",
|
||||
"enterCurrentPasswordForDeleteServer": "Por favor, digite a senha atual para excluir este servidor",
|
||||
"copyAddress": "Copiar endereço",
|
||||
|
|
|
@ -1,6 +1,16 @@
|
|||
{
|
||||
"@@locale": "ro",
|
||||
"@@last_modified": "2023-05-15T21:16:36+02:00",
|
||||
"@@last_modified": "2023-08-21T19:40:19+02:00",
|
||||
"deleteServerConfirmBtn": "Sigur doriți sa ștergeți serverul",
|
||||
"cannotDeleteServerIfActiveGroups": "There are active groups associated with this Cwtch Server. Please delete them prior to deleting this Cwtch Server entry.",
|
||||
"groupsOnThisServerLabel": "Grupurile în care mă aflu care sunt găzduite pe acest 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": "Dimensiunea implicită a textului (factor de scară:",
|
||||
"localeJa": "Japanese \/ 日本語",
|
||||
|
@ -23,7 +33,6 @@
|
|||
"blodeuweddExperimentEnable": "Blodeuwedd Assistant",
|
||||
"localeKo": "Korean \/ 한국어",
|
||||
"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",
|
||||
|
@ -310,7 +319,6 @@
|
|||
"copyAddress": "Copiați adresa",
|
||||
"enterCurrentPasswordForDeleteServer": "Vă rugăm să introduceți parola actuală pentru a șterge acest server",
|
||||
"deleteServerSuccess": "Serverul a fost șters cu succes",
|
||||
"deleteServerConfirmBtn": "Sigur doriți sa ștergeți serverul",
|
||||
"plainServerDescription": "Vă recomandăm să vă protejați serverele Cwtch cu o parolă. Dacă nu setați o parolă pe acest server, atunci oricine are acces la acest dispozitiva are acces la informații despre acest server, inclusiv la chei criptografice importante.",
|
||||
"fileSavedTo": "Salvat în",
|
||||
"fileInterrupted": "Întrerupt",
|
||||
|
@ -321,7 +329,6 @@
|
|||
"importLocalServerLabel": "Importați un server găzduit local",
|
||||
"importLocalServerSelectText": "Selectați Server local",
|
||||
"importLocalServerButton": "Importă %1",
|
||||
"groupsOnThisServerLabel": "Grupurile în care mă aflu care sunt găzduite pe acest server",
|
||||
"fieldDescriptionLabel": "Descriere",
|
||||
"manageKnownServersButton": "Gestionați serverele cunoscute",
|
||||
"displayNameTooltip": "Vă rugăm să introduceți un nume de afișat",
|
||||
|
|
|
@ -1,6 +1,16 @@
|
|||
{
|
||||
"@@locale": "ru",
|
||||
"@@last_modified": "2023-05-15T21:16:36+02:00",
|
||||
"@@last_modified": "2023-08-21T19:40:19+02:00",
|
||||
"deleteServerConfirmBtn": "Вы точно хотите удалить сервер?",
|
||||
"cannotDeleteServerIfActiveGroups": "There are active groups associated with this Cwtch Server. Please delete them prior to deleting this Cwtch Server entry.",
|
||||
"groupsOnThisServerLabel": "Группы, в которых я нахожусь, размещены на этом сервере",
|
||||
"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": "Размер текста по умолчанию (коэффициент масштабирования:",
|
||||
"localeJa": "Japanese \/ 日本語",
|
||||
|
@ -23,7 +33,6 @@
|
|||
"blodeuweddExperimentEnable": "Blodeuwedd Assistant",
|
||||
"localeKo": "Korean \/ 한국어",
|
||||
"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",
|
||||
|
@ -128,7 +137,6 @@
|
|||
"themeColorLabel": "Основной цвет темы",
|
||||
"settingDownloadFolder": "Папка для загрузок",
|
||||
"importLocalServerLabel": "Использовать локальный сервер",
|
||||
"deleteServerConfirmBtn": "Вы точно хотите удалить сервер?",
|
||||
"unlockProfileTip": "Создайте или импортируйте профиль, чтобы начать",
|
||||
"unlockServerTip": "Создайте или импортируйте сервер, чтобы начать",
|
||||
"saveServerButton": "Сохранить",
|
||||
|
@ -184,7 +192,6 @@
|
|||
"displayNameTooltip": "Введите отображаемое имя",
|
||||
"manageKnownServersButton": "Управление серверами",
|
||||
"fieldDescriptionLabel": "Описание",
|
||||
"groupsOnThisServerLabel": "Группы, в которых я нахожусь, размещены на этом сервере",
|
||||
"importLocalServerButton": "Импорт %1",
|
||||
"importLocalServerSelectText": "Выбрать локальный сервер",
|
||||
"newMessagesLabel": "Новое сообщение",
|
||||
|
|
|
@ -1,6 +1,16 @@
|
|||
{
|
||||
"@@locale": "sk",
|
||||
"@@last_modified": "2023-05-15T21:16:36+02:00",
|
||||
"@@last_modified": "2023-08-21T19:40:19+02:00",
|
||||
"deleteServerConfirmBtn": "Vážne vymazať server?",
|
||||
"cannotDeleteServerIfActiveGroups": "There are active groups associated with this Cwtch Server. Please delete them prior to deleting this Cwtch Server entry.",
|
||||
"groupsOnThisServerLabel": "Skupiny ktorých som členom a sú hostované na tomto servery",
|
||||
"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": "Spustiť alebo zastaviť profil",
|
||||
"localeSw": "Swahili \/ Kiswahili",
|
||||
"localeSv": "Swedish \/ Svenska",
|
||||
"fontScalingDescription": "Adjust the relative font scaling factor applied to text and widgets.",
|
||||
"defaultScalingText": "Predvolená veľkosť textu (mierka):",
|
||||
"localeJa": "Japanese \/ 日本語",
|
||||
|
@ -146,7 +156,6 @@
|
|||
"displayNameTooltip": "Prosím zadajte zobrazované meno",
|
||||
"manageKnownServersButton": "Spravovať Známe Servery",
|
||||
"fieldDescriptionLabel": "Popis",
|
||||
"groupsOnThisServerLabel": "Skupiny ktorých som členom a sú hostované na tomto servery",
|
||||
"importLocalServerButton": "Importovať %1",
|
||||
"importLocalServerSelectText": "Zvoliť Lokálny Server",
|
||||
"importLocalServerLabel": "Importovať lokálne hostovaný server",
|
||||
|
@ -159,7 +168,6 @@
|
|||
"fileSavedTo": "Uložené do",
|
||||
"encryptedServerDescription": "Šifrovanie serveru heslom ho chráni pred ostatnými ľuďmi ktorý by mohli toto zariadenie využívať taktiež. Šifrované servery sa nedajú odšifrovať, zobraziť alebo sprístupniť pokiaľ nie je zadané správne heslo.",
|
||||
"plainServerDescription": "Odporúčame aby ste si ochránili Cwtch servery heslom. Ak si na servery nenastavíte heslo, každý s prístupom k tomuto zariadeniu bude schopný vidieť informácie o danom servry, vrátane citlivých kryptografických klúčov.",
|
||||
"deleteServerConfirmBtn": "Vážne vymazať server?",
|
||||
"deleteServerSuccess": "Server bol úspešne vymazaný",
|
||||
"enterCurrentPasswordForDeleteServer": "Prosím zadajte aktuálne heslo pre zmazanie tohoto serveru",
|
||||
"copyAddress": "Kopírovať Adresu",
|
||||
|
@ -383,6 +391,5 @@
|
|||
"createGroupBtn": " Vytvoriť",
|
||||
"defaultGroupName": "Úžasná Skupina",
|
||||
"createGroupTitle": "Vytvoriť Skupinu",
|
||||
"profileEnabled": "Povoliť",
|
||||
"profileEnabledDescription": "Spustiť alebo zastaviť profil"
|
||||
"profileEnabled": "Povoliť"
|
||||
}
|
|
@ -0,0 +1,395 @@
|
|||
{
|
||||
"@@locale": "sv",
|
||||
"@@last_modified": "2023-08-21T19:40:19+02:00",
|
||||
"deleteServerConfirmBtn": "Bekräfta borttagning av servern",
|
||||
"cannotDeleteServerIfActiveGroups": "There are active groups associated with this Cwtch Server. Please delete them prior to deleting this Cwtch Server entry.",
|
||||
"groupsOnThisServerLabel": "Grupper jag är med i på den här servern",
|
||||
"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": "Ukrainska \/ українською",
|
||||
"profileEnabledDescription": "Aktivera eller inaktivera profilen",
|
||||
"localeSw": "Swahili \/ Kiswahili",
|
||||
"createGroupTitle": "Skapa grupp",
|
||||
"serverLabel": "Server",
|
||||
"defaultGroupName": "Fantastisk grupp",
|
||||
"createGroupBtn": "Skapa",
|
||||
"profileOnionLabel": "Skicka den här adressen till personer du vill ansluta till",
|
||||
"addPeerTab": "Lägg till en kontakt",
|
||||
"createGroupTab": "Skapa en grupp",
|
||||
"joinGroupTab": "Gå med i en grupp",
|
||||
"peerAddress": "Adress",
|
||||
"peerName": "Namn",
|
||||
"server": "Server",
|
||||
"invitation": "Inbjudan",
|
||||
"groupAddr": "Adress",
|
||||
"addPeer": "Lägg till kontakt",
|
||||
"createGroup": "Skapa grupp",
|
||||
"joinGroup": "Gå med i grupp",
|
||||
"newBulletinLabel": "Ny rapport",
|
||||
"postNewBulletinLabel": "Lägg upp ny rapport",
|
||||
"titlePlaceholder": "titel...",
|
||||
"pasteAddressToAddContact": "Klistra in en cwtch-adress, inbjudan eller nyckelpaket här för att lägga till en ny konversation",
|
||||
"blocked": "Blockerad",
|
||||
"search": "Sök...",
|
||||
"invitationLabel": "Inbjudan",
|
||||
"serverInfo": "Server info",
|
||||
"serverConnectivityConnected": "Server ansluten",
|
||||
"serverConnectivityDisconnected": "Server frånkopplad",
|
||||
"serverSynced": "Synkroniserad",
|
||||
"serverNotSynced": "Synkroniserar nya meddelanden (det kan ta lite tid)...",
|
||||
"viewServerInfo": "Server info",
|
||||
"groupNameLabel": "Gruppens namn",
|
||||
"saveBtn": "Spara",
|
||||
"inviteToGroupLabel": "Bjud in till grupp",
|
||||
"inviteBtn": "Bjud in",
|
||||
"deleteBtn": "Ta bort",
|
||||
"update": "Uppdatera",
|
||||
"searchList": "Söklista",
|
||||
"peerNotOnline": "Kontakten är offline. Program kan inte användas just nu.",
|
||||
"addListItemBtn": "Lägg till",
|
||||
"membershipDescription": "Nedan finns en lista över användare som har skickat meddelanden till gruppen. Den kanske inte innehåller alla användare som har åtkomst till gruppen dock.",
|
||||
"dmTooltip": "Klicka för DM",
|
||||
"couldNotSendMsgError": "Det gick inte att skicka detta meddelande",
|
||||
"acknowledgedLabel": "Bekräftad",
|
||||
"pendingLabel": "Väntar",
|
||||
"peerBlockedMessage": "Kontakten är blockerad",
|
||||
"peerOfflineMessage": "Kontakten är offline, meddelanden kan inte levereras just nu",
|
||||
"copyBtn": "Kopiera",
|
||||
"newGroupBtn": "Skapa ny grupp",
|
||||
"acceptGroupInviteLabel": "Vill du acceptera inbjudan till",
|
||||
"acceptGroupBtn": "Acceptera",
|
||||
"rejectGroupBtn": "Avvisa",
|
||||
"chatBtn": "Chatt",
|
||||
"bulletinsBtn": "Rapporter",
|
||||
"listsBtn": "Listor",
|
||||
"puzzleGameBtn": "Pussel",
|
||||
"addressLabel": "Adress",
|
||||
"copiedToClipboardNotification": "Kopierat till urklipp",
|
||||
"displayNameLabel": "Visningsnamn",
|
||||
"blockBtn": "Blockera kontakt",
|
||||
"savePeerHistory": "Spara historik",
|
||||
"savePeerHistoryDescription": "Avgör om historik som är kopplad till kontakten ska tas bort.",
|
||||
"dontSavePeerHistory": "Rensa historik",
|
||||
"unblockBtn": "Avblockera kontakt",
|
||||
"editProfileTitle": "Redigera profil",
|
||||
"addProfileTitle": "Lägg till en ny profil",
|
||||
"profileName": "Visningsnamn",
|
||||
"defaultProfileName": "Alice",
|
||||
"newProfile": "Ny profil",
|
||||
"editProfile": "Redigera profil",
|
||||
"radioUsePassword": "Lösenord",
|
||||
"radioNoPassword": "Okrypterad (inget lösenord)",
|
||||
"noPasswordWarning": "Att inte använda ett lösenord på detta konto innebär att all data som lagras lokalt är okrypterat",
|
||||
"yourDisplayName": "Ditt visningsnamn",
|
||||
"currentPasswordLabel": "Nuvarande lösenord",
|
||||
"password1Label": "Lösenord",
|
||||
"password2Label": "Ange lösenordet på nytt",
|
||||
"passwordErrorEmpty": "Lösenordet kan inte vara tomt",
|
||||
"createProfileBtn": "Skapa profil",
|
||||
"saveProfileBtn": "Spara profil",
|
||||
"passwordErrorMatch": "Lösenorden matchar inte",
|
||||
"passwordChangeError": "Fel vid ändring av lösenord: Det angivna lösenordet avvisades",
|
||||
"deleteProfileBtn": "Ta bort profil",
|
||||
"deleteConfirmLabel": "Skriv DELETE för att bekräfta",
|
||||
"deleteProfileConfirmBtn": "Ta bort profilen",
|
||||
"deleteConfirmText": "TA BORT",
|
||||
"addNewProfileBtn": "Lägg till en ny profil",
|
||||
"enterProfilePassword": "Ange ett lösenord för att se dina profiler",
|
||||
"password": "Lösenord",
|
||||
"error0ProfilesLoadedForPassword": "0 profiler laddade med det lösenordet",
|
||||
"yourProfiles": "Dina profiler",
|
||||
"yourServers": "Dina servrar",
|
||||
"unlock": "Lås upp",
|
||||
"cwtchSettingsTitle": "Cwtch-inställningar",
|
||||
"versionBuilddate": "Version: %1 Byggd: %2",
|
||||
"zoomLabel": "Gränssnittszoom (påverkar främst storleken på text och knappar)",
|
||||
"blockUnknownLabel": "Blockera okända kontakter",
|
||||
"settingLanguage": "Språk",
|
||||
"localeEn": "Engelska \/ English",
|
||||
"localeFr": "Franska \/ Français",
|
||||
"localePt": "Portugisiska \/ Portuguesa",
|
||||
"localeDe": "Tyska \/ Deutsch",
|
||||
"settingInterfaceZoom": "Zoomnivå",
|
||||
"largeTextLabel": "Stor",
|
||||
"settingTheme": "Använd ljusa teman",
|
||||
"themeLight": "Ljust",
|
||||
"themeDark": "Mörkt",
|
||||
"experimentsEnabled": "Aktivera experimentella funktioner",
|
||||
"versionTor": "Version %1 med tor %2",
|
||||
"version": "Version %1",
|
||||
"builddate": "Byggt: %2",
|
||||
"defaultScalingText": "Teckensnittsskalning",
|
||||
"smallTextLabel": "Liten",
|
||||
"loadingTor": "Laddar tor...",
|
||||
"viewGroupMembershipTooltip": "Visa gruppmedlemskap",
|
||||
"networkStatusDisconnected": "Frånkopplad från internet, kontrollera din anslutning",
|
||||
"networkStatusAttemptingTor": "Försöker ansluta till Tor-nätverket",
|
||||
"networkStatusConnecting": "Ansluter till nätverk och kontakter...",
|
||||
"networkStatusOnline": "Uppkopplad",
|
||||
"newConnectionPaneTitle": "Ny anslutning",
|
||||
"addListItem": "Lägg till ett nytt listobjekt",
|
||||
"addNewItem": "Lägg till ett nytt objekt i listan",
|
||||
"todoPlaceholder": "Att göra...",
|
||||
"localeEs": "Spanska \/ Español",
|
||||
"localeIt": "Italienska \/ Italiano",
|
||||
"enableGroups": "Aktivera gruppchatt",
|
||||
"enterCurrentPasswordForDelete": "Ange aktuellt lösenord för att ta bort den här profilen.",
|
||||
"conversationSettings": "Konversationsinställningar",
|
||||
"invalidImportString": "Ogiltig importsträng",
|
||||
"contactAlreadyExists": "Kontakten finns redan",
|
||||
"tooltipOpenSettings": "Öppna inställningsfönstret",
|
||||
"tooltipAddContact": "Lägg till en ny kontakt eller konversation",
|
||||
"titleManageContacts": "Konversationer",
|
||||
"tooltipUnlockProfiles": "Lås upp krypterade profiler genom att ange deras lösenord.",
|
||||
"titleManageProfiles": "Hantera Cwtch-profiler",
|
||||
"descriptionExperiments": "Cwtch experimentella funktioner är frivilliga. De utökar funktionaliteten av Cwtch med t.ex. gruppchatt eller integration av botar vilket försämrar säkerhet och integritet jämfört med traditionell 1:1 metadataresistent chatt.",
|
||||
"descriptionExperimentsGroups": "Grupper tillåter Cwtch att ansluta till opålitlig serverinfrastruktur för att möjliggöra kommunikation med mer än en kontakt.",
|
||||
"descriptionBlockUnknownConnections": "Om det här alternativet är aktiverat stängs automatiskt anslutningar från Cwtch-användare som inte finns i din kontaktlista.",
|
||||
"successfullAddedContact": "Har lagts till ",
|
||||
"titleManageServers": "Hantera servrar",
|
||||
"inviteToGroup": "Du har blivit inbjuden att gå med i en grupp:",
|
||||
"leaveConversation": "Lämna denna konversation",
|
||||
"reallyLeaveThisGroupPrompt": "Är du säker på att du vill lämna den här konversationen? Alla meddelanden och attribut kommer att raderas.",
|
||||
"yesLeave": "Ja, lämna denna konversation",
|
||||
"newPassword": "Nytt lösenord",
|
||||
"chatHistoryDefault": "Den här konversationen kommer att raderas när Cwtch stängs! Meddelandehistorik kan aktiveras per konversation via menyn Inställningar uppe till höger.",
|
||||
"accepted": "Accepterad!",
|
||||
"rejected": "Avvisad!",
|
||||
"contactSuggestion": "Detta är ett kontaktförslag för:",
|
||||
"sendAnInvitation": "Du skickade en inbjudan till:",
|
||||
"torStatus": "Tor-status",
|
||||
"torVersion": "Tor-version",
|
||||
"resetTor": "Återställ",
|
||||
"cancel": "Avbryt",
|
||||
"sendMessage": "Skicka meddelande",
|
||||
"sendInvite": "Skicka en kontakt- eller gruppinbjudan",
|
||||
"deleteProfileSuccess": "Profilen har tagits bort",
|
||||
"addServerFirst": "Du måste lägga till en server innan du kan skapa en grupp",
|
||||
"nickChangeSuccess": "Profilens smeknamn har ändrats",
|
||||
"createProfileToBegin": "Skapa eller lås upp en profil för att börja",
|
||||
"addContactFirst": "Lägg till eller välj en kontakt för att börja chatta.",
|
||||
"torNetworkStatus": "Tor nätverksstatus",
|
||||
"debugLog": "Aktivera debug-logg",
|
||||
"profileDeleteSuccess": "Profilen har tagits bort",
|
||||
"malformedMessage": "Felaktigt meddelande",
|
||||
"shutdownCwtchTooltip": "Stäng ner Cwtch",
|
||||
"shutdownCwtchDialog": "Är du säker på att du vill stänga ner Cwtch? Detta kommer att stänga alla anslutningar och avsluta programmet.",
|
||||
"shutdownCwtchAction": "Stäng ner Cwtch",
|
||||
"shutdownCwtchDialogTitle": "Stänga ner Cwtch?",
|
||||
"groupInviteSettingsWarning": "Du har blivit inbjuden att gå med i en grupp! Aktivera gruppchatt i Inställningar för att se denna inbjudan.",
|
||||
"tooltipShowPassword": "Visa lösenord",
|
||||
"tooltipHidePassword": "Dölj lösenordet",
|
||||
"notificationNewMessageFromPeer": "Nytt meddelande från en kontakt!",
|
||||
"notificationNewMessageFromGroup": "Nytt meddelande i en grupp!",
|
||||
"tooltipAcceptContactRequest": "Acceptera kontaktförfrågan.",
|
||||
"tooltipReplyToThisMessage": "Svara på meddelande",
|
||||
"tooltipRejectContactRequest": "Neka kontaktförfrågan",
|
||||
"tooltipRemoveThisQuotedMessage": "Ta bort citerat meddelande.",
|
||||
"localePl": "Polska \/ Polski",
|
||||
"settingUIColumnPortrait": "UI-kolumner i stående läge",
|
||||
"settingUIColumnOptionSame": "Samma som stående läge",
|
||||
"settingUIColumnLandscape": "UI-kolumner i liggande läge",
|
||||
"settingUIColumnSingle": "Enkel",
|
||||
"settingUIColumnDouble12Ratio": "Dubbel (1:2)",
|
||||
"settingUIColumnDouble14Ratio": "Dubbel (1:4)",
|
||||
"contactGoto": "Gå till konversation med %1",
|
||||
"addContact": "Lägg till kontakt",
|
||||
"addContactConfirm": "Lägg till kontakt %1",
|
||||
"encryptedProfileDescription": "Genom att kryptera en profil med ett lösenord skyddas den från andra personer som också kan använda den här enheten. Krypterade profiler kan inte dekrypteras, visas eller nås förrän rätt lösenord har angetts för att låsa upp dem.",
|
||||
"plainProfileDescription": "Vi rekommenderar att du skyddar dina Cwtch-profiler med ett lösenord. Om du inte anger ett lösenord för den här profilen kan alla som har åtkomst till den här enheten komma åt information om den här profilen, inklusive kontakter, meddelanden och känsliga kryptografiska nycklar.",
|
||||
"placeholderEnterMessage": "Skriv ett meddelande...",
|
||||
"blockedMessageMessage": "Det här meddelandet kommer från en profil som du har blockerat.",
|
||||
"showMessageButton": "Visa meddelande",
|
||||
"blockUnknownConnectionsEnabledDescription": "Anslutningar från okända kontakter blockeras. Du kan ändra detta i Inställningar",
|
||||
"archiveConversation": "Arkivera denna konversation",
|
||||
"streamerModeLabel": "Streaming\/presentationsläge",
|
||||
"descriptionStreamerMode": "Aktivera för att dölja privat information (exempelvis profil och kontaktadresser) vilket kan vara lämpligt vid streaming eller presentation.",
|
||||
"retrievingManifestMessage": "Hämtar filinformation...",
|
||||
"openFolderButton": "Öppna mapp",
|
||||
"downloadFileButton": "Ladda ner",
|
||||
"labelFilename": "Filnamn",
|
||||
"labelFilesize": "Storlek",
|
||||
"messageEnableFileSharing": "Aktivera fildelning för att kunna se meddelandet.",
|
||||
"messageFileSent": "Du skickade en fil",
|
||||
"messageFileOffered": "Kontakten försöker skicka en fil till dig",
|
||||
"tooltipSendFile": "Skicka fil",
|
||||
"settingFileSharing": "Fildelning",
|
||||
"descriptionFileSharing": "Fildelning gör att du kan skicka och ta emot filer från Cwtch-kontakter och grupper. Observera att om du delar en fil med en grupp kommer medlemmarna i den gruppen behöva ansluta direkt till dig med Cwtch för att kunna ladda ner filen.",
|
||||
"titleManageProfilesShort": "Profiler",
|
||||
"addServerTitle": "Lägg till server",
|
||||
"editServerTitle": "Redigera server",
|
||||
"serverAddress": "Serveradress",
|
||||
"serverDescriptionLabel": "Serverbeskrivning",
|
||||
"serverDescriptionDescription": "Din beskrivning av servern. Endast synligt för dig, kommer aldrig att delas",
|
||||
"serverEnabled": "Server startad",
|
||||
"serverEnabledDescription": "Starta eller stoppa servern",
|
||||
"serverAutostartLabel": "Autostart",
|
||||
"serverAutostartDescription": "Styr om programmet automatiskt startar servern vid start",
|
||||
"saveServerButton": "Spara server",
|
||||
"serversManagerTitleLong": "Servrar du är värd för",
|
||||
"serversManagerTitleShort": "Servrar",
|
||||
"addServerTooltip": "Lägg till server",
|
||||
"unlockServerTip": "Skapa eller lås upp en server för att börja!",
|
||||
"unlockProfileTip": "Skapa eller lås upp en profil för att börja!",
|
||||
"enterServerPassword": "Ange lösenord för att låsa upp servern",
|
||||
"settingServers": "Server-värd",
|
||||
"settingServersDescription": "Server-värd gör det möjligt att vara värd för och hantera Cwtch-servrar",
|
||||
"copyAddress": "Kopiera adress",
|
||||
"enterCurrentPasswordForDeleteServer": "Ange lösenord för att radera den här servern",
|
||||
"deleteServerSuccess": "Servern har tagits bort",
|
||||
"plainServerDescription": "Vi rekommenderar att du skyddar dina Cwtch-servrar med ett lösenord. Om du inte anger ett lösenord på den här servern kan alla som har åtkomst till den här enheten komma åt information om den här servern, inklusive känsliga kryptografiska nycklar.",
|
||||
"encryptedServerDescription": "Genom att kryptera en server med ett lösenord skyddas den från andra personer som också kan använda den här enheten. Krypterade servrar kan inte dekrypteras, visas eller nås förrän rätt lösenord har angetts för att låsa upp dem.",
|
||||
"fileSavedTo": "Sparad till",
|
||||
"fileInterrupted": "Avbruten",
|
||||
"fileCheckingStatus": "Kontrollera status för nedladdning",
|
||||
"verfiyResumeButton": "Verifiera\/återuppta",
|
||||
"copyServerKeys": "Kopiera nycklar",
|
||||
"localeRU": "Ryska \/ Русский",
|
||||
"newMessagesLabel": "Nya meddelanden",
|
||||
"importLocalServerLabel": "Importera en lokal server",
|
||||
"importLocalServerSelectText": "Välj lokal server",
|
||||
"importLocalServerButton": "Importera %1",
|
||||
"fieldDescriptionLabel": "Beskrivning",
|
||||
"manageKnownServersButton": "Hantera kända servrar",
|
||||
"displayNameTooltip": "Ange ett visningsnamn",
|
||||
"manageKnownServersLong": "Hantera kända servrar",
|
||||
"manageKnownServersShort": "Servrar",
|
||||
"serverMetricsLabel": "Serverinfo",
|
||||
"serverTotalMessagesLabel": "Antal meddelanden",
|
||||
"serverConnectionsLabel": "Anslutningar",
|
||||
"enableExperimentClickableLinks": "Aktivera klickbara länkar",
|
||||
"experimentClickableLinksDescription": "Med klickbara länkar aktiverat kan du klicka på webbadresser som delas i meddelanden",
|
||||
"settingImagePreviews": "Förhandsgranskningar av bilder och profilbilder",
|
||||
"settingImagePreviewsDescription": "Bilder och profilbilder kommer att laddas ner och förhandsgranskas automatiskt. Vi rekommenderar att du inte aktiverar detta om du använder Cwtch med opålitliga kontakter.",
|
||||
"settingDownloadFolder": "Hämtade filer",
|
||||
"themeNameCwtch": "Cwtch",
|
||||
"themeNameWitch": "Häxa",
|
||||
"themeNameVampire": "Vampyr",
|
||||
"themeNameGhost": "Spöke",
|
||||
"themeNamePumpkin": "Pumpa",
|
||||
"themeNameMermaid": "Sjöjungfru",
|
||||
"themeNameMidnight": "Midnatt",
|
||||
"themeNameNeon1": "Neon1",
|
||||
"themeNameNeon2": "Neon2",
|
||||
"themeColorLabel": "Färgtema",
|
||||
"loadingCwtch": "Laddar Cwtch...",
|
||||
"storageMigrationModalMessage": "Migrerar profiler till nytt lagringsformat. Detta kan ta några minuter...",
|
||||
"msgFileTooBig": "Filstorleken får inte överstiga 10 GB",
|
||||
"msgConfirmSend": "Är du säker på att du vill skicka",
|
||||
"btnSendFile": "Skicka fil",
|
||||
"msgAddToAccept": "Lägg till det här kontot i dina kontakter för att acceptera den här filen.",
|
||||
"torSettingsEnabledAdvanced": "Aktivera avancerad Tor-konfiguration",
|
||||
"torSettingsEnabledAdvancedDescription": "Använd en befintlig Tor-tjänst på ditt system, eller ändra parametrarna för Cwtch Tor-tjänst",
|
||||
"torSettingsCustomSocksPort": "Anpassad SOCKS-port",
|
||||
"torSettingsCustomSocksPortDescription": "Använd en anpassad port för dataanslutningar till Tor-proxyn",
|
||||
"torSettingsCustomControlPort": "Anpassad kontrollport",
|
||||
"torSettingsCustomControlPortDescription": "Använd en anpassad port för kontrollanslutningar till Tor-proxyn",
|
||||
"torSettingsUseCustomTorServiceConfiguration": "Använd en anpassad konfiguration av Tor (torrc)",
|
||||
"torSettingsUseCustomTorServiceConfigurastionDescription": "Åsidosätt standard-konfigurationen för Tor. Varning: Detta kan vara farligt. Använd bara om du vet vad du gör.",
|
||||
"torSettingsErrorSettingPort": "Portnumret måste vara mellan 1 och 65535",
|
||||
"fileSharingSettingsDownloadFolderDescription": "När filer laddas ned automatiskt (t.ex. bildfiler, när förhandsgranskning är aktiverat) behövs en standardplats att ladda ner filerna till.",
|
||||
"fileSharingSettingsDownloadFolderTooltip": "Bläddra för att välja en annan standardmapp för nedladdade filer.",
|
||||
"descriptionACNCircuitInfo": "Detaljerad information om den väg som det anonyma kommunikationsnätverket använder för att ansluta till den här konversationen.",
|
||||
"labelACNCircuitInfo": "Info om ACN-vägen",
|
||||
"labelTorNetwork": "Tor-nätverket",
|
||||
"torSettingsEnableCache": "Lagra konsensus i cache",
|
||||
"torSettingsEnabledCacheDescription": "Lagra nedladdad Tor-konsensus i cache för att återanvända nästa gång Cwtch öppnas. Detta gör att Tor kan starta snabbare. Om detta är inaktiverat kommer Cwtch rensa cache vid uppstart.",
|
||||
"tooltipSelectACustomProfileImage": "Välj en anpassad profilbild",
|
||||
"notificationPolicyOptIn": "Välj",
|
||||
"notificationPolicyMute": "Tysta",
|
||||
"conversationNotificationPolicyOptIn": "Välj",
|
||||
"notificationPolicyDefaultAll": "Återställ standard",
|
||||
"conversationNotificationPolicyDefault": "Standard",
|
||||
"conversationNotificationPolicyNever": "Aldrig",
|
||||
"notificationPolicySettingLabel": "Aviseringspolicy",
|
||||
"notificationContentSettingLabel": "Aviseringsinnehåll",
|
||||
"notificationPolicySettingDescription": "Styr programmets standardaviseringsbeteende",
|
||||
"notificationContentSettingDescription": "Styr innehållet i konversationsaviseringar",
|
||||
"settingGroupBehaviour": "Beteende",
|
||||
"settingsGroupAppearance": "Utseende",
|
||||
"settingsGroupExperiments": "Experiment",
|
||||
"conversationNotificationPolicySettingLabel": "Policy för konversationsaviseringar",
|
||||
"conversationNotificationPolicySettingDescription": "Ändra aviseringar för den här konversationen",
|
||||
"notificationContentSimpleEvent": "Enkel händelse",
|
||||
"notificationContentContactInfo": "Info om konversation",
|
||||
"newMessageNotificationSimple": "Nytt meddelande",
|
||||
"newMessageNotificationConversationInfo": "Nytt meddelande från %1",
|
||||
"localeRo": "Rumänska \/ Română",
|
||||
"localeLb": "Luxemburgiska \/ Lëtzebuergesch",
|
||||
"localeNo": "Norska \/ Norsk",
|
||||
"localeEl": "Grekiska \/ Ελληνικά",
|
||||
"localeCy": "Walesiska \/ Cymraeg",
|
||||
"localeDa": "Danska \/ Dansk",
|
||||
"exportProfile": "Exportera profil",
|
||||
"exportProfileTooltip": "Säkerhetskopiera den här profilen till en krypterad fil. Den krypterade filen kan importeras till en annan Cwtch-app.",
|
||||
"importProfileTooltip": "Använd en krypterad Cwtch-säkerhetskopia för att importera en profil skapad i en annan instans av Cwtch.",
|
||||
"importProfile": "Importera profil",
|
||||
"failedToImportProfile": "Fel vid import av profil",
|
||||
"successfullyImportedProfile": "Profilen har importerats: %profile",
|
||||
"shuttingDownApp": "Stänger ner...",
|
||||
"clickableLinksWarning": "Om du öppnar den här webbadressen startar en applikation utanför Cwtch som kan avslöja metadata eller på annat sätt äventyra säkerheten för Cwtch. Öppna bara webbadresser från personer du litar på. Är du säker på att du vill fortsätta?",
|
||||
"clickableLinkOpen": "Öppna URL",
|
||||
"clickableLinksCopy": "Kopiera URL",
|
||||
"clickableLinkError": "Fel uppstod vid försök att öppna URL",
|
||||
"formattingExperiment": "Meddelandeformatering",
|
||||
"messageFormattingDescription": "Aktivera RTF-formatering i visade meddelanden, t.ex. **fet** och *kursiv*",
|
||||
"thisFeatureRequiresGroupExpermientsToBeEnabled": "Den här funktionen kräver att Grupper är aktiverat i Inställningar.",
|
||||
"settingAndroidPowerExemption": "Undanta Android batterioptimering",
|
||||
"settingAndroidPowerExemptionDescription": "Valfritt: Begär att Android ska undanta Cwtch från optimerad energihantering. Detta kommer att leda till bättre stabilitet till priset av större batterianvändning.",
|
||||
"settingsAndroidPowerReenablePopup": "Det går inte att aktivera batterioptimering från Cwtch. Gå till Android \/ Inställningar \/ Appar \/ Cwtch \/ Batteri och välj \"Optimerad\"",
|
||||
"okButton": "OK",
|
||||
"tooltipBoldText": "Fet",
|
||||
"tooltipBackToMessageEditing": "Tillbaka till meddelanderedigering",
|
||||
"tooltipItalicize": "Kursiv",
|
||||
"tooltipSuperscript": "Upphöjd",
|
||||
"tooltipSubscript": "Nedsänkt",
|
||||
"tooltipStrikethrough": "Överstruket",
|
||||
"tooltipCode": "Kod \/ Monospace",
|
||||
"tooltipPreviewFormatting": "Förhandsgranska meddelandeformatering",
|
||||
"manageSharedFiles": "Hantera delade filer",
|
||||
"stopSharingFile": "Sluta dela fil",
|
||||
"restartFileShare": "Dela fil",
|
||||
"viewReplies": "Visa svar på detta meddelande",
|
||||
"headingReplies": "Svar",
|
||||
"messageNoReplies": "Det finns inga svar på detta meddelande.",
|
||||
"fileDownloadUnavailable": "Den här filen verkar inte vara tillgänglig för nedladdning. Avsändaren kan ha inaktiverat nedladdningar för den här filen.",
|
||||
"replyingTo": "Svarar %1",
|
||||
"tooltipPinConversation": "Fäst konversationen högst upp i \"Konversationer\".",
|
||||
"tooltipUnpinConversation": "Ta bort konversationen från toppen av \"Konversationer\"",
|
||||
"localeTr": "Turkiska \/ Türk",
|
||||
"errorDownloadDirectoryDoesNotExist": "Fildelning kan inte aktiveras eftersom nedladdningsmappen inte har ställts in eller är inställd på en mapp som inte finns.",
|
||||
"acquiringTicketsFromServer": "Utför Antispam-test",
|
||||
"acquiredTicketsFromServer": "Antispam-testet slutfört",
|
||||
"shareProfileMenuTooltop": "Dela profil via...",
|
||||
"shareMenuQRCode": "Visa QR-kod",
|
||||
"enableExperimentQRCode": "QR-koder",
|
||||
"experimentQRCodeDescription": "QR-kodstöd tillåter delning av data (som profilidentitet) med QR-koder",
|
||||
"localeNl": "Nederländska \/ Dutch",
|
||||
"localePtBr": "Brasiliansk portugisiska \/ Português do Brasil",
|
||||
"profileAutostartLabel": "Starta automatiskt",
|
||||
"profileEnabled": "Aktivera",
|
||||
"profileAutostartDescription": "Styr om profilen ska startas automatiskt vid programstart",
|
||||
"localeSk": "Slovakiska \/ Slovák",
|
||||
"localeKo": "Koreanska \/ 한국어",
|
||||
"blodeuweddExperimentEnable": "Blodeuwedd-assistenten",
|
||||
"blodeuweddDescription": "Blodeuwedd-assistenten lägger till nya funktioner till Cwtch, såsom sammanfattning av koversationer och meddelandeöversättning. Allt via en språkmodell som körs i datorn.",
|
||||
"blodeuweddNotSupported": "Denna version av Cwtch har kompilerats utan stöd för Blodeuwedd-assistenten.",
|
||||
"blodeuweddPath": "Katalogen där Blodeuwedd finns på din dator.",
|
||||
"blodeuweddSummarize": "Sammanfatta konversation",
|
||||
"blodeuweddTranslate": "Översätt meddelande",
|
||||
"blodeuweddWarning": "Blodeuwedd använder en lokal språkmodell och en uppsättning små hjälpmodeller för att driva dess funktionalitet. Dessa tekniker är ofta mycket effektiva, de är inte felfria.\n\nÄven om vi har vidtagit åtgärder för att minimera risken, finns det fortfarande en möjlighet att data från Blodeuwedd kan vara felaktigt, missvisande och\/eller stötande.\n\nPå grund av det kräver Blodeuwedd nedladdning av två ytterligare komponenter separat från Cwtch, Blodeuwedd Model (eller annan kompatibel modell) och Blodeuwedd Runner.\n\nLäs på https:\/\/docs.cwtch.im\/docs\/settings\/experiments\/blodeuwedd för mer information om hur du skaffar dessa komponenter och konfigurerar dem.",
|
||||
"blodeuweddProcessing": "Blodeuwedd arbetar...",
|
||||
"availabilityStatusAvailable": "Tillgänglig",
|
||||
"availabilityStatusAway": "Borta",
|
||||
"availabilityStatusBusy": "Upptagen",
|
||||
"availabilityStatusTooltip": "Ange tillgänglighetsstatus",
|
||||
"profileInfoHint": "Lägg till lite offentlig information om dig själv här, t.ex. blogg, webbplatser, kortfattad biografi.",
|
||||
"profileInfoHint2": "Du kan lägga till upp till 3 fält.",
|
||||
"profileInfoHint3": "Kontakter kommer att kunna se denna information under konversationsinställningar",
|
||||
"retryConnection": "Försök igen",
|
||||
"retryConnectionTooltip": "Cwtch försöker ansluta till noder regelbundet, men du kan be Cwtch att försöka tidigare genom att trycka på den här knappen.",
|
||||
"localeSv": "Svenska \/ Svenska",
|
||||
"localeJa": "Japanska \/ 日本語",
|
||||
"fontScalingDescription": "Justera den relativa skalningsfaktorn för teckensnitt som tillämpas på text och widgets."
|
||||
}
|
|
@ -0,0 +1,395 @@
|
|||
{
|
||||
"@@locale": "sw",
|
||||
"@@last_modified": "2023-08-21T19:40:19+02:00",
|
||||
"deleteServerConfirmBtn": "Futa kabisa seva",
|
||||
"cannotDeleteServerIfActiveGroups": "There are active groups associated with this Cwtch Server. Please delete them prior to deleting this Cwtch Server entry.",
|
||||
"groupsOnThisServerLabel": "Vikundi nilivyopangishwa kwenye seva hii",
|
||||
"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",
|
||||
"blodeuweddPath": "Saraka ambapo Blodeuwedd iko kwenye kompyuta yako.",
|
||||
"tooltipSuperscript": "Superscript",
|
||||
"tooltipStrikethrough": "Mgomo",
|
||||
"errorDownloadDirectoryDoesNotExist": "Kushiriki faili hakuwezi kuwashwa kwa sababu Folda ya Upakuaji haijawekwa, au imewekwa kwenye folda ambayo haipo.",
|
||||
"blodeuweddDescription": "Mratibu wa Blodeuwedd huongeza vipengele vipya kwenye Cwtch kama vile muhtasari wa manukuu ya gumzo na tafsiri ya ujumbe kupitia modeli ya lugha inayopangishwa ndani ya nchi.",
|
||||
"blodeuweddWarning": "Blodeuwedd hutumia modeli ya lugha ya ndani na seti ya modeli ndogo ndogo ili kudhibiti utendakazi wake. Mbinu hizi mara nyingi ni nzuri sana sio bila makosa. \n\n Ingawa tumechukua juhudi za kupunguza hatari, bado kuna uwezekano kwamba matokeo ya Blodeuwedd yatakuwa yasiyo sahihi, ya kuonewa na\/au ya kukera. \n\n Kwa sababu hiyo Blodeuwedd inahitaji kupakua vijenzi viwili vya ziada tofauti na Cwtch, Mfano wa Blodeuwedd (au kielelezo kinachooana) na Blodeuwedd Runner. \n\n Tazama https:\/\/docs.cwtch.im\/docs\/settings\/experiments\/blodeuwedd kwa maelezo zaidi kuhusu kupata vipengele hivi na kuviweka.",
|
||||
"fontScalingDescription": "Rekebisha kipengele cha kuongeza fonti kinachotumika kwa maandishi na wijeti.",
|
||||
"createGroupTitle": "Unda Kikundi",
|
||||
"serverLabel": "Seva",
|
||||
"defaultGroupName": "Kundi la Kushangaza",
|
||||
"createGroupBtn": "Unda",
|
||||
"profileOnionLabel": "Tuma anwani hii kwa watu unaotaka kuungana nao",
|
||||
"addPeerTab": "Ongeza anwani",
|
||||
"createGroupTab": "Unda kikundi",
|
||||
"joinGroupTab": "Jiunge na kikundi",
|
||||
"peerAddress": "Anwani",
|
||||
"peerName": "Jina",
|
||||
"server": "Seva",
|
||||
"invitation": "Mwaliko",
|
||||
"groupAddr": "Anwani",
|
||||
"addPeer": "Ongeza Anwani",
|
||||
"createGroup": "Unda kikundi",
|
||||
"joinGroup": "Jiunge na kikundi",
|
||||
"newBulletinLabel": "Bulletin Mpya",
|
||||
"postNewBulletinLabel": "Chapisha taarifa mpya",
|
||||
"titlePlaceholder": "kichwa...",
|
||||
"pasteAddressToAddContact": "Bandika anwani ya cwtch, mwaliko au kifungu muhimu hapa ili kuongeza mazungumzo mapya",
|
||||
"blocked": "Imezuiwa",
|
||||
"search": "Tafuta...",
|
||||
"invitationLabel": "Mwaliko",
|
||||
"serverInfo": "Taarifa za Seva",
|
||||
"serverConnectivityConnected": "Seva Imeunganishwa",
|
||||
"serverConnectivityDisconnected": "Seva Imetenganishwa",
|
||||
"serverSynced": "Imesawazishwa",
|
||||
"serverNotSynced": "Inasawazisha Ujumbe Mpya (Hii inaweza kuchukua muda)...",
|
||||
"viewServerInfo": "Taarifa za Seva",
|
||||
"groupNameLabel": "Jina la Kikundi",
|
||||
"saveBtn": "Hifadhi",
|
||||
"inviteToGroupLabel": "Alika kwenye kikundi",
|
||||
"inviteBtn": "Alika",
|
||||
"deleteBtn": "Futa",
|
||||
"update": "Sasisha",
|
||||
"searchList": "Orodha ya Utafutaji",
|
||||
"peerNotOnline": "Anwani haipo mtandaoni. Maombo hayawezi kutumika kwa sasa.",
|
||||
"addListItemBtn": "Ongeza Kipengee",
|
||||
"membershipDescription": "Ifuatayo ni orodha ya watumiaji ambao wametuma ujumbe kwa kikundi. Orodha hii inaweza isiakisi watumiaji wote wanaoweza kufikia kikundi.",
|
||||
"dmTooltip": "Bofya kwa DM",
|
||||
"couldNotSendMsgError": "Haikuweza kutuma ujumbe huu",
|
||||
"acknowledgedLabel": "Imekubaliwa",
|
||||
"pendingLabel": "Inasubiri",
|
||||
"peerBlockedMessage": "Anwani imezuiwa",
|
||||
"peerOfflineMessage": "Anwani haipo mtandaoni, ujumbe hauwezi kutumwa kwa sasa",
|
||||
"copyBtn": "Nakili",
|
||||
"newGroupBtn": "Unda kikundi kipya",
|
||||
"acceptGroupInviteLabel": "Je, ungependa kukubali mwaliko wa",
|
||||
"acceptGroupBtn": "Kubali",
|
||||
"rejectGroupBtn": "Kataa",
|
||||
"chatBtn": "Soga",
|
||||
"listsBtn": "Orodha",
|
||||
"bulletinsBtn": "Viaridhishi",
|
||||
"puzzleGameBtn": "Mchezo wa Mafumbo",
|
||||
"addressLabel": "Anwani",
|
||||
"copiedToClipboardNotification": "Imenakiliwa kwenye Ubao wa kunakili",
|
||||
"displayNameLabel": "Jina la Kuonyesha",
|
||||
"blockBtn": "Zuia Anwani",
|
||||
"savePeerHistory": "Hifadhi Historia",
|
||||
"savePeerHistoryDescription": "Huamua kama kufuta historia yoyote inayohusishwa na mwasiliani.",
|
||||
"dontSavePeerHistory": "Futa Historia",
|
||||
"unblockBtn": "Ondoa kizuizi kwa Anwani",
|
||||
"addProfileTitle": "Ongeza wasifu mpya",
|
||||
"editProfileTitle": "Hariri Wasifu",
|
||||
"profileName": "Jina la kuonyesha",
|
||||
"defaultProfileName": "Alice",
|
||||
"newProfile": "Wasifu Mpya",
|
||||
"editProfile": "Hariri Wasifu",
|
||||
"radioUsePassword": "Nywila",
|
||||
"radioNoPassword": "Haijasimbwa (Hakuna nywila)",
|
||||
"noPasswordWarning": "Kutotumia nywila kwenye akaunti hii kunamaanisha kuwa data zote zilizohifadhiwa ndani hazitasimbwa kwa njia fiche",
|
||||
"yourDisplayName": "Jina Lako la Kuonyesha",
|
||||
"currentPasswordLabel": "Nywila ya sasa",
|
||||
"password1Label": "Nywila",
|
||||
"password2Label": "Ingiza tena Nywila",
|
||||
"passwordErrorEmpty": "Nywila haiwezi kuwa tupu",
|
||||
"createProfileBtn": "Unda Wasifu",
|
||||
"saveProfileBtn": "Hifadhi Wasifu",
|
||||
"passwordErrorMatch": "Nywila hailingani",
|
||||
"passwordChangeError": "Hitilafu katika kubadilisha nywila: Nenosiri lililotolewa limekataliwa",
|
||||
"deleteProfileBtn": "Futa Wasifu",
|
||||
"deleteConfirmLabel": "Andika FUTA ili kuthibitisha",
|
||||
"deleteProfileConfirmBtn": "Kweli Futa Wasifu",
|
||||
"deleteConfirmText": "FUTA",
|
||||
"addNewProfileBtn": "Ongeza wasifu mpya",
|
||||
"enterProfilePassword": "weka nywila ili uone wasifu wako",
|
||||
"password": "Nywila",
|
||||
"error0ProfilesLoadedForPassword": "0 wasifu iliyopakiwa na nywila hiyo",
|
||||
"yourProfiles": "Wasifu Wako",
|
||||
"yourServers": "Seva zako",
|
||||
"unlock": "Fungua",
|
||||
"cwtchSettingsTitle": "Mipangilio ya Cwtch",
|
||||
"versionBuilddate": "Toleo: %1 Imejengwa kwa: %2",
|
||||
"zoomLabel": "Ukuza wa kiolesura (huathiri zaidi maandishi na ukubwa wa vitufe)",
|
||||
"blockUnknownLabel": "Zuia Anwani Zisizojulikana",
|
||||
"settingLanguage": "Lugha",
|
||||
"localeEn": "Kiingereza \/ Kiingereza",
|
||||
"localeFr": "Kifaransa \/ Kifaransa",
|
||||
"localePt": "Kireno \/ Kireno",
|
||||
"localeDe": "Kijerumani \/ Kijerumani",
|
||||
"settingInterfaceZoom": "Kiwango cha kukuza",
|
||||
"largeTextLabel": "Kubwa",
|
||||
"settingTheme": "Tumia Mandhari Mwanga",
|
||||
"themeLight": "Mwanga",
|
||||
"themeDark": "Giza",
|
||||
"experimentsEnabled": "Washa Majaribio",
|
||||
"versionTor": "Toleo la %1 lenye tor %2",
|
||||
"version": "Toleo %1",
|
||||
"builddate": "Imejengwa kwa: %2",
|
||||
"defaultScalingText": "Kuongeza herufi",
|
||||
"smallTextLabel": "Ndogo",
|
||||
"loadingTor": "Inapakia tor...",
|
||||
"viewGroupMembershipTooltip": "Tazama Uanachama wa Kikundi",
|
||||
"networkStatusDisconnected": "Imetenganishwa na mtandao, angalia muunganisho wako",
|
||||
"networkStatusAttemptingTor": "Inajaribu kuunganisha kwenye mtandao wa Tor",
|
||||
"networkStatusConnecting": "Inaunganisha kwenye mtandao na anwani...",
|
||||
"networkStatusOnline": "Mtandaoni",
|
||||
"newConnectionPaneTitle": "Muunganisho Mpya",
|
||||
"addListItem": "Ongeza Kipengee Kipya cha Orodha",
|
||||
"addNewItem": "Ongeza kipengee kipya kwenye orodha",
|
||||
"todoPlaceholder": "Kufanya...",
|
||||
"localeEs": "Kihispania \/ Kihispania",
|
||||
"localeIt": "Kiitaliano \/ Kiitaliano",
|
||||
"enableGroups": "Washa Gumzo la Kikundi",
|
||||
"enterCurrentPasswordForDelete": "Tafadhali weka nywila ya sasa ili kufuta wasifu huu.",
|
||||
"conversationSettings": "Mipangilio ya Mazungumzo",
|
||||
"invalidImportString": "Mfuatano batili wa kuleta",
|
||||
"contactAlreadyExists": "Anwani Tayari Ipo",
|
||||
"tooltipOpenSettings": "Fungua kidirisha cha mipangilio",
|
||||
"tooltipAddContact": "Ongeza anwani au mazungumzo mapya",
|
||||
"titleManageContacts": "Mazungumzo",
|
||||
"tooltipUnlockProfiles": "Fungua wasifu uliosimbwa kwa njia fiche kwa kuweka nenosiri lao.",
|
||||
"titleManageProfiles": "Dhibiti Wasifu wa Cwtch",
|
||||
"descriptionExperiments": "Majaribio ya Cwtch ni ya hiari, vipengele vya kujijumuisha vinavyoongeza utendakazi wa ziada kwenye Cwtch ambavyo vinaweza kuwa na masuala ya faragha tofauti na gumzo la kawaida la metadata 1:1 kwa mfano gumzo la kikundi, muunganisho wa roboti n.k.",
|
||||
"descriptionExperimentsGroups": "The group experiment allows Cwtch to connect with untrusted server infrastructure to facilitate communication with more than one contact.",
|
||||
"descriptionBlockUnknownConnections": "Ikiwashwa, chaguo hili litafunga kiotomatiki miunganisho kutoka kwa watumiaji wa Cwtch ambao hawajaongezwa kwenye orodha yako ya anwani.",
|
||||
"successfullAddedContact": "Imefanikiwa kuongezwa",
|
||||
"titleManageServers": "Dhibiti Seva",
|
||||
"inviteToGroup": "Umealikwa kujiunga na kikundi:",
|
||||
"leaveConversation": "Acha Mazungumzo Haya",
|
||||
"reallyLeaveThisGroupPrompt": "Je, una uhakika unataka kuondoka kwenye mazungumzo haya? Ujumbe na sifa zote zitafutwa.",
|
||||
"yesLeave": "Ndiyo, Acha Mazungumzo Haya",
|
||||
"newPassword": "Nywila Mpya",
|
||||
"chatHistoryDefault": "Mazungumzo haya yatafutwa Cwtch itakapofungwa! Historia ya ujumbe inaweza kuwashwa kwa kila mazungumzo kupitia menyu ya Mipangilio iliyo upande wa juu kulia.",
|
||||
"accepted": "Imekubaliwa!",
|
||||
"rejected": "Imekataliwa!",
|
||||
"contactSuggestion": "Hili ni pendekezo la mawasiliano kwa:",
|
||||
"sendAnInvitation": "Ulituma mwaliko kwa:",
|
||||
"torVersion": "Toleo la Tor",
|
||||
"torStatus": "Hali ya Tor",
|
||||
"resetTor": "Weka upya",
|
||||
"cancel": "Ghairi",
|
||||
"sendMessage": "Tuma Ujumbe",
|
||||
"sendInvite": "Tuma mwaliko wa anwani au kikundi",
|
||||
"deleteProfileSuccess": "Imefaulu kufuta wasifu",
|
||||
"addServerFirst": "Unahitaji kuongeza seva kabla ya kuunda kikundi",
|
||||
"nickChangeSuccess": "Jina la utani la wasifu limebadilishwa",
|
||||
"createProfileToBegin": "Tafadhali unda au fungua wasifu wa kuanza",
|
||||
"addContactFirst": "Ongeza au uchague anwani ili kuanza kupiga gumzo.",
|
||||
"torNetworkStatus": "Hali ya mtandao wa Tor",
|
||||
"debugLog": "Washa kumbukumbu ya utatuzi wa kiweko",
|
||||
"profileDeleteSuccess": "Imefaulu kufuta wasifu",
|
||||
"malformedMessage": "Ujumbe wenye hitilafu",
|
||||
"shutdownCwtchTooltip": "Zima Cwtch",
|
||||
"shutdownCwtchDialogTitle": "Zima Cwtch?",
|
||||
"shutdownCwtchDialog": "Je, una uhakika unataka kuzima Cwtch? Hii itafunga miunganisho yote, na kuacha programu.",
|
||||
"shutdownCwtchAction": "Zima Cwtch",
|
||||
"groupInviteSettingsWarning": "Umealikwa kujiunga na kikundi! Tafadhali washa Jaribio la Gumzo la Kikundi katika Mipangilio ili kutazama Mwaliko huu.",
|
||||
"tooltipShowPassword": "Onyesha Nywila",
|
||||
"tooltipHidePassword": "Ficha Nywila",
|
||||
"notificationNewMessageFromPeer": "Ujumbe mpya kutoka kwa anwani unayowasiliana nayo!",
|
||||
"notificationNewMessageFromGroup": "Ujumbe mpya katika kikundi!",
|
||||
"tooltipAcceptContactRequest": "Kubali ombi hili la mawasiliano.",
|
||||
"tooltipRejectContactRequest": "Kataa ombi hili la mawasiliano",
|
||||
"tooltipReplyToThisMessage": "Jibu ujumbe huu",
|
||||
"tooltipRemoveThisQuotedMessage": "Ondoa ujumbe ulionukuliwa.",
|
||||
"localePl": "Kipolishi \/ Polski",
|
||||
"settingUIColumnPortrait": "Safu wima za UI katika Hali ya Wima",
|
||||
"settingUIColumnLandscape": "Safu wima za UI katika Hali ya Mandhari",
|
||||
"settingUIColumnSingle": "Moja",
|
||||
"settingUIColumnDouble12Ratio": "Mara mbili (1:2)",
|
||||
"settingUIColumnDouble14Ratio": "Mara mbili (1:4)",
|
||||
"settingUIColumnOptionSame": "Sawa na mpangilio wa hali ya wima",
|
||||
"contactGoto": "Nenda kwenye mazungumzo na %1",
|
||||
"addContact": "Ongeza anwani",
|
||||
"addContactConfirm": "Ongeza anwani %1",
|
||||
"encryptedProfileDescription": "Kusimba wasifu kwa nenosiri huilinda dhidi ya watu wengine ambao wanaweza pia kutumia kifaa hiki. Wasifu uliosimbwa kwa njia fiche hauwezi kusimbwa, kuonyeshwa au kufikiwa hadi nenosiri sahihi liingizwe ili kuzifungua.",
|
||||
"plainProfileDescription": "Tunapendekeza kwamba ulinde wasifu wako wa Cwtch kwa nenosiri. Ikiwa hutaweka nenosiri kwenye wasifu huu basi mtu yeyote anayeweza kufikia kifaa hiki anaweza kufikia maelezo kuhusu wasifu huu, ikiwa ni pamoja na anwani, ujumbe na funguo nyeti za kriptografia.",
|
||||
"placeholderEnterMessage": "Andika ujumbe...",
|
||||
"blockedMessageMessage": "Ujumbe huu unatoka kwa wasifu uliouzuia.",
|
||||
"showMessageButton": "Onyesha Ujumbe",
|
||||
"blockUnknownConnectionsEnabledDescription": "Miunganisho kutoka kwa anwani zisizojulikana umezuiwa. Unaweza kubadilisha hii katika Mipangilio",
|
||||
"archiveConversation": "Hifadhi Mazungumzo haya kwenye kumbukumbu",
|
||||
"streamerModeLabel": "Hali ya Kipeperushi\/Uwasilishaji",
|
||||
"descriptionStreamerMode": "Ikiwashwa, chaguo hili hufanya programu ionekane kuwa ya faragha zaidi kwa ajili ya kutiririsha au kuwasilisha, kwa mfano, kuficha wasifu na anwani za mawasiliano.",
|
||||
"retrievingManifestMessage": "Inarejesha maelezo ya faili...",
|
||||
"openFolderButton": "Fungua Folda",
|
||||
"downloadFileButton": "Pakua",
|
||||
"labelFilename": "Jina la faili",
|
||||
"labelFilesize": "Ukubwa",
|
||||
"messageEnableFileSharing": "wezesha jaribio la kushiriki faili ili kuona ujumbe huu.",
|
||||
"messageFileSent": "Umetuma faili",
|
||||
"messageFileOffered": "Anwani inajitolea kukutumia faili",
|
||||
"tooltipSendFile": "Tuma Faili",
|
||||
"settingFileSharing": "Kushiriki faili",
|
||||
"descriptionFileSharing": "Jaribio la kushiriki faili hukuruhusu kutuma na kupokea faili kutoka kwa anwani na vikundi vya Cwtch. Kumbuka kwamba kushiriki faili na kikundi kutasababisha washiriki wa kikundi hicho kuungana nawe moja kwa moja kupitia Cwtch ili kuipakua.",
|
||||
"titleManageProfilesShort": "Wasifu",
|
||||
"addServerTitle": "Ongeza Seva",
|
||||
"editServerTitle": "Hariri Seva",
|
||||
"serverAddress": "Anuani ya server",
|
||||
"serverDescriptionLabel": "Maelezo ya Seva",
|
||||
"serverDescriptionDescription": "Maelezo yako ya seva kwa matumizi ya usimamizi wa kibinafsi pekee, hayatashirikiwa kamwe",
|
||||
"serverEnabled": "Seva Imewezeshwa",
|
||||
"serverEnabledDescription": "Anzisha au usimamishe seva",
|
||||
"serverAutostartLabel": "Anzisha kiotomatiki",
|
||||
"serverAutostartDescription": "Hudhibiti ikiwa programu itazindua seva kiotomatiki inapoanza",
|
||||
"saveServerButton": "Hifadhi Seva",
|
||||
"serversManagerTitleLong": "Seva Unazopangisha",
|
||||
"serversManagerTitleShort": "Seva",
|
||||
"addServerTooltip": "Ongeza seva mpya",
|
||||
"unlockServerTip": "Tafadhali unda au kufungua seva kuanza!",
|
||||
"unlockProfileTip": "Tafadhali unda au fungua wasifu ili kuanza!",
|
||||
"enterServerPassword": "Weka nenosiri ili kufungua seva",
|
||||
"settingServers": "Seva za Kukaribisha",
|
||||
"settingServersDescription": "Jaribio la seva za kupangisha huwezesha kupangisha na kudhibiti seva za Cwtch",
|
||||
"copyAddress": "Nakili Anwani",
|
||||
"enterCurrentPasswordForDeleteServer": "Tafadhali ingiza nywila ya sasa ili kufuta seva hii",
|
||||
"deleteServerSuccess": "Seva iliyo fanikiwa futwa",
|
||||
"plainServerDescription": "Tunapendekeza kwamba ulinde seva zako za Cwtch kwa nenosiri. Ikiwa hutaweka nenosiri kwenye seva hii basi mtu yeyote ambaye ana idhini ya kufikia kifaa hiki anaweza kufikia maelezo kuhusu seva hii, ikiwa ni pamoja na funguo nyeti za kriptografia.",
|
||||
"encryptedServerDescription": "Kusimba seva kwa nenosiri huilinda dhidi ya watu wengine ambao wanaweza pia kutumia kifaa hiki. Seva zilizosimbwa kwa njia fiche haziwezi kusimbwa, kuonyeshwa au kufikiwa hadi nenosiri sahihi liingizwe ili kuzifungua.",
|
||||
"fileSavedTo": "Imehifadhiwa kwa",
|
||||
"fileInterrupted": "Imekatizwa",
|
||||
"fileCheckingStatus": "Inakagua hali ya upakuaji",
|
||||
"verfiyResumeButton": "Thibitisha\/endelea tena",
|
||||
"copyServerKeys": "Nakili funguo",
|
||||
"localeRU": "Kirusi \/ Русский",
|
||||
"newMessagesLabel": "Ujumbe Mpya",
|
||||
"importLocalServerLabel": "Ingiza seva iliyopangishwa ndani ya nchi",
|
||||
"importLocalServerSelectText": "Chagua Seva ya Karibu",
|
||||
"importLocalServerButton": "Ingiza %1",
|
||||
"fieldDescriptionLabel": "Maelezo",
|
||||
"manageKnownServersButton": "Dhibiti Seva Zinazojulikana",
|
||||
"displayNameTooltip": "Tafadhali ingiza jina la kuonyesha",
|
||||
"manageKnownServersLong": "Dhibiti Seva Zinazojulikana",
|
||||
"manageKnownServersShort": "Seva",
|
||||
"serverMetricsLabel": "Vipimo vya Seva",
|
||||
"serverTotalMessagesLabel": "Jumla ya Ujumbe",
|
||||
"serverConnectionsLabel": "Muunganisho",
|
||||
"enableExperimentClickableLinks": "Wezesha Viungo Vinavyobofka",
|
||||
"experimentClickableLinksDescription": "Jaribio la viungo vinavyoweza kubofya hukuruhusu kubofya URL zilizoshirikiwa katika ujumbe",
|
||||
"settingImagePreviews": "Muhtasari wa Picha na Picha za Wasifu",
|
||||
"settingImagePreviewsDescription": "Picha na Picha za Profaili zitapakuliwa na kuoneshwa kiotomatiki. Tunapendekeza kwamba usiwezeshe Jaribio hili ikiwa unatumia Cwtch na anwani zisizoaminika.",
|
||||
"settingDownloadFolder": "Pakua Folda",
|
||||
"themeNameCwtch": "Cwtch",
|
||||
"themeNameWitch": "Mchawi",
|
||||
"themeNameVampire": "Vampire",
|
||||
"themeNameGhost": "Roho",
|
||||
"themeNamePumpkin": "Maboga",
|
||||
"themeNameMermaid": "Mermaid",
|
||||
"themeNameMidnight": "Usiku wa manane",
|
||||
"themeNameNeon1": "Neon1",
|
||||
"themeNameNeon2": "Neon2",
|
||||
"themeColorLabel": "Mandhari ya Rangi",
|
||||
"loadingCwtch": "Inapakia Cwtch...",
|
||||
"storageMigrationModalMessage": "Inahamisha wasifu hadi umbizo jipya la hifadhi. Hii inaweza kuchukua dakika chache...",
|
||||
"msgFileTooBig": "Ukubwa wa faili hauwezi kuzidi GB 10",
|
||||
"msgConfirmSend": "Je, una uhakika unataka kutuma",
|
||||
"btnSendFile": "Tuma Faili",
|
||||
"msgAddToAccept": "Ongeza akaunti hii kwa watu unaowasiliana nao ili ukubali faili hii.",
|
||||
"torSettingsEnabledAdvanced": "Wezesha Usanidi wa juu wa Tor",
|
||||
"torSettingsEnabledAdvancedDescription": "Tumia huduma iliyopo ya Tor kwenye mfumo wako, au ubadilishe vigezo vya Huduma ya Cwtch Tor",
|
||||
"torSettingsCustomSocksPort": "Bandari Maalum ya SOKS",
|
||||
"torSettingsCustomSocksPortDescription": "Tumia mlango maalum kwa miunganisho ya data kwa seva mbadala ya Tor",
|
||||
"torSettingsCustomControlPort": "Mlango wa Kudhibiti Maalum",
|
||||
"torSettingsCustomControlPortDescription": "Tumia mlango maalum kudhibiti miunganisho kwa seva mbadala ya Tor",
|
||||
"torSettingsUseCustomTorServiceConfiguration": "Tumia Usanidi Maalum wa Huduma ya Tor (torrc)",
|
||||
"torSettingsUseCustomTorServiceConfigurastionDescription": "Batilisha usanidi chaguo-msingi wa tor. Onyo: Hii inaweza kuwa hatari. Washa hii ikiwa tu unajua unachofanya.",
|
||||
"torSettingsErrorSettingPort": "Nambari ya Mlango lazima iwe kati ya 1 na 65535",
|
||||
"fileSharingSettingsDownloadFolderDescription": "Faili zinapopakuliwa kiotomatiki (km faili za picha, mapitio ya picha yanapowezeshwa) eneo chaguomsingi la kupakua faili linahitajika.",
|
||||
"fileSharingSettingsDownloadFolderTooltip": "Vinjari ili kuchagua folda chaguo-msingi tofauti kwa faili zilizopakuliwa.",
|
||||
"labelACNCircuitInfo": "Maelezo ya Mzunguko wa ACN",
|
||||
"descriptionACNCircuitInfo": "Maelezo ya kina kuhusu njia ambayo mtandao wa mawasiliano usiojulikana unatumia kuunganisha kwenye mazungumzo haya.",
|
||||
"labelTorNetwork": "Mtandao wa Tor",
|
||||
"torSettingsEnableCache": "Makubaliano ya Cache Tor",
|
||||
"tooltipSelectACustomProfileImage": "Chagua Picha Maalum ya Wasifu",
|
||||
"notificationPolicyMute": "Nyamazisha",
|
||||
"notificationPolicyOptIn": "Chagua Katika",
|
||||
"notificationPolicyDefaultAll": "Chaguomsingi Zote",
|
||||
"availabilityStatusBusy": "Shughuli",
|
||||
"conversationNotificationPolicyDefault": "Chaguomsingi",
|
||||
"conversationNotificationPolicyOptIn": "Chagua kujijumuisha ",
|
||||
"conversationNotificationPolicyNever": "Kamwe",
|
||||
"notificationPolicySettingLabel": "Sera ya Arifa",
|
||||
"notificationContentSettingLabel": "Maudhui ya Arifa",
|
||||
"notificationPolicySettingDescription": "Hudhibiti tabia ya arifa ya programu chaguomsingi",
|
||||
"notificationContentSettingDescription": "Hudhibiti maudhui ya arifa za mazungumzo",
|
||||
"settingGroupBehaviour": "Tabia",
|
||||
"settingsGroupAppearance": "Muonekano",
|
||||
"settingsGroupExperiments": "Majaribio",
|
||||
"conversationNotificationPolicySettingLabel": "Sera ya Arifa ya Mazungumzo",
|
||||
"conversationNotificationPolicySettingDescription": "Dhibiti tabia ya arifa kwa mazungumzo haya",
|
||||
"notificationContentSimpleEvent": "Tukio la wazi",
|
||||
"notificationContentContactInfo": "Taarifa za Mazungumzo",
|
||||
"newMessageNotificationSimple": "Ujumbe Mpya",
|
||||
"newMessageNotificationConversationInfo": "Ujumbe Mpya Kutoka %1",
|
||||
"localeRo": "Kiromania \/ Kirumi",
|
||||
"localeLb": "Luxembourgish \/ Lëtzebuergesch",
|
||||
"localeNo": "Kinorwe \/ Norsk",
|
||||
"localeEl": "Kigiriki \/ Ελληνικά",
|
||||
"localeCy": "Welsh \/ Cymraeg",
|
||||
"localeDa": "Kidenishi \/ Dansk",
|
||||
"exportProfile": "Hamisha Wasifu",
|
||||
"exportProfileTooltip": "Hifadhi nakala ya wasifu huu kwa faili iliyosimbwa. Faili iliyosimbwa kwa njia fiche inaweza kuingizwa kwenye programu nyingine ya Cwtch.",
|
||||
"importProfile": "Ingiza Wasifu",
|
||||
"importProfileTooltip": "Tumia chelezo iliyosimbwa kwa njia fiche ya Cwtch kuleta wasifu ulioundwa katika mfano mwingine wa Cwtch.",
|
||||
"failedToImportProfile": "Hitilafu katika Kuingiza Wasifu",
|
||||
"successfullyImportedProfile": "Imefaulu Kuingiza Wasifu: %wasifu",
|
||||
"shuttingDownApp": "Inazima...",
|
||||
"clickableLinksWarning": "Kufungua URL hii itafungua programu nje ya Cwtch na kunaweza kufichua metadata au vinginevyo kuhatarisha usalama wa Cwtch. Fungua URL kutoka kwa watu unaowaamini pekee. Je, una uhakika ungependa kuendelea?",
|
||||
"clickableLinkOpen": "Fungua URL",
|
||||
"clickableLinksCopy": "Nakili URL",
|
||||
"clickableLinkError": "Hitilafu ilitokea wakati wa kujaribu kufungua URL",
|
||||
"formattingExperiment": "Uumbizaji wa Ujumbe",
|
||||
"messageFormattingDescription": "Washa uumbizaji wa maandishi umbizo katika ujumbe unaoonyeshwa kwa mfano **bold** na *italic*",
|
||||
"thisFeatureRequiresGroupExpermientsToBeEnabled": "Kipengele hiki kinahitaji Majaribio ya Vikundi kuwashwa katika Mipangilio",
|
||||
"settingAndroidPowerExemption": "Android Puuza Uboreshaji wa Betri",
|
||||
"settingAndroidPowerExemptionDescription": "Hiari: Omba Android kuondoa Cwtch kutoka kwa usimamizi bora wa nishati. Hii itasababisha uthabiti bora kwa gharama ya matumizi makubwa ya betri.",
|
||||
"settingsAndroidPowerReenablePopup": "Haiwezi kuwezesha upya Uboreshaji wa Betri kutoka ndani ya Cwtch. Tafadhali nenda kwa Android \/ Mipangilio \/ Programu \/ Cwtch \/ Betri na uweke Matumizi kwa 'Imeboreshwa'",
|
||||
"okButton": "sawa",
|
||||
"tooltipBoldText": "Kolevu",
|
||||
"tooltipBackToMessageEditing": "Rudi kwa Kuhariri Ujumbe",
|
||||
"tooltipItalicize": "Italiki",
|
||||
"tooltipSubscript": "Usajili",
|
||||
"tooltipCode": "Nambari \/ Nafasi moja",
|
||||
"tooltipPreviewFormatting": "Hakiki Uumbizaji wa Ujumbe",
|
||||
"manageSharedFiles": "Dhibiti Faili Zilizoshirikiwa",
|
||||
"stopSharingFile": "Acha Kushiriki Faili",
|
||||
"restartFileShare": "Anza Kushiriki Faili",
|
||||
"viewReplies": "Tazama majibu kwa ujumbe huu",
|
||||
"headingReplies": "Majibu",
|
||||
"messageNoReplies": "Hakuna majibu kwa ujumbe huu.",
|
||||
"fileDownloadUnavailable": "Faili hii inaonekana haipatikani kwa kupakuliwa. Mtumaji anaweza kuwa amezima upakuaji wa faili hii.",
|
||||
"replyingTo": "Kujibu %1",
|
||||
"tooltipPinConversation": "Bandika mazungumzo juu ya \"Mazungumzo\"",
|
||||
"tooltipUnpinConversation": "Bandua mazungumzo kutoka sehemu ya juu ya \"Mazungumzo\"",
|
||||
"localeTr": "Kituruki \/ Kituruki",
|
||||
"acquiringTicketsFromServer": "Kutekeleza Changamoto ya Antispam",
|
||||
"acquiredTicketsFromServer": "Changamoto ya Antispam Imekamilika",
|
||||
"shareProfileMenuTooltop": "Shiriki wasifu kupitia...",
|
||||
"shareMenuQRCode": "Onyesha Msimbo wa QR",
|
||||
"enableExperimentQRCode": "Misimbo ya QR",
|
||||
"experimentQRCodeDescription": "Usaidizi wa Msimbo wa QR huruhusu kushiriki data (kama vile utambulisho wa wasifu) kwa Misimbo ya QR",
|
||||
"localeNl": "Kiholanzi \/ Kiholanzi",
|
||||
"localePtBr": "Kireno cha Kibrazili \/ Português do Brasil",
|
||||
"profileAutostartLabel": "Anzisha kiotomatiki",
|
||||
"profileEnabled": "Wezesha",
|
||||
"profileAutostartDescription": "Hudhibiti ikiwa wasifu utazinduliwa kiotomatiki inapowashwa",
|
||||
"profileEnabledDescription": "Washa au Lemaza wasifu.",
|
||||
"localeSk": "Kislovakia \/ Kislovakia",
|
||||
"localeKo": "Kikorea \/ 한국어",
|
||||
"blodeuweddExperimentEnable": "Msaidizi wa Blodeuwedd",
|
||||
"blodeuweddNotSupported": "Toleo hili la Cwtch limeundwa bila usaidizi kwa Msaidizi wa Blodeuwedd.",
|
||||
"retryConnectionTooltip": "Cwtch retries wenzao mara kwa mara, lakini unaweza kuwaambia Cwtch kujaribu mapema kwa kubofya hiki kitufe",
|
||||
"blodeuweddSummarize": "Fupisha Mazungumzo",
|
||||
"blodeuweddTranslate": "Tafsiri Ujumbe",
|
||||
"blodeuweddProcessing": "Blodeuwedd inachakata...",
|
||||
"availabilityStatusAvailable": "Inapatikana",
|
||||
"availabilityStatusAway": "Sipo karibu",
|
||||
"availabilityStatusTooltip": "Weka hali ya upatikanaji wako",
|
||||
"profileInfoHint": "Ongeza taarifa za umma kukuhusu hapa kwa mfano blogu, tovuti, wasifu mfupi.",
|
||||
"profileInfoHint2": "Unaweza kuongeza hadi sehemu 3.",
|
||||
"profileInfoHint3": "Anwani zitaweza kuona maelezo haya katika Mipangilio ya Mazungumzo",
|
||||
"retryConnection": "Jaribu tena",
|
||||
"localeUk": "Kiukreni \/ українською",
|
||||
"localeSv": "Kiswidi \/ Svenska",
|
||||
"localeJa": "Kijapani \/ 日本語",
|
||||
"localeSw": "Kiswahili \/ Kiswahili",
|
||||
"torSettingsEnabledCacheDescription": "Cache the current downloaded Tor consensus to reuse next time Cwtch is opened. This will allow Tor to start faster. When disabled, Cwtch will purge cached data on start up."
|
||||
}
|
|
@ -1,6 +1,16 @@
|
|||
{
|
||||
"@@locale": "tr",
|
||||
"@@last_modified": "2023-05-15T21:16:36+02:00",
|
||||
"@@last_modified": "2023-08-21T19:40:19+02:00",
|
||||
"deleteServerConfirmBtn": "Sunucuyu gerçekten sil",
|
||||
"cannotDeleteServerIfActiveGroups": "There are active groups associated with this Cwtch Server. Please delete them prior to deleting this Cwtch Server entry.",
|
||||
"groupsOnThisServerLabel": "Bu sunucuda içinde bulunduğum gruplar",
|
||||
"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": "Profili başlat veya durdur",
|
||||
"localeSw": "Swahili \/ Kiswahili",
|
||||
"localeSv": "Swedish \/ Svenska",
|
||||
"fontScalingDescription": "Adjust the relative font scaling factor applied to text and widgets.",
|
||||
"defaultScalingText": "Varsayılan metin boyutu (ölçek faktörü: ",
|
||||
"localeJa": "Japanese \/ 日本語",
|
||||
|
@ -23,7 +33,6 @@
|
|||
"blodeuweddExperimentEnable": "Blodeuwedd Assistant",
|
||||
"localeKo": "Korean \/ 한국어",
|
||||
"localeSk": "Slovak \/ Slovák",
|
||||
"profileEnabledDescription": "Profili başlat veya durdur",
|
||||
"profileAutostartLabel": "Otomatik başlatma",
|
||||
"profileAutostartDescription": "Profilin başlangıçta otomatik olarak başlatılıp başlatılmayacağını kontrol eder",
|
||||
"profileEnabled": "Etkinleştir",
|
||||
|
@ -295,7 +304,6 @@
|
|||
"copyAddress": "Adresi Kopyala",
|
||||
"enterCurrentPasswordForDeleteServer": "Lütfen sunucuyu silmek için şifreyi girin",
|
||||
"deleteServerSuccess": "Sunucu başarıyla silindi",
|
||||
"deleteServerConfirmBtn": "Sunucuyu gerçekten sil",
|
||||
"plainServerDescription": "Cwtch sunucularınızı bir parola ile korumanızı öneririz. Bir parola belirlemezseniz, bu cihaza erişimi olan herkes kriptografik anahtarlar da dahil olmak üzere sunucunun hassas bilgilerine erişebilir.",
|
||||
"encryptedServerDescription": "Bir sunucuyu parola ile şifrelemek, sunucuyu bu aygıtı kullanabilecek diğer kişilerden korur. Doğru şifre girilene kadar şifrelenmiş sunucular görüntülenemez veya erişilemez.",
|
||||
"fileSavedTo": "Şuraya kaydedildi",
|
||||
|
@ -307,7 +315,6 @@
|
|||
"importLocalServerLabel": "Yerel bir sunucuyu içeri aktar",
|
||||
"importLocalServerSelectText": "Yerel Sunucu Seç",
|
||||
"importLocalServerButton": "%1'i içeri aktar",
|
||||
"groupsOnThisServerLabel": "Bu sunucuda içinde bulunduğum gruplar",
|
||||
"fieldDescriptionLabel": "Açıklama",
|
||||
"manageKnownServersButton": "Bilinen Sunucuları Yönet",
|
||||
"displayNameTooltip": "Lütfen bir ad girin",
|
||||
|
|
|
@ -0,0 +1,395 @@
|
|||
{
|
||||
"@@locale": "uk",
|
||||
"@@last_modified": "2023-08-21T19:40:19+02:00",
|
||||
"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 \/ українською",
|
||||
"localeSw": "Swahili \/ Kiswahili",
|
||||
"localeSv": "Swedish \/ Svenska",
|
||||
"fontScalingDescription": "Adjust the relative font scaling factor applied to text and widgets.",
|
||||
"localeJa": "Japanese \/ 日本語",
|
||||
"retryConnectionTooltip": "Cwtch retries peers regularly, but you can tell Cwtch to try sooner by pushing this button.",
|
||||
"retryConnection": "Retry",
|
||||
"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.",
|
||||
"availabilityStatusTooltip": "Set your availability status",
|
||||
"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 \/ 한국어",
|
||||
"localeSk": "Slovak \/ Slovák",
|
||||
"profileEnabledDescription": "Activate or Deactivate the profile.",
|
||||
"profileAutostartDescription": "Controls if the profile will be automatically launched on startup",
|
||||
"profileEnabled": "Enable",
|
||||
"profileAutostartLabel": "Autostart",
|
||||
"localePtBr": "Brazilian Portuguese \/ Português do Brasil",
|
||||
"localeNl": "Dutch \/ Dutch",
|
||||
"experimentQRCodeDescription": "QR Code support allows sharing data (such as profile identity) by QR Codes",
|
||||
"enableExperimentQRCode": "QR Codes",
|
||||
"shareMenuQRCode": "Show QR Code",
|
||||
"shareProfileMenuTooltop": "Share profile via...",
|
||||
"acquiredTicketsFromServer": "Antispam Challenge Complete",
|
||||
"acquiringTicketsFromServer": "Performing Antispam Challenge",
|
||||
"errorDownloadDirectoryDoesNotExist": "Filesharing cannot be enabled because the Download Folder has not been set, or is set to a folder that does not exist.",
|
||||
"localeTr": "Turkish \/ Türk",
|
||||
"tooltipUnpinConversation": "Unpin conversation from the top of \"Conversations\"",
|
||||
"tooltipPinConversation": "Pin conversation to the top of \"Conversations\"",
|
||||
"replyingTo": "Replying to %1",
|
||||
"fileDownloadUnavailable": "This file appears unavailable for download. The sender may have disabled downloads for this file.",
|
||||
"messageNoReplies": "There are no replies to this message.",
|
||||
"headingReplies": "Replies",
|
||||
"viewReplies": "View replies to this message",
|
||||
"restartFileShare": "Start Sharing File",
|
||||
"stopSharingFile": "Stop Sharing File",
|
||||
"manageSharedFiles": "Manage Shared Files",
|
||||
"tooltipPreviewFormatting": "Preview Message Formatting",
|
||||
"tooltipCode": "Code \/ Monospace",
|
||||
"tooltipStrikethrough": "Strikethrough",
|
||||
"tooltipSubscript": "Subscript",
|
||||
"tooltipSuperscript": "Superscript",
|
||||
"tooltipItalicize": "Italic",
|
||||
"tooltipBackToMessageEditing": "Back to Message Editing",
|
||||
"tooltipBoldText": "Bold",
|
||||
"okButton": "OK",
|
||||
"settingsAndroidPowerReenablePopup": "Cannot re-enable Battery Optimization from within Cwtch. Please go to Android \/ Settings \/ Apps \/ Cwtch \/ Battery and set Usage to 'Optimized'",
|
||||
"settingAndroidPowerExemptionDescription": "Optional: Request Android to exempt Cwtch from optimized power management. This will result in better stability at the cost of greater battery use.",
|
||||
"settingAndroidPowerExemption": "Android Ignore Battery Optimizations",
|
||||
"thisFeatureRequiresGroupExpermientsToBeEnabled": "This feature requires the Groups Experiment to be enabled in Settings",
|
||||
"messageFormattingDescription": "Enable rich text formatting in displayed messages e.g. **bold** and *italic*",
|
||||
"formattingExperiment": "Message Formatting",
|
||||
"clickableLinkError": "Error encountered while attempting to open URL",
|
||||
"clickableLinksCopy": "Copy URL",
|
||||
"clickableLinkOpen": "Open URL",
|
||||
"clickableLinksWarning": "Opening this URL will launch an application outside of Cwtch and may reveal metadata or otherwise compromise the security of Cwtch. Only open URLs from people you trust. Are you sure you want to continue?",
|
||||
"shuttingDownApp": "Shutting down...",
|
||||
"successfullyImportedProfile": "Successfully Imported Profile: %profile",
|
||||
"failedToImportProfile": "Error Importing Profile",
|
||||
"importProfileTooltip": "Use an encrypted Cwtch backup to bring in a profile created in another instance of Cwtch.",
|
||||
"importProfile": "Import Profile",
|
||||
"exportProfileTooltip": "Backup this profile to an encrypted file. The encrypted file can be imported into another Cwtch app.",
|
||||
"exportProfile": "Export Profile",
|
||||
"localeDa": "Danish \/ Dansk",
|
||||
"localeCy": "Welsh \/ Cymraeg",
|
||||
"localeEl": "Greek \/ Ελληνικά",
|
||||
"localeNo": "Norwegian \/ Norsk",
|
||||
"localeLb": "Luxembourgish \/ Lëtzebuergesch",
|
||||
"localeRo": "Romanian \/ Română",
|
||||
"newMessageNotificationConversationInfo": "New Message From %1",
|
||||
"newMessageNotificationSimple": "New Message",
|
||||
"notificationContentContactInfo": "Conversation Information",
|
||||
"notificationContentSimpleEvent": "Plain Event",
|
||||
"conversationNotificationPolicySettingDescription": "Control notification behaviour for this conversation",
|
||||
"conversationNotificationPolicySettingLabel": "Conversation Notification Policy",
|
||||
"settingsGroupExperiments": "Experiments",
|
||||
"settingsGroupAppearance": "Appearance",
|
||||
"settingGroupBehaviour": "Behaviour",
|
||||
"notificationContentSettingDescription": "Controls the contents of conversation notifications",
|
||||
"notificationPolicySettingDescription": "Controls the default application notification behaviour",
|
||||
"notificationContentSettingLabel": "Notification Content",
|
||||
"notificationPolicySettingLabel": "Notification Policy",
|
||||
"conversationNotificationPolicyNever": "Never",
|
||||
"conversationNotificationPolicyOptIn": "Opt In",
|
||||
"conversationNotificationPolicyDefault": "Default",
|
||||
"notificationPolicyDefaultAll": "Default All",
|
||||
"notificationPolicyOptIn": "Opt In",
|
||||
"notificationPolicyMute": "Mute",
|
||||
"tooltipSelectACustomProfileImage": "Select a Custom Profile Image",
|
||||
"torSettingsEnabledCacheDescription": "Cache the current downloaded Tor consensus to reuse next time Cwtch is opened. This will allow Tor to start faster. When disabled, Cwtch will purge cached data on start up.",
|
||||
"torSettingsEnableCache": "Cache Tor Consensus",
|
||||
"labelTorNetwork": "Tor Network",
|
||||
"descriptionACNCircuitInfo": "In depth information about the path that the anonymous communication network is using to connect to this conversation.",
|
||||
"labelACNCircuitInfo": "ACN Circuit Info",
|
||||
"fileSharingSettingsDownloadFolderTooltip": "Browse to select a different default folder for downloaded files.",
|
||||
"fileSharingSettingsDownloadFolderDescription": "When files are downloaded automatically (e.g. image files, when image previews are enabled) a default location to download the files to is needed.",
|
||||
"torSettingsErrorSettingPort": "Port Number must be between 1 and 65535",
|
||||
"torSettingsUseCustomTorServiceConfigurastionDescription": "Override the default tor configuration. Warning: This could be dangerous. Only turn this on if you know what you are doing.",
|
||||
"torSettingsUseCustomTorServiceConfiguration": "Use a Custom Tor Service Configuration (torrc)",
|
||||
"torSettingsCustomControlPortDescription": "Use a custom port for control connections to the Tor proxy",
|
||||
"torSettingsCustomControlPort": "Custom Control Port",
|
||||
"torSettingsCustomSocksPortDescription": "Use a custom port for data connections to the Tor proxy",
|
||||
"torSettingsCustomSocksPort": "Custom SOCKS Port",
|
||||
"torSettingsEnabledAdvancedDescription": "Use an existing Tor service on your system, or change the parameters of the Cwtch Tor Service",
|
||||
"torSettingsEnabledAdvanced": "Enable Advanced Tor Configuration",
|
||||
"msgAddToAccept": "Add this account to your contacts in order to accept this file.",
|
||||
"btnSendFile": "Send File",
|
||||
"msgConfirmSend": "Are you sure you want to send",
|
||||
"msgFileTooBig": "File size cannot exceed 10 GB",
|
||||
"storageMigrationModalMessage": "Migrating profiles to new storage format. This could take a few minutes...",
|
||||
"loadingCwtch": "Loading Cwtch...",
|
||||
"themeColorLabel": "Color Theme",
|
||||
"themeNameNeon2": "Neon2",
|
||||
"themeNameNeon1": "Neon1",
|
||||
"themeNameMidnight": "Midnight",
|
||||
"themeNameMermaid": "Mermaid",
|
||||
"themeNamePumpkin": "Pumpkin",
|
||||
"themeNameGhost": "Ghost",
|
||||
"themeNameVampire": "Vampire",
|
||||
"themeNameWitch": "Witch",
|
||||
"themeNameCwtch": "Cwtch",
|
||||
"settingDownloadFolder": "Download Folder",
|
||||
"settingImagePreviewsDescription": "Images and Profile Pictures will be downloaded and previewed automatically. We recommend that you do not enable this Experiment if you use Cwtch with untrusted contacts.",
|
||||
"settingImagePreviews": "Image Previews and Profile Pictures",
|
||||
"experimentClickableLinksDescription": "The clickable links experiment allows you to click on URLs shared in messages",
|
||||
"enableExperimentClickableLinks": "Enable Clickable Links",
|
||||
"serverConnectionsLabel": "Connection",
|
||||
"serverTotalMessagesLabel": "Total Messages",
|
||||
"serverMetricsLabel": "Server Metrics",
|
||||
"manageKnownServersShort": "Servers",
|
||||
"manageKnownServersLong": "Manage Known Servers",
|
||||
"displayNameTooltip": "Please enter a display name",
|
||||
"manageKnownServersButton": "Manage Known Servers",
|
||||
"fieldDescriptionLabel": "Description",
|
||||
"importLocalServerButton": "Import %1",
|
||||
"importLocalServerSelectText": "Select Local Server",
|
||||
"importLocalServerLabel": "Import a locally hosted server",
|
||||
"newMessagesLabel": "New Messages",
|
||||
"localeRU": "Russian \/ Русский",
|
||||
"copyServerKeys": "Copy keys",
|
||||
"verfiyResumeButton": "Verify\/resume",
|
||||
"fileCheckingStatus": "Checking download status",
|
||||
"fileInterrupted": "Interrupted",
|
||||
"fileSavedTo": "Saved to",
|
||||
"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.",
|
||||
"deleteServerSuccess": "Successfully deleted server",
|
||||
"enterCurrentPasswordForDeleteServer": "Please enter current password to delete this server",
|
||||
"copyAddress": "Copy Address",
|
||||
"settingServersDescription": "The hosting servers experiment enables hosting and managing Cwtch servers",
|
||||
"settingServers": "Hosting Servers",
|
||||
"enterServerPassword": "Enter password to unlock server",
|
||||
"unlockProfileTip": "Please create or unlock a profile to begin!",
|
||||
"unlockServerTip": "Please create or unlock a server to begin!",
|
||||
"addServerTooltip": "Add new server",
|
||||
"serversManagerTitleShort": "Servers",
|
||||
"serversManagerTitleLong": "Servers You Host",
|
||||
"saveServerButton": "Save Server",
|
||||
"serverAutostartDescription": "Controls if the application will automatically launch the server on start",
|
||||
"serverAutostartLabel": "Autostart",
|
||||
"serverEnabledDescription": "Start or stop the server",
|
||||
"serverEnabled": "Server Enabled",
|
||||
"serverDescriptionDescription": "Your description of the server for personal management use only, will never be shared",
|
||||
"serverDescriptionLabel": "Server Description",
|
||||
"serverAddress": "Server Address",
|
||||
"editServerTitle": "Edit Server",
|
||||
"addServerTitle": "Add Server",
|
||||
"titleManageProfilesShort": "Profiles",
|
||||
"descriptionFileSharing": "The file sharing experiment allows you to send and receive files from Cwtch contacts and groups. Note that sharing a file with a group will result in members of that group connecting with you directly over Cwtch to download it.",
|
||||
"settingFileSharing": "File Sharing",
|
||||
"tooltipSendFile": "Send File",
|
||||
"messageFileOffered": "Contact is offering to send you a file",
|
||||
"messageFileSent": "You sent a file",
|
||||
"messageEnableFileSharing": "Enable the file sharing experiment to view this message.",
|
||||
"labelFilesize": "Size",
|
||||
"labelFilename": "Filename",
|
||||
"downloadFileButton": "Download",
|
||||
"openFolderButton": "Open Folder",
|
||||
"retrievingManifestMessage": "Retrieving file information...",
|
||||
"descriptionStreamerMode": "If turned on, this option makes the app more visually private for streaming or presenting with, for example, hiding profile and contact addresses",
|
||||
"streamerModeLabel": "Streamer\/Presentation Mode",
|
||||
"archiveConversation": "Archive this Conversation",
|
||||
"blockUnknownConnectionsEnabledDescription": "Connections from unknown contacts are blocked. You can change this in Settings",
|
||||
"showMessageButton": "Show Message",
|
||||
"blockedMessageMessage": "This message is from a profile you have blocked.",
|
||||
"placeholderEnterMessage": "Type a message...",
|
||||
"plainProfileDescription": "We recommend that you protect your Cwtch profiles with a password. If you do not set a password on this profile then anyone who has access to this device may be able to access information about this profile, including contacts, messages and sensitive cryptographic keys.",
|
||||
"encryptedProfileDescription": "Encrypting a profile with a password protects it from other people who may also use this device. Encrypted profiles cannot be decrypted, displayed or accessed until the correct password is entered to unlock them.",
|
||||
"addContactConfirm": "Add contact %1",
|
||||
"addContact": "Add contact",
|
||||
"contactGoto": "Go to conversation with %1",
|
||||
"settingUIColumnOptionSame": "Same as portrait mode setting",
|
||||
"settingUIColumnDouble14Ratio": "Double (1:4)",
|
||||
"settingUIColumnDouble12Ratio": "Double (1:2)",
|
||||
"settingUIColumnSingle": "Single",
|
||||
"settingUIColumnLandscape": "UI Columns in Landscape Mode",
|
||||
"settingUIColumnPortrait": "UI Columns in Portrait Mode",
|
||||
"localePl": "Polish \/ Polski",
|
||||
"tooltipRemoveThisQuotedMessage": "Remove quoted message.",
|
||||
"tooltipReplyToThisMessage": "Reply to this message",
|
||||
"tooltipRejectContactRequest": "Reject this contact request",
|
||||
"tooltipAcceptContactRequest": "Accept this contact request.",
|
||||
"notificationNewMessageFromGroup": "New message in a group!",
|
||||
"notificationNewMessageFromPeer": "New message from a contact!",
|
||||
"tooltipHidePassword": "Hide Password",
|
||||
"tooltipShowPassword": "Show Password",
|
||||
"groupInviteSettingsWarning": "You have been invited to join a group! Please enable the Group Chat Experiment in Settings to view this Invitation.",
|
||||
"shutdownCwtchAction": "Shutdown Cwtch",
|
||||
"shutdownCwtchDialog": "Are you sure you want to shutdown Cwtch? This will close all connections, and exit the application.",
|
||||
"shutdownCwtchDialogTitle": "Shutdown Cwtch?",
|
||||
"shutdownCwtchTooltip": "Shutdown Cwtch",
|
||||
"malformedMessage": "Malformed message",
|
||||
"profileDeleteSuccess": "Successfully deleted profile",
|
||||
"debugLog": "Turn on console debug logging",
|
||||
"torNetworkStatus": "Tor network status",
|
||||
"addContactFirst": "Add or pick a contact to begin chatting.",
|
||||
"createProfileToBegin": "Please create or unlock a profile to begin",
|
||||
"nickChangeSuccess": "Profile nickname changed successfully",
|
||||
"addServerFirst": "You need to add a server before you can create a group",
|
||||
"deleteProfileSuccess": "Successfully deleted profile",
|
||||
"sendInvite": "Send a contact or group invite",
|
||||
"sendMessage": "Send Message",
|
||||
"cancel": "Cancel",
|
||||
"resetTor": "Reset",
|
||||
"torStatus": "Tor Status",
|
||||
"torVersion": "Tor Version",
|
||||
"sendAnInvitation": "You sent an invitation for: ",
|
||||
"contactSuggestion": "This is a contact suggestion for: ",
|
||||
"rejected": "Rejected!",
|
||||
"accepted": "Accepted!",
|
||||
"chatHistoryDefault": "This conversation will be deleted when Cwtch is closed! Message history can be enabled per-conversation via the Settings menu in the upper right.",
|
||||
"newPassword": "New Password",
|
||||
"yesLeave": "Yes, Leave This Conversation",
|
||||
"reallyLeaveThisGroupPrompt": "Are you sure you want to leave this conversation? All messages and attributes will be deleted.",
|
||||
"leaveConversation": "Leave This Conversation",
|
||||
"inviteToGroup": "You have been invited to join a group:",
|
||||
"titleManageServers": "Manage Servers",
|
||||
"successfullAddedContact": "Successfully added ",
|
||||
"descriptionBlockUnknownConnections": "If turned on, this option will automatically close connections from Cwtch users that have not been added to your contact list.",
|
||||
"descriptionExperimentsGroups": "The group experiment allows Cwtch to connect with untrusted server infrastructure to facilitate communication with more than one contact.",
|
||||
"descriptionExperiments": "Cwtch experiments are optional, opt-in features that add additional functionality to Cwtch that may have different privacy considerations than traditional 1:1 metadata resistant chat e.g. group chat, bot integration etc.",
|
||||
"titleManageProfiles": "Manage Cwtch Profiles",
|
||||
"tooltipUnlockProfiles": "Unlock encrypted profiles by entering their password.",
|
||||
"titleManageContacts": "Conversations",
|
||||
"tooltipAddContact": "Add a new contact or conversation",
|
||||
"tooltipOpenSettings": "Open the settings pane",
|
||||
"contactAlreadyExists": "Contact Already Exists",
|
||||
"invalidImportString": "Invalid import string",
|
||||
"conversationSettings": "Conversation Settings",
|
||||
"enterCurrentPasswordForDelete": "Please enter current password to delete this profile.",
|
||||
"enableGroups": "Enable Group Chat",
|
||||
"localeIt": "Italian \/ Italiano",
|
||||
"localeEs": "Spanish \/ Español",
|
||||
"todoPlaceholder": "Todo...",
|
||||
"addNewItem": "Add a new item to the list",
|
||||
"addListItem": "Add a New List Item",
|
||||
"newConnectionPaneTitle": "New Connection",
|
||||
"networkStatusOnline": "Online",
|
||||
"networkStatusConnecting": "Connecting to network and contacts...",
|
||||
"networkStatusAttemptingTor": "Attempting to connect to Tor network",
|
||||
"networkStatusDisconnected": "Disconnected from the internet, check your connection",
|
||||
"viewGroupMembershipTooltip": "View Group Membership",
|
||||
"loadingTor": "Loading tor...",
|
||||
"smallTextLabel": "Small",
|
||||
"defaultScalingText": "Font Scaling",
|
||||
"builddate": "Built on: %2",
|
||||
"version": "Version %1",
|
||||
"versionTor": "Version %1 with tor %2",
|
||||
"experimentsEnabled": "Enable Experiments",
|
||||
"themeDark": "Dark",
|
||||
"themeLight": "Light",
|
||||
"settingTheme": "Use Light Themes",
|
||||
"largeTextLabel": "Large",
|
||||
"settingInterfaceZoom": "Zoom level",
|
||||
"localeDe": "German \/ Deutsch",
|
||||
"localePt": "Portuguese \/ Portuguesa",
|
||||
"localeFr": "French \/ Français",
|
||||
"localeEn": "English \/ English",
|
||||
"settingLanguage": "Language",
|
||||
"blockUnknownLabel": "Block Unknown Contacts",
|
||||
"zoomLabel": "Interface zoom (mostly affects text and button sizes)",
|
||||
"versionBuilddate": "Version: %1 Built on: %2",
|
||||
"cwtchSettingsTitle": "Cwtch Settings",
|
||||
"unlock": "Unlock",
|
||||
"yourServers": "Your Servers",
|
||||
"yourProfiles": "Your Profiles",
|
||||
"error0ProfilesLoadedForPassword": "0 profiles loaded with that password",
|
||||
"password": "Password",
|
||||
"enterProfilePassword": "Enter a password to view your profiles",
|
||||
"addNewProfileBtn": "Add new profile",
|
||||
"deleteConfirmText": "DELETE",
|
||||
"deleteProfileConfirmBtn": "Really Delete Profile",
|
||||
"deleteConfirmLabel": "Type DELETE to confirm",
|
||||
"deleteProfileBtn": "Delete Profile",
|
||||
"passwordChangeError": "Error changing password: Supplied password rejected",
|
||||
"passwordErrorMatch": "Passwords do not match",
|
||||
"saveProfileBtn": "Save Profile",
|
||||
"createProfileBtn": "Create Profile",
|
||||
"passwordErrorEmpty": "Password cannot be empty",
|
||||
"password2Label": "Reenter password",
|
||||
"password1Label": "Password",
|
||||
"currentPasswordLabel": "Current Password",
|
||||
"yourDisplayName": "Your Display Name",
|
||||
"profileOnionLabel": "Send this address to contacts 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",
|
||||
"editProfile": "Edit Profile",
|
||||
"newProfile": "New Profile",
|
||||
"defaultProfileName": "Alice",
|
||||
"profileName": "Display name",
|
||||
"editProfileTitle": "Edit Profile",
|
||||
"addProfileTitle": "Add new profile",
|
||||
"deleteBtn": "Delete",
|
||||
"unblockBtn": "Unblock Contact",
|
||||
"dontSavePeerHistory": "Delete History",
|
||||
"savePeerHistoryDescription": "Determines whether to delete any history associated with the contact.",
|
||||
"savePeerHistory": "Save History",
|
||||
"blockBtn": "Block Contact",
|
||||
"saveBtn": "Save",
|
||||
"displayNameLabel": "Display Name",
|
||||
"copiedToClipboardNotification": "Copied to Clipboard",
|
||||
"addressLabel": "Address",
|
||||
"puzzleGameBtn": "Puzzle Game",
|
||||
"bulletinsBtn": "Bulletins",
|
||||
"listsBtn": "Lists",
|
||||
"chatBtn": "Chat",
|
||||
"rejectGroupBtn": "Reject",
|
||||
"acceptGroupBtn": "Accept",
|
||||
"acceptGroupInviteLabel": "Do you want to accept the invitation to",
|
||||
"newGroupBtn": "Create new group",
|
||||
"copyBtn": "Copy",
|
||||
"peerOfflineMessage": "Contact is offline, messages can't be delivered right now",
|
||||
"peerBlockedMessage": "Contact 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": "Contact is offline. Applications cannot be used right now.",
|
||||
"searchList": "Search List",
|
||||
"update": "Update",
|
||||
"inviteBtn": "Invite",
|
||||
"inviteToGroupLabel": "Invite to group",
|
||||
"groupNameLabel": "Group Name",
|
||||
"viewServerInfo": "Server Info",
|
||||
"serverNotSynced": "Syncing New Messages (This can take some time)...",
|
||||
"serverSynced": "Synced",
|
||||
"serverConnectivityDisconnected": "Server Disconnected",
|
||||
"serverConnectivityConnected": "Server Connected",
|
||||
"serverInfo": "Server Information",
|
||||
"invitationLabel": "Invitation",
|
||||
"serverLabel": "Server",
|
||||
"search": "Search...",
|
||||
"blocked": "Blocked",
|
||||
"pasteAddressToAddContact": "Paste a cwtch address, invitation or key bundle here to add a new conversation",
|
||||
"titlePlaceholder": "title...",
|
||||
"postNewBulletinLabel": "Post new bulletin",
|
||||
"newBulletinLabel": "New Bulletin",
|
||||
"joinGroup": "Join group",
|
||||
"createGroup": "Create group",
|
||||
"addPeer": "Add Contact",
|
||||
"groupAddr": "Address",
|
||||
"invitation": "Invitation",
|
||||
"server": "Server",
|
||||
"peerName": "Name",
|
||||
"peerAddress": "Address",
|
||||
"joinGroupTab": "Join a group",
|
||||
"createGroupTab": "Create a group",
|
||||
"addPeerTab": "Add a contact",
|
||||
"createGroupBtn": "Create",
|
||||
"defaultGroupName": "Awesome Group",
|
||||
"createGroupTitle": "Create Group"
|
||||
}
|
|
@ -44,6 +44,8 @@ Future<void> main() async {
|
|||
print("Cwtch version: ${EnvironmentConfig.BUILD_VER} built on: ${EnvironmentConfig.BUILD_DATE}");
|
||||
LicenseRegistry.addLicense(() => licenses());
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
// window_manager requires (await recommended but probably not required if not using immediately)
|
||||
windowManager.ensureInitialized();
|
||||
print("runApp()");
|
||||
return runApp(Flwtch());
|
||||
}
|
||||
|
@ -76,6 +78,7 @@ class FlwtchState extends State<Flwtch> with WindowListener {
|
|||
|
||||
@override
|
||||
initState() {
|
||||
print("initState() started, setting up handlers");
|
||||
globalSettings = Settings(Locale("en", ''), CwtchDark());
|
||||
globalErrorHandler = ErrorHandler();
|
||||
globalTorStatus = TorStatus();
|
||||
|
@ -85,7 +88,6 @@ class FlwtchState extends State<Flwtch> with WindowListener {
|
|||
print("initState: running...");
|
||||
windowManager.addListener(this);
|
||||
|
||||
|
||||
print("initState: registering notification, shutdown handlers...");
|
||||
profs = ProfileListState();
|
||||
notificationClickChannel.setMethodCallHandler(_externalNotificationClicked);
|
||||
|
@ -104,9 +106,14 @@ class FlwtchState extends State<Flwtch> with WindowListener {
|
|||
new CwtchNotifier(profs, globalSettings, globalErrorHandler, globalTorStatus, newDesktopNotificationsManager(_notificationSelectConvo), globalAppState, globalServersList, this);
|
||||
cwtch = CwtchFfi(cwtchNotifier);
|
||||
}
|
||||
startConnectivityListener();
|
||||
print("initState: invoking cwtch.Start()");
|
||||
cwtch.Start();
|
||||
print("initState: starting connectivityListener");
|
||||
if (EnvironmentConfig.TEST_MODE == false) {
|
||||
startConnectivityListener();
|
||||
} else {
|
||||
connectivityStream = null;
|
||||
}
|
||||
print("initState: done!");
|
||||
super.initState();
|
||||
}
|
||||
|
@ -288,7 +295,8 @@ class FlwtchState extends State<Flwtch> with WindowListener {
|
|||
);
|
||||
// On Gnome follows up a clicked notification with a "Cwtch is ready" notification that takes you to the app. AFAICT just because Gnome is bad
|
||||
// https://askubuntu.com/questions/1286206/how-to-skip-the-is-ready-notification-and-directly-open-apps-in-ubuntu-20-4
|
||||
windowManager.focus();
|
||||
await windowManager.show();
|
||||
await windowManager.focus();
|
||||
}
|
||||
|
||||
// using windowManager flutter plugin until proper lifecycle management lands in desktop
|
||||
|
@ -303,6 +311,8 @@ class FlwtchState extends State<Flwtch> with WindowListener {
|
|||
globalAppState.focus = false;
|
||||
}
|
||||
|
||||
void onWindowClose() {}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
globalAppState.SetModalState(ModalState.shutdown);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:cwtch/config.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
enum ModalState { none, storageMigration, shutdown }
|
||||
|
@ -11,6 +12,7 @@ class AppState extends ChangeNotifier {
|
|||
String appError = "";
|
||||
String? _selectedProfile;
|
||||
int? _selectedConversation;
|
||||
int? _selectedSearchMessage;
|
||||
int _initialScrollIndex = 0;
|
||||
bool _unreadMessagesBelow = false;
|
||||
bool _disableFilePicker = false;
|
||||
|
@ -30,11 +32,13 @@ class AppState extends ChangeNotifier {
|
|||
|
||||
void SetAppError(String error) {
|
||||
appError = error;
|
||||
EnvironmentConfig.debugLog("App Error: ${appError}");
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void SetModalState(ModalState newState) {
|
||||
modalState = newState;
|
||||
EnvironmentConfig.debugLog("Modal State: ${newState}");
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
|
@ -51,6 +55,12 @@ class AppState extends ChangeNotifier {
|
|||
notifyListeners();
|
||||
}
|
||||
|
||||
int? get selectedSearchMessage => _selectedSearchMessage;
|
||||
set selectedSearchMessage(int? newVal) {
|
||||
this._selectedSearchMessage = newVal;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
bool get disableFilePicker => _disableFilePicker;
|
||||
set disableFilePicker(bool newVal) {
|
||||
this._disableFilePicker = newVal;
|
||||
|
|
|
@ -68,6 +68,7 @@ class ContactInfoState extends ChangeNotifier {
|
|||
MessageDraft _messageDraft = MessageDraft.empty();
|
||||
|
||||
var _hoveredIndex = -1;
|
||||
var _pendingScroll = -1;
|
||||
|
||||
ContactInfoState(
|
||||
this.profileOnion,
|
||||
|
@ -264,6 +265,15 @@ class ContactInfoState extends ChangeNotifier {
|
|||
}
|
||||
}
|
||||
|
||||
bool canSend() {
|
||||
if (this.isGroup == true) {
|
||||
// We now have an out of sync warning so we will mark these as online...
|
||||
return this.status == "Synced" && this.antispamTickets > 0;
|
||||
} else {
|
||||
return this.isOnline();
|
||||
}
|
||||
}
|
||||
|
||||
ConversationNotificationPolicy get notificationsPolicy => _notificationPolicy;
|
||||
|
||||
set notificationsPolicy(ConversationNotificationPolicy newVal) {
|
||||
|
@ -429,6 +439,12 @@ class ContactInfoState extends ChangeNotifier {
|
|||
notifyListeners();
|
||||
}
|
||||
|
||||
int get pendingScroll => _pendingScroll;
|
||||
set pendingScroll(int newVal) {
|
||||
this._pendingScroll = newVal;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
String statusString(BuildContext context) {
|
||||
switch (this.availabilityStatus) {
|
||||
case ProfileStatusMenu.available:
|
||||
|
|
|
@ -160,6 +160,7 @@ class ById implements CacheHandler {
|
|||
if (messageInfo == null) {
|
||||
return Future.value(null);
|
||||
}
|
||||
EnvironmentConfig.debugLog("fetching $profileOnion $conversationIdentifier $id ${messageInfo.wrapper}");
|
||||
cache.addUnindexed(messageInfo);
|
||||
return Future.value(messageInfo);
|
||||
}
|
||||
|
|
|
@ -1,24 +1,26 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
/// A "MessageDraft" structure that stores information about in-progress message drafts.
|
||||
/// MessageDraft stores text, quoted replies, and attached images.
|
||||
/// Only one draft is stored per conversation.
|
||||
class MessageDraft extends ChangeNotifier {
|
||||
String? _messageText;
|
||||
QuotedReference? _quotedReference;
|
||||
|
||||
TextEditingController ctrlCompose = TextEditingController();
|
||||
|
||||
static MessageDraft empty() {
|
||||
return MessageDraft();
|
||||
}
|
||||
|
||||
bool isEmpty() {
|
||||
return (this._messageText == null && this._quotedReference == null) || (this._messageText != null && this._messageText!.isEmpty);
|
||||
return (this._quotedReference == null) || (this.messageText.isEmpty);
|
||||
}
|
||||
|
||||
String? get messageText => _messageText;
|
||||
String get messageText => ctrlCompose.text;
|
||||
|
||||
set messageText(String? text) {
|
||||
this._messageText = text;
|
||||
set messageText(String text) {
|
||||
this.ctrlCompose.text = text;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
|
@ -35,6 +37,18 @@ class MessageDraft extends ChangeNotifier {
|
|||
this._quotedReference = null;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void clearDraft() {
|
||||
this._quotedReference = null;
|
||||
this.ctrlCompose.clear();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
ctrlCompose.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// A QuotedReference encapsulates the state of replied-to message.
|
||||
|
|
|
@ -4,6 +4,7 @@ import 'package:cwtch/config.dart';
|
|||
import 'package:cwtch/models/message.dart';
|
||||
import 'package:cwtch/models/messages/malformedmessage.dart';
|
||||
import 'package:cwtch/widgets/malformedbubble.dart';
|
||||
import 'package:cwtch/widgets/messageBubbleWidgetHelpers.dart';
|
||||
import 'package:cwtch/widgets/messagerow.dart';
|
||||
import 'package:cwtch/widgets/quotedmessage.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
@ -39,15 +40,7 @@ class QuotedMessage extends Message {
|
|||
);
|
||||
var content = message["body"];
|
||||
var formatMessages = Provider.of<Settings>(bcontext).isExperimentEnabled(FormattingExperiment);
|
||||
return SelectableLinkify(
|
||||
text: content + '\u202F',
|
||||
options: LinkifyOptions(messageFormatting: formatMessages, parseLinks: false, looseUrl: true, defaultToHttps: true),
|
||||
linkifiers: [UrlLinkifier()],
|
||||
onOpen: null,
|
||||
textAlign: TextAlign.left,
|
||||
style: TextStyle(fontSize: 12.0 * Provider.of<Settings>(context).fontScaling, fontWeight: FontWeight.normal, fontFamily: "Inter", overflow: TextOverflow.ellipsis),
|
||||
codeStyle: TextStyle(fontSize: 12.0 * Provider.of<Settings>(context).fontScaling, fontWeight: FontWeight.normal, fontFamily: "Inter", overflow: TextOverflow.ellipsis),
|
||||
textWidthBasis: TextWidthBasis.longestLine);
|
||||
return compileMessageContentWidget(context, false, content, FocusNode(), formatMessages, false);
|
||||
} catch (e) {
|
||||
return MalformedBubble();
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import 'package:provider/provider.dart';
|
|||
|
||||
import '../../settings.dart';
|
||||
import '../../third_party/linkify/flutter_linkify.dart';
|
||||
import '../../widgets/messageBubbleWidgetHelpers.dart';
|
||||
|
||||
class TextMessage extends Message {
|
||||
final MessageMetadata metadata;
|
||||
|
@ -25,20 +26,8 @@ class TextMessage extends Message {
|
|||
value: this.metadata,
|
||||
builder: (bcontext, child) {
|
||||
var formatMessages = Provider.of<Settings>(bcontext).isExperimentEnabled(FormattingExperiment);
|
||||
return SelectableLinkify(
|
||||
text: content + '\u202F',
|
||||
options: LinkifyOptions(messageFormatting: formatMessages, parseLinks: false, looseUrl: true, defaultToHttps: true),
|
||||
linkifiers: [UrlLinkifier()],
|
||||
onOpen: null,
|
||||
textAlign: TextAlign.left,
|
||||
style: TextStyle(overflow: TextOverflow.fade, fontFamily: "Inter", fontSize: 12.0 * Provider.of<Settings>(context).fontScaling),
|
||||
linkStyle: TextStyle(overflow: TextOverflow.fade, fontFamily: "Inter", fontSize: 12.0 * Provider.of<Settings>(context).fontScaling),
|
||||
codeStyle: TextStyle(
|
||||
overflow: TextOverflow.ellipsis,
|
||||
fontFamily: "RobotoMono",
|
||||
),
|
||||
textWidthBasis: TextWidthBasis.parent,
|
||||
);
|
||||
return compileMessageContentWidget(context, false, content, FocusNode(), formatMessages, false);
|
||||
;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:convert';
|
|||
|
||||
import 'package:cwtch/config.dart';
|
||||
import 'package:cwtch/models/remoteserver.dart';
|
||||
import 'package:cwtch/models/search.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
|
||||
|
||||
|
@ -10,6 +11,7 @@ import '../views/contactsview.dart';
|
|||
import 'contact.dart';
|
||||
import 'contactlist.dart';
|
||||
import 'filedownloadprogress.dart';
|
||||
import 'message.dart';
|
||||
import 'messagecache.dart';
|
||||
import 'profileservers.dart';
|
||||
|
||||
|
@ -65,9 +67,11 @@ class ProfileInfoState extends ChangeNotifier {
|
|||
List<dynamic> contacts = jsonDecode(contactsJson);
|
||||
this._contacts.addAll(contacts.map((contact) {
|
||||
this._unreadMessages += contact["numUnread"] as int;
|
||||
|
||||
|
||||
return ContactInfoState(this.onion, contact["identifier"], contact["onion"],
|
||||
nickname: contact["name"],
|
||||
localNickname: contact["localname"],
|
||||
localNickname: contact["attributes"]?["local.profile.name"] ?? "", // contact may not have a local name
|
||||
status: contact["status"],
|
||||
imagePath: contact["picture"],
|
||||
defaultImagePath: contact["isGroup"] ? contact["picture"] : contact["defaultPicture"],
|
||||
|
@ -91,6 +95,23 @@ class ProfileInfoState extends ChangeNotifier {
|
|||
}
|
||||
}
|
||||
|
||||
// Code for managing the state of the profile-wide search feature...
|
||||
String activeSearchID = "";
|
||||
List<SearchResult> activeSearchResults = List.empty(growable: true);
|
||||
|
||||
void newSearch(String activeSearchID) {
|
||||
this.activeSearchID = activeSearchID;
|
||||
this.activeSearchResults.clear();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void handleSearchResult(String searchID, int conversationIdentifier, int messageIndex) {
|
||||
if (searchID == activeSearchID) {
|
||||
activeSearchResults.add(SearchResult(searchID: searchID, conversationIdentifier: conversationIdentifier, messageIndex: messageIndex));
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
// Parse out the server list json into our server info state struct...
|
||||
void replaceServers(String serversJson) {
|
||||
if (serversJson != "" && serversJson != "null") {
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
class SearchResult {
|
||||
String searchID;
|
||||
int conversationIdentifier;
|
||||
int messageIndex;
|
||||
SearchResult({required this.searchID, required this.conversationIdentifier, required this.messageIndex});
|
||||
}
|
|
@ -31,11 +31,33 @@ class NullNotificationsManager implements NotificationsManager {
|
|||
class WindowsNotificationManager implements NotificationsManager {
|
||||
bool active = false;
|
||||
bool initialized = false;
|
||||
late Future<void> Function(String, int) notificationSelectConvo;
|
||||
|
||||
// TODO This needs testing and redefining...
|
||||
WindowsNotificationManager() {
|
||||
WindowsNotificationManager(Future<void> Function(String, int) notificationSelectConvo) {
|
||||
this.notificationSelectConvo = notificationSelectConvo;
|
||||
scheduleMicrotask(() async {
|
||||
initialized = await WinToast.instance().initialize(clsid: 'cwtch', displayName: 'Cwtch', aumId: 'Open Privacy Research Society', iconPath: '');
|
||||
initialized = await WinToast.instance().initialize(appName: 'cwtch', productName: 'Cwtch', companyName: 'Open Privacy Research Society');
|
||||
/*
|
||||
* WinToast 0.3.0 code for when we can compile it
|
||||
*
|
||||
var init = await WinToast.instance().initialize(
|
||||
aumId: 'OpenPrivacyResearchSociety.Cwtch',
|
||||
displayName: 'Cwtch',
|
||||
iconPath: '', // TODO NEED ICON
|
||||
clsid: 'cwtch',
|
||||
);
|
||||
WinToast.instance().setActivatedCallback((event) {
|
||||
if (event.argument != "close") {
|
||||
try {
|
||||
Map<String, dynamic> payloadMap = jsonDecode(event.argument);
|
||||
var payload = NotificationPayload.fromJson(payloadMap);
|
||||
notificationSelectConvo(payload.profileOnion, payload.convoId);
|
||||
} catch (e) {
|
||||
/* it failed, is ok, may have been 'close'? */
|
||||
}
|
||||
}
|
||||
});*/
|
||||
initialized = true;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -43,15 +65,43 @@ class WindowsNotificationManager implements NotificationsManager {
|
|||
if (initialized && !globalAppState.focus) {
|
||||
if (!active) {
|
||||
active = true;
|
||||
// WinToast.instance().clear();
|
||||
//final toast = await WinToast.instance().showToast(toast: Toast(children: ,type: ToastType.text01, title: message));
|
||||
//toast?.eventStream.listen((event) {
|
||||
// if (event is ActivatedEvent) {
|
||||
// WinToast.instance().bringWindowToFront();
|
||||
// }
|
||||
WinToast.instance().clear();
|
||||
final toast = await WinToast.instance().showToast(type: ToastType.text01, title: message);
|
||||
toast?.eventStream.listen((event) {
|
||||
if (event is ActivatedEvent) {
|
||||
WinToast.instance().bringWindowToFront();
|
||||
}
|
||||
active = false;
|
||||
// });
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* WinToast 0.3.0 code for when we can compile it
|
||||
*
|
||||
WinToast.instance().clear();
|
||||
await WinToast.instance().showToast(
|
||||
toast: Toast(duration: ToastDuration.short, children: [
|
||||
ToastChildAudio(source: ToastAudioSource.im),
|
||||
ToastChildVisual(
|
||||
binding: ToastVisualBinding(children: [
|
||||
ToastVisualBindingChildText(
|
||||
text: message,
|
||||
id: 1,
|
||||
),
|
||||
])),
|
||||
ToastChildActions(children: [
|
||||
ToastAction(
|
||||
content: "Open",
|
||||
arguments: jsonEncode(NotificationPayload(profile, conversationId)),
|
||||
),
|
||||
ToastAction(
|
||||
content: "Close",
|
||||
arguments: "close",
|
||||
),
|
||||
]),
|
||||
]));
|
||||
active = false;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -113,12 +163,12 @@ class NixNotificationManager implements NotificationsManager {
|
|||
linuxAssetsPath = "";
|
||||
}
|
||||
|
||||
|
||||
var linuxIcon = FilePathLinuxIcon(path.join(linuxAssetsPath, 'assets/knott.png'));
|
||||
|
||||
final LinuxInitializationSettings initializationSettingsLinux = LinuxInitializationSettings(defaultActionName: 'Open notification', defaultIcon: linuxIcon, defaultSuppressSound: true);
|
||||
|
||||
final InitializationSettings initializationSettings = InitializationSettings(android: null, iOS: null, macOS: DarwinInitializationSettings(defaultPresentSound: false), linux: initializationSettingsLinux);
|
||||
final InitializationSettings initializationSettings =
|
||||
InitializationSettings(android: null, iOS: null, macOS: DarwinInitializationSettings(defaultPresentSound: false), linux: initializationSettingsLinux);
|
||||
|
||||
flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<MacOSFlutterLocalNotificationsPlugin>()?.requestPermissions(
|
||||
alert: true,
|
||||
|
@ -126,7 +176,9 @@ class NixNotificationManager implements NotificationsManager {
|
|||
sound: false,
|
||||
);
|
||||
|
||||
await flutterLocalNotificationsPlugin.initialize(initializationSettings, );
|
||||
await flutterLocalNotificationsPlugin.initialize(
|
||||
initializationSettings,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -173,7 +225,7 @@ NotificationsManager newDesktopNotificationsManager(Future<void> Function(String
|
|||
}
|
||||
} else if (Platform.isWindows) {
|
||||
try {
|
||||
return WindowsNotificationManager();
|
||||
return WindowsNotificationManager(notificationSelectConvo);
|
||||
} catch (e) {
|
||||
EnvironmentConfig.debugLog("Failed to create Windows desktoasts notification manager");
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ class Settings extends ChangeNotifier {
|
|||
NotificationPolicy _notificationPolicy = NotificationPolicy.DefaultAll;
|
||||
NotificationContent _notificationContent = NotificationContent.SimpleEvent;
|
||||
|
||||
bool preserveHistoryByDefault = false;
|
||||
bool blockUnknownConnections = false;
|
||||
bool streamerMode = false;
|
||||
String _downloadPath = "";
|
||||
|
@ -131,13 +132,18 @@ class Settings extends ChangeNotifier {
|
|||
switchLocaleByCode(settings["Locale"]);
|
||||
|
||||
// Decide whether to enable Experiments
|
||||
_fontScaling = double.parse(settings["FontScaling"].toString()).clamp(0.5, 2.0);
|
||||
var fontScale = settings["FontScaling"];
|
||||
if (fontScale == null) {
|
||||
fontScale = 1.0;
|
||||
}
|
||||
_fontScaling = double.parse(fontScale.toString()).clamp(0.5, 2.0);
|
||||
|
||||
blockUnknownConnections = settings["BlockUnknownConnections"] ?? false;
|
||||
streamerMode = settings["StreamerMode"] ?? false;
|
||||
|
||||
// Decide whether to enable Experiments
|
||||
experimentsEnabled = settings["ExperimentsEnabled"] ?? false;
|
||||
preserveHistoryByDefault = settings["DefaultSaveHistory"] ?? false;
|
||||
|
||||
// Set the internal experiments map. Casting from the Map<dynamic, dynamic> that we get from JSON
|
||||
experiments = new HashMap<String, bool>.from(settings["Experiments"]);
|
||||
|
@ -192,6 +198,11 @@ class Settings extends ChangeNotifier {
|
|||
|
||||
double get fontScaling => _fontScaling;
|
||||
|
||||
// a convenience function to scale fonts dynamically...
|
||||
TextStyle scaleFonts(TextStyle input) {
|
||||
return input.copyWith(fontSize: (input.fontSize ?? 12) * this.fontScaling);
|
||||
}
|
||||
|
||||
/// Switch the Locale of the App
|
||||
switchLocale(Locale newLocale) {
|
||||
locale = newLocale;
|
||||
|
@ -203,6 +214,18 @@ class Settings extends ChangeNotifier {
|
|||
notifyListeners();
|
||||
}
|
||||
|
||||
/// Preserve the History of all Conversations By Default (can be overridden for specific conversations)
|
||||
setPreserveHistoryDefault() {
|
||||
preserveHistoryByDefault = true;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// Delete the History of all Conversations By Default (can be overridden for specific conversations)
|
||||
setDeleteHistoryDefault() {
|
||||
preserveHistoryByDefault = false;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// Block Unknown Connections will autoblock connections if they authenticate with public key not in our contacts list.
|
||||
/// This is one of the best tools we have to combat abuse, while it isn't ideal it does allow a user to curate their contacts
|
||||
/// list without being bothered by spurious requests (either permanently, or as a short term measure).
|
||||
|
@ -467,7 +490,8 @@ class Settings extends ChangeNotifier {
|
|||
"UseTorCache": _useTorCache,
|
||||
"TorCacheDir": _torCacheDir,
|
||||
"BlodeuweddPath": _blodeuweddPath,
|
||||
"FontScaling": _fontScaling
|
||||
"FontScaling": _fontScaling,
|
||||
"DefaultSaveHistory": preserveHistoryByDefault
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,13 @@ import 'neon2.dart';
|
|||
const mode_light = "light";
|
||||
const mode_dark = "dark";
|
||||
|
||||
final TextStyle defaultSmallTextStyle = TextStyle(fontFamily: "Inter", fontWeight: FontWeight.normal, fontSize: 10);
|
||||
final TextStyle defaultMessageTextStyle = TextStyle(fontFamily: "Inter", fontWeight: FontWeight.w400, fontSize: 13);
|
||||
final TextStyle defaultFormLabelTextStyle = TextStyle(fontFamily: "Inter", fontWeight: FontWeight.bold, fontSize: 20);
|
||||
final TextStyle defaultTextStyle = TextStyle(fontFamily: "Inter", fontWeight: FontWeight.w500, fontSize: 12);
|
||||
final TextStyle defaultTextButtonStyle = defaultTextStyle.copyWith(fontWeight: FontWeight.bold);
|
||||
final TextStyle defaultDropDownMenuItemTextStyle = TextStyle(fontFamily: "Inter", fontWeight: FontWeight.bold, fontSize: 16);
|
||||
|
||||
final themes = {
|
||||
cwtch_theme: {mode_light: CwtchLight(), mode_dark: CwtchDark()},
|
||||
ghost_theme: {mode_light: GhostLight(), mode_dark: GhostDark()},
|
||||
|
@ -177,6 +184,7 @@ ThemeData mkThemeData(Settings opaque) {
|
|||
? opaque.current().defaultButtonDisabledColor
|
||||
: null),
|
||||
enableFeedback: true,
|
||||
textStyle: MaterialStateProperty.all(opaque.scaleFonts(defaultTextButtonStyle)),
|
||||
padding: MaterialStateProperty.all(EdgeInsets.all(20)),
|
||||
shape: MaterialStateProperty.all(RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(6.0),
|
||||
|
@ -186,9 +194,12 @@ ThemeData mkThemeData(Settings opaque) {
|
|||
|
||||
scrollbarTheme: ScrollbarThemeData(isAlwaysShown: false, thumbColor: MaterialStateProperty.all(opaque.current().scrollbarDefaultColor)),
|
||||
tabBarTheme: TabBarTheme(
|
||||
labelColor: opaque.current().mainTextColor,
|
||||
unselectedLabelColor: opaque.current().mainTextColor,
|
||||
indicator: UnderlineTabIndicator(borderSide: BorderSide(color: opaque.current().defaultButtonActiveColor))),
|
||||
labelColor: opaque.current().mainTextColor,
|
||||
unselectedLabelColor: opaque.current().mainTextColor,
|
||||
indicator: UnderlineTabIndicator(borderSide: BorderSide(color: opaque.current().defaultButtonActiveColor)),
|
||||
labelStyle: opaque.scaleFonts(defaultTextButtonStyle),
|
||||
unselectedLabelStyle: opaque.scaleFonts(defaultTextStyle),
|
||||
),
|
||||
dialogTheme: DialogTheme(
|
||||
backgroundColor: opaque.current().backgroundPaneColor,
|
||||
titleTextStyle: TextStyle(fontFamily: "Inter", fontWeight: FontWeight.bold, color: opaque.current().mainTextColor),
|
||||
|
@ -199,8 +210,8 @@ ThemeData mkThemeData(Settings opaque) {
|
|||
textTheme: TextTheme(
|
||||
// NOTE: The following font scales were arrived at after consulting the material text scale
|
||||
// docs: https://m3.material.io/styles/typography/type-scale-tokens and some trial and error
|
||||
displayMedium: TextStyle(fontFamily: "Inter", fontSize: opaque.fontScaling * 16.0, color: opaque.current().mainTextColor),
|
||||
displaySmall: TextStyle(fontFamily: "Inter", fontSize: opaque.fontScaling * 14.0, color: opaque.current().mainTextColor),
|
||||
displayMedium: TextStyle(fontFamily: "Inter", fontSize: opaque.fontScaling * 16.0, color: opaque.current().mainTextColor),
|
||||
displayLarge: TextStyle(fontFamily: "Inter", fontSize: opaque.fontScaling * 18.0, color: opaque.current().mainTextColor),
|
||||
titleSmall: TextStyle(fontFamily: "Inter", fontWeight: FontWeight.bold, fontSize: opaque.fontScaling * 16.0, color: opaque.current().mainTextColor),
|
||||
titleLarge: TextStyle(fontFamily: "Inter", fontWeight: FontWeight.bold, fontSize: opaque.fontScaling * 18.0, color: opaque.current().mainTextColor),
|
||||
|
@ -212,8 +223,8 @@ ThemeData mkThemeData(Settings opaque) {
|
|||
headlineMedium: TextStyle(fontFamily: "Inter", fontWeight: FontWeight.bold, fontSize: opaque.fontScaling * 26.0, color: opaque.current().mainTextColor),
|
||||
headlineLarge: TextStyle(fontFamily: "Inter", fontWeight: FontWeight.bold, fontSize: opaque.fontScaling * 28.0, color: opaque.current().mainTextColor),
|
||||
labelSmall: TextStyle(fontFamily: "Inter", fontWeight: FontWeight.w100, fontSize: opaque.fontScaling * 14.0, color: opaque.current().mainTextColor),
|
||||
labelLarge: TextStyle(fontFamily: "Inter", fontWeight: FontWeight.w200, fontSize: opaque.fontScaling * 16.0, color: opaque.current().mainTextColor),
|
||||
labelMedium: TextStyle(fontFamily: "Inter", fontWeight: FontWeight.w300, fontSize: opaque.fontScaling * 18.0, color: opaque.current().mainTextColor),
|
||||
labelMedium: TextStyle(fontFamily: "Inter", fontWeight: FontWeight.w300, fontSize: opaque.fontScaling * 16.0, color: opaque.current().mainTextColor),
|
||||
labelLarge: TextStyle(fontFamily: "Inter", fontWeight: FontWeight.w200, fontSize: opaque.fontScaling * 18.0, color: opaque.current().mainTextColor),
|
||||
),
|
||||
switchTheme: SwitchThemeData(
|
||||
overlayColor: MaterialStateProperty.all(opaque.current().defaultButtonActiveColor),
|
||||
|
|
|
@ -121,7 +121,7 @@ class UrlLinkifier extends Linkifier {
|
|||
Formatter(_boldRegex, BoldElement.new),
|
||||
Formatter(_italicRegex, ItalicElement.new),
|
||||
Formatter(_superRegex, SuperElement.new),
|
||||
Formatter(_subRegex, SubElement.new),
|
||||
// Formatter(_subRegex, SubElement.new),
|
||||
Formatter(_strikeRegex, StrikeElement.new)
|
||||
];
|
||||
|
||||
|
|
|
@ -227,7 +227,8 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
|
|||
|
||||
// Enabled
|
||||
Visibility(
|
||||
visible: Provider.of<ProfileInfoState>(context).onion.isNotEmpty && !Provider.of<ProfileInfoState>(context).enabled,
|
||||
// FIXME don't show the disable switch in test mode...this is a bug relating to scrolling things into view
|
||||
visible: Provider.of<ProfileInfoState>(context).onion.isNotEmpty && (EnvironmentConfig.TEST_MODE == false),
|
||||
child: SwitchListTile(
|
||||
title: Text(AppLocalizations.of(context)!.profileEnabled, style: TextStyle(color: Provider.of<Settings>(context).current().mainTextColor)),
|
||||
subtitle: Text(AppLocalizations.of(context)!.profileEnabledDescription),
|
||||
|
|
|
@ -7,6 +7,7 @@ import 'package:cwtch/models/contact.dart';
|
|||
import 'package:cwtch/models/contactlist.dart';
|
||||
import 'package:cwtch/models/profile.dart';
|
||||
import 'package:cwtch/models/profilelist.dart';
|
||||
import 'package:cwtch/models/search.dart';
|
||||
import 'package:cwtch/views/profileserversview.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cwtch/widgets/contactrow.dart';
|
||||
|
@ -15,8 +16,11 @@ import 'package:cwtch/widgets/textfield.dart';
|
|||
import 'package:flutter/services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
|
||||
import '../config.dart';
|
||||
import '../main.dart';
|
||||
import '../models/message.dart';
|
||||
import '../settings.dart';
|
||||
import '../themes/opaque.dart';
|
||||
import 'addcontactview.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:qr_flutter/qr_flutter.dart';
|
||||
|
@ -35,10 +39,23 @@ class ContactsView extends StatefulWidget {
|
|||
}
|
||||
|
||||
// selectConversation can be called from anywhere to set the active conversation
|
||||
void selectConversation(BuildContext context, int handle) {
|
||||
void selectConversation(BuildContext context, int handle, int? messageIndex) {
|
||||
int? index = null;
|
||||
|
||||
if (messageIndex != null) {
|
||||
// this message is loaded
|
||||
Provider.of<AppState>(context, listen: false).selectedSearchMessage = messageIndex;
|
||||
Provider.of<AppState>(context, listen: false).initialScrollIndex = messageIndex!;
|
||||
EnvironmentConfig.debugLog("Looked up index $messageIndex");
|
||||
}
|
||||
|
||||
if (handle == Provider.of<AppState>(context, listen: false).selectedConversation) {
|
||||
if (messageIndex != null) {
|
||||
Provider.of<ContactInfoState>(context, listen: false).messageScrollController.scrollTo(index: messageIndex, duration: Duration(milliseconds: 100));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// requery instead of using contactinfostate directly because sometimes listview gets confused about data that resorts
|
||||
var unread = Provider.of<ProfileInfoState>(context, listen: false).contactList.getContact(handle)!.unreadMessages;
|
||||
var previouslySelected = Provider.of<AppState>(context, listen: false).selectedConversation;
|
||||
|
@ -48,9 +65,12 @@ void selectConversation(BuildContext context, int handle) {
|
|||
Provider.of<ProfileInfoState>(context, listen: false).contactList.getContact(handle)!.selected();
|
||||
|
||||
// triggers update in Double/TripleColumnView
|
||||
Provider.of<AppState>(context, listen: false).initialScrollIndex = unread;
|
||||
Provider.of<AppState>(context, listen: false).selectedConversation = handle;
|
||||
Provider.of<ContactInfoState>(context, listen: false).hoveredIndex = -1;
|
||||
Provider.of<AppState>(context, listen: false).selectedConversation = handle;
|
||||
if (index != null) {
|
||||
Provider.of<AppState>(context, listen: false).initialScrollIndex = unread;
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
@ -164,21 +184,15 @@ class _ContactsViewState extends State<ContactsView> {
|
|||
itemBuilder: (BuildContext context) => <PopupMenuEntry<ProfileStatusMenu>>[
|
||||
PopupMenuItem<ProfileStatusMenu>(
|
||||
value: ProfileStatusMenu.available,
|
||||
child: Text(
|
||||
AppLocalizations.of(context)!.availabilityStatusAvailable!,
|
||||
),
|
||||
child: Text(AppLocalizations.of(context)!.availabilityStatusAvailable!, style: Provider.of<Settings>(context, listen: false).scaleFonts(defaultTextButtonStyle)),
|
||||
),
|
||||
PopupMenuItem<ProfileStatusMenu>(
|
||||
value: ProfileStatusMenu.away,
|
||||
child: Text(
|
||||
AppLocalizations.of(context)!.availabilityStatusAway!,
|
||||
),
|
||||
child: Text(AppLocalizations.of(context)!.availabilityStatusAway!, style: Provider.of<Settings>(context, listen: false).scaleFonts(defaultTextButtonStyle)),
|
||||
),
|
||||
PopupMenuItem<ProfileStatusMenu>(
|
||||
value: ProfileStatusMenu.busy,
|
||||
child: Text(
|
||||
AppLocalizations.of(context)!.availabilityStatusBusy!,
|
||||
),
|
||||
child: Text(AppLocalizations.of(context)!.availabilityStatusBusy!, style: Provider.of<Settings>(context, listen: false).scaleFonts(defaultTextButtonStyle)),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -237,11 +251,11 @@ class _ContactsViewState extends State<ContactsView> {
|
|||
itemBuilder: (BuildContext context) => <PopupMenuEntry<ShareMenu>>[
|
||||
PopupMenuItem<ShareMenu>(
|
||||
value: ShareMenu.copyCode,
|
||||
child: Text(AppLocalizations.of(context)!.copyAddress),
|
||||
child: Text(AppLocalizations.of(context)!.copyAddress, style: Provider.of<Settings>(context, listen: false).scaleFonts(defaultTextButtonStyle)),
|
||||
),
|
||||
PopupMenuItem<ShareMenu>(
|
||||
value: ShareMenu.qrcode,
|
||||
child: Text(AppLocalizations.of(context)!.shareMenuQRCode),
|
||||
child: Text(AppLocalizations.of(context)!.shareMenuQRCode, style: Provider.of<Settings>(context, listen: false).scaleFonts(defaultTextButtonStyle)),
|
||||
),
|
||||
],
|
||||
));
|
||||
|
@ -287,6 +301,10 @@ class _ContactsViewState extends State<ContactsView> {
|
|||
controller: ctrlrFilter,
|
||||
hintText: AppLocalizations.of(context)!.search,
|
||||
onChanged: (newVal) {
|
||||
String profileHandle = Provider.of<ProfileInfoState>(context, listen: false).onion;
|
||||
Provider.of<FlwtchState>(context, listen: false).cwtch.SearchConversations(profileHandle, newVal).then((value) {
|
||||
Provider.of<ProfileInfoState>(context, listen: false).newSearch(value);
|
||||
});
|
||||
Provider.of<ContactListState>(context, listen: false).filter = newVal;
|
||||
},
|
||||
);
|
||||
|
@ -294,7 +312,7 @@ class _ContactsViewState extends State<ContactsView> {
|
|||
}
|
||||
|
||||
Widget _buildContactList() {
|
||||
final tiles = Provider.of<ContactListState>(context).filteredList().map((ContactInfoState contact) {
|
||||
var tilesSearchResult = Provider.of<ContactListState>(context).filteredList().map((ContactInfoState contact) {
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider.value(value: contact),
|
||||
|
@ -310,15 +328,28 @@ class _ContactsViewState extends State<ContactsView> {
|
|||
initialScroll = 0;
|
||||
}
|
||||
|
||||
if (showSearchBar) {
|
||||
List<SearchResult> searchResults = Provider.of<ProfileInfoState>(context).activeSearchResults;
|
||||
tilesSearchResult = searchResults.map((SearchResult searchResult) {
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider.value(value: Provider.of<ProfileInfoState>(context).contactList.getContact(searchResult.conversationIdentifier)),
|
||||
ChangeNotifierProvider.value(value: Provider.of<ProfileInfoState>(context).serverList),
|
||||
],
|
||||
builder: (context, child) => ContactRow(messageIndex: searchResult.messageIndex),
|
||||
);
|
||||
});
|
||||
} else {}
|
||||
|
||||
var contactList = ScrollablePositionedList.separated(
|
||||
itemScrollController: Provider.of<ProfileInfoState>(context).contactListScrollController,
|
||||
itemCount: Provider.of<ContactListState>(context).numFiltered,
|
||||
itemCount: tilesSearchResult.length,
|
||||
initialScrollIndex: initialScroll,
|
||||
shrinkWrap: true,
|
||||
physics: BouncingScrollPhysics(),
|
||||
semanticChildCount: Provider.of<ContactListState>(context).numFiltered,
|
||||
semanticChildCount: tilesSearchResult.length,
|
||||
itemBuilder: (context, index) {
|
||||
return tiles.elementAt(index);
|
||||
return tilesSearchResult.elementAt(index);
|
||||
},
|
||||
separatorBuilder: (BuildContext context, int index) {
|
||||
return Divider(height: 1);
|
||||
|
@ -354,6 +385,7 @@ class _ContactsViewState extends State<ContactsView> {
|
|||
|
||||
Navigator.of(context).push(
|
||||
PageRouteBuilder(
|
||||
settings: RouteSettings(name: "profileremoteservers"),
|
||||
pageBuilder: (bcontext, a1, a2) {
|
||||
return MultiProvider(
|
||||
providers: [ChangeNotifierProvider.value(value: profileInfoState), Provider.value(value: Provider.of<FlwtchState>(context))],
|
||||
|
|
|
@ -37,7 +37,7 @@ class _FileSharingViewState extends State<FileSharingView> {
|
|||
future: Provider.of<FlwtchState>(context, listen: false).cwtch.GetSharedFiles(profileHandle, Provider.of<ContactInfoState>(context).identifier),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
List<dynamic> sharedFiles = jsonDecode(snapshot.data as String);
|
||||
List<dynamic> sharedFiles = jsonDecode(snapshot.data as String) ?? List<dynamic>.empty();
|
||||
sharedFiles.sort((a, b) {
|
||||
return a["DateShared"].toString().compareTo(b["DateShared"].toString());
|
||||
});
|
||||
|
|
|
@ -128,7 +128,12 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
|
|||
items: AppLocalizations.supportedLocales.map<DropdownMenuItem<String>>((Locale value) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: value.toString(),
|
||||
child: Text(key: Key("dropdownLanguage" + value.languageCode), getLanguageFull(context, value.languageCode, value.countryCode)),
|
||||
child: Text(
|
||||
key: Key("dropdownLanguage" + value.languageCode),
|
||||
getLanguageFull(context, value.languageCode, value.countryCode),
|
||||
style: settings.scaleFonts(defaultDropDownMenuItemTextStyle),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
);
|
||||
}).toList()))),
|
||||
SwitchListTile(
|
||||
|
@ -165,7 +170,7 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
|
|||
items: themes.keys.map<DropdownMenuItem<String>>((String themeId) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: themeId,
|
||||
child: Text(getThemeName(context, themeId)), //"ddi_$themeId", key: Key("ddi_$themeId")),
|
||||
child: Text(getThemeName(context, themeId), style: settings.scaleFonts(defaultDropDownMenuItemTextStyle)), //"ddi_$themeId", key: Key("ddi_$themeId")),
|
||||
);
|
||||
}).toList())),
|
||||
leading: Icon(Icons.palette, color: settings.current().mainTextColor),
|
||||
|
@ -185,7 +190,7 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
|
|||
items: Settings.uiColumnModeOptions(false).map<DropdownMenuItem<String>>((DualpaneMode value) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: value.toString(),
|
||||
child: Text(Settings.uiColumnModeToString(value, context)),
|
||||
child: Text(Settings.uiColumnModeToString(value, context), style: settings.scaleFonts(defaultDropDownMenuItemTextStyle)),
|
||||
);
|
||||
}).toList()))),
|
||||
ListTile(
|
||||
|
@ -193,7 +198,6 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
|
|||
AppLocalizations.of(context)!.settingUIColumnLandscape,
|
||||
textWidthBasis: TextWidthBasis.longestLine,
|
||||
softWrap: true,
|
||||
style: TextStyle(color: settings.current().mainTextColor),
|
||||
),
|
||||
leading: Icon(Icons.stay_primary_landscape, color: settings.current().mainTextColor),
|
||||
trailing: Container(
|
||||
|
@ -210,10 +214,7 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
|
|||
items: Settings.uiColumnModeOptions(true).map<DropdownMenuItem<String>>((DualpaneMode value) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: value.toString(),
|
||||
child: Text(
|
||||
Settings.uiColumnModeToString(value, context),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
child: Text(Settings.uiColumnModeToString(value, context), overflow: TextOverflow.ellipsis, style: settings.scaleFonts(defaultDropDownMenuItemTextStyle)),
|
||||
);
|
||||
}).toList())))),
|
||||
ListTile(
|
||||
|
@ -229,8 +230,9 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
|
|||
EnvironmentConfig.debugLog("Font Scaling: $value");
|
||||
},
|
||||
min: 0.5,
|
||||
divisions: 6,
|
||||
divisions: 12,
|
||||
max: 2.0,
|
||||
label: '${settings.fontScaling * 100}%',
|
||||
activeColor: settings.current().defaultButtonColor,
|
||||
thumbColor: settings.current().mainTextColor,
|
||||
overlayColor: MaterialStateProperty.all(settings.current().mainTextColor),
|
||||
|
@ -305,10 +307,7 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
|
|||
items: NotificationPolicy.values.map<DropdownMenuItem<NotificationPolicy>>((NotificationPolicy value) {
|
||||
return DropdownMenuItem<NotificationPolicy>(
|
||||
value: value,
|
||||
child: Text(
|
||||
Settings.notificationPolicyToString(value, context),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
child: Text(Settings.notificationPolicyToString(value, context), overflow: TextOverflow.ellipsis, style: settings.scaleFonts(defaultDropDownMenuItemTextStyle)),
|
||||
);
|
||||
}).toList())),
|
||||
leading: Icon(CwtchIcons.chat_bubble_empty_24px, color: settings.current().mainTextColor),
|
||||
|
@ -328,10 +327,7 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
|
|||
items: NotificationContent.values.map<DropdownMenuItem<NotificationContent>>((NotificationContent value) {
|
||||
return DropdownMenuItem<NotificationContent>(
|
||||
value: value,
|
||||
child: Text(
|
||||
Settings.notificationContentToString(value, context),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
child: Text(Settings.notificationContentToString(value, context), overflow: TextOverflow.ellipsis, style: settings.scaleFonts(defaultDropDownMenuItemTextStyle)),
|
||||
);
|
||||
}).toList())),
|
||||
leading: Icon(CwtchIcons.chat_bubble_empty_24px, color: settings.current().mainTextColor),
|
||||
|
@ -354,6 +350,24 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
|
|||
inactiveTrackColor: settings.theme.defaultButtonDisabledColor,
|
||||
secondary: Icon(CwtchIcons.block_unknown, color: settings.current().mainTextColor),
|
||||
),
|
||||
SwitchListTile(
|
||||
title: Text(AppLocalizations.of(context)!.defaultPreserveHistorySetting),
|
||||
subtitle: Text(AppLocalizations.of(context)!.preserveHistorySettingDescription),
|
||||
value: settings.preserveHistoryByDefault,
|
||||
onChanged: (bool value) {
|
||||
if (value) {
|
||||
settings.setPreserveHistoryDefault();
|
||||
} else {
|
||||
settings.setDeleteHistoryDefault();
|
||||
}
|
||||
|
||||
// Save Settings...
|
||||
saveSettings(context);
|
||||
},
|
||||
activeTrackColor: settings.theme.defaultButtonColor,
|
||||
inactiveTrackColor: settings.theme.defaultButtonDisabledColor,
|
||||
secondary: Icon(CwtchIcons.block_unknown, color: settings.current().mainTextColor),
|
||||
),
|
||||
SizedBox(
|
||||
height: 40,
|
||||
),
|
||||
|
@ -472,6 +486,7 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
|
|||
testKey: Key("DownloadFolderPicker"),
|
||||
label: AppLocalizations.of(context)!.settingDownloadFolder,
|
||||
initialValue: settings.downloadPath,
|
||||
textStyle: settings.scaleFonts(defaultDropDownMenuItemTextStyle),
|
||||
description: AppLocalizations.of(context)!.fileSharingSettingsDownloadFolderDescription,
|
||||
tooltip: AppLocalizations.of(context)!.fileSharingSettingsDownloadFolderTooltip,
|
||||
onSave: (newVal) {
|
||||
|
@ -747,6 +762,15 @@ String getLanguageFull(context, String languageCode, String? countryCode) {
|
|||
if (languageCode == "ja") {
|
||||
return AppLocalizations.of(context)!.localeJa;
|
||||
}
|
||||
if (languageCode == "sv") {
|
||||
return AppLocalizations.of(context)!.localeSv;
|
||||
}
|
||||
if (languageCode == "sw") {
|
||||
return AppLocalizations.of(context)!.localeSw;
|
||||
}
|
||||
if (languageCode == "uk") {
|
||||
return AppLocalizations.of(context)!.localeUk;
|
||||
}
|
||||
return languageCode;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'package:cwtch/cwtch_icons_icons.dart';
|
|||
import 'package:cwtch/models/appstate.dart';
|
||||
import 'package:cwtch/models/contact.dart';
|
||||
import 'package:cwtch/models/profile.dart';
|
||||
import 'package:cwtch/themes/opaque.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:cwtch/widgets/buttontextfield.dart';
|
||||
import 'package:cwtch/widgets/cwtchlabel.dart';
|
||||
|
@ -130,7 +131,7 @@ class _GroupSettingsViewState extends State<GroupSettingsView> {
|
|||
items: ConversationNotificationPolicy.values.map<DropdownMenuItem<ConversationNotificationPolicy>>((ConversationNotificationPolicy value) {
|
||||
return DropdownMenuItem<ConversationNotificationPolicy>(
|
||||
value: value,
|
||||
child: Text(value.toName(context)),
|
||||
child: Text(value.toName(context), style: settings.scaleFonts(defaultDropDownMenuItemTextStyle)),
|
||||
);
|
||||
}).toList(),
|
||||
onChanged: (ConversationNotificationPolicy? newVal) {
|
||||
|
@ -180,7 +181,7 @@ class _GroupSettingsViewState extends State<GroupSettingsView> {
|
|||
icon: Icon(CwtchIcons.leave_group),
|
||||
label: Text(
|
||||
AppLocalizations.of(context)!.leaveConversation,
|
||||
style: TextStyle(decoration: TextDecoration.underline),
|
||||
style: settings.scaleFonts(defaultTextButtonStyle.copyWith(decoration: TextDecoration.underline)),
|
||||
),
|
||||
))
|
||||
])
|
||||
|
|
|
@ -14,6 +14,7 @@ import 'package:cwtch/models/message_draft.dart';
|
|||
import 'package:cwtch/models/messagecache.dart';
|
||||
import 'package:cwtch/models/messages/quotedmessage.dart';
|
||||
import 'package:cwtch/models/profile.dart';
|
||||
import 'package:cwtch/themes/opaque.dart';
|
||||
import 'package:cwtch/third_party/linkify/flutter_linkify.dart';
|
||||
import 'package:cwtch/widgets/malformedbubble.dart';
|
||||
import 'package:cwtch/widgets/messageloadingbubble.dart';
|
||||
|
@ -44,7 +45,6 @@ class MessageView extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _MessageViewState extends State<MessageView> {
|
||||
final ctrlrCompose = TextEditingController();
|
||||
final focusNode = FocusNode();
|
||||
int selectedContact = -1;
|
||||
ItemPositionsListener scrollListener = ItemPositionsListener.create();
|
||||
|
@ -68,7 +68,6 @@ class _MessageViewState extends State<MessageView> {
|
|||
showDown = false;
|
||||
}
|
||||
});
|
||||
ctrlrCompose.text = Provider.of<ContactInfoState>(context, listen: false).messageDraft.messageText ?? "";
|
||||
super.initState();
|
||||
}
|
||||
|
||||
|
@ -88,7 +87,6 @@ class _MessageViewState extends State<MessageView> {
|
|||
@override
|
||||
void dispose() {
|
||||
focusNode.dispose();
|
||||
ctrlrCompose.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
@ -321,22 +319,21 @@ class _MessageViewState extends State<MessageView> {
|
|||
|
||||
void _sendMessage([String? ignoredParam]) {
|
||||
// Do this after we trim to preserve enter-behaviour...
|
||||
bool isOffline = Provider.of<ContactInfoState>(context, listen: false).isOnline() == false;
|
||||
bool performingAntiSpam = Provider.of<ContactInfoState>(context, listen: false).antispamTickets == 0;
|
||||
bool cannotSend = Provider.of<ContactInfoState>(context, listen: false).canSend() == false;
|
||||
bool isGroup = Provider.of<ContactInfoState>(context, listen: false).isGroup;
|
||||
if (isOffline || (isGroup && performingAntiSpam)) {
|
||||
if (cannotSend) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Trim message
|
||||
final messageWithoutNewLine = ctrlrCompose.value.text.trimRight();
|
||||
ctrlrCompose.value = TextEditingValue(text: messageWithoutNewLine, selection: TextSelection.fromPosition(TextPosition(offset: messageWithoutNewLine.length)));
|
||||
var messageText = Provider.of<ContactInfoState>(context, listen: false).messageDraft.messageText ?? "";
|
||||
final messageWithoutNewLine = messageText.trimRight();
|
||||
|
||||
// peers and groups currently have different length constraints (servers can store less)...
|
||||
var actualMessageLength = ctrlrCompose.value.text.length;
|
||||
var actualMessageLength = messageText.length;
|
||||
var lengthOk = (isGroup && actualMessageLength < GroupMessageLengthMax) || actualMessageLength <= P2PMessageLengthMax;
|
||||
|
||||
if (ctrlrCompose.value.text.isNotEmpty && lengthOk) {
|
||||
if (messageWithoutNewLine.isNotEmpty && lengthOk) {
|
||||
if (Provider.of<AppState>(context, listen: false).selectedConversation != null && Provider.of<ContactInfoState>(context, listen: false).messageDraft.getQuotedMessage() != null) {
|
||||
var conversationId = Provider.of<AppState>(context, listen: false).selectedConversation!;
|
||||
MessageCache? cache = Provider.of<ProfileInfoState>(context, listen: false).contactList.getContact(conversationId)?.messageCache;
|
||||
|
@ -347,7 +344,7 @@ class _MessageViewState extends State<MessageView> {
|
|||
var bytes1 = utf8.encode(data!.metadata.senderHandle + data.wrapper);
|
||||
var digest1 = sha256.convert(bytes1);
|
||||
var contentHash = base64Encode(digest1.bytes);
|
||||
var quotedMessage = jsonEncode(QuotedMessageStructure(contentHash, ctrlrCompose.value.text));
|
||||
var quotedMessage = jsonEncode(QuotedMessageStructure(contentHash, messageWithoutNewLine));
|
||||
ChatMessage cm = new ChatMessage(o: QuotedMessageOverlay, d: quotedMessage);
|
||||
Provider.of<FlwtchState>(context, listen: false)
|
||||
.cwtch
|
||||
|
@ -359,7 +356,7 @@ class _MessageViewState extends State<MessageView> {
|
|||
Provider.of<ContactInfoState>(context, listen: false).messageDraft.clearQuotedReference();
|
||||
});
|
||||
} else {
|
||||
ChatMessage cm = new ChatMessage(o: TextMessageOverlay, d: ctrlrCompose.value.text);
|
||||
ChatMessage cm = new ChatMessage(o: TextMessageOverlay, d: messageWithoutNewLine);
|
||||
Provider.of<FlwtchState>(context, listen: false)
|
||||
.cwtch
|
||||
.SendMessage(Provider.of<ContactInfoState>(context, listen: false).profileOnion, Provider.of<ContactInfoState>(context, listen: false).identifier, jsonEncode(cm))
|
||||
|
@ -391,8 +388,7 @@ class _MessageViewState extends State<MessageView> {
|
|||
|
||||
// At this point we have decided to send the text to the backend, failure is still possible
|
||||
// but it will show as an error-ed message, as such the draft can be purged.
|
||||
Provider.of<ContactInfoState>(context, listen: false).messageDraft = MessageDraft.empty();
|
||||
ctrlrCompose.clear();
|
||||
Provider.of<ContactInfoState>(context, listen: false).messageDraft.clearDraft();
|
||||
|
||||
var profileOnion = Provider.of<ContactInfoState>(context, listen: false).profileOnion;
|
||||
var identifier = Provider.of<ContactInfoState>(context, listen: false).identifier;
|
||||
|
@ -424,7 +420,7 @@ class _MessageViewState extends State<MessageView> {
|
|||
var wdgMessage = Padding(
|
||||
padding: EdgeInsets.all(8),
|
||||
child: SelectableLinkify(
|
||||
text: ctrlrCompose.text + '\n',
|
||||
text: Provider.of<ContactInfoState>(context).messageDraft.messageText + '\n',
|
||||
options: LinkifyOptions(messageFormatting: true, parseLinks: showClickableLinks, looseUrl: true, defaultToHttps: true),
|
||||
linkifiers: [UrlLinkifier()],
|
||||
onOpen: showClickableLinks ? null : null,
|
||||
|
@ -468,7 +464,7 @@ class _MessageViewState extends State<MessageView> {
|
|||
margin: EdgeInsets.all(2),
|
||||
|
||||
// 164 minimum height + 16px for every line of text so the entire message is displayed when previewed.
|
||||
height: 164 + ((ctrlrCompose.text.split("\n").length - 1) * 16),
|
||||
height: 164 + ((Provider.of<ContactInfoState>(context).messageDraft.messageText.split("\n").length - 1) * 16),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(mainAxisAlignment: MainAxisAlignment.start, mainAxisSize: MainAxisSize.max, children: [preview]),
|
||||
|
@ -483,11 +479,11 @@ class _MessageViewState extends State<MessageView> {
|
|||
}
|
||||
|
||||
Widget _buildComposeBox(BuildContext context) {
|
||||
bool isOffline = Provider.of<ContactInfoState>(context).isOnline() == false;
|
||||
bool cannotSend = Provider.of<ContactInfoState>(context).canSend() == false;
|
||||
bool isGroup = Provider.of<ContactInfoState>(context).isGroup;
|
||||
var showToolbar = Provider.of<Settings>(context).isExperimentEnabled(FormattingExperiment);
|
||||
var charLength = ctrlrCompose.value.text.characters.length;
|
||||
var expectedLength = ctrlrCompose.value.text.length;
|
||||
var charLength = Provider.of<ContactInfoState>(context).messageDraft.messageText.characters.length;
|
||||
var expectedLength = Provider.of<ContactInfoState>(context).messageDraft.messageText.length;
|
||||
var numberOfBytesMoreThanChar = (expectedLength - charLength);
|
||||
|
||||
var bold = IconButton(
|
||||
|
@ -495,12 +491,14 @@ class _MessageViewState extends State<MessageView> {
|
|||
tooltip: AppLocalizations.of(context)!.tooltipBoldText,
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
var ctrlrCompose = Provider.of<ContactInfoState>(context, listen: false).messageDraft.ctrlCompose;
|
||||
var selected = ctrlrCompose.selection.textInside(ctrlrCompose.text);
|
||||
var selection = ctrlrCompose.selection;
|
||||
var start = ctrlrCompose.selection.start;
|
||||
var end = ctrlrCompose.selection.end;
|
||||
ctrlrCompose.text = ctrlrCompose.text.replaceRange(start, end, "**" + selected + "**");
|
||||
ctrlrCompose.selection = selection.copyWith(baseOffset: selection.start + 2, extentOffset: selection.start + 2);
|
||||
Provider.of<ContactInfoState>(context, listen: false).messageDraft.ctrlCompose = ctrlrCompose;
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -509,12 +507,14 @@ class _MessageViewState extends State<MessageView> {
|
|||
tooltip: AppLocalizations.of(context)!.tooltipItalicize,
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
var ctrlrCompose = Provider.of<ContactInfoState>(context, listen: false).messageDraft.ctrlCompose;
|
||||
var selected = ctrlrCompose.selection.textInside(ctrlrCompose.text);
|
||||
var selection = ctrlrCompose.selection;
|
||||
var start = ctrlrCompose.selection.start;
|
||||
var end = ctrlrCompose.selection.end;
|
||||
ctrlrCompose.text = ctrlrCompose.text.replaceRange(start, end, "*" + selected + "*");
|
||||
ctrlrCompose.selection = selection.copyWith(baseOffset: selection.start + 1, extentOffset: selection.start + 1);
|
||||
Provider.of<ContactInfoState>(context, listen: false).messageDraft.ctrlCompose = ctrlrCompose;
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -523,12 +523,14 @@ class _MessageViewState extends State<MessageView> {
|
|||
tooltip: AppLocalizations.of(context)!.tooltipCode,
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
var ctrlrCompose = Provider.of<ContactInfoState>(context, listen: false).messageDraft.ctrlCompose;
|
||||
var selected = ctrlrCompose.selection.textInside(ctrlrCompose.text);
|
||||
var selection = ctrlrCompose.selection;
|
||||
var start = ctrlrCompose.selection.start;
|
||||
var end = ctrlrCompose.selection.end;
|
||||
ctrlrCompose.text = ctrlrCompose.text.replaceRange(start, end, "`" + selected + "`");
|
||||
ctrlrCompose.selection = selection.copyWith(baseOffset: selection.start + 1, extentOffset: selection.start + 1);
|
||||
Provider.of<ContactInfoState>(context, listen: false).messageDraft.ctrlCompose = ctrlrCompose;
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -537,40 +539,46 @@ class _MessageViewState extends State<MessageView> {
|
|||
tooltip: AppLocalizations.of(context)!.tooltipSuperscript,
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
var ctrlrCompose = Provider.of<ContactInfoState>(context, listen: false).messageDraft.ctrlCompose;
|
||||
var selected = ctrlrCompose.selection.textInside(ctrlrCompose.text);
|
||||
var selection = ctrlrCompose.selection;
|
||||
var start = ctrlrCompose.selection.start;
|
||||
var end = ctrlrCompose.selection.end;
|
||||
ctrlrCompose.text = ctrlrCompose.text.replaceRange(start, end, "^" + selected + "^");
|
||||
ctrlrCompose.selection = selection.copyWith(baseOffset: selection.start + 1, extentOffset: selection.start + 1);
|
||||
Provider.of<ContactInfoState>(context, listen: false).messageDraft.ctrlCompose = ctrlrCompose;
|
||||
});
|
||||
});
|
||||
|
||||
var subscript = IconButton(
|
||||
icon: Icon(Icons.subscript),
|
||||
tooltip: AppLocalizations.of(context)!.tooltipSubscript,
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
var selected = ctrlrCompose.selection.textInside(ctrlrCompose.text);
|
||||
var selection = ctrlrCompose.selection;
|
||||
var start = ctrlrCompose.selection.start;
|
||||
var end = ctrlrCompose.selection.end;
|
||||
ctrlrCompose.text = ctrlrCompose.text.replaceRange(start, end, "_" + selected + "_");
|
||||
ctrlrCompose.selection = selection.copyWith(baseOffset: selection.start + 1, extentOffset: selection.start + 1);
|
||||
});
|
||||
});
|
||||
// var subscript = IconButton(
|
||||
// icon: Icon(Icons.subscript),
|
||||
// tooltip: AppLocalizations.of(context)!.tooltipSubscript,
|
||||
// onPressed: () {
|
||||
// setState(() {
|
||||
// var ctrlrCompose = Provider.of<ContactInfoState>(context, listen: false).messageDraft.ctrlCompose;
|
||||
// var selected = ctrlrCompose.selection.textInside(ctrlrCompose.text);
|
||||
// var selection = ctrlrCompose.selection;
|
||||
// var start = ctrlrCompose.selection.start;
|
||||
// var end = ctrlrCompose.selection.end;
|
||||
// ctrlrCompose.text = ctrlrCompose.text.replaceRange(start, end, "_" + selected + "_");
|
||||
// ctrlrCompose.selection = selection.copyWith(baseOffset: selection.start + 1, extentOffset: selection.start + 1);
|
||||
// Provider.of<ContactInfoState>(context, listen: false).messageDraft.ctrlCompose = ctrlrCompose;
|
||||
// });
|
||||
// });
|
||||
|
||||
var strikethrough = IconButton(
|
||||
icon: Icon(Icons.format_strikethrough),
|
||||
tooltip: AppLocalizations.of(context)!.tooltipStrikethrough,
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
var ctrlrCompose = Provider.of<ContactInfoState>(context, listen: false).messageDraft.ctrlCompose;
|
||||
var selected = ctrlrCompose.selection.textInside(ctrlrCompose.text);
|
||||
var selection = ctrlrCompose.selection;
|
||||
var start = ctrlrCompose.selection.start;
|
||||
var end = ctrlrCompose.selection.end;
|
||||
ctrlrCompose.text = ctrlrCompose.text.replaceRange(start, end, "~~" + selected + "~~");
|
||||
ctrlrCompose.selection = selection.copyWith(baseOffset: selection.start + 2, extentOffset: selection.start + 2);
|
||||
Provider.of<ContactInfoState>(context, listen: false).messageDraft.ctrlCompose = ctrlrCompose;
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -589,7 +597,7 @@ class _MessageViewState extends State<MessageView> {
|
|||
|
||||
var formattingToolbar = Container(
|
||||
decoration: BoxDecoration(color: Provider.of<Settings>(context).theme.defaultButtonActiveColor),
|
||||
child: Row(mainAxisAlignment: MainAxisAlignment.start, children: [bold, italic, code, superscript, subscript, strikethrough, vline, preview]));
|
||||
child: Row(mainAxisAlignment: MainAxisAlignment.start, children: [bold, italic, code, superscript, strikethrough, vline, preview]));
|
||||
|
||||
var textField = Container(
|
||||
decoration: BoxDecoration(border: Border(top: BorderSide(color: Provider.of<Settings>(context).theme.defaultButtonActiveColor))),
|
||||
|
@ -600,7 +608,7 @@ class _MessageViewState extends State<MessageView> {
|
|||
padding: EdgeInsets.all(8),
|
||||
child: TextFormField(
|
||||
key: Key('txtCompose'),
|
||||
controller: ctrlrCompose,
|
||||
controller: Provider.of<ContactInfoState>(context).messageDraft.ctrlCompose,
|
||||
focusNode: focusNode,
|
||||
autofocus: !Platform.isAndroid,
|
||||
textInputAction: TextInputAction.newline,
|
||||
|
@ -612,22 +620,20 @@ class _MessageViewState extends State<MessageView> {
|
|||
maxLengthEnforcement: MaxLengthEnforcement.enforced,
|
||||
maxLines: 3,
|
||||
onFieldSubmitted: _sendMessage,
|
||||
style: TextStyle(
|
||||
fontFamily: "Inter",
|
||||
fontSize: 12.0 * Provider.of<Settings>(context).fontScaling,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
style: Provider.of<Settings>(context).scaleFonts(defaultMessageTextStyle).copyWith(
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
enabled: true, // always allow editing...
|
||||
|
||||
onChanged: (String x) {
|
||||
Provider.of<ContactInfoState>(context, listen: false).messageDraft.messageText = x;
|
||||
setState(() {
|
||||
// we need to force a rerender here to update the max length count
|
||||
});
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
hintText: isOffline ? "" : AppLocalizations.of(context)!.placeholderEnterMessage,
|
||||
hintStyle: TextStyle(fontFamily: "Inter", fontSize: 10.0 * Provider.of<Settings>(context).fontScaling, color: Provider.of<Settings>(context).theme.sendHintTextColor),
|
||||
hintText: AppLocalizations.of(context)!.placeholderEnterMessage,
|
||||
hintStyle:
|
||||
Provider.of<Settings>(context).scaleFonts(defaultMessageTextStyle).copyWith(color: Provider.of<Settings>(context).theme.sendHintTextColor, fontWeight: FontWeight.bold),
|
||||
enabledBorder: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
enabled: true,
|
||||
|
@ -635,13 +641,13 @@ class _MessageViewState extends State<MessageView> {
|
|||
key: Key("btnSend"),
|
||||
style: ElevatedButton.styleFrom(padding: EdgeInsets.all(0.0), shape: new RoundedRectangleBorder(borderRadius: new BorderRadius.circular(45.0))),
|
||||
child: Tooltip(
|
||||
message: isOffline
|
||||
message: cannotSend
|
||||
? (isGroup ? AppLocalizations.of(context)!.serverNotSynced : AppLocalizations.of(context)!.peerOfflineMessage)
|
||||
: (isGroup && Provider.of<ContactInfoState>(context, listen: false).antispamTickets == 0)
|
||||
? AppLocalizations.of(context)!.acquiringTicketsFromServer
|
||||
: AppLocalizations.of(context)!.sendMessage,
|
||||
child: Icon(CwtchIcons.send_24px, size: 24, color: Provider.of<Settings>(context).theme.defaultButtonTextColor)),
|
||||
onPressed: isOffline || (isGroup && Provider.of<ContactInfoState>(context, listen: false).antispamTickets == 0) ? null : _sendMessage,
|
||||
onPressed: cannotSend || (isGroup && Provider.of<ContactInfoState>(context, listen: false).antispamTickets == 0) ? null : _sendMessage,
|
||||
))),
|
||||
)));
|
||||
|
||||
|
@ -727,7 +733,8 @@ class _MessageViewState extends State<MessageView> {
|
|||
if (event is RawKeyUpEvent) {
|
||||
if ((data.logicalKey == LogicalKeyboardKey.enter && !event.isShiftPressed) || data.logicalKey == LogicalKeyboardKey.numpadEnter && !event.isShiftPressed) {
|
||||
// Don't send when inserting a new line that is not at the end of the message
|
||||
if (ctrlrCompose.selection.baseOffset != ctrlrCompose.text.length) {
|
||||
if (Provider.of<ContactInfoState>(context, listen: false).messageDraft.ctrlCompose.selection.baseOffset !=
|
||||
Provider.of<ContactInfoState>(context, listen: false).messageDraft.ctrlCompose.text.length) {
|
||||
return;
|
||||
}
|
||||
_sendMessage();
|
||||
|
@ -735,8 +742,6 @@ class _MessageViewState extends State<MessageView> {
|
|||
}
|
||||
}
|
||||
|
||||
void placeHolder() => {};
|
||||
|
||||
// explicitly passing BuildContext ctx here is important, change at risk to own health
|
||||
// otherwise some Providers will become inaccessible to subwidgets...?
|
||||
// https://stackoverflow.com/a/63818697
|
||||
|
|
|
@ -14,6 +14,7 @@ import 'package:provider/provider.dart';
|
|||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
|
||||
import '../main.dart';
|
||||
import '../themes/opaque.dart';
|
||||
|
||||
/// Peer Settings View Provides way to Configure .
|
||||
class PeerSettingsView extends StatefulWidget {
|
||||
|
@ -216,8 +217,9 @@ class _PeerSettingsViewState extends State<PeerSettingsView> {
|
|||
subtitle: Text(AppLocalizations.of(context)!.savePeerHistoryDescription),
|
||||
leading: Icon(CwtchIcons.peer_history, color: settings.current().mainTextColor),
|
||||
trailing: DropdownButton(
|
||||
value: Provider.of<ContactInfoState>(context).savePeerHistory == "DefaultDeleteHistory"
|
||||
? AppLocalizations.of(context)!.dontSavePeerHistory
|
||||
value: (Provider.of<ContactInfoState>(context).savePeerHistory == "DefaultDeleteHistory" ||
|
||||
Provider.of<ContactInfoState>(context).savePeerHistory == "HistoryDefault")
|
||||
? AppLocalizations.of(context)!.conversationNotificationPolicyDefault
|
||||
: (Provider.of<ContactInfoState>(context).savePeerHistory == "SaveHistory"
|
||||
? AppLocalizations.of(context)!.savePeerHistory
|
||||
: AppLocalizations.of(context)!.dontSavePeerHistory),
|
||||
|
@ -229,8 +231,13 @@ class _PeerSettingsViewState extends State<PeerSettingsView> {
|
|||
const SaveHistoryKey = "profile.SavePeerHistory";
|
||||
const SaveHistory = "SaveHistory";
|
||||
const DelHistory = "DeleteHistoryConfirmed";
|
||||
const HistoryDefault = "HistoryDefault";
|
||||
|
||||
if (newValue == AppLocalizations.of(context)!.savePeerHistory) {
|
||||
// NOTE: .savePeerHistory is used to show ephemeral warnings so it's state is important to update.
|
||||
if(newValue == AppLocalizations.of(context)!.conversationNotificationPolicyDefault) {
|
||||
Provider.of<ContactInfoState>(context, listen: false).savePeerHistory = HistoryDefault;
|
||||
Provider.of<FlwtchState>(context, listen: false).cwtch.SetConversationAttribute(profileOnion, identifier, SaveHistoryKey, HistoryDefault);
|
||||
} else if (newValue == AppLocalizations.of(context)!.savePeerHistory) {
|
||||
Provider.of<ContactInfoState>(context, listen: false).savePeerHistory = SaveHistory;
|
||||
Provider.of<FlwtchState>(context, listen: false).cwtch.SetConversationAttribute(profileOnion, identifier, SaveHistoryKey, SaveHistory);
|
||||
} else {
|
||||
|
@ -239,10 +246,10 @@ class _PeerSettingsViewState extends State<PeerSettingsView> {
|
|||
}
|
||||
});
|
||||
},
|
||||
items: [AppLocalizations.of(context)!.savePeerHistory, AppLocalizations.of(context)!.dontSavePeerHistory].map<DropdownMenuItem<String>>((String value) {
|
||||
items: [AppLocalizations.of(context)!.conversationNotificationPolicyDefault, AppLocalizations.of(context)!.savePeerHistory, AppLocalizations.of(context)!.dontSavePeerHistory].map<DropdownMenuItem<String>>((String value) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: value,
|
||||
child: Text(value),
|
||||
child: Text(value, style: settings.scaleFonts(defaultDropDownMenuItemTextStyle)),
|
||||
);
|
||||
}).toList())),
|
||||
ListTile(
|
||||
|
@ -254,7 +261,7 @@ class _PeerSettingsViewState extends State<PeerSettingsView> {
|
|||
items: ConversationNotificationPolicy.values.map<DropdownMenuItem<ConversationNotificationPolicy>>((ConversationNotificationPolicy value) {
|
||||
return DropdownMenuItem<ConversationNotificationPolicy>(
|
||||
value: value,
|
||||
child: Text(value.toName(context)),
|
||||
child: Text(value.toName(context), style: settings.scaleFonts(defaultDropDownMenuItemTextStyle)),
|
||||
);
|
||||
}).toList(),
|
||||
onChanged: (ConversationNotificationPolicy? newVal) {
|
||||
|
|
|
@ -20,6 +20,8 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
|||
import '../errorHandler.dart';
|
||||
import '../main.dart';
|
||||
import '../config.dart';
|
||||
import '../models/appstate.dart';
|
||||
import '../themes/opaque.dart';
|
||||
|
||||
/// Pane to add or edit a server
|
||||
class RemoteServerView extends StatefulWidget {
|
||||
|
@ -91,12 +93,26 @@ class _RemoteServerViewState extends State<RemoteServerView> {
|
|||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
|
||||
Row(crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.end, children: [
|
||||
Tooltip(
|
||||
message: serverInfoState.groups.isNotEmpty ? AppLocalizations.of(context)!.cannotDeleteServerIfActiveGroups : AppLocalizations.of(context)!.leaveConversation,
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: serverInfoState.groups.isNotEmpty ? null : () {
|
||||
showAlertDialog(context);
|
||||
},
|
||||
icon: Icon(CwtchIcons.leave_group),
|
||||
label: Text(
|
||||
AppLocalizations.of(context)!.deleteBtn,
|
||||
style: settings.scaleFonts(defaultTextButtonStyle),
|
||||
),
|
||||
))
|
||||
]),
|
||||
Padding(
|
||||
padding: EdgeInsets.all(8),
|
||||
child: Text(AppLocalizations.of(context)!.groupsOnThisServerLabel),
|
||||
),
|
||||
Expanded(child: _buildGroupsList(serverInfoState))
|
||||
Expanded(child: _buildGroupsList(serverInfoState)),
|
||||
|
||||
])));
|
||||
});
|
||||
}
|
||||
|
@ -147,3 +163,40 @@ class _RemoteServerViewState extends State<RemoteServerView> {
|
|||
]));
|
||||
}
|
||||
}
|
||||
|
||||
showAlertDialog(BuildContext context) {
|
||||
// set up the buttons
|
||||
Widget cancelButton = ElevatedButton(
|
||||
child: Text(AppLocalizations.of(context)!.cancel),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(); // dismiss dialog
|
||||
},
|
||||
);
|
||||
Widget continueButton = ElevatedButton(
|
||||
style: ButtonStyle(padding: MaterialStateProperty.all(EdgeInsets.all(20))),
|
||||
child: Text(AppLocalizations.of(context)!.deleteServerConfirmBtn),
|
||||
onPressed: () {
|
||||
var profileOnion = Provider.of<ProfileInfoState>(context, listen: false).onion;
|
||||
var serverInfoState = Provider.of<RemoteServerInfoState>(context, listen: false);
|
||||
Provider.of<FlwtchState>(context, listen: false).cwtch.DeleteServerInfo(profileOnion, serverInfoState.onion);
|
||||
Navigator.popUntil(context, (route) => route.settings.name == "profileremoteservers");
|
||||
},
|
||||
);
|
||||
|
||||
// set up the AlertDialog
|
||||
AlertDialog alert = AlertDialog(
|
||||
title: Text(AppLocalizations.of(context)!.deleteServerConfirmBtn),
|
||||
actions: [
|
||||
cancelButton,
|
||||
continueButton,
|
||||
],
|
||||
);
|
||||
|
||||
// show the dialog
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return alert;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:cwtch/models/appstate.dart';
|
||||
import 'package:cwtch/themes/opaque.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
@ -52,7 +53,7 @@ class _SplashViewState extends State<SplashView> {
|
|||
: appState.modalState == ModalState.storageMigration
|
||||
? AppLocalizations.of(context)!.storageMigrationModalMessage
|
||||
: AppLocalizations.of(context)!.shuttingDownApp, // Todo l10n AppLocalizations.of(context)!.storageMigrationModalMessage
|
||||
style: TextStyle(
|
||||
style: defaultTextButtonStyle.copyWith(
|
||||
fontSize: 16.0, color: appState.appError == "" ? Provider.of<Settings>(context).theme.mainTextColor : Provider.of<Settings>(context).theme.textfieldErrorColor))),
|
||||
Visibility(
|
||||
visible: appState.modalState == ModalState.storageMigration || appState.modalState == ModalState.shutdown,
|
||||
|
|
|
@ -14,6 +14,7 @@ class CwtchButtonTextField extends StatefulWidget {
|
|||
this.labelText,
|
||||
this.testKey,
|
||||
this.onChanged,
|
||||
this.textStyle,
|
||||
});
|
||||
final TextEditingController controller;
|
||||
final Function()? onPressed;
|
||||
|
@ -22,6 +23,7 @@ class CwtchButtonTextField extends StatefulWidget {
|
|||
final String tooltip;
|
||||
final bool readonly;
|
||||
final Key? testKey;
|
||||
final TextStyle? textStyle;
|
||||
String? labelText;
|
||||
|
||||
@override
|
||||
|
@ -56,7 +58,7 @@ class _CwtchButtonTextFieldState extends State<CwtchButtonTextField> {
|
|||
enableIMEPersonalizedLearning: false,
|
||||
onChanged: widget.onChanged,
|
||||
maxLines: 1,
|
||||
style: TextStyle(overflow: TextOverflow.clip),
|
||||
style: widget.textStyle == null ? TextStyle(overflow: TextOverflow.clip) : widget.textStyle,
|
||||
decoration: InputDecoration(
|
||||
labelText: widget.labelText,
|
||||
labelStyle: TextStyle(color: theme.current().mainTextColor, backgroundColor: theme.current().textfieldBackgroundColor),
|
||||
|
|
|
@ -10,21 +10,34 @@ import 'package:cwtch/widgets/profileimage.dart';
|
|||
import 'package:provider/provider.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import '../main.dart';
|
||||
import '../models/message.dart';
|
||||
import '../settings.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
class ContactRow extends StatefulWidget {
|
||||
int? messageIndex;
|
||||
|
||||
ContactRow({this.messageIndex});
|
||||
@override
|
||||
_ContactRowState createState() => _ContactRowState();
|
||||
}
|
||||
|
||||
class _ContactRowState extends State<ContactRow> {
|
||||
bool isHover = false;
|
||||
Message? cachedMessage = null;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var contact = Provider.of<ContactInfoState>(context);
|
||||
|
||||
if (widget.messageIndex != null && this.cachedMessage == null) {
|
||||
messageHandler(context, Provider.of<ProfileInfoState>(context, listen: false).onion, contact.identifier, ByIndex(widget.messageIndex!)).then((value) {
|
||||
setState(() {
|
||||
this.cachedMessage = value;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Only groups have a sync status
|
||||
Widget? syncStatus;
|
||||
if (contact.isGroup) {
|
||||
|
@ -37,11 +50,19 @@ class _ContactRowState extends State<ContactRow> {
|
|||
));
|
||||
}
|
||||
|
||||
bool selected = Provider.of<AppState>(context).selectedConversation == contact.identifier;
|
||||
if (selected && widget.messageIndex != null) {
|
||||
if (selected && widget.messageIndex == Provider.of<AppState>(context).selectedSearchMessage) {
|
||||
selected = true;
|
||||
} else {
|
||||
selected = false;
|
||||
}
|
||||
}
|
||||
return InkWell(
|
||||
enableFeedback: true,
|
||||
splashFactory: InkSplash.splashFactory,
|
||||
child: Ink(
|
||||
color: Provider.of<AppState>(context).selectedConversation == contact.identifier ? Provider.of<Settings>(context).theme.backgroundHilightElementColor : Colors.transparent,
|
||||
color: selected ? Provider.of<Settings>(context).theme.backgroundHilightElementColor : Colors.transparent,
|
||||
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(6.0), //border size
|
||||
|
@ -85,6 +106,17 @@ class _ContactRowState extends State<ContactRow> {
|
|||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(color: contact.isBlocked ? Provider.of<Settings>(context).theme.portraitBlockedTextColor : Provider.of<Settings>(context).theme.mainTextColor)),
|
||||
),
|
||||
// we need to ignore the child widget in this context, otherwise gesture events will flow down...
|
||||
IgnorePointer(
|
||||
ignoring: true,
|
||||
child: Visibility(
|
||||
visible: this.cachedMessage != null,
|
||||
maintainSize: false,
|
||||
maintainInteractivity: false,
|
||||
maintainSemantics: false,
|
||||
maintainState: false,
|
||||
child: this.cachedMessage == null ? CircularProgressIndicator() : this.cachedMessage!.getPreviewWidget(context),
|
||||
)),
|
||||
Container(
|
||||
padding: EdgeInsets.all(0),
|
||||
child: contact.isInvitation == true
|
||||
|
@ -124,7 +156,7 @@ class _ContactRowState extends State<ContactRow> {
|
|||
icon: Icon(Icons.block, color: Provider.of<Settings>(context).theme.mainTextColor),
|
||||
onPressed: () {},
|
||||
)
|
||||
: Text(dateToNiceString(contact.lastMessageTime))),
|
||||
: Text(dateToNiceString(widget.messageIndex == null ? contact.lastMessageTime : (this.cachedMessage?.getMetadata().timestamp ?? DateTime.now())))),
|
||||
),
|
||||
],
|
||||
))),
|
||||
|
@ -149,7 +181,7 @@ class _ContactRowState extends State<ContactRow> {
|
|||
])),
|
||||
onTap: () {
|
||||
setState(() {
|
||||
selectConversation(context, contact.identifier);
|
||||
selectConversation(context, contact.identifier, widget.messageIndex);
|
||||
});
|
||||
},
|
||||
onHover: (hover) {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:cwtch/themes/opaque.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../settings.dart';
|
||||
|
@ -18,7 +19,7 @@ class _CwtchLabelState extends State<CwtchLabel> {
|
|||
return Consumer<Settings>(builder: (context, theme, child) {
|
||||
return Text(
|
||||
widget.label,
|
||||
style: TextStyle(fontSize: 20, color: theme.current().mainTextColor),
|
||||
style: Provider.of<Settings>(context).scaleFonts(defaultFormLabelTextStyle),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -7,7 +7,9 @@ import 'package:cwtch/models/contact.dart';
|
|||
import 'package:cwtch/models/filedownloadprogress.dart';
|
||||
import 'package:cwtch/models/message.dart';
|
||||
import 'package:cwtch/models/profile.dart';
|
||||
import 'package:cwtch/themes/opaque.dart';
|
||||
import 'package:cwtch/widgets/malformedbubble.dart';
|
||||
import 'package:cwtch/widgets/messageBubbleWidgetHelpers.dart';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
@ -147,18 +149,10 @@ class FileBubbleState extends State<FileBubble> {
|
|||
var wdgSender = Visibility(
|
||||
visible: widget.interactive,
|
||||
child: Container(
|
||||
height: 14 * Provider.of<Settings>(context).fontScaling,
|
||||
clipBehavior: Clip.hardEdge,
|
||||
decoration: BoxDecoration(),
|
||||
child: SelectableText(senderDisplayStr + '\u202F',
|
||||
style: TextStyle(
|
||||
fontSize: 9.0 * Provider.of<Settings>(context).fontScaling,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontFamily: "Inter",
|
||||
color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor : Provider.of<Settings>(context).theme.messageFromOtherTextColor))));
|
||||
height: 14 * Provider.of<Settings>(context).fontScaling, clipBehavior: Clip.hardEdge, decoration: BoxDecoration(), child: compileSenderWidget(context, fromMe, senderDisplayStr)));
|
||||
var isPreview = false;
|
||||
var wdgMessage = !showFileSharing
|
||||
? Text(AppLocalizations.of(context)!.messageEnableFileSharing)
|
||||
? Text(AppLocalizations.of(context)!.messageEnableFileSharing, style: Provider.of<Settings>(context).scaleFonts(defaultTextStyle))
|
||||
: fromMe
|
||||
? senderFileChrome(AppLocalizations.of(context)!.messageFileSent, widget.nameSuggestion, widget.rootHash, widget.fileSize)
|
||||
: (fileChrome(AppLocalizations.of(context)!.messageFileOffered + ":", widget.nameSuggestion, widget.rootHash, widget.fileSize,
|
||||
|
@ -182,11 +176,13 @@ class FileBubbleState extends State<FileBubble> {
|
|||
},
|
||||
)));
|
||||
} else {
|
||||
wdgDecorations = Visibility(visible: widget.interactive, child: Text(AppLocalizations.of(context)!.fileSavedTo + ': ' + path + '\u202F'));
|
||||
wdgDecorations = Visibility(
|
||||
visible: widget.interactive, child: Text(AppLocalizations.of(context)!.fileSavedTo + ': ' + path + '\u202F', style: Provider.of<Settings>(context).scaleFonts(defaultTextStyle)));
|
||||
}
|
||||
} else if (downloadActive) {
|
||||
if (!downloadGotManifest) {
|
||||
wdgDecorations = Visibility(visible: widget.interactive, child: Text(AppLocalizations.of(context)!.retrievingManifestMessage + '\u202F'));
|
||||
wdgDecorations = Visibility(
|
||||
visible: widget.interactive, child: Text(AppLocalizations.of(context)!.retrievingManifestMessage + '\u202F', style: Provider.of<Settings>(context).scaleFonts(defaultTextStyle)));
|
||||
} else {
|
||||
wdgDecorations = Visibility(
|
||||
visible: widget.interactive,
|
||||
|
@ -199,19 +195,19 @@ class FileBubbleState extends State<FileBubble> {
|
|||
// in this case, the download was done in a previous application launch,
|
||||
// so we probably have to request an info lookup
|
||||
if (!downloadInterrupted) {
|
||||
wdgDecorations = Text(AppLocalizations.of(context)!.fileCheckingStatus + '...' + '\u202F');
|
||||
wdgDecorations = Text(AppLocalizations.of(context)!.fileCheckingStatus + '...' + '\u202F', style: Provider.of<Settings>(context).scaleFonts(defaultTextStyle));
|
||||
// We should have already requested this...
|
||||
} else {
|
||||
var path = Provider.of<ProfileInfoState>(context).downloadFinalPath(widget.fileKey()) ?? "";
|
||||
wdgDecorations = Visibility(
|
||||
visible: widget.interactive,
|
||||
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
Text(AppLocalizations.of(context)!.fileInterrupted + ': ' + path + '\u202F'),
|
||||
ElevatedButton(onPressed: _btnResume, child: Text(AppLocalizations.of(context)!.verfiyResumeButton))
|
||||
Text(AppLocalizations.of(context)!.fileInterrupted + ': ' + path + '\u202F', style: Provider.of<Settings>(context).scaleFonts(defaultTextStyle)),
|
||||
ElevatedButton(onPressed: _btnResume, child: Text(AppLocalizations.of(context)!.verfiyResumeButton, style: Provider.of<Settings>(context).scaleFonts(defaultTextButtonStyle)))
|
||||
]));
|
||||
}
|
||||
} else if (!senderIsContact) {
|
||||
wdgDecorations = Text(AppLocalizations.of(context)!.msgAddToAccept);
|
||||
wdgDecorations = Text(AppLocalizations.of(context)!.msgAddToAccept, style: Provider.of<Settings>(context).scaleFonts(defaultTextStyle));
|
||||
} else if (!widget.isAuto || Provider.of<MessageMetadata>(context).attributes["file-missing"] == "false") {
|
||||
//Note: we need this second case to account for scenarios where a user deletes the downloaded file, we won't automatically
|
||||
// fetch it again, so we need to offer the user the ability to restart..
|
||||
|
@ -220,7 +216,10 @@ class FileBubbleState extends State<FileBubble> {
|
|||
child: Center(
|
||||
widthFactor: 1,
|
||||
child: Wrap(children: [
|
||||
Padding(padding: EdgeInsets.all(5), child: ElevatedButton(child: Text(AppLocalizations.of(context)!.downloadFileButton + '\u202F'), onPressed: _btnAccept)),
|
||||
Padding(
|
||||
padding: EdgeInsets.all(5),
|
||||
child: ElevatedButton(
|
||||
child: Text(AppLocalizations.of(context)!.downloadFileButton + '\u202F', style: Provider.of<Settings>(context).scaleFonts(defaultTextButtonStyle)), onPressed: _btnAccept)),
|
||||
])));
|
||||
} else {
|
||||
wdgDecorations = Container();
|
||||
|
@ -278,7 +277,7 @@ class FileBubbleState extends State<FileBubble> {
|
|||
}
|
||||
} else {
|
||||
try {
|
||||
selectedFileName = await FilePicker.platform.saveFile(
|
||||
selectedFileName = await FilePicker.platform.saveFile(
|
||||
fileName: widget.nameSuggestion,
|
||||
lockParentWindow: true,
|
||||
);
|
||||
|
@ -308,52 +307,35 @@ class FileBubbleState extends State<FileBubble> {
|
|||
|
||||
// Construct an file chrome for the sender
|
||||
Widget senderFileChrome(String chrome, String fileName, String rootHash, int fileSize) {
|
||||
var settings = Provider.of<Settings>(context);
|
||||
return ListTile(
|
||||
visualDensity: VisualDensity.compact,
|
||||
title: Wrap(direction: Axis.horizontal, alignment: WrapAlignment.start, children: [
|
||||
SelectableText(
|
||||
chrome + '\u202F',
|
||||
style: TextStyle(
|
||||
color: Provider.of<Settings>(context).theme.messageFromMeTextColor,
|
||||
fontWeight: FontWeight.normal,
|
||||
fontFamily: "Inter",
|
||||
fontSize: 12 * Provider.of<Settings>(context).fontScaling,
|
||||
),
|
||||
style: settings.scaleFonts(defaultMessageTextStyle.copyWith(color: Provider.of<Settings>(context).theme.messageFromMeTextColor)),
|
||||
textAlign: TextAlign.left,
|
||||
maxLines: 2,
|
||||
textWidthBasis: TextWidthBasis.longestLine,
|
||||
),
|
||||
SelectableText(
|
||||
fileName + '\u202F',
|
||||
style: TextStyle(
|
||||
color: Provider.of<Settings>(context).theme.messageFromMeTextColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
fontFamily: "Inter",
|
||||
fontSize: 12 * Provider.of<Settings>(context).fontScaling,
|
||||
),
|
||||
style:
|
||||
settings.scaleFonts(defaultMessageTextStyle.copyWith(overflow: TextOverflow.ellipsis, fontWeight: FontWeight.bold, color: Provider.of<Settings>(context).theme.messageFromMeTextColor)),
|
||||
textAlign: TextAlign.left,
|
||||
textWidthBasis: TextWidthBasis.parent,
|
||||
maxLines: 2,
|
||||
),
|
||||
SelectableText(
|
||||
prettyBytes(fileSize) + '\u202F' + '\n',
|
||||
style: TextStyle(
|
||||
color: Provider.of<Settings>(context).theme.messageFromMeTextColor,
|
||||
fontSize: 10 * Provider.of<Settings>(context).fontScaling,
|
||||
fontFamily: "Inter",
|
||||
),
|
||||
style: settings.scaleFonts(defaultSmallTextStyle.copyWith(color: Provider.of<Settings>(context).theme.messageFromMeTextColor)),
|
||||
textAlign: TextAlign.left,
|
||||
maxLines: 2,
|
||||
)
|
||||
]),
|
||||
subtitle: SelectableText(
|
||||
'sha512: ' + rootHash + '\u202F',
|
||||
style: TextStyle(
|
||||
color: Provider.of<Settings>(context).theme.messageFromMeTextColor,
|
||||
fontSize: 10 * Provider.of<Settings>(context).fontScaling,
|
||||
fontFamily: "RobotoMono",
|
||||
),
|
||||
style: settings.scaleFonts(defaultSmallTextStyle.copyWith(fontFamily: "RobotoMono", color: Provider.of<Settings>(context).theme.messageFromMeTextColor)),
|
||||
textAlign: TextAlign.left,
|
||||
maxLines: 4,
|
||||
textWidthBasis: TextWidthBasis.parent,
|
||||
|
@ -363,50 +345,35 @@ class FileBubbleState extends State<FileBubble> {
|
|||
|
||||
// Construct an file chrome
|
||||
Widget fileChrome(String chrome, String fileName, String rootHash, int fileSize, String speed) {
|
||||
var settings = Provider.of<Settings>(context);
|
||||
return ListTile(
|
||||
visualDensity: VisualDensity.compact,
|
||||
title: Wrap(direction: Axis.horizontal, alignment: WrapAlignment.start, children: [
|
||||
SelectableText(
|
||||
chrome + '\u202F',
|
||||
style: TextStyle(
|
||||
color: Provider.of<Settings>(context).theme.messageFromOtherTextColor,
|
||||
fontSize: 12 * Provider.of<Settings>(context).fontScaling,
|
||||
fontFamily: "Inter",
|
||||
),
|
||||
style: settings.scaleFonts(defaultMessageTextStyle.copyWith(color: Provider.of<Settings>(context).theme.messageFromOtherTextColor)),
|
||||
textAlign: TextAlign.left,
|
||||
maxLines: 2,
|
||||
textWidthBasis: TextWidthBasis.longestLine,
|
||||
),
|
||||
SelectableText(
|
||||
fileName + '\u202F',
|
||||
style: TextStyle(
|
||||
color: Provider.of<Settings>(context).theme.messageFromOtherTextColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
fontFamily: "Inter",
|
||||
),
|
||||
style: settings
|
||||
.scaleFonts(defaultMessageTextStyle.copyWith(overflow: TextOverflow.ellipsis, fontWeight: FontWeight.bold, color: Provider.of<Settings>(context).theme.messageFromOtherTextColor)),
|
||||
textAlign: TextAlign.left,
|
||||
textWidthBasis: TextWidthBasis.parent,
|
||||
maxLines: 2,
|
||||
),
|
||||
SelectableText(
|
||||
AppLocalizations.of(context)!.labelFilesize + ': ' + prettyBytes(fileSize) + '\u202F' + '\n',
|
||||
style: TextStyle(
|
||||
color: Provider.of<Settings>(context).theme.messageFromOtherTextColor,
|
||||
fontFamily: "Inter",
|
||||
fontSize: 10 * Provider.of<Settings>(context).fontScaling,
|
||||
),
|
||||
style: settings.scaleFonts(defaultSmallTextStyle.copyWith(color: Provider.of<Settings>(context).theme.messageFromOtherTextColor)),
|
||||
textAlign: TextAlign.left,
|
||||
maxLines: 2,
|
||||
)
|
||||
]),
|
||||
subtitle: SelectableText(
|
||||
'sha512: ' + rootHash + '\u202F',
|
||||
style: TextStyle(
|
||||
color: Provider.of<Settings>(context).theme.messageFromMeTextColor,
|
||||
fontSize: 10 * Provider.of<Settings>(context).fontScaling,
|
||||
fontFamily: "RobotoMono",
|
||||
),
|
||||
style: settings.scaleFonts(defaultSmallTextStyle.copyWith(fontFamily: "RobotoMono", color: Provider.of<Settings>(context).theme.messageFromOtherTextColor)),
|
||||
textAlign: TextAlign.left,
|
||||
maxLines: 4,
|
||||
textWidthBasis: TextWidthBasis.parent,
|
||||
|
@ -416,11 +383,7 @@ class FileBubbleState extends State<FileBubble> {
|
|||
visible: speed != "0 B/s",
|
||||
child: SelectableText(
|
||||
speed + '\u202F',
|
||||
style: TextStyle(
|
||||
color: Provider.of<Settings>(context).theme.messageFromMeTextColor,
|
||||
fontFamily: "Inter",
|
||||
fontSize: 10 * Provider.of<Settings>(context).fontScaling,
|
||||
),
|
||||
style: settings.scaleFonts(defaultSmallTextStyle.copyWith(color: Provider.of<Settings>(context).theme.messageFromOtherTextColor)),
|
||||
textAlign: TextAlign.left,
|
||||
maxLines: 1,
|
||||
textWidthBasis: TextWidthBasis.longestLine,
|
||||
|
@ -467,7 +430,7 @@ class FileBubbleState extends State<FileBubble> {
|
|||
icon: Icon(Icons.arrow_downward),
|
||||
onPressed: androidExport,
|
||||
label: Text(
|
||||
AppLocalizations.of(context)!.saveBtn,
|
||||
AppLocalizations.of(bcontext)!.saveBtn,
|
||||
)))),
|
||||
]),
|
||||
))));
|
||||
|
|
|
@ -14,7 +14,8 @@ class CwtchFolderPicker extends StatefulWidget {
|
|||
final String description;
|
||||
final Function(String)? onSave;
|
||||
final Key? testKey;
|
||||
const CwtchFolderPicker({Key? key, this.testKey, this.label = "", this.tooltip = "", this.initialValue = "", this.onSave, this.description = ""}) : super(key: key);
|
||||
final TextStyle? textStyle;
|
||||
const CwtchFolderPicker({Key? key, this.testKey, this.textStyle, this.label = "", this.tooltip = "", this.initialValue = "", this.onSave, this.description = ""}) : super(key: key);
|
||||
|
||||
@override
|
||||
_CwtchFolderPickerState createState() => _CwtchFolderPickerState();
|
||||
|
@ -40,6 +41,7 @@ class _CwtchFolderPickerState extends State<CwtchFolderPicker> {
|
|||
child: CwtchButtonTextField(
|
||||
testKey: widget.testKey,
|
||||
controller: ctrlrVal,
|
||||
textStyle: widget.textStyle,
|
||||
readonly: Platform.isAndroid,
|
||||
onPressed: Provider.of<AppState>(context).disableFilePicker
|
||||
? null
|
||||
|
|
|
@ -5,6 +5,7 @@ import 'package:cwtch/cwtch_icons_icons.dart';
|
|||
import 'package:cwtch/models/contact.dart';
|
||||
import 'package:cwtch/models/message.dart';
|
||||
import 'package:cwtch/models/profile.dart';
|
||||
import 'package:cwtch/themes/opaque.dart';
|
||||
import 'package:cwtch/widgets/malformedbubble.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
@ -13,6 +14,7 @@ import 'package:intl/intl.dart';
|
|||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
|
||||
import '../settings.dart';
|
||||
import 'messageBubbleWidgetHelpers.dart';
|
||||
import 'messagebubbledecorations.dart';
|
||||
|
||||
// Like MessageBubble but for displaying chat overlay 100/101 invitations
|
||||
|
@ -54,15 +56,7 @@ class InvitationBubbleState extends State<InvitationBubble> {
|
|||
}
|
||||
}
|
||||
|
||||
var wdgSender = Center(
|
||||
widthFactor: 1,
|
||||
child: SelectableText(senderDisplayStr + '\u202F',
|
||||
style: TextStyle(
|
||||
fontSize: 9.0 * Provider.of<Settings>(context).fontScaling,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontFamily: "Inter",
|
||||
color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor : Provider.of<Settings>(context).theme.messageFromOtherTextColor)));
|
||||
|
||||
var wdgSender = compileSenderWidget(context, fromMe, senderDisplayStr);
|
||||
// If we receive an invite for ourselves, treat it as a bug. The UI no longer allows this so it could have only come from
|
||||
// some kind of malfeasance.
|
||||
var selfInvite = widget.inviteNick == Provider.of<ProfileInfoState>(context).onion;
|
||||
|
@ -71,7 +65,7 @@ class InvitationBubbleState extends State<InvitationBubble> {
|
|||
}
|
||||
|
||||
var wdgMessage = isGroup && !showGroupInvite
|
||||
? Text(AppLocalizations.of(context)!.groupInviteSettingsWarning)
|
||||
? Text(AppLocalizations.of(context)!.groupInviteSettingsWarning, style: Provider.of<Settings>(context).scaleFonts(defaultTextStyle))
|
||||
: fromMe
|
||||
? senderInviteChrome(
|
||||
AppLocalizations.of(context)!.sendAnInvitation, isGroup ? Provider.of<ProfileInfoState>(context).contactList.findContact(widget.inviteTarget)!.nickname : widget.inviteTarget)
|
||||
|
@ -83,15 +77,21 @@ class InvitationBubbleState extends State<InvitationBubble> {
|
|||
} else if (fromMe) {
|
||||
wdgDecorations = MessageBubbleDecoration(ackd: Provider.of<MessageMetadata>(context).ackd, errored: Provider.of<MessageMetadata>(context).error, fromMe: fromMe, messageDate: messageDate);
|
||||
} else if (isAccepted) {
|
||||
wdgDecorations = Text(AppLocalizations.of(context)!.accepted + '\u202F');
|
||||
wdgDecorations = Text(AppLocalizations.of(context)!.accepted + '\u202F', style: Provider.of<Settings>(context).scaleFonts(defaultTextStyle));
|
||||
} else if (this.rejected) {
|
||||
wdgDecorations = Text(AppLocalizations.of(context)!.rejected + '\u202F');
|
||||
wdgDecorations = Text(AppLocalizations.of(context)!.rejected + '\u202F', style: Provider.of<Settings>(context).scaleFonts(defaultTextStyle));
|
||||
} else {
|
||||
wdgDecorations = Center(
|
||||
widthFactor: 1,
|
||||
child: Wrap(children: [
|
||||
Padding(padding: EdgeInsets.all(5), child: ElevatedButton(child: Text(AppLocalizations.of(context)!.rejectGroupBtn + '\u202F'), onPressed: _btnReject)),
|
||||
Padding(padding: EdgeInsets.all(5), child: ElevatedButton(child: Text(AppLocalizations.of(context)!.acceptGroupBtn + '\u202F'), onPressed: _btnAccept)),
|
||||
Padding(
|
||||
padding: EdgeInsets.all(5),
|
||||
child: ElevatedButton(
|
||||
child: Text(AppLocalizations.of(context)!.rejectGroupBtn + '\u202F', style: Provider.of<Settings>(context).scaleFonts(defaultTextButtonStyle)), onPressed: _btnReject)),
|
||||
Padding(
|
||||
padding: EdgeInsets.all(5),
|
||||
child: ElevatedButton(
|
||||
child: Text(AppLocalizations.of(context)!.acceptGroupBtn + '\u202F', style: Provider.of<Settings>(context).scaleFonts(defaultTextButtonStyle)), onPressed: _btnAccept)),
|
||||
]));
|
||||
}
|
||||
|
||||
|
@ -149,21 +149,19 @@ class InvitationBubbleState extends State<InvitationBubble> {
|
|||
|
||||
// Construct an invite chrome for the sender
|
||||
Widget senderInviteChrome(String chrome, String targetName) {
|
||||
var settings = Provider.of<Settings>(context);
|
||||
|
||||
return Wrap(children: [
|
||||
SelectableText(
|
||||
chrome + '\u202F',
|
||||
style: TextStyle(
|
||||
color: Provider.of<Settings>(context).theme.messageFromMeTextColor,
|
||||
),
|
||||
style: settings.scaleFonts(defaultMessageTextStyle.copyWith(color: Provider.of<Settings>(context).theme.messageFromMeTextColor)),
|
||||
textAlign: TextAlign.left,
|
||||
maxLines: 2,
|
||||
textWidthBasis: TextWidthBasis.longestLine,
|
||||
),
|
||||
SelectableText(
|
||||
targetName + '\u202F',
|
||||
style: TextStyle(
|
||||
color: Provider.of<Settings>(context).theme.messageFromMeTextColor,
|
||||
),
|
||||
style: settings.scaleFonts(defaultMessageTextStyle.copyWith(color: Provider.of<Settings>(context).theme.messageFromMeTextColor)),
|
||||
textAlign: TextAlign.left,
|
||||
maxLines: 2,
|
||||
textWidthBasis: TextWidthBasis.longestLine,
|
||||
|
@ -173,19 +171,19 @@ class InvitationBubbleState extends State<InvitationBubble> {
|
|||
|
||||
// Construct an invite chrome
|
||||
Widget inviteChrome(String chrome, String targetName, String targetId) {
|
||||
var settings = Provider.of<Settings>(context);
|
||||
|
||||
return Wrap(children: [
|
||||
SelectableText(
|
||||
chrome + '\u202F',
|
||||
style: TextStyle(
|
||||
color: Provider.of<Settings>(context).theme.messageFromOtherTextColor,
|
||||
),
|
||||
style: settings.scaleFonts(defaultMessageTextStyle.copyWith(color: Provider.of<Settings>(context).theme.messageFromOtherTextColor)),
|
||||
textAlign: TextAlign.left,
|
||||
textWidthBasis: TextWidthBasis.longestLine,
|
||||
maxLines: 2,
|
||||
),
|
||||
SelectableText(
|
||||
targetName + '\u202F',
|
||||
style: TextStyle(color: Provider.of<Settings>(context).theme.messageFromOtherTextColor),
|
||||
style: settings.scaleFonts(defaultMessageTextStyle.copyWith(color: Provider.of<Settings>(context).theme.messageFromOtherTextColor)),
|
||||
textAlign: TextAlign.left,
|
||||
maxLines: 2,
|
||||
textWidthBasis: TextWidthBasis.longestLine,
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../controllers/open_link_modal.dart';
|
||||
import '../settings.dart';
|
||||
import '../themes/opaque.dart';
|
||||
import '../third_party/linkify/flutter_linkify.dart';
|
||||
|
||||
Widget compileSenderWidget(BuildContext context, bool fromMe, String senderDisplayStr) {
|
||||
return Container(
|
||||
height: 14 * Provider.of<Settings>(context).fontScaling,
|
||||
clipBehavior: Clip.hardEdge,
|
||||
decoration: BoxDecoration(),
|
||||
child: SelectableText(senderDisplayStr,
|
||||
maxLines: 1,
|
||||
style: TextStyle(
|
||||
fontSize: 9.0 * Provider.of<Settings>(context).fontScaling,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontFamily: "Inter",
|
||||
overflow: TextOverflow.clip,
|
||||
color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor : Provider.of<Settings>(context).theme.messageFromOtherTextColor,
|
||||
)));
|
||||
}
|
||||
|
||||
Widget compileMessageContentWidget(BuildContext context, bool fromMe, String content, FocusNode focus, bool formatMessages, bool showClickableLinks) {
|
||||
return SelectableLinkify(
|
||||
text: content + '\u202F',
|
||||
// TODO: onOpen breaks the "selectable" functionality. Maybe something to do with gesture handler?
|
||||
options: LinkifyOptions(messageFormatting: formatMessages, parseLinks: showClickableLinks, looseUrl: true, defaultToHttps: true),
|
||||
linkifiers: [UrlLinkifier()],
|
||||
onOpen: showClickableLinks
|
||||
? (link) {
|
||||
modalOpenLink(context, link);
|
||||
}
|
||||
: null,
|
||||
//key: Key(myKey),
|
||||
focusNode: focus,
|
||||
style: Provider.of<Settings>(context)
|
||||
.scaleFonts(defaultMessageTextStyle.copyWith(color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor : Provider.of<Settings>(context).theme.messageFromOtherTextColor)),
|
||||
linkStyle: Provider.of<Settings>(context)
|
||||
.scaleFonts(defaultMessageTextStyle.copyWith(color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor : Provider.of<Settings>(context).theme.messageFromOtherTextColor)),
|
||||
codeStyle: Provider.of<Settings>(context).scaleFonts(defaultMessageTextStyle.copyWith(
|
||||
fontFamily: "RobotoMono",
|
||||
color: fromMe ? Provider.of<Settings>(context).theme.messageFromOtherTextColor : Provider.of<Settings>(context).theme.messageFromMeTextColor,
|
||||
backgroundColor: fromMe ? Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor : Provider.of<Settings>(context).theme.messageFromMeBackgroundColor)),
|
||||
textAlign: TextAlign.left,
|
||||
textWidthBasis: TextWidthBasis.longestLine,
|
||||
);
|
||||
}
|
|
@ -3,6 +3,7 @@ import 'dart:io';
|
|||
import 'package:cwtch/controllers/open_link_modal.dart';
|
||||
import 'package:cwtch/models/contact.dart';
|
||||
import 'package:cwtch/models/message.dart';
|
||||
import 'package:cwtch/themes/opaque.dart';
|
||||
import 'package:cwtch/third_party/linkify/flutter_linkify.dart';
|
||||
import 'package:cwtch/models/profile.dart';
|
||||
import 'package:cwtch/widgets/malformedbubble.dart';
|
||||
|
@ -10,6 +11,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../settings.dart';
|
||||
import 'messageBubbleWidgetHelpers.dart';
|
||||
import 'messagebubbledecorations.dart';
|
||||
|
||||
class MessageBubble extends StatefulWidget {
|
||||
|
@ -42,56 +44,9 @@ class MessageBubbleState extends State<MessageBubble> {
|
|||
senderDisplayStr = Provider.of<MessageMetadata>(context).senderHandle;
|
||||
}
|
||||
}
|
||||
var wdgSender = Container(
|
||||
height: 14 * Provider.of<Settings>(context).fontScaling,
|
||||
clipBehavior: Clip.hardEdge,
|
||||
decoration: BoxDecoration(),
|
||||
child: SelectableText(senderDisplayStr,
|
||||
maxLines: 1,
|
||||
style: TextStyle(
|
||||
fontSize: 9.0 * Provider.of<Settings>(context).fontScaling,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontFamily: "Inter",
|
||||
overflow: TextOverflow.clip,
|
||||
color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor : Provider.of<Settings>(context).theme.messageFromOtherTextColor,
|
||||
)));
|
||||
|
||||
var wdgMessage = SelectableLinkify(
|
||||
text: widget.content + '\u202F',
|
||||
// TODO: onOpen breaks the "selectable" functionality. Maybe something to do with gesture handler?
|
||||
options: LinkifyOptions(messageFormatting: formatMessages, parseLinks: showClickableLinks, looseUrl: true, defaultToHttps: true),
|
||||
linkifiers: [UrlLinkifier()],
|
||||
onOpen: showClickableLinks
|
||||
? (link) {
|
||||
modalOpenLink(context, link);
|
||||
}
|
||||
: null,
|
||||
//key: Key(myKey),
|
||||
focusNode: _focus,
|
||||
style: TextStyle(
|
||||
fontSize: 12.0 * Provider.of<Settings>(context).fontScaling,
|
||||
fontWeight: FontWeight.normal,
|
||||
fontFamily: "Inter",
|
||||
color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor : Provider.of<Settings>(context).theme.messageFromOtherTextColor,
|
||||
),
|
||||
linkStyle: TextStyle(
|
||||
fontSize: 12.0 * Provider.of<Settings>(context).fontScaling,
|
||||
fontWeight: FontWeight.normal,
|
||||
fontFamily: "Inter",
|
||||
color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor : Provider.of<Settings>(context).theme.messageFromOtherTextColor),
|
||||
codeStyle: TextStyle(
|
||||
fontSize: 12.0 * Provider.of<Settings>(context).fontScaling,
|
||||
fontWeight: FontWeight.normal,
|
||||
fontFamily: "Inter",
|
||||
// note: these colors are flipped
|
||||
color: fromMe ? Provider.of<Settings>(context).theme.messageFromOtherTextColor : Provider.of<Settings>(context).theme.messageFromMeTextColor,
|
||||
backgroundColor: fromMe ? Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor : Provider.of<Settings>(context).theme.messageFromMeBackgroundColor),
|
||||
textAlign: TextAlign.left,
|
||||
textWidthBasis: TextWidthBasis.longestLine,
|
||||
);
|
||||
|
||||
var wdgSender = compileSenderWidget(context, fromMe, senderDisplayStr);
|
||||
var wdgMessage = compileMessageContentWidget(context, fromMe, widget.content, _focus, formatMessages, showClickableLinks);
|
||||
var wdgDecorations = MessageBubbleDecoration(ackd: Provider.of<MessageMetadata>(context).ackd, errored: Provider.of<MessageMetadata>(context).error, fromMe: fromMe, messageDate: messageDate);
|
||||
|
||||
var error = Provider.of<MessageMetadata>(context).error;
|
||||
|
||||
return LayoutBuilder(builder: (context, constraints) {
|
||||
|
|
|
@ -38,7 +38,8 @@ class _MessageListState extends State<MessageList> {
|
|||
//bool isGroupAndSynced = Provider.of<ContactInfoState>(context).isGroup && Provider.of<ContactInfoState>(context).status == "Synced";
|
||||
//bool isGroupAndNotAuthenticated = Provider.of<ContactInfoState>(context).isGroup && Provider.of<ContactInfoState>(context).status != "Authenticated";
|
||||
|
||||
bool showEphemeralWarning = (isP2P && Provider.of<ContactInfoState>(context).savePeerHistory != "SaveHistory");
|
||||
bool preserveHistoryByDefault = Provider.of<Settings>(context, listen:false).preserveHistoryByDefault;
|
||||
bool showEphemeralWarning = (isP2P && (!preserveHistoryByDefault && Provider.of<ContactInfoState>(context).savePeerHistory != "SaveHistory"));
|
||||
bool showOfflineWarning = Provider.of<ContactInfoState>(context).isOnline() == false;
|
||||
bool showSyncing = isGroupAndSyncing;
|
||||
bool showMessageWarning = showEphemeralWarning || showOfflineWarning || showSyncing;
|
||||
|
|
|
@ -7,6 +7,7 @@ import 'package:cwtch/models/appstate.dart';
|
|||
import 'package:cwtch/models/contact.dart';
|
||||
import 'package:cwtch/models/message.dart';
|
||||
import 'package:cwtch/models/profile.dart';
|
||||
import 'package:cwtch/themes/opaque.dart';
|
||||
import 'package:cwtch/third_party/base32/base32.dart';
|
||||
import 'package:cwtch/views/contactsview.dart';
|
||||
import 'package:cwtch/widgets/staticmessagebubble.dart';
|
||||
|
@ -149,8 +150,8 @@ class MessageRowState extends State<MessageRow> with SingleTickerProviderStateMi
|
|||
if (fromMe) {
|
||||
widgetRow = <Widget>[
|
||||
wdgSpacer,
|
||||
wdgSeeReplies,
|
||||
wdgTranslateMessage,
|
||||
wdgSeeReplies,
|
||||
wdgReply,
|
||||
actualMessage,
|
||||
];
|
||||
|
@ -289,7 +290,9 @@ class MessageRowState extends State<MessageRow> with SingleTickerProviderStateMi
|
|||
)))));
|
||||
|
||||
if (Provider.of<ContactInfoState>(context).newMarkerMsgIndex == widget.index) {
|
||||
return Column(crossAxisAlignment: fromMe ? CrossAxisAlignment.end : CrossAxisAlignment.start, children: [Align(alignment: Alignment.center, child: _bubbleNew()), mr]);
|
||||
return Column(
|
||||
crossAxisAlignment: fromMe ? CrossAxisAlignment.end : CrossAxisAlignment.start,
|
||||
children: [Align(alignment: Alignment.center, child: Padding(padding: EdgeInsets.all(5.0), child: _bubbleNew())), mr]);
|
||||
} else {
|
||||
return mr;
|
||||
}
|
||||
|
@ -307,7 +310,7 @@ class MessageRowState extends State<MessageRow> with SingleTickerProviderStateMi
|
|||
bottomRight: Radius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Padding(padding: EdgeInsets.all(9.0), child: Text(AppLocalizations.of(context)!.newMessagesLabel)));
|
||||
child: Padding(padding: EdgeInsets.all(9.0), child: Text(AppLocalizations.of(context)!.newMessagesLabel, style: Provider.of<Settings>(context).scaleFonts(defaultTextButtonStyle))));
|
||||
}
|
||||
|
||||
void _runAnimation(Offset pixelsPerSecond, Size size) {
|
||||
|
@ -339,7 +342,7 @@ class MessageRowState extends State<MessageRow> with SingleTickerProviderStateMi
|
|||
if (id == null) {
|
||||
// Can't happen
|
||||
} else {
|
||||
selectConversation(context, id);
|
||||
selectConversation(context, id, null);
|
||||
var contactIndex = Provider.of<ProfileInfoState>(context, listen: false).contactList.filteredList().indexWhere((element) => element.identifier == id);
|
||||
Provider.of<ProfileInfoState>(context, listen: false).contactListScrollController.jumpTo(index: contactIndex);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:provider/provider.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import '../settings.dart';
|
||||
import 'messageBubbleWidgetHelpers.dart';
|
||||
import 'messagebubbledecorations.dart';
|
||||
|
||||
class QuotedMessageBubble extends StatefulWidget {
|
||||
|
@ -43,53 +44,11 @@ class QuotedMessageBubbleState extends State<QuotedMessageBubble> {
|
|||
}
|
||||
}
|
||||
|
||||
var wdgSender = Container(
|
||||
height: 14 * Provider.of<Settings>(context).fontScaling,
|
||||
clipBehavior: Clip.hardEdge,
|
||||
decoration: BoxDecoration(),
|
||||
child: SelectableText(senderDisplayStr,
|
||||
style: TextStyle(
|
||||
fontSize: 9.0 * Provider.of<Settings>(context).fontScaling,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontFamily: "Inter",
|
||||
color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor : Provider.of<Settings>(context).theme.messageFromOtherTextColor)));
|
||||
var wdgSender = compileSenderWidget(context, fromMe, senderDisplayStr);
|
||||
|
||||
var showClickableLinks = Provider.of<Settings>(context).isExperimentEnabled(ClickableLinksExperiment);
|
||||
var formatMessages = Provider.of<Settings>(context).isExperimentEnabled(FormattingExperiment);
|
||||
|
||||
var wdgMessage = SelectableLinkify(
|
||||
text: widget.body + '\u202F',
|
||||
// TODO: onOpen breaks the "selectable" functionality. Maybe something to do with gesture handler?
|
||||
options: LinkifyOptions(messageFormatting: formatMessages, parseLinks: showClickableLinks, looseUrl: true, defaultToHttps: true),
|
||||
linkifiers: [UrlLinkifier()],
|
||||
onOpen: showClickableLinks
|
||||
? (link) {
|
||||
modalOpenLink(context, link);
|
||||
}
|
||||
: null,
|
||||
//key: Key(myKey),
|
||||
focusNode: _focus,
|
||||
style: TextStyle(
|
||||
fontSize: 12.0 * Provider.of<Settings>(context).fontScaling,
|
||||
fontWeight: FontWeight.normal,
|
||||
fontFamily: "Inter",
|
||||
color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor : Provider.of<Settings>(context).theme.messageFromOtherTextColor,
|
||||
),
|
||||
linkStyle: TextStyle(
|
||||
fontSize: 12.0 * Provider.of<Settings>(context).fontScaling,
|
||||
fontWeight: FontWeight.normal,
|
||||
fontFamily: "Inter",
|
||||
color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor : Provider.of<Settings>(context).theme.messageFromOtherTextColor),
|
||||
codeStyle: TextStyle(
|
||||
fontSize: 12.0 * Provider.of<Settings>(context).fontScaling,
|
||||
fontWeight: FontWeight.normal,
|
||||
fontFamily: "RobotoMono",
|
||||
// note: these colors are flipped
|
||||
color: fromMe ? Provider.of<Settings>(context).theme.messageFromOtherTextColor : Provider.of<Settings>(context).theme.messageFromMeTextColor,
|
||||
backgroundColor: fromMe ? Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor : Provider.of<Settings>(context).theme.messageFromMeBackgroundColor),
|
||||
textAlign: TextAlign.left,
|
||||
textWidthBasis: TextWidthBasis.longestLine,
|
||||
);
|
||||
var wdgMessage = compileMessageContentWidget(context, fromMe, widget.body, _focus, formatMessages, showClickableLinks);
|
||||
|
||||
var wdgQuote = FutureBuilder(
|
||||
future: widget.quotedMessage,
|
||||
|
@ -118,7 +77,7 @@ class QuotedMessageBubbleState extends State<QuotedMessageBubble> {
|
|||
|
||||
var wdgReplyingTo = SelectableText(
|
||||
AppLocalizations.of(context)!.replyingTo.replaceAll("%1", qMessageSender),
|
||||
style: TextStyle(fontSize: 10, color: qTextColor.withOpacity(0.8)),
|
||||
style: Provider.of<Settings>(context).scaleFonts(TextStyle(fontSize: 10, color: qTextColor.withOpacity(0.8))),
|
||||
);
|
||||
// Swap the background color for quoted tweets..
|
||||
return MouseRegion(
|
||||
|
|
|
@ -3,6 +3,7 @@ import 'package:cwtch/models/profile.dart';
|
|||
import 'package:cwtch/models/profileservers.dart';
|
||||
import 'package:cwtch/models/remoteserver.dart';
|
||||
import 'package:cwtch/models/servers.dart';
|
||||
import 'package:cwtch/themes/opaque.dart';
|
||||
import 'package:cwtch/views/addeditservers.dart';
|
||||
import 'package:cwtch/views/remoteserverview.dart';
|
||||
import 'package:cwtch/widgets/profileimage.dart';
|
||||
|
@ -50,7 +51,9 @@ class _RemoteServerRowState extends State<RemoteServerRow> {
|
|||
Text(
|
||||
description,
|
||||
semanticsLabel: description,
|
||||
style: TextStyle(fontFamily: "Inter", fontSize: 10.0 * Provider.of<Settings>(context).fontScaling, fontWeight: FontWeight.bold)
|
||||
style: Provider.of<Settings>(context)
|
||||
.scaleFonts(defaultFormLabelTextStyle)
|
||||
.copyWith(fontWeight: FontWeight.bold)
|
||||
.apply(color: running ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor : Provider.of<Settings>(context).theme.portraitOfflineBorderColor),
|
||||
softWrap: true,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import 'package:cwtch/main.dart';
|
||||
import 'package:cwtch/models/servers.dart';
|
||||
import 'package:cwtch/themes/opaque.dart';
|
||||
import 'package:cwtch/views/addeditservers.dart';
|
||||
import 'package:cwtch/widgets/profileimage.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
@ -43,7 +42,8 @@ class _ServerRowState extends State<ServerRow> {
|
|||
Text(
|
||||
server.description,
|
||||
semanticsLabel: server.description,
|
||||
style: TextStyle(fontFamily: "Inter", fontSize: 10.0 * Provider.of<Settings>(context).fontScaling)
|
||||
style: Provider.of<Settings>(context)
|
||||
.scaleFonts(defaultFormLabelTextStyle)
|
||||
.apply(color: server.running ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor : Provider.of<Settings>(context).theme.portraitOfflineBorderColor),
|
||||
softWrap: true,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
|
@ -55,7 +55,9 @@ class _ServerRowState extends State<ServerRow> {
|
|||
server.onion,
|
||||
softWrap: true,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(color: server.running ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor : Provider.of<Settings>(context).theme.portraitOfflineBorderColor),
|
||||
style: Provider.of<Settings>(context)
|
||||
.scaleFonts(defaultFormLabelTextStyle)
|
||||
.copyWith(color: server.running ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor : Provider.of<Settings>(context).theme.portraitOfflineBorderColor),
|
||||
)))
|
||||
],
|
||||
)),
|
||||
|
|
|
@ -6,6 +6,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../settings.dart';
|
||||
import 'messageBubbleWidgetHelpers.dart';
|
||||
import 'messagebubbledecorations.dart';
|
||||
|
||||
class StaticMessageBubble extends StatefulWidget {
|
||||
|
@ -40,12 +41,7 @@ class StaticMessageBubbleState extends State<StaticMessageBubble> {
|
|||
senderDisplayStr = widget.profile.nickname;
|
||||
}
|
||||
|
||||
var wdgSender = SelectableText(senderDisplayStr,
|
||||
style: TextStyle(
|
||||
fontSize: 9.0 * Provider.of<Settings>(context).fontScaling,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontFamily: "Inter",
|
||||
color: fromMe ? widget.settings.theme.messageFromMeTextColor : widget.settings.theme.messageFromOtherTextColor));
|
||||
var wdgSender = compileSenderWidget(context, fromMe, senderDisplayStr);
|
||||
|
||||
var wdgDecorations = MessageBubbleDecoration(ackd: widget.metadata.ackd, errored: widget.metadata.error, fromMe: fromMe, messageDate: messageDate);
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:cwtch/themes/opaque.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
@ -64,7 +65,7 @@ class _CwtchTextFieldState extends State<CwtchTextField> {
|
|||
scrollController: _scrollController,
|
||||
enableIMEPersonalizedLearning: false,
|
||||
focusNode: _focusNode,
|
||||
style: TextStyle(overflow: TextOverflow.clip),
|
||||
style: Provider.of<Settings>(context).scaleFonts(defaultTextStyle).copyWith(overflow: TextOverflow.clip),
|
||||
decoration: InputDecoration(
|
||||
errorMaxLines: 2,
|
||||
hintText: widget.hintText,
|
||||
|
|
|
@ -1,11 +1,19 @@
|
|||
# Project-level configuration.
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
project(runner LANGUAGES CXX)
|
||||
|
||||
# The name of the executable created for the application. Change this to change
|
||||
# the on-disk name of your application.
|
||||
set(BINARY_NAME "cwtch")
|
||||
# The unique GTK application identifier for this application. See:
|
||||
# https://wiki.gnome.org/HowDoI/ChooseApplicationID
|
||||
set(APPLICATION_ID "im.cwtch.cwtch")
|
||||
|
||||
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
|
||||
# versions of CMake.
|
||||
cmake_policy(SET CMP0063 NEW)
|
||||
|
||||
# Load bundled libraries from the lib/ directory relative to the binary.
|
||||
set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
|
||||
|
||||
# Root filesystem for cross-building.
|
||||
|
@ -18,7 +26,7 @@ if(FLUTTER_TARGET_PLATFORM_SYSROOT)
|
|||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
endif()
|
||||
|
||||
# Configure build options.
|
||||
# Define build configuration options.
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
set(CMAKE_BUILD_TYPE "Debug" CACHE
|
||||
STRING "Flutter build mode" FORCE)
|
||||
|
@ -27,13 +35,20 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
|||
endif()
|
||||
|
||||
# Compilation settings that should be applied to most targets.
|
||||
#
|
||||
# Be cautious about adding new options here, as plugins use this function by
|
||||
# default. In most cases, you should add new options to specific targets instead
|
||||
# of modifying this function.
|
||||
function(APPLY_STANDARD_SETTINGS TARGET)
|
||||
target_compile_features(${TARGET} PUBLIC cxx_std_14)
|
||||
target_compile_options(${TARGET} PRIVATE -Wall -Werror)
|
||||
target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
|
||||
target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
|
||||
# -Os -fno-ident (optimize for size, and strip idents, don't generate a build-id, fix hash style)
|
||||
target_compile_options(${TARGET} PRIVATE -Wall -Werror -Os -fno-ident)
|
||||
target_link_libraries(${TARGET} PRIVATE -Qn -Os -Wl,-s,--hash-style=gnu,--build-id=none,--script=${PROJECT_BUILD_DIR}/../elf_x86_64.x)
|
||||
endfunction()
|
||||
|
||||
# Flutter library and tool build rules.
|
||||
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
|
||||
|
||||
# Flutter library and tool build rules.
|
||||
|
@ -45,16 +60,27 @@ pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
|
|||
|
||||
add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
|
||||
|
||||
# Application build
|
||||
# Define the application target. To change its name, change BINARY_NAME above,
|
||||
# not the value here, or `flutter run` will no longer work.
|
||||
#
|
||||
# Any new source files that you add to the application should be added here.
|
||||
add_executable(${BINARY_NAME}
|
||||
"main.cc"
|
||||
"my_application.cc"
|
||||
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
|
||||
)
|
||||
|
||||
# Apply the standard set of build settings. This can be removed for applications
|
||||
# that need different build settings.
|
||||
apply_standard_settings(${BINARY_NAME})
|
||||
|
||||
# Add dependency libraries. Add any application-specific dependencies here.
|
||||
target_link_libraries(${BINARY_NAME} PRIVATE flutter)
|
||||
target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
|
||||
|
||||
# Run the Flutter tool portions of the build. This must not be removed.
|
||||
add_dependencies(${BINARY_NAME} flutter_assemble)
|
||||
|
||||
# Only the install-generated bundle's copy of the executable will launch
|
||||
# correctly, since the resources must in the right relative locations. To avoid
|
||||
# people trying to run the unbundled copy, put it in a subdirectory instead of
|
||||
|
@ -64,6 +90,7 @@ set_target_properties(${BINARY_NAME}
|
|||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
|
||||
)
|
||||
|
||||
|
||||
# Generated plugin build rules, which manage building the plugins and adding
|
||||
# them to the application.
|
||||
include(flutter/generated_plugins.cmake)
|
||||
|
@ -94,11 +121,11 @@ install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}
|
|||
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||
COMPONENT Runtime)
|
||||
|
||||
if(PLUGIN_BUNDLED_LIBRARIES)
|
||||
install(FILES "${PLUGIN_BUNDLED_LIBRARIES}"
|
||||
foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES})
|
||||
install(FILES "${bundled_library}"
|
||||
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||
COMPONENT Runtime)
|
||||
endif()
|
||||
endforeach(bundled_library)
|
||||
|
||||
# Fully re-copy the assets directory on each build to avoid having stale files
|
||||
# from a previous install.
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
# TODO: This can likely be restricted even further, especially in regards to the ADD_ONION pattern
|
||||
- exe-paths:
|
||||
- ''
|
||||
users:
|
||||
- '*'
|
||||
hosts:
|
||||
- '*'
|
||||
commands:
|
||||
AUTHCHALLENGE:
|
||||
- 'SAFECOOKIE .*'
|
||||
SETEVENTS:
|
||||
- 'CIRC WARN ERR'
|
||||
- 'CIRC ORCONN INFO NOTICE WARN ERR HS_DESC HS_DESC_CONTENT'
|
||||
GETINFO:
|
||||
- 'net/listeners/socks'
|
||||
- '.*'
|
||||
GETCONF:
|
||||
- 'DisableNetwork'
|
||||
SETCONF:
|
||||
- 'DisableNetwork.*'
|
||||
ADD_ONION:
|
||||
- '.*'
|
||||
DEL_ONION:
|
||||
- '.+'
|
||||
HSFETCH:
|
||||
- '.+'
|
||||
events:
|
||||
CIRC:
|
||||
suppress: true
|
||||
ORCONN:
|
||||
suppress: true
|
||||
INFO:
|
||||
suppress: true
|
||||
NOTICE:
|
||||
suppress: true
|
||||
WARN:
|
||||
suppress: true
|
||||
ERR:
|
||||
suppress: true
|
||||
HS_DESC:
|
||||
response:
|
||||
- pattern: '650 HS_DESC CREATED (\S+) (\S+) (\S+) \S+ (.+)'
|
||||
replacement: '650 HS_DESC CREATED {} {} {} redacted {}'
|
||||
- pattern: '650 HS_DESC UPLOAD (\S+) (\S+) .*'
|
||||
replacement: '650 HS_DESC UPLOAD {} {} redacted redacted'
|
||||
- pattern: '650 HS_DESC UPLOADED (\S+) (\S+) .+'
|
||||
replacement: '650 HS_DESC UPLOADED {} {} redacted'
|
||||
- pattern: '650 HS_DESC REQUESTED (\S+) NO_AUTH'
|
||||
replacement: '650 HS_DESC REQUESTED {} NO_AUTH'
|
||||
- pattern: '650 HS_DESC REQUESTED (\S+) NO_AUTH \S+ \S+'
|
||||
replacement: '650 HS_DESC REQUESTED {} NO_AUTH redacted redacted'
|
||||
- pattern: '650 HS_DESC RECEIVED (\S+) NO_AUTH \S+ \S+'
|
||||
replacement: '650 HS_DESC RECEIVED {} NO_AUTH redacted redacted'
|
||||
- pattern: '.*'
|
||||
replacement: ''
|
||||
HS_DESC_CONTENT:
|
||||
suppress: true
|
|
@ -10,6 +10,7 @@
|
|||
#include <pwd.h>
|
||||
|
||||
#include <flutter_linux/flutter_linux.h>
|
||||
#include <flutter_linux/fl_dart_project.h>
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
#include <gdk/gdkx.h>
|
||||
#endif
|
||||
|
@ -28,7 +29,6 @@ struct _MyApplication {
|
|||
struct _FlDartProject {
|
||||
GObject parent_instance;
|
||||
|
||||
gboolean enable_mirrors;
|
||||
gchar* aot_library_path;
|
||||
gchar* assets_path;
|
||||
gchar* icu_data_path;
|
||||
|
@ -65,29 +65,29 @@ static void my_application_activate(GApplication* application) {
|
|||
// if future cases occur).
|
||||
gboolean use_header_bar = TRUE;
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
GdkScreen *screen = gtk_window_get_screen(window);
|
||||
GdkScreen* screen = gtk_window_get_screen(window);
|
||||
if (GDK_IS_X11_SCREEN(screen)) {
|
||||
const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen);
|
||||
if (g_strcmp0(wm_name, "GNOME Shell") != 0) {
|
||||
use_header_bar = FALSE;
|
||||
}
|
||||
const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen);
|
||||
if (g_strcmp0(wm_name, "GNOME Shell") != 0) {
|
||||
use_header_bar = FALSE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (use_header_bar) {
|
||||
GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
|
||||
GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
|
||||
gtk_widget_show(GTK_WIDGET(header_bar));
|
||||
gtk_header_bar_set_title(header_bar, "cwtch");
|
||||
gtk_header_bar_set_show_close_button(header_bar, TRUE);
|
||||
gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
gtk_window_set_title(window, "cwtch");
|
||||
}
|
||||
|
||||
gtk_window_set_default_size(window, 1280, 720);
|
||||
gtk_widget_show(GTK_WIDGET(window));
|
||||
|
||||
g_signal_connect(G_OBJECT(window),
|
||||
// custom hook to catch app exit and send notification to flutter to cleanup
|
||||
g_signal_connect(G_OBJECT(window),
|
||||
"destroy", G_CALLBACK(on_shutdown), NULL);
|
||||
|
||||
g_autoptr(FlDartProject) project = fl_dart_project_new();
|
||||
|
@ -98,58 +98,51 @@ static void my_application_activate(GApplication* application) {
|
|||
if (stat(fl_dart_project_get_assets_path(project), &info ) != 0 ) {
|
||||
if( stat("lib/cwtch", &info) == 0) {
|
||||
// use local dir structure
|
||||
project->assets_path = g_build_filename("data", "flutter_assets", nullptr);
|
||||
fl_dart_project_set_assets_path(project, g_build_filename("data", "flutter_assets", nullptr));
|
||||
project->aot_library_path = g_build_filename("lib", "libapp.so", nullptr);
|
||||
project->icu_data_path = g_build_filename("data", "icudtl.dat", nullptr);
|
||||
fl_dart_project_set_icu_data_path(project, g_build_filename("data", "icudtl.dat", nullptr));
|
||||
gtk_window_set_icon_from_file(window, "./cwtch.png", NULL);
|
||||
} else if( stat("/usr/share/cwtch/data/flutter_assets", &info ) != 0 ) {
|
||||
// if we're non in sys installed structure, use home dir structure
|
||||
struct passwd *pw = getpwuid(getuid());
|
||||
const char *homedir = pw->pw_dir;
|
||||
// /home/$USER/.local/share/cwtch/data/flutter_assets
|
||||
project->assets_path = g_build_filename(homedir, ".local", "share", "cwtch", "data", "flutter_assets", nullptr);
|
||||
fl_dart_project_set_assets_path(project, g_build_filename(homedir, ".local", "share", "cwtch", "data", "flutter_assets", nullptr));
|
||||
// /home/$USER/.local/lib/cwtch/
|
||||
project->aot_library_path = g_build_filename(homedir, ".local", "lib", "cwtch", "libapp.so", nullptr);
|
||||
// /home/$USER/.local/share/cwtch/data
|
||||
project->icu_data_path = g_build_filename(homedir, ".local", "share", "cwtch", "data", "icudtl.dat", nullptr);
|
||||
fl_dart_project_set_icu_data_path(project, g_build_filename(homedir, ".local", "share", "cwtch", "data", "icudtl.dat", nullptr));
|
||||
gtk_window_set_icon_from_file(window, g_build_filename(homedir, ".local", "share", "icons", "cwtch.png", nullptr), NULL);
|
||||
} else {
|
||||
// else assume we are in sys installed structure
|
||||
// /usr/share/cwtch/data/flutter_assets
|
||||
project->assets_path = g_build_filename("/", "usr", "share", "cwtch", "data", "flutter_assets", nullptr);
|
||||
fl_dart_project_set_assets_path(project, g_build_filename("/", "usr", "share", "cwtch", "data", "flutter_assets", nullptr));
|
||||
// /usr/lib/cwtch
|
||||
project->aot_library_path = g_build_filename("/", "usr", "lib", "cwtch", "libapp.so", nullptr);
|
||||
// /usr/share/cwtch/data
|
||||
project->icu_data_path = g_build_filename("/", "usr", "share", "cwtch", "data", "icudtl.dat", nullptr);
|
||||
fl_dart_project_set_icu_data_path(project, g_build_filename("/", "usr", "share", "cwtch", "data", "icudtl.dat", nullptr));
|
||||
gtk_window_set_icon_from_file(window, "/usr/share/icons/cwtch.png", NULL);
|
||||
}
|
||||
}
|
||||
printf("my_application.cc: using aot_library_path or '%s'\n", project->aot_library_path);
|
||||
fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments);
|
||||
|
||||
FlView* view = fl_view_new(project);
|
||||
gtk_widget_show(GTK_WIDGET(view));
|
||||
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
|
||||
|
||||
|
||||
fl_register_plugins(FL_PLUGIN_REGISTRY(view));
|
||||
|
||||
// Create a specific channel for shutting down cwtch when the close button is triggered
|
||||
// We have registered the "destroy" handle above for this reason
|
||||
FlEngine *engine = fl_view_get_engine(view);
|
||||
g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
|
||||
g_autoptr(FlBinaryMessenger) messenger = fl_engine_get_binary_messenger(engine);
|
||||
channel = fl_method_channel_new(messenger, "im.cwtch.linux.shutdown", FL_METHOD_CODEC(codec));
|
||||
|
||||
|
||||
g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
|
||||
g_autoptr(FlBinaryMessenger) messenger = fl_engine_get_binary_messenger(engine);
|
||||
channel = fl_method_channel_new(messenger, "im.cwtch.linux.shutdown", FL_METHOD_CODEC(codec));
|
||||
|
||||
gtk_widget_grab_focus(GTK_WIDGET(view));
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Implements GApplication::local_command_line.
|
||||
static gboolean my_application_local_command_line(GApplication* application, gchar ***arguments, int *exit_status) {
|
||||
static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) {
|
||||
MyApplication* self = MY_APPLICATION(application);
|
||||
// Strip out the first argument as it is the binary name.
|
||||
self->dart_entrypoint_arguments = g_strdupv(*arguments + 1);
|
||||
|
@ -168,7 +161,7 @@ static gboolean my_application_local_command_line(GApplication* application, gch
|
|||
}
|
||||
|
||||
// Implements GObject::dispose.
|
||||
static void my_application_dispose(GObject *object) {
|
||||
static void my_application_dispose(GObject* object) {
|
||||
MyApplication* self = MY_APPLICATION(object);
|
||||
g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev);
|
||||
G_OBJECT_CLASS(my_application_parent_class)->dispose(object);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
platform :osx, '10.11'
|
||||
platform :osx, '10.14'
|
||||
|
||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
PODS:
|
||||
- connectivity_plus (0.0.1):
|
||||
- FlutterMacOS
|
||||
- ReachabilitySwift
|
||||
- flutter_local_notifications (0.0.1):
|
||||
- FlutterMacOS
|
||||
- FlutterMacOS (1.0.0)
|
||||
- package_info_plus_macos (0.0.1):
|
||||
- package_info_plus (0.0.1):
|
||||
- FlutterMacOS
|
||||
- path_provider_macos (0.0.1):
|
||||
- path_provider_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- ReachabilitySwift (5.0.0)
|
||||
- screen_retriever (0.0.1):
|
||||
- FlutterMacOS
|
||||
- url_launcher_macos (0.0.1):
|
||||
|
@ -14,23 +19,30 @@ PODS:
|
|||
- FlutterMacOS
|
||||
|
||||
DEPENDENCIES:
|
||||
- connectivity_plus (from `Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos`)
|
||||
- flutter_local_notifications (from `Flutter/ephemeral/.symlinks/plugins/flutter_local_notifications/macos`)
|
||||
- FlutterMacOS (from `Flutter/ephemeral`)
|
||||
- package_info_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus_macos/macos`)
|
||||
- path_provider_macos (from `Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos`)
|
||||
- package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`)
|
||||
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- screen_retriever (from `Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos`)
|
||||
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
|
||||
- window_manager (from `Flutter/ephemeral/.symlinks/plugins/window_manager/macos`)
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- ReachabilitySwift
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
connectivity_plus:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos
|
||||
flutter_local_notifications:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/flutter_local_notifications/macos
|
||||
FlutterMacOS:
|
||||
:path: Flutter/ephemeral
|
||||
package_info_plus_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/package_info_plus_macos/macos
|
||||
path_provider_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos
|
||||
package_info_plus:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos
|
||||
path_provider_foundation:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
|
||||
screen_retriever:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos
|
||||
url_launcher_macos:
|
||||
|
@ -39,14 +51,16 @@ EXTERNAL SOURCES:
|
|||
:path: Flutter/ephemeral/.symlinks/plugins/window_manager/macos
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
connectivity_plus: 18d3c32514c886e046de60e9c13895109866c747
|
||||
flutter_local_notifications: 3805ca215b2fb7f397d78b66db91f6a747af52e4
|
||||
FlutterMacOS: 57701585bf7de1b3fc2bb61f6378d73bbdea8424
|
||||
package_info_plus_macos: f010621b07802a241d96d01876d6705f15e77c1c
|
||||
path_provider_macos: 3c0c3b4b0d4a76d2bf989a913c2de869c5641a19
|
||||
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
|
||||
package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce
|
||||
path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8
|
||||
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
|
||||
screen_retriever: 59634572a57080243dd1bf715e55b6c54f241a38
|
||||
url_launcher_macos: 597e05b8e514239626bcf4a850fcf9ef5c856ec3
|
||||
url_launcher_macos: 5335912b679c073563f29d89d33d10d459f95451
|
||||
window_manager: 3a1844359a6295ab1e47659b1a777e36773cd6e8
|
||||
|
||||
PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c
|
||||
PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7
|
||||
|
||||
COCOAPODS: 1.11.2
|
||||
COCOAPODS: 1.11.3
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 51;
|
||||
objectVersion = 54;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXAggregateTarget section */
|
||||
|
@ -202,7 +202,7 @@
|
|||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0920;
|
||||
LastUpgradeCheck = 0930;
|
||||
LastUpgradeCheck = 1300;
|
||||
ORGANIZATIONNAME = "";
|
||||
TargetAttributes = {
|
||||
33CC10EC2044A3C60003C045 = {
|
||||
|
@ -255,6 +255,7 @@
|
|||
/* Begin PBXShellScriptBuildPhase section */
|
||||
3399D490228B24CF009A79C7 /* ShellScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
|
@ -403,7 +404,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.14;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
|
@ -483,7 +484,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.14;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
|
@ -530,7 +531,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.14;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1000"
|
||||
LastUpgradeVersion = "1300"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
|
98
pubspec.lock
|
@ -5,18 +5,18 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: _fe_analyzer_shared
|
||||
sha256: "405666cd3cf0ee0a48d21ec67e65406aad2c726d9fa58840d3375e7bdcd32a07"
|
||||
sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "60.0.0"
|
||||
version: "61.0.0"
|
||||
analyzer:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: analyzer
|
||||
sha256: "1952250bd005bacb895a01bf1b4dc00e3ba1c526cf47dca54dfe24979c65f5b3"
|
||||
sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.12.0"
|
||||
version: "5.13.0"
|
||||
archive:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -29,10 +29,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: args
|
||||
sha256: c372bb384f273f0c2a8aaaa226dad84dc27c8519a691b888725dec59518ad53a
|
||||
sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.1"
|
||||
version: "2.4.2"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -77,26 +77,26 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: build_resolvers
|
||||
sha256: "687cf90a3951affac1bd5f9ecb5e3e90b60487f3d9cdc359bb310f8876bb02a6"
|
||||
sha256: db49b8609ef8c81cca2b310618c3017c00f03a92af44c04d310b907b2d692d95
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.10"
|
||||
version: "2.2.0"
|
||||
build_runner:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: build_runner
|
||||
sha256: "220ae4553e50d7c21a17c051afc7b183d28a24a420502e842f303f8e4e6edced"
|
||||
sha256: "5e1929ad37d48bd382b124266cb8e521de5548d406a45a5ae6656c13dab73e37"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.4"
|
||||
version: "2.4.5"
|
||||
build_runner_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_runner_core
|
||||
sha256: "30859c90e9ddaccc484f56303931f477b1f1ba2bab74aa32ed5d6ce15870f8cf"
|
||||
sha256: "6d6ee4276b1c5f34f21fdf39425202712d2be82019983d52f351c94aafbc2c41"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.2.8"
|
||||
version: "7.2.10"
|
||||
built_collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -109,10 +109,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: built_value
|
||||
sha256: "2f17434bd5d52a26762043d6b43bb53b3acd029b4d9071a329f46d67ef297e6d"
|
||||
sha256: "598a2a682e2a7a90f08ba39c0aaa9374c5112340f0a2e275f61b59389543d166"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.5.0"
|
||||
version: "8.6.1"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -149,10 +149,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: code_builder
|
||||
sha256: "0d43dd1288fd145de1ecc9a3948ad4a6d5a82f0a14c4fdd0892260787d975cbe"
|
||||
sha256: "4ad01d6e56db961d29661561effde45e519939fdaeb46c351275b182eac70189"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.4.0"
|
||||
version: "4.5.0"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -211,10 +211,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: dart_style
|
||||
sha256: "7a03456c3490394c8e7665890333e91ae8a49be43542b616e414449ac358acd4"
|
||||
sha256: f4f1f73ab3fd2afcbcca165ee601fe980d966af6a21b5970c6c9376955c528ad
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.4"
|
||||
version: "2.3.1"
|
||||
dbus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -278,7 +278,7 @@ packages:
|
|||
description:
|
||||
path: "."
|
||||
ref: main
|
||||
resolved-ref: "9e89cc0d89770242a3c2e86573f9618a0dd49194"
|
||||
resolved-ref: cfa8a5f93267e8b544cd705ad015dcc55d7804fa
|
||||
url: "https://git.openprivacy.ca/openprivacy/flutter_gherkin"
|
||||
source: git
|
||||
version: "3.0.0-rc.17"
|
||||
|
@ -286,10 +286,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_local_notifications
|
||||
sha256: ee6ee56855aa920899b68586b538474d086c149932220b47b92502cbfb5ba5e5
|
||||
sha256: "812791d43ccfc1b443a0d39fa02a206fc228c597e28ff9337e09e3ca8d370391"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "14.0.0+2"
|
||||
version: "14.1.1"
|
||||
flutter_local_notifications_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -315,10 +315,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: flutter_plugin_android_lifecycle
|
||||
sha256: "96af49aa6b57c10a312106ad6f71deed5a754029c24789bbf620ba784f0bd0b0"
|
||||
sha256: "950e77c2bbe1692bc0874fc7fb491b96a4dc340457f4ea1641443d0a6c1ea360"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.14"
|
||||
version: "2.0.15"
|
||||
flutter_test:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
|
@ -362,26 +362,26 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: glob
|
||||
sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c"
|
||||
sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
version: "2.1.2"
|
||||
graphs:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: graphs
|
||||
sha256: "772db3d53d23361d4ffcf5a9bb091cf3ee9b22f2be52cd107cd7a2683a89ba0e"
|
||||
sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.0"
|
||||
version: "2.3.1"
|
||||
http:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http
|
||||
sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2"
|
||||
sha256: "4c3f04bfb64d3efd508d06b41b825542f08122d30bda4933fb95c069d22a4fa3"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.13.6"
|
||||
version: "1.0.0"
|
||||
http_multi_server:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -447,10 +447,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: logging
|
||||
sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d"
|
||||
sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
version: "1.2.0"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -487,10 +487,10 @@ packages:
|
|||
dependency: "direct dev"
|
||||
description:
|
||||
name: msix
|
||||
sha256: "88ee83949d87dc635ffd51d7c17ef222390e5067693cc248046661b12a353d13"
|
||||
sha256: bf151b9a1648985e7604672ade54c8df693566099d0731e318548c47d54676e6
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.12.2"
|
||||
version: "3.14.2"
|
||||
nested:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -511,10 +511,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: package_info_plus
|
||||
sha256: d39e8fbff4c5aef4592737e25ad6ac500df006ce7a7a8e1f838ce1256e167542
|
||||
sha256: ceb027f6bc6a60674a233b4a90a7658af1aebdea833da0b5b53c1e9821a78c7b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
version: "4.0.2"
|
||||
package_info_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -559,10 +559,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_linux
|
||||
sha256: "2ae08f2216225427e64ad224a24354221c2c7907e448e6e0e8b57b1eb9f10ad1"
|
||||
sha256: ffbb8cc9ed2c9ec0e4b7a541e56fd79b138e8f47d2fb86815f15358a349b3b57
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.10"
|
||||
version: "2.1.11"
|
||||
path_provider_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -575,10 +575,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_windows
|
||||
sha256: d3f80b32e83ec208ac95253e0cd4d298e104fbc63cb29c5c69edaed43b0c69d6
|
||||
sha256: "1cb68ba4cd3a795033de62ba1b7b4564dace301f952de6bfb3cd91b202b6ee96"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.6"
|
||||
version: "2.1.7"
|
||||
petitparser:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -708,10 +708,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: source_gen
|
||||
sha256: "2d79738b6bbf38a43920e2b8d189e9a3ce6cc201f4b8fc76be5e4fe377b1c38d"
|
||||
sha256: "373f96cf5a8744bc9816c1ff41cf5391bbdbe3d7a96fe98c622b6738a8a7bd33"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.6"
|
||||
version: "1.3.2"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -812,10 +812,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_android
|
||||
sha256: "7aac14be5f4731b923cc697ae2d42043945076cd0dbb8806baecc92c1dc88891"
|
||||
sha256: eed4e6a1164aa9794409325c3b707ff424d4d1c2a785e7db67f8bbda00e36e51
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.0.33"
|
||||
version: "6.0.35"
|
||||
url_launcher_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -852,10 +852,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_web
|
||||
sha256: "81fe91b6c4f84f222d186a9d23c73157dc4c8e1c71489c4d08be1ad3b228f1aa"
|
||||
sha256: "6bb1e5d7fe53daf02a8fee85352432a40b1f868a81880e99ec7440113d5cfcab"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.16"
|
||||
version: "2.0.17"
|
||||
url_launcher_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -924,18 +924,18 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: win_toast
|
||||
sha256: "371d62b17b30489cad41e831e6340c2777202d2b4b2fd55a14ffc566b3df7518"
|
||||
sha256: "6349ef17a487d2ebf9caa51da1cb5a325f4cd7e5a601935ced456f3c00d1e64f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.0"
|
||||
version: "0.0.2"
|
||||
window_manager:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: window_manager
|
||||
sha256: "2b2572442b2a5178642730442dc625ac088244f5827b1f0811371b1b7485eb62"
|
||||
sha256: "95096fede562cbb65f30d38b62d819a458f59ba9fe4a317f6cee669710f6676b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.2"
|
||||
version: "0.3.4"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -44,7 +44,11 @@ dependencies:
|
|||
url_launcher: ^6.0.18
|
||||
window_manager: ^0.3.2
|
||||
# notification plugins
|
||||
win_toast: ^0.3.0
|
||||
## Somewhere between 0.0.2 and 0.3 they introduced a dependancy on a new Windows RT feature
|
||||
## Which can only be linked to with a new VC 17 compiler and we're suspicious only work on
|
||||
## Windows 2022 and newer... we can't seem to automate compiling on win server 2019 containers
|
||||
## So pinning to 0.0.2 for the forseeable future or until we change plugins
|
||||
win_toast: ^0.0.2
|
||||
flutter_local_notifications: ^14.0.0+2
|
||||
dbus: ^0.7.8
|
||||
connectivity_plus:
|
||||
|
|
|
@ -7,7 +7,7 @@ flutter pub run build_runner build --delete-conflicting-outputs
|
|||
|
||||
PATH=$PATH:$PWD/linux/Tor
|
||||
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:"$PWD/linux/":"$PWD/linux/Tor/"
|
||||
PATH=$PATH LD_LIBRARY_PATH=$LD_LIBRARY_PATH CWTCH_HOME=$PWD/integration_test/env/temp/ flutter test -d linux --dart-define TEST_MODE=true integration_test/gherkin_suite_test.dart
|
||||
PATH=$PATH LD_LIBRARY_PATH=$LD_LIBRARY_PATH LOG_FILE=test.log CWTCH_HOME=$PWD/integration_test/env/temp/ flutter test -d linux --dart-define TEST_MODE=true integration_test/gherkin_suite_test.dart
|
||||
#node index2.js
|
||||
#if [ "$HEADLESS" = "false" ]; then
|
||||
# xdg-open integration_test/gherkin/reports/cucumber_report.html
|
||||
|
|
Before Width: | Height: | Size: 252 B After Width: | Height: | Size: 252 B |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 5.9 KiB |