Merge branch 'trunk' into opaqueBlock
continuous-integration/drone/pr Build is passing Details

This commit is contained in:
Sarah Jamie Lewis 2021-06-24 11:20:34 -07:00
commit 93dbba5f15
15 changed files with 199 additions and 107 deletions

View File

@ -28,9 +28,7 @@ steps:
- name: deps - name: deps
path: /root/.pub-cache path: /root/.pub-cache
commands: commands:
- wget https://git.openprivacy.ca/openprivacy/buildfiles/raw/master/tor/tor - ./fetch-tor.sh
- wget https://git.openprivacy.ca/openprivacy/buildfiles/raw/master/tor/torrc
- chmod a+x tor
- echo `git describe --tags` > VERSION - echo `git describe --tags` > VERSION
- echo `date +%G-%m-%d-%H-%M` > BUILDDATE - echo `date +%G-%m-%d-%H-%M` > BUILDDATE
- flutter pub get - flutter pub get
@ -62,7 +60,7 @@ steps:
- cp linux/libCwtch.so deploy/linux/lib/ - cp linux/libCwtch.so deploy/linux/lib/
# should not be needed, should be in data/flutter_assets and work from there # 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 /sdks/flutter/bin/cache/artifacts/engine/linux-x64/icudtl.dat deploy/linux
- cp tor deploy/linux - cp linux/tor deploy/linux
- cd deploy - cd deploy
- mv linux cwtch - mv linux cwtch
- tar -czf cwtch-`cat ../VERSION`.tar.gz cwtch - tar -czf cwtch-`cat ../VERSION`.tar.gz cwtch
@ -215,45 +213,56 @@ steps:
- name: fetch - name: fetch
image: openpriv/flutter-desktop:windows-sdk30-fdev2.3rc image: openpriv/flutter-desktop:windows-sdk30-fdev2.3rc
commands: commands:
- powershell -command "Invoke-WebRequest -Uri https://www.torproject.org/dist/torbrowser/10.0.16/tor-win32-0.4.5.7.zip -OutFile tor.zip" - powershell -command "Invoke-WebRequest -Uri https://dist.torproject.org/torbrowser/10.0.18/tor-win64-0.4.5.9.zip -OutFile tor.zip"
- powershell -command "if ((Get-FileHash tor.zip -Algorithm sha512).Hash -ne '2b7d683f036d0fec149f1d2bdfcf5b7ef4c337005a2b685c056b00047fdb2b57d4c25b8559ad7ef5c7a030b273934be82a9f83ef6e391f5d7d13d8d6c83e8048' ) { Write-Error 'tor.zip sha512sum mismatch' }" - powershell -command "if ((Get-FileHash tor.zip -Algorithm sha512).Hash -ne '72764eb07ad8ab511603aba0734951ca003989f5f4686af91ba220217b4a8a4bcc5f571b59f52c847932f6efedf847b111621983050fcddbb8099d43ca66fb07' ) { Write-Error 'tor.zip sha512sum mismatch' }"
- git describe --tags > VERSION - git describe --tags > VERSION
- powershell -command "Get-Date -Format 'yyyy-MM-dd-HH-mm'" > BUILDDATE - powershell -command "Get-Date -Format 'yyyy-MM-dd-HH-mm'" > BUILDDATE
- .\fetch-libcwtch-go.ps1 - .\fetch-libcwtch-go.ps1
-
- name: build-windows - name: build-windows
image: openpriv/flutter-desktop:windows-sdk30-fdev2.3rc image: openpriv/flutter-desktop:windows-sdk30-fdev2.3rc
environment:
pfx:
from_secret: pfx
pfx_pass:
from_secret: pfx_pass
commands: commands:
- move pubspec.yaml pubspec.yaml.orig
- (Get-Content -path pubspec.yaml.orig -Raw) -Replace 'pfx_pass',"$Env:pfx_pass" | Set-Content -path pubspec.yaml
- flutter pub get - flutter pub get
# flwtch-`cat VERSION`-`cat BUILDDATE`
- $Env:buildname = 'flwtch-win-'
- $Env:version += type .\VERSION - $Env:version += type .\VERSION
- $Env:buildname += $Env:version
- $Env:buildname += '-'
- $Env:builddate += type .\BUILDDATE - $Env:builddate += type .\BUILDDATE
- $Env:buildname += $Env:builddate - $Env:buildname = 'flwtch-win-' + $Env:version + '-' + $Env:builddate
- $Env:builddir += $Env:buildname - $Env:builddir = $Env:buildname
- $Env:zip = 'cwtch-' - $Env:zip = 'deploy\\' + $Env:builddir +'\\cwtch-' + $Env:version + '.zip'
- $Env:zip += $Env:version - $Env:zipsha = $Env:zip + '.sha512'
- $Env:zip += '.zip' - $Env:msix = 'cwtch-install-' + $Env:version + '.msix'
- $Env:sha = $Env:zip - $Env:msixsha = $Env:msix + '.sha512'
- $Env:sha += '.sha512' - $Env:releasedir = "build\\windows\\runner\\Release\\"
- echo $Env:releasedir
- echo $Env:builddir
- echo $Env:zip
- flutter build windows --dart-define BUILD_VER=$Env:version --dart-define BUILD_DATE=$Env:builddate - flutter build windows --dart-define BUILD_VER=$Env:version --dart-define BUILD_DATE=$Env:builddate
- mkdir deploy - copy windows\libCwtch.dll $Env:releasedir
- 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 # 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/google/flutter-desktop-embedding/issues/587
# https://github.com/flutter/flutter/issues/53167 # 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.dll $Env:releasedir
- 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\vcruntime140_1.dll $Env:releasedir
- copy C:\BuildTools\VC\Redist\MSVC\14.29.30036\x64\Microsoft.VC142.CRT\msvcp140.dll $Env:builddir - copy C:\BuildTools\VC\Redist\MSVC\14.29.30036\x64\Microsoft.VC142.CRT\msvcp140.dll $Env:releasedir
- powershell -command "Expand-Archive -Path tor.zip -DestinationPath $Env:builddir\Tor" - powershell -command "Expand-Archive -Path tor.zip -DestinationPath $Env:releasedir\Tor"
- powershell -command "Compress-Archive -Path $Env:builddir -DestinationPath $Env:zip" - dir $Env:releasedir
- powershell -command "(Get-FileHash *.zip -Algorithm sha512).Hash" > $Env:sha - echo $Env:pfx > codesign.pfx.b64
- certutil -decode codesign.pfx.b64 codesign.pfx
- flutter pub run msix:create
- mkdir deploy
- mkdir deploy\$Env:builddir - mkdir deploy\$Env:builddir
- move $Env:zip deploy\$Env:builddir - dir deploy
- move $Env:sha deploy\$Env:builddir - powershell -command "move $Env:releasedir\cwtch.msix deploy\$Env:builddir\$Env:msix"
- move $Env:releasedir $Env:builddir
- powershell -command "Compress-Archive -Path $Env:builddir -DestinationPath $Env:zip"
#- powershell -command "move $Env:zip deploy\$Env:builddir\$Env:zip"
#- powershell -command "(Get-FileHash $Env:zip -Algorithm sha512).Hash" > ${Env:zipsha}
- name: deploy-windows - name: deploy-windows
image: openpriv/flutter-desktop:windows-sdk30-fdev2.3rc image: openpriv/flutter-desktop:windows-sdk30-fdev2.3rc

View File

@ -1 +1 @@
v0.0.2-87-gc6f1c4d-2021-06-17-22-45 v0.0.2-104-gc1b7e4c-2021-06-22-23-59

View File

@ -55,8 +55,9 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) :
if (Cwtch.startCwtch(appDir, torPath) != 0.toLong()) return Result.failure() if (Cwtch.startCwtch(appDir, torPath) != 0.toLong()) return Result.failure()
// infinite coroutine :) Log.i("FlwtchWorker.kt", "startCwtch success, starting coroutine AppbusEvent loop...")
while(true) { while(true) {
Log.i("FlwtchWorker.kt", "while(true)getAppbusEvent()")
val evt = MainActivity.AppbusEvent(Cwtch.getAppBusEvent()) val evt = MainActivity.AppbusEvent(Cwtch.getAppBusEvent())
if (evt.EventType == "NewMessageFromPeer" || evt.EventType == "NewMessageFromGroup") { if (evt.EventType == "NewMessageFromPeer" || evt.EventType == "NewMessageFromGroup") {
val data = JSONObject(evt.Data) val data = JSONObject(evt.Data)
@ -180,8 +181,8 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) :
} }
"DeleteProfile" -> { "DeleteProfile" -> {
val profile = (a.get("ProfileOnion") as? String) ?: "" val profile = (a.get("ProfileOnion") as? String) ?: ""
val groupHandle = (a.get("pass") as? String) ?: "" val pass = (a.get("pass") as? String) ?: ""
Cwtch.deleteProfile(profile, groupHandle) Cwtch.deleteProfile(profile, pass)
} }
"LeaveConversation" -> { "LeaveConversation" -> {
val profile = (a.get("ProfileOnion") as? String) ?: "" val profile = (a.get("ProfileOnion") as? String) ?: ""
@ -213,11 +214,20 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) :
val id = "flwtch" val id = "flwtch"
val title = "Flwtch" val title = "Flwtch"
val cancel = "Shut down"//todo: translate val cancel = "Shut down"//todo: translate
val channelId =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createForegroundNotificationChannel(id, id)
} 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)
""
}
// This PendingIntent can be used to cancel the worker // This PendingIntent can be used to cancel the worker
val intent = WorkManager.getInstance(applicationContext) val intent = WorkManager.getInstance(applicationContext)
.createCancelPendingIntent(getId()) .createCancelPendingIntent(getId())
val notification = NotificationCompat.Builder(applicationContext, id) val notification = NotificationCompat.Builder(applicationContext, channelId)
.setContentTitle(title) .setContentTitle(title)
.setTicker(title) .setTicker(title)
.setContentText(progress) .setContentText(progress)
@ -231,10 +241,18 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) :
return ForegroundInfo(101, notification) return ForegroundInfo(101, notification)
} }
@RequiresApi(Build.VERSION_CODES.O)
private fun createForegroundNotificationChannel(channelId: String, channelName: String): String{
val chan = NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_NONE)
chan.lightColor = Color.MAGENTA
chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
notificationManager.createNotificationChannel(chan)
return channelId
}
@RequiresApi(Build.VERSION_CODES.O) @RequiresApi(Build.VERSION_CODES.O)
private fun createMessageNotificationChannel(channelId: String, channelName: String): String{ private fun createMessageNotificationChannel(channelId: String, channelName: String): String{
val chan = NotificationChannel(channelId, val chan = NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH)
channelName, NotificationManager.IMPORTANCE_HIGH)
chan.lightColor = Color.MAGENTA chan.lightColor = Color.MAGENTA
chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
notificationManager.createNotificationChannel(chan) notificationManager.createNotificationChannel(chan)

View File

@ -7,40 +7,23 @@ import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import androidx.annotation.NonNull import androidx.annotation.NonNull
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.os.Looper
import android.util.Log import android.util.Log
import android.view.Window import android.view.Window
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.localbroadcastmanager.content.LocalBroadcastManager import androidx.localbroadcastmanager.content.LocalBroadcastManager
import androidx.work.* import androidx.work.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.flutter.embedding.android.SplashScreen import io.flutter.embedding.android.SplashScreen
import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result import io.flutter.plugin.common.MethodChannel.Result
import cwtch.Cwtch
import io.flutter.plugin.common.EventChannel
import kotlin.concurrent.thread
import org.json.JSONObject import org.json.JSONObject
import java.io.File
import java.time.Duration
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
class MainActivity: FlutterActivity() { class MainActivity: FlutterActivity() {
override fun provideSplashScreen(): SplashScreen? = SplashView() override fun provideSplashScreen(): SplashScreen? = SplashView()
// Channel to get app info // Channel to get app info
@ -56,6 +39,10 @@ class MainActivity: FlutterActivity() {
// Channel to trigger contactview when an external notification is clicked // Channel to trigger contactview when an external notification is clicked
private val CHANNEL_NOTIF_CLICK = "im.cwtch.flwtch/notificationClickHandler" private val CHANNEL_NOTIF_CLICK = "im.cwtch.flwtch/notificationClickHandler"
// WorkManager tag applied to all Start() infinite coroutines
val WORKER_TAG = "cwtchEventBusWorker"
private var myReceiver: MyBroadcastReceiver? = null
private var methodChan: MethodChannel? = null private var methodChan: MethodChannel? = null
override fun onNewIntent(intent: Intent) { override fun onNewIntent(intent: Intent) {
@ -106,42 +93,28 @@ class MainActivity: FlutterActivity() {
// in case the ForegroundService is still running. in both cases, however, we *do* want to re-register // in case the ForegroundService is still running. in both cases, however, we *do* want to re-register
// the eventbus listener. // the eventbus listener.
if (call.method == "Start") { if (call.method == "Start") {
val workerTag = "cwtchEventBusWorker"
val uniqueTag = argmap["torPath"] ?: "nullEventBus" val uniqueTag = argmap["torPath"] ?: "nullEventBus"
// note: because the ForegroundService is specified as UniquePeriodicWork, it can't actually get // note: because the ForegroundService is specified as UniquePeriodicWork, it can't actually get
// accidentally duplicated. however, we still need to manually check if it's running or not, so // accidentally duplicated. however, we still need to manually check if it's running or not, so
// that we can divert this method call to ReconnectCwtchForeground instead if so. // that we can divert this method call to ReconnectCwtchForeground instead if so.
val works = WorkManager.getInstance(this).getWorkInfosByTag(workerTag).get() val works = WorkManager.getInstance(this).getWorkInfosByTag(WORKER_TAG).get()
var alreadyRunning = false
for (workInfo in works) { for (workInfo in works) {
if (workInfo.tags.contains(uniqueTag)) { Log.i("handleCwtch:WorkManager", "$workInfo")
if (workInfo.state == WorkInfo.State.RUNNING || workInfo.state == WorkInfo.State.ENQUEUED) { if (!workInfo.tags.contains(uniqueTag)) {
alreadyRunning = true Log.i("handleCwtch:WorkManager", "canceling ${workInfo.id} bc tags don't include $uniqueTag")
}
} else {
WorkManager.getInstance(this).cancelWorkById(workInfo.id) WorkManager.getInstance(this).cancelWorkById(workInfo.id)
} }
} }
WorkManager.getInstance(this).pruneWork()
// register our eventbus listener. note that we observe any/all work according to its tag, which Log.i("MainActivity.kt", "Start() launching foregroundservice")
// results in an implicit "reconnection" to old service threads even after frontend restarts // this is where the eventbus ForegroundService gets launched. WorkManager should keep it alive after this
val mc = MethodChannel(flutterEngine?.dartExecutor?.binaryMessenger, CWTCH_EVENTBUS) val data: Data = Data.Builder().putString(FlwtchWorker.KEY_METHOD, call.method).putString(FlwtchWorker.KEY_ARGS, JSONObject(argmap).toString()).build()
val filter = IntentFilter("im.cwtch.flwtch.broadcast.SERVICE_EVENT_BUS") // 15 minutes is the shortest interval you can request
LocalBroadcastManager.getInstance(applicationContext).registerReceiver(MyBroadcastReceiver(mc), filter) val workRequest = PeriodicWorkRequestBuilder<FlwtchWorker>(15, TimeUnit.MINUTES).setInputData(data).addTag(WORKER_TAG).addTag(uniqueTag).build()
WorkManager.getInstance(this).enqueueUniquePeriodicWork("req_$uniqueTag", ExistingPeriodicWorkPolicy.REPLACE, workRequest)
if (alreadyRunning) { return
Log.i("MainActivity.kt", "diverting Start -> Reconnect")
method = "ReconnectCwtchForeground"
} else {
Log.i("MainActivity.kt", "Start() launching foregroundservice")
// this is where the eventbus ForegroundService gets launched. WorkManager should keep it alive after this
val data: Data = Data.Builder().putString(FlwtchWorker.KEY_METHOD, call.method).putString(FlwtchWorker.KEY_ARGS, JSONObject(argmap).toString()).build()
// 15 minutes is the shortest interval you can request
val workRequest = PeriodicWorkRequestBuilder<FlwtchWorker>(15, TimeUnit.MINUTES).setInputData(data).addTag(workerTag).addTag(uniqueTag).build()
WorkManager.getInstance(this).enqueueUniquePeriodicWork("req_$uniqueTag", ExistingPeriodicWorkPolicy.KEEP, workRequest)
return
}
} }
// ...otherwise fallthru to a normal ffi method call (and return the result using the result callback) // ...otherwise fallthru to a normal ffi method call (and return the result using the result callback)
@ -158,6 +131,43 @@ class MainActivity: FlutterActivity() {
) )
} }
// using onresume/onstop for broadcastreceiver because of extended discussion on https://stackoverflow.com/questions/7439041/how-to-unregister-broadcastreceiver
override fun onResume() {
super.onResume()
Log.i("MainActivity.kt", "onResume")
if (myReceiver == null) {
Log.i("MainActivity.kt", "onResume registering localbroadcastreceiver")
val mc = MethodChannel(flutterEngine?.dartExecutor?.binaryMessenger, CWTCH_EVENTBUS)
val filter = IntentFilter("im.cwtch.flwtch.broadcast.SERVICE_EVENT_BUS")
myReceiver = MyBroadcastReceiver(mc)
LocalBroadcastManager.getInstance(applicationContext).registerReceiver(myReceiver!!, filter)
}
// ReconnectCwtchForeground which will resync counters and settings...
// We need to do this here because after a "pause" flutter is still running
// but we might have lost sync with the background process...
Log.i("MainActivity.kt", "Call ReconnectCwtchForeground")
val data: Data = Data.Builder().putString(FlwtchWorker.KEY_METHOD, "ReconnectCwtchForeground").putString(FlwtchWorker.KEY_ARGS, "{}").build()
val workRequest = OneTimeWorkRequestBuilder<FlwtchWorker>().setInputData(data).build()
WorkManager.getInstance(applicationContext).enqueue(workRequest)
}
override fun onStop() {
super.onStop()
Log.i("MainActivity.kt", "onStop")
if (myReceiver != null) {
LocalBroadcastManager.getInstance(applicationContext).unregisterReceiver(myReceiver!!);
myReceiver = null;
}
}
override fun onDestroy() {
super.onDestroy()
Log.i("MainActivity.kt", "onDestroy")
WorkManager.getInstance(this).cancelAllWorkByTag(WORKER_TAG)
WorkManager.getInstance(this).pruneWork()
}
// source: https://web.archive.org/web/20210203022531/https://stackoverflow.com/questions/41928803/how-to-parse-json-in-kotlin/50468095 // source: https://web.archive.org/web/20210203022531/https://stackoverflow.com/questions/41928803/how-to-parse-json-in-kotlin/50468095
// for reference: // for reference:
// //

12
fetch-tor.sh Executable file
View File

@ -0,0 +1,12 @@
#!/bin/sh
wget https://git.openprivacy.ca/openprivacy/buildfiles/raw/branch/master/tor/tor-0.4.5.9-linux-x86_64 -O linux/tor
chmod a+x linux/tor
mkdir -p android/app/src/main/jniLibs/arm64-v8a
wget https://git.openprivacy.ca/openprivacy/buildfiles/raw/branch/master/tor/tor-0.4.4.9-arm64_pie -O android/app/src/main/jniLibs/arm64-v8a/libtor.so
chmod a+x android/app/src/main/jniLibs/arm64-v8a/libtor.so
mkdir -p android/app/src/main/jniLibs/armeabi-v7a
wget https://git.openprivacy.ca/openprivacy/buildfiles/raw/branch/master/tor/tor-0.4.4.9-arm_pie -O android/app/src/main/jniLibs/armeabi-v7a/libtor.so
chmod a+x android/app/src/main/jniLibs/armeabi-v7a/libtor.so

View File

@ -37,8 +37,7 @@ class CwtchNotifier {
appState.SetAppError(data["Error"]); appState.SetAppError(data["Error"]);
break; break;
case "NewPeer": case "NewPeer":
profileCN.add(ProfileInfoState( profileCN.add(data["Identity"], data["name"], data["picture"], data["ContactsJson"], data["ServerList"], data["Online"] == "true");
onion: data["Identity"], nickname: data["name"], imagePath: data["picture"], contactsJson: data["ContactsJson"], serversJson: data["ServerList"], online: data["Online"] == "true"));
break; break;
case "PeerCreated": case "PeerCreated":
profileCN.getProfile(data["ProfileOnion"])?.contactList.add(ContactInfoState( profileCN.getProfile(data["ProfileOnion"])?.contactList.add(ContactInfoState(

View File

@ -83,7 +83,7 @@ class CwtchGomobile implements Cwtch {
// ignore: non_constant_identifier_names // ignore: non_constant_identifier_names
void DeleteProfile(String onion, String pass) { void DeleteProfile(String onion, String pass) {
cwtchPlatform.invokeMethod("DeleteProfile", {"onion": onion, "pass": pass}); cwtchPlatform.invokeMethod("DeleteProfile", {"ProfileOnion": onion, "pass": pass});
} }
// ignore: non_constant_identifier_names // ignore: non_constant_identifier_names

View File

@ -30,6 +30,7 @@ var globalAppState = AppState();
void main() { void main() {
print("main()"); print("main()");
LicenseRegistry.addLicense(() => licenses()); LicenseRegistry.addLicense(() => licenses());
WidgetsFlutterBinding.ensureInitialized();
print("runApp()"); print("runApp()");
runApp(Flwtch()); runApp(Flwtch());
} }
@ -55,11 +56,14 @@ class FlwtchState extends State<Flwtch> {
@override @override
initState() { initState() {
print("initState: running...");
super.initState(); super.initState();
print("initState: registering notification, shutdown handlers...");
profs = ProfileListState(); profs = ProfileListState();
notificationClickChannel.setMethodCallHandler(_externalNotificationClicked); notificationClickChannel.setMethodCallHandler(_externalNotificationClicked);
shutdownMethodChannel.setMethodCallHandler(shutdown); shutdownMethodChannel.setMethodCallHandler(shutdown);
print("initState: creating cwtchnotifier, ffi");
if (Platform.isAndroid) { if (Platform.isAndroid) {
var cwtchNotifier = new CwtchNotifier(profs, globalSettings, globalErrorHandler, globalTorStatus, NullNotificationsManager(), globalAppState); var cwtchNotifier = new CwtchNotifier(profs, globalSettings, globalErrorHandler, globalTorStatus, NullNotificationsManager(), globalAppState);
cwtch = CwtchGomobile(cwtchNotifier); cwtch = CwtchGomobile(cwtchNotifier);
@ -70,7 +74,9 @@ class FlwtchState extends State<Flwtch> {
var cwtchNotifier = new CwtchNotifier(profs, globalSettings, globalErrorHandler, globalTorStatus, NullNotificationsManager(), globalAppState); var cwtchNotifier = new CwtchNotifier(profs, globalSettings, globalErrorHandler, globalTorStatus, NullNotificationsManager(), globalAppState);
cwtch = CwtchFfi(cwtchNotifier); cwtch = CwtchFfi(cwtchNotifier);
} }
print("initState: invoking cwtch.Start()");
cwtch.Start(); cwtch.Start();
print("initState: done!");
} }
ChangeNotifierProvider<TorStatus> getTorStatusProvider() => ChangeNotifierProvider.value(value: globalTorStatus); ChangeNotifierProvider<TorStatus> getTorStatusProvider() => ChangeNotifierProvider.value(value: globalTorStatus);

View File

@ -38,13 +38,13 @@ class ProfileListState extends ChangeNotifier {
List<ProfileInfoState> _profiles = []; List<ProfileInfoState> _profiles = [];
int get num => _profiles.length; int get num => _profiles.length;
void addAll(Iterable<ProfileInfoState> newProfiles) { void add(String onion, String name, String picture, String contactsJson, String serverJson, bool online) {
_profiles.addAll(newProfiles); var idx = _profiles.indexWhere((element) => element.onion == onion);
notifyListeners(); if (idx == -1) {
} _profiles.add(ProfileInfoState(onion: onion, nickname: name, imagePath: picture, contactsJson: contactsJson, serversJson: serverJson, online: online));
} else {
void add(ProfileInfoState newProfile) { _profiles[idx].updateFrom(onion, name, picture, contactsJson, serverJson, online);
_profiles.add(newProfile); }
notifyListeners(); notifyListeners();
} }
@ -261,6 +261,41 @@ class ProfileInfoState extends ChangeNotifier {
super.dispose(); super.dispose();
print("profileinfostate.dispose()"); print("profileinfostate.dispose()");
} }
void updateFrom(String onion, String name, String picture, String contactsJson, String serverJson, bool online) {
this._nickname = name;
this._imagePath = picture;
this._online = online;
this.replaceServers(serverJson);
if (contactsJson != null && contactsJson != "" && contactsJson != "null") {
List<dynamic> contacts = jsonDecode(contactsJson);
contacts.forEach((contact) {
var profileContact = this._contacts.getContact(contact["onion"]);
if (profileContact != null) {
profileContact.status = contact["status"];
profileContact.totalMessages = contact["numMessages"];
profileContact.lastMessageTime = DateTime.fromMillisecondsSinceEpoch(1000 * int.parse(contact["lastMsgTime"]));
} else {
this._contacts.add(ContactInfoState(
this.onion,
contact["onion"],
nickname: contact["name"],
status: contact["status"],
imagePath: contact["picture"],
isBlocked: contact["authorization"] == "blocked",
isInvitation: contact["authorization"] == "unknown",
savePeerHistory: contact["saveConversationHistory"],
numMessages: contact["numMessages"],
numUnread: contact["numUnread"],
isGroup: contact["isGroup"],
server: contact["groupServer"],
lastMessageTime: DateTime.fromMillisecondsSinceEpoch(1000 * int.parse(contact["lastMsgTime"])),
));
}
});
}
}
} }
class ContactInfoState extends ChangeNotifier { class ContactInfoState extends ChangeNotifier {

View File

@ -20,7 +20,7 @@ class Settings extends ChangeNotifier {
bool experimentsEnabled = false; bool experimentsEnabled = false;
HashMap<String, bool> experiments = HashMap.identity(); HashMap<String, bool> experiments = HashMap.identity();
late bool blockUnknownConnections; bool blockUnknownConnections = false;
/// Set the dark theme. /// Set the dark theme.
void setDark() { void setDark() {

View File

@ -55,7 +55,7 @@ class _TorStatusView extends State<TorStatusView> {
ListTile( ListTile(
title: Text(AppLocalizations.of(context)!.torVersion), title: Text(AppLocalizations.of(context)!.torVersion),
subtitle: Text(torStatus.version), subtitle: Text(torStatus.version),
), ),
])))); ]))));
}); });
}); });

View File

@ -428,15 +428,6 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.1" version: "2.1.1"
window_size:
dependency: "direct main"
description:
path: "plugins/window_size"
ref: e48abe7c3e9ebfe0b81622167c5201d4e783bb81
resolved-ref: e48abe7c3e9ebfe0b81622167c5201d4e783bb81
url: "git://github.com/google/flutter-desktop-embedding.git"
source: git
version: "0.1.0"
xdg_directories: xdg_directories:
dependency: transitive dependency: transitive
description: description:

View File

@ -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. # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at # Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.0.0+12 version: 1.0.0+14
environment: environment:
sdk: ">=2.12.0 <3.0.0" sdk: ">=2.12.0 <3.0.0"
@ -45,12 +45,8 @@ dependencies:
flutter_driver: flutter_driver:
sdk: flutter sdk: flutter
window_size: dev_dependencies:
git: msix: ^2.1.3
url: git://github.com/google/flutter-desktop-embedding.git
path: plugins/window_size
ref: e48abe7c3e9ebfe0b81622167c5201d4e783bb81
# Uncomment to update lokalise translations (see README for list of deps to comment out bc incompatibilities) # Uncomment to update lokalise translations (see README for list of deps to comment out bc incompatibilities)
#dev_dependencies: #dev_dependencies:
# flutter_lokalise: any # flutter_lokalise: any
@ -116,3 +112,19 @@ flutter:
# #
# For details regarding fonts from package dependencies, # For details regarding fonts from package dependencies,
# see https://flutter.dev/custom-fonts/#from-packages # see https://flutter.dev/custom-fonts/#from-packages
msix_config:
display_name: Cwtch
publisher_display_name: Open Privacy Research Society
identity_name: im.cwtch.flwtch
msix_version: 1.0.0.0
certificate_path: codesign.pfx
certificate_password: pfx_pass
publisher: CN=Open Privacy Research Society, O=Open Privacy Research Society, L=Vancouver, S=British Columbia, C=CA
logo_path: cwtch.png
start_menu_icon_path: cwtch.png
tile_icon_path: assets\cwtch_title.png
icons_background_color: transparent
architecture: x64
capabilities: 'internetClient'