diff --git a/SPEC.md b/SPEC.md index 50f07cb..2bd747c 100644 --- a/SPEC.md +++ b/SPEC.md @@ -47,7 +47,7 @@ required - any new Cwtch work is beyond the scope of this initial spec. - [X] Save/Load - [X] Switch Dark / Light Theme - [X] Switch Language -- [ ] Enable/Disable Experiments +- [X] Enable/Disable Experiments - [ ] Accessibility Settings (Zoom etc. - needs a deep dive into flutter) - [X] Display Build & Version Info - [X] Acknowledgements & Credits diff --git a/android/app/build.gradle b/android/app/build.gradle index f5b0d04..e6ebbc7 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -64,4 +64,6 @@ dependencies { implementation project(':cwtch') implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.2" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.2" + implementation "com.airbnb.android:lottie:3.5.0" + implementation "com.android.support.constraint:constraint-layout:2.0.4" } diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index a488615..ce5d411 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -12,7 +12,7 @@ @@ -24,15 +24,7 @@ android:name="io.flutter.embedding.android.NormalTheme" android:resource="@style/NormalTheme" /> - - + diff --git a/android/app/src/main/kotlin/com/example/flutter_app/MainActivity.kt b/android/app/src/main/kotlin/com/example/flutter_app/MainActivity.kt index bf69dd5..3c1cdca 100644 --- a/android/app/src/main/kotlin/com/example/flutter_app/MainActivity.kt +++ b/android/app/src/main/kotlin/com/example/flutter_app/MainActivity.kt @@ -1,5 +1,6 @@ package com.example.flutter_app +import SplashView import androidx.annotation.NonNull import android.content.pm.PackageManager import android.os.Bundle @@ -10,6 +11,7 @@ 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 @@ -25,6 +27,8 @@ import org.json.JSONObject class MainActivity: FlutterActivity() { + override fun provideSplashScreen(): SplashScreen? = SplashView() + // Channel to get app info private val CHANNEL_APP_INFO = "test.flutter.dev/applicationInfo" private val CALL_APP_INFO = "getNativeLibDir" diff --git a/android/app/src/main/kotlin/com/example/flutter_app/SplashView.kt b/android/app/src/main/kotlin/com/example/flutter_app/SplashView.kt new file mode 100644 index 0000000..288957a --- /dev/null +++ b/android/app/src/main/kotlin/com/example/flutter_app/SplashView.kt @@ -0,0 +1,15 @@ +import android.content.Context +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import com.example.flutter_app.R +import io.flutter.embedding.android.SplashScreen + +class SplashView : SplashScreen { + override fun createSplashView(context: Context, savedInstanceState: Bundle?): View? = + LayoutInflater.from(context).inflate(R.layout.splash_view, null, false) + + override fun transitionToFlutter(onTransitionComplete: Runnable) { + onTransitionComplete.run() + } +} \ No newline at end of file diff --git a/android/app/src/main/res/layout/splash_view.xml b/android/app/src/main/res/layout/splash_view.xml new file mode 100644 index 0000000..85c2362 --- /dev/null +++ b/android/app/src/main/res/layout/splash_view.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/raw/cwtch_animated_logo.json b/android/app/src/main/res/raw/cwtch_animated_logo.json new file mode 100644 index 0000000..b556344 --- /dev/null +++ b/android/app/src/main/res/raw/cwtch_animated_logo.json @@ -0,0 +1 @@ +{"v":"5.7.4","fr":29.9700012207031,"ip":0,"op":168.00000684278,"w":510,"h":510,"nm":"Comp 1","ddd":0,"assets":[{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-45,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":13,"s":[130.813,36.688,0],"to":[15.854,16.521,0],"ti":[-15.854,-16.521,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.167,"y":0.167},"t":17,"s":[225.938,135.813,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":187,"s":[225.938,135.813,0],"to":[-15.854,-16.521,0],"ti":[15.854,16.521,0]},{"t":191.000007779589,"s":[130.813,36.688,0]}],"ix":2,"l":2},"a":{"a":0,"k":[43.563,-24.563,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[44.125,137.125],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.485674749636,0.949019607843,0.850899430817,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[43.563,-24.563],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":13.0000005295009,"op":216.00000879786,"st":13.0000005295009,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Gradient Fill_1","tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[163.5,145,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[25.75,-64.625],[6.5,-47.625],[99.25,45.75],[121.125,29.375]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0.411,0.392,0.192,0.486,0.706,0.229,0.127,0.273,1,0.067,0.063,0.059],"ix":9}},"s":{"a":0,"k":[0,0],"ix":5},"e":{"a":0,"k":[100,0],"ix":6},"t":1,"nm":"Gradient Fill 1","mn":"ADBE Vector Graphic - G-Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":13.0000005295009,"op":223.000009082976,"st":13.0000005295009,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Shape Layer 3","td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[163.5,145,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":5,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[84.25,32.25],[84.625,30.75],[84.5,31.625],[84.75,29.75],[84.75,30.625],[83.625,29.25],[84.625,31.25],[85,30.375],[98.25,17],[71,-3.25],[61.25,8.125],[61.875,9],[60.875,7.5],[61,8.625],[60.375,9.375],[61.125,9.25],[84.5,30.25],[85.375,30.875]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":5.889,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[57.25,59.5],[57.625,58],[57.5,58.875],[57.75,57],[57.75,57.875],[56.625,56.5],[57.625,58.5],[58,57.625],[98.25,17],[71,-3.25],[36.125,32.25],[36.75,33.125],[35.75,31.625],[35.875,32.75],[35.25,33.5],[36,33.375],[57.5,57.5],[58.375,58.125]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":6.778,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[20.125,98.125],[20.5,96.625],[20.375,97.5],[20.625,95.625],[20.625,96.5],[19.5,95.125],[20.5,97.125],[36.5,82.75],[98.25,17],[71,-3.25],[-0.375,68.5],[0.25,69.375],[-0.75,67.875],[-0.625,69],[-1.25,69.75],[-0.5,69.625],[20.375,96.125],[21.25,96.75]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":7.668,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-21,97.25],[-20.625,95.75],[-20.75,96.625],[-20.5,94.75],[-20.5,95.625],[-21.625,94.25],[-4,112.25],[36.5,82.75],[98.25,17],[71,-3.25],[-0.375,68.5],[0.25,69.375],[-0.75,67.875],[-0.625,69],[-1.25,69.75],[-0.5,69.625],[-20.75,95.25],[-19.875,95.875]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":8.556,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-61.375,66.25],[-61,64.75],[-61.125,65.625],[-60.875,63.75],[-60.875,64.625],[-62,63.25],[-4,112.25],[36.5,82.75],[98.25,17],[71,-3.25],[-3.75,65.75],[-33.75,37],[-34.75,35.5],[-34.625,36.625],[-35.25,37.375],[-34.5,37.25],[-61.125,64.25],[-60.25,64.875]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":9.444,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-92.875,31.25],[-92.5,29.75],[-92.625,30.625],[-92.375,28.75],[-92.375,29.625],[-62,63.25],[-4,112.25],[36.5,82.75],[98.25,17],[71,-3.25],[-3.75,65.75],[-61.75,6],[-62.75,4.5],[-62.625,5.625],[-63.25,6.375],[-62.5,6.25],[-92.625,29.25],[-91.75,29.875]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":10.333,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-118.75,-72.875],[-118.375,-74.375],[-118.5,-73.5],[-118,-16.5],[-99,19.75],[-62,63.25],[-4,112.25],[36.5,82.75],[98.25,17],[71,-3.25],[-3.75,65.75],[-61.75,6],[-79.5,-25.5],[-82.25,-57.75],[-82.875,-57],[-82.125,-57.125],[-118.5,-74.875],[-117.625,-74.25]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":11.223,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[-19,17],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[19,-17],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-72,-116.5],[-98.5,-99.25],[-118.5,-73.5],[-118,-16.5],[-99,19.75],[-62,63.25],[-4,112.25],[36.5,82.75],[98.25,17],[71,-3.25],[-3.75,65.75],[-61.75,6],[-79.5,-25.5],[-82.25,-57.75],[-69.25,-71.375],[-63.75,-71.25],[-62.875,-116.875],[-67.375,-116.875]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":12.111,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[-19,17],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[19,-17],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-72,-116.5],[-98.5,-99.25],[-118.5,-73.5],[-118,-16.5],[-99,19.75],[-62,63.25],[-4,112.25],[36.5,82.75],[98.25,17],[71,-3.25],[-3.75,65.75],[-61.75,6],[-79.5,-25.5],[-82.25,-57.75],[-69.25,-71.375],[-63.75,-71.25],[-62.875,-116.875],[-67.375,-116.875]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":13,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[-19,17],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[19,-17],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-72,-116.5],[-98.5,-99.25],[-118.5,-73.5],[-118,-16.5],[-99,19.75],[-62,63.25],[-4,112.25],[36.5,82.75],[98.25,17],[71,-3.25],[-3.75,65.75],[-61.75,6],[-79.5,-25.5],[-82.25,-57.75],[-62.75,-75.5],[-32.75,-65.75],[0.25,-99.25],[-36.75,-115.25]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":191.223,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[-19,17],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[19,-17],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-72,-116.5],[-98.5,-99.25],[-118.5,-73.5],[-118,-16.5],[-99,19.75],[-62,63.25],[-4,112.25],[36.5,82.75],[98.25,17],[71,-3.25],[-3.75,65.75],[-61.75,6],[-79.5,-25.5],[-82.25,-57.75],[-62.75,-75.5],[-32.75,-65.75],[0.25,-99.25],[-36.75,-115.25]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":192.111,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[-19,17],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[19,-17],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-72,-116.5],[-98.5,-99.25],[-118.5,-73.5],[-118,-16.5],[-99,19.75],[-62,63.25],[-4,112.25],[36.5,82.75],[98.25,17],[71,-3.25],[-3.75,65.75],[-61.75,6],[-79.5,-25.5],[-82.25,-57.75],[-69.25,-71.375],[-63.75,-71.25],[-62.875,-116.875],[-67.375,-116.875]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":193,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[-19,17],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[19,-17],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-72,-116.5],[-98.5,-99.25],[-118.5,-73.5],[-118,-16.5],[-99,19.75],[-62,63.25],[-4,112.25],[36.5,82.75],[98.25,17],[71,-3.25],[-3.75,65.75],[-61.75,6],[-79.5,-25.5],[-82.25,-57.75],[-69.25,-71.375],[-63.75,-71.25],[-62.875,-116.875],[-67.375,-116.875]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":193.89,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-118.75,-72.875],[-118.375,-74.375],[-118.5,-73.5],[-118,-16.5],[-99,19.75],[-62,63.25],[-4,112.25],[36.5,82.75],[98.25,17],[71,-3.25],[-3.75,65.75],[-61.75,6],[-79.5,-25.5],[-82.25,-57.75],[-82.875,-57],[-82.125,-57.125],[-118.5,-74.875],[-117.625,-74.25]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":194.779,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-92.875,31.25],[-92.5,29.75],[-92.625,30.625],[-92.375,28.75],[-92.375,29.625],[-62,63.25],[-4,112.25],[36.5,82.75],[98.25,17],[71,-3.25],[-3.75,65.75],[-61.75,6],[-62.75,4.5],[-62.625,5.625],[-63.25,6.375],[-62.5,6.25],[-92.625,29.25],[-91.75,29.875]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":195.666,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-61.375,66.25],[-61,64.75],[-61.125,65.625],[-60.875,63.75],[-60.875,64.625],[-62,63.25],[-4,112.25],[36.5,82.75],[98.25,17],[71,-3.25],[-3.75,65.75],[-33.75,37],[-34.75,35.5],[-34.625,36.625],[-35.25,37.375],[-34.5,37.25],[-61.125,64.25],[-60.25,64.875]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":196.555,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-21,97.25],[-20.625,95.75],[-20.75,96.625],[-20.5,94.75],[-20.5,95.625],[-21.625,94.25],[-4,112.25],[36.5,82.75],[98.25,17],[71,-3.25],[-0.375,68.5],[0.25,69.375],[-0.75,67.875],[-0.625,69],[-1.25,69.75],[-0.5,69.625],[-20.75,95.25],[-19.875,95.875]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":197.445,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[20.125,98.125],[20.5,96.625],[20.375,97.5],[20.625,95.625],[20.625,96.5],[19.5,95.125],[20.5,97.125],[36.5,82.75],[98.25,17],[71,-3.25],[-0.375,68.5],[0.25,69.375],[-0.75,67.875],[-0.625,69],[-1.25,69.75],[-0.5,69.625],[20.375,96.125],[21.25,96.75]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":198.334,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[57.25,59.5],[57.625,58],[57.5,58.875],[57.75,57],[57.75,57.875],[56.625,56.5],[57.625,58.5],[58,57.625],[98.25,17],[71,-3.25],[36.125,32.25],[36.75,33.125],[35.75,31.625],[35.875,32.75],[35.25,33.5],[36,33.375],[57.5,57.5],[58.375,58.125]],"c":true}]},{"t":199.222508114499,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[84.25,32.25],[84.625,30.75],[84.5,31.625],[84.75,29.75],[84.75,30.625],[83.625,29.25],[84.625,31.25],[85,30.375],[98.25,17],[71,-3.25],[61.25,8.125],[61.875,9],[60.875,7.5],[61,8.625],[60.375,9.375],[61.125,9.25],[84.5,30.25],[85.375,30.875]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.485674749636,0.949019607843,0.850899430817,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":5.00000020365417,"op":215.00000875713,"st":5.00000020365417,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Gradient Fill_2","tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[144.5,143.75,0],"ix":2,"l":2},"a":{"a":0,"k":[97,108.5,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[15.32,-15.32],[-22.18,-37.58],[-8.27,-9.9],[-34.38,-27.34],[-15.84,15.83],[-5.9,6.87],[0,0],[7.34,-7.34],[13.62,-11.5],[0,0],[0,0],[14.29,17.55],[4.55,9.42],[0.38,6.48],[-2.45,5.95],[-6.41,6.41],[-5.83,2.09],[-8.02,-1.44],[0,0],[-4.58,-2.6],[0,0],[11.46,2.33]],"o":[[-28.01,28.01],[5.34,9.04],[18.86,22.58],[22.52,-17.91],[7.26,-7.26],[0,0],[-5.78,6.83],[-10.39,10.39],[0,0],[0,0],[-24.91,-21.03],[-9.08,-11.14],[-3.92,-8.14],[-0.19,-3.16],[2.4,-5.84],[2.39,-2.39],[6.02,-2.16],[0,0],[3.49,0.72],[0,0],[-5.51,-2.83],[-23.38,-4.74]],"v":[[-73.323,-90.495],[-81.753,4.345],[-61.243,32.885],[18.987,108.105],[76.777,57.275],[96.587,36.005],[77.827,17.245],[58.077,38.565],[21.887,71.555],[18.987,73.995],[16.097,71.555],[-42.993,13.415],[-63.523,-17.565],[-70.013,-39.595],[-67.713,-53.595],[-54.623,-71.795],[-42.543,-79.705],[-21.673,-80.775],[-21.563,-80.755],[-9.533,-75.805],[11.627,-96.965],[-14.993,-106.435]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.39199999641,0.19199999641,0.486000001197,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[96.587,108.105],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":5.00000020365417,"op":215.00000875713,"st":5.00000020365417,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"new curve 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[163.5,145,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-5.5,4],[0,0],[-31,-24.75],[1.25,-1.5]],"o":[[5.5,-4],[0,0],[44.579,35.591],[-1.25,1.5]],"v":[[-65.5,-9.5],[10.75,-84],[79.5,-86.25],[93.5,-13.5]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gs","o":{"a":0,"k":100,"ix":9},"w":{"a":0,"k":26,"ix":10},"g":{"p":3,"k":{"a":0,"k":[0,0,0,0,0.092,0.196,0.096,0.243,0.64,0.392,0.192,0.486],"ix":8}},"s":{"a":0,"k":[0,0],"ix":4},"e":{"a":0,"k":[100,0],"ix":5},"t":1,"lc":1,"lj":1,"ml":4,"ml2":{"a":0,"k":4,"ix":13},"bm":0,"nm":"Gradient Stroke 1","mn":"ADBE Vector Graphic - G-Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":5,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":199,"s":[0]},{"t":206.000008390552,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":5,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":199,"s":[100]},{"t":206.000008390552,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":210.000008553475,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"new curve","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[163.5,145,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-5.5,4],[0,0],[-31,-24.75],[1.25,-1.5]],"o":[[5.5,-4],[0,0],[44.579,35.591],[-1.25,1.5]],"v":[[-65.5,-9.5],[10.75,-84],[79.5,-86.25],[93.5,-13.5]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.392156892664,0.192156877705,0.486274539723,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":26,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":5,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":199,"s":[0]},{"t":206.000008390552,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":5,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":199,"s":[100]},{"t":206.000008390552,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":210.000008553475,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"heart1","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":270,"ix":10},"p":{"a":0,"k":[119.75,254.25,0],"ix":2,"l":2},"a":{"a":0,"k":[163.5,145,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":327,"h":290,"ip":81.0000032991976,"op":107.000004358199,"st":-103.000004195276,"bm":0},{"ddd":0,"ind":2,"ty":0,"nm":"heart1","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":270,"ix":10},"p":{"a":0,"k":[119.75,254.25,0],"ix":2,"l":2},"a":{"a":0,"k":[163.5,145,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":327,"h":290,"ip":54.0000021994651,"op":81.0000032991976,"st":54.0000021994651,"bm":0},{"ddd":0,"ind":3,"ty":0,"nm":"heart1","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":180,"ix":10},"p":{"a":0,"k":[252.75,388.75,0],"ix":2,"l":2},"a":{"a":0,"k":[163.5,145,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":327,"h":290,"ip":103.000004195276,"op":127.000005172816,"st":-83.0000033806593,"bm":0},{"ddd":0,"ind":4,"ty":0,"nm":"heart1","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":180,"ix":10},"p":{"a":0,"k":[252.75,388.75,0],"ix":2,"l":2},"a":{"a":0,"k":[163.5,145,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":327,"h":290,"ip":35.0000014255792,"op":103.000004195276,"st":35.0000014255792,"bm":0},{"ddd":0,"ind":5,"ty":0,"nm":"heart1","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[389.25,255.25,0],"ix":2,"l":2},"a":{"a":0,"k":[163.5,145,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":327,"h":290,"ip":124.000005050624,"op":147.000005987433,"st":-63.0000025660426,"bm":0},{"ddd":0,"ind":6,"ty":0,"nm":"heart1","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[389.25,255.25,0],"ix":2,"l":2},"a":{"a":0,"k":[163.5,145,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":327,"h":290,"ip":18.000000733155,"op":124.000005050624,"st":18.000000733155,"bm":0},{"ddd":0,"ind":7,"ty":0,"nm":"heart1","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[255,122.25,0],"ix":2,"l":2},"a":{"a":0,"k":[163.5,145,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":327,"h":290,"ip":144.00000586524,"op":168.00000684278,"st":-42.0000017106951,"bm":0},{"ddd":0,"ind":8,"ty":0,"nm":"heart1","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[255,122.25,0],"ix":2,"l":2},"a":{"a":0,"k":[163.5,145,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":327,"h":290,"ip":0,"op":144.00000586524,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml deleted file mode 100644 index 1f83a33..0000000 --- a/android/app/src/main/res/values/styles.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - diff --git a/android/build.gradle b/android/build.gradle index 3100ad2..361fb7a 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -8,6 +8,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:3.5.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } } diff --git a/android/cwtch/cwtch.aar b/android/cwtch/cwtch.aar index 2f7f548..10e699d 100644 Binary files a/android/cwtch/cwtch.aar and b/android/cwtch/cwtch.aar differ diff --git a/lib/cwtch/cwtchNotifier.dart b/lib/cwtch/cwtchNotifier.dart index aa4e0c5..f075b11 100644 --- a/lib/cwtch/cwtchNotifier.dart +++ b/lib/cwtch/cwtchNotifier.dart @@ -21,31 +21,32 @@ class CwtchNotifier { switch (type) { case "NewPeer": profileCN.add(ProfileInfoState( - onion: data["Identity"], - nickname: data["name"], - imagePath: data["picture"], - contactsJson: data["ContactsJson"], + onion: data["Identity"], + nickname: data["name"], + imagePath: data["picture"], + contactsJson: data["ContactsJson"], )); break; case "PeerCreated": print("xx peercreated"); profileCN.getProfile(data["ProfileOnion"]).contactList.add(ContactInfoState( - profileOnion: data["ProfileOnion"], - onion: data["RemotePeer"], - nickname: data["nick"], - status: data["status"], - )); + profileOnion: data["ProfileOnion"], + onion: data["RemotePeer"], + nickname: data["nick"], + status: data["status"], + )); break; case "PeerStateChange": ContactInfoState contact = profileCN.getProfile(data["ProfileOnion"]).contactList.getContact(data["RemotePeer"]); - if (contact == null) {//todo: stopgap, as lc-g is supposed to handle this - print("PSC -> adding "+data["ProfileOnion"]+" :: " + data["RemotePeer"]); + if (contact == null) { + //todo: stopgap, as lc-g is supposed to handle this + print("PSC -> adding " + data["ProfileOnion"] + " :: " + data["RemotePeer"]); profileCN.getProfile(data["ProfileOnion"]).contactList.add(ContactInfoState( - profileOnion: data["ProfileOnion"], - onion: data["RemotePeer"], - nickname: data["nick"], - status: data["ConnectionState"], - )); + profileOnion: data["ProfileOnion"], + onion: data["RemotePeer"], + nickname: data["nick"], + status: data["ConnectionState"], + )); } else { contact.status = data["ConnectionState"]; } diff --git a/lib/cwtch/ffi.dart b/lib/cwtch/ffi.dart index 2e677e8..a79a88d 100644 --- a/lib/cwtch/ffi.dart +++ b/lib/cwtch/ffi.dart @@ -15,52 +15,38 @@ import '../model.dart'; /// Cwtch API /// ///////////////////// -typedef start_cwtch_function = Void Function( - Pointer str, Int32 length, Pointer str2, Int32 length2); -typedef StartCwtchFn = void Function( - Pointer dir, int len, Pointer tor, int torLen); +typedef start_cwtch_function = Void Function(Pointer str, Int32 length, Pointer str2, Int32 length2); +typedef StartCwtchFn = void Function(Pointer dir, int len, Pointer tor, int torLen); -typedef void_from_string_string_function = Void Function( - Pointer, Int32, Pointer, Int32); -typedef VoidFromStringStringFn = void Function( - Pointer, int, Pointer, int); +typedef void_from_string_string_function = Void Function(Pointer, Int32, Pointer, Int32); +typedef VoidFromStringStringFn = void Function(Pointer, int, Pointer, int); typedef access_cwtch_eventbus_function = Void Function(); typedef NextEventFn = void Function(); -typedef string_to_void_function = Void Function( - Pointer str, Int32 length); +typedef string_to_void_function = Void Function(Pointer str, Int32 length); typedef StringFn = void Function(Pointer dir, int); -typedef string_string_to_void_function = Void Function( - Pointer str, Int32 length, Pointer str2, Int32 length2); +typedef string_string_to_void_function = Void Function(Pointer str, Int32 length, Pointer str2, Int32 length2); typedef StringStringFn = void Function(Pointer, int, Pointer, int); typedef get_json_blob_void_function = Pointer Function(); typedef GetJsonBlobVoidFn = Pointer Function(); -typedef get_json_blob_string_function = Pointer Function( - Pointer str, Int32 length); -typedef GetJsonBlobStringFn = Pointer Function( - Pointer str, int len); +typedef get_json_blob_string_function = Pointer Function(Pointer str, Int32 length); +typedef GetJsonBlobStringFn = Pointer Function(Pointer str, int len); //func NumMessages(profile_ptr *C.char, profile_len C.int, handle_ptr *C.char, handle_len C.int) (n C.int) { -typedef get_int_from_str_str_function = Int32 Function( - Pointer, Int32, Pointer, Int32); -typedef GetIntFromStrStrFn = int Function( - Pointer, int, Pointer, int); +typedef get_int_from_str_str_function = Int32 Function(Pointer, Int32, Pointer, Int32); +typedef GetIntFromStrStrFn = int Function(Pointer, int, Pointer, int); //func GetMessage(profile_ptr *C.char, profile_len C.int, handle_ptr *C.char, handle_len C.int, message_index C.int) *C.char { -typedef get_json_blob_from_str_str_int_function = Pointer Function( - Pointer, Int32, Pointer, Int32, Int32); -typedef GetJsonBlobFromStrStrIntFn = Pointer Function( - Pointer, int, Pointer, int, int); +typedef get_json_blob_from_str_str_int_function = Pointer Function(Pointer, Int32, Pointer, Int32, Int32); +typedef GetJsonBlobFromStrStrIntFn = Pointer Function(Pointer, int, Pointer, int, int); //func GetMessages(profile_ptr *C.char, profile_len C.int, handle_ptr *C.char, handle_len C.int, start C.int, end C.int) *C.char { -typedef get_json_blob_from_str_str_int_int_function = Pointer Function( - Pointer, Int32, Pointer, Int32, Int32, Int32); -typedef GetJsonBlobFromStrStrIntIntFn = Pointer Function( - Pointer, int, Pointer, int, int, int); +typedef get_json_blob_from_str_str_int_int_function = Pointer Function(Pointer, Int32, Pointer, Int32, Int32, Int32); +typedef GetJsonBlobFromStrStrIntIntFn = Pointer Function(Pointer, int, Pointer, int, int, int); typedef acn_events_function = Pointer Function(); typedef ACNEventsFn = Pointer Function(); @@ -86,8 +72,7 @@ class CwtchFfi implements Cwtch { var cwtchDir = path.join(home, ".cwtch/dev/"); print("cwtchDir $cwtchDir"); - var startCwtchC = - library.lookup>("c_StartCwtch"); + var startCwtchC = library.lookup>("c_StartCwtch"); // ignore: non_constant_identifier_names final StartCwtch = startCwtchC.asFunction(); @@ -96,8 +81,7 @@ class CwtchFfi implements Cwtch { // Spawn an isolate to listen to events from libcwtch-go and then dispatch them when received on main thread to cwtchNotifier var _receivePort = ReceivePort(); - cwtchIsolate = - await Isolate.spawn(_checkAppbusEvents, _receivePort.sendPort); + cwtchIsolate = await Isolate.spawn(_checkAppbusEvents, _receivePort.sendPort); _receivePort.listen((message) { var env = jsonDecode(message); cwtchNotifier.handleMessage(env["EventType"], env["Data"]); @@ -123,8 +107,7 @@ class CwtchFfi implements Cwtch { // Steam of appbus events. Call blocks in libcwtch-go GetAppbusEvent. Static so the isolate can use it static Stream pollAppbusEvents() async* { var library = DynamicLibrary.open("libCwtch.so"); - var getAppbusEventC = - library.lookup>("c_GetAppBusEvent"); + var getAppbusEventC = library.lookup>("c_GetAppBusEvent"); final GetAppbusEvent = getAppbusEventC.asFunction(); while (true) { @@ -136,9 +119,7 @@ class CwtchFfi implements Cwtch { // ignore: non_constant_identifier_names void SelectProfile(String onion) async { - var selectProfileC = - library.lookup>( - "c_SelectProfile"); + var selectProfileC = library.lookup>("c_SelectProfile"); // ignore: non_constant_identifier_names final SelectProfile = selectProfileC.asFunction(); final ut8Onion = onion.toNativeUtf8(); @@ -147,9 +128,7 @@ class CwtchFfi implements Cwtch { // ignore: non_constant_identifier_names void CreateProfile(String nick, String pass) { - var createProfileC = - library.lookup>( - "c_CreateProfile"); + var createProfileC = library.lookup>("c_CreateProfile"); // ignore: non_constant_identifier_names final CreateProfile = createProfileC.asFunction(); final utf8nick = nick.toNativeUtf8(); @@ -159,8 +138,7 @@ class CwtchFfi implements Cwtch { // ignore: non_constant_identifier_names void LoadProfiles(String pass) { - var loadProfileC = library - .lookup>("c_LoadProfiles"); + var loadProfileC = library.lookup>("c_LoadProfiles"); // ignore: non_constant_identifier_names final LoadProfiles = loadProfileC.asFunction(); final ut8pass = pass.toNativeUtf8(); @@ -168,8 +146,7 @@ class CwtchFfi implements Cwtch { } Future ACNEvents() async { - var acnEventsC = - library.lookup>("c_ACNEvents"); + var acnEventsC = library.lookup>("c_ACNEvents"); // ignore: non_constant_identifier_names final ACNEvents = acnEventsC.asFunction(); @@ -179,8 +156,7 @@ class CwtchFfi implements Cwtch { } Future ContactEvents() async { - var acnEventsC = - library.lookup>("c_ContactEvents"); + var acnEventsC = library.lookup>("c_ContactEvents"); // ignore: non_constant_identifier_names final ContactEvents = acnEventsC.asFunction(); @@ -190,8 +166,7 @@ class CwtchFfi implements Cwtch { } Future GetProfiles() async { - var getProfilesC = library - .lookup>("c_GetProfiles"); + var getProfilesC = library.lookup>("c_GetProfiles"); // ignore: non_constant_identifier_names final GetProfiles = getProfilesC.asFunction(); @@ -201,8 +176,7 @@ class CwtchFfi implements Cwtch { } Future GetContacts(String onion) async { - var getContactsC = library - .lookup>("c_GetContacts"); + var getContactsC = library.lookup>("c_GetContacts"); // ignore: non_constant_identifier_names final GetContacts = getContactsC.asFunction(); final utf8onion = onion.toNativeUtf8(); @@ -212,52 +186,40 @@ class CwtchFfi implements Cwtch { } Future NumMessages(String profile, String handle) async { - var numMessagesC = library - .lookup>("c_NumMessages"); + var numMessagesC = library.lookup>("c_NumMessages"); // ignore: non_constant_identifier_names final NumMessages = numMessagesC.asFunction(); final utf8profile = profile.toNativeUtf8(); final utf8handle = handle.toNativeUtf8(); - int num = NumMessages( - utf8profile, utf8profile.length, utf8handle, utf8handle.length); + int num = NumMessages(utf8profile, utf8profile.length, utf8handle, utf8handle.length); return num; } Future GetMessage(String profile, String handle, int index) async { - var getMessageC = - library.lookup>( - "c_GetMessage"); + var getMessageC = library.lookup>("c_GetMessage"); // ignore: non_constant_identifier_names final GetMessage = getMessageC.asFunction(); final utf8profile = profile.toNativeUtf8(); final utf8handle = handle.toNativeUtf8(); - Pointer jsonMessageBytes = GetMessage( - utf8profile, utf8profile.length, utf8handle, utf8handle.length, index); + Pointer jsonMessageBytes = GetMessage(utf8profile, utf8profile.length, utf8handle, utf8handle.length, index); String jsonMessage = jsonMessageBytes.toDartString(); return jsonMessage; } - Future GetMessages( - String profile, String handle, int start, int end) async { - var getMessagesC = library - .lookup>( - "c_GetMessages"); + Future GetMessages(String profile, String handle, int start, int end) async { + var getMessagesC = library.lookup>("c_GetMessages"); // ignore: non_constant_identifier_names - final GetMessages = - getMessagesC.asFunction(); + final GetMessages = getMessagesC.asFunction(); final utf8profile = profile.toNativeUtf8(); final utf8handle = handle.toNativeUtf8(); - Pointer jsonMessagesBytes = GetMessages(utf8profile, - utf8profile.length, utf8handle, utf8handle.length, start, end); + Pointer jsonMessagesBytes = GetMessages(utf8profile, utf8profile.length, utf8handle, utf8handle.length, start, end); String jsonMessages = jsonMessagesBytes.toDartString(); return jsonMessages; } @override void SendProfileEvent(String onion, String json) { - var sendAppBusEvent = - library.lookup>( - "c_SendProfileEvent"); + var sendAppBusEvent = library.lookup>("c_SendProfileEvent"); // ignore: non_constant_identifier_names final SendAppBusEvent = sendAppBusEvent.asFunction(); final utf8onion = onion.toNativeUtf8(); @@ -267,8 +229,7 @@ class CwtchFfi implements Cwtch { @override void SendAppEvent(String json) { - var sendAppBusEvent = library - .lookup>("c_SendAppEvent"); + var sendAppBusEvent = library.lookup>("c_SendAppEvent"); // ignore: non_constant_identifier_names final SendAppBusEvent = sendAppBusEvent.asFunction(); final utf8json = json.toNativeUtf8(); diff --git a/lib/cwtch/gomobile.dart b/lib/cwtch/gomobile.dart index b69fb4c..04a470a 100644 --- a/lib/cwtch/gomobile.dart +++ b/lib/cwtch/gomobile.dart @@ -22,8 +22,7 @@ Future startCwtch() async { */ class CwtchGomobile implements Cwtch { - static const appInfoPlatform = - const MethodChannel('test.flutter.dev/applicationInfo'); + static const appInfoPlatform = const MethodChannel('test.flutter.dev/applicationInfo'); static const cwtchPlatform = const MethodChannel('cwtch'); final appbusEventChannelName = 'test.flutter.dev/eventBus'; @@ -48,8 +47,7 @@ class CwtchGomobile implements Cwtch { var cwtchDir = path.join((await androidHomeDirectory).path, ".cwtch/dev/"); String torPath = path.join(await androidLibraryDir, "libtor.so"); print("gomobile.dart: Start invokeMethod Start($cwtchDir, $torPath)..."); - cwtchPlatform - .invokeMethod("Start", {"appDir": cwtchDir, "torPath": torPath}); + cwtchPlatform.invokeMethod("Start", {"appDir": cwtchDir, "torPath": torPath}); } // Handle libcwtch-go events (received via kotlin) and dispatch to the cwtchNotifier @@ -89,26 +87,21 @@ class CwtchGomobile implements Cwtch { } Future NumMessages(String profile, String handle) { - return cwtchPlatform - .invokeMethod("NumMessages", {"profile": profile, "contact": handle}); + return cwtchPlatform.invokeMethod("NumMessages", {"profile": profile, "contact": handle}); } Future GetMessage(String profile, String handle, int index) { print("gomobile.dart GetMessage " + index.toString()); - return cwtchPlatform.invokeMethod( - "GetMessage", {"profile": profile, "contact": handle, "index": index}); + return cwtchPlatform.invokeMethod("GetMessage", {"profile": profile, "contact": handle, "index": index}); } - Future GetMessages( - String profile, String handle, int start, int end) { - return cwtchPlatform.invokeMethod("GetMessage", - {"profile": profile, "contact": handle, "start": start, "end": end}); + Future GetMessages(String profile, String handle, int start, int end) { + return cwtchPlatform.invokeMethod("GetMessage", {"profile": profile, "contact": handle, "start": start, "end": end}); } @override void SendProfileEvent(String onion, String jsonEvent) { - cwtchPlatform.invokeMethod( - "SendProfileEvent", {"onion": onion, "jsonEvent": jsonEvent}); + cwtchPlatform.invokeMethod("SendProfileEvent", {"onion": onion, "jsonEvent": jsonEvent}); } @override diff --git a/lib/l10n/intl_de.arb b/lib/l10n/intl_de.arb index 0f59776..340e162 100644 --- a/lib/l10n/intl_de.arb +++ b/lib/l10n/intl_de.arb @@ -47,6 +47,8 @@ "dontSavePeerHistory": "Peer-Verlauf löschen", "editProfile": "Profil bearbeiten", "editProfileTitle": "Profil bearbeiten", + "enableGroups": "", + "enterCurrentPasswordForDelete": "", "enterProfilePassword": "Geben Sie ein Passwort ein, um Ihre Profile anzuzeigen", "error0ProfilesLoadedForPassword": "0 Profile mit diesem Passwort geladen", "experimentsEnabled": "Experimente aktiviert", diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index 8704392..15e3f20 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -47,9 +47,11 @@ "dontSavePeerHistory": "Delete Peer History", "editProfile": "Edit Profille", "editProfileTitle": "Edit Profile", + "enableGroups": "Enable Group Chat", + "enterCurrentPasswordForDelete": "Please enter current password to delete this profile.", "enterProfilePassword": "Enter a password to view your profiles", "error0ProfilesLoadedForPassword": "0 profiles loaded with that password", - "experimentsEnabled": "Experiments enabled", + "experimentsEnabled": "Enable Experiments", "groupAddr": "Address", "groupName": "Group name", "groupNameLabel": "Group Name", diff --git a/lib/l10n/intl_es.arb b/lib/l10n/intl_es.arb index 023d7eb..661e351 100644 --- a/lib/l10n/intl_es.arb +++ b/lib/l10n/intl_es.arb @@ -47,6 +47,8 @@ "dontSavePeerHistory": "Eliminar historial de contacto", "editProfile": "Editar perfil", "editProfileTitle": "Editar perfil", + "enableGroups": "", + "enterCurrentPasswordForDelete": "", "enterProfilePassword": "Ingresa tu contraseña para ver tus perfiles", "error0ProfilesLoadedForPassword": "0 perfiles cargados con esa contraseña", "experimentsEnabled": "Experimentos habilitados", diff --git a/lib/l10n/intl_fr.arb b/lib/l10n/intl_fr.arb index ea7b94f..56bf040 100644 --- a/lib/l10n/intl_fr.arb +++ b/lib/l10n/intl_fr.arb @@ -47,6 +47,8 @@ "dontSavePeerHistory": "", "editProfile": "", "editProfileTitle": "", + "enableGroups": "", + "enterCurrentPasswordForDelete": "", "enterProfilePassword": "", "error0ProfilesLoadedForPassword": "", "experimentsEnabled": "", diff --git a/lib/l10n/intl_it.arb b/lib/l10n/intl_it.arb index 5526c92..6fd0a19 100644 --- a/lib/l10n/intl_it.arb +++ b/lib/l10n/intl_it.arb @@ -47,6 +47,8 @@ "dontSavePeerHistory": "Elimina cronologia dei peer", "editProfile": "Modifica profilo", "editProfileTitle": "Modifica profilo", + "enableGroups": "", + "enterCurrentPasswordForDelete": "", "enterProfilePassword": "Inserisci una password per visualizzare i tuoi profili", "error0ProfilesLoadedForPassword": "0 profili caricati con quella password", "experimentsEnabled": "Esperimenti abilitati", diff --git a/lib/l10n/intl_pt.arb b/lib/l10n/intl_pt.arb index 4812797..f1ccc09 100644 --- a/lib/l10n/intl_pt.arb +++ b/lib/l10n/intl_pt.arb @@ -47,6 +47,8 @@ "dontSavePeerHistory": "", "editProfile": "", "editProfileTitle": "", + "enableGroups": "", + "enterCurrentPasswordForDelete": "", "enterProfilePassword": "", "error0ProfilesLoadedForPassword": "", "experimentsEnabled": "", diff --git a/lib/licenses.dart b/lib/licenses.dart new file mode 100644 index 0000000..a06b816 --- /dev/null +++ b/lib/licenses.dart @@ -0,0 +1,117 @@ +import 'package:flutter/foundation.dart'; + +Stream licenses() async* { + /// Open Privacy Code + yield LicenseEntryWithLineBreaks(["cwtch", "tapir", "connectivity", "log"], '''MIT License + + Copyright (c) 2018 Open Privacy Research Society + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files ("the Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.'''); + + /// Ristretto Code + yield LicenseEntryWithLineBreaks(["ristretto255"], '''Copyright (c) 2009 The Go Authors. All rights reserved. +Copyright (c) 2017 George Tankersley. All rights reserved. +Copyright (c) 2019 Henry de Valence. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.'''); + + /// Package pretty provides pretty-printing for Go values. (via Cwtch) + yield LicenseEntryWithLineBreaks(["pretty"], '''Copyright 2012 Keith Rarick + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE.'''); + + yield LicenseEntryWithLineBreaks(["pidusage"], '''MIT License + +Copyright (c) 2017 David 大伟 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.'''); + + /// Go Standard Lib + yield LicenseEntryWithLineBreaks(["crypto, net"], '''Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.'''); +} diff --git a/lib/main.dart b/lib/main.dart index b5c3fb4..fe9b83d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,3 +1,4 @@ +import 'package:flutter/foundation.dart'; import 'package:flutter_app/cwtch/ffi.dart'; import 'package:flutter_app/cwtch/gomobile.dart'; import 'package:flutter/material.dart'; @@ -6,6 +7,7 @@ import 'package:flutter_app/views/triplecolview.dart'; import 'package:provider/provider.dart'; import 'cwtch/cwtch.dart'; import 'cwtch/cwtchNotifier.dart'; +import 'licenses.dart'; import 'model.dart'; import 'views/profilemgrview.dart'; import 'views/splashView.dart'; @@ -13,9 +15,12 @@ import 'dart:io' show Platform; import 'opaque.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -var GlobalSettings = Settings(Locale("en", ''), Opaque.dark); +var globalSettings = Settings(Locale("en", ''), Opaque.dark); -void main() => runApp(Flwtch()); +void main() { + LicenseRegistry.addLicense(() => licenses()); + runApp(Flwtch()); +} class Flwtch extends StatefulWidget { final Key flwtch = GlobalKey(); @@ -41,7 +46,7 @@ class FlwtchState extends State { cwtchInit = false; profs = ProfileListState(); - var cwtchNotifier = new CwtchNotifier(profs, GlobalSettings); + var cwtchNotifier = new CwtchNotifier(profs, globalSettings); if (Platform.isAndroid) { cwtch = CwtchGomobile(cwtchNotifier); @@ -58,23 +63,16 @@ class FlwtchState extends State { appStatus = AppModel(cwtch: cwtch); } - ChangeNotifierProvider getSettingsProvider() => - ChangeNotifierProvider(create: (context) => GlobalSettings); - Provider getFlwtchStateProvider() => - Provider(create: (_) => this); - ChangeNotifierProvider getProfileListProvider() => - ChangeNotifierProvider(create: (context) => profs); + ChangeNotifierProvider getSettingsProvider() => ChangeNotifierProvider(create: (context) => globalSettings); + Provider getFlwtchStateProvider() => Provider(create: (_) => this); + ChangeNotifierProvider getProfileListProvider() => ChangeNotifierProvider(create: (context) => profs); @override Widget build(BuildContext context) { appStatus = AppModel(cwtch: cwtch); return MultiProvider( - providers: [ - getFlwtchStateProvider(), - getProfileListProvider(), - getSettingsProvider() - ], + providers: [getFlwtchStateProvider(), getProfileListProvider(), getSettingsProvider()], builder: (context, widget) { Provider.of(context).initPackageInfo(); return Consumer( @@ -97,20 +95,15 @@ class FlwtchState extends State { cardColor: opaque.current().backgroundMainColor(), textButtonTheme: TextButtonThemeData( style: ButtonStyle( - backgroundColor: MaterialStateProperty.all( - opaque.current().defaultButtonColor()), - foregroundColor: MaterialStateProperty.all( - opaque.current().defaultButtonTextColor()), - overlayColor: MaterialStateProperty.all( - opaque.current().defaultButtonActiveColor()), + backgroundColor: MaterialStateProperty.all(opaque.current().defaultButtonColor()), + foregroundColor: MaterialStateProperty.all(opaque.current().defaultButtonTextColor()), + overlayColor: MaterialStateProperty.all(opaque.current().defaultButtonActiveColor()), padding: MaterialStateProperty.all(EdgeInsets.all(20))), ), dialogTheme: DialogTheme( backgroundColor: opaque.current().backgroundPaneColor(), - titleTextStyle: - TextStyle(color: opaque.current().mainTextColor()), - contentTextStyle: - TextStyle(color: opaque.current().mainTextColor())), + titleTextStyle: TextStyle(color: opaque.current().mainTextColor()), + contentTextStyle: TextStyle(color: opaque.current().mainTextColor())), textTheme: TextTheme( headline1: TextStyle(color: opaque.current().mainTextColor()), headline2: TextStyle(color: opaque.current().mainTextColor()), @@ -128,9 +121,7 @@ class FlwtchState extends State { ), // from dan: home: cwtchInit == true ? ProfileMgrView(cwtch) : SplashView(), // from erinn: home: columns.length == 3 ? TripleColumnView() : ProfileMgrView(), - home: cwtchInit == true - ? (columns.length == 3 ? TripleColumnView() : ProfileMgrView()) - : SplashView(), + home: cwtchInit == true ? (columns.length == 3 ? TripleColumnView() : ProfileMgrView()) : SplashView(), ), ); }, diff --git a/lib/model.dart b/lib/model.dart index 5713c1c..df09914 100644 --- a/lib/model.dart +++ b/lib/model.dart @@ -29,13 +29,7 @@ class ContactModel { String status; String imagePath; - ContactModel( - {this.onion, - this.nickname, - this.status, - this.isInvitation, - this.isBlocked, - this.imagePath}); + ContactModel({this.onion, this.nickname, this.status, this.isInvitation, this.isBlocked, this.imagePath}); } //todo: delete @@ -78,12 +72,12 @@ class ProfileListState extends ChangeNotifier { } void add(ProfileInfoState newProfile) { - print("ProfileListState: adding " + newProfile.onion +" and notifying"); + print("ProfileListState: adding " + newProfile.onion + " and notifying"); _profiles.add(newProfile); notifyListeners(); } - List get profiles => _profiles.sublist(0);//todo: copy?? dont want caller able to bypass changenotifier + List get profiles => _profiles.sublist(0); //todo: copy?? dont want caller able to bypass changenotifier ProfileInfoState getProfile(String onion) { int idx = _profiles.indexWhere((element) => element.onion == onion); @@ -106,13 +100,15 @@ class ContactListState extends ChangeNotifier { } void updateUnreadMessages(String forOnion, int newVal) { - _contacts.sort((ContactInfoState a, ContactInfoState b) { return b.unreadMessages - a.unreadMessages; }); + _contacts.sort((ContactInfoState a, ContactInfoState b) { + return b.unreadMessages - a.unreadMessages; + }); // if(changed) { notifyListeners(); //} } - List get contacts => _contacts.sublist(0);//todo: copy?? dont want caller able to bypass changenotifier + List get contacts => _contacts.sublist(0); //todo: copy?? dont want caller able to bypass changenotifier ContactInfoState getContact(String onion) { int idx = _contacts.indexWhere((element) => element.onion == onion); @@ -127,7 +123,13 @@ class ProfileInfoState extends ChangeNotifier { String _imagePath = ""; int _unreadMessages = 0; - ProfileInfoState({this.onion, nickname = "", imagePath = "", unreadMessages = 0, contactsJson = "",}){ + ProfileInfoState({ + this.onion, + nickname = "", + imagePath = "", + unreadMessages = 0, + contactsJson = "", + }) { this._nickname = nickname; this._imagePath = imagePath; this._unreadMessages = unreadMessages; @@ -135,17 +137,15 @@ class ProfileInfoState extends ChangeNotifier { if (contactsJson != null && contactsJson != "" && contactsJson != "null") { print("decoding " + contactsJson); List contacts = jsonDecode(contactsJson); - this._contacts.addAll( - contacts.map((contact){ - return ContactInfoState( - profileOnion: this.onion, - onion: contact["onion"], - nickname: contact["name"], - status: contact["status"], - imagePath: contact["picture"], - ); - }) - ); + this._contacts.addAll(contacts.map((contact) { + return ContactInfoState( + profileOnion: this.onion, + onion: contact["onion"], + nickname: contact["name"], + status: contact["status"], + imagePath: contact["picture"], + ); + })); } } diff --git a/lib/opaque.dart.bak b/lib/opaque.dart.bak deleted file mode 100644 index 7b5e165..0000000 --- a/lib/opaque.dart.bak +++ /dev/null @@ -1,509 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT BY HAND AS CHANGES WILL BE OVERRIDDEN. -// TO EDIT THE THEME, SEE https://git.openprivacy.ca/openprivacy/opaque/ -// FOR HOW THIS FILE IS GENERATED, SEE ../regenerate_opaque_theme.sh - - -import 'dart:ui'; -import 'dart:core'; -abstract class OpaqueThemeType { - static final Color red = Color(0xFFFF0000); - Color backgroundMainColor(){return red;} - Color backgroundPaneColor(){return red;} - Color backgroundHilightElementColor(){return red;} - - Color dividerColor(){return red;} - - Color mainTextColor(){return red;} - Color altTextColor(){return red;} - Color hilightElementTextColor(){return red;} - - Color defaultButtonColor(){return red;} - Color defaultButtonActiveColor(){return red;} - Color defaultButtonTextColor(){return red;} - Color defaultButtonDisabledColor(){return red;} - Color defaultButtonDisabledTextColor(){return red;} - Color altButtonColor(){return red;} - Color altButtonTextColor(){return red;} - Color altButtonDisabledColor(){return red;} - Color altButtonDisabledTextColor(){return red;} - - Color textfieldBackgroundColor(){return red;} - Color textfieldBorderColor(){return red;} - Color textfieldTextColor(){return red;} - Color textfieldErrorColor(){return red;} - Color textfieldButtonColor(){return red;} - Color textfieldButtonTextColor(){return red;} - - Color scrollbarDefaultColor(){return red;} - Color scrollbarActiveColor(){return red;} - - Color portraitOnlineBorderColor(){return red;} - Color portraitOnlineBackgroundColor(){return red;} - Color portraitOnlineTextColor(){return red;} - Color portraitConnectingBorderColor(){return red;} - Color portraitConnectingBackgroundColor(){return red;} - Color portraitConnectingTextColor(){return red;} - Color portraitOfflineBorderColor(){return red;} - Color portraitOfflineBackgroundColor(){return red;} - Color portraitOfflineTextColor(){return red;} - Color portraitBlockedBorderColor(){return red;} - Color portraitBlockedBackgroundColor(){return red;} - Color portraitBlockedTextColor(){return red;} - - Color portraitOnlineBadgeColor(){return red;} - Color portraitOfflineBadgeColor(){return red;} - - - Color portraitContactBadgeColor(){return red;} - Color portraitContactBadgeTextColor(){return red;} - Color portraitProfileBadgeColor(){return red;} - Color portraitProfileBadgeTextColor(){return red;} - - Color portraitOverlayOfflineColor(){return red;} - - Color dropShadowColor(){return red;} - Color dropShadowPaneColor(){return red;} - Color toggleColor(){return red;} - Color toggleOnColor(){return red;} - Color toggleOffColor(){return red;} - Color sliderButtonColor(){return red;} - Color sliderBarLeftColor(){return red;} - Color sliderBarRightColor(){return red;} - Color boxCheckedColor(){return red;} - - - Color toolbarIconColor(){return red;} - Color toolbarMainColor(){return red;} - Color toolbarAltColor(){return red;} - - Color statusbarDisconnectedInternetColor(){return red;} - Color statusbarDisconnectedInternetFontColor(){return red;} - Color statusbarDisconnectedTorFontColor(){return red;} - Color statusbarDisconnectedTorColor(){return red;} - Color statusbarConnectingColor(){return red;} - Color statusbarConnectingFontColor(){return red;} - Color statusbarOnlineColor(){return red;} - Color statusbarOnlineFontColor(){return red;} - - Color chatOverlayWarningTextColor(){return red;} - Color messageFromMeBackgroundColor(){return red;} - Color messageFromMeTextColor(){return red;} - Color messageFromOtherBackgroundColor(){return red;} - Color messageFromOtherTextColor(){return red;} - - Color messageStatusNormalColor(){return red;} - Color messageStatusBlockedColor(){return red;} - Color messageStatusBlockedTextColor(){return red;} - Color messageStatusAlertColor(){return red;} - Color messageStatusAlertTextColor(){return red;} - - - // ... more to come - - -} - - - - -class CwtchDark extends OpaqueThemeType { - static final Color darkGreyPurple = Color(0xFF281831); - static final Color deepPurple = Color(0xFF422850); - static final Color mauvePurple = Color(0xFF8E64A5); - static final Color purple = Color(0xFFDFB9DE); - static final Color whitePurple = Color(0xFFE3DFE4); - static final Color softPurple = Color(0xFFFDF3FC); - static final Color pink = Color(0xFFE85DA1); - static final Color hotPink = Color(0xFFD01972); - static final Color lightGrey = Color(0xFF9E9E9E); - static final Color softGreen = Color(0xFFA0FFB0); - static final Color softRed = Color(0xFFFFA0B0); - - Color backgroundMainColor() { return darkGreyPurple; } - Color backgroundPaneColor() { return darkGreyPurple; } - Color backgroundHilightElementColor() { return deepPurple; } - - Color dividerColor() { return deepPurple; } - - Color mainTextColor() { return whitePurple; } - Color altTextColor() { return whitePurple; } - Color hilightElementTextColor() { return purple; } - Color defaultButtonColor() { return hotPink; } - Color defaultButtonActiveColor() { return pink; } - Color defaultButtonTextColor() { return whitePurple; } - Color defaultButtonDisabledColor() { return deepPurple; } - Color defaultButtonDisabledTextColor() { return darkGreyPurple; } - Color altButtonColor() { return darkGreyPurple; } - Color altButtonTextColor() { return purple; } - Color altButtonDisabledColor() { return darkGreyPurple; } - Color altButtonDisabledTextColor() { return purple; } - - Color textfieldBackgroundColor() { return deepPurple; } - Color textfieldBorderColor() { return deepPurple; } - Color textfieldTextColor() { return purple; } - Color textfieldErrorColor() { return hotPink; } - Color textfieldButtonColor() { return purple; } - Color textfieldButtonTextColor() { return darkGreyPurple; } - - Color scrollbarDefaultColor() { return purple; } - Color scrollbarActiveColor() { return hotPink; } - - Color portraitOnlineBorderColor() { return whitePurple; } - Color portraitOnlineBackgroundColor() { return whitePurple; } - Color portraitOnlineTextColor() { return whitePurple; } - Color portraitConnectingBorderColor() { return purple; } //mauvePurple - Color portraitConnectingBackgroundColor() { return purple; } //darkGreyPurple - Color portraitConnectingTextColor() { return purple; } - Color portraitOfflineBorderColor() { return purple; } - Color portraitOfflineBackgroundColor() { return purple; } - Color portraitOfflineTextColor() { return purple; } - Color portraitBlockedBorderColor() { return lightGrey; } - Color portraitBlockedBackgroundColor() { return lightGrey; } - Color portraitBlockedTextColor() { return lightGrey; } - - Color portraitOnlineBadgeColor() { return softGreen; } - Color portraitOfflineBadgeColor() { return softRed; } - - Color portraitContactBadgeColor() { return hotPink; } - Color portraitContactBadgeTextColor() { return whitePurple; } - Color portraitProfileBadgeColor() { return mauvePurple; } - Color portraitProfileBadgeTextColor() { return darkGreyPurple; } - - Color portraitOverlayOfflineColor() { return mauvePurple; } - - Color dropShadowColor() { return mauvePurple; } - Color dropShadowPaneColor() { return darkGreyPurple; } - - Color toggleColor() { return darkGreyPurple; } - Color toggleOnColor() { return whitePurple; } - Color toggleOffColor() { return deepPurple; } - Color sliderButtonColor() { return whitePurple; } - Color sliderBarLeftColor() { return mauvePurple; } - Color sliderBarRightColor() { return mauvePurple; } - Color boxCheckedColor() { return hotPink; } - - Color toolbarIconColor() { return whitePurple; } - Color toolbarMainColor() { return darkGreyPurple; } - Color toolbarAltColor() { return deepPurple; } - - Color statusbarDisconnectedInternetColor() { return whitePurple; } - Color statusbarDisconnectedInternetFontColor() { return deepPurple; } - Color statusbarDisconnectedTorColor() { return darkGreyPurple; } - Color statusbarDisconnectedTorFontColor() { return whitePurple; } - Color statusbarConnectingColor() { return deepPurple; } - Color statusbarConnectingFontColor() { return whitePurple; } - Color statusbarOnlineColor() { return mauvePurple; } - Color statusbarOnlineFontColor() { return whitePurple; } - - Color chatOverlayWarningTextColor() { return purple; } - - Color messageFromMeBackgroundColor() { return mauvePurple; } - Color messageFromMeTextColor() { return whitePurple; } - Color messageFromOtherBackgroundColor() { return deepPurple; } - Color messageFromOtherTextColor() { return whitePurple; } - - Color messageStatusNormalColor() { return deepPurple; } - Color messageStatusBlockedColor() { return lightGrey; } - Color messageStatusBlockedTextColor() { return whitePurple; } - Color messageStatusAlertColor() { return mauvePurple; } - Color messageStatusAlertTextColor() { return whitePurple; } -} - - - - -class CwtchLight extends OpaqueThemeType { - static final Color whitePurple = Color(0xFFFFFDFF); - static final Color softPurple = Color(0xFFFDF3FC); - static final Color purple = Color(0xFFDFB9DE); - static final Color brightPurple = Color(0xFF760388); - static final Color darkPurple = Color(0xFF350052); - static final Color greyPurple = Color(0xFF775F84); - static final Color pink = Color(0xFFE85DA1); - static final Color hotPink = Color(0xFFD01972); - static final Color lightGrey = Color(0xFFB3B6B3); - static final Color softGreen = Color(0xFFA0FFB0); - static final Color softRed = Color(0xFFFFA0B0); - - Color backgroundMainColor() { return whitePurple; } - Color backgroundPaneColor() { return softPurple; } - Color backgroundHilightElementColor() { return softPurple; } - - Color dividerColor() { return purple; } - - Color mainTextColor() { return darkPurple; } - Color altTextColor() { return purple; } - Color hilightElementTextColor() { return darkPurple; } - - Color defaultButtonColor() { return hotPink; } - Color defaultButtonActiveColor() { return pink; } - Color defaultButtonTextColor() { return whitePurple; } - Color defaultButtonDisabledColor() { return purple; } - Color defaultButtonDisabledTextColor() { return whitePurple; } - Color altButtonColor() { return whitePurple; } - Color altButtonTextColor() { return purple; } - Color altButtonDisabledColor() { return softPurple; } - Color altButtonDisabledTextColor() { return purple; } - - Color textfieldBackgroundColor() { return whitePurple; } - Color textfieldBorderColor() { return purple; } - Color textfieldTextColor() { return purple; } - Color textfieldErrorColor() { return hotPink; } - Color textfieldButtonColor() { return hotPink; } - Color textfieldButtonTextColor() { return whitePurple; } - - Color scrollbarDefaultColor() { return darkPurple; } - Color scrollbarActiveColor() { return hotPink; } - - Color portraitOnlineBorderColor() { return darkPurple; } - Color portraitOnlineBackgroundColor() { return darkPurple; } - Color portraitOnlineTextColor() { return darkPurple; } - Color portraitConnectingBorderColor() { return greyPurple; } - Color portraitConnectingBackgroundColor() { return greyPurple; } - Color portraitConnectingTextColor() { return greyPurple; } - Color portraitOfflineBorderColor() { return greyPurple; } //purple - Color portraitOfflineBackgroundColor() { return greyPurple; } //purple - Color portraitOfflineTextColor() { return greyPurple; }//purple - Color portraitBlockedBorderColor() { return lightGrey; } - Color portraitBlockedBackgroundColor() { return lightGrey; } - Color portraitBlockedTextColor() { return lightGrey; } - - Color portraitOnlineBadgeColor() { return softGreen; } - Color portraitOfflineBadgeColor() { return softRed; } - - Color portraitContactBadgeColor() { return hotPink; } - Color portraitContactBadgeTextColor() { return whitePurple; } - Color portraitProfileBadgeColor() { return brightPurple; } - Color portraitProfileBadgeTextColor() { return whitePurple; } - - Color portraitOverlayOfflineColor() { return whitePurple; } - - Color dropShadowColor() { return purple; } - Color dropShadowPaneColor() { return purple; } - - Color toggleColor() { return whitePurple; } - Color toggleOnColor() { return hotPink; } - Color toggleOffColor() { return purple; } - Color sliderButtonColor() { return pink; } - Color sliderBarLeftColor() { return purple; } - Color sliderBarRightColor() { return purple; } - Color boxCheckedColor() { return darkPurple; } - - Color toolbarIconColor() { return darkPurple; } - Color toolbarMainColor() { return whitePurple; } - Color toolbarAltColor() { return softPurple; } - - Color statusbarDisconnectedInternetColor() { return softPurple; } - Color statusbarDisconnectedInternetFontColor() { return darkPurple; } - Color statusbarDisconnectedTorColor() { return purple; } - Color statusbarDisconnectedTorFontColor() { return darkPurple; } - Color statusbarConnectingColor() { return greyPurple; } - Color statusbarConnectingFontColor() { return whitePurple; } - Color statusbarOnlineColor() { return darkPurple; } - Color statusbarOnlineFontColor() { return whitePurple; } - - Color chatOverlayWarningTextColor() { return purple; } - - Color messageFromMeBackgroundColor() { return darkPurple; } - Color messageFromMeTextColor() { return whitePurple; } - Color messageFromOtherBackgroundColor() { return purple; } - Color messageFromOtherTextColor() { return darkPurple; } - - Color messageStatusNormalColor() { return purple; } - Color messageStatusBlockedColor() { return lightGrey; } - Color messageStatusBlockedTextColor() { return whitePurple; } - Color messageStatusAlertColor() { return hotPink; } - Color messageStatusAlertTextColor() { return whitePurple; } -} - - - - - - - -class Opaque extends OpaqueThemeType { - Color backgroundMainColor() { return current().backgroundMainColor(); } - Color backgroundPaneColor() { return current().backgroundPaneColor(); } - Color backgroundHilightElementColor() { return current().backgroundHilightElementColor(); } - - Color dividerColor() { return current().dividerColor(); } - - Color mainTextColor() { return current().mainTextColor(); } - Color altTextColor() { return current().altTextColor(); } - Color hilightElementTextColor() { return current().hilightElementTextColor(); } - - Color defaultButtonColor() { return current().defaultButtonColor(); } - Color defaultButtonActiveColor() { return current().defaultButtonActiveColor(); } - Color defaultButtonTextColor() { return current().defaultButtonTextColor(); } - Color defaultButtonDisabledColor() { return current().defaultButtonDisabledColor(); } - Color defaultButtonDisabledTextColor() { return current().defaultButtonDisabledTextColor(); } - Color altButtonColor() { return current().altButtonColor(); } - Color altButtonTextColor() { return current().altButtonTextColor(); } - Color altButtonDisabledColor() { return current().altButtonDisabledColor(); } - Color altButtonDisabledTextColor() { return current().altButtonDisabledTextColor(); } - - Color textfieldBackgroundColor() { return current().textfieldBackgroundColor(); } - Color textfieldBorderColor() { return current().textfieldBorderColor(); } - Color textfieldTextColor() { return current().textfieldTextColor(); } - Color textfieldErrorColor() { return current().textfieldErrorColor(); } - Color textfieldButtonColor() { return current().textfieldButtonColor(); } - Color textfieldButtonTextColor() { return current().textfieldButtonTextColor(); } - - - Color dropShadowColor() { return current().dropShadowColor(); } - Color dropShadowPaneColor() { return current().dropShadowPaneColor(); } - - Color portraitOnlineBorderColor() { return current().portraitOnlineBorderColor(); } - Color portraitOnlineBackgroundColor() { return current().portraitOnlineBackgroundColor(); } - Color portraitOnlineTextColor() { return current().portraitOnlineTextColor(); } - Color portraitConnectingBorderColor() { return current().portraitConnectingBorderColor(); } - Color portraitConnectingBackgroundColor() { return current().portraitConnectingBackgroundColor(); } - Color portraitConnectingTextColor() { return current().portraitConnectingTextColor(); } - Color portraitOfflineBorderColor() { return current().portraitOfflineBorderColor(); } - Color portraitOfflineBackgroundColor() { return current().portraitOfflineBackgroundColor(); } - Color portraitOfflineTextColor() { return current().portraitOfflineTextColor(); } - Color portraitBlockedBorderColor() { return current().portraitBlockedBorderColor(); } - Color portraitBlockedBackgroundColor() { return current().portraitBlockedBackgroundColor(); } - Color portraitBlockedTextColor() { return current().portraitBlockedTextColor(); } - - Color portraitOnlineBadgeColor() { return current().portraitOnlineBadgeColor(); } - Color portraitOfflineBadgeColor() { return current().portraitOfflineBadgeColor(); } - - Color portraitContactBadgeColor() { return current().portraitContactBadgeColor(); } - Color portraitContactBadgeTextColor() { return current().portraitContactBadgeTextColor(); } - Color portraitProfileBadgeColor() { return current().portraitProfileBadgeColor(); } - Color portraitProfileBadgeTextColor() { return current().portraitProfileBadgeTextColor(); } - - Color portraitOverlayOfflineColor() { return current().portraitOverlayOfflineColor(); } - - Color toggleColor() { return current().toggleColor(); } - Color toggleOffColor() { return current().toggleOffColor(); } - Color toggleOnColor() { return current().toggleOnColor(); } - Color sliderButtonColor() { return current().sliderButtonColor(); } - Color sliderBarLeftColor() { return current().sliderBarLeftColor(); } - Color sliderBarRightColor() { return current().sliderBarRightColor(); } - Color boxCheckedColor() { return current().boxCheckedColor(); } - - - Color toolbarIconColor() { return current().toolbarIconColor(); } - Color toolbarMainColor() { return current().toolbarMainColor(); } - Color toolbarAltColor() { return current().toolbarAltColor(); } - - Color statusbarDisconnectedInternetColor() { return current().statusbarDisconnectedInternetColor(); } - Color statusbarDisconnectedInternetFontColor() { return current().statusbarDisconnectedInternetFontColor(); } - Color statusbarDisconnectedTorFontColor() { return current().statusbarDisconnectedTorFontColor(); } - Color statusbarDisconnectedTorColor() { return current().statusbarDisconnectedTorColor(); } - Color statusbarConnectingColor() { return current().statusbarConnectingColor(); } - Color statusbarConnectingFontColor() { return current().statusbarConnectingFontColor(); } - Color statusbarOnlineColor() { return current().statusbarOnlineColor(); } - Color statusbarOnlineFontColor() { return current().statusbarOnlineFontColor(); } - - Color chatOverlayWarningTextColor() { return current().chatOverlayWarningTextColor(); } - Color messageFromMeBackgroundColor() { return current().messageFromMeBackgroundColor(); } - Color messageFromMeTextColor() { return current().messageFromMeTextColor(); } - Color messageFromOtherBackgroundColor() { return current().messageFromOtherBackgroundColor(); } - Color messageFromOtherTextColor() { return current().messageFromOtherTextColor(); } - - Color messageStatusNormalColor() { return current().messageStatusNormalColor(); } - Color messageStatusBlockedColor() { return current().messageStatusBlockedColor(); } - Color messageStatusBlockedTextColor() { return current().messageStatusBlockedTextColor(); } - Color messageStatusAlertColor() { return current().messageStatusAlertColor(); } - Color messageStatusAlertTextColor() { return current().messageStatusAlertTextColor(); } - - Color scrollbarDefaultColor() { return current().scrollbarDefaultColor(); } - Color scrollbarActiveColor() { return current().scrollbarActiveColor(); } - - - var sidePaneMinSizeBase = [200, 400, 600]; - int sidePaneMinSize() { return sidePaneMinSizeBase[p[scale]]+200/*for debugging*/; } - var chatPaneMinSizeBase = [300, 400, 500]; - int chatPaneMinSize() { return chatPaneMinSizeBase[p[scale]]; } - int doublePaneMinSize() { return sidePaneMinSize() + chatPaneMinSize(); } - - static final OpaqueThemeType dark = CwtchDark(); - static final OpaqueThemeType light = CwtchLight(); - static static Opaque current() { return dark; } - - -int scale = 2; - static final String gcdOS = "linux"; - - - - - - - - - - - - - - var p = [0, 1, 1, 1, 2]; - var t = [0, 0, 1, 2, 2]; - - - - - - var paddingMinimalBase = [1, 4, 6]; - int paddingMinimal() { return paddingMinimalBase[p[scale]]; } - var paddingSmallBase = [3, 10, 15]; - int paddingSmall() { return paddingSmallBase[p[scale]]; } - var paddingStandardBase = [8, 20, 30]; - int paddingStandard() { return paddingStandardBase[p[scale]]; } - var paddingLargeBase = [10, 30, 40]; - int paddingLarge() { return paddingLargeBase[p[scale]]; } - - var paddingClickTargetBase = gcdOS == "android" ? [10, 40, 100] : [3, 10, 15]; - int paddingClickTarget() { return paddingClickTargetBase[p[scale]]; } - - - - - - var textSmallPtBase = [8, 12, 16]; - int textSmallPt() { return textSmallPtBase[t[scale]]; } - var textMediumPtBase = [10, 16, 24]; - int textMediumPt() { return textMediumPtBase[t[scale]]; } - var textLargePtBase = [16, 24, 32]; - int textLargePt() { return textLargePtBase[t[scale]]; } - - var textSubHeaderPtBase = [12, 18, 26]; - int textSubHeaderPt() { return textHeaderPtBase[t[scale]]; } - var textHeaderPtBase = [16, 24, 32]; - int textHeaderPt() { return textHeaderPtBase[t[scale]]; } - - - - - - var uiIconSizeSBase = [8, 16, 24]; - int uiIconSizeS() { return uiIconSizeSBase[p[scale]]; } - var uiIconSizeMBase = [24, 32, 48]; - int uiIconSizeM() { return uiIconSizeMBase[p[scale]]; } - var uiIconSizeLBase = [32, 48, 60]; - int uiIconSizeL() { return uiIconSizeLBase[p[scale]]; } - - var uiEmojiSizeBase = [24, 32, 48]; - int uiEmojiSize() { return uiEmojiSizeBase[p[scale]]; } - var contactPortraitSizeBase = [60, 72, 84]; - int contactPortraitSize() { return contactPortraitSizeBase[p[scale]]; } - - - - - - - int badgeTextSize() { return 12; } - int statusTextSize() { return 12; } - - - int chatSize() { return textMediumPt(); } - - int tabSize() { return textMediumPt(); } - - -} diff --git a/lib/settings.dart b/lib/settings.dart index 62e789a..f9d047b 100644 --- a/lib/settings.dart +++ b/lib/settings.dart @@ -1,3 +1,4 @@ +import 'dart:collection'; import 'dart:ui'; import 'dart:core'; @@ -6,38 +7,57 @@ import 'package:package_info_plus/package_info_plus.dart'; import 'opaque.dart'; +/// Settings govern the *Globally* relevant settings like Locale, Theme and Experiments. +/// We also provide access to the version information here as it is also accessed from the +/// Settings Pane. class Settings extends ChangeNotifier { Locale locale; - PackageInfo packageInfo; - OpaqueThemeType theme; + bool experimentsEnabled; + HashMap experiments = HashMap.identity(); + /// Set the dark theme. void setDark() { theme = Opaque.dark; notifyListeners(); } + /// Set the Light theme. void setLight() { theme = Opaque.light; notifyListeners(); } + /// Get access to the current theme. OpaqueThemeType current() { return theme; } + /// 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) { - print("Settings ${settings}"); - switchLocale(Locale(settings["Locale"])); + // Set Theme and notify listeners if (settings["Theme"] == "light") { this.setLight(); } else { this.setDark(); } + + // Set Locale and notify listeners + switchLocale(Locale(settings["Locale"])); + + // Decide whether to enable Experiments + experimentsEnabled = settings["ExperimentsEnabled"]; + + // Set the internal experiments map. Casting from the Map that we get from JSON + experiments = new HashMap.from(settings["Experiments"]); + + // Push the experimental settings to Consumers of Settings notifyListeners(); } + /// Initialize the Package Version information initPackageInfo() { PackageInfo.fromPlatform().then((PackageInfo newPackageInfo) { packageInfo = newPackageInfo; @@ -45,13 +65,42 @@ class Settings extends ChangeNotifier { }); } + // Switch the Locale of the App switchLocale(Locale newLocale) { locale = newLocale; notifyListeners(); } + /// Turn Experiments On, this will also have the side effect of enabling any + /// Experiments that have been previously activated. + enableExperiments() { + experimentsEnabled = true; + notifyListeners(); + } + + /// Turn Experiments Off. This will disable **all** active experiments. + /// Note: This will not set the preference for individual experiments, if experiments are enabled + /// any experiments that were active previously will become active again unless they are explicitly disabled. + disableExperiments() { + experimentsEnabled = false; + notifyListeners(); + } + + /// Turn on a specific experiment. + enableExperiment(String key) { + experiments.update(key, (value) => true, ifAbsent: () => true); + } + + /// Turn off a specific experiment + disableExperiment(String key) { + experiments.update(key, (value) => false, ifAbsent: () => false); + } + + /// Construct a default settings object. Settings(this.locale, this.theme); + /// Convert this Settings object to a JSON representation for serialization on the + /// event bus. dynamic asJson() { var themeString = "light"; if (theme == Opaque.dark) { @@ -62,8 +111,8 @@ class Settings extends ChangeNotifier { "Locale": this.locale.languageCode, "Theme": themeString, "PreviousPid": -1, - "ExperimentsEnabled": false, - "Experiments": {}, + "ExperimentsEnabled": this.experimentsEnabled, + "Experiments": experiments, "StateRootPane": 0, "FirstTime": false }; diff --git a/lib/views/addeditprofileview.dart b/lib/views/addeditprofileview.dart index eb3af99..a684552 100644 --- a/lib/views/addeditprofileview.dart +++ b/lib/views/addeditprofileview.dart @@ -47,9 +47,7 @@ class _AddEditProfileViewState extends State { ctrlrOnion.text = Provider.of(context).onion; return Scaffold( appBar: AppBar( - title: Text(Provider.of(context).onion.isEmpty - ? AppLocalizations.of(context).addProfileTitle - : AppLocalizations.of(context).editProfileTitle), + title: Text(Provider.of(context).onion.isEmpty ? AppLocalizations.of(context).addProfileTitle : AppLocalizations.of(context).editProfileTitle), ), body: _buildForm(), ); @@ -66,8 +64,7 @@ class _AddEditProfileViewState extends State { // We used SizedBox for inter-widget height padding in columns, otherwise elements can render a little too close together. Widget _buildForm() { return Consumer(builder: (context, theme, child) { - return LayoutBuilder( - builder: (BuildContext context, BoxConstraints viewportConstraints) { + return LayoutBuilder(builder: (BuildContext context, BoxConstraints viewportConstraints) { return Scrollbar( isAlwaysShown: true, child: SingleChildScrollView( @@ -81,306 +78,184 @@ class _AddEditProfileViewState extends State { child: Container( margin: EdgeInsets.all(30), padding: EdgeInsets.all(20), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ + child: Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ + Visibility( + visible: Provider.of(context).onion.isNotEmpty, + child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [ + SizedBox( + width: 120, + height: 120, + child: ClipOval( + child: SizedBox( + width: 120, + height: 120, + child: Container( + color: Colors.white, + width: 120, + height: 120, + child: Image( + image: AssetImage("assets/" + Provider.of(context).imagePath), + width: 100, + height: 100, + ))), + ), + ) + ])), + Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + CwtchLabel(label: AppLocalizations.of(context).displayNameLabel), + SizedBox( + height: 20, + ), + CwtchTextField( + controller: ctrlrNick, + labelText: AppLocalizations.of(context).yourDisplayName, + validator: (value) { + if (value.isEmpty) { + return "Please enter a display name"; + } + return null; + }, + ), + ]), + Visibility( + visible: Provider.of(context).onion.isNotEmpty, + child: Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ + SizedBox( + height: 20, + ), + CwtchLabel(label: AppLocalizations.of(context).addressLabel), + SizedBox( + height: 20, + ), + CwtchButtonTextField( + controller: ctrlrOnion, + onPressed: _copyOnion, + icon: Icon(Icons.copy), + tooltip: AppLocalizations.of(context).copyBtn, + ) + ])), + // We only allow setting password types on profile creation + Visibility( + visible: Provider.of(context).onion.isEmpty, + child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [ + Radio( + value: false, + groupValue: usePassword, + onChanged: _handleSwitchPassword, + ), + Text( + AppLocalizations.of(context).radioNoPassword, + style: TextStyle(color: theme.current().mainTextColor()), + ), + Radio( + value: true, + groupValue: usePassword, + onChanged: _handleSwitchPassword, + ), + Text( + AppLocalizations.of(context).radioUsePassword, + style: TextStyle(color: theme.current().mainTextColor()), + ), + ])), + SizedBox( + height: 20, + ), + Visibility( + visible: usePassword, + child: Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Visibility( - visible: - Provider.of(context) - .onion - .isNotEmpty, - child: Row( - mainAxisAlignment: - MainAxisAlignment.center, - children: [ - SizedBox( - width: 120, - height: 120, - child: ClipOval( - child: SizedBox( - width: 120, - height: 120, - child: Container( - color: Colors.white, - width: 120, - height: 120, - child: Image( - image: AssetImage("assets/" + - Provider.of( - context) - .imagePath), - width: 100, - height: 100, - ))), - ), - ) - ])), - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - CwtchLabel( - label: AppLocalizations.of(context) - .displayNameLabel), + visible: Provider.of(context, listen: false).onion.isNotEmpty, + child: Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ + CwtchLabel(label: AppLocalizations.of(context).currentPasswordLabel), SizedBox( height: 20, ), - CwtchTextField( - controller: ctrlrNick, - labelText: - AppLocalizations.of(context) - .yourDisplayName, + CwtchPasswordField( + controller: ctrlrOldPass, validator: (value) { - if (value.isEmpty) { - return "Please enter a display name"; + // Password field can be empty when just updating the profile, not on creation + if (Provider.of(context, listen: false).onion.isEmpty && value.isEmpty && usePassword) { + return AppLocalizations.of(context).passwordErrorEmpty; } return null; }, ), - ]), - Visibility( - visible: - Provider.of(context) - .onion - .isNotEmpty, - child: Column( - mainAxisAlignment: - MainAxisAlignment.start, - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - SizedBox( - height: 20, - ), - CwtchLabel( - label: - AppLocalizations.of(context) - .addressLabel), - SizedBox( - height: 20, - ), - CwtchButtonTextField( - controller: ctrlrOnion, - onPressed: _copyOnion, - icon: Icon(Icons.copy), - tooltip: - AppLocalizations.of(context) - .copyBtn, - ) - ])), - // We only allow setting password types on profile creation - Visibility( - visible: - Provider.of(context) - .onion - .isEmpty, - child: Row( - mainAxisAlignment: - MainAxisAlignment.center, - children: [ - Radio( - value: false, - groupValue: usePassword, - onChanged: _handleSwitchPassword, - ), - Text( - AppLocalizations.of(context) - .radioNoPassword, - style: TextStyle( - color: theme - .current() - .mainTextColor()), - ), - Radio( - value: true, - groupValue: usePassword, - onChanged: _handleSwitchPassword, - ), - Text( - AppLocalizations.of(context) - .radioUsePassword, - style: TextStyle( - color: theme - .current() - .mainTextColor()), - ), - ])), + SizedBox( + height: 20, + ), + ])), + CwtchLabel(label: AppLocalizations.of(context).password1Label), SizedBox( height: 20, ), - Visibility( - visible: usePassword, - child: Column( - mainAxisAlignment: - MainAxisAlignment.start, - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Visibility( - visible: - Provider.of( - context, - listen: false) - .onion - .isNotEmpty, - child: Column( - mainAxisAlignment: - MainAxisAlignment.start, - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - CwtchLabel( - label: AppLocalizations - .of(context) - .currentPasswordLabel), - SizedBox( - height: 20, - ), - CwtchPasswordField( - controller: ctrlrOldPass, - validator: (value) { - // Password field can be empty when just updating the profile, not on creation - if (Provider.of( - context, - listen: - false) - .onion - .isEmpty && - value.isEmpty && - usePassword) { - return AppLocalizations - .of(context) - .passwordErrorEmpty; - } - return null; - }, - ), - SizedBox( - height: 20, - ), - ])), - CwtchLabel( - label: - AppLocalizations.of(context) - .password1Label), - SizedBox( - height: 20, - ), - CwtchPasswordField( - controller: ctrlrPass, - validator: (value) { - // Password field can be empty when just updating the profile, not on creation - if (Provider.of( - context, - listen: false) - .onion - .isEmpty && - value.isEmpty && - usePassword) { - return AppLocalizations.of( - context) - .passwordErrorEmpty; - } - if (value != - ctrlrPass2.value.text) { - return AppLocalizations.of( - context) - .passwordErrorMatch; - } - return null; - }, - ), - SizedBox( - height: 20, - ), - CwtchLabel( - label: - AppLocalizations.of(context) - .password2Label), - SizedBox( - height: 20, - ), - CwtchPasswordField( - controller: ctrlrPass2, - validator: (value) { - // Password field can be empty when just updating the profile, not on creation - if (Provider.of( - context, - listen: false) - .onion - .isEmpty && - value.isEmpty && - usePassword) { - return AppLocalizations.of( - context) - .passwordErrorEmpty; - } - if (value != - ctrlrPass.value.text) { - return AppLocalizations.of( - context) - .passwordErrorMatch; - } - return null; - }), - ]), + CwtchPasswordField( + controller: ctrlrPass, + validator: (value) { + // Password field can be empty when just updating the profile, not on creation + if (Provider.of(context, listen: false).onion.isEmpty && value.isEmpty && usePassword) { + return AppLocalizations.of(context).passwordErrorEmpty; + } + if (value != ctrlrPass2.value.text) { + return AppLocalizations.of(context).passwordErrorMatch; + } + return null; + }, ), SizedBox( height: 20, ), - ElevatedButton( - onPressed: _createPressed, - style: ElevatedButton.styleFrom( - primary: theme - .current() - .defaultButtonColor()), - child: Text( - Provider.of(context) - .onion - .isEmpty - ? AppLocalizations.of(context) - .addNewProfileBtn - : AppLocalizations.of(context) - .saveProfileBtn), + CwtchLabel(label: AppLocalizations.of(context).password2Label), + SizedBox( + height: 20, ), - Visibility( - visible: Provider.of( - context, - listen: false) - .onion - .isNotEmpty, - child: Column( - mainAxisAlignment: - MainAxisAlignment.start, - crossAxisAlignment: - CrossAxisAlignment.end, - children: [ - SizedBox( - height: 20, - ), - ElevatedButton.icon( - onPressed: () { - showAlertDialog(context); - }, - style: ElevatedButton.styleFrom( - primary: theme - .current() - .defaultButtonColor()), - icon: Icon(Icons.delete_forever), - label: Text( - AppLocalizations.of(context) - .deleteBtn), - ) - ])) - ])))))); + CwtchPasswordField( + controller: ctrlrPass2, + validator: (value) { + // Password field can be empty when just updating the profile, not on creation + if (Provider.of(context, listen: false).onion.isEmpty && value.isEmpty && usePassword) { + return AppLocalizations.of(context).passwordErrorEmpty; + } + if (value != ctrlrPass.value.text) { + return AppLocalizations.of(context).passwordErrorMatch; + } + return null; + }), + ]), + ), + SizedBox( + height: 20, + ), + ElevatedButton( + onPressed: _createPressed, + style: ElevatedButton.styleFrom(primary: theme.current().defaultButtonColor()), + child: Text(Provider.of(context).onion.isEmpty ? AppLocalizations.of(context).addNewProfileBtn : AppLocalizations.of(context).saveProfileBtn), + ), + Visibility( + visible: Provider.of(context, listen: false).onion.isNotEmpty, + child: Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.end, children: [ + SizedBox( + height: 20, + ), + Tooltip( + message: AppLocalizations.of(context).enterCurrentPasswordForDelete, + child: ElevatedButton.icon( + onPressed: checkCurrentPassword() + ? null + : () { + showAlertDialog(context); + }, + style: ElevatedButton.styleFrom(primary: theme.current().defaultButtonColor()), + icon: Icon(Icons.delete_forever), + label: Text(AppLocalizations.of(context).deleteBtn), + )) + ])) + ])))))); }); }); } void _copyOnion() { - Clipboard.setData(new ClipboardData( - text: Provider.of(context, listen: false).onion)); + Clipboard.setData(new ClipboardData(text: Provider.of(context, listen: false).onion)); // TODO Toast } @@ -391,14 +266,10 @@ class _AddEditProfileViewState extends State { if (_formKey.currentState.validate()) { if (Provider.of(context, listen: false).onion.isEmpty) { if (usePassword == true) { - Provider.of(context, listen: false) - .cwtch - .CreateProfile(ctrlrNick.value.text, ctrlrPass.value.text); + Provider.of(context, listen: false).cwtch.CreateProfile(ctrlrNick.value.text, ctrlrPass.value.text); Navigator.of(context).pop(); } else { - Provider.of(context, listen: false) - .cwtch - .CreateProfile(ctrlrNick.value.text, "be gay do crime"); + Provider.of(context, listen: false).cwtch.CreateProfile(ctrlrNick.value.text, "be gay do crime"); Navigator.of(context).pop(); } } else { @@ -411,11 +282,7 @@ class _AddEditProfileViewState extends State { }; final json = jsonEncode(event); - Provider.of(context, listen: false) - .cwtch - .SendProfileEvent( - Provider.of(context, listen: false).onion, - json); + Provider.of(context, listen: false).cwtch.SendProfileEvent(Provider.of(context, listen: false).onion, json); Navigator.of(context).pop(); } else { // At this points passwords have been validated to be the same and not empty @@ -426,32 +293,26 @@ class _AddEditProfileViewState extends State { }; final updateNameEventJson = jsonEncode(updateNameEvent); - Provider.of(context, listen: false) - .cwtch - .SendProfileEvent( - Provider.of(context, listen: false).onion, - updateNameEventJson); + Provider.of(context, listen: false).cwtch.SendProfileEvent(Provider.of(context, listen: false).onion, updateNameEventJson); final updatePasswordEvent = { "EventType": "ChangePassword", - "Data": { - "Password": ctrlrOldPass.text, - "NewPassword": ctrlrPass.text - } + "Data": {"Password": ctrlrOldPass.text, "NewPassword": ctrlrPass.text} }; final updatePasswordEventJson = jsonEncode(updatePasswordEvent); - Provider.of(context, listen: false) - .cwtch - .SendProfileEvent( - Provider.of(context, listen: false).onion, - updatePasswordEventJson); + Provider.of(context, listen: false).cwtch.SendProfileEvent(Provider.of(context, listen: false).onion, updatePasswordEventJson); Navigator.of(context).pop(); } } } } + + // TODO Stub - wire this into a libCwtch call. + bool checkCurrentPassword() { + return ctrlrOldPass.value.text.isEmpty; + } } showAlertDialog(BuildContext context) { @@ -459,12 +320,9 @@ showAlertDialog(BuildContext context) { Widget cancelButton = TextButton( child: Text("Cancel"), style: ButtonStyle( - backgroundColor: - MaterialStateProperty.all(Opaque.current().defaultButtonColor()), - foregroundColor: MaterialStateProperty.all( - Opaque.current().defaultButtonTextColor()), - overlayColor: MaterialStateProperty.all( - Opaque.current().defaultButtonActiveColor()), + backgroundColor: MaterialStateProperty.all(Opaque.current().defaultButtonColor()), + foregroundColor: MaterialStateProperty.all(Opaque.current().defaultButtonTextColor()), + overlayColor: MaterialStateProperty.all(Opaque.current().defaultButtonActiveColor()), padding: MaterialStateProperty.all(EdgeInsets.all(20))), onPressed: () { Navigator.of(context).pop(); // dismiss dialog @@ -472,12 +330,9 @@ showAlertDialog(BuildContext context) { ); Widget continueButton = TextButton( style: ButtonStyle( - backgroundColor: - MaterialStateProperty.all(Opaque.current().defaultButtonColor()), - foregroundColor: MaterialStateProperty.all( - Opaque.current().defaultButtonTextColor()), - overlayColor: MaterialStateProperty.all( - Opaque.current().defaultButtonActiveColor()), + backgroundColor: MaterialStateProperty.all(Opaque.current().defaultButtonColor()), + foregroundColor: MaterialStateProperty.all(Opaque.current().defaultButtonTextColor()), + overlayColor: MaterialStateProperty.all(Opaque.current().defaultButtonActiveColor()), padding: MaterialStateProperty.all(EdgeInsets.all(20))), child: Text(AppLocalizations.of(context).deleteProfileConfirmBtn), onPressed: () { diff --git a/lib/views/contactsview.dart b/lib/views/contactsview.dart index 58f60e2..c9e3caa 100644 --- a/lib/views/contactsview.dart +++ b/lib/views/contactsview.dart @@ -18,11 +18,7 @@ class _ContactsViewState extends State { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text("%1's contacts".replaceAll( - "%1", - Provider.of(context).nickname ?? - Provider.of(context).onion ?? - '')), //todo + title: Text("%1's contacts".replaceAll("%1", Provider.of(context).nickname ?? Provider.of(context).onion ?? '')), //todo actions: [ IconButton( icon: Icon(Icons.copy), @@ -41,9 +37,12 @@ class _ContactsViewState extends State { Widget _buildContactList() { final tiles = Provider.of(context).contacts.map((ContactInfoState contact) { - return ChangeNotifierProvider.value(value: contact, child: ContactRow()); + return ChangeNotifierProvider.value(value: contact, child: ContactRow()); }); - final divided = ListTile.divideTiles(context: context, tiles: tiles, ).toList(); + final divided = ListTile.divideTiles( + context: context, + tiles: tiles, + ).toList(); return ListView(children: divided); } @@ -59,9 +58,7 @@ class _ContactsViewState extends State { } void _copyOnion() { - final snackBar = SnackBar( - content: Text( - AppLocalizations.of(context).copiedClipboardNotification)); //todo + final snackBar = SnackBar(content: Text(AppLocalizations.of(context).copiedClipboardNotification)); //todo // Find the Scaffold in the widget tree and use it to show a SnackBar. ScaffoldMessenger.of(context).showSnackBar(snackBar); } diff --git a/lib/views/doublecolview.dart b/lib/views/doublecolview.dart index 1bc340a..04249ac 100644 --- a/lib/views/doublecolview.dart +++ b/lib/views/doublecolview.dart @@ -26,10 +26,7 @@ class _DoubleColumnViewState extends State { child: flwtch.selectedConversation == "" ? Center(child: Text("pick a contact")) : //dev - Container( - child: MessageView( - profile: flwtch.selectedProfile, - conversationHandle: flwtch.selectedConversation)), + Container(child: MessageView(profile: flwtch.selectedProfile, conversationHandle: flwtch.selectedConversation)), ), ], ); diff --git a/lib/views/globalsettingsview.dart b/lib/views/globalsettingsview.dart index 178bbd7..6fdcfe5 100644 --- a/lib/views/globalsettingsview.dart +++ b/lib/views/globalsettingsview.dart @@ -9,6 +9,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import '../main.dart'; +/// Global Settings View provides access to modify all the Globally Relevant Settings including Locale, Theme and Experiments. class GlobalSettingsView extends StatefulWidget { @override _GlobalSettingsViewState createState() => _GlobalSettingsViewState(); @@ -31,69 +32,103 @@ class _GlobalSettingsViewState extends State { } Widget _buildSettingsList() { - return Consumer(builder: (context, theme, child) { - return Center( - child: Column(children: [ - ListTile( - title: Text(AppLocalizations.of(context).settingLanguage, - style: TextStyle(color: theme.current().mainTextColor())), - leading: - Icon(Icons.language, color: theme.current().mainTextColor()), - trailing: DropdownButton( - value: Provider.of(context).locale.languageCode, - onChanged: (String newValue) { - setState(() { - var settings = - Provider.of(context, listen: false); - settings.switchLocale(Locale(newValue, '')); - saveSettings(context); - }); - }, - items: AppLocalizations.supportedLocales - .map>((Locale value) { - return DropdownMenuItem( - value: value.languageCode, - child: Text(getLanguageFull(context, value.languageCode)), - ); - }).toList())), - SwitchListTile( - title: Text(AppLocalizations.of(context).settingTheme, - style: TextStyle(color: theme.current().mainTextColor())), - value: theme.current() == Opaque.light, - onChanged: (bool value) { - if (value) { - theme.setLight(); - } else { - theme.setDark(); - } + return Consumer(builder: (context, settings, child) { + return LayoutBuilder(builder: (BuildContext context, BoxConstraints viewportConstraints) { + return Scrollbar( + isAlwaysShown: true, + child: SingleChildScrollView( + clipBehavior: Clip.antiAlias, + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: viewportConstraints.maxHeight, + ), + child: Column(children: [ + ListTile( + title: Text(AppLocalizations.of(context).settingLanguage, style: TextStyle(color: settings.current().mainTextColor())), + leading: Icon(Icons.language, color: settings.current().mainTextColor()), + trailing: DropdownButton( + value: Provider.of(context).locale.languageCode, + onChanged: (String newValue) { + setState(() { + settings.switchLocale(Locale(newValue, '')); + saveSettings(context); + }); + }, + items: AppLocalizations.supportedLocales.map>((Locale value) { + return DropdownMenuItem( + value: value.languageCode, + child: Text(getLanguageFull(context, value.languageCode)), + ); + }).toList())), + SwitchListTile( + title: Text(AppLocalizations.of(context).settingTheme, style: TextStyle(color: settings.current().mainTextColor())), + value: settings.current() == Opaque.light, + onChanged: (bool value) { + if (value) { + settings.setLight(); + } else { + settings.setDark(); + } - // Save Settings... - saveSettings(context); - }, - secondary: Icon(Icons.lightbulb_outline, - color: theme.current().mainTextColor()), - ), - AboutListTile( - icon: Icon(Icons.info, color: theme.current().mainTextColor()), - applicationIcon: Padding( - padding: EdgeInsets.all(20), - child: Image( - image: AssetImage("assets/knott.png"), - width: 128, - height: 128, - )), - applicationName: "Cwtch (Flutter UI)", - applicationVersion: AppLocalizations.of(context).version.replaceAll( - "%1", - constructVersionString( - Provider.of(context).packageInfo)), - applicationLegalese: '\u{a9} 2021 Open Privacy Research Society', - ), - ])); + // Save Settings... + saveSettings(context); + }, + secondary: Icon(Icons.lightbulb_outline, color: settings.current().mainTextColor()), + ), + SwitchListTile( + title: Text(AppLocalizations.of(context).experimentsEnabled, style: TextStyle(color: settings.current().mainTextColor())), + value: settings.experimentsEnabled, + onChanged: (bool value) { + if (value) { + settings.enableExperiments(); + } else { + settings.disableExperiments(); + } + // Save Settings... + saveSettings(context); + }, + secondary: Icon(Icons.science, color: settings.current().mainTextColor()), + ), + Visibility( + visible: settings.experimentsEnabled, + child: Column( + children: [ + SwitchListTile( + title: Text(AppLocalizations.of(context).enableGroups, style: TextStyle(color: settings.current().mainTextColor())), + value: settings.experiments.containsKey("tapir-groups-experiment") && settings.experiments["tapir-groups-experiment"], + onChanged: (bool value) { + if (value) { + settings.enableExperiment("tapir-groups-experiment"); + } else { + settings.disableExperiment("tapir-groups-experiment"); + } + // Save Settings... + saveSettings(context); + }, + secondary: Icon(Icons.group_sharp, color: settings.current().mainTextColor()), + ), + ], + )), + AboutListTile( + icon: Icon(Icons.info, color: settings.current().mainTextColor()), + applicationIcon: Padding( + padding: EdgeInsets.all(20), + child: Image( + image: AssetImage("assets/knott.png"), + width: 128, + height: 128, + )), + applicationName: "Cwtch (Flutter UI)", + applicationVersion: AppLocalizations.of(context).version.replaceAll("%1", constructVersionString(Provider.of(context).packageInfo)), + applicationLegalese: '\u{a9} 2021 Open Privacy Research Society', + ), + ])))); + }); }); } } +/// Construct a version string from Package Info String constructVersionString(PackageInfo pinfo) { if (pinfo == null) { return ""; @@ -101,6 +136,8 @@ String constructVersionString(PackageInfo pinfo) { return pinfo.version + "." + pinfo.buildNumber; } +/// A slightly verbose way to extract the full language name from +/// an individual language code. There might be a more efficient way of doing this. String getLanguageFull(context, String languageCode) { if (languageCode == "en") { return AppLocalizations.of(context).localeEn; @@ -123,6 +160,7 @@ String getLanguageFull(context, String languageCode) { return languageCode; } +/// Send an UpdateGlobalSettings to the Event Bus saveSettings(context) { var settings = Provider.of(context, listen: false); final updateSettingsEvent = { @@ -130,7 +168,5 @@ saveSettings(context) { "Data": {"Data": jsonEncode(settings.asJson())}, }; final updateSettingsEventJson = jsonEncode(updateSettingsEvent); - Provider.of(context, listen: false) - .cwtch - .SendAppEvent(updateSettingsEventJson); + Provider.of(context, listen: false).cwtch.SendAppEvent(updateSettingsEventJson); } diff --git a/lib/views/messageview.dart b/lib/views/messageview.dart index 68944ed..f84c081 100644 --- a/lib/views/messageview.dart +++ b/lib/views/messageview.dart @@ -5,8 +5,7 @@ import '../opaque.dart'; import '../widgets/messagelist.dart'; class MessageView extends StatefulWidget { - const MessageView({Key key, this.profile, this.conversationHandle}) - : super(key: key); + const MessageView({Key key, this.profile, this.conversationHandle}) : super(key: key); final ProfileInfoState profile; final String conversationHandle; @@ -35,9 +34,7 @@ class _MessageViewState extends State { IconButton(icon: Icon(Icons.settings), onPressed: _pushConvoSettings), ], ), - body: MessageList( - profile: widget.profile, - conversationHandle: widget.conversationHandle), + body: MessageList(profile: widget.profile, conversationHandle: widget.conversationHandle), bottomSheet: _buildComposeBox(), ); } @@ -62,25 +59,15 @@ class _MessageViewState extends State { height: 80, child: Column(children: [ ElevatedButton( - child: - Icon(Icons.send, color: Opaque.current().mainTextColor()), + child: Icon(Icons.send, color: Opaque.current().mainTextColor()), style: ButtonStyle( - backgroundColor: MaterialStateProperty.all( - Opaque.current().defaultButtonColor()), + backgroundColor: MaterialStateProperty.all(Opaque.current().defaultButtonColor()), ), onPressed: _sendMessage, ), Row(children: [ - SizedBox( - width: 45, - child: ElevatedButton( - child: Icon(Icons.emoji_emotions_outlined, - color: Opaque.current().mainTextColor()))), - SizedBox( - width: 45, - child: ElevatedButton( - child: Icon(Icons.attach_file, - color: Opaque.current().mainTextColor()))), + SizedBox(width: 45, child: ElevatedButton(child: Icon(Icons.emoji_emotions_outlined, color: Opaque.current().mainTextColor()))), + SizedBox(width: 45, child: ElevatedButton(child: Icon(Icons.attach_file, color: Opaque.current().mainTextColor()))), ]) ]), ), diff --git a/lib/views/profilemgrview.dart b/lib/views/profilemgrview.dart index 30f6b8b..eb39270 100644 --- a/lib/views/profilemgrview.dart +++ b/lib/views/profilemgrview.dart @@ -29,15 +29,12 @@ class _ProfileMgrViewState extends State { appBar: AppBar( title: Text(AppLocalizations.of(context).profileName), actions: [ - IconButton( - icon: Icon(Icons.bug_report_outlined), - onPressed: _testChangingContactInfo), + IconButton(icon: Icon(Icons.bug_report_outlined), onPressed: _testChangingContactInfo), IconButton( icon: Icon(Icons.lock_open), onPressed: _modalUnlockProfiles, ), - IconButton( - icon: Icon(Icons.settings), onPressed: _pushGlobalSettings), + IconButton(icon: Icon(Icons.settings), onPressed: _pushGlobalSettings), ], ), floatingActionButton: FloatingActionButton( @@ -50,7 +47,7 @@ class _ProfileMgrViewState extends State { } void _testChangingContactInfo() { - Provider.of(context, listen:false).profiles.first.nickname = "yay!"; + Provider.of(context, listen: false).profiles.first.nickname = "yay!"; } void _pushGlobalSettings() { @@ -103,9 +100,7 @@ class _ProfileMgrViewState extends State { ElevatedButton( child: Text(AppLocalizations.of(context).unlock), onPressed: () { - Provider.of(context, listen: false) - .cwtch - .LoadProfiles(ctrlrPassword.value.text); + Provider.of(context, listen: false).cwtch.LoadProfiles(ctrlrPassword.value.text); Navigator.pop(context); }, ), diff --git a/lib/views/triplecolview.dart b/lib/views/triplecolview.dart index 3d3db31..ff5e475 100644 --- a/lib/views/triplecolview.dart +++ b/lib/views/triplecolview.dart @@ -22,19 +22,14 @@ class _TripleColumnViewState extends State { ), Flexible( flex: flwtch.columns[1], - child: flwtch.selectedProfile == null - ? Center(child: Text("pick a profile")) - : ContactsView(), //dev + child: flwtch.selectedProfile == null ? Center(child: Text("pick a profile")) : ContactsView(), //dev ), Flexible( flex: flwtch.columns[2], child: flwtch.selectedConversation == "" ? Center(child: Text("pick a contact")) : //dev - Container( - child: MessageView( - profile: flwtch.selectedProfile, - conversationHandle: flwtch.selectedConversation)), + Container(child: MessageView(profile: flwtch.selectedProfile, conversationHandle: flwtch.selectedConversation)), ), ]); } diff --git a/lib/widgets/buttontextfield.dart b/lib/widgets/buttontextfield.dart index e50fa16..4b34cfb 100644 --- a/lib/widgets/buttontextfield.dart +++ b/lib/widgets/buttontextfield.dart @@ -1,13 +1,11 @@ import 'package:flutter/material.dart'; import 'package:flutter_app/settings.dart'; import 'package:provider/provider.dart'; -import '../opaque.dart'; // Provides a styled Text Field for use in Form Widgets. // Callers must provide a text controller, label helper text and a validator. class CwtchButtonTextField extends StatefulWidget { - CwtchButtonTextField( - {this.controller, this.onPressed, this.icon, this.tooltip}); + CwtchButtonTextField({this.controller, this.onPressed, this.icon, this.tooltip}); final TextEditingController controller; final Function onPressed; final Icon icon; @@ -37,32 +35,17 @@ class _CwtchButtonTextFieldState extends State { ), floatingLabelBehavior: FloatingLabelBehavior.never, filled: true, - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(15.0), - borderSide: BorderSide( - color: theme.current().textfieldBorderColor(), width: 3.0)), - focusedErrorBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(15.0), - borderSide: BorderSide( - color: theme.current().textfieldErrorColor(), width: 3.0)), - errorBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(15.0), - borderSide: BorderSide( - color: theme.current().textfieldErrorColor(), width: 3.0)), + focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldBorderColor(), width: 3.0)), + focusedErrorBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldErrorColor(), width: 3.0)), + errorBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldErrorColor(), width: 3.0)), errorStyle: TextStyle( color: theme.current().textfieldErrorColor(), fontWeight: FontWeight.bold, ), fillColor: theme.current().textfieldBackgroundColor(), contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(15.0), - borderSide: BorderSide( - color: theme.current().textfieldBorderColor(), - width: 3.0))), - style: TextStyle( - color: theme.current().mainTextColor(), - backgroundColor: theme.current().textfieldBackgroundColor()), + enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldBorderColor(), width: 3.0))), + style: TextStyle(color: theme.current().mainTextColor(), backgroundColor: theme.current().textfieldBackgroundColor()), ); }); } diff --git a/lib/widgets/contactrow.dart b/lib/widgets/contactrow.dart index 97f7f52..349a1d5 100644 --- a/lib/widgets/contactrow.dart +++ b/lib/widgets/contactrow.dart @@ -20,16 +20,23 @@ class _ContactRowState extends State { width: 60, height: 60, child: ClipOval( - child: SizedBox(width:60, height:60, child:Container(color:Colors.white, width: 60, height: 60, child: Image(image: AssetImage("assets/"+contact.imagePath), width:50,height:50,))), + child: SizedBox( + width: 60, + height: 60, + child: Container( + color: Colors.white, + width: 60, + height: 60, + child: Image( + image: AssetImage("assets/" + contact.imagePath), + width: 50, + height: 50, + ))), ), ), trailing: contact.isInvitation != null && contact.isInvitation - ? Column(children: [ - Icon(Icons.favorite, color: Opaque.current().mainTextColor()), - Icon(Icons.delete, color: Opaque.current().mainTextColor()) - ]) - : Text( - "99+"), //(nb: Icons.create is a pencil and we use it for "edit", not create) + ? Column(children: [Icon(Icons.favorite, color: Opaque.current().mainTextColor()), Icon(Icons.delete, color: Opaque.current().mainTextColor())]) + : Text("99+"), //(nb: Icons.create is a pencil and we use it for "edit", not create) title: Text( contact.nickname, style: Provider.of(context).biggerFont, diff --git a/lib/widgets/cwtchlabel.dart b/lib/widgets/cwtchlabel.dart index 6780198..a2e062d 100644 --- a/lib/widgets/cwtchlabel.dart +++ b/lib/widgets/cwtchlabel.dart @@ -1,7 +1,5 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import '../opaque.dart'; import '../settings.dart'; // Provides a styled Label diff --git a/lib/widgets/messagebubble.dart b/lib/widgets/messagebubble.dart index 56c0b9f..a421033 100644 --- a/lib/widgets/messagebubble.dart +++ b/lib/widgets/messagebubble.dart @@ -24,15 +24,8 @@ class _MessageBubbleState extends State { super.didChangeDependencies(); print("requesting message " + widget.messageIndex.toString()); - Provider.of(context) - .cwtch - .GetMessage( - widget.profile.onion, widget.contactOnion, widget.messageIndex) - .then((jsonMessage) { - print("got message: " + - widget.messageIndex.toString() + - ": " + - jsonMessage); + Provider.of(context).cwtch.GetMessage(widget.profile.onion, widget.contactOnion, widget.messageIndex).then((jsonMessage) { + print("got message: " + widget.messageIndex.toString() + ": " + jsonMessage); dynamic messageWrapper = jsonDecode(jsonMessage); dynamic message = jsonDecode(messageWrapper['Message']); setState(() { @@ -50,9 +43,7 @@ class _MessageBubbleState extends State { child: Container( decoration: BoxDecoration( color: Opaque.current().messageFromOtherBackgroundColor(), - border: Border.all( - color: Opaque.current().messageFromOtherBackgroundColor(), - width: 1), + border: Border.all(color: Opaque.current().messageFromOtherBackgroundColor(), width: 1), borderRadius: BorderRadius.all( Radius.circular(15.0), ), @@ -65,11 +56,7 @@ class _MessageBubbleState extends State { subtitle: Row( children: [ Text("" + widget.messageIndex.toString()), - ack - ? Icon(Icons.check_circle_outline, - color: Opaque.current().mainTextColor()) - : Icon(Icons.hourglass_bottom_outlined, - color: Opaque.current().mainTextColor()) + ack ? Icon(Icons.check_circle_outline, color: Opaque.current().mainTextColor()) : Icon(Icons.hourglass_bottom_outlined, color: Opaque.current().mainTextColor()) ], ), ), diff --git a/lib/widgets/messagelist.dart b/lib/widgets/messagelist.dart index 0f2612b..5b7d245 100644 --- a/lib/widgets/messagelist.dart +++ b/lib/widgets/messagelist.dart @@ -10,8 +10,7 @@ class MessageList extends StatefulWidget { final ProfileInfoState profile; final String conversationHandle; - const MessageList({Key key, this.profile, this.conversationHandle}) - : super(key: key); + const MessageList({Key key, this.profile, this.conversationHandle}) : super(key: key); @override _MessageListState createState() => _MessageListState(); @@ -50,14 +49,8 @@ class _MessageListState extends State { return; } - Provider.of(context, listen: false) - .cwtch - .NumMessages( - Provider.of(context, listen: false).onion, - widget.conversationHandle) - .then((n) { - if (n != conversationNumMessages) - setState(() => conversationNumMessages = n); + Provider.of(context, listen: false).cwtch.NumMessages(Provider.of(context, listen: false).onion, widget.conversationHandle).then((n) { + if (n != conversationNumMessages) setState(() => conversationNumMessages = n); }); } } diff --git a/lib/widgets/passwordfield.dart b/lib/widgets/passwordfield.dart index 5853d1f..77330c5 100644 --- a/lib/widgets/passwordfield.dart +++ b/lib/widgets/passwordfield.dart @@ -1,7 +1,5 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import '../opaque.dart'; import '../settings.dart'; // Provides a styled Password Input Field for use in Form Widgets. @@ -30,28 +28,14 @@ class _CwtchTextFieldState extends State { color: theme.current().textfieldErrorColor(), fontWeight: FontWeight.bold, ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(15.0), - borderSide: BorderSide( - color: theme.current().textfieldBorderColor(), width: 3.0)), - focusedErrorBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(15.0), - borderSide: BorderSide( - color: theme.current().textfieldErrorColor(), width: 3.0)), - errorBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(15.0), - borderSide: BorderSide( - color: theme.current().textfieldErrorColor(), width: 3.0)), + focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldBorderColor(), width: 3.0)), + focusedErrorBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldErrorColor(), width: 3.0)), + errorBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldErrorColor(), width: 3.0)), filled: true, fillColor: theme.current().textfieldBackgroundColor(), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(15.0), - borderSide: BorderSide( - color: theme.current().textfieldBorderColor(), width: 3.0)), + enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldBorderColor(), width: 3.0)), ), - style: TextStyle( - color: theme.current().mainTextColor(), - backgroundColor: theme.current().textfieldBackgroundColor()), + style: TextStyle(color: theme.current().mainTextColor(), backgroundColor: theme.current().textfieldBackgroundColor()), ); }); } diff --git a/lib/widgets/profilerow.dart b/lib/widgets/profilerow.dart index b044e10..e3c3c91 100644 --- a/lib/widgets/profilerow.dart +++ b/lib/widgets/profilerow.dart @@ -6,7 +6,6 @@ import 'package:provider/provider.dart'; import '../main.dart'; import '../model.dart'; -import '../opaque.dart'; import '../settings.dart'; class ProfileRow extends StatefulWidget { @@ -38,13 +37,9 @@ class _ProfileRowState extends State { ), ), trailing: IconButton( - icon: Icon(Icons.create, - color: Provider.of(context).current().mainTextColor()), + icon: Icon(Icons.create, color: Provider.of(context).current().mainTextColor()), onPressed: () { - _pushAddEditProfile( - onion: profile.onion, - displayName: profile.nickname, - profileImage: profile.imagePath); + _pushAddEditProfile(onion: profile.onion, displayName: profile.nickname, profileImage: profile.imagePath); }, ), //(nb: Icons.create is a pencil and we use it for "edit", not create) title: Text( @@ -83,8 +78,7 @@ class _ProfileRowState extends State { ChangeNotifierProvider.value(value: profile), ChangeNotifierProvider.value(value: profile.contactList), ], - builder: (context, widget) => - includeDoublePane ? DoubleColumnView() : ContactsView(), + builder: (context, widget) => includeDoublePane ? DoubleColumnView() : ContactsView(), ); }, ), @@ -97,8 +91,7 @@ class _ProfileRowState extends State { return MultiProvider( providers: [ ChangeNotifierProvider( - create: (_) => ProfileInfoState( - onion: onion, nickname: displayName, imagePath: profileImage), + create: (_) => ProfileInfoState(onion: onion, nickname: displayName, imagePath: profileImage), ), ], builder: (context, widget) => AddEditProfileView(), diff --git a/lib/widgets/textfield.dart b/lib/widgets/textfield.dart index f2a31b3..3d16397 100644 --- a/lib/widgets/textfield.dart +++ b/lib/widgets/textfield.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import '../opaque.dart'; import '../settings.dart'; // Provides a styled Text Field for use in Form Widgets. @@ -24,37 +23,20 @@ class _CwtchTextFieldState extends State { validator: widget.validator, decoration: InputDecoration( labelText: widget.labelText, - labelStyle: TextStyle( - color: theme.current().mainTextColor(), - backgroundColor: theme.current().textfieldBackgroundColor()), + labelStyle: TextStyle(color: theme.current().mainTextColor(), backgroundColor: theme.current().textfieldBackgroundColor()), floatingLabelBehavior: FloatingLabelBehavior.never, filled: true, - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(15.0), - borderSide: BorderSide( - color: theme.current().textfieldBorderColor(), width: 3.0)), - focusedErrorBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(15.0), - borderSide: BorderSide( - color: theme.current().textfieldErrorColor(), width: 3.0)), - errorBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(15.0), - borderSide: BorderSide( - color: theme.current().textfieldErrorColor(), width: 3.0)), + focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldBorderColor(), width: 3.0)), + focusedErrorBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldErrorColor(), width: 3.0)), + errorBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldErrorColor(), width: 3.0)), errorStyle: TextStyle( color: theme.current().textfieldErrorColor(), fontWeight: FontWeight.bold, ), fillColor: theme.current().textfieldBackgroundColor(), contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(15.0), - borderSide: BorderSide( - color: theme.current().textfieldBorderColor(), - width: 3.0))), - style: TextStyle( - color: theme.current().mainTextColor(), - backgroundColor: theme.current().textfieldBackgroundColor()), + enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15.0), borderSide: BorderSide(color: theme.current().textfieldBorderColor(), width: 3.0))), + style: TextStyle(color: theme.current().mainTextColor(), backgroundColor: theme.current().textfieldBackgroundColor()), ); }); } diff --git a/lib/widgets/torstatuslabel.dart b/lib/widgets/torstatuslabel.dart index 6453854..a89d28d 100644 --- a/lib/widgets/torstatuslabel.dart +++ b/lib/widgets/torstatuslabel.dart @@ -18,9 +18,7 @@ class _TorStatusState extends State { stream: Provider.of(context).appStatus.torStatus(), builder: (BuildContext context, AsyncSnapshot snapshot) { return Text( - snapshot.hasData - ? snapshot.data - : AppLocalizations.of(context).loadingTor, + snapshot.hasData ? snapshot.data : AppLocalizations.of(context).loadingTor, style: Theme.of(context).textTheme.headline4, ); }, diff --git a/pubspec.yaml b/pubspec.yaml index ec288c7..0319339 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -35,7 +35,6 @@ dependencies: ffi: ^1.0.0 path_provider: ^2.0.0 - dev_dependencies: flutter_test: sdk: flutter