diff --git a/.drone.yml b/.drone.yml index 12da23c..7ad1372 100644 --- a/.drone.yml +++ b/.drone.yml @@ -28,9 +28,7 @@ steps: - name: deps path: /root/.pub-cache commands: - - wget https://git.openprivacy.ca/openprivacy/buildfiles/raw/master/tor/tor - - wget https://git.openprivacy.ca/openprivacy/buildfiles/raw/master/tor/torrc - - chmod a+x tor + - ./fetch-tor.sh - echo `git describe --tags` > VERSION - echo `date +%G-%m-%d-%H-%M` > BUILDDATE - flutter pub get @@ -62,7 +60,7 @@ steps: - cp linux/libCwtch.so deploy/linux/lib/ # 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 + - cp linux/tor deploy/linux - cd deploy - mv linux cwtch - tar -czf cwtch-`cat ../VERSION`.tar.gz cwtch @@ -215,45 +213,56 @@ steps: - name: fetch image: openpriv/flutter-desktop:windows-sdk30-fdev2.3rc 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 "if ((Get-FileHash tor.zip -Algorithm sha512).Hash -ne '2b7d683f036d0fec149f1d2bdfcf5b7ef4c337005a2b685c056b00047fdb2b57d4c25b8559ad7ef5c7a030b273934be82a9f83ef6e391f5d7d13d8d6c83e8048' ) { Write-Error 'tor.zip sha512sum mismatch' }" + - 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 '72764eb07ad8ab511603aba0734951ca003989f5f4686af91ba220217b4a8a4bcc5f571b59f52c847932f6efedf847b111621983050fcddbb8099d43ca66fb07' ) { Write-Error 'tor.zip sha512sum mismatch' }" - git describe --tags > VERSION - powershell -command "Get-Date -Format 'yyyy-MM-dd-HH-mm'" > BUILDDATE - .\fetch-libcwtch-go.ps1 - - + - name: build-windows image: openpriv/flutter-desktop:windows-sdk30-fdev2.3rc + environment: + pfx: + from_secret: pfx + pfx_pass: + from_secret: pfx_pass 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 - # flwtch-`cat VERSION`-`cat BUILDDATE` - - $Env:buildname = 'flwtch-win-' - $Env:version += type .\VERSION - - $Env:buildname += $Env:version - - $Env:buildname += '-' - $Env:builddate += type .\BUILDDATE - - $Env:buildname += $Env:builddate - - $Env:builddir += $Env:buildname - - $Env:zip = 'cwtch-' - - $Env:zip += $Env:version - - $Env:zip += '.zip' - - $Env:sha = $Env:zip - - $Env:sha += '.sha512' + - $Env:buildname = 'flwtch-win-' + $Env:version + '-' + $Env:builddate + - $Env:builddir = $Env:buildname + - $Env:zip = 'deploy\\' + $Env:builddir +'\\cwtch-' + $Env:version + '.zip' + - $Env:zipsha = $Env:zip + '.sha512' + - $Env:msix = 'cwtch-install-' + $Env:version + '.msix' + - $Env:msixsha = $Env:msix + '.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 - - mkdir deploy - - move build\\windows\\runner\\Release $Env:builddir - - copy windows\libCwtch.dll $Env:builddir + - copy windows\libCwtch.dll $Env:releasedir # flutter hasn't worked out it's packaging of required dll's so we have to resort to this manual nonsense # https://github.com/google/flutter-desktop-embedding/issues/587 # https://github.com/flutter/flutter/issues/53167 - - copy C:\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 + - copy C:\BuildTools\VC\Redist\MSVC\14.29.30036\x64\Microsoft.VC142.CRT\vcruntime140.dll $Env:releasedir + - copy C:\BuildTools\VC\Redist\MSVC\14.29.30036\x64\Microsoft.VC142.CRT\vcruntime140_1.dll $Env:releasedir + - copy C:\BuildTools\VC\Redist\MSVC\14.29.30036\x64\Microsoft.VC142.CRT\msvcp140.dll $Env:releasedir + - powershell -command "Expand-Archive -Path tor.zip -DestinationPath $Env:releasedir\Tor" + - dir $Env:releasedir + - echo $Env:pfx > codesign.pfx.b64 + - certutil -decode codesign.pfx.b64 codesign.pfx + - flutter pub run msix:create + - mkdir deploy - mkdir deploy\$Env:builddir - - move $Env:zip deploy\$Env:builddir - - move $Env:sha deploy\$Env:builddir + - dir deploy + - 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 image: openpriv/flutter-desktop:windows-sdk30-fdev2.3rc diff --git a/LIBCWTCH-GO.version b/LIBCWTCH-GO.version index 0a33cb8..0bc6904 100644 --- a/LIBCWTCH-GO.version +++ b/LIBCWTCH-GO.version @@ -1 +1 @@ -v0.0.2-87-gc6f1c4d-2021-06-17-22-45 +v0.0.2-104-gc1b7e4c-2021-06-22-23-59 \ No newline at end of file diff --git a/android/app/src/main/jniLibs/arm64-v8a/libtor.so b/android/app/src/main/jniLibs/arm64-v8a/libtor.so deleted file mode 100755 index 8c5a5fc..0000000 Binary files a/android/app/src/main/jniLibs/arm64-v8a/libtor.so and /dev/null differ diff --git a/android/app/src/main/jniLibs/armeabi-v7a/libtor.so b/android/app/src/main/jniLibs/armeabi-v7a/libtor.so deleted file mode 100755 index f1f19c7..0000000 Binary files a/android/app/src/main/jniLibs/armeabi-v7a/libtor.so and /dev/null differ diff --git a/android/app/src/main/kotlin/im/cwtch/flwtch/FlwtchWorker.kt b/android/app/src/main/kotlin/im/cwtch/flwtch/FlwtchWorker.kt index 50b94d5..90d751c 100644 --- a/android/app/src/main/kotlin/im/cwtch/flwtch/FlwtchWorker.kt +++ b/android/app/src/main/kotlin/im/cwtch/flwtch/FlwtchWorker.kt @@ -55,8 +55,9 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) : if (Cwtch.startCwtch(appDir, torPath) != 0.toLong()) return Result.failure() - // infinite coroutine :) + Log.i("FlwtchWorker.kt", "startCwtch success, starting coroutine AppbusEvent loop...") while(true) { + Log.i("FlwtchWorker.kt", "while(true)getAppbusEvent()") val evt = MainActivity.AppbusEvent(Cwtch.getAppBusEvent()) if (evt.EventType == "NewMessageFromPeer" || evt.EventType == "NewMessageFromGroup") { val data = JSONObject(evt.Data) @@ -180,8 +181,8 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) : } "DeleteProfile" -> { val profile = (a.get("ProfileOnion") as? String) ?: "" - val groupHandle = (a.get("pass") as? String) ?: "" - Cwtch.deleteProfile(profile, groupHandle) + val pass = (a.get("pass") as? String) ?: "" + Cwtch.deleteProfile(profile, pass) } "LeaveConversation" -> { val profile = (a.get("ProfileOnion") as? String) ?: "" @@ -213,11 +214,20 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) : val id = "flwtch" val title = "Flwtch" 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 val intent = WorkManager.getInstance(applicationContext) .createCancelPendingIntent(getId()) - val notification = NotificationCompat.Builder(applicationContext, id) + val notification = NotificationCompat.Builder(applicationContext, channelId) .setContentTitle(title) .setTicker(title) .setContentText(progress) @@ -231,10 +241,18 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) : 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) private fun createMessageNotificationChannel(channelId: String, channelName: String): String{ - val chan = NotificationChannel(channelId, - channelName, NotificationManager.IMPORTANCE_HIGH) + val chan = NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH) chan.lightColor = Color.MAGENTA chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE notificationManager.createNotificationChannel(chan) diff --git a/android/app/src/main/kotlin/im/cwtch/flwtch/MainActivity.kt b/android/app/src/main/kotlin/im/cwtch/flwtch/MainActivity.kt index e9a6d11..93c740a 100644 --- a/android/app/src/main/kotlin/im/cwtch/flwtch/MainActivity.kt +++ b/android/app/src/main/kotlin/im/cwtch/flwtch/MainActivity.kt @@ -7,40 +7,23 @@ import android.content.Intent import android.content.IntentFilter import androidx.annotation.NonNull import android.content.pm.PackageManager -import android.os.Build -import android.os.Bundle -import android.os.Looper import android.util.Log import android.view.Window -import android.widget.Toast -import androidx.annotation.RequiresApi import androidx.lifecycle.Observer import androidx.localbroadcastmanager.content.LocalBroadcastManager 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.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodCall -import io.flutter.plugin.common.MethodChannel.MethodCallHandler 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 java.io.File -import java.time.Duration import java.util.concurrent.TimeUnit class MainActivity: FlutterActivity() { - override fun provideSplashScreen(): SplashScreen? = SplashView() // Channel to get app info @@ -56,6 +39,10 @@ class MainActivity: FlutterActivity() { // Channel to trigger contactview when an external notification is clicked 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 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 // the eventbus listener. if (call.method == "Start") { - val workerTag = "cwtchEventBusWorker" val uniqueTag = argmap["torPath"] ?: "nullEventBus" // 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 // that we can divert this method call to ReconnectCwtchForeground instead if so. - val works = WorkManager.getInstance(this).getWorkInfosByTag(workerTag).get() - var alreadyRunning = false + val works = WorkManager.getInstance(this).getWorkInfosByTag(WORKER_TAG).get() for (workInfo in works) { - if (workInfo.tags.contains(uniqueTag)) { - if (workInfo.state == WorkInfo.State.RUNNING || workInfo.state == WorkInfo.State.ENQUEUED) { - alreadyRunning = true - } - } else { + Log.i("handleCwtch:WorkManager", "$workInfo") + if (!workInfo.tags.contains(uniqueTag)) { + Log.i("handleCwtch:WorkManager", "canceling ${workInfo.id} bc tags don't include $uniqueTag") 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 - // results in an implicit "reconnection" to old service threads even after frontend restarts - val mc = MethodChannel(flutterEngine?.dartExecutor?.binaryMessenger, CWTCH_EVENTBUS) - val filter = IntentFilter("im.cwtch.flwtch.broadcast.SERVICE_EVENT_BUS") - LocalBroadcastManager.getInstance(applicationContext).registerReceiver(MyBroadcastReceiver(mc), filter) - - if (alreadyRunning) { - 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(15, TimeUnit.MINUTES).setInputData(data).addTag(workerTag).addTag(uniqueTag).build() - WorkManager.getInstance(this).enqueueUniquePeriodicWork("req_$uniqueTag", ExistingPeriodicWorkPolicy.KEEP, workRequest) - return - } + 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(15, TimeUnit.MINUTES).setInputData(data).addTag(WORKER_TAG).addTag(uniqueTag).build() + WorkManager.getInstance(this).enqueueUniquePeriodicWork("req_$uniqueTag", ExistingPeriodicWorkPolicy.REPLACE, workRequest) + return } // ...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().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 // for reference: // diff --git a/fetch-tor.sh b/fetch-tor.sh new file mode 100755 index 0000000..90e26e3 --- /dev/null +++ b/fetch-tor.sh @@ -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 diff --git a/lib/cwtch/cwtchNotifier.dart b/lib/cwtch/cwtchNotifier.dart index 251dad6..bb564e6 100644 --- a/lib/cwtch/cwtchNotifier.dart +++ b/lib/cwtch/cwtchNotifier.dart @@ -37,8 +37,7 @@ class CwtchNotifier { appState.SetAppError(data["Error"]); break; case "NewPeer": - profileCN.add(ProfileInfoState( - onion: data["Identity"], nickname: data["name"], imagePath: data["picture"], contactsJson: data["ContactsJson"], serversJson: data["ServerList"], online: data["Online"] == "true")); + profileCN.add(data["Identity"], data["name"], data["picture"], data["ContactsJson"], data["ServerList"], data["Online"] == "true"); break; case "PeerCreated": profileCN.getProfile(data["ProfileOnion"])?.contactList.add(ContactInfoState( diff --git a/lib/cwtch/gomobile.dart b/lib/cwtch/gomobile.dart index 06e3a05..d9be08c 100644 --- a/lib/cwtch/gomobile.dart +++ b/lib/cwtch/gomobile.dart @@ -83,7 +83,7 @@ class CwtchGomobile implements Cwtch { // ignore: non_constant_identifier_names 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 diff --git a/lib/main.dart b/lib/main.dart index 31e8a27..6dd6b20 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -30,6 +30,7 @@ var globalAppState = AppState(); void main() { print("main()"); LicenseRegistry.addLicense(() => licenses()); + WidgetsFlutterBinding.ensureInitialized(); print("runApp()"); runApp(Flwtch()); } @@ -55,11 +56,14 @@ class FlwtchState extends State { @override initState() { + print("initState: running..."); super.initState(); + print("initState: registering notification, shutdown handlers..."); profs = ProfileListState(); notificationClickChannel.setMethodCallHandler(_externalNotificationClicked); shutdownMethodChannel.setMethodCallHandler(shutdown); + print("initState: creating cwtchnotifier, ffi"); if (Platform.isAndroid) { var cwtchNotifier = new CwtchNotifier(profs, globalSettings, globalErrorHandler, globalTorStatus, NullNotificationsManager(), globalAppState); cwtch = CwtchGomobile(cwtchNotifier); @@ -70,7 +74,9 @@ class FlwtchState extends State { var cwtchNotifier = new CwtchNotifier(profs, globalSettings, globalErrorHandler, globalTorStatus, NullNotificationsManager(), globalAppState); cwtch = CwtchFfi(cwtchNotifier); } + print("initState: invoking cwtch.Start()"); cwtch.Start(); + print("initState: done!"); } ChangeNotifierProvider getTorStatusProvider() => ChangeNotifierProvider.value(value: globalTorStatus); diff --git a/lib/model.dart b/lib/model.dart index 93d6f34..a6ffb47 100644 --- a/lib/model.dart +++ b/lib/model.dart @@ -38,13 +38,13 @@ class ProfileListState extends ChangeNotifier { List _profiles = []; int get num => _profiles.length; - void addAll(Iterable newProfiles) { - _profiles.addAll(newProfiles); - notifyListeners(); - } - - void add(ProfileInfoState newProfile) { - _profiles.add(newProfile); + void add(String onion, String name, String picture, String contactsJson, String serverJson, bool online) { + var idx = _profiles.indexWhere((element) => element.onion == onion); + if (idx == -1) { + _profiles.add(ProfileInfoState(onion: onion, nickname: name, imagePath: picture, contactsJson: contactsJson, serversJson: serverJson, online: online)); + } else { + _profiles[idx].updateFrom(onion, name, picture, contactsJson, serverJson, online); + } notifyListeners(); } @@ -261,6 +261,41 @@ class ProfileInfoState extends ChangeNotifier { super.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 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 { diff --git a/lib/settings.dart b/lib/settings.dart index ed4653e..f14052f 100644 --- a/lib/settings.dart +++ b/lib/settings.dart @@ -20,7 +20,7 @@ class Settings extends ChangeNotifier { bool experimentsEnabled = false; HashMap experiments = HashMap.identity(); - late bool blockUnknownConnections; + bool blockUnknownConnections = false; /// Set the dark theme. void setDark() { diff --git a/lib/views/torstatusview.dart b/lib/views/torstatusview.dart index 43bb5f0..e3f445d 100644 --- a/lib/views/torstatusview.dart +++ b/lib/views/torstatusview.dart @@ -55,7 +55,7 @@ class _TorStatusView extends State { ListTile( title: Text(AppLocalizations.of(context)!.torVersion), subtitle: Text(torStatus.version), - ), + ), ])))); }); }); diff --git a/pubspec.lock b/pubspec.lock index 3db29ce..c59f48b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -428,15 +428,6 @@ packages: url: "https://pub.dartlang.org" source: hosted 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: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 979c014..7e0eca9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -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+12 +version: 1.0.0+14 environment: sdk: ">=2.12.0 <3.0.0" @@ -45,12 +45,8 @@ dependencies: flutter_driver: sdk: flutter - window_size: - git: - url: git://github.com/google/flutter-desktop-embedding.git - path: plugins/window_size - ref: e48abe7c3e9ebfe0b81622167c5201d4e783bb81 - +dev_dependencies: + msix: ^2.1.3 # Uncomment to update lokalise translations (see README for list of deps to comment out bc incompatibilities) #dev_dependencies: # flutter_lokalise: any @@ -116,3 +112,19 @@ flutter: # # For details regarding fonts from package dependencies, # 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'