merge
continuous-integration/drone/pr Build is passing
Details
|
@ -59,7 +59,8 @@ steps:
|
|||
- cp linux/cwtch.desktop deploy/linux
|
||||
- cp linux/cwtch.png deploy/linux
|
||||
- cp linux/libCwtch.so deploy/linux/lib/
|
||||
- cp /sdks/flutter/bin/cache/artifacts/engine/linux-x64/icudtl.dat deploy/linux
|
||||
# should not be needed, should be in data/flutter_assets and work from there
|
||||
#- cp /sdks/flutter/bin/cache/artifacts/engine/linux-x64/icudtl.dat deploy/linux
|
||||
- cp tor deploy/linux
|
||||
- cd deploy
|
||||
- mv linux cwtch
|
||||
|
@ -230,6 +231,12 @@ steps:
|
|||
- mkdir deploy
|
||||
- move build\\windows\\runner\\Release $Env:builddir
|
||||
- copy windows\libCwtch.dll $Env:builddir
|
||||
# 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.30036\x64\Microsoft.VC142.CRT\vcruntime140.dll $Env:builddir
|
||||
- copy C:\BuildTools\VC\Redist\MSVC\14.29.30036\x64\Microsoft.VC142.CRT\vcruntime140_1.dll $Env:builddir
|
||||
- copy C:\BuildTools\VC\Redist\MSVC\14.29.30036\x64\Microsoft.VC142.CRT\msvcp140.dll $Env:builddir
|
||||
- powershell -command "Expand-Archive -Path tor.zip -DestinationPath $Env:builddir\Tor"
|
||||
- powershell -command "Compress-Archive -Path $Env:builddir -DestinationPath $Env:zip"
|
||||
- powershell -command "(Get-FileHash *.zip -Algorithm sha512).Hash" > $Env:sha
|
||||
|
|
14
README.md
|
@ -1,6 +1,6 @@
|
|||
# flwtch
|
||||
|
||||
A new Flutter application.
|
||||
A Flutter based Cwtch UI
|
||||
|
||||
## Getting Started
|
||||
|
||||
|
@ -8,13 +8,19 @@ click the play button in android studio
|
|||
|
||||
### Linux
|
||||
|
||||
- libCwtch-go: the result of `make linux`, `libCwtch.so` should be in the link path
|
||||
- libCwtch-go: required to be on the link path (linux/cwtch.destktop demonstrates with `env LD_LIBRARY_PATH=./lib/` on the front of the comman)
|
||||
- fetch-libcwtch-go.sh will fetch a prebuilt version
|
||||
- or compile from source from libcwtch-go with `make linux`
|
||||
- `tor` should be in the PATH
|
||||
|
||||
### Windows
|
||||
|
||||
- libCwtch-go: the result of `make windows`, `libCwtch.dll` should be placed in the source root
|
||||
- tor is bundled in `windors/Tor`
|
||||
- run `fetch-libcwtch-go.ps1` to get `libCwtch.dll` which is required to run
|
||||
- run `fetch-tor-win.ps1` to fetch Tor for windows
|
||||
|
||||
#### Issues
|
||||
|
||||
- Flutter engine has a [known bug](https://github.com/flutter/flutter/issues/75675) around the Right Shift key being sticky. We have implemented the mostly work around, but until it is fixed, right shift occasionally acts permenent. If this happens, just tap left shift and it will reset
|
||||
|
||||
## l10n
|
||||
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
style="enable-background:new 0 0 24 24;"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="negative_heart_24px.svg"
|
||||
inkscape:export-filename="/home/sarah/AndroidStudioProjects/flutter_app/assets/core/negative_heart_512px.png"
|
||||
inkscape:export-xdpi="4096"
|
||||
inkscape:export-ydpi="4096"
|
||||
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"><metadata
|
||||
inkscape:export-filename="/home/sarah/PARA/projects/cwtch/assets/core/negative_heart_256px.png"
|
||||
inkscape:export-xdpi="1024"
|
||||
inkscape:export-ydpi="1024"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"><metadata
|
||||
id="metadata14"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||
|
@ -34,14 +34,14 @@
|
|||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1015"
|
||||
inkscape:window-height="1020"
|
||||
id="namedview10"
|
||||
showgrid="false"
|
||||
inkscape:zoom="9.8333333"
|
||||
inkscape:cx="12"
|
||||
inkscape:cy="14.687942"
|
||||
inkscape:cx="-5.8983051"
|
||||
inkscape:cy="14.281162"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-y="31"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Layer_1" />
|
||||
<style
|
||||
|
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
|
@ -207,6 +207,7 @@ class CwtchNotifier {
|
|||
break;
|
||||
case "AcceptGroupInvite":
|
||||
print("accept group invite: $data");
|
||||
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["GroupID"])!.isInvitation = false;
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.updateLastMessageTime(data["GroupID"], DateTime.now());
|
||||
break;
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
/// Flutter icons MyFlutterApp
|
||||
/// Copyright (C) 2021 by original authors @ fluttericon.com, fontello.com
|
||||
/// This font was generated by FlutterIcon.com, which is derived from Fontello.
|
||||
///
|
||||
/// To use this font, place it in your fonts/ directory and include the
|
||||
/// following in your pubspec.yaml
|
||||
///
|
||||
/// flutter:
|
||||
/// fonts:
|
||||
/// - family: CwtchIcons
|
||||
/// fonts:
|
||||
/// - asset: assets/fonts/CwtchIcons.ttf
|
||||
///
|
||||
///
|
||||
///
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class CwtchIcons {
|
||||
CwtchIcons._();
|
||||
|
||||
static const _kFontFam = 'CwtchIcons';
|
||||
static const String? _kFontPkg = null;
|
||||
|
||||
static const IconData arrow_back_24px = IconData(0xe800, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData attach_file_24px = IconData(0xe801, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData block_peer = IconData(0xe802, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData block_unknown = IconData(0xe803, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData block_24px = IconData(0xe804, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData brightness_5_24px = IconData(0xe805, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData camera_alt_24px = IconData(0xe806, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData change_language = IconData(0xe807, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData change_theme = IconData(0xe808, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData chat_bubble_empty_24px = IconData(0xe809, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData chat_bubble_24px = IconData(0xe80a, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData chat_seetings_24px = IconData(0xe80b, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData check_24px = IconData(0xe80c, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData chevron_left_24px = IconData(0xe80d, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData clear_24px = IconData(0xe80e, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData content_copy_24px = IconData(0xe80f, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData create_group = IconData(0xe810, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData cwtch_knott = IconData(0xe811, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData dark_mode_24px = IconData(0xe812, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData delete_24px = IconData(0xe813, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData dns_24px = IconData(0xe814, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData drag_indicator_24px = IconData(0xe815, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData edit_24px = IconData(0xe816, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData enable_experiments = IconData(0xe817, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData enable_groups = IconData(0xe818, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData eye_closed = IconData(0xe819, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData eye_open = IconData(0xe81a, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData favorite_24dp = IconData(0xe81b, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData favorite_black_24dp_broken = IconData(0xe81c, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData favorite_black_24dp_brokenhalf = IconData(0xe81d, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData favorite_black_24dp_malformed = IconData(0xe81e, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData favorite_black_24dp_sad = IconData(0xe81f, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData group_add_24px = IconData(0xe820, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData group_settings_24px = IconData(0xe821, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData groups_24px = IconData(0xe822, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData info_24px = IconData(0xe823, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData join_group = IconData(0xe824, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData list_black_24dp = IconData(0xe825, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData lock_open_24px = IconData(0xe826, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData lock_24px = IconData(0xe827, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData maps_ugc_24px = IconData(0xe828, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData menu_24px = IconData(0xe829, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData message_24px = IconData(0xe82a, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData mood_24px = IconData(0xe82b, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData more_vert_24px = IconData(0xe82c, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData negative_heart_24px = IconData(0xe82d, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData onion_off = IconData(0xe82e, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData onion_on = IconData(0xe82f, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData onion_waiting = IconData(0xe830, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData peer_history = IconData(0xe831, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData peer_settings_24px = IconData(0xe832, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData person_add_alt_1_24px = IconData(0xe833, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData person_add_24px = IconData(0xe834, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData person_24px = IconData(0xe835, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData push_pin_black_24dp = IconData(0xe836, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData push_pin_24px = IconData(0xe837, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData search_24px = IconData(0xe838, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData send_24px = IconData(0xe839, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData settings_24px = IconData(0xe83a, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData signal_cellular_4_bar_24px = IconData(0xe83b, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData signal_cellular_alt_24px = IconData(0xe83c, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData signal_cellular_connected_no_internet_4_bar_24px = IconData(0xe83d, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData signal_cellular_off_24px = IconData(0xe83e, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData swap_horiz_24px = IconData(0xe83f, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData sync_disabled_24px = IconData(0xe840, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData sync_problem_24px = IconData(0xe841, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData sync_24px = IconData(0xe842, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData syncing_01 = IconData(0xe843, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData syncing_02 = IconData(0xe844, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData syncing_03 = IconData(0xe845, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData toggle_on_24px = IconData(0xe846, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData vpn_key_24px = IconData(0xe847, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData account_blocked = IconData(0xe848, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData account_circle_24px = IconData(0xe849, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData account_circle_24px_lines = IconData(0xe84a, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData account_circle_24px_lines_thin___blocked = IconData(0xe84b, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData account_circle_24px_user = IconData(0xe84c, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData add_circle_24px = IconData(0xe84d, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData add_group = IconData(0xe84e, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData add_peer = IconData(0xe84f, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData add_24px = IconData(0xe850, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData send_invite = IconData(0xe888, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData copy_address = IconData(0xe889, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData leave_group = IconData(0xe88a, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData leave_chat = IconData(0xe88b, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"@@locale": "de",
|
||||
"accepted": "",
|
||||
"acceptGroupBtn": "Annehmen",
|
||||
"acceptGroupInviteLabel": "Möchtest Du die Einladung annehmen",
|
||||
"acknowledgedLabel": "bestätigt",
|
||||
|
@ -17,7 +18,9 @@
|
|||
"builddate": "Aufgebaut auf: %2",
|
||||
"bulletinsBtn": "Meldungen",
|
||||
"chatBtn": "Chat",
|
||||
"chatHistoryDefault": "",
|
||||
"contactAlreadyExists": "",
|
||||
"contactSuggestion": "",
|
||||
"conversationSettings": "",
|
||||
"copiedClipboardNotification": "in die Zwischenablage kopiert",
|
||||
"copiedToClipboardNotification": "in die Zwischenablage kopiert",
|
||||
|
@ -120,6 +123,7 @@
|
|||
"radioNoPassword": "Unverschlüsselt (kein Passwort)",
|
||||
"radioUsePassword": "Passwort",
|
||||
"reallyLeaveThisGroupPrompt": "",
|
||||
"rejected": "",
|
||||
"rejectGroupBtn": "Ablehnen",
|
||||
"saveBtn": "Speichern",
|
||||
"savePeerHistory": "Peer-Verlauf speichern",
|
||||
|
@ -127,6 +131,7 @@
|
|||
"saveProfileBtn": "Profil speichern",
|
||||
"search": "Suche...",
|
||||
"searchList": "",
|
||||
"sendAnInvitation": "",
|
||||
"server": "Server",
|
||||
"serverConnectivityConnected": "Server verbunden",
|
||||
"serverConnectivityDisconnected": "Server getrennt",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"@@locale": "en",
|
||||
"accepted": "Accepted!",
|
||||
"acceptGroupBtn": "Accept",
|
||||
"acceptGroupInviteLabel": "Do you want to accept the invitation to",
|
||||
"acknowledgedLabel": "Acknowledged",
|
||||
|
@ -17,7 +18,9 @@
|
|||
"builddate": "Built on: %2",
|
||||
"bulletinsBtn": "Bulletins",
|
||||
"chatBtn": "Chat",
|
||||
"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.",
|
||||
"contactAlreadyExists": "Contact Already Exists",
|
||||
"contactSuggestion": "This is a contact suggestion for: ",
|
||||
"conversationSettings": "Conversation Settings",
|
||||
"copiedClipboardNotification": "Copied to clipboard",
|
||||
"copiedToClipboardNotification": "Copied to Clipboard",
|
||||
|
@ -120,6 +123,7 @@
|
|||
"radioNoPassword": "Unencrypted (No password)",
|
||||
"radioUsePassword": "Password",
|
||||
"reallyLeaveThisGroupPrompt": "Are you sure you want to leave this conversation? All messages and attributes will be deleted.",
|
||||
"rejected": "Rejected!",
|
||||
"rejectGroupBtn": "Reject",
|
||||
"saveBtn": "Save",
|
||||
"savePeerHistory": "Save Peer History",
|
||||
|
@ -127,6 +131,7 @@
|
|||
"saveProfileBtn": "Save Profile",
|
||||
"search": "Search...",
|
||||
"searchList": "Search List",
|
||||
"sendAnInvitation": "You sent an invitation for: ",
|
||||
"server": "Server",
|
||||
"serverConnectivityConnected": "Server Connected",
|
||||
"serverConnectivityDisconnected": "Server Disconnected",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"@@locale": "es",
|
||||
"accepted": "",
|
||||
"acceptGroupBtn": "Aceptar",
|
||||
"acceptGroupInviteLabel": "¿Quieres aceptar la invitación a ",
|
||||
"acknowledgedLabel": "Reconocido",
|
||||
|
@ -17,7 +18,9 @@
|
|||
"builddate": "Basado en: %2",
|
||||
"bulletinsBtn": "Boletines",
|
||||
"chatBtn": "Chat",
|
||||
"chatHistoryDefault": "",
|
||||
"contactAlreadyExists": "",
|
||||
"contactSuggestion": "",
|
||||
"conversationSettings": "",
|
||||
"copiedClipboardNotification": "Copiado al portapapeles",
|
||||
"copiedToClipboardNotification": "Copiado al portapapeles",
|
||||
|
@ -120,6 +123,7 @@
|
|||
"radioNoPassword": "Sin cifrado (sin contraseña)",
|
||||
"radioUsePassword": "Contraseña",
|
||||
"reallyLeaveThisGroupPrompt": "",
|
||||
"rejected": "",
|
||||
"rejectGroupBtn": "Rechazar",
|
||||
"saveBtn": "Guardar",
|
||||
"savePeerHistory": "Guardar el historial con contacto",
|
||||
|
@ -127,6 +131,7 @@
|
|||
"saveProfileBtn": "Guardar perfil",
|
||||
"search": "Búsqueda...",
|
||||
"searchList": "Buscar en la lista",
|
||||
"sendAnInvitation": "",
|
||||
"server": "Servidor",
|
||||
"serverConnectivityConnected": "Servidor conectado",
|
||||
"serverConnectivityDisconnected": "Servidor desconectado",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"@@locale": "fr",
|
||||
"accepted": "",
|
||||
"acceptGroupBtn": "Accepter",
|
||||
"acceptGroupInviteLabel": "Voulez-vous accepter l'invitation au groupe",
|
||||
"acknowledgedLabel": "Confirmé",
|
||||
|
@ -17,7 +18,9 @@
|
|||
"builddate": "",
|
||||
"bulletinsBtn": "Bulletins",
|
||||
"chatBtn": "Discuter",
|
||||
"chatHistoryDefault": "",
|
||||
"contactAlreadyExists": "",
|
||||
"contactSuggestion": "",
|
||||
"conversationSettings": "",
|
||||
"copiedClipboardNotification": "Copié dans le presse-papier",
|
||||
"copiedToClipboardNotification": "Copié dans le presse-papier",
|
||||
|
@ -120,6 +123,7 @@
|
|||
"radioNoPassword": "",
|
||||
"radioUsePassword": "",
|
||||
"reallyLeaveThisGroupPrompt": "",
|
||||
"rejected": "",
|
||||
"rejectGroupBtn": "Refuser",
|
||||
"saveBtn": "Sauvegarder",
|
||||
"savePeerHistory": "",
|
||||
|
@ -127,6 +131,7 @@
|
|||
"saveProfileBtn": "",
|
||||
"search": "",
|
||||
"searchList": "",
|
||||
"sendAnInvitation": "",
|
||||
"server": "",
|
||||
"serverConnectivityConnected": "",
|
||||
"serverConnectivityDisconnected": "",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"@@locale": "it",
|
||||
"accepted": "",
|
||||
"acceptGroupBtn": "Accetta",
|
||||
"acceptGroupInviteLabel": "Vuoi accettare l'invito a",
|
||||
"acknowledgedLabel": "Riconosciuto",
|
||||
|
@ -17,7 +18,9 @@
|
|||
"builddate": "Costruito il: %2",
|
||||
"bulletinsBtn": "Bollettini",
|
||||
"chatBtn": "Chat",
|
||||
"chatHistoryDefault": "",
|
||||
"contactAlreadyExists": "",
|
||||
"contactSuggestion": "",
|
||||
"conversationSettings": "",
|
||||
"copiedClipboardNotification": "Copiato negli Appunti",
|
||||
"copiedToClipboardNotification": "Copiato negli Appunti",
|
||||
|
@ -120,6 +123,7 @@
|
|||
"radioNoPassword": "Non criptato (senza password)",
|
||||
"radioUsePassword": "Password",
|
||||
"reallyLeaveThisGroupPrompt": "",
|
||||
"rejected": "",
|
||||
"rejectGroupBtn": "Rifiuta",
|
||||
"saveBtn": "Salva",
|
||||
"savePeerHistory": "Salva cronologia peer",
|
||||
|
@ -127,6 +131,7 @@
|
|||
"saveProfileBtn": "Salva il profilo",
|
||||
"search": "Ricerca...",
|
||||
"searchList": "Cerca nella lista",
|
||||
"sendAnInvitation": "",
|
||||
"server": "Server",
|
||||
"serverConnectivityConnected": "Server connesso",
|
||||
"serverConnectivityDisconnected": "Server disconnesso",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"@@locale": "pt",
|
||||
"accepted": "",
|
||||
"acceptGroupBtn": "Aceitar",
|
||||
"acceptGroupInviteLabel": "Você quer aceitar o convite para",
|
||||
"acknowledgedLabel": "Confirmada",
|
||||
|
@ -17,7 +18,9 @@
|
|||
"builddate": "",
|
||||
"bulletinsBtn": "Boletins",
|
||||
"chatBtn": "Chat",
|
||||
"chatHistoryDefault": "",
|
||||
"contactAlreadyExists": "",
|
||||
"contactSuggestion": "",
|
||||
"conversationSettings": "",
|
||||
"copiedClipboardNotification": "Copiado",
|
||||
"copiedToClipboardNotification": "Copiado",
|
||||
|
@ -120,6 +123,7 @@
|
|||
"radioNoPassword": "",
|
||||
"radioUsePassword": "",
|
||||
"reallyLeaveThisGroupPrompt": "",
|
||||
"rejected": "",
|
||||
"rejectGroupBtn": "Recusar",
|
||||
"saveBtn": "Salvar",
|
||||
"savePeerHistory": "",
|
||||
|
@ -127,6 +131,7 @@
|
|||
"saveProfileBtn": "",
|
||||
"search": "",
|
||||
"searchList": "",
|
||||
"sendAnInvitation": "",
|
||||
"server": "",
|
||||
"serverConnectivityConnected": "",
|
||||
"serverConnectivityDisconnected": "",
|
||||
|
|
|
@ -64,13 +64,13 @@ class ContactListState extends ChangeNotifier {
|
|||
bool get isFiltered => _filter != "";
|
||||
String get filter => _filter;
|
||||
set filter(String newVal) {
|
||||
_filter = newVal;
|
||||
_filter = newVal.toLowerCase();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
List<ContactInfoState> filteredList() {
|
||||
if (!isFiltered) return contacts;
|
||||
return _contacts.where((ContactInfoState c) => c.onion.contains(_filter) || (c.nickname.contains(_filter))).toList();
|
||||
return _contacts.where((ContactInfoState c) => c.onion.toLowerCase().startsWith(_filter) || (c.nickname.toLowerCase().contains(_filter))).toList();
|
||||
}
|
||||
|
||||
void addAll(Iterable<ContactInfoState> newContacts) {
|
||||
|
@ -382,7 +382,7 @@ class MessageState extends ChangeNotifier {
|
|||
late String _inviteNick;
|
||||
late DateTime _timestamp;
|
||||
late String _senderOnion;
|
||||
late String _senderImage;
|
||||
String? _senderImage;
|
||||
late String _signature = "";
|
||||
late bool _ackd = false;
|
||||
late bool _error = false;
|
||||
|
@ -404,10 +404,10 @@ class MessageState extends ChangeNotifier {
|
|||
get timestamp => this._timestamp;
|
||||
bool get ackd => this._ackd;
|
||||
bool get error => this._error;
|
||||
get malformed => this._malformed;
|
||||
bool get malformed => this._malformed;
|
||||
bool get loaded => this._loaded;
|
||||
get senderOnion => this._senderOnion;
|
||||
get senderImage => this._senderImage;
|
||||
get loaded => this._loaded;
|
||||
get signature => this._signature;
|
||||
get isInvite => this.overlay == 100 || this.overlay == 101;
|
||||
get inviteTarget => this._inviteTarget;
|
||||
|
@ -423,6 +423,16 @@ class MessageState extends ChangeNotifier {
|
|||
notifyListeners();
|
||||
}
|
||||
|
||||
set malformed(bool newVal) {
|
||||
this._malformed = newVal;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
set loaded(bool newVal) {
|
||||
this._loaded = newVal;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void tryLoad(BuildContext context) {
|
||||
Provider.of<FlwtchState>(context, listen: false).cwtch.GetMessage(profileOnion, contactHandle, messageIndex).then((jsonMessage) {
|
||||
try {
|
||||
|
@ -430,7 +440,6 @@ class MessageState extends ChangeNotifier {
|
|||
dynamic messageWrapper = jsonDecode(jsonMessage);
|
||||
if (messageWrapper['Message'] == null || messageWrapper['Message'] == '' || messageWrapper['Message'] == '{}') {
|
||||
this._senderOnion = profileOnion;
|
||||
//todo: remove once sent group messages are prestored
|
||||
Future.delayed(const Duration(milliseconds: 2), () {
|
||||
tryLoad(context);
|
||||
});
|
||||
|
@ -464,7 +473,7 @@ class MessageState extends ChangeNotifier {
|
|||
}
|
||||
}
|
||||
|
||||
this._loaded = true;
|
||||
this.loaded = true;
|
||||
|
||||
//update ackd and error last as they are changenotified
|
||||
this.ackd = messageWrapper['Acknowledged'];
|
||||
|
@ -472,7 +481,9 @@ class MessageState extends ChangeNotifier {
|
|||
this.error = true;
|
||||
}
|
||||
} catch (e) {
|
||||
this._malformed = true;
|
||||
this._overlay = -1;
|
||||
this.loaded = true;
|
||||
this.malformed = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1357,14 +1357,14 @@ ThemeData mkThemeData(Settings opaque) {
|
|||
),
|
||||
cardColor: opaque.current().backgroundMainColor(),
|
||||
appBarTheme: AppBarTheme(
|
||||
backgroundColor: opaque.current().backgroundPaneColor(),
|
||||
titleTextStyle: TextStyle(
|
||||
color: opaque.current().mainTextColor(),
|
||||
),
|
||||
actionsIconTheme: IconThemeData(
|
||||
color: opaque.current().mainTextColor(),
|
||||
),
|
||||
),
|
||||
backgroundColor: opaque.current().backgroundPaneColor(),
|
||||
titleTextStyle: TextStyle(
|
||||
color: opaque.current().mainTextColor(),
|
||||
),
|
||||
actionsIconTheme: IconThemeData(
|
||||
color: opaque.current().mainTextColor(),
|
||||
)),
|
||||
bottomNavigationBarTheme: BottomNavigationBarThemeData(type: BottomNavigationBarType.fixed, backgroundColor: opaque.current().backgroundHilightElementColor()),
|
||||
textButtonTheme: TextButtonThemeData(
|
||||
style: ButtonStyle(
|
||||
backgroundColor: MaterialStateProperty.all(opaque.current().defaultButtonColor()),
|
||||
|
@ -1383,6 +1383,8 @@ ThemeData mkThemeData(Settings opaque) {
|
|||
)),
|
||||
),
|
||||
),
|
||||
scrollbarTheme: ScrollbarThemeData(
|
||||
isAlwaysShown: false, thumbColor: MaterialStateProperty.all(opaque.current().scrollbarActiveColor()), trackColor: MaterialStateProperty.all(opaque.current().scrollbarDefaultColor())),
|
||||
tabBarTheme: TabBarTheme(indicator: UnderlineTabIndicator(borderSide: BorderSide(color: opaque.current().defaultButtonActiveColor()))),
|
||||
dialogTheme: DialogTheme(
|
||||
backgroundColor: opaque.current().backgroundPaneColor(),
|
||||
|
|
|
@ -16,7 +16,8 @@ class Settings extends ChangeNotifier {
|
|||
Locale locale;
|
||||
late PackageInfo packageInfo;
|
||||
OpaqueThemeType theme;
|
||||
late bool experimentsEnabled;
|
||||
// explicitly set experiments to false until told otherwise...
|
||||
bool experimentsEnabled = false;
|
||||
HashMap<String, bool> experiments = HashMap.identity();
|
||||
|
||||
late bool blockUnknownConnections;
|
||||
|
@ -38,6 +39,18 @@ class Settings extends ChangeNotifier {
|
|||
return theme;
|
||||
}
|
||||
|
||||
/// isExperimentEnabled can be used to safely check whether a particular
|
||||
/// experiment is enabled
|
||||
bool isExperimentEnabled(String experiment) {
|
||||
if (this.experimentsEnabled) {
|
||||
if (this.experiments.containsKey(experiment)) {
|
||||
// We now know it cannot be null...
|
||||
return this.experiments[experiment]! == true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Called by the event bus. When new settings are loaded from a file the JSON will
|
||||
/// be sent to the function and new settings will be instantiated based on the contents.
|
||||
handleUpdate(dynamic settings) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:cwtch/cwtch_icons_icons.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:cwtch/errorHandler.dart';
|
||||
|
@ -49,8 +50,8 @@ class _AddContactViewState extends State<AddContactView> {
|
|||
Widget _buildForm() {
|
||||
ctrlrOnion.text = Provider.of<ProfileInfoState>(context).onion;
|
||||
|
||||
/// We display a different number of tabs dependening on the experiment setup
|
||||
bool groupsEnabled = Provider.of<Settings>(context).experimentsEnabled && Provider.of<Settings>(context).experiments[TapirGroupsExperiment]!;
|
||||
/// We display a different number of tabs depending on the experiment setup
|
||||
bool groupsEnabled = Provider.of<Settings>(context).isExperimentEnabled(TapirGroupsExperiment);
|
||||
return Consumer<ErrorHandler>(builder: (context, globalErrorHandler, child) {
|
||||
return DefaultTabController(
|
||||
length: groupsEnabled ? 2 : 1,
|
||||
|
@ -80,7 +81,7 @@ class _AddContactViewState extends State<AddContactView> {
|
|||
return TabBar(
|
||||
tabs: [
|
||||
Tab(
|
||||
icon: Icon(Icons.person_add_rounded),
|
||||
icon: Icon(CwtchIcons.add_peer),
|
||||
text: AppLocalizations.of(context)!.addPeer,
|
||||
),
|
||||
],
|
||||
|
@ -92,11 +93,11 @@ class _AddContactViewState extends State<AddContactView> {
|
|||
return TabBar(
|
||||
tabs: [
|
||||
Tab(
|
||||
icon: Icon(Icons.person_add_rounded),
|
||||
icon: Icon(CwtchIcons.add_peer),
|
||||
text: AppLocalizations.of(context)!.tooltipAddContact,
|
||||
),
|
||||
//Tab(icon: Icon(Icons.backup), text: AppLocalizations.of(context)!.titleManageServers),
|
||||
Tab(icon: Icon(Icons.group), text: AppLocalizations.of(context)!.createGroup),
|
||||
Tab(icon: Icon(CwtchIcons.add_group), text: AppLocalizations.of(context)!.createGroup),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
@ -118,7 +119,7 @@ class _AddContactViewState extends State<AddContactView> {
|
|||
CwtchButtonTextField(
|
||||
controller: ctrlrOnion,
|
||||
onPressed: _copyOnion,
|
||||
icon: Icon(Icons.copy),
|
||||
icon: Icon(CwtchIcons.copy_address),
|
||||
tooltip: AppLocalizations.of(context)!.copyBtn,
|
||||
),
|
||||
SizedBox(
|
||||
|
|
|
@ -99,6 +99,7 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
|
|||
),
|
||||
CwtchTextField(
|
||||
controller: ctrlrNick,
|
||||
autofocus: true,
|
||||
labelText: AppLocalizations.of(context)!.yourDisplayName,
|
||||
validator: (value) {
|
||||
if (value.isEmpty) {
|
||||
|
@ -167,7 +168,7 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
|
|||
height: 20,
|
||||
),
|
||||
])),
|
||||
CwtchLabel(label: AppLocalizations.of(context)!.password1Label),
|
||||
CwtchLabel(label: AppLocalizations.of(context)!.newPassword),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:cwtch/cwtch_icons_icons.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cwtch/views/torstatusview.dart';
|
||||
import 'package:cwtch/widgets/contactrow.dart';
|
||||
|
@ -66,7 +67,7 @@ class _ContactsViewState extends State<ContactsView> {
|
|||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: _pushAddContact,
|
||||
tooltip: AppLocalizations.of(context)!.tooltipAddContact,
|
||||
child: const Icon(Icons.person_add_sharp),
|
||||
child: const Icon(CwtchIcons.person_add_alt_1_24px),
|
||||
),
|
||||
body: showSearchBar || Provider.of<ContactListState>(context).isFiltered ? _buildFilterable() : _buildContactList());
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'package:cwtch/cwtch_icons_icons.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cwtch/opaque.dart';
|
||||
|
@ -46,7 +47,7 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
|
|||
child: Column(children: [
|
||||
ListTile(
|
||||
title: Text(AppLocalizations.of(context)!.settingLanguage, style: TextStyle(color: settings.current().mainTextColor())),
|
||||
leading: Icon(Icons.language, color: settings.current().mainTextColor()),
|
||||
leading: Icon(CwtchIcons.change_language, color: settings.current().mainTextColor()),
|
||||
trailing: DropdownButton(
|
||||
value: Provider.of<Settings>(context).locale.languageCode,
|
||||
onChanged: (String? newValue) {
|
||||
|
@ -74,7 +75,9 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
|
|||
// Save Settings...
|
||||
saveSettings(context);
|
||||
},
|
||||
secondary: Icon(Icons.lightbulb_outline, color: settings.current().mainTextColor()),
|
||||
activeTrackColor: settings.theme.defaultButtonActiveColor(),
|
||||
inactiveTrackColor: settings.theme.defaultButtonDisabledColor(),
|
||||
secondary: Icon(CwtchIcons.change_theme, color: settings.current().mainTextColor()),
|
||||
),
|
||||
ListTile(
|
||||
title: Text(/*AppLocalizations.of(context)!.settingLanguage*/ "UI Columns", style: TextStyle(color: settings.current().mainTextColor())),
|
||||
|
@ -111,7 +114,9 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
|
|||
// Save Settings...
|
||||
saveSettings(context);
|
||||
},
|
||||
secondary: Icon(Icons.app_blocking, color: settings.current().mainTextColor()),
|
||||
activeTrackColor: settings.theme.defaultButtonActiveColor(),
|
||||
inactiveTrackColor: settings.theme.defaultButtonDisabledColor(),
|
||||
secondary: Icon(CwtchIcons.block_unknown, color: settings.current().mainTextColor()),
|
||||
),
|
||||
SwitchListTile(
|
||||
title: Text(AppLocalizations.of(context)!.experimentsEnabled, style: TextStyle(color: settings.current().mainTextColor())),
|
||||
|
@ -126,7 +131,9 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
|
|||
// Save Settings...
|
||||
saveSettings(context);
|
||||
},
|
||||
secondary: Icon(Icons.science, color: settings.current().mainTextColor()),
|
||||
activeTrackColor: settings.theme.defaultButtonActiveColor(),
|
||||
inactiveTrackColor: settings.theme.defaultButtonDisabledColor(),
|
||||
secondary: Icon(CwtchIcons.enable_experiments, color: settings.current().mainTextColor()),
|
||||
),
|
||||
Visibility(
|
||||
visible: settings.experimentsEnabled,
|
||||
|
@ -135,7 +142,7 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
|
|||
SwitchListTile(
|
||||
title: Text(AppLocalizations.of(context)!.enableGroups, style: TextStyle(color: settings.current().mainTextColor())),
|
||||
subtitle: Text(AppLocalizations.of(context)!.descriptionExperimentsGroups),
|
||||
value: settings.experiments.containsKey(TapirGroupsExperiment) && settings.experiments[TapirGroupsExperiment]!,
|
||||
value: settings.isExperimentEnabled(TapirGroupsExperiment),
|
||||
onChanged: (bool value) {
|
||||
if (value) {
|
||||
settings.enableExperiment(TapirGroupsExperiment);
|
||||
|
@ -145,7 +152,9 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
|
|||
// Save Settings...
|
||||
saveSettings(context);
|
||||
},
|
||||
secondary: Icon(Icons.group_sharp, color: settings.current().mainTextColor()),
|
||||
activeTrackColor: settings.theme.defaultButtonActiveColor(),
|
||||
inactiveTrackColor: settings.theme.defaultButtonDisabledColor(),
|
||||
secondary: Icon(CwtchIcons.enable_groups, color: settings.current().mainTextColor()),
|
||||
),
|
||||
],
|
||||
)),
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:cwtch/cwtch_icons_icons.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:cwtch/model.dart';
|
||||
import 'package:cwtch/widgets/buttontextfield.dart';
|
||||
|
@ -135,12 +136,12 @@ class _GroupSettingsViewState extends State<GroupSettingsView> {
|
|||
height: 20,
|
||||
),
|
||||
Tooltip(
|
||||
message: AppLocalizations.of(context)!.rejectGroupBtn,
|
||||
message: AppLocalizations.of(context)!.leaveGroup,
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
showAlertDialog(context);
|
||||
},
|
||||
icon: Icon(Icons.delete),
|
||||
icon: Icon(CwtchIcons.leave_group),
|
||||
label: Text(AppLocalizations.of(context)!.leaveGroup),
|
||||
))
|
||||
])
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:cwtch/cwtch_icons_icons.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cwtch/views/peersettingsview.dart';
|
||||
|
@ -49,7 +50,10 @@ class _MessageViewState extends State<MessageView> {
|
|||
//IconButton(icon: Icon(Icons.chat), onPressed: _pushContactSettings),
|
||||
//IconButton(icon: Icon(Icons.list), onPressed: _pushContactSettings),
|
||||
//IconButton(icon: Icon(Icons.push_pin), onPressed: _pushContactSettings),
|
||||
IconButton(icon: Icon(Icons.settings), tooltip: AppLocalizations.of(context)!.conversationSettings, onPressed: _pushContactSettings),
|
||||
IconButton(
|
||||
icon: Provider.of<ContactInfoState>(context, listen: false).isGroup == true ? Icon(CwtchIcons.group_settings_24px) : Icon(CwtchIcons.peer_settings_24px),
|
||||
tooltip: AppLocalizations.of(context)!.conversationSettings,
|
||||
onPressed: _pushContactSettings),
|
||||
],
|
||||
),
|
||||
body: Padding(padding: EdgeInsets.fromLTRB(8.0, 8.0, 8.0, 108.0), child: MessageList()),
|
||||
|
@ -134,11 +138,11 @@ class _MessageViewState extends State<MessageView> {
|
|||
focusedBorder: InputBorder.none,
|
||||
enabled: true,
|
||||
prefixIcon: IconButton(
|
||||
icon: Icon(Icons.insert_invitation, size: 24, color: Provider.of<Settings>(context).theme.mainTextColor()),
|
||||
icon: Icon(CwtchIcons.send_invite, size: 24, color: Provider.of<Settings>(context).theme.mainTextColor()),
|
||||
tooltip: "Send a contact or group invite",
|
||||
onPressed: () => _modalSendInvitation(context)),
|
||||
suffixIcon: IconButton(
|
||||
icon: Icon(Icons.send, size: 24, color: Provider.of<Settings>(context).theme.mainTextColor()),
|
||||
icon: Icon(CwtchIcons.send_24px, size: 24, color: Provider.of<Settings>(context).theme.mainTextColor()),
|
||||
tooltip: "Send Message",
|
||||
onPressed: _sendMessage,
|
||||
),
|
||||
|
@ -173,7 +177,9 @@ class _MessageViewState extends State<MessageView> {
|
|||
),
|
||||
ChangeNotifierProvider.value(
|
||||
value: Provider.of<ProfileInfoState>(ctx, listen: false),
|
||||
child: DropdownContacts(onChanged: (newVal) {
|
||||
child: DropdownContacts(filter: (contact) {
|
||||
return contact.onion != Provider.of<ContactInfoState>(context).onion;
|
||||
}, onChanged: (newVal) {
|
||||
setState(() {
|
||||
this.selectedContact = newVal;
|
||||
});
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'dart:convert';
|
||||
import 'package:cwtch/cwtch_icons_icons.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:cwtch/model.dart';
|
||||
import 'package:cwtch/widgets/buttontextfield.dart';
|
||||
|
@ -138,12 +139,14 @@ class _PeerSettingsViewState extends State<PeerSettingsView> {
|
|||
Provider.of<FlwtchState>(context, listen: false).cwtch.SendProfileEvent(profileOnion, setPeerAttributeJson);
|
||||
}
|
||||
},
|
||||
secondary: Icon(Icons.block, color: settings.current().mainTextColor()),
|
||||
activeTrackColor: settings.theme.defaultButtonActiveColor(),
|
||||
inactiveTrackColor: settings.theme.defaultButtonDisabledColor(),
|
||||
secondary: Icon(CwtchIcons.block_peer, color: settings.current().mainTextColor()),
|
||||
),
|
||||
ListTile(
|
||||
title: Text(AppLocalizations.of(context)!.savePeerHistory, style: TextStyle(color: settings.current().mainTextColor())),
|
||||
subtitle: Text(AppLocalizations.of(context)!.savePeerHistoryDescription),
|
||||
leading: Icon(Icons.history_sharp, color: settings.current().mainTextColor()),
|
||||
leading: Icon(CwtchIcons.peer_history, color: settings.current().mainTextColor()),
|
||||
trailing: DropdownButton(
|
||||
value: Provider.of<ContactInfoState>(context).savePeerHistory == "DefaultDeleteHistory"
|
||||
? AppLocalizations.of(context)!.dontSavePeerHistory
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:cwtch/cwtch_icons_icons.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cwtch/settings.dart';
|
||||
import 'package:cwtch/views/torstatusview.dart';
|
||||
|
@ -11,6 +12,7 @@ import 'package:provider/provider.dart';
|
|||
import '../main.dart';
|
||||
import '../model.dart';
|
||||
import '../opaque.dart';
|
||||
import '../torstatus.dart';
|
||||
import 'addeditprofileview.dart';
|
||||
import 'globalsettingsview.dart';
|
||||
|
||||
|
@ -57,10 +59,16 @@ class _ProfileMgrViewState extends State<ProfileMgrView> {
|
|||
Expanded(child: Text(AppLocalizations.of(context)!.titleManageProfiles, style: TextStyle(color: settings.current().mainTextColor())))
|
||||
]),
|
||||
actions: [
|
||||
IconButton(icon: TorIcon(), onPressed: _pushTorStatus),
|
||||
IconButton(
|
||||
icon: TorIcon(),
|
||||
onPressed: _pushTorStatus,
|
||||
tooltip: Provider.of<TorStatus>(context).progress == 100
|
||||
? AppLocalizations.of(context)!.networkStatusOnline
|
||||
: (Provider.of<TorStatus>(context).progress == 0 ? AppLocalizations.of(context)!.networkStatusDisconnected : AppLocalizations.of(context)!.networkStatusAttemptingTor),
|
||||
),
|
||||
IconButton(icon: Icon(Icons.bug_report_outlined), onPressed: _setLoggingLevelDebug),
|
||||
IconButton(
|
||||
icon: Icon(Icons.lock_open),
|
||||
icon: Icon(CwtchIcons.lock_open_24px),
|
||||
tooltip: AppLocalizations.of(context)!.tooltipUnlockProfiles,
|
||||
onPressed: _modalUnlockProfiles,
|
||||
),
|
||||
|
|
|
@ -3,6 +3,10 @@ import 'package:provider/provider.dart';
|
|||
|
||||
import '../model.dart';
|
||||
|
||||
bool noFilter(ContactInfoState peer) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Dropdown menu populated from Provider.of<ProfileInfoState>'s contact list
|
||||
// Includes both peers and groups; begins empty/nothing selected
|
||||
// Displays nicknames to UI but uses handles as values
|
||||
|
@ -10,8 +14,10 @@ import '../model.dart';
|
|||
class DropdownContacts extends StatefulWidget {
|
||||
DropdownContacts({
|
||||
required this.onChanged,
|
||||
this.filter = noFilter,
|
||||
});
|
||||
final Function(dynamic) onChanged;
|
||||
final bool Function(ContactInfoState) filter;
|
||||
|
||||
@override
|
||||
_DropdownContactsState createState() => _DropdownContactsState();
|
||||
|
@ -24,7 +30,7 @@ class _DropdownContactsState extends State<DropdownContacts> {
|
|||
Widget build(BuildContext context) {
|
||||
return DropdownButton(
|
||||
value: this.selected,
|
||||
items: Provider.of<ProfileInfoState>(context, listen: false).contactList.contacts.map<DropdownMenuItem<String>>((ContactInfoState contact) {
|
||||
items: Provider.of<ProfileInfoState>(context, listen: false).contactList.contacts.where(widget.filter).map<DropdownMenuItem<String>>((ContactInfoState contact) {
|
||||
return DropdownMenuItem<String>(value: contact.onion, child: Text(contact.nickname));
|
||||
}).toList(),
|
||||
onChanged: (String? newVal) {
|
||||
|
|
|
@ -50,7 +50,7 @@ class _ContactRowState extends State<ContactRow> {
|
|||
))),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(5.0),
|
||||
child: contact.isInvitation != null && contact.isInvitation
|
||||
child: contact.isInvitation == true
|
||||
? Wrap(direction: Axis.vertical, children: <Widget>[
|
||||
IconButton(
|
||||
padding: EdgeInsets.zero,
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:cwtch/cwtch_icons_icons.dart';
|
||||
import 'package:cwtch/widgets/malformedbubble.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../main.dart';
|
||||
|
@ -53,24 +55,33 @@ class InvitationBubbleState extends State<InvitationBubble> {
|
|||
style: TextStyle(fontSize: 9.0, color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor() : Provider.of<Settings>(context).theme.messageFromOtherTextColor())));
|
||||
|
||||
// todo: translations
|
||||
|
||||
// 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 = Provider.of<MessageState>(context).inviteNick == Provider.of<ProfileInfoState>(context).onion;
|
||||
if (selfInvite) {
|
||||
return MalformedBubble();
|
||||
}
|
||||
|
||||
var wdgMessage = fromMe
|
||||
? senderInviteChrome("You sent an invitation for", isGroup ? "a group" : Provider.of<MessageState>(context).message, myKey)
|
||||
: inviteChrome(isGroup ? AppLocalizations.of(context)!.inviteToGroup : "This is a contact suggestion for:", Provider.of<MessageState>(context).inviteNick,
|
||||
Provider.of<MessageState>(context).inviteTarget, myKey);
|
||||
? senderInviteChrome(AppLocalizations.of(context)!.sendAnInvitation,
|
||||
isGroup ? Provider.of<ProfileInfoState>(context).contactList.getContact(Provider.of<MessageState>(context).inviteTarget)!.nickname : Provider.of<MessageState>(context).message, myKey)
|
||||
: (inviteChrome(isGroup ? AppLocalizations.of(context)!.inviteToGroup : AppLocalizations.of(context)!.contactSuggestion, Provider.of<MessageState>(context).inviteNick,
|
||||
Provider.of<MessageState>(context).inviteTarget, myKey));
|
||||
|
||||
Widget wdgDecorations;
|
||||
if (fromMe) {
|
||||
wdgDecorations = MessageBubbleDecoration(ackd: Provider.of<MessageState>(context).ackd, errored: Provider.of<MessageState>(context).error, fromMe: fromMe, prettyDate: prettyDate);
|
||||
} else if (isAccepted) {
|
||||
wdgDecorations = Text("Accepted!");
|
||||
wdgDecorations = Text(AppLocalizations.of(context)!.accepted + '\u202F');
|
||||
} else if (this.rejected) {
|
||||
wdgDecorations = Text("Rejected.");
|
||||
wdgDecorations = Text(AppLocalizations.of(context)!.rejected + '\u202F');
|
||||
} else {
|
||||
wdgDecorations = Center(
|
||||
widthFactor: 1,
|
||||
child: Row(children: [
|
||||
Padding(padding: EdgeInsets.all(5), child: TextButton(child: Text("Reject"), onPressed: _btnReject)),
|
||||
Padding(padding: EdgeInsets.all(5), child: TextButton(child: Text("Accept"), onPressed: _btnAccept)),
|
||||
child: Wrap(children: [
|
||||
Padding(padding: EdgeInsets.all(5), child: TextButton(child: Text(AppLocalizations.of(context)!.rejectGroupBtn + '\u202F'), onPressed: _btnReject)),
|
||||
Padding(padding: EdgeInsets.all(5), child: TextButton(child: Text(AppLocalizations.of(context)!.acceptGroupBtn + '\u202F'), onPressed: _btnAccept)),
|
||||
]));
|
||||
}
|
||||
|
||||
|
@ -94,15 +105,16 @@ class InvitationBubbleState extends State<InvitationBubble> {
|
|||
widthFactor: 1.0,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(9.0),
|
||||
child: Row(mainAxisSize: MainAxisSize.min, children: [
|
||||
Center(widthFactor: 1, child: Padding(padding: EdgeInsets.all(4), child: Icon(Icons.group_add, size: 32))),
|
||||
child: Wrap(runAlignment: WrapAlignment.spaceEvenly, alignment: WrapAlignment.spaceEvenly, runSpacing: 1.0, crossAxisAlignment: WrapCrossAlignment.center, children: [
|
||||
Center(widthFactor: 1, child: Padding(padding: EdgeInsets.all(10.0), child: Icon(CwtchIcons.send_invite, size: 32))),
|
||||
Center(
|
||||
widthFactor: 1.0,
|
||||
child: Column(
|
||||
crossAxisAlignment: fromMe ? CrossAxisAlignment.end : CrossAxisAlignment.start,
|
||||
mainAxisAlignment: fromMe ? MainAxisAlignment.end : MainAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: fromMe ? [wdgMessage, wdgDecorations] : [wdgSender, wdgMessage, wdgDecorations])),
|
||||
widthFactor: 1.0,
|
||||
child: Column(
|
||||
crossAxisAlignment: fromMe ? CrossAxisAlignment.end : CrossAxisAlignment.start,
|
||||
mainAxisAlignment: fromMe ? MainAxisAlignment.end : MainAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: fromMe ? [wdgMessage, wdgDecorations] : [wdgSender, wdgMessage, wdgDecorations]),
|
||||
)
|
||||
])))));
|
||||
});
|
||||
}
|
||||
|
@ -128,55 +140,49 @@ class InvitationBubbleState extends State<InvitationBubble> {
|
|||
|
||||
// Construct an invite chrome for the sender
|
||||
Widget senderInviteChrome(String chrome, String targetName, String myKey) {
|
||||
return Center(
|
||||
widthFactor: 1,
|
||||
child: Row(children: [
|
||||
SelectableText(
|
||||
chrome,
|
||||
key: Key(myKey),
|
||||
focusNode: _focus,
|
||||
style: TextStyle(
|
||||
color: Provider.of<Settings>(context).theme.messageFromMeTextColor(),
|
||||
),
|
||||
textAlign: TextAlign.left,
|
||||
textWidthBasis: TextWidthBasis.longestLine,
|
||||
),
|
||||
SelectableText(
|
||||
targetName + '\u202F',
|
||||
key: Key(myKey),
|
||||
focusNode: _focus,
|
||||
style: TextStyle(
|
||||
color: Provider.of<Settings>(context).theme.messageFromMeTextColor(),
|
||||
),
|
||||
textAlign: TextAlign.left,
|
||||
textWidthBasis: TextWidthBasis.longestLine,
|
||||
)
|
||||
]));
|
||||
return Wrap(children: [
|
||||
SelectableText(
|
||||
chrome + '\u202F',
|
||||
style: TextStyle(
|
||||
color: Provider.of<Settings>(context).theme.messageFromMeTextColor(),
|
||||
),
|
||||
textAlign: TextAlign.left,
|
||||
maxLines: 2,
|
||||
textWidthBasis: TextWidthBasis.longestLine,
|
||||
),
|
||||
SelectableText(
|
||||
targetName + '\u202F',
|
||||
key: Key(myKey),
|
||||
style: TextStyle(
|
||||
color: Provider.of<Settings>(context).theme.messageFromMeTextColor(),
|
||||
),
|
||||
textAlign: TextAlign.left,
|
||||
maxLines: 2,
|
||||
textWidthBasis: TextWidthBasis.longestLine,
|
||||
)
|
||||
]);
|
||||
}
|
||||
|
||||
// Construct an invite chrome
|
||||
Widget inviteChrome(String chrome, String targetName, String targetId, String myKey) {
|
||||
return Center(
|
||||
widthFactor: 1,
|
||||
child: Row(children: [
|
||||
SelectableText(
|
||||
chrome,
|
||||
key: Key(myKey),
|
||||
focusNode: _focus,
|
||||
style: TextStyle(
|
||||
color: Provider.of<Settings>(context).theme.messageFromOtherTextColor(),
|
||||
),
|
||||
textAlign: TextAlign.left,
|
||||
textWidthBasis: TextWidthBasis.longestLine,
|
||||
),
|
||||
SelectableText(
|
||||
targetName,
|
||||
key: Key(myKey),
|
||||
focusNode: _focus,
|
||||
style: TextStyle(color: Provider.of<Settings>(context).theme.messageFromOtherTextColor()),
|
||||
textAlign: TextAlign.left,
|
||||
textWidthBasis: TextWidthBasis.longestLine,
|
||||
)
|
||||
]));
|
||||
return Wrap(children: [
|
||||
SelectableText(
|
||||
chrome + '\u202F',
|
||||
style: TextStyle(
|
||||
color: Provider.of<Settings>(context).theme.messageFromOtherTextColor(),
|
||||
),
|
||||
textAlign: TextAlign.left,
|
||||
textWidthBasis: TextWidthBasis.longestLine,
|
||||
maxLines: 2,
|
||||
),
|
||||
SelectableText(
|
||||
targetName + '\u202F',
|
||||
key: Key(myKey),
|
||||
style: TextStyle(color: Provider.of<Settings>(context).theme.messageFromOtherTextColor()),
|
||||
textAlign: TextAlign.left,
|
||||
maxLines: 2,
|
||||
textWidthBasis: TextWidthBasis.longestLine,
|
||||
)
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:ffi';
|
||||
|
||||
import 'package:cwtch/cwtch_icons_icons.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../settings.dart';
|
||||
|
||||
final Color malformedColor = Color(0xFFE85DA1);
|
||||
|
||||
|
@ -40,15 +35,10 @@ class MalformedBubbleState extends State<MalformedBubble> {
|
|||
widthFactor: 1,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(4),
|
||||
child: Image(
|
||||
image: AssetImage("assets/core/broken_heart_24.png"),
|
||||
filterQuality: FilterQuality.medium,
|
||||
// We need some theme specific blending here...we might want to consider making this a theme level attribute
|
||||
colorBlendMode: BlendMode.srcIn,
|
||||
color: Provider.of<Settings>(context).theme.mainTextColor(),
|
||||
isAntiAlias: false,
|
||||
width: 32,
|
||||
height: 32))),
|
||||
child: Icon(
|
||||
CwtchIcons.favorite_black_24dp_broken,
|
||||
size: 24,
|
||||
))),
|
||||
Center(
|
||||
widthFactor: 1.0,
|
||||
child: Column(
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import '../model.dart';
|
||||
import '../settings.dart';
|
||||
import 'messagerow.dart';
|
||||
|
@ -15,24 +16,44 @@ class _MessageListState extends State<MessageList> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext outerContext) {
|
||||
bool showEphemeralWarning = (Provider.of<ContactInfoState>(context).isGroup == false && Provider.of<ContactInfoState>(context).savePeerHistory != "SaveHistory");
|
||||
bool showOfflineWarning = Provider.of<ContactInfoState>(context).isOnline() == false;
|
||||
bool showMessageWarning = showEphemeralWarning || showOfflineWarning;
|
||||
return RepaintBoundary(
|
||||
child: Container(
|
||||
child: Scrollbar(
|
||||
isAlwaysShown: true,
|
||||
controller: ctrlr1,
|
||||
child: Container(
|
||||
child: Column(children: [
|
||||
Visibility(
|
||||
visible: showMessageWarning,
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(5.0),
|
||||
color: Provider.of<Settings>(context).theme.defaultButtonActiveColor(),
|
||||
child: showOfflineWarning
|
||||
? Text(Provider.of<ContactInfoState>(context).isGroup ? AppLocalizations.of(context)!.serverConnectivityDisconnected : AppLocalizations.of(context)!.peerOfflineMessage,
|
||||
textAlign: TextAlign.center)
|
||||
// Only show the ephemeral status for peer conversations, not for groups...
|
||||
: (showEphemeralWarning
|
||||
? Text(AppLocalizations.of(context)!.chatHistoryDefault, textAlign: TextAlign.center)
|
||||
:
|
||||
// We are not allowed to put null here, so put an empty text widge
|
||||
Text("")),
|
||||
)),
|
||||
Expanded(
|
||||
child: Scrollbar(
|
||||
controller: ctrlr1,
|
||||
child: Container(
|
||||
// Only show broken heart is the contact is offline...
|
||||
decoration: BoxDecoration(
|
||||
image: Provider.of<ContactInfoState>(outerContext).isOnline()
|
||||
? null
|
||||
: DecorationImage(
|
||||
fit: BoxFit.contain,
|
||||
fit: BoxFit.scaleDown,
|
||||
alignment: Alignment.center,
|
||||
image: AssetImage("assets/core/negative_heart_512px.png"),
|
||||
colorFilter: ColorFilter.mode(Provider.of<Settings>(context).theme.mainTextColor(), BlendMode.srcIn))),
|
||||
colorFilter: ColorFilter.mode(Provider.of<Settings>(context).theme.hilightElementTextColor(), BlendMode.srcIn))),
|
||||
child: ListView.builder(
|
||||
controller: ctrlr1,
|
||||
itemCount: Provider.of<ContactInfoState>(outerContext).totalMessages,
|
||||
reverse: true,
|
||||
reverse: true, // NOTE: There seems to be a bug in flutter that corrects the mouse wheel scroll, but not the drag direction...
|
||||
itemBuilder: (itemBuilderContext, index) {
|
||||
var trueIndex = Provider.of<ContactInfoState>(outerContext).totalMessages - index - 1;
|
||||
return ChangeNotifierProvider(
|
||||
|
@ -51,7 +72,7 @@ class _MessageListState extends State<MessageList> {
|
|||
return RepaintBoundary(child: MessageRow(key: Provider.of<ContactInfoState>(bcontext).getMessageKey(idx)));
|
||||
});
|
||||
},
|
||||
),
|
||||
))));
|
||||
))))
|
||||
])));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,10 +31,8 @@ class _MessageRowState extends State<MessageRow> {
|
|||
fromMe = false;
|
||||
}
|
||||
|
||||
Widget wdgBubble = Flexible(
|
||||
flex: 3,
|
||||
fit: FlexFit.loose,
|
||||
child: malformed ? MalformedBubble() : (Provider.of<MessageState>(context).loaded == true ? widgetForOverlay(Provider.of<MessageState>(context).overlay) : MessageLoadingBubble()));
|
||||
Widget wdgBubble =
|
||||
Flexible(flex: 3, fit: FlexFit.loose, child: Provider.of<MessageState>(context).loaded == true ? widgetForOverlay(Provider.of<MessageState>(context).overlay) : MessageLoadingBubble());
|
||||
Widget wdgIcons = Icon(Icons.delete_forever_outlined, color: Provider.of<Settings>(context).theme.dropShadowColor());
|
||||
Widget wdgSpacer = Expanded(child: SizedBox(width: 60, height: 10));
|
||||
var widgetRow = <Widget>[];
|
||||
|
@ -96,7 +94,10 @@ class _MessageRowState extends State<MessageRow> {
|
|||
final setPeerAttributeJson = jsonEncode(setPeerAttribute);
|
||||
Provider.of<FlwtchState>(context, listen: false).cwtch.SendProfileEvent(profileOnion, setPeerAttributeJson);
|
||||
|
||||
final snackBar = SnackBar(content: Text(AppLocalizations.of(context)!.successfullAddedContact));
|
||||
final snackBar = SnackBar(
|
||||
content: Text(AppLocalizations.of(context)!.successfullAddedContact),
|
||||
duration: Duration(seconds: 2),
|
||||
);
|
||||
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:cwtch/cwtch_icons_icons.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../settings.dart';
|
||||
|
@ -5,7 +6,7 @@ import '../settings.dart';
|
|||
// Provides a styled Password Input Field for use in Form Widgets.
|
||||
// Callers must provide a text controller, label helper text and a validator.
|
||||
class CwtchPasswordField extends StatefulWidget {
|
||||
CwtchPasswordField({required this.controller, required this.validator, this.action, this.autofocus = true});
|
||||
CwtchPasswordField({required this.controller, required this.validator, this.action, this.autofocus = false});
|
||||
final TextEditingController controller;
|
||||
final FormFieldValidator validator;
|
||||
final Function(String)? action;
|
||||
|
@ -43,7 +44,7 @@ class _CwtchTextFieldState extends State<CwtchPasswordField> {
|
|||
obscureText = !obscureText;
|
||||
});
|
||||
},
|
||||
icon: Icon((obscureText ? Icons.remove_red_eye : Icons.remove_red_eye_outlined), semanticLabel: label),
|
||||
icon: Icon((obscureText ? CwtchIcons.eye_closed : CwtchIcons.eye_open), semanticLabel: label),
|
||||
tooltip: label,
|
||||
color: theme.current().mainTextColor(),
|
||||
highlightColor: theme.current().defaultButtonColor(),
|
||||
|
|
|
@ -7,11 +7,12 @@ doNothing(String x) {}
|
|||
// Provides a styled Text Field for use in Form Widgets.
|
||||
// Callers must provide a text controller, label helper text and a validator.
|
||||
class CwtchTextField extends StatefulWidget {
|
||||
CwtchTextField({required this.controller, required this.labelText, this.validator = null, this.onChanged = doNothing});
|
||||
CwtchTextField({required this.controller, required this.labelText, this.validator = null, this.autofocus = false, this.onChanged = doNothing});
|
||||
final TextEditingController controller;
|
||||
final String labelText;
|
||||
final FormFieldValidator? validator;
|
||||
final Function(String) onChanged;
|
||||
final bool autofocus;
|
||||
|
||||
@override
|
||||
_CwtchTextFieldState createState() => _CwtchTextFieldState();
|
||||
|
@ -25,6 +26,7 @@ class _CwtchTextFieldState extends State<CwtchTextField> {
|
|||
controller: widget.controller,
|
||||
validator: widget.validator,
|
||||
onChanged: widget.onChanged,
|
||||
autofocus: widget.autofocus,
|
||||
decoration: InputDecoration(
|
||||
labelText: widget.labelText,
|
||||
labelStyle: TextStyle(color: theme.current().mainTextColor(), backgroundColor: theme.current().textfieldBackgroundColor()),
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:cwtch/cwtch_icons_icons.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
|
@ -16,13 +17,9 @@ class _TorIconState extends State<TorIcon> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return RepaintBoundary(
|
||||
child: Image(
|
||||
image: AssetImage(Provider.of<TorStatus>(context).progress == 0
|
||||
? "assets/core/Tor_OFF.png"
|
||||
: (Provider.of<TorStatus>(context).progress == 100 ? "assets/core/Tor_icon.png" : "assets/core/Tor_Booting_up.png")),
|
||||
// Color the onion per the text color...
|
||||
child: Icon(
|
||||
Provider.of<TorStatus>(context).progress == 0 ? CwtchIcons.onion_off : (Provider.of<TorStatus>(context).progress == 100 ? CwtchIcons.onion_on : CwtchIcons.onion_waiting),
|
||||
color: Provider.of<Settings>(context).theme.mainTextColor(),
|
||||
colorBlendMode: BlendMode.srcIn,
|
||||
semanticLabel: Provider.of<TorStatus>(context).progress == 100
|
||||
? AppLocalizations.of(context)!.networkStatusOnline
|
||||
: (Provider.of<TorStatus>(context).progress == 0 ? AppLocalizations.of(context)!.networkStatusDisconnected : AppLocalizations.of(context)!.networkStatusAttemptingTor),
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
// clang-format off
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <window_size/window_size_plugin.h>
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
// clang-format off
|
||||
|
||||
#ifndef GENERATED_PLUGIN_REGISTRANT_
|
||||
#define GENERATED_PLUGIN_REGISTRANT_
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ packages:
|
|||
name: async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.5.0"
|
||||
version: "2.7.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -191,7 +191,7 @@ packages:
|
|||
name: meta
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
version: "1.4.0"
|
||||
nested:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -392,7 +392,7 @@ packages:
|
|||
name: test_api
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.3.0"
|
||||
version: "0.4.0"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -450,7 +450,7 @@ packages:
|
|||
name: xml
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.1.1"
|
||||
version: "5.1.2"
|
||||
sdks:
|
||||
dart: ">=2.13.0 <3.0.0"
|
||||
flutter: ">=1.20.0"
|
||||
|
|
|
@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
|||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||
# Read more about iOS versioning at
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
version: 1.0.0+9
|
||||
version: 1.0.0+10
|
||||
|
||||
environment:
|
||||
sdk: ">=2.12.0 <3.0.0"
|
||||
|
@ -95,6 +95,11 @@ flutter:
|
|||
- assets/profiles/
|
||||
- assets/servers/
|
||||
|
||||
fonts:
|
||||
- family: CwtchIcons
|
||||
fonts:
|
||||
- asset: assets/fonts/CwtchIcons.ttf
|
||||
|
||||
# To add custom fonts to your application, add a fonts section here,
|
||||
# in this "flutter" section. Each entry in this list should have a
|
||||
# "family" key with the font family name, and a "fonts" key with a
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
cmake_minimum_required(VERSION 3.15)
|
||||
project(flutter_app LANGUAGES CXX)
|
||||
project(cwtch LANGUAGES CXX)
|
||||
|
||||
set(BINARY_NAME "flutter_app")
|
||||
set(BINARY_NAME "cwtch")
|
||||
|
||||
cmake_policy(SET CMP0063 NEW)
|
||||
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <window_size/window_size_plugin.h>
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
WindowSizePluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("WindowSizePlugin"));
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
window_size
|
||||
)
|
||||
|
||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||
|
|
|
@ -52,7 +52,16 @@ END
|
|||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDI_APP_ICON ICON "resources\\app_icon.ico"
|
||||
IDI_APP_ICON_LG ICON "resources\\knot_256.ico"
|
||||
IDI_APP_ICON_SM ICON "resources\\knot_64.ico"
|
||||
|
||||
IDI_APP_ICON_256 ICON "resources\\knot_256.ico"
|
||||
IDI_APP_ICON_128 ICON "resources\\knot_128.ico"
|
||||
IDI_APP_ICON_64 ICON "resources\\knot_64.ico"
|
||||
IDI_APP_ICON_48 ICON "resources\\knot_48.ico"
|
||||
IDI_APP_ICON_32 ICON "resources\\knot_32.ico"
|
||||
IDI_APP_ICON_16 ICON "resources\\knot_16.ico"
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -89,13 +98,13 @@ BEGIN
|
|||
BEGIN
|
||||
BLOCK "040904e4"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "com.example" "\0"
|
||||
VALUE "FileDescription", "A new Flutter project." "\0"
|
||||
VALUE "CompanyName", "Open Privacy Research Society" "\0"
|
||||
VALUE "FileDescription", "Cwtch Instant Messenger" "\0"
|
||||
VALUE "FileVersion", VERSION_AS_STRING "\0"
|
||||
VALUE "InternalName", "flutter_app" "\0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2021 com.example. All rights reserved." "\0"
|
||||
VALUE "OriginalFilename", "flutter_app.exe" "\0"
|
||||
VALUE "ProductName", "flutter_app" "\0"
|
||||
VALUE "InternalName", "cwtch" "\0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2021 Open Privacy Research Society. All rights reserved." "\0"
|
||||
VALUE "OriginalFilename", "cwtch.exe" "\0"
|
||||
VALUE "ProductName", "Cwtch" "\0"
|
||||
VALUE "ProductVersion", VERSION_AS_STRING "\0"
|
||||
END
|
||||
END
|
||||
|
|
|
@ -30,7 +30,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
|
|||
FlutterWindow window(&run_loop, project);
|
||||
Win32Window::Point origin(10, 10);
|
||||
Win32Window::Size size(1280, 720);
|
||||
if (!window.CreateAndShow(L"flutter_app", origin, size)) {
|
||||
if (!window.CreateAndShow(L"cwtch", origin, size)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
window.SetQuitOnClose(true);
|
||||
|
|
|
@ -2,7 +2,16 @@
|
|||
// Microsoft Visual C++ generated include file.
|
||||
// Used by Runner.rc
|
||||
//
|
||||
#define IDI_APP_ICON 101
|
||||
#define IDI_APP_ICON_LG 101
|
||||
#define IDI_APP_ICON_SM 102
|
||||
|
||||
#define IDI_APP_ICON_256 103
|
||||
#define IDI_APP_ICON_128 104
|
||||
#define IDI_APP_ICON_64 105
|
||||
#define IDI_APP_ICON_48 106
|
||||
#define IDI_APP_ICON_32 107
|
||||
#define IDI_APP_ICON_16 108
|
||||
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
|
|
Before Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 66 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 9.4 KiB |
After Width: | Height: | Size: 17 KiB |
|
@ -1,4 +1,5 @@
|
|||
#include "win32_window.h"
|
||||
#include "winuser.h"
|
||||
|
||||
#include <flutter_windows.h>
|
||||
|
||||
|
@ -70,19 +71,49 @@ WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr;
|
|||
|
||||
const wchar_t* WindowClassRegistrar::GetWindowClass() {
|
||||
if (!class_registered_) {
|
||||
WNDCLASS window_class{};
|
||||
WNDCLASSEX window_class{};
|
||||
window_class.cbSize = sizeof(WNDCLASSEX);
|
||||
window_class.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
||||
window_class.lpszClassName = kWindowClassName;
|
||||
window_class.style = CS_HREDRAW | CS_VREDRAW;
|
||||
window_class.cbClsExtra = 0;
|
||||
window_class.cbWndExtra = 0;
|
||||
window_class.hInstance = GetModuleHandle(nullptr);
|
||||
int icon_sz = GetSystemMetrics(SM_CXICON);
|
||||
int iconh_id = IDI_APP_ICON_32;
|
||||
if (icon_sz > 128) {
|
||||
iconh_id = IDI_APP_ICON_256;
|
||||
} else if (icon_sz > 64) {
|
||||
iconh_id = IDI_APP_ICON_128;
|
||||
} else if (icon_sz > 48) {
|
||||
iconh_id = IDI_APP_ICON_64;
|
||||
} else if (icon_sz > 32) {
|
||||
iconh_id = IDI_APP_ICON_48;
|
||||
}
|
||||
window_class.hIcon =
|
||||
LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON));
|
||||
LoadIcon(window_class.hInstance, MAKEINTRESOURCE(iconh_id));
|
||||
|
||||
|
||||
int icon_sm_sz = GetSystemMetrics(SM_CXSMICON);
|
||||
int iconsmh_id = IDI_APP_ICON_16;
|
||||
if (icon_sm_sz > 128) {
|
||||
iconsmh_id = IDI_APP_ICON_256;
|
||||
} else if (icon_sm_sz > 64) {
|
||||
iconsmh_id = IDI_APP_ICON_128;
|
||||
} else if (icon_sm_sz > 48) {
|
||||
iconsmh_id = IDI_APP_ICON_64;
|
||||
} else if (icon_sm_sz > 32) {
|
||||
iconsmh_id = IDI_APP_ICON_48;
|
||||
} else if (icon_sm_sz > 16) {
|
||||
iconsmh_id = IDI_APP_ICON_32;
|
||||
}
|
||||
window_class.hIconSm =
|
||||
LoadIcon(window_class.hInstance, MAKEINTRESOURCE(iconsmh_id));
|
||||
|
||||
window_class.hbrBackground = 0;
|
||||
window_class.lpszMenuName = nullptr;
|
||||
window_class.lpfnWndProc = Win32Window::WndProc;
|
||||
RegisterClass(&window_class);
|
||||
RegisterClassEx(&window_class);
|
||||
class_registered_ = true;
|
||||
}
|
||||
return kWindowClassName;
|
||||
|
|