Merge branch 'trunk' into opaqueBlock
continuous-integration/drone/pr Build is passing
Details
continuous-integration/drone/pr Build is passing
Details
This commit is contained in:
commit
93dbba5f15
67
.drone.yml
67
.drone.yml
|
@ -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
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
v0.0.2-87-gc6f1c4d-2021-06-17-22-45
|
v0.0.2-104-gc1b7e4c-2021-06-22-23-59
|
Binary file not shown.
Binary file not shown.
|
@ -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)
|
||||||
|
|
|
@ -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:
|
||||||
//
|
//
|
||||||
|
|
|
@ -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
|
|
@ -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(
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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),
|
||||||
),
|
),
|
||||||
]))));
|
]))));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -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:
|
||||||
|
|
26
pubspec.yaml
26
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.
|
# 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'
|
||||||
|
|
Loading…
Reference in New Issue