Compare commits

..

3 Commits

Author SHA1 Message Date
Dan Ballard 3fd0af6c0b more translation updates 2024-01-04 13:53:36 -08:00
Dan Ballard 6ac29f2b14 settings about translations
continuous-integration/drone/pr Build is passing Details
2024-01-04 13:05:37 -08:00
Dan Ballard 5b5de79693 settings into pane 2024-01-04 01:53:10 -08:00
170 changed files with 3330 additions and 4746 deletions

View File

@ -8,7 +8,7 @@ clone:
steps: steps:
- name: clone - name: clone
image: openpriv/flutter-desktop:linux-fstable-3.19.3 image: openpriv/flutter-desktop:linux-fstable-3.13.4
environment: environment:
buildbot_key_b64: buildbot_key_b64:
from_secret: buildbot_key_b64 from_secret: buildbot_key_b64
@ -24,7 +24,7 @@ steps:
- git checkout $DRONE_COMMIT - git checkout $DRONE_COMMIT
- name: fetch - name: fetch
image: openpriv/flutter-desktop:linux-fstable-3.19.3 image: openpriv/flutter-desktop:linux-fstable-3.13.4
volumes: volumes:
- name: deps - name: deps
path: /root/.pub-cache path: /root/.pub-cache
@ -47,7 +47,7 @@ steps:
# #Todo: fix all the lint errors and add `-set_exit_status` above to enforce linting # #Todo: fix all the lint errors and add `-set_exit_status` above to enforce linting
- name: build-linux - name: build-linux
image: openpriv/flutter-desktop:linux-fstable-3.19.3 image: openpriv/flutter-desktop:linux-fstable-3.13.4
volumes: volumes:
- name: deps - name: deps
path: /root/.pub-cache path: /root/.pub-cache
@ -55,29 +55,14 @@ steps:
- flutter build linux --dart-define BUILD_VER=`cat VERSION` --dart-define BUILD_DATE=`cat COMMIT_DATE` - flutter build linux --dart-define BUILD_VER=`cat VERSION` --dart-define BUILD_DATE=`cat COMMIT_DATE`
- linux/package-release.sh - linux/package-release.sh
- mkdir -p deploy/cwtch - mkdir -p deploy/cwtch
- mkdir -p deploy/deb/cwtch/usr
- mkdir -p deploy/deb/cwtch/DEBIAN
- export VERSION=`cat VERSION | tr -d 'v'`
- sed "s|VERSION|$VERSION|g" linux/deb/control > deploy/deb/cwtch/DEBIAN/control
- cp -r build/linux/x64/release/bundle/* deploy/cwtch - cp -r build/linux/x64/release/bundle/* deploy/cwtch
- cd deploy - cd deploy
- cd cwtch
- INSTALL_PREFIX=./../deb/cwtch/usr DESKTOP_PREFIX=/usr/ ./install.sh
- cd ..
# we depend on tor, get it from the tor project apt repo
- rm -r deb/cwtch/usr/lib/cwtch/Tor
# Tar archives need a few tricks to make this deterministic, see https://reproducible-builds.org/docs/archives/ # Tar archives need a few tricks to make this deterministic, see https://reproducible-builds.org/docs/archives/
- tar --sort=name --mtime=`cat COMMIT_DATE` --owner=0 --group=0 --numeric-owner --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime -czf cwtch-`cat ../VERSION`.tar.gz cwtch - tar --sort=name --mtime=`cat COMMIT_DATE` --owner=0 --group=0 --numeric-owner --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime -czf cwtch-`cat ../VERSION`.tar.gz cwtch
- rm -r cwtch - rm -r cwtch
- cd deb
- dpkg-deb --build cwtch
- cd ..
- mv deb/cwtch.deb cwtch-$VERSION.deb
- rm -r deb
- name: linux-ui-tests - name: linux-ui-tests
image: openpriv/flutter-desktop:linux-fstable-3.19.3 image: openpriv/flutter-desktop:linux-fstable-3.13.4
volumes: volumes:
- name: deps - name: deps
path: /root/.pub-cache path: /root/.pub-cache
@ -86,7 +71,7 @@ steps:
- ./run-tests-headless.sh "01_general|01_tor|02_global_settings|04_profile_mgmt" - ./run-tests-headless.sh "01_general|01_tor|02_global_settings|04_profile_mgmt"
- name: test-build-android - name: test-build-android
image: openpriv/flutter-desktop:linux-fstable-3.19.3 image: openpriv/flutter-desktop:linux-fstable-3.13.4
when: when:
event: pull_request event: pull_request
volumes: volumes:
@ -96,7 +81,7 @@ steps:
- flutter build apk --debug - flutter build apk --debug
- name: build-android - name: build-android
image: openpriv/flutter-desktop:linux-fstable-3.19.3 image: openpriv/flutter-desktop:linux-fstable-3.13.4
when: when:
event: push event: push
environment: environment:
@ -120,7 +105,7 @@ steps:
#- cp build/app/outputs/flutter-apk/app-debug.apk deploy/android #- cp build/app/outputs/flutter-apk/app-debug.apk deploy/android
- name: widget-tests - name: widget-tests
image: openpriv/flutter-desktop:linux-fstable-3.19.3 image: openpriv/flutter-desktop:linux-fstable-3.13.4
volumes: volumes:
- name: deps - name: deps
path: /root/.pub-cache path: /root/.pub-cache
@ -129,21 +114,6 @@ steps:
- flutter test --coverage - flutter test --coverage
- genhtml coverage/lcov.info -o coverage/html - genhtml coverage/lcov.info -o coverage/html
- name: upload-nightlies
image: openpriv/flutter-desktop:linux-fstable-3.19.3
environment:
GOGS_ACCOUNT_TOKEN:
from_secret: gogs_account_token
secrets: [gogs_account_token]
volumes:
- name: deps
path: /root/.pub-cache
when:
event: push
status: [ success ]
commands:
- ./upload-releases.sh deploy/cwtch-`cat VERSION`.apk application/vnd.android.package-archive cwtch-`cat VERSION`.apk
- name: deploy-buildfiles - name: deploy-buildfiles
image: kroniak/ssh-client image: kroniak/ssh-client
pull: if-not-exists pull: if-not-exists
@ -208,7 +178,7 @@ clone:
steps: steps:
- name: clone - name: clone
image: openpriv/flutter-desktop:windows-sdk30-fstable-3.19.3 image: openpriv/flutter-desktop:windows-sdk30-fstable-3.13.4
environment: environment:
buildbot_key_b64: buildbot_key_b64:
from_secret: buildbot_key_b64 from_secret: buildbot_key_b64
@ -226,7 +196,7 @@ steps:
- git checkout $Env:DRONE_COMMIT - git checkout $Env:DRONE_COMMIT
- name: fetch - name: fetch
image: openpriv/flutter-desktop:windows-sdk30-fstable-3.19.3 image: openpriv/flutter-desktop:windows-sdk30-fstable-3.10.2
commands: commands:
- git describe --tags --abbrev=1 > VERSION - git describe --tags --abbrev=1 > VERSION
- git log -1 --format=%cd --date=format:'%Y-%m-%d-%H-%M' > COMMIT_DATE - git log -1 --format=%cd --date=format:'%Y-%m-%d-%H-%M' > COMMIT_DATE
@ -234,12 +204,12 @@ steps:
- .\fetch-libcwtch-go.ps1 - .\fetch-libcwtch-go.ps1
- name: build-windows - name: build-windows
image: openpriv/flutter-desktop:windows-sdk30-fstable-3.19.3 image: openpriv/flutter-desktop:windows-sdk30-fstable-3.13.4
commands: commands:
- flutter pub get - flutter pub get
- $Env:version += type .\VERSION - $Env:version += type .\VERSION
- $Env:commitdate += type .\COMMIT_DATE - $Env:commitdate += type .\COMMIT_DATE
- $Env:releasedir = "build\\windows\\x64\\runner\\Release\\" - $Env:releasedir = "build\\windows\\runner\\Release\\"
- flutter build windows --dart-define BUILD_VER=$Env:version --dart-define BUILD_DATE=$Env:commitdate - flutter build windows --dart-define BUILD_VER=$Env:version --dart-define BUILD_DATE=$Env:commitdate
- copy windows\libCwtch.dll $Env:releasedir - copy windows\libCwtch.dll $Env:releasedir
# flutter hasn't worked out it's packaging of required dll's so we have to resort to this manual nonsense # flutter hasn't worked out it's packaging of required dll's so we have to resort to this manual nonsense
@ -266,7 +236,7 @@ steps:
commands: commands:
- $Env:version += type .\VERSION - $Env:version += type .\VERSION
- $Env:commitdate += type .\COMMIT_DATE - $Env:commitdate += type .\COMMIT_DATE
- $Env:releasedir = "build\\windows\\x64\\runner\\Release\\" - $Env:releasedir = "build\\windows\\runner\\Release\\"
- $Env:zip = 'cwtch-' + $Env:version + '.zip' - $Env:zip = 'cwtch-' + $Env:version + '.zip'
- $Env:zipsha = $Env:zip + '.sha512.txt' - $Env:zipsha = $Env:zip + '.sha512.txt'
- $Env:buildname = 'flwtch-' + $Env:commitdate + '-' + $Env:version - $Env:buildname = 'flwtch-' + $Env:commitdate + '-' + $Env:version
@ -291,7 +261,7 @@ steps:
- move *.sha512.txt deploy\$Env:builddir - move *.sha512.txt deploy\$Env:builddir
- name: deploy-windows - name: deploy-windows
image: openpriv/flutter-desktop:windows-sdk30-fstable-3.19.3 image: openpriv/flutter-desktop:windows-sdk30-fstable-3.13.4
when: when:
event: push event: push
status: [ success ] status: [ success ]
@ -363,7 +333,6 @@ steps:
commands: commands:
- export PATH=$PATH:/Users/drone/bin/flutter/bin - export PATH=$PATH:/Users/drone/bin/flutter/bin
- export PATH=$GEM_HOME/ruby/2.6.0/bin:$PATH - export PATH=$GEM_HOME/ruby/2.6.0/bin:$PATH
- flutter doctor
- flutter build macos --dart-define BUILD_VER=`cat VERSION` --dart-define BUILD_DATE=`cat COMMIT_DATE` - flutter build macos --dart-define BUILD_VER=`cat VERSION` --dart-define BUILD_DATE=`cat COMMIT_DATE`
- export PATH=$PATH:/opt/homebrew/bin/ #create-dmg - export PATH=$PATH:/opt/homebrew/bin/ #create-dmg
- macos/package-release.sh - macos/package-release.sh

3
.gitignore vendored
View File

@ -35,7 +35,6 @@ test_home
.pub-cache/ .pub-cache/
.pub/ .pub/
/build/ /build/
./lib/gen/
# Web related # Web related
lib/generated_plugin_registrant.dart lib/generated_plugin_registrant.dart
@ -59,7 +58,7 @@ package.
# Compiled Libs # Compiled Libs
linux/tor linux/tor
linux/libCwtch.so linux/libCwtch.so
android/app/cwtch/cwtch.aar android/cwtch/cwtch.aar
android/app/src/main/jniLibs/*/libtor.so android/app/src/main/jniLibs/*/libtor.so
*.dylib *.dylib
integration_test/gherkin_suite_test.g.dart integration_test/gherkin_suite_test.g.dart

View File

@ -1 +1 @@
2024-02-26-18-01-v0.0.14 2024-01-03-20-52-v0.0.10-4-g6c0b2e2

View File

@ -1,5 +1,5 @@
MIT License MIT License
Copyright (c) 2021-2024 Open Privacy Research Society Copyright (c) 2021 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: 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:

View File

@ -1,8 +0,0 @@
# NSIS Notes
## Images
Requires Windows 3 Compatible Bitmaps.
Can convert to the correct format with e.g. `mogrify -compress none -format bmp3 windows/nsis/cwtch_title.bmp
`

View File

@ -1,9 +1,3 @@
plugins {
id "com.android.application"
id "kotlin-android"
id "dev.flutter.flutter-gradle-plugin"
}
def localProperties = new Properties() def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties') def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) { if (localPropertiesFile.exists()) {
@ -12,6 +6,11 @@ if (localPropertiesFile.exists()) {
} }
} }
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new FileNotFoundException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode') def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) { if (flutterVersionCode == null) {
flutterVersionCode = '1' flutterVersionCode = '1'
@ -22,6 +21,10 @@ if (flutterVersionName == null) {
flutterVersionName = '1.0' flutterVersionName = '1.0'
} }
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
// key.properties MUST have password placeholders filled in (via drone with secrets) and cwtch-upload.jks file must be added (from drone secret) // key.properties MUST have password placeholders filled in (via drone with secrets) and cwtch-upload.jks file must be added (from drone secret)
def keystoreProperties = new Properties() def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties') def keystorePropertiesFile = rootProject.file('key.properties')
@ -30,7 +33,7 @@ if (keystorePropertiesFile.exists()) {
} }
android { android {
compileSdkVersion 34 compileSdkVersion 33
sourceSets { sourceSets {
main.java.srcDirs += 'src/main/kotlin' main.java.srcDirs += 'src/main/kotlin'
@ -51,7 +54,7 @@ android {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "im.cwtch.flwtch" applicationId "im.cwtch.flwtch"
minSdkVersion 19 minSdkVersion 19
targetSdkVersion 34 targetSdkVersion 33
versionCode flutterVersionCode.toInteger() versionCode flutterVersionCode.toInteger()
versionName flutterVersionName versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@ -90,11 +93,11 @@ flutter {
} }
dependencies { dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.21" // same as kotlin version in settings.gradle implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation fileTree( dir: 'cwtch') implementation project(':cwtch')
implementation files ('cwtch/cwtch.aar')
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.2" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.2"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.2" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.2"
implementation "com.airbnb.android:lottie:5.2.0"
implementation "androidx.localbroadcastmanager:localbroadcastmanager:1.0.0" implementation "androidx.localbroadcastmanager:localbroadcastmanager:1.0.0"
implementation "com.android.support.constraint:constraint-layout:2.0.4" implementation "com.android.support.constraint:constraint-layout:2.0.4"

View File

@ -1,4 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="im.cwtch.flwtch"> package="im.cwtch.flwtch">
<!-- io.flutter.app.FlutterApplication is an android.app.Application that <!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method. calls FlutterMain.startInitialization(this); in its onCreate method.
@ -13,7 +13,7 @@
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:launchMode="singleTop" android:launchMode="singleTop"
android:theme="@style/LaunchTheme" android:theme="@style/NormalTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true" android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize" android:windowSoftInputMode="adjustResize"
@ -38,30 +38,22 @@
android:name="flutterEmbedding" android:name="flutterEmbedding"
android:value="2" /> android:value="2" />
<!--Needed to run in background (lol)-->
<service
android:name="androidx.work.impl.foreground.SystemForegroundService"
android:foregroundServiceType="dataSync"
tools:node="merge" />
</application> </application>
<!--Needed to access Tor socket--> <!--Needed to access Tor socket-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<!-- Needed for running in the background --> <!--Needed to run in background (lol)-->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- As of Android 13 this permission is required -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<!-- Ability to ask user to exempt app from power management (which can kill it more frequently especially on some devices. <!-- Ability to ask user to exempt app from power management (which can kill it more frequently especially on some devices.
Allows app to use ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS --> Allows app to use ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS -->
<uses-permission-sdk-23 android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" /> <uses-permission-sdk-23 android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<!-- TODO when we support sdk 31
<uses-permission-sdk-23 android:name="android.permission.HIDE_OVERLAY_WINDOWS" /> <uses-permission-sdk-23 android:name="android.permission.HIDE_OVERLAY_WINDOWS" />
-->
<!--Needed to check if activity is foregrounded or if messages from the service should be queued--> <!--Needed to check if activity is foregrounded or if messages from the service should be queued-->
<uses-permission android:name="android.permission.GET_TASKS" /> <uses-permission android:name="android.permission.GET_TASKS" />

View File

@ -11,7 +11,6 @@ import android.graphics.Color
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
import android.util.Log import android.util.Log
import android.content.pm.ServiceInfo
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import androidx.localbroadcastmanager.content.LocalBroadcastManager import androidx.localbroadcastmanager.content.LocalBroadcastManager
@ -23,13 +22,6 @@ import io.flutter.FlutterInjector
import org.json.JSONObject import org.json.JSONObject
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.Paths import java.nio.file.Paths
import java.io.FileInputStream
import java.io.File
class FlwtchWorker(context: Context, parameters: WorkerParameters) : class FlwtchWorker(context: Context, parameters: WorkerParameters) :
CoroutineWorker(context, parameters) { CoroutineWorker(context, parameters) {
@ -145,19 +137,7 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) :
Log.i(TAG, "notification for " + evt.EventType + " " + handle + " " + conversationId + " " + channelId) Log.i(TAG, "notification for " + evt.EventType + " " + handle + " " + conversationId + " " + channelId)
Log.i(TAG, data.toString()); Log.i(TAG, data.toString());
val key = loader.getLookupKeyForAsset(data.getString("picture"))//"assets/profiles/001-centaur.png") val key = loader.getLookupKeyForAsset(data.getString("picture"))//"assets/profiles/001-centaur.png")
var fh : java.io.InputStream? = null; val fh = applicationContext.assets.open(key)
try {
fh = applicationContext.assets.open(key)
} catch (e: Exception) {
Log.d("FlwtchWorker->ContactInfo", e.toString() + " :: " + e.getStackTrace());
}
try {
val file = File(data.getString("picture"))
fh = FileInputStream(file)
} catch (e: Exception) {
Log.d("FlwtchWorker->ContactInfo", e.toString() + " :: " + e.getStackTrace());
}
val clickIntent = Intent(applicationContext, MainActivity::class.java).also { intent -> val clickIntent = Intent(applicationContext, MainActivity::class.java).also { intent ->
intent.action = Intent.ACTION_RUN intent.action = Intent.ACTION_RUN
@ -165,21 +145,18 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) :
intent.putExtra("ProfileOnion", data.getString("ProfileOnion")) intent.putExtra("ProfileOnion", data.getString("ProfileOnion"))
intent.putExtra("Handle", handle) intent.putExtra("Handle", handle)
} }
val image : android.graphics.Bitmap? = if (fh != null) BitmapFactory.decodeStream(fh ) else null;
val newNotification = NotificationCompat.Builder(applicationContext, channelId) val newNotification = NotificationCompat.Builder(applicationContext, channelId)
.setContentTitle(data.getString("Nick")) .setContentTitle(data.getString("Nick"))
.setContentText((notificationConversationInfo .setContentText((notificationConversationInfo
?: "New Message From %1").replace("%1", data.getString("Nick"))) ?: "New Message From %1").replace("%1", data.getString("Nick")))
.setLargeIcon(image) .setLargeIcon(BitmapFactory.decodeStream(fh))
.setSmallIcon(R.mipmap.knott_transparent) .setSmallIcon(R.mipmap.knott_transparent)
.setContentIntent(PendingIntent.getActivity(applicationContext, 1, clickIntent, flags)) .setContentIntent(PendingIntent.getActivity(applicationContext, 1, clickIntent, flags))
.setAutoCancel(true) .setAutoCancel(true)
.build() .build()
notificationManager.notify(getNotificationID(data.getString("ProfileOnion"), channelId), newNotification) notificationManager.notify(getNotificationID(data.getString("ProfileOnion"), channelId), newNotification)
if (fh != null) {
fh.close()
}
} }
} }
@ -315,7 +292,7 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) :
.addAction(android.R.drawable.ic_delete, cancel, PendingIntent.getActivity(applicationContext, 2, cancelIntent, flags)) .addAction(android.R.drawable.ic_delete, cancel, PendingIntent.getActivity(applicationContext, 2, cancelIntent, flags))
.build() .build()
return ForegroundInfo(101, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC) return ForegroundInfo(101, notification)
} }
@RequiresApi(Build.VERSION_CODES.O) @RequiresApi(Build.VERSION_CODES.O)

View File

@ -1,5 +1,6 @@
package im.cwtch.flwtch package im.cwtch.flwtch
import SplashView
import android.annotation.TargetApi import android.annotation.TargetApi
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
@ -18,6 +19,7 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager
import androidx.work.* import androidx.work.*
import cwtch.Cwtch import cwtch.Cwtch
import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.android.SplashScreen
import io.flutter.embedding.engine.FlutterEngine import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.ErrorLogResult import io.flutter.plugin.common.ErrorLogResult
import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodCall
@ -30,6 +32,8 @@ import java.util.concurrent.TimeUnit
import kotlinx.coroutines.* import kotlinx.coroutines.*
class MainActivity: FlutterActivity() { class MainActivity: FlutterActivity() {
override fun provideSplashScreen(): SplashScreen? = SplashView()
// Channel to get app info // Channel to get app info
private val CHANNEL_APP_INFO = "test.flutter.dev/applicationInfo" private val CHANNEL_APP_INFO = "test.flutter.dev/applicationInfo"
@ -573,6 +577,9 @@ class MainActivity: FlutterActivity() {
result.success(Cwtch.searchConversations(profile, pattern)) result.success(Cwtch.searchConversations(profile, pattern))
return return
} }
"ReconnectCwtchForeground" -> {
Cwtch.reconnectCwtchForeground()
}
"Shutdown" -> { "Shutdown" -> {
Cwtch.shutdownCwtch(); Cwtch.shutdownCwtch();
} }

View File

@ -0,0 +1,15 @@
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import im.cwtch.flwtch.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()
}
}

View File

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen --> <!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/darkGreyPurple" /> <item android:drawable="?android:colorBackground" />
<!-- You can insert your own image assets here --> <!-- You can insert your own image assets here -->
<item> <!-- <item>
<bitmap <bitmap
android:gravity="center" android:gravity="center"
android:src="@mipmap/knott" /> android:src="@mipmap/launch_image" />
</item> </item> -->
</layer-list> </layer-list>

View File

@ -1,81 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="500dp"
android:height="500dp"
android:viewportWidth="500"
android:viewportHeight="500">
<path
android:pathData="M436.2,215c-0.6,3 -2,6.4 -4.3,10.4l18.2,18.2c2.4,-4.8 6.2,-13.1 8.2,-22.9c4.1,-20.2 -0.5,-37.1 -13.7,-50.3c-24.2,-24.2 -49.4,-26.4 -81.8,-7.3c-7.8,4.6 -16.1,10.6 -24.6,17.7c-19.5,16.3 -41.3,39.5 -64.9,69.2c15.4,19.4 30.2,36.2 43.8,49.8c6.3,6.3 12.4,12 18.3,17.1l16.2,-16.2c-5.9,-5 -12.1,-10.7 -18.4,-17c-9,-9 -18.5,-19.5 -28.4,-31.2l-2.1,-2.5l2.1,-2.5c18.1,-21.5 35,-38.6 50.1,-50.9c9.6,-7.8 18.6,-13.8 26.7,-17.7c7,-3.4 13.4,-5.3 19,-5.6c2.7,-0.2 6.9,-0.1 12.1,2c5,2.1 10.2,5.8 15.7,11.3c2.1,2.1 5,5.4 6.8,10.4C437.1,202.1 437.5,208 436.2,215L436.2,215z"
android:fillColor="#242425"/>
<path
android:pathData="M340.9,354.7l81.5,-81.5c-4.8,-7.1 -11.1,-14 -14.6,-17.7L327.3,336C332.5,342.4 337.1,348.6 340.9,354.7z"
android:fillColor="#242425"/>
<path
android:pathData="M444.6,329.6c13.2,-13.2 17.8,-30.1 13.7,-50.3c-2.8,-14 -9.1,-24.9 -10.3,-26.9L382.6,187c-6,3.1 -12.5,7.4 -19.4,12.8l50.1,50.1l0,0c4.1,4.3 12.1,13 17.4,21.6c3.2,5.2 5.1,9.7 5.6,13.5c1.2,6.9 0.9,12.7 -0.9,17.9c-1.8,5 -4.8,8.3 -6.8,10.4c-5.9,5.9 -11.3,9.7 -16.7,11.7c-5.5,2 -10,1.8 -13.3,1.4c-4.4,-0.5 -9.2,-2 -14.3,-4.2l-17,17C397.5,355.7 421.5,352.7 444.6,329.6z"
android:fillColor="#242425"/>
<path
android:pathData="M303.1,64.7c5,1.8 8.3,4.8 10.4,6.8c5.9,5.9 9.7,11.3 11.7,16.7c2,5.5 1.8,10 1.4,13.3c-0.5,4.4 -2,9.2 -4.2,14.3l17,17c16.4,-30.3 13.3,-54.4 -9.7,-77.4c-13.2,-13.2 -30.1,-17.8 -50.3,-13.7c-14,2.8 -24.9,9.1 -26.9,10.3L187,117.4c3.1,6 7.4,12.5 12.8,19.4L250,86.7l0,0c4.3,-4.1 13,-12.1 21.6,-17.4c5.2,-3.2 9.7,-5.1 13.5,-5.6C292,62.6 297.9,62.9 303.1,64.7z"
android:fillColor="#242425"/>
<path
android:pathData="M170.4,55.4c-24.2,24.2 -26.4,49.4 -7.3,81.8c4.6,7.8 10.6,16.1 17.7,24.6c16.3,19.5 39.5,41.3 69.2,64.9c19.4,-15.4 36.2,-30.2 49.8,-43.8c6.3,-6.3 12,-12.4 17.1,-18.3l-16.2,-16.2c-5,5.9 -10.7,12.1 -17,18.4c-9,9 -19.5,18.5 -31.2,28.4l-2.5,2.1l-2.5,-2.1c-21.5,-18.1 -38.6,-35 -50.9,-50.1c-7.8,-9.6 -13.8,-18.6 -17.7,-26.7c-3.4,-7 -5.3,-13.4 -5.6,-19c-0.2,-2.7 -0.1,-6.9 2,-12.1c2.1,-5 5.8,-10.2 11.3,-15.7c2.1,-2.1 5.4,-5 10.4,-6.8c5.2,-1.9 11.1,-2.2 18,-0.9l0.1,0c3,0.6 6.4,2 10.4,4.3l18.2,-18.2c-4.8,-2.4 -13.1,-6.2 -23,-8.2C200.5,37.6 183.6,42.2 170.4,55.4z"
android:fillColor="#242425"/>
<path
android:pathData="M273.2,77.6c-7.1,4.8 -14,11.1 -17.7,14.6l80.5,80.5c6.4,-5.2 12.7,-9.7 18.7,-13.6L273.2,77.6z"
android:fillColor="#242425"/>
<path
android:pathData="M55.4,329.6c24.2,24.2 49.4,26.4 81.8,7.3c7.8,-4.6 16.1,-10.6 24.6,-17.7c19.5,-16.3 41.3,-39.5 64.9,-69.2c-15.4,-19.4 -30.2,-36.2 -43.8,-49.8c-6.3,-6.3 -12.4,-12 -18.3,-17.1l-16.2,16.2c5.9,5 12.1,10.7 18.4,17c9,9 18.5,19.5 28.4,31.2l2.1,2.5l-2.1,2.5c-18.1,21.5 -35,38.6 -50.1,50.9c-9.6,7.8 -18.6,13.8 -26.7,17.7c-7,3.4 -13.4,5.3 -19,5.6c-2.7,0.2 -6.9,0.1 -12.1,-2c-5,-2.1 -10.2,-5.8 -15.7,-11.3c-2.1,-2.1 -5,-5.4 -6.8,-10.4c-1.9,-5.2 -2.2,-11.1 -0.9,-18l0,-0.1c0.6,-3 2,-6.4 4.3,-10.4l-18.2,-18.2c-2.4,4.8 -6.2,13.1 -8.2,23C37.6,299.5 42.2,316.4 55.4,329.6z"
android:fillColor="#242425"/>
<path
android:pathData="M86.7,250L86.7,250c-4.1,-4.4 -12,-13.1 -17.3,-21.6c-3.2,-5.2 -5.1,-9.7 -5.6,-13.5c-1.2,-6.9 -0.9,-12.7 0.9,-17.9c1.8,-5 4.8,-8.3 6.8,-10.4c5.9,-5.9 11.3,-9.7 16.7,-11.7c5.5,-2 10,-1.8 13.3,-1.4c4.4,0.5 9.2,2 14.3,4.2l17,-17c-30.3,-16.4 -54.4,-13.3 -77.4,9.7c-13.2,13.2 -17.8,30.1 -13.7,50.3c2.8,14 9.1,24.9 10.3,26.9l65.4,65.4c6,-3.1 12.5,-7.4 19.4,-12.8L86.7,250z"
android:fillColor="#242425"/>
<path
android:pathData="M92.2,244.5l80.5,-80.5c-5.2,-6.4 -9.7,-12.7 -13.6,-18.7l-81.5,81.5C82.4,233.9 88.6,240.8 92.2,244.5z"
android:fillColor="#242425"/>
<path
android:pathData="M329.6,444.6c24.2,-24.2 26.4,-49.4 7.3,-81.8c-4.6,-7.8 -10.6,-16.1 -17.7,-24.6c-16.3,-19.5 -39.5,-41.3 -69.2,-64.9c-19.4,15.4 -36.2,30.2 -49.8,43.8c-6.3,6.3 -12,12.4 -17.1,18.3l16.2,16.2c5,-5.9 10.7,-12.1 17,-18.4c9,-9 19.5,-18.5 31.2,-28.4l2.5,-2.1l2.5,2.1c21.5,18.1 38.6,35 50.9,50.1c7.8,9.6 13.8,18.6 17.7,26.7c3.4,7 5.3,13.4 5.6,19c0.2,2.7 0.1,6.9 -2,12.1c-2.1,5 -5.8,10.2 -11.3,15.7c-2.1,2.1 -5.4,5 -10.4,6.8c-5.2,1.9 -11.1,2.2 -18,0.9l-0.1,0c-3,-0.6 -6.4,-2 -10.4,-4.3l-18.2,18.2c4.7,2.4 13.1,6.1 22.9,8.2C299.4,462.4 316.4,457.8 329.6,444.6z"
android:fillColor="#242425"/>
<path
android:pathData="M244.5,407.8L164,327.3c-6.4,5.2 -12.7,9.7 -18.7,13.6l81.5,81.5C233.9,417.6 240.8,411.4 244.5,407.8z"
android:fillColor="#242425"/>
<path
android:pathData="M483.4,250c2.6,-6.3 5.3,-14 7.1,-22.7c6.3,-30.8 -1.8,-59.2 -22.7,-80.1c-19.7,-19.7 -41.7,-29.7 -65.5,-29.7c-7.5,0 -15.1,1 -22.8,3c2.9,-11.3 3.7,-22.3 2.3,-33.2c-2.5,-19.8 -12.3,-38.3 -29,-55.1C336.6,15.9 315.9,7.4 293,7.4c-6.6,0 -13.4,0.7 -20.2,2.1c-8.7,1.8 -16.5,4.5 -22.7,7.1c-6.3,-2.6 -14.1,-5.3 -22.8,-7.1c-6.9,-1.4 -13.7,-2.1 -20.2,-2.1c-22.9,0 -43.6,8.6 -59.9,24.8c-17.6,17.6 -27.5,37.2 -29.4,58.1c-0.9,9.9 0,19.9 2.7,30.2c-7.7,-2 -15.3,-3 -22.8,-3c-23.8,0 -45.8,10 -65.5,29.7c-20.9,20.9 -28.9,49.3 -22.7,80.1c1.8,8.7 4.5,16.5 7.1,22.7c-2.6,6.3 -5.3,14.1 -7.1,22.8c-6.2,30.8 1.8,59.2 22.7,80.1c19.7,19.7 41.7,29.7 65.5,29.7c0,0 0,0 0,0c7.5,0 15.1,-1 22.8,-3c-2.9,11.3 -3.7,22.3 -2.3,33.2c2.5,19.8 12.3,38.3 29,55.1c16.2,16.2 36.9,24.8 59.8,24.8c0,0 0,0 0,0c6.6,0 13.4,-0.7 20.2,-2.1c8.7,-1.8 16.5,-4.4 22.7,-7.1c6.3,2.6 14,5.3 22.7,7.1c6.9,1.4 13.7,2.1 20.3,2.1c0,0 0,0 0,0c22.9,0 43.6,-8.6 59.9,-24.8c17.6,-17.6 27.5,-37.2 29.4,-58.1c0.9,-9.9 0,-19.9 -2.7,-30.2c7.7,2 15.3,3 22.8,3c0,0 0,0 0,0c23.8,0 45.8,-10 65.5,-29.7c20.9,-20.9 29,-49.3 22.7,-80.1C488.8,264 486.1,256.3 483.4,250z"
android:fillColor="#242425"/>
<path
android:pathData="M170.4,444.6c13.2,13.2 30.1,17.8 50.3,13.7c14,-2.8 24.9,-9.1 26.9,-10.3l65.4,-65.4c-3.1,-6 -7.4,-12.5 -12.8,-19.4L250,413.3l0,0c-4.3,4.1 -13,12.1 -21.6,17.4c-5.2,3.2 -9.7,5.1 -13.5,5.6c-6.9,1.2 -12.7,0.9 -17.9,-0.9c-5,-1.8 -8.3,-4.8 -10.4,-6.8c-5.9,-5.9 -9.7,-11.3 -11.7,-16.7c-2,-5.5 -1.8,-10 -1.4,-13.3c0.5,-4.4 2,-9.2 4.2,-14.3l-17,-17C144.3,397.5 147.3,421.5 170.4,444.6z"
android:fillColor="#242425"/>
<path
android:pathData="M436.2,215c-0.6,3 -2,6.4 -4.3,10.4l18.2,18.2c2.4,-4.8 6.2,-13.1 8.2,-22.9c4.1,-20.2 -0.5,-37.1 -13.7,-50.3c-24.2,-24.2 -49.4,-26.4 -81.8,-7.3c-7.8,4.6 -16.1,10.6 -24.6,17.7c-19.5,16.3 -41.3,39.5 -64.9,69.2c15.4,19.4 30.2,36.2 43.8,49.8c6.3,6.3 12.4,12 18.3,17.1l16.2,-16.2c-5.9,-5 -12.1,-10.7 -18.4,-17c-9,-9 -18.5,-19.5 -28.4,-31.2l-2.1,-2.5l2.1,-2.5c18.1,-21.5 35,-38.6 50.1,-50.9c9.6,-7.8 18.6,-13.8 26.7,-17.7c7,-3.4 13.4,-5.3 19,-5.6c2.7,-0.2 6.9,-0.1 12.1,2c5,2.1 10.2,5.8 15.7,11.3c2.1,2.1 5,5.4 6.8,10.4C437.1,202.1 437.5,208 436.2,215L436.2,215z"
android:fillColor="#FFFFFF"/>
<path
android:pathData="M340.9,354.7l81.5,-81.5c-4.8,-7.1 -11.1,-14 -14.6,-17.7L327.3,336C332.5,342.4 337.1,348.6 340.9,354.7z"
android:fillColor="#FFFFFF"/>
<path
android:pathData="M444.6,329.6c13.2,-13.2 17.8,-30.1 13.7,-50.3c-2.8,-14 -9.1,-24.9 -10.3,-26.9L382.6,187c-6,3.1 -12.5,7.4 -19.4,12.8l50.1,50.1l0,0c4.1,4.3 12.1,13 17.4,21.6c3.2,5.2 5.1,9.7 5.6,13.5c1.2,6.9 0.9,12.7 -0.9,17.9c-1.8,5 -4.8,8.3 -6.8,10.4c-5.9,5.9 -11.3,9.7 -16.7,11.7c-5.5,2 -10,1.8 -13.3,1.4c-4.4,-0.5 -9.2,-2 -14.3,-4.2l-17,17C397.5,355.7 421.5,352.7 444.6,329.6z"
android:fillColor="#FFFFFF"/>
<path
android:pathData="M303.1,64.7c5,1.8 8.3,4.8 10.4,6.8c5.9,5.9 9.7,11.3 11.7,16.7c2,5.5 1.8,10 1.4,13.3c-0.5,4.4 -2,9.2 -4.2,14.3l17,17c16.4,-30.3 13.3,-54.4 -9.7,-77.4c-13.2,-13.2 -30.1,-17.8 -50.3,-13.7c-14,2.8 -24.9,9.1 -26.9,10.3L187,117.4c3.1,6 7.4,12.5 12.8,19.4L250,86.7l0,0c4.3,-4.1 13,-12.1 21.6,-17.4c5.2,-3.2 9.7,-5.1 13.5,-5.6C292,62.6 297.9,62.9 303.1,64.7z"
android:fillColor="#FFFFFF"/>
<path
android:pathData="M170.4,55.4c-24.2,24.2 -26.4,49.4 -7.3,81.8c4.6,7.8 10.6,16.1 17.7,24.6c16.3,19.5 39.5,41.3 69.2,64.9c19.4,-15.4 36.2,-30.2 49.8,-43.8c6.3,-6.3 12,-12.4 17.1,-18.3l-16.2,-16.2c-5,5.9 -10.7,12.1 -17,18.4c-9,9 -19.5,18.5 -31.2,28.4l-2.5,2.1l-2.5,-2.1c-21.5,-18.1 -38.6,-35 -50.9,-50.1c-7.8,-9.6 -13.8,-18.6 -17.7,-26.7c-3.4,-7 -5.3,-13.4 -5.6,-19c-0.2,-2.7 -0.1,-6.9 2,-12.1c2.1,-5 5.8,-10.2 11.3,-15.7c2.1,-2.1 5.4,-5 10.4,-6.8c5.2,-1.9 11.1,-2.2 18,-0.9l0.1,0c3,0.6 6.4,2 10.4,4.3l18.2,-18.2c-4.8,-2.4 -13.1,-6.2 -23,-8.2C200.5,37.6 183.6,42.2 170.4,55.4z"
android:fillColor="#FFFFFF"/>
<path
android:pathData="M273.2,77.6c-7.1,4.8 -14,11.1 -17.7,14.6l80.5,80.5c6.4,-5.2 12.7,-9.7 18.7,-13.6L273.2,77.6z"
android:fillColor="#FFFFFF"/>
<path
android:pathData="M55.4,329.6c24.2,24.2 49.4,26.4 81.8,7.3c7.8,-4.6 16.1,-10.6 24.6,-17.7c19.5,-16.3 41.3,-39.5 64.9,-69.2c-15.4,-19.4 -30.2,-36.2 -43.8,-49.8c-6.3,-6.3 -12.4,-12 -18.3,-17.1l-16.2,16.2c5.9,5 12.1,10.7 18.4,17c9,9 18.5,19.5 28.4,31.2l2.1,2.5l-2.1,2.5c-18.1,21.5 -35,38.6 -50.1,50.9c-9.6,7.8 -18.6,13.8 -26.7,17.7c-7,3.4 -13.4,5.3 -19,5.6c-2.7,0.2 -6.9,0.1 -12.1,-2c-5,-2.1 -10.2,-5.8 -15.7,-11.3c-2.1,-2.1 -5,-5.4 -6.8,-10.4c-1.9,-5.2 -2.2,-11.1 -0.9,-18l0,-0.1c0.6,-3 2,-6.4 4.3,-10.4l-18.2,-18.2c-2.4,4.8 -6.2,13.1 -8.2,23C37.6,299.5 42.2,316.4 55.4,329.6z"
android:fillColor="#FFFFFF"/>
<path
android:pathData="M86.7,250L86.7,250c-4.1,-4.4 -12,-13.1 -17.3,-21.6c-3.2,-5.2 -5.1,-9.7 -5.6,-13.5c-1.2,-6.9 -0.9,-12.7 0.9,-17.9c1.8,-5 4.8,-8.3 6.8,-10.4c5.9,-5.9 11.3,-9.7 16.7,-11.7c5.5,-2 10,-1.8 13.3,-1.4c4.4,0.5 9.2,2 14.3,4.2l17,-17c-30.3,-16.4 -54.4,-13.3 -77.4,9.7c-13.2,13.2 -17.8,30.1 -13.7,50.3c2.8,14 9.1,24.9 10.3,26.9l65.4,65.4c6,-3.1 12.5,-7.4 19.4,-12.8L86.7,250z"
android:fillColor="#FFFFFF"/>
<path
android:pathData="M92.2,244.5l80.5,-80.5c-5.2,-6.4 -9.7,-12.7 -13.6,-18.7l-81.5,81.5C82.4,233.9 88.6,240.8 92.2,244.5z"
android:fillColor="#FFFFFF"/>
<path
android:pathData="M329.6,444.6c24.2,-24.2 26.4,-49.4 7.3,-81.8c-4.6,-7.8 -10.6,-16.1 -17.7,-24.6c-16.3,-19.5 -39.5,-41.3 -69.2,-64.9c-19.4,15.4 -36.2,30.2 -49.8,43.8c-6.3,6.3 -12,12.4 -17.1,18.3l16.2,16.2c5,-5.9 10.7,-12.1 17,-18.4c9,-9 19.5,-18.5 31.2,-28.4l2.5,-2.1l2.5,2.1c21.5,18.1 38.6,35 50.9,50.1c7.8,9.6 13.8,18.6 17.7,26.7c3.4,7 5.3,13.4 5.6,19c0.2,2.7 0.1,6.9 -2,12.1c-2.1,5 -5.8,10.2 -11.3,15.7c-2.1,2.1 -5.4,5 -10.4,6.8c-5.2,1.9 -11.1,2.2 -18,0.9l-0.1,0c-3,-0.6 -6.4,-2 -10.4,-4.3l-18.2,18.2c4.7,2.4 13.1,6.1 22.9,8.2C299.4,462.4 316.4,457.8 329.6,444.6z"
android:fillColor="#FFFFFF"/>
<path
android:pathData="M244.5,407.8L164,327.3c-6.4,5.2 -12.7,9.7 -18.7,13.6l81.5,81.5C233.9,417.6 240.8,411.4 244.5,407.8z"
android:fillColor="#FFFFFF"/>
<path
android:pathData="M170.4,444.6c13.2,13.2 30.1,17.8 50.3,13.7c14,-2.8 24.9,-9.1 26.9,-10.3l65.4,-65.4c-3.1,-6 -7.4,-12.5 -12.8,-19.4L250,413.3l0,0c-4.3,4.1 -13,12.1 -21.6,17.4c-5.2,3.2 -9.7,5.1 -13.5,5.6c-6.9,1.2 -12.7,0.9 -17.9,-0.9c-5,-1.8 -8.3,-4.8 -10.4,-6.8c-5.9,-5.9 -9.7,-11.3 -11.7,-16.7c-2,-5.5 -1.8,-10 -1.4,-13.3c0.5,-4.4 2,-9.2 4.2,-14.3l-17,-17C144.3,397.5 147.3,421.5 170.4,444.6z"
android:fillColor="#FFFFFF"/>
</vector>

View File

@ -1,10 +1,12 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen --> <!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/darkGreyPurple" /> <item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here --> <!-- You can insert your own image assets here -->
<item android:drawable="@drawable/knott" <!-- <item>
android:gravity="center" <bitmap
/> android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list> </layer-list>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.airbnb.lottie.LottieAnimationView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:lottie_autoPlay="true"
app:lottie_rawRes="@raw/cwtch_animated_logo_op"
app:lottie_loop="true"
app:lottie_speed="1.00"
app:lottie_enableMergePathsForKitKatAndAbove="true" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@drawable/knott"/>
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

File diff suppressed because one or more lines are too long

View File

@ -1,23 +1,18 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off --> <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar"> <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when <!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame --> Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item> <item name="android:windowBackground">@drawable/launch_background</item>
</style> </style>
<!-- Theme applied to the Android Window as soon as the process has started. <!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its Flutter UI initializes, as well as behind your Flutter UI while its
running. running.
This Theme is only used starting with V2 of Flutter's Android embedding. --> This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar"> <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item> <item name="android:windowBackground">?android:colorBackground</item>
</style> </style>
</resources> </resources>

View File

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowSplashScreenBackground">@color/darkGreyPurple</item>
<item name="android:windowSplashScreenAnimatedIcon">@drawable/knott</item>
<item name="android:windowSplashScreenIconBackgroundColor">@color/darkGreyPurple</item>
</style>
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@ -1,5 +0,0 @@
<resources>
<color name="darkGreyPurple">#281831</color>
<color name="testGreen">#00ff00</color>
<color name="ic_launcher_background">@color/darkGreyPurple</color>
</resources>

View File

@ -1,3 +1,18 @@
buildscript {
ext.kotlin_version = '1.8.21'
repositories {
google()
// jCenter() no longer exists... https://blog.gradle.org/jcenter-shutdown
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.0.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects { allprojects {
repositories { repositories {
google() google()
@ -13,6 +28,7 @@ subprojects {
project.evaluationDependsOn(':app') project.evaluationDependsOn(':app')
} }
tasks.register("clean", Delete) { //removed due to gradle namespace conflicts that are beyond erinn's mere mortal understanding
delete rootProject.buildDir //task clean(type: Delete) {
} // delete rootProject.buildDir
//}

View File

@ -1,25 +1,11 @@
pluginManagement { include ':app', ':cwtch'
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}()
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
def properties = new Properties()
repositories { assert localPropertiesFile.exists()
google() localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
mavenCentral()
gradlePluginPortal()
}
}
plugins { def flutterSdkPath = properties.getProperty("flutter.sdk")
id "dev.flutter.flutter-plugin-loader" version "1.0.0" assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
id "com.android.application" version "7.4.2" apply false apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
id "org.jetbrains.kotlin.android" version "1.8.21" apply false
}
include ":app"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

View File

@ -1,107 +1,104 @@
--- ---
colors: colors:
darkGreyPurple: 0x281831 darkGreyPurple: 0x281831
deepPurple: 0x422850 deepPurple: 0x422850
mauvePurple: 0x8E64A5 mauvePurple: 0x8E64A5
whiteishPurple: 0xE3DFE4 whiteishPurple: 0xE3DFE4
lightGrey: 0x9E9E9E lightGrey: 0x9E9E9E
softGreen: 0xA0FFB0 softGreen: 0xA0FFB0
softRed: 0xFFA0B0 softRed: 0xFFA0B0
whitePurple: 0xFFFDFF whitePurple: 0xFFFDFF
softPurple: 0xFDF3FC softPurple: 0xFDF3FC
purple: 0xDFB9DE purple: 0xDFB9DE
brightPurple: 0xD1B0E0 # not in new: portrait badge color brightPurple: 0xD1B0E0 # not in new: portrait badge color
darkPurple: 0x350052 darkPurple: 0x350052
greyPurple: 0x775F84 # not in new: portrait borders greyPurple: 0x775F84 # not in new: portrait borders
pink: 0xE85DA1 # not in new: active button color pink: 0xE85DA1 # not in new: active button color
hotPink: 0xD20070 # #D01972) hotPink: 0xD20070 # #D01972)
softGrey: 0xB3B6B3 # not in new theme: blocked softGrey: 0xB3B6B3 # not in new theme: blocked
themes:
name: cwtch themes:
dark: name: cwtch
colors: dark:
background: darkGreyPurple colors:
header: darkGreyPurple background: darkGreyPurple
userBubble: mauvePurple header: darkGreyPurple
peerBubble: deepPurple userBubble: mauvePurple
font: whiteishPurple peerBubble: deepPurple
settings: whiteishPurple font: whiteishPurple
accent: hotPink settings: whiteishPurple
theme: accent: hotPink
backgroundHilightElementColor: deepPurple theme:
backgroundMainColor: background # darkGreyPurple backgroundHilightElementColor: deepPurple
backgroundPaneColor: header # darkGreyPurple backgroundMainColor: background # darkGreyPurple
defaultButtonColor: accent # hotPink backgroundPaneColor: header # darkGreyPurple
defaultButtonDisabledColor: lightGrey defaultButtonColor: accent # hotPink
defaultButtonDisabledTextColor: darkGreyPurple defaultButtonDisabledColor: lightGrey
defaultButtonTextColor: whiteishPurple defaultButtonDisabledTextColor: darkGreyPurple
dropShadowColor: mauvePurple defaultButtonTextColor: whiteishPurple
hilightElementColor: purple dropShadowColor: mauvePurple
mainTextColor: font # whiteishPurple hilightElementColor: purple
messageFromMeBackgroundColor: userBubble # mauvePurple mainTextColor: font # whiteishPurple
messageFromMeTextColor: font # whiteishPurple messageFromMeBackgroundColor: userBubble # mauvePurple
messageFromOtherBackgroundColor: peerBubble # deepPurple messageFromMeTextColor: font # whiteishPurple
messageFromOtherTextColor: font # whiteishPurple messageFromOtherBackgroundColor: peerBubble # deepPurple
portraitBackgroundColor: deepPurple messageFromOtherTextColor: font # whiteishPurple
portraitBlockedBorderColor: lightGrey portraitBackgroundColor: deepPurple
portraitBlockedTextColor: lightGrey portraitBlockedBorderColor: lightGrey
portraitContactBadgeColor: hotPink portraitBlockedTextColor: lightGrey
portraitContactBadgeTextColor: whiteishPurple portraitContactBadgeColor: hotPink
portraitOfflineBorderColor: purple portraitContactBadgeTextColor: whiteishPurple
portraitOnlineBorderColor: whiteishPurple portraitOfflineBorderColor: purple
portraitProfileBadgeColor: hotPink portraitOnlineBorderColor: whiteishPurple
portraitProfileBadgeTextColor: whiteishPurple portraitProfileBadgeColor: hotPink
scrollbarDefaultColor: purple portraitProfileBadgeTextColor: whiteishPurple
sendHintTextColor: mauvePurple scrollbarDefaultColor: purple
chatReactionIconColor: mauvePurple sendHintTextColor: mauvePurple
textfieldBackgroundColor: deepPurple chatReactionIconColor: mauvePurple
textfieldBorderColor: deepPurple textfieldBackgroundColor: deepPurple
textfieldErrorColor: hotPink textfieldBorderColor: deepPurple
textfieldHintColor: mainTextColor textfieldErrorColor: hotPink
toolbarIconColor: settings # whiteishPurple textfieldHintColor: mainTextColor
topbarColor: header # darkGreyPurple toolbarIconColor: settings # whiteishPurple
chatImage: Cwtch.png topbarColor: header # darkGreyPurple
chatImageColor: peerBubble light:
light: colors:
colors: background: whitePurple
background: whitePurple header: softPurple
header: softPurple userBubble: purple
userBubble: purple peerBubble: softPurple
peerBubble: softPurple font: darkPurple
font: 0x281831 settings: darkPurple
settings: 0x281831 accent: hotPink
accent: hotPink theme:
theme: backgroundHilightElementColor: softPurple
backgroundHilightElementColor: softPurple backgroundMainColor: background # whitePurple
backgroundMainColor: background # whitePurple backgroundPaneColor: background # whitePurple
backgroundPaneColor: background # whitePurple defaultButtonColor: accent # hotPink
defaultButtonColor: accent # hotPink defaultButtonDisabledColor: softGrey
defaultButtonDisabledColor: softGrey defaultButtonTextColor: whitePurple # ?
defaultButtonTextColor: whitePurple # ? dropShadowColor: purple
dropShadowColor: purple hilightElementColor: purple
hilightElementColor: purple mainTextColor: settings
mainTextColor: settings messageFromMeBackgroundColor: userBubble # brightPurple
messageFromMeBackgroundColor: userBubble # brightPurple messageFromMeTextColor: font # mainTextColor
messageFromMeTextColor: font # mainTextColor messageFromOtherBackgroundColor: peerBubble # purple
messageFromOtherBackgroundColor: peerBubble # purple messageFromOtherTextColor: font # darkPurple
messageFromOtherTextColor: font # darkPurple portraitBackgroundColor: softPurple
portraitBackgroundColor: softPurple portraitBlockedBorderColor: softGrey
portraitBlockedBorderColor: softGrey portraitBlockedTextColor: softGrey
portraitBlockedTextColor: softGrey portraitContactBadgeColor: accent
portraitContactBadgeColor: accent portraitContactBadgeTextColor: whitePurple
portraitContactBadgeTextColor: whitePurple portraitOfflineBorderColor: greyPurple
portraitOfflineBorderColor: greyPurple portraitOnlineBorderColor: greyPurple
portraitOnlineBorderColor: font portraitProfileBadgeColor: accent
portraitProfileBadgeColor: accent portraitProfileBadgeTextColor: whitePurple
portraitProfileBadgeTextColor: whitePurple scrollbarDefaultColor: accent
scrollbarDefaultColor: accent sendHintTextColor: purple
sendHintTextColor: purple chatReactionIconColor: purple
chatReactionIconColor: purple textfieldBackgroundColor: purple
textfieldBackgroundColor: purple textfieldBorderColor: purple
textfieldBorderColor: purple textfieldErrorColor: hotPink
textfieldErrorColor: hotPink textfieldHintColor: font
textfieldHintColor: font toolbarIconColor: settings # darkPurple
toolbarIconColor: background # darkPurple topbarColor: header # softPurple
topbarColor: header # softPurple
chatImage: Cwtch.png
chatImageColor: 0xf1dff0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

View File

@ -1,86 +1,68 @@
--- ---
colors: colors:
darkDarkBlue: 0x0E1628 darkDarkBlue: 0x000051
darkLightBlue: 0x19243E darkLightBlue: 0x1A237E
white: 0xE6E9F4 white: 0xFFFFFF
darkBlue: 0x131B2E darkBlue: 0xAAB6FE
lighterDarkBlue: 0x19243E lighterDarkBlue: 0xC3CCFE
lightBlue: 0xC0C8E5 lightBlue: 0xE8EAF6
themes: themes:
name: ghost name: ghost
dark: dark:
colors: colors:
background: 0x131B2E background: 0x0D0D1F
header: 0x0E1628 header: 0x0D0D1F
userBubble: 0x25355A userBubble: darkLightBlue
peerBubble: 0x19243E peerBubble: darkDarkBlue
font: 0xE6E9F4 font: white
settings: 0xE6E9F4 settings: 0xDFFFD
accent: 0xD20070 accent: darkLightBlue # Color(0xFFD20070)
reaction: 0x96A5D4 theme:
theme: backgroundHilightElementColor: darkDarkBlue
backgroundHilightElementColor: darkDarkBlue backgroundMainColor: background
backgroundMainColor: background backgroundPaneColor: header
backgroundPaneColor: header defaultButtonColor: accent
defaultButtonColor: accent dropShadowColor: darkBlue
dropShadowColor: darkBlue mainTextColor: font
mainTextColor: font messageFromMeBackgroundColor: userBubble
messageFromMeBackgroundColor: userBubble messageFromMeTextColor: font
messageFromMeTextColor: font messageFromOtherBackgroundColor: peerBubble
messageFromOtherBackgroundColor: peerBubble messageFromOtherTextColor: font
messageFromOtherTextColor: font scrollbarDefaultColor: darkLightBlue
portraitOfflineBorderColor: 0x96A5D4 sendHintTextColor: darkBlue
portraitOnlineBorderColor: font textfieldBackgroundColor: peerBubble
portraitBackgroundColor: background textfieldBorderColor: userBubble
scrollbarDefaultColor: darkLightBlue textfieldHintColor: mainTextColor
sendHintTextColor: userBubble toolbarIconColor: settings
textfieldBackgroundColor: peerBubble topbarColor: header
textfieldBorderColor: userBubble light:
textfieldHintColor: font colors:
toolbarIconColor: settings background: 0xFDFDFF
topbarColor: header header: darkBlue
chatReactionIconColor: reaction userBubble: darkBlue
chatImage: Ghost.png peerBubble: lightBlue
chatImageColor: userBubble font: 0x0D0D1F
snackbarBackgroundColor: accent settings: 0x0D0D1F
snackbarTextColor: 0xE6E9F4 accent: darkBlue
light: theme:
colors: backgroundHilightElementColor: peerBubble
background: 0xE6E9F4 backgroundMainColor: background
header: 0x96A5D4 backgroundPaneColor: background
userBubble: 0x96A5D4 defaultButtonColor: accent
peerBubble: 0xC0C8E5 defaultButtonActiveColor: lighterDarkBlue
font: 0x131B2E defaultButtonDisabledColor: peerBubble
settings: 0x131B2E dropShadowColor: darkBlue
accent: 0xD20070 mainTextColor: settings
reaction: 0x96A5D4 messageFromMeBackgroundColor: userBubble
theme: messageFromMeTextColor: font
backgroundHilightElementColor: peerBubble messageFromOtherBackgroundColor: peerBubble
backgroundMainColor: background messageFromOtherTextColor: font
backgroundPaneColor: background portraitContactBadgeColor: accent
defaultButtonColor: accent scrollbarDefaultColor: accent
defaultButtonActiveColor: lighterDarkBlue sendHintTextColor: lightBlue
defaultButtonDisabledColor: userBubble textfieldBackgroundColor: peerBubble
dropShadowColor: darkBlue textfieldBorderColor: userBubble
mainTextColor: settings textfieldHintColor: font
messageFromMeBackgroundColor: userBubble toolbarIconColor: settings
messageFromMeTextColor: font topbarColor: header
messageFromOtherBackgroundColor: peerBubble
messageFromOtherTextColor: font
portraitContactBadgeColor: accent
portraitOfflineBorderColor: header
portraitOnlineBorderColor: font
portraitBackgroundColor: background
scrollbarDefaultColor: accent
sendHintTextColor: peerBubble
textfieldBackgroundColor: peerBubble
textfieldBorderColor: userBubble
textfieldHintColor: font
toolbarIconColor: 0xffffff
topbarColor: header
chatReactionIconColor: reaction
chatImage: Ghost.png
chatImageColor: peerBubble
snackbarBackgroundColor: accent
snackbarTextColor: background

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

View File

@ -1,53 +1,47 @@
--- ---
themes: themes:
name: juniper name: juniper
dark: dark:
colors: colors:
background: 0x1B1B1B background: 0x1B1B1B
backgroundAlt: 0x494949 backgroundAlt: 0x494949
header: 0x1B1B1B header: 0x1B1B1B
userBubble: 0x373737 userBubble: 0x373737
peerBubble: 0x494949 peerBubble: 0x494949
font: 0xFFFFFF font: 0xFFFFFF
settings: 0xFFFDFF settings: 0xFFFDFF
accent: 0x9E6A56 accent: 0x9E6A56
accentAlt: 0x9E6A56 accentAlt: 0x845A48
theme: theme:
backgroundMainColor: background backgroundMainColor: background # darkGreyPurple
backgroundPaneColor: header backgroundPaneColor: header # darkGreyPurple
topbarColor: header topbarColor: header # darkGreyPurple
mainTextColor: font mainTextColor: font # whiteishPurple
defaultButtonColor: accent defaultButtonColor: accent # hotPink
textfieldHintColor: mainTextColor textfieldHintColor: mainTextColor # TODO pick
toolbarIconColor: settings toolbarIconColor: settings # whiteishPurple
messageFromMeBackgroundColor: userBubble messageFromMeBackgroundColor: userBubble # mauvePurple
messageFromMeTextColor: font messageFromMeTextColor: font # whiteishPurple
messageFromOtherBackgroundColor: peerBubble messageFromOtherBackgroundColor: peerBubble # deepPurple
messageFromOtherTextColor: font messageFromOtherTextColor: font # whiteishPurple
textfieldBackgroundColor: peerBubble textfieldBackgroundColor: peerBubble
textfieldBorderColor: userBubble textfieldBorderColor: userBubble
backgroundHilightElementColor: accent backgroundHilightElementColor: accent
sendHintTextColor: accentAlt sendHintTextColor: accentAlt
hilightElementColor: accentAlt hilightElementColor: accentAlt
defaultButtonTextColor: mainTextColor defaultButtonTextColor: mainTextColor
defaultButtonDisabledColor: peerBubble defaultButtonDisabledColor: peerBubble
defaultButtonDisabledTextColor: peerBubble defaultButtonDisabledTextColor: peerBubble
textfieldErrorColor: accent textfieldErrorColor: accent
scrollbarDefaultColor: accent scrollbarDefaultColor: accent
portraitBackgroundColor: header portraitBackgroundColor: header
portraitOnlineBorderColor: font portraitOnlineBorderColor: font
portraitOfflineBorderColor: peerBubble portraitOfflineBorderColor: peerBubble
portraitBlockedBorderColor: peerBubble portraitBlockedBorderColor: peerBubble
portraitBlockedTextColor: peerBubble portraitBlockedTextColor: peerBubble
portraitContactBadgeColor: accent portraitContactBadgeColor: accent
portraitContactBadgeTextColor: mainTextColor portraitContactBadgeTextColor: mainTextColor
portraitProfileBadgeColor: accent portraitProfileBadgeColor: accent
portraitProfileBadgeTextColor: mainTextColor portraitProfileBadgeTextColor: mainTextColor
dropShadowColor: accentAlt dropShadowColor: accentAlt
chatReactionIconColor: accentAlt
chatImage: JuniperDark.png
chatImageColor: userBubble
messageSelectionColor: accent
textfieldSelectionColor: accent
menuBackgroundColor: accent

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

View File

@ -1,91 +1,58 @@
--- ---
colors: colors:
lavender: 0xB194C1 lavender: 0xB194C1
themes: themes:
name: mermaid name: mermaid
dark: dark:
colors: colors:
background: 0x15282A background: 0x102426
header: 0x15282A header: 0x102426
userBubble: 0x1d5754 userBubble: 0x00838F
peerBubble: 0x253D3F peerBubble: 0x00363A
font: 0xEDFAFC font: 0xFFFFFF
settings: 0xEDFAFC settings: 0xF7FCFD
accent: 0x8E64A5 accent: 0x8E64A5
reaction: 0x8E64A5 theme:
theme: backgroundHilightElementColor: peerBubble
backgroundHilightElementColor: peerBubble backgroundMainColor: background # darkGreyPurple
backgroundMainColor: background # darkGreyPurple backgroundPaneColor: header # darkGreyPurple
backgroundPaneColor: header # darkGreyPurple defaultButtonColor: accent # hotPink
defaultButtonColor: accent # hotPink dropShadowColor: lavender
dropShadowColor: lavender mainTextColor: font # whiteishPurple
mainTextColor: font # whiteishPurple messageFromMeBackgroundColor: userBubble # mauvePurple
messageFromMeBackgroundColor: userBubble # mauvePurple messageFromMeTextColor: font # whiteishPurple
messageFromMeTextColor: font # whiteishPurple messageFromOtherBackgroundColor: peerBubble # deepPurple
messageFromOtherBackgroundColor: peerBubble # deepPurple messageFromOtherTextColor: font # whiteishPurple
messageFromOtherTextColor: font # whiteishPurple textfieldBackgroundColor: peerBubble
portraitOfflineBorderColor: userBubble textfieldBorderColor: userBubble
portraitOnlineBorderColor: font textfieldHintColor: mainTextColor
portraitContactBadgeColor: accent toolbarIconColor: settings # whiteishPurple
portraitContactBadgeTextColor: 0xffffff topbarColor: header # darkGreyPurple
portraitProfileBadgeColor: accent light:
portraitProfileBadgeTextColor: 0xffffff colors:
portraitBackgroundColor: background background: 0xF7FCFD
textfieldBackgroundColor: peerBubble header: 0x56C8D8
textfieldBorderColor: userBubble userBubble: 0x56C8D8
textfieldHintColor: mainTextColor peerBubble: 0xB2EBF2
toolbarIconColor: settings # whiteishPurple font: 0x102426
topbarColor: header # darkGreyPurple settings: 0x102426
sendHintTextColor: userBubble accent: 0x8E64A5
chatReactionIconColor: reaction theme:
chatImage: Mermaid.png backgroundHilightElementColor: peerBubble
chatImageColor: peerBubble backgroundMainColor: background # whitePurple
snackbarBackgroundColor: accent backgroundPaneColor: background # whitePurple
snackbarTextColor: 0xEDFAFC defaultButtonColor: accent # hotPink
messageSelectionColor: accent dropShadowColor: peerBubble
textfieldSelectionColor: accent mainTextColor: settings
menuBackgroundColor: accent messageFromMeBackgroundColor: userBubble # brightPurple
light: messageFromMeTextColor: font # mainTextColor
colors: messageFromOtherBackgroundColor: peerBubble # purple
background: 0xEDFAFC messageFromOtherTextColor: font # darkPurple
header: 0x71C1BF portraitContactBadgeColor: accent
userBubble: 0x71C1BF scrollbarDefaultColor: accent
peerBubble: 0xD2EFF3 textfieldBackgroundColor: peerBubble
font: 0x15282A textfieldBorderColor: userBubble
settings: 0x15282A textfieldHintColor: font
accent: 0x8E64A5 toolbarIconColor: settings # darkPurple
reaction: 0x71C1BF topbarColor: header # softPurple
theme:
backgroundHilightElementColor: peerBubble
backgroundMainColor: background # whitePurple
backgroundPaneColor: background # whitePurple
defaultButtonColor: accent # hotPink
dropShadowColor: peerBubble
mainTextColor: settings
messageFromMeBackgroundColor: userBubble # brightPurple
messageFromMeTextColor: font # mainTextColor
messageFromOtherBackgroundColor: peerBubble # purple
messageFromOtherTextColor: font # darkPurple
portraitContactBadgeColor: accent
portraitContactBadgeTextColor: 0xffffff
portraitProfileBadgeColor: accent
portraitProfileBadgeTextColor: 0xffffff
portraitOfflineBorderColor: userBubble
portraitOnlineBorderColor: font
portraitBackgroundColor: background
scrollbarDefaultColor: accent
textfieldBackgroundColor: peerBubble
textfieldBorderColor: userBubble
textfieldHintColor: font
toolbarIconColor: 0xffffff
topbarColor: header # softPurple
sendHintTextColor: userBubble
chatReactionIconColor: reaction
chatImage: Mermaid.png
chatImageColor: peerBubble
snackbarBackgroundColor: accent
snackbarTextColor: background
messageSelectionColor: 0xb1e3ea
textfieldSelectionColor: 0xb1e3ea
menuBackgroundColor: 0xb1e3ea

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

View File

@ -1,77 +1,59 @@
--- ---
themes: themes:
name: midnight name: midnight
dark: dark:
colors: colors:
accentGray: 0xE0E0E0 accentGray: 0xE0E0E0
background: 0x111111 background: 0x1B1B1B
backgroundAlt: 0x494949 backgroundAlt: 0x494949
header: 0x111111 header: 0x1B1B1B
userBubble: 0x2D2D2D userBubble: 0x373737
peerBubble: 0x1B1B1B peerBubble: 0x494949
font: 0xF0F1F1 font: 0xFFFFFF
settings: 0xF0F1F1 settings: 0xFFFDFF
accent: 0xD20070 accent: 0xD20070
reaction: 0xD20070 theme:
theme: backgroundHilightElementColor: backgroundAlt
backgroundHilightElementColor: backgroundAlt backgroundMainColor: background # darkGreyPurple
backgroundMainColor: background # darkGreyPurple backgroundPaneColor: header # darkGreyPurple
backgroundPaneColor: header # darkGreyPurple defaultButtonColor: accent # hotPink
defaultButtonColor: accent # hotPink dropShadowColor: accentGray
dropShadowColor: accentGray mainTextColor: font # whiteishPurple
mainTextColor: font # whiteishPurple messageFromMeBackgroundColor: userBubble # mauvePurple
messageFromMeBackgroundColor: userBubble # mauvePurple messageFromMeTextColor: font # whiteishPurple
messageFromMeTextColor: font # whiteishPurple messageFromOtherBackgroundColor: peerBubble # deepPurple
messageFromOtherBackgroundColor: peerBubble # deepPurple messageFromOtherTextColor: font # whiteishPurple
messageFromOtherTextColor: font # whiteishPurple scrollbarDefaultColor: accentGray
scrollbarDefaultColor: accentGray textfieldBackgroundColor: peerBubble
textfieldBackgroundColor: peerBubble textfieldBorderColor: userBubble
textfieldBorderColor: userBubble textfieldHintColor: mainTextColor
textfieldHintColor: mainTextColor toolbarIconColor: settings # whiteishPurple
portraitOfflineBorderColor: 0x676767 topbarColor: header # darkGreyPurple
portraitOnlineBorderColor: font light:
portraitBackgroundColor: background colors:
toolbarIconColor: settings # whiteishPurple background: 0xFBFBFB # Color( 0xFFFDFF)
topbarColor: header # darkGreyPurple header: 0xE0E0E0
sendHintTextColor: userBubble userBubble: 0xE0E0E0
chatReactionIconColor: reaction peerBubble: 0xBABDBE
chatImage: Midnight.png font: 0x1B1B1B
chatImageColor: userBubble settings: 0x1B1B1B
snackbarBackgroundColor: accent accent: 0xD20070
snackbarTextColor: 0xF0F1F1 theme:
light: backgroundHilightElementColor: peerBubble
colors: backgroundMainColor: background # whitePurple
background: 0xF0F1F1 # Color( 0xFFFDFF) backgroundPaneColor: background # whitePurple
header: 0xE0E0E0 defaultButtonColor: accent # hotPink
userBubble: 0xBABDBE mainTextColor: settings
peerBubble: 0xE0E0E0 messageFromMeBackgroundColor: userBubble # brightPurple
font: 0x111111 messageFromMeTextColor: font # mainTextColor
settings: 0x111111 messageFromOtherBackgroundColor: peerBubble # purple
accent: 0xD20070 messageFromOtherTextColor: font # darkPurple
reaction: 0xD20070 portraitContactBadgeColor: accent
theme: portraitOfflineBorderColor: peerBubble
backgroundHilightElementColor: peerBubble portraitOnlineBorderColor: font
backgroundMainColor: background # whitePurple scrollbarDefaultColor: accent
backgroundPaneColor: background # whitePurple textfieldBackgroundColor: userBubble
defaultButtonColor: accent # hotPink textfieldHintColor: font
mainTextColor: settings toolbarIconColor: settings # darkPurple
messageFromMeBackgroundColor: userBubble # brightPurple topbarColor: header # softPurple
messageFromMeTextColor: font # mainTextColor
messageFromOtherBackgroundColor: peerBubble # purple
messageFromOtherTextColor: font # darkPurple
portraitContactBadgeColor: accent
portraitOfflineBorderColor: userBubble
portraitOnlineBorderColor: font
portraitBackgroundColor: background
scrollbarDefaultColor: accent
textfieldBackgroundColor: userBubble
textfieldHintColor: font
toolbarIconColor: 0xffffff
topbarColor: header # softPurple
sendHintTextColor: userBubble
chatReactionIconColor: reaction
chatImage: Midnight.png
chatImageColor: peerBubble
snackbarBackgroundColor: accent
snackbarTextColor: background

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

View File

@ -1,86 +1,54 @@
--- ---
themes: themes:
name: neon1 name: neon1
dark: dark:
colors: colors:
background: 0x281831 background: 0x290826
header: 0x281831 header: 0x290826
userBubble: 0x7F00C5 userBubble: 0xD20070
peerBubble: 0x422850 peerBubble: 0x26A9A4
font: 0xFBF3FF font: 0xFFFFFF
settings: 0x281831 settings: 0xFFFDFF
accent: 0x56DCD8 accent: 0xA604FE
reaction: 0xD891FF theme:
theme: backgroundMainColor: background # darkGreyPurple
backgroundMainColor: background # darkGreyPurple backgroundPaneColor: header # darkGreyPurple
backgroundPaneColor: header # darkGreyPurple defaultButtonColor: accent # hotPink
defaultButtonColor: accent # hotPink mainTextColor: font # whiteishPurple
mainTextColor: 0xFBF3FF # whiteishPurple messageFromMeBackgroundColor: userBubble # mauvePurple
messageFromMeBackgroundColor: userBubble # mauvePurple messageFromMeTextColor: font # whiteishPurple
messageFromMeTextColor: font # whiteishPurple messageFromOtherBackgroundColor: peerBubble # deepPurple
messageFromOtherBackgroundColor: peerBubble # deepPurple messageFromOtherTextColor: font # whiteishPurple
messageFromOtherTextColor: font # whiteishPurple scrollbarDefaultColor: accent
portraitContactBadgeColor: accent textfieldHintColor: mainTextColor
portraitContactBadgeTextColor: background toolbarIconColor: settings # whiteishPurple
portraitProfileBadgeColor: accent topbarColor: header # darkGreyPurple
portraitProfileBadgeTextColor: background light:
portraitBackgroundColor: background colors:
portraitOfflineBorderColor: 0x775F84 background: 0xFFFDFF
portraitOnlineBorderColor: font header: 0xFF94C2
scrollbarDefaultColor: accent userBubble: 0xFF94C2
textfieldHintColor: mainTextColor peerBubble: 0xE7F6F6
toolbarIconColor: settings # whiteishPurple font: 0x290826
topbarColor: header # darkGreyPurple settings: 0x290826
sendHintTextColor: userBubble accent: 0xA604FE
chatReactionIconColor: reaction theme:
defaultButtonTextColor: 0x281831 backgroundMainColor: background # whitePurple
chatImage: Neon1.png backgroundPaneColor: background # whitePurple
chatImageColor: 0x4f3060 defaultButtonColor: accent # hotPink
snackbarBackgroundColor: accent dropShadowColor: userBubble
snackbarTextColor: background mainTextColor: settings
messageSelectionColor: 0x775F84 messageFromMeBackgroundColor: userBubble # brightPurple
textfieldSelectionColor: 0x775F84 messageFromMeTextColor: font # mainTextColor
menuBackgroundColor: 0x775F84 messageFromOtherBackgroundColor: peerBubble # purple
light: messageFromOtherTextColor: font # darkPurple
colors: portraitContactBadgeColor: accent
background: 0xFBF3FF portraitOfflineBorderColor: peerBubble
header: 0x56DCD8 portraitOnlineBorderColor: font
userBubble: 0x56DCD8 scrollbarDefaultColor: accent
peerBubble: 0xF5E1FF textfieldBackgroundColor: peerBubble
font: 0x281831 textfieldBorderColor: userBubble
settings: 0x281831 textfieldHintColor: font
accent: 0xD891FF toolbarIconColor: settings # darkPurple
reaction: 0xD891FF topbarColor: header # softPurple
theme:
backgroundMainColor: background # whitePurple
backgroundPaneColor: background # whitePurple
defaultButtonColor: accent # hotPink
dropShadowColor: userBubble
mainTextColor: settings
messageFromMeBackgroundColor: userBubble # brightPurple
messageFromMeTextColor: font # mainTextColor
messageFromOtherBackgroundColor: peerBubble # purple
messageFromOtherTextColor: font # darkPurple
portraitOfflineBorderColor: 0xeac1ff
portraitOnlineBorderColor: font
portraitContactBadgeColor: accent
portraitContactBadgeTextColor: font
portraitProfileBadgeColor: accent
portraitProfileBadgeTextColor: font
scrollbarDefaultColor: accent
textfieldBackgroundColor: peerBubble
textfieldBorderColor: userBubble
textfieldHintColor: font
toolbarIconColor: settings # darkPurple
topbarColor: header # softPurple
sendHintTextColor: 0xeac1ff
chatReactionIconColor: reaction
chatImage: Neon1.png
chatImageColor: 0xeac1ff
defaultButtonTextColor: font
snackbarBackgroundColor: accent
snackbarTextColor: font
messageSelectionColor: accent
textfieldSelectionColor: accent
menuBackgroundColor: accent

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

View File

@ -1,83 +1,55 @@
--- ---
themes: themes:
name: neon2 name: neon2
dark: dark:
colors: colors:
background: 0x281831 background: 0x290826
header: 0x281831 header: 0x290826
userBubble: 0x7F00C5 userBubble: 0xA604FE
peerBubble: 0x422850 peerBubble: 0x03AD00
font: 0xFBF3FF font: 0xFFFFFF
settings: 0x281831 settings: 0xFFFDFF
accent: 0x90EE02 accent: 0xA604FE
reaction: 0xD891FF theme:
theme: backgroundMainColor: background # darkGreyPurple
backgroundMainColor: background # darkGreyPurple backgroundPaneColor: header # darkGreyPurple
backgroundPaneColor: header # darkGreyPurple defaultButtonColor: accent # hotPink
defaultButtonColor: accent # hotPink mainTextColor: font # whiteishPurple
mainTextColor: font # whiteishPurple messageFromMeBackgroundColor: userBubble # mauvePurple
messageFromMeBackgroundColor: userBubble # mauvePurple messageFromMeTextColor: font # whiteishPurple
messageFromMeTextColor: font # whiteishPurple messageFromOtherBackgroundColor: peerBubble # deepPurple
messageFromOtherBackgroundColor: peerBubble # deepPurple messageFromOtherTextColor: font # whiteishPurple
messageFromOtherTextColor: font # whiteishPurple scrollbarDefaultColor: accent
portraitContactBadgeColor: accent textfieldHintColor: mainTextColor
portraitContactBadgeTextColor: 0x281831 toolbarIconColor: settings # whiteishPurple
portraitProfileBadgeColor: accent topbarColor: header # darkGreyPurple
portraitProfileBadgeTextColor: 0x281831 light:
scrollbarDefaultColor: accent colors:
textfieldHintColor: mainTextColor paleGreen: 0xE7F6F6
toolbarIconColor: settings # whiteishPurple background: 0xFFFDFF
topbarColor: header # darkGreyPurple header: 0xD8C7E1
sendHintTextColor: userBubble userBubble: 0xD8C7E1
chatReactionIconColor: reaction peerBubble: 0x80E27E
defaultButtonTextColor: background font: 0x290826
chatImage: Neon2.png settings: 0x290826
chatImageColor: 0x573569 accent: 0xA604FE
snackbarBackgroundColor: accent theme:
snackbarTextColor: background backgroundMainColor: background # whitePurple
messageSelectionColor: 0x775F84 backgroundPaneColor: background # whitePurple
textfieldSelectionColor: 0x775F84 defaultButtonColor: accent # hotPink
menuBackgroundColor: 0x775F84 dropShadowColor: userBubble
light: mainTextColor: settings
colors: messageFromMeBackgroundColor: userBubble # brightPurple
paleGreen: 0xE7F6F6 messageFromMeTextColor: font # mainTextColor
background: 0xFBFFF6 messageFromOtherBackgroundColor: peerBubble # purple
header: 0x90EE02 messageFromOtherTextColor: font # darkPurple
userBubble: 0x90EE02 portraitContactBadgeColor: accent
peerBubble: 0xF3FFE4 portraitOfflineBorderColor: peerBubble
font: 0x281831 portraitOnlineBorderColor: font
settings: 0x281831 scrollbarDefaultColor: accent
accent: 0x7F00C5 textfieldBackgroundColor: paleGreen
reaction: 0x7F00C5 textfieldBorderColor: peerBubble
theme: textfieldHintColor: font
backgroundMainColor: background # whitePurple toolbarIconColor: settings # darkPurple
backgroundPaneColor: background # whitePurple topbarColor: header # softPurple
defaultButtonColor: accent # hotPink
dropShadowColor: userBubble
mainTextColor: settings
messageFromMeBackgroundColor: userBubble # brightPurple
messageFromMeTextColor: font # mainTextColor
messageFromOtherBackgroundColor: peerBubble # purple
messageFromOtherTextColor: font # darkPurple
portraitOfflineBorderColor: 0x775F84
portraitOnlineBorderColor: font
portraitContactBadgeColor: accent
portraitContactBadgeTextColor: background
portraitProfileBadgeColor: accent
portraitProfileBadgeTextColor: background
portraitBackgroundColor: background
scrollbarDefaultColor: accent
textfieldBackgroundColor: paleGreen
textfieldBorderColor: peerBubble
textfieldHintColor: font
toolbarIconColor: background # darkPurple
topbarColor: header # softPurple
chatReactionIconColor: accent
chatImage: Neon2.png
chatImageColor: 0xd9ffa8
snackbarBackgroundColor: accent
snackbarTextColor: background
messageSelectionColor: 0xd9ffa8
textfieldSelectionColor: 0xd9ffa8
menuBackgroundColor: 0xd9ffa8

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

View File

@ -1,84 +1,49 @@
--- ---
themes: themes:
name: pumpkin name: pumpkin
dark: dark:
colors: colors:
background: 0x281831 background: 0x281831
header: 0x281831 header: 0x281831
userBubble: 0x873C14 userBubble: 0xB53D00
peerBubble: 0x422850 peerBubble: 0x422850
font: 0xFFFAF2 font: 0xFFFFFF
settings: 0xFFFAF2 settings: 0xFFFBF6
accent: 0x873C14 accent: 0x8E64A5
reaction: 0x873C14 theme:
theme: backgroundMainColor: background # darkGreyPurple
backgroundMainColor: background # darkGreyPurple backgroundPaneColor: header # darkGreyPurple
backgroundPaneColor: header # darkGreyPurple defaultButtonColor: accent # hotPink
defaultButtonColor: accent # hotPink mainTextColor: font # whiteishPurple
mainTextColor: font # whiteishPurple messageFromMeBackgroundColor: userBubble # mauvePurple
messageFromMeBackgroundColor: userBubble # mauvePurple messageFromMeTextColor: font # whiteishPurple
messageFromMeTextColor: font # whiteishPurple messageFromOtherBackgroundColor: peerBubble # deepPurple
messageFromOtherBackgroundColor: peerBubble # deepPurple messageFromOtherTextColor: font # whiteishPurple
messageFromOtherTextColor: font # whiteishPurple textfieldHintColor: mainTextColor
scrollbarDefaultColor: accent toolbarIconColor: settings # whiteishPurple
portraitContactBadgeColor: accent topbarColor: header # darkGreyPurple
portraitContactBadgeTextColor: 0xFFFAF2 light:
portraitProfileBadgeColor: accent colors:
portraitProfileBadgeTextColor: 0xFFFAF2 background: 0xFFFBF6
portraitOfflineBorderColor: 0x775F84 header: 0xFF9800
portraitOnlineBorderColor: font userBubble: 0xFF9800
textfieldHintColor: mainTextColor peerBubble: 0xD8C7E1
toolbarIconColor: settings # whiteishPurple font: 0x281831
topbarColor: header # darkGreyPurple settings: 0x281831
sendHintTextColor: peerBubble accent: 0x8E64A5
chatReactionIconColor: reaction theme:
chatImage: Pumpkin.png backgroundMainColor: background # whitePurple
chatImageColor: 0x573569 backgroundPaneColor: background # whitePurple
snackbarBackgroundColor: accent defaultButtonColor: accent # hotPink
snackbarTextColor: 0xFFFAF2 dropShadowColor: peerBubble
messageSelectionColor: 0x775F84 mainTextColor: settings
textfieldSelectionColor: 0x775F84 messageFromMeBackgroundColor: userBubble # brightPurple
menuBackgroundColor: 0x775F84 messageFromMeTextColor: font # mainTextColor
light: messageFromOtherBackgroundColor: peerBubble # purple
colors: messageFromOtherTextColor: font # darkPurple
background: 0xFFFAF2 portraitContactBadgeColor: accent
header: 0xFF9800 scrollbarDefaultColor: accent
userBubble: 0xFF9800 textfieldHintColor: font
peerBubble: 0xFFF3E0 toolbarIconColor: settings # darkPurple
font: 0x281831 topbarColor: header # softPurple
settings: 0x281831
accent: 0x422850
reaction: 0xFF9800
theme:
backgroundHilightElementColor: peerBubble
backgroundMainColor: background # whitePurple
backgroundPaneColor: background # whitePurple
defaultButtonColor: accent # hotPink
dropShadowColor: peerBubble
mainTextColor: settings
messageFromMeBackgroundColor: userBubble # brightPurple
messageFromMeTextColor: font # mainTextColor
messageFromOtherBackgroundColor: peerBubble # purple
messageFromOtherTextColor: font # darkPurple
portraitContactBadgeColor: accent
portraitContactBadgeTextColor: 0xFFFAF2
portraitProfileBadgeColor: accent
portraitProfileBadgeTextColor: 0xFFFAF2
portraitOfflineBorderColor: 0x775F84
portraitOnlineBorderColor: font
scrollbarDefaultColor: accent
textfieldBackgroundColor: background
textfieldBorderColor: userBubble
textfieldHintColor: mainTextColor
toolbarIconColor: background # darkPurple
topbarColor: header # softPurple
sendHintTextColor: 0xffd494
chatReactionIconColor: reaction
chatImage: Pumpkin.png
chatImageColor: 0xFFDCA8
snackbarBackgroundColor: accent
snackbarTextColor: background
messageSelectionColor: 0xFFDCA8
textfieldSelectionColor: 0xFFDCA8
menuBackgroundColor: 0xFFDCA8

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

View File

@ -1,85 +1,52 @@
--- ---
themes: themes:
name: vampire name: vampire
dark: dark:
colors: colors:
background: 0x27141B background: 0x281831
header: 0x27141B header: 0x281831
userBubble: 0x422850 userBubble: 0x9A1218
peerBubble: 0x502033 peerBubble: 0x422850
font: 0xFBF4F7 font: 0xFFFFFF
settings: 0xFBF4F7 settings: 0xFDFFFD
accent: 0x502033 accent: 0x8E64A5
reaction: 0xC86B89 theme:
theme: backgroundMainColor: background # darkGreyPurple
backgroundMainColor: background # darkGreyPurple backgroundPaneColor: header # darkGreyPurple
backgroundPaneColor: header # darkGreyPurple defaultButtonColor: accent # hotPink
defaultButtonColor: accent # hotPink mainTextColor: font # whiteishPurple
mainTextColor: font # whiteishPurple messageFromMeBackgroundColor: userBubble # mauvePurple
messageFromMeBackgroundColor: userBubble # mauvePurple messageFromMeTextColor: font # whiteishPurple
messageFromMeTextColor: font # whiteishPurple messageFromOtherBackgroundColor: peerBubble # deepPurple
messageFromOtherBackgroundColor: peerBubble # deepPurple messageFromOtherTextColor: font # whiteishPurple
messageFromOtherTextColor: font # whiteishPurple scrollbarDefaultColor: accent
portraitContactBadgeColor: 0x863655 textfieldHintColor: mainTextColor
portraitContactBadgeTextColor: 0xFBF4F7 toolbarIconColor: settings # whiteishPurple
portraitProfileBadgeColor: 0x863655 topbarColor: header # darkGreyPurple
portraitProfileBadgeTextColor: 0xFBF4F7 light:
portraitBackgroundColor: peerBubble colors:
portraitOfflineBorderColor: 0x863655 background: 0xFFFDFD
portraitOnlineBorderColor: font header: 0xD8C7E1
scrollbarDefaultColor: accent userBubble: 0xD8C7E1
textfieldHintColor: mainTextColor peerBubble: 0xFFEBEE
toolbarIconColor: settings # whiteishPurple font: 0x281831
topbarColor: header # darkGreyPurple settings: 0x281831
sendHintTextColor: peerBubble accent: 0x8E64A5
chatReactionIconColor: reaction theme:
chatImage: Vampire.png backgroundMainColor: background # whitePurple
chatImageColor: peerBubble backgroundPaneColor: background # whitePurple
snackbarBackgroundColor: accent defaultButtonColor: accent # hotPink
snackbarTextColor: 0xFBF4F7 dropShadowColor: userBubble
messageSelectionColor: 0x863655 mainTextColor: settings
textfieldSelectionColor: 0x863655 messageFromMeBackgroundColor: userBubble # brightPurple
menuBackgroundColor: 0x863655 messageFromMeTextColor: font # mainTextColor
light: messageFromOtherBackgroundColor: peerBubble # purple
colors: messageFromOtherTextColor: font # darkPurple
background: 0xFBF4F7 portraitContactBadgeColor: accent
header: 0xC86B89 scrollbarDefaultColor: accent
userBubble: 0xDA94A9 textfieldBackgroundColor: peerBubble
peerBubble: 0xF7EAF0 textfieldBorderColor: userBubble
font: 0x27141B textfieldHintColor: font
settings: 0xFBF4F7 toolbarIconColor: settings # darkPurple
accent: 0x502033 topbarColor: header # softPurple
reaction: 0xDA94A9
theme:
backgroundMainColor: background # whitePurple
backgroundPaneColor: background # whitePurple
defaultButtonColor: accent # hotPink
dropShadowColor: userBubble
mainTextColor: font
messageFromMeBackgroundColor: userBubble # brightPurple
messageFromMeTextColor: font # mainTextColor
messageFromOtherBackgroundColor: peerBubble # purple
messageFromOtherTextColor: font # darkPurple
portraitContactBadgeColor: accent
portraitContactBadgeTextColor: 0xFBF4F7
portraitProfileBadgeColor: accent
portraitProfileBadgeTextColor: 0xFBF4F7
portraitOfflineBorderColor: 0x775F84
portraitOnlineBorderColor: font
portraitBackgroundColor: background
scrollbarDefaultColor: accent
textfieldBackgroundColor: peerBubble
textfieldBorderColor: userBubble
textfieldHintColor: font
toolbarIconColor: settings # darkPurple
topbarColor: header # softPurple
sendHintTextColor: userBubble
chatReactionIconColor: reaction
chatImage: Vampire.png
chatImageColor: 0xE9BFCD
snackbarBackgroundColor: accent
snackbarTextColor: background
messageSelectionColor: header
textfieldSelectionColor: header
menuBackgroundColor: header

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

View File

@ -1,86 +1,55 @@
--- ---
themes: themes:
name: witch name: witch
dark: dark:
colors: colors:
background: 0x111b11 background: 0x0E1E0E
header: 0x0E1E0E header: 0x0E1E0E
userBubble: 0x3B5132 userBubble: 0x1B5E20
peerBubble: 0x152716 peerBubble: 0x003300
font: 0xF1F3EC font: 0xFFFFFF
settings: 0xE3ECD3 settings: 0xFDFFFD
accent: 0x8E64A5 accent: 0xD20070
reaction: 0x97AF6E theme:
theme: backgroundHilightElementColor: peerBubble
backgroundHilightElementColor: peerBubble backgroundMainColor: background # darkGreyPurple
backgroundMainColor: background # darkGreyPurple backgroundPaneColor: header # darkGreyPurple
backgroundPaneColor: header # darkGreyPurple defaultButtonColor: accent # hotPink
defaultButtonColor: accent # hotPink mainTextColor: font # whiteishPurple
mainTextColor: font # whiteishPurple messageFromMeBackgroundColor: userBubble # mauvePurple
messageFromMeBackgroundColor: userBubble # mauvePurple messageFromMeTextColor: font # whiteishPurple
messageFromMeTextColor: font # whiteishPurple messageFromOtherBackgroundColor: peerBubble # deepPurple
messageFromOtherBackgroundColor: peerBubble # deepPurple messageFromOtherTextColor: font # whiteishPurple
messageFromOtherTextColor: font # whiteishPurple scrollbarDefaultColor: accent
portraitContactBadgeColor: accent textfieldBackgroundColor: peerBubble
portraitContactBadgeTextColor: 0xF1F3EC textfieldBorderColor: userBubble
portraitProfileBadgeColor: accent textfieldHintColor: mainTextColor
portraitProfileBadgeTextColor: 0xF1F3EC toolbarIconColor: settings # whiteishPurple
portraitOfflineBorderColor: 0x355934 topbarColor: header # darkGreyPurple
portraitOnlineBorderColor: font light:
portraitBackgroundColor: peerBubble colors:
scrollbarDefaultColor: accent background: 0xFDFFFD
textfieldBackgroundColor: peerBubble header: 0x80E27E
textfieldBorderColor: userBubble userBubble: 0x80E27E
textfieldHintColor: mainTextColor peerBubble: 0xE8F5E9
toolbarIconColor: settings # whiteishPurple font: 0x0E1E0E
topbarColor: header # darkGreyPurple settings: 0x0E1E0E
chatReactionIconColor: reaction accent: 0xD20070
chatImage: Witch.png theme:
chatImageColor: 0x1E321D backgroundHilightElementColor: peerBubble
snackbarBackgroundColor: accent backgroundMainColor: background # whitePurple
snackbarTextColor: 0xF1F3EC backgroundPaneColor: background # whitePurple
messageSelectionColor: accent defaultButtonColor: accent # hotPink
textfieldSelectionColor: accent mainTextColor: settings
menuBackgroundColor: accent messageFromMeBackgroundColor: userBubble # brightPurple
light: messageFromMeTextColor: font # mainTextColor
colors: messageFromOtherBackgroundColor: peerBubble # purple
background: 0xF1F3EC messageFromOtherTextColor: font # darkPurple
header: 0x97af6e portraitContactBadgeColor: accent
userBubble: 0x97AF6E scrollbarDefaultColor: accent
peerBubble: 0xE3ECD3 textfieldBackgroundColor: peerBubble
font: 0x111b11 textfieldBorderColor: userBubble
settings: 0x0E1E0E textfieldHintColor: font
accent: 0x8E64A5 toolbarIconColor: settings # darkPurple
reaction: 0x97AF6E topbarColor: header # softPurple
theme:
backgroundHilightElementColor: peerBubble
backgroundMainColor: background # whitePurple
backgroundPaneColor: background # whitePurple
defaultButtonColor: accent # hotPink
mainTextColor: settings
messageFromMeBackgroundColor: userBubble # brightPurple
messageFromMeTextColor: font # mainTextColor
messageFromOtherBackgroundColor: peerBubble # purple
messageFromOtherTextColor: font # darkPurple
portraitContactBadgeColor: accent
portraitContactBadgeTextColor: 0xF1F3EC
portraitProfileBadgeColor: accent
portraitProfileBadgeTextColor: 0xF1F3EC
portraitOfflineBorderColor: userBubble
portraitOnlineBorderColor: font
portraitBackgroundColor: background
scrollbarDefaultColor: accent
textfieldBackgroundColor: background
textfieldBorderColor: userBubble
textfieldHintColor: font
toolbarIconColor: settings # darkPurple
topbarColor: header # softPurple
chatReactionIconColor: reaction
chatImage: Witch.png
chatImageColor: 0xD0DDBA
snackbarBackgroundColor: accent
snackbarTextColor: background
messageSelectionColor: accent
textfieldSelectionColor: accent
menuBackgroundColor: accent

View File

@ -3,6 +3,6 @@
VERSION=`cat LIBCWTCH-GO.version` VERSION=`cat LIBCWTCH-GO.version`
echo $VERSION echo $VERSION
curl --fail https://build.openprivacy.ca/files/libCwtch-autobindings-$VERSION/android/cwtch.aar --output android/app/cwtch/cwtch.aar curl --fail https://build.openprivacy.ca/files/libCwtch-autobindings-$VERSION/android/cwtch.aar --output android/cwtch/cwtch.aar
# FIXME...at some point we need to support different linux architectures...for now rely on existing expectations and rename x64 lib # FIXME...at some point we need to support different linux architectures...for now rely on existing expectations and rename x64 lib
curl --fail https://build.openprivacy.ca/files/libCwtch-autobindings-$VERSION/linux/libCwtch.x64.so --output linux/libCwtch.so curl --fail https://build.openprivacy.ca/files/libCwtch-autobindings-$VERSION/linux/libCwtch.x64.so --output linux/libCwtch.so

View File

@ -1,8 +1,17 @@
import 'package:cwtch/main.dart';
import 'package:cwtch/widgets/messagebubble.dart';
import 'package:cwtch/widgets/profilerow.dart';
import 'package:cwtch/widgets/quotedmessage.dart'; import 'package:cwtch/widgets/quotedmessage.dart';
import 'package:cwtch/widgets/tor_icon.dart';
import 'package:cwtch/views/profilemgrview.dart';
import 'package:flutter_gherkin/flutter_gherkin.dart'; import 'package:flutter_gherkin/flutter_gherkin.dart';
import 'package:flutter_gherkin/src/flutter/parameters/existence_parameter.dart';
import 'package:flutter_gherkin/src/flutter/parameters/swipe_direction_parameter.dart';
import 'package:gherkin/gherkin.dart'; import 'package:gherkin/gherkin.dart';
import 'package:flutter/material.dart';
import 'overrides.dart';
StepDefinitionGeneric ExpectReply() { StepDefinitionGeneric ExpectReply() {
return given3<String, String, int, FlutterWorld>( return given3<String, String, int, FlutterWorld>(

View File

@ -1,7 +1,10 @@
import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_driver/flutter_driver.dart';
import 'package:flutter_gherkin/flutter_gherkin.dart'; import 'package:flutter_gherkin/flutter_gherkin.dart';
import 'package:gherkin/gherkin.dart'; import 'package:gherkin/gherkin.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
enum SwitchState { checked, unchecked } enum SwitchState { checked, unchecked }
@ -14,7 +17,6 @@ class SwitchStateParameter extends CustomParameter<SwitchState> {
case "unchecked": case "unchecked":
return SwitchState.unchecked; return SwitchState.unchecked;
} }
return null;
}); });
} }

View File

@ -1,5 +1,6 @@
import 'package:cwtch/themes/opaque.dart'; import 'package:cwtch/themes/opaque.dart';
import 'package:cwtch/third_party/linkify/linkify.dart'; import 'package:cwtch/third_party/linkify/linkify.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
@ -37,7 +38,7 @@ void modalOpenLink(BuildContext ctx, LinkableElement link) {
final snackBar = SnackBar( final snackBar = SnackBar(
content: Text( content: Text(
AppLocalizations.of(bcontext)!.copiedToClipboardNotification, AppLocalizations.of(bcontext)!.copiedToClipboardNotification,
style: Provider.of<Settings>(bcontext, listen: false).scaleFonts(defaultTextButtonStyle), style: Provider.of<Settings>(bcontext).scaleFonts(defaultTextButtonStyle),
), ),
); );

View File

@ -11,10 +11,8 @@ abstract class Cwtch {
// ignore: non_constant_identifier_names // ignore: non_constant_identifier_names
Future<void> Start(); Future<void> Start();
// ignore: non_constant_identifier_names
Future<String> getCwtchDir(); Future<void> ReconnectCwtchForeground();
String getAssetsDir();
// ignore: non_constant_identifier_names // ignore: non_constant_identifier_names
void CreateProfile(String nick, String pass, bool autostart); void CreateProfile(String nick, String pass, bool autostart);

View File

@ -3,10 +3,15 @@ import 'package:cwtch/cwtch/cwtch.dart';
import 'package:cwtch/main.dart'; import 'package:cwtch/main.dart';
import 'package:cwtch/models/appstate.dart'; import 'package:cwtch/models/appstate.dart';
import 'package:cwtch/models/contact.dart'; import 'package:cwtch/models/contact.dart';
import 'package:cwtch/models/message.dart';
import 'package:cwtch/models/profilelist.dart'; import 'package:cwtch/models/profilelist.dart';
import 'package:cwtch/models/profileservers.dart';
import 'package:cwtch/models/remoteserver.dart'; import 'package:cwtch/models/remoteserver.dart';
import 'package:cwtch/models/servers.dart'; import 'package:cwtch/models/servers.dart';
import 'package:cwtch/notification_manager.dart'; import 'package:cwtch/notification_manager.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:provider/provider.dart';
import 'package:cwtch/torstatus.dart'; import 'package:cwtch/torstatus.dart';
@ -58,14 +63,7 @@ class CwtchNotifier {
// EnvironmentConfig.debugLog("NewEvent $type $data"); // EnvironmentConfig.debugLog("NewEvent $type $data");
switch (type) { switch (type) {
case "CwtchStarted": case "CwtchStarted":
if (data["Reload"] == "true" && profileCN.num > 0) { flwtchState.cwtch.LoadProfiles(DefaultPassword);
// don't reload...
// unless we have loaded no profiles...then there isnt a risk and this
// might be a first time (e.g. new apk, existing service)
} else {
flwtchState.cwtch.LoadProfiles(DefaultPassword);
}
appState.SetCwtchInit(); appState.SetCwtchInit();
break; break;
case "CwtchStartError": case "CwtchStartError":
@ -195,9 +193,21 @@ class CwtchNotifier {
var senderImage = data['picture']; var senderImage = data['picture'];
var isAuto = data['Auto'] == "true"; var isAuto = data['Auto'] == "true";
String contenthash = data['ContentHash']; String contenthash = data['ContentHash'];
var selectedProfile = appState.selectedProfile == data["ProfileOnion"]; var selectedProfile = appState.selectedProfile == data["ProfileOnion"];
var selectedConversation = selectedProfile && appState.selectedConversation == identifier; var selectedConversation = selectedProfile && appState.selectedConversation == identifier;
var notification = data["notification"];
if (selectedConversation && seenMessageCallback != null) {
seenMessageCallback!(data["ProfileOnion"]!, identifier, DateTime.now().toUtc());
}
if (notification == "SimpleEvent") {
notificationManager.notify(notificationSimple ?? "New Message", "", 0);
} else if (notification == "ContactInfo") {
var contact = profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier);
notificationManager.notify((notificationConversationInfo ?? "New Message from %1").replaceFirst("%1", (contact?.nickname ?? senderHandle.toString())), data["ProfileOnion"], identifier);
}
profileCN.getProfile(data["ProfileOnion"])?.newMessage( profileCN.getProfile(data["ProfileOnion"])?.newMessage(
identifier, identifier,
messageID, messageID,
@ -210,19 +220,6 @@ class CwtchNotifier {
selectedProfile, selectedProfile,
selectedConversation, selectedConversation,
); );
// Now perform the notification logic...
var notification = data["notification"];
if (selectedConversation && seenMessageCallback != null) {
seenMessageCallback!(data["ProfileOnion"]!, identifier, DateTime.now().toUtc());
}
if (notification == "SimpleEvent") {
notificationManager.notify(notificationSimple ?? "New Message", "", 0);
} else if (notification == "ContactInfo") {
var contact = profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier);
notificationManager.notify((notificationConversationInfo ?? "New Message from %1").replaceFirst("%1", (contact?.nickname ?? senderHandle.toString())), data["ProfileOnion"], identifier);
}
appState.notifyProfileUnread(); appState.notifyProfileUnread();
break; break;
case "PeerAcknowledgement": case "PeerAcknowledgement":
@ -257,7 +254,7 @@ class CwtchNotifier {
var notification = data["notification"]; var notification = data["notification"];
// Only bother to do anything if we know about the group and the provided index is greater than our current total... // Only bother to do anything if we know about the group and the provided index is greater than our current total...
if (idx >= currentTotal) { if (currentTotal != null && idx >= currentTotal) {
// TODO: There are 2 timestamps associated with a new group message - time sent and time received. // TODO: There are 2 timestamps associated with a new group message - time sent and time received.
// Sent refers to the time a profile alleges they sent a message // Sent refers to the time a profile alleges they sent a message
// Received refers to the time we actually saw the message from the server // Received refers to the time we actually saw the message from the server
@ -305,7 +302,6 @@ class CwtchNotifier {
break; break;
case "UpdateGlobalSettings": case "UpdateGlobalSettings":
settings.handleUpdate(jsonDecode(data["Data"])); settings.handleUpdate(jsonDecode(data["Data"]));
appState.settingsLoaded = true;
break; break;
case "UpdatedProfileAttribute": case "UpdatedProfileAttribute":
if (data["Key"] == "public.profile.name") { if (data["Key"] == "public.profile.name") {
@ -350,7 +346,7 @@ class CwtchNotifier {
associatedGroups.forEach((identifier) { associatedGroups.forEach((identifier) {
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(int.parse(identifier.toString()))!.antispamTickets = count; profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(int.parse(identifier.toString()))!.antispamTickets = count;
}); });
EnvironmentConfig.debugLog("update server token count for $associatedGroups, $count"); EnvironmentConfig.debugLog("update server token count for ${associatedGroups}, $count");
} catch (e) { } catch (e) {
// No tokens in data... // No tokens in data...
} }

View File

@ -3,6 +3,7 @@ import 'dart:convert';
import 'dart:ffi'; import 'dart:ffi';
import 'dart:io'; import 'dart:io';
import 'dart:isolate'; import 'dart:isolate';
import 'dart:io' show Platform;
import 'package:cwtch/cwtch/cwtchNotifier.dart'; import 'package:cwtch/cwtch/cwtchNotifier.dart';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
@ -12,6 +13,7 @@ import 'package:cwtch/cwtch/cwtch.dart';
import '../config.dart'; import '../config.dart';
import "package:path/path.dart" show dirname, join; import "package:path/path.dart" show dirname, join;
import 'dart:io' show Platform;
///////////////////// /////////////////////
/// Cwtch API /// /// Cwtch API ///
@ -132,8 +134,6 @@ class CwtchFfi implements Cwtch {
late Isolate cwtchIsolate; late Isolate cwtchIsolate;
ReceivePort _receivePort = ReceivePort(); ReceivePort _receivePort = ReceivePort();
bool _isL10nInit = false; bool _isL10nInit = false;
String _assetsDir = path.join(Directory.current.path, "data", "flutter_assets");
String _cwtchDir = "";
static String getLibraryPath() { static String getLibraryPath() {
if (Platform.isWindows) { if (Platform.isWindows) {
@ -168,12 +168,13 @@ class CwtchFfi implements Cwtch {
String home = ""; String home = "";
String bundledTor = ""; String bundledTor = "";
Map<String, String> envVars = Platform.environment; Map<String, String> envVars = Platform.environment;
String cwtchDir = "";
if (Platform.isLinux) { if (Platform.isLinux) {
home = envVars['HOME'] ?? ""; home = envVars['HOME'] ?? "";
if (EnvironmentConfig.TEST_MODE) { if (EnvironmentConfig.TEST_MODE) {
_cwtchDir = envVars['CWTCH_HOME']!; cwtchDir = envVars['CWTCH_HOME']!;
} else { } else {
_cwtchDir = envVars['CWTCH_HOME'] ?? path.join(envVars['HOME']!, ".cwtch"); cwtchDir = envVars['CWTCH_HOME'] ?? path.join(envVars['HOME']!, ".cwtch");
} }
if (await File("linux/Tor/tor").exists()) { if (await File("linux/Tor/tor").exists()) {
@ -182,30 +183,24 @@ class CwtchFfi implements Cwtch {
bundledTor = "lib/Tor/tor"; bundledTor = "lib/Tor/tor";
} else if (await File(path.join(home, ".local/lib/cwtch/Tor/tor")).exists()) { } else if (await File(path.join(home, ".local/lib/cwtch/Tor/tor")).exists()) {
bundledTor = path.join(home, ".local/lib/cwtch/Tor/tor"); bundledTor = path.join(home, ".local/lib/cwtch/Tor/tor");
_assetsDir = path.join(home, ".local", "share", "cwtch", "data", "flutter_assets");
} else if (await File("/usr/lib/cwtch/Tor/tor").exists()) { } else if (await File("/usr/lib/cwtch/Tor/tor").exists()) {
bundledTor = "/usr/lib/cwtch/Tor/tor"; bundledTor = "/usr/lib/cwtch/Tor/tor";
_assetsDir = path.join("usr", "share", "cwtch", "data", "flutter_assets");
} else { } else {
bundledTor = "tor"; bundledTor = "tor";
} }
} else if (Platform.isWindows) { } else if (Platform.isWindows) {
_cwtchDir = envVars['CWTCH_DIR'] ?? path.join(envVars['UserProfile']!, ".cwtch"); cwtchDir = envVars['CWTCH_DIR'] ?? path.join(envVars['UserProfile']!, ".cwtch");
String currentTor = path.join(Directory.current.absolute.path, "Tor\\Tor\\tor.exe"); String currentTor = path.join(Directory.current.absolute.path, "Tor\\Tor\\tor.exe");
if (await File(currentTor).exists()) { if (await File(currentTor).exists()) {
bundledTor = currentTor; bundledTor = currentTor;
_assetsDir = path.join(Directory.current.absolute.path, "data", "flutter_assets");
} else { } else {
String exeDir = path.dirname(Platform.resolvedExecutable); String exeDir = path.dirname(Platform.resolvedExecutable);
bundledTor = path.join(exeDir, "Tor\\Tor\\tor.exe"); bundledTor = path.join(exeDir, "Tor\\Tor\\tor.exe");
_assetsDir = path.join(exeDir, "data", "flutter_assets");
} }
} else if (Platform.isMacOS) { } else if (Platform.isMacOS) {
_cwtchDir = envVars['CWTCH_HOME'] ?? path.join(envVars['HOME']!, "Library/Application Support/Cwtch"); cwtchDir = envVars['CWTCH_HOME'] ?? path.join(envVars['HOME']!, "Library/Application Support/Cwtch");
_assetsDir = "/Applications/Cwtch.app/Contents/Frameworks/App.framework/Versions/Current/Resources/flutter_assets/";
if (await File("Cwtch.app/Contents/MacOS/Tor/tor").exists()) { if (await File("Cwtch.app/Contents/MacOS/Tor/tor").exists()) {
bundledTor = "Cwtch.app/Contents/MacOS/Tor/tor"; bundledTor = "Cwtch.app/Contents/MacOS/Tor/tor";
_assetsDir = "Cwtch.app/Contents/Frameworks/App.framework/Versions/Current/Resources/flutter_assets/";
} else if (await File("/Applications/Cwtch.app/Contents/MacOS/Tor/tor").exists()) { } else if (await File("/Applications/Cwtch.app/Contents/MacOS/Tor/tor").exists()) {
bundledTor = "/Applications/Cwtch.app/Contents/MacOS/Tor/tor"; bundledTor = "/Applications/Cwtch.app/Contents/MacOS/Tor/tor";
} else if (await File("/Volumes/Cwtch/Cwtch.app/Contents/MacOS/Tor/tor").exists()) { } else if (await File("/Volumes/Cwtch/Cwtch.app/Contents/MacOS/Tor/tor").exists()) {
@ -230,27 +225,27 @@ class CwtchFfi implements Cwtch {
// if macOs and release build and no profile and is dev profile // if macOs and release build and no profile and is dev profile
// copy dev profile to release profile // copy dev profile to release profile
if (Platform.isMacOS && EnvironmentConfig.BUILD_VER != dev_version) { if (Platform.isMacOS && EnvironmentConfig.BUILD_VER != dev_version) {
var devProfileExists = await Directory(path.join(_cwtchDir, "dev", "profiles")).exists(); var devProfileExists = await Directory(path.join(cwtchDir, "dev", "profiles")).exists();
var releaseProfileExists = await Directory(path.join(_cwtchDir, "profiles")).exists(); var releaseProfileExists = await Directory(path.join(cwtchDir, "profiles")).exists();
if (devProfileExists && !releaseProfileExists) { if (devProfileExists && !releaseProfileExists) {
print("MacOS one time dev -> release profile migration..."); print("MacOS one time dev -> release profile migration...");
await Process.run("cp", ["-r", "-p", path.join(_cwtchDir, "dev", "profiles"), _cwtchDir]); await Process.run("cp", ["-r", "-p", path.join(cwtchDir, "dev", "profiles"), cwtchDir]);
await Process.run("cp", ["-r", "-p", path.join(_cwtchDir, "dev", "SALT"), _cwtchDir]); await Process.run("cp", ["-r", "-p", path.join(cwtchDir, "dev", "SALT"), cwtchDir]);
await Process.run("cp", ["-r", "-p", path.join(_cwtchDir, "dev", "ui.globals"), _cwtchDir]); await Process.run("cp", ["-r", "-p", path.join(cwtchDir, "dev", "ui.globals"), cwtchDir]);
} }
} }
if (EnvironmentConfig.BUILD_VER == dev_version) { if (EnvironmentConfig.BUILD_VER == dev_version) {
_cwtchDir = path.join(_cwtchDir, "dev"); cwtchDir = path.join(cwtchDir, "dev");
} }
print("StartCwtch( cwtchdir: $_cwtchDir, torPath: $bundledTor )"); print("StartCwtch( cwtchdir: $cwtchDir, torPath: $bundledTor )");
var startCwtchC = library.lookup<NativeFunction<start_cwtch_function>>("c_StartCwtch"); var startCwtchC = library.lookup<NativeFunction<start_cwtch_function>>("c_StartCwtch");
// ignore: non_constant_identifier_names // ignore: non_constant_identifier_names
final StartCwtch = startCwtchC.asFunction<StartCwtchFn>(); final StartCwtch = startCwtchC.asFunction<StartCwtchFn>();
final utf8CwtchDir = _cwtchDir.toNativeUtf8(); final utf8CwtchDir = cwtchDir.toNativeUtf8();
StartCwtch(utf8CwtchDir, utf8CwtchDir.length, bundledTor.toNativeUtf8(), bundledTor.length); StartCwtch(utf8CwtchDir, utf8CwtchDir.length, bundledTor.toNativeUtf8(), bundledTor.length);
malloc.free(utf8CwtchDir); malloc.free(utf8CwtchDir);
@ -262,12 +257,12 @@ class CwtchFfi implements Cwtch {
}); });
} }
String getAssetsDir() { // ignore: non_constant_identifier_names
return _assetsDir; Future<void> ReconnectCwtchForeground() async {
} var reconnectCwtch = library.lookup<NativeFunction<Void Function()>>("c_ReconnectCwtchForeground");
// ignore: non_constant_identifier_names
Future<String> getCwtchDir() async { final ReconnectCwtchForeground = reconnectCwtch.asFunction<void Function()>();
return _cwtchDir; ReconnectCwtchForeground();
} }
// Called on object being disposed to (presumably on app close) to close the isolate that's listening to libcwtch-go events // Called on object being disposed to (presumably on app close) to close the isolate that's listening to libcwtch-go events

View File

@ -30,7 +30,6 @@ class CwtchGomobile implements Cwtch {
late Future<dynamic> androidLibraryDir; late Future<dynamic> androidLibraryDir;
late Future<dynamic> androidHomeDirectory; late Future<dynamic> androidHomeDirectory;
String androidHomeDirectoryStr = ""; String androidHomeDirectoryStr = "";
String _cwtchDir = "";
late CwtchNotifier cwtchNotifier; late CwtchNotifier cwtchNotifier;
bool _isL10nInit = false; bool _isL10nInit = false;
@ -63,27 +62,23 @@ class CwtchGomobile implements Cwtch {
appbusEventChannel.setMethodCallHandler(this._handleAppbusEvent); appbusEventChannel.setMethodCallHandler(this._handleAppbusEvent);
} }
String getAssetsDir() {
// TODO
return "";
}
// Requires Start() to have been run to initialize
Future<String> getCwtchDir() async {
return _cwtchDir;
}
// ignore: non_constant_identifier_names // ignore: non_constant_identifier_names
Future<void> Start() async { Future<void> Start() async {
print("gomobile.dart: Start()..."); print("gomobile.dart: Start()...");
androidHomeDirectoryStr = (await androidHomeDirectory).path; androidHomeDirectoryStr = (await androidHomeDirectory).path;
_cwtchDir = path.join(androidHomeDirectoryStr, ".cwtch"); var cwtchDir = path.join(androidHomeDirectoryStr, ".cwtch");
if (EnvironmentConfig.BUILD_VER == dev_version) { if (EnvironmentConfig.BUILD_VER == dev_version) {
_cwtchDir = path.join(_cwtchDir, "dev"); cwtchDir = path.join(cwtchDir, "dev");
} }
String torPath = path.join(await androidLibraryDir, "libtor.so"); String torPath = path.join(await androidLibraryDir, "libtor.so");
print("gomobile.dart: Start invokeMethod Start($_cwtchDir, $torPath)..."); print("gomobile.dart: Start invokeMethod Start($cwtchDir, $torPath)...");
cwtchPlatform.invokeMethod("Start", {"appDir": _cwtchDir, "torPath": torPath}); cwtchPlatform.invokeMethod("Start", {"appDir": cwtchDir, "torPath": torPath});
}
@override
// ignore: non_constant_identifier_names
Future<void> ReconnectCwtchForeground() async {
cwtchPlatform.invokeMethod("ReconnectCwtchForeground", {});
} }
// Handle libcwtch-go events (received via kotlin) and dispatch to the cwtchNotifier // Handle libcwtch-go events (received via kotlin) and dispatch to the cwtchNotifier

View File

@ -648,20 +648,4 @@ class MaterialLocalizationLu extends MaterialLocalizations {
@override @override
// TODO: implement scanTextButtonLabel // TODO: implement scanTextButtonLabel
String get scanTextButtonLabel => throw UnimplementedError(); String get scanTextButtonLabel => throw UnimplementedError();
@override
// TODO: implement lookUpButtonLabel
String get lookUpButtonLabel => throw UnimplementedError();
@override
// TODO: implement menuDismissLabel
String get menuDismissLabel => throw UnimplementedError();
@override
// TODO: implement searchWebButtonLabel
String get searchWebButtonLabel => throw UnimplementedError();
@override
// TODO: implement shareButtonLabel
String get shareButtonLabel => throw UnimplementedError();
} }

View File

@ -1,16 +1,6 @@
{ {
"@@locale": "cy", "@@locale": "cy",
"@@last_modified": "2024-02-12T08:05:24+01:00", "@@last_modified": "2024-01-04T10:56:20+01:00",
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
"settingsImportThemeButton": "Import Theme",
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
"settingsImportThemeTitle": "Import Theme",
"settingsThemeErrorInvalid": "Error: Could not import $themeName, theme.yml missing, not a theme directory",
"settingThemeOverwriteQuestion": "Theme $themeName already exists, confirm overwrite?",
"settingThemeOverwriteConfirm": "Confirm",
"settingsThemeImagesDescription": "Enable display of images from themes",
"settingsThemeImages": "Theme Images",
"settingsGroupAbout": "About", "settingsGroupAbout": "About",
"localeUzbek": "Uzbek \/ Oʻzbekcha", "localeUzbek": "Uzbek \/ Oʻzbekcha",
"profileOfflineAtStart": "Appear Offline at Startup", "profileOfflineAtStart": "Appear Offline at Startup",

View File

@ -1,16 +1,6 @@
{ {
"@@locale": "da", "@@locale": "da",
"@@last_modified": "2024-02-12T08:05:24+01:00", "@@last_modified": "2024-01-04T10:56:20+01:00",
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
"settingsImportThemeButton": "Import Theme",
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
"settingsImportThemeTitle": "Import Theme",
"settingsThemeErrorInvalid": "Error: Could not import $themeName, theme.yml missing, not a theme directory",
"settingThemeOverwriteQuestion": "Theme $themeName already exists, confirm overwrite?",
"settingThemeOverwriteConfirm": "Confirm",
"settingsThemeImagesDescription": "Enable display of images from themes",
"settingsThemeImages": "Theme Images",
"settingsGroupAbout": "About", "settingsGroupAbout": "About",
"localeUzbek": "Uzbek \/ Oʻzbekcha", "localeUzbek": "Uzbek \/ Oʻzbekcha",
"profileOfflineAtStart": "Appear Offline at Startup", "profileOfflineAtStart": "Appear Offline at Startup",

View File

@ -1,40 +1,28 @@
{ {
"@@locale": "de", "@@locale": "de",
"@@last_modified": "2024-02-12T08:05:24+01:00", "@@last_modified": "2024-01-04T10:56:20+01:00",
"settingsExperimentsShowPerformanceTitle": "Leistungs-Overlay anzeigen", "settingsGroupAbout": "About",
"settingsExperimentsShowPerformanceDescription": "Zeigt ein Overlay-Diagramm der Renderzeit an.", "localeUzbek": "Uzbek \/ Oʻzbekcha",
"defaultScalingText": "Text in Standardgröße (Skalierungsfaktor:", "profileOfflineAtStart": "Appear Offline at Startup",
"now": "Now",
"xSecondsAgo": "$seconds seconds ago",
"xMinutesAgo": "$minutes minutes ago",
"xHoursAgo": "$hours hours ago",
"xDaysAgo": "$days days ago",
"profileAllowUnknownContacts": "Allow Unknown Contacts",
"profileBlockUnknownContacts": "Block Unknown Contacts",
"profileDisableProfile": "Disable Profile",
"profileEnableProfile": "Enable Profile",
"profileAppearOnline": "Appear Online",
"contactDisconnect": "Disconnect from Contact (if you do not have Appear Offline set this contact may still be able to reestablish a connection to you)",
"profileAppearOfflineDescription": "By default, when Cwtch profile is enabled it automatically attempts to connect to know contacts, and allows inbound connections. This settings disables those actions and allows you to choose, manually, which contacts to connect to.",
"profileAppearOffline": "Appear Offline",
"deleteServerConfirmBtn": "Server wirklich löschen", "deleteServerConfirmBtn": "Server wirklich löschen",
"cannotDeleteServerIfActiveGroups": "There are active groups associated with this Cwtch Server. Please delete them prior to deleting this Cwtch Server entry.",
"groupsOnThisServerLabel": "Gruppen, in denen ich bin, werden auf diesem Server gehostet", "groupsOnThisServerLabel": "Gruppen, in denen ich bin, werden auf diesem Server gehostet",
"profileEnabledDescription": "Starten oder Stoppen des Profils", "serverinfoNoGroupInfo": "There are no groups associated with this Cwtch Server.",
"defaultPreserveHistorySetting": "Konversationsverlauf bewahren", "preserveHistorySettingDescription": "By default, Cwtch will purge conversation history when Cwtch is shutdown. If this setting is enabled, Cwtch will preserve the conversation history of peer conversations.",
"preserveHistorySettingDescription": "Standardmäßig löscht Cwtch den Gesprächsverlauf, wenn Cwtch heruntergefahren wird. Wenn diese Einstellung aktiviert ist, bewahrt Cwtch den Gesprächsverlauf von Peer-Unterhaltungen auf.", "defaultPreserveHistorySetting": "Preserve Conversation History",
"serverinfoNoGroupInfo": "Es gibt keine Gruppen, die mit diesem Cwtch Server verbunden sind.",
"cannotDeleteServerIfActiveGroups": "Es gibt aktive Gruppen, die mit diesem Cwtch Server verbunden sind. Bitte lösche diese, bevor du diesen Cwtch-Server-Eintrag löschst.",
"profileAppearOnline": "Online erscheinen",
"profileAppearOffline": "Offline erscheinen",
"profileAppearOfflineDescription": "Standardmäßig wird bei aktiviertem Cwtch-Profil automatisch versucht, eine Verbindung zu bekannten Kontakten herzustellen und es werden eingehende Verbindungen zugelassen. Mit dieser Einstellung werden diese Aktionen deaktiviert und du kannst manuell auswählen, mit welchen Kontakten eine Verbindung hergestellt werden soll.",
"contactDisconnect": "Trenne die Verbindung mit dem Kontakt (wenn du die Funktion Offline erscheinen nicht aktiviert habst, kann der Kontakt trotzdem eine Verbindung zu dir herstellen)",
"profileEnableProfile": "Profil aktivieren",
"profileDisableProfile": "Profil deaktivieren",
"profileBlockUnknownContacts": "Unbekannte Kontakte blockieren",
"profileAllowUnknownContacts": "Unbekannte Kontakte zulassen",
"profileOfflineAtStart": "Beim Start offline erscheinen",
"xDaysAgo": "vor $days Tagen",
"xHoursAgo": "vor $hours Stunden",
"xMinutesAgo": "vor $minutes Minuten",
"xSecondsAgo": "vor $seconds Sekunden",
"now": "Jetzt",
"localeUzbek": "Usbekisch \/ Oʻzbekcha",
"settingsGroupAbout": "Über",
"settingsThemeImages": "Theme Bilder",
"settingsThemeImagesDescription": "Aktiviere die Anzeige von Bildern aus Themes",
"settingThemeOverwriteConfirm": "Bestätigen",
"settingThemeOverwriteQuestion": "Theme $themeName existiert bereits, Überschreiben bestätigen?",
"settingsThemeErrorInvalid": "Fehler: Konnte $themeName nicht importieren, theme.yml fehlt, kein Theme-Verzeichnis",
"settingsImportThemeTitle": "Theme importieren",
"settingsImportThemeDescription": "Wähle das Theme-Verzeichnis aus, das zur Verwendung in Cwtch importiert werden soll",
"settingsImportThemeButton": "Theme importieren",
"retryConnection": "Wiederholen", "retryConnection": "Wiederholen",
"retryConnectionTooltip": "Cwtch wiederholt die Versuche regelmäßig, aber du kannst Cwtch anweisen, es früher zu versuchen, indem du diese Taste drückst.", "retryConnectionTooltip": "Cwtch wiederholt die Versuche regelmäßig, aber du kannst Cwtch anweisen, es früher zu versuchen, indem du diese Taste drückst.",
"localeJa": "Japanisch \/ 日本語", "localeJa": "Japanisch \/ 日本語",
@ -42,6 +30,8 @@
"localeSv": "Schwedisch \/ Svenska", "localeSv": "Schwedisch \/ Svenska",
"localeSw": "Suaheli \/ Kiswahili", "localeSw": "Suaheli \/ Kiswahili",
"localeUk": "Ukrainisch \/ українською", "localeUk": "Ukrainisch \/ українською",
"profileEnabledDescription": "Starten oder Stoppen des Profils",
"defaultScalingText": "Text in Standardgröße (Skalierungsfaktor:",
"blodeuweddExperimentEnable": "Blodeuwedd Assistent", "blodeuweddExperimentEnable": "Blodeuwedd Assistent",
"blodeuweddDescription": "Der Blodeuwedd-Assistent erweitert Cwtch um neue Funktionen wie die Zusammenfassung von Chat-Transkripten und die Übersetzung von Nachrichten über ein lokal gehostetes Sprachmodell.", "blodeuweddDescription": "Der Blodeuwedd-Assistent erweitert Cwtch um neue Funktionen wie die Zusammenfassung von Chat-Transkripten und die Übersetzung von Nachrichten über ein lokal gehostetes Sprachmodell.",
"blodeuweddNotSupported": "Diese Version von Cwtch wurde ohne Unterstützung für den Blodeuwedd-Assistenten kompiliert.", "blodeuweddNotSupported": "Diese Version von Cwtch wurde ohne Unterstützung für den Blodeuwedd-Assistenten kompiliert.",

View File

@ -1,16 +1,6 @@
{ {
"@@locale": "el", "@@locale": "el",
"@@last_modified": "2024-02-12T08:05:24+01:00", "@@last_modified": "2024-01-04T10:56:20+01:00",
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
"settingsImportThemeButton": "Import Theme",
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
"settingsImportThemeTitle": "Import Theme",
"settingsThemeErrorInvalid": "Error: Could not import $themeName, theme.yml missing, not a theme directory",
"settingThemeOverwriteQuestion": "Theme $themeName already exists, confirm overwrite?",
"settingThemeOverwriteConfirm": "Confirm",
"settingsThemeImagesDescription": "Enable display of images from themes",
"settingsThemeImages": "Theme Images",
"settingsGroupAbout": "About", "settingsGroupAbout": "About",
"localeUzbek": "Uzbek \/ Oʻzbekcha", "localeUzbek": "Uzbek \/ Oʻzbekcha",
"profileOfflineAtStart": "Appear Offline at Startup", "profileOfflineAtStart": "Appear Offline at Startup",

View File

@ -1,16 +1,6 @@
{ {
"@@locale": "en", "@@locale": "en",
"@@last_modified": "2024-02-12T08:05:24+01:00", "@@last_modified": "2024-01-04T10:56:20+01:00",
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
"settingThemeOverwriteConfirm": "Confirm",
"settingThemeOverwriteQuestion": "Theme $themeName already exists, confirm overwrite?",
"settingsThemeErrorInvalid": "Error: Could not import $themeName, theme.yml missing, not a theme directory",
"settingsImportThemeTitle": "Import Theme",
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
"settingsImportThemeButton": "Import Theme",
"settingsThemeImagesDescription": "Enable display of images from themes",
"settingsThemeImages": "Theme Images",
"settingsGroupAbout": "About", "settingsGroupAbout": "About",
"localeUzbek": "Uzbek \/ Oʻzbekcha", "localeUzbek": "Uzbek \/ Oʻzbekcha",
"profileOfflineAtStart": "Appear Offline at Startup", "profileOfflineAtStart": "Appear Offline at Startup",

View File

@ -1,16 +1,6 @@
{ {
"@@locale": "es", "@@locale": "es",
"@@last_modified": "2024-02-12T08:05:24+01:00", "@@last_modified": "2024-01-04T10:56:20+01:00",
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
"settingsImportThemeButton": "Import Theme",
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
"settingsImportThemeTitle": "Import Theme",
"settingsThemeErrorInvalid": "Error: Could not import $themeName, theme.yml missing, not a theme directory",
"settingThemeOverwriteQuestion": "Theme $themeName already exists, confirm overwrite?",
"settingThemeOverwriteConfirm": "Confirm",
"settingsThemeImagesDescription": "Enable display of images from themes",
"settingsThemeImages": "Theme Images",
"settingsGroupAbout": "About", "settingsGroupAbout": "About",
"deleteServerConfirmBtn": "¿Realmente desea borrar el servidor?", "deleteServerConfirmBtn": "¿Realmente desea borrar el servidor?",
"defaultScalingText": "Factor de escala del texto", "defaultScalingText": "Factor de escala del texto",

View File

@ -1,16 +1,6 @@
{ {
"@@locale": "fr", "@@locale": "fr",
"@@last_modified": "2024-02-12T08:05:24+01:00", "@@last_modified": "2024-01-04T10:56:20+01:00",
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
"settingsImportThemeButton": "Import Theme",
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
"settingsImportThemeTitle": "Import Theme",
"settingsThemeErrorInvalid": "Error: Could not import $themeName, theme.yml missing, not a theme directory",
"settingThemeOverwriteQuestion": "Theme $themeName already exists, confirm overwrite?",
"settingThemeOverwriteConfirm": "Confirm",
"settingsThemeImagesDescription": "Enable display of images from themes",
"settingsThemeImages": "Theme Images",
"settingsGroupAbout": "About", "settingsGroupAbout": "About",
"localeUzbek": "Uzbek \/ Oʻzbekcha", "localeUzbek": "Uzbek \/ Oʻzbekcha",
"profileOfflineAtStart": "Appear Offline at Startup", "profileOfflineAtStart": "Appear Offline at Startup",

View File

@ -1,16 +1,6 @@
{ {
"@@locale": "it", "@@locale": "it",
"@@last_modified": "2024-02-12T08:05:24+01:00", "@@last_modified": "2024-01-04T10:56:20+01:00",
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
"settingsImportThemeButton": "Import Theme",
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
"settingsImportThemeTitle": "Import Theme",
"settingsThemeErrorInvalid": "Error: Could not import $themeName, theme.yml missing, not a theme directory",
"settingThemeOverwriteQuestion": "Theme $themeName already exists, confirm overwrite?",
"settingThemeOverwriteConfirm": "Confirm",
"settingsThemeImagesDescription": "Enable display of images from themes",
"settingsThemeImages": "Theme Images",
"settingsGroupAbout": "About", "settingsGroupAbout": "About",
"localeUzbek": "Uzbek \/ Oʻzbekcha", "localeUzbek": "Uzbek \/ Oʻzbekcha",
"profileOfflineAtStart": "Appear Offline at Startup", "profileOfflineAtStart": "Appear Offline at Startup",

View File

@ -1,16 +1,6 @@
{ {
"@@locale": "ja", "@@locale": "ja",
"@@last_modified": "2024-02-12T08:05:24+01:00", "@@last_modified": "2024-01-04T10:56:20+01:00",
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
"settingsImportThemeButton": "Import Theme",
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
"settingsImportThemeTitle": "Import Theme",
"settingsThemeErrorInvalid": "Error: Could not import $themeName, theme.yml missing, not a theme directory",
"settingThemeOverwriteQuestion": "Theme $themeName already exists, confirm overwrite?",
"settingThemeOverwriteConfirm": "Confirm",
"settingsThemeImagesDescription": "Enable display of images from themes",
"settingsThemeImages": "Theme Images",
"settingsGroupAbout": "About", "settingsGroupAbout": "About",
"localeUzbek": "Uzbek \/ Oʻzbekcha", "localeUzbek": "Uzbek \/ Oʻzbekcha",
"profileOfflineAtStart": "Appear Offline at Startup", "profileOfflineAtStart": "Appear Offline at Startup",

View File

@ -1,44 +1,6 @@
{ {
"@@locale": "ko", "@@locale": "ko",
"@@last_modified": "2024-02-12T08:05:24+01:00", "@@last_modified": "2024-01-04T10:56:20+01:00",
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
"sendAnInvitation": "초대를 보냈습니다: ",
"sendInvite": "연락처 또는 그룹 초대 보내기",
"pasteAddressToAddContact": "Paste a cwtch address, invitation or key bundle here to add a new conversation",
"invalidImportString": "잘못된 가져오기 문자열",
"settingsImportThemeButton": "Import Theme",
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
"settingsImportThemeTitle": "Import Theme",
"settingsThemeErrorInvalid": "Error: Could not import $themeName, theme.yml missing, not a theme directory",
"settingThemeOverwriteQuestion": "Theme $themeName already exists, confirm overwrite?",
"settingThemeOverwriteConfirm": "Confirm",
"resetTor": "초기화",
"torStatus": "Tor 상태",
"torVersion": "Tor 버전",
"passwordChangeError": "암호 변경 오류: 제공된 암호가 거부되었습니다.",
"enterProfilePassword": "프로필을 보려면 암호를 입력하세요.",
"todoPlaceholder": "할 일...",
"addNewItem": "목록에 새 항목 추가",
"addListItem": "새 목록 항목 추가",
"networkStatusConnecting": "네트워크 및 연락처에 연결 중...",
"networkStatusAttemptingTor": "Tor 네트워크에 연결을 시도 중",
"networkStatusDisconnected": "인터넷 연결 끊김, 연결 확인하세요",
"viewGroupMembershipTooltip": "그룹 구성원 보기",
"defaultScalingText": "글꼴 크기 조정",
"experimentsEnabled": "실험 사용",
"loadingTor": "tor 로딩 중...",
"builddate": "빌드 대상: %2",
"version": "버전: %1",
"versionTor": "버전 %1 및 tor %2",
"settingInterfaceZoom": "확대\/축소 수준",
"versionBuilddate": "버전: %1 빌드 대상: %2",
"error0ProfilesLoadedForPassword": "해당 비밀번호가 포함된 프로필이 0개 로드되었습니다.",
"deleteConfirmText": "삭제",
"unblockBtn": "연락처 차단 해제",
"savePeerHistoryDescription": "연락처와 연결된 기록을 삭제할지 여부를 결정합니다.",
"settingsThemeImagesDescription": "Enable display of images from themes",
"settingsThemeImages": "Theme Images",
"settingsGroupAbout": "About", "settingsGroupAbout": "About",
"localeUzbek": "Uzbek \/ Oʻzbekcha", "localeUzbek": "Uzbek \/ Oʻzbekcha",
"profileOfflineAtStart": "Appear Offline at Startup", "profileOfflineAtStart": "Appear Offline at Startup",
@ -152,6 +114,7 @@
"server": "서버", "server": "서버",
"peerName": "이름", "peerName": "이름",
"peerAddress": "주소", "peerAddress": "주소",
"builddate": "Built on: %2",
"deleteProfileConfirmBtn": "프로필 삭제 확인", "deleteProfileConfirmBtn": "프로필 삭제 확인",
"deleteConfirmLabel": "DELETE를 입력하여 확인", "deleteConfirmLabel": "DELETE를 입력하여 확인",
"deleteProfileBtn": "프로필 삭제", "deleteProfileBtn": "프로필 삭제",
@ -187,6 +150,7 @@
"localeSw": "Swahili \/ Kiswahili", "localeSw": "Swahili \/ Kiswahili",
"localeSv": "Swedish \/ Svenska", "localeSv": "Swedish \/ Svenska",
"fontScalingDescription": "Adjust the relative font scaling factor applied to text and widgets.", "fontScalingDescription": "Adjust the relative font scaling factor applied to text and widgets.",
"defaultScalingText": "Font Scaling",
"localeJa": "Japanese \/ 日本語", "localeJa": "Japanese \/ 日本語",
"retryConnectionTooltip": "Cwtch retries peers regularly, but you can tell Cwtch to try sooner by pushing this button.", "retryConnectionTooltip": "Cwtch retries peers regularly, but you can tell Cwtch to try sooner by pushing this button.",
"retryConnection": "Retry", "retryConnection": "Retry",
@ -410,6 +374,11 @@
"nickChangeSuccess": "Profile nickname changed successfully", "nickChangeSuccess": "Profile nickname changed successfully",
"addServerFirst": "You need to add a server before you can create a group", "addServerFirst": "You need to add a server before you can create a group",
"deleteProfileSuccess": "Successfully deleted profile", "deleteProfileSuccess": "Successfully deleted profile",
"sendInvite": "Send a contact or group invite",
"resetTor": "Reset",
"torStatus": "Tor Status",
"torVersion": "Tor Version",
"sendAnInvitation": "You sent an invitation for: ",
"contactSuggestion": "This is a contact suggestion for: ", "contactSuggestion": "This is a contact suggestion for: ",
"chatHistoryDefault": "This conversation will be deleted when Cwtch is closed! Message history can be enabled per-conversation via the Settings menu in the upper right.", "chatHistoryDefault": "This conversation will be deleted when Cwtch is closed! Message history can be enabled per-conversation via the Settings menu in the upper right.",
"reallyLeaveThisGroupPrompt": "Are you sure you want to leave this conversation? All messages and attributes will be deleted.", "reallyLeaveThisGroupPrompt": "Are you sure you want to leave this conversation? All messages and attributes will be deleted.",
@ -417,5 +386,26 @@
"descriptionBlockUnknownConnections": "If turned on, this option will automatically close connections from Cwtch users that have not been added to your contact list.", "descriptionBlockUnknownConnections": "If turned on, this option will automatically close connections from Cwtch users that have not been added to your contact list.",
"descriptionExperimentsGroups": "The group experiment allows Cwtch to connect with untrusted server infrastructure to facilitate communication with more than one contact.", "descriptionExperimentsGroups": "The group experiment allows Cwtch to connect with untrusted server infrastructure to facilitate communication with more than one contact.",
"descriptionExperiments": "Cwtch experiments are optional, opt-in features that add additional functionality to Cwtch that may have different privacy considerations than traditional 1:1 metadata resistant chat e.g. group chat, bot integration etc.", "descriptionExperiments": "Cwtch experiments are optional, opt-in features that add additional functionality to Cwtch that may have different privacy considerations than traditional 1:1 metadata resistant chat e.g. group chat, bot integration etc.",
"tooltipUnlockProfiles": "Unlock encrypted profiles by entering their password." "tooltipUnlockProfiles": "Unlock encrypted profiles by entering their password.",
"invalidImportString": "Invalid import string",
"todoPlaceholder": "Todo...",
"addNewItem": "Add a new item to the list",
"addListItem": "Add a New List Item",
"networkStatusConnecting": "Connecting to network and contacts...",
"networkStatusAttemptingTor": "Attempting to connect to Tor network",
"networkStatusDisconnected": "Disconnected from the internet, check your connection",
"viewGroupMembershipTooltip": "View Group Membership",
"loadingTor": "Loading tor...",
"version": "Version %1",
"versionTor": "Version %1 with tor %2",
"experimentsEnabled": "Enable Experiments",
"settingInterfaceZoom": "Zoom level",
"versionBuilddate": "Version: %1 Built on: %2",
"error0ProfilesLoadedForPassword": "0 profiles loaded with that password",
"enterProfilePassword": "Enter a password to view your profiles",
"deleteConfirmText": "DELETE",
"passwordChangeError": "Error changing password: Supplied password rejected",
"unblockBtn": "Unblock Contact",
"savePeerHistoryDescription": "Determines whether to delete any history associated with the contact.",
"pasteAddressToAddContact": "Paste a cwtch address, invitation or key bundle here to add a new conversation"
} }

View File

@ -1,16 +1,6 @@
{ {
"@@locale": "lb", "@@locale": "lb",
"@@last_modified": "2024-02-12T08:05:24+01:00", "@@last_modified": "2024-01-04T10:56:20+01:00",
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
"settingsImportThemeButton": "Import Theme",
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
"settingsImportThemeTitle": "Import Theme",
"settingsThemeErrorInvalid": "Error: Could not import $themeName, theme.yml missing, not a theme directory",
"settingThemeOverwriteQuestion": "Theme $themeName already exists, confirm overwrite?",
"settingThemeOverwriteConfirm": "Confirm",
"settingsThemeImagesDescription": "Enable display of images from themes",
"settingsThemeImages": "Theme Images",
"settingsGroupAbout": "About", "settingsGroupAbout": "About",
"localeUzbek": "Uzbek \/ Oʻzbekcha", "localeUzbek": "Uzbek \/ Oʻzbekcha",
"profileOfflineAtStart": "Appear Offline at Startup", "profileOfflineAtStart": "Appear Offline at Startup",

View File

@ -1,16 +1,6 @@
{ {
"@@locale": "nl", "@@locale": "nl",
"@@last_modified": "2024-02-12T08:05:24+01:00", "@@last_modified": "2024-01-04T10:56:20+01:00",
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
"settingsImportThemeButton": "Import Theme",
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
"settingsImportThemeTitle": "Import Theme",
"settingsThemeErrorInvalid": "Error: Could not import $themeName, theme.yml missing, not a theme directory",
"settingThemeOverwriteQuestion": "Theme $themeName already exists, confirm overwrite?",
"settingThemeOverwriteConfirm": "Confirm",
"settingsThemeImagesDescription": "Enable display of images from themes",
"settingsThemeImages": "Theme Images",
"settingsGroupAbout": "About", "settingsGroupAbout": "About",
"localeUzbek": "Uzbek \/ Oʻzbekcha", "localeUzbek": "Uzbek \/ Oʻzbekcha",
"profileOfflineAtStart": "Appear Offline at Startup", "profileOfflineAtStart": "Appear Offline at Startup",

View File

@ -1,16 +1,6 @@
{ {
"@@locale": "no", "@@locale": "no",
"@@last_modified": "2024-02-12T08:05:24+01:00", "@@last_modified": "2024-01-04T10:56:20+01:00",
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
"settingsImportThemeButton": "Import Theme",
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
"settingsImportThemeTitle": "Import Theme",
"settingsThemeErrorInvalid": "Error: Could not import $themeName, theme.yml missing, not a theme directory",
"settingThemeOverwriteQuestion": "Theme $themeName already exists, confirm overwrite?",
"settingThemeOverwriteConfirm": "Confirm",
"settingsThemeImagesDescription": "Enable display of images from themes",
"settingsThemeImages": "Theme Images",
"settingsGroupAbout": "About", "settingsGroupAbout": "About",
"localeUzbek": "Uzbek \/ Oʻzbekcha", "localeUzbek": "Uzbek \/ Oʻzbekcha",
"profileOfflineAtStart": "Appear Offline at Startup", "profileOfflineAtStart": "Appear Offline at Startup",

View File

@ -1,16 +1,6 @@
{ {
"@@locale": "pl", "@@locale": "pl",
"@@last_modified": "2024-02-12T08:05:24+01:00", "@@last_modified": "2024-01-04T10:56:20+01:00",
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
"settingsImportThemeButton": "Import Theme",
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
"settingsImportThemeTitle": "Import Theme",
"settingsThemeErrorInvalid": "Error: Could not import $themeName, theme.yml missing, not a theme directory",
"settingThemeOverwriteQuestion": "Theme $themeName already exists, confirm overwrite?",
"settingThemeOverwriteConfirm": "Confirm",
"settingsThemeImagesDescription": "Enable display of images from themes",
"settingsThemeImages": "Theme Images",
"settingsGroupAbout": "About", "settingsGroupAbout": "About",
"localeUzbek": "Uzbek \/ Oʻzbekcha", "localeUzbek": "Uzbek \/ Oʻzbekcha",
"profileOfflineAtStart": "Appear Offline at Startup", "profileOfflineAtStart": "Appear Offline at Startup",

View File

@ -1,16 +1,6 @@
{ {
"@@locale": "pt", "@@locale": "pt",
"@@last_modified": "2024-02-12T08:05:24+01:00", "@@last_modified": "2024-01-04T10:56:20+01:00",
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
"settingsImportThemeButton": "Import Theme",
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
"settingsImportThemeTitle": "Import Theme",
"settingsThemeErrorInvalid": "Error: Could not import $themeName, theme.yml missing, not a theme directory",
"settingThemeOverwriteQuestion": "Theme $themeName already exists, confirm overwrite?",
"settingThemeOverwriteConfirm": "Confirm",
"settingsThemeImagesDescription": "Enable display of images from themes",
"settingsThemeImages": "Theme Images",
"settingsGroupAbout": "About", "settingsGroupAbout": "About",
"localeUzbek": "Uzbek \/ Oʻzbekcha", "localeUzbek": "Uzbek \/ Oʻzbekcha",
"profileOfflineAtStart": "Appear Offline at Startup", "profileOfflineAtStart": "Appear Offline at Startup",

View File

@ -1,16 +1,6 @@
{ {
"@@locale": "pt_BR", "@@locale": "pt_BR",
"@@last_modified": "2024-02-12T08:05:24+01:00", "@@last_modified": "2024-01-04T10:56:20+01:00",
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
"settingsImportThemeButton": "Import Theme",
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
"settingsImportThemeTitle": "Import Theme",
"settingsThemeErrorInvalid": "Error: Could not import $themeName, theme.yml missing, not a theme directory",
"settingThemeOverwriteQuestion": "Theme $themeName already exists, confirm overwrite?",
"settingThemeOverwriteConfirm": "Confirm",
"settingsThemeImagesDescription": "Enable display of images from themes",
"settingsThemeImages": "Theme Images",
"settingsGroupAbout": "About", "settingsGroupAbout": "About",
"localeUzbek": "Uzbek \/ Oʻzbekcha", "localeUzbek": "Uzbek \/ Oʻzbekcha",
"profileOfflineAtStart": "Appear Offline at Startup", "profileOfflineAtStart": "Appear Offline at Startup",

View File

@ -1,16 +1,6 @@
{ {
"@@locale": "ro", "@@locale": "ro",
"@@last_modified": "2024-02-12T08:05:24+01:00", "@@last_modified": "2024-01-04T10:56:20+01:00",
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
"settingsImportThemeButton": "Import Theme",
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
"settingsImportThemeTitle": "Import Theme",
"settingsThemeErrorInvalid": "Error: Could not import $themeName, theme.yml missing, not a theme directory",
"settingThemeOverwriteQuestion": "Theme $themeName already exists, confirm overwrite?",
"settingThemeOverwriteConfirm": "Confirm",
"settingsThemeImagesDescription": "Enable display of images from themes",
"settingsThemeImages": "Theme Images",
"settingsGroupAbout": "About", "settingsGroupAbout": "About",
"localeUzbek": "Uzbek \/ Oʻzbekcha", "localeUzbek": "Uzbek \/ Oʻzbekcha",
"profileOfflineAtStart": "Appear Offline at Startup", "profileOfflineAtStart": "Appear Offline at Startup",

View File

@ -1,16 +1,6 @@
{ {
"@@locale": "ru", "@@locale": "ru",
"@@last_modified": "2024-02-12T08:05:24+01:00", "@@last_modified": "2024-01-04T10:56:20+01:00",
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
"settingsImportThemeButton": "Import Theme",
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
"settingsImportThemeTitle": "Import Theme",
"settingsThemeErrorInvalid": "Error: Could not import $themeName, theme.yml missing, not a theme directory",
"settingThemeOverwriteQuestion": "Theme $themeName already exists, confirm overwrite?",
"settingThemeOverwriteConfirm": "Confirm",
"settingsThemeImagesDescription": "Enable display of images from themes",
"settingsThemeImages": "Theme Images",
"settingsGroupAbout": "About", "settingsGroupAbout": "About",
"localeUzbek": "Uzbek \/ Oʻzbekcha", "localeUzbek": "Uzbek \/ Oʻzbekcha",
"profileOfflineAtStart": "Appear Offline at Startup", "profileOfflineAtStart": "Appear Offline at Startup",

View File

@ -1,16 +1,6 @@
{ {
"@@locale": "sk", "@@locale": "sk",
"@@last_modified": "2024-02-12T08:05:24+01:00", "@@last_modified": "2024-01-04T10:56:20+01:00",
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
"settingsImportThemeButton": "Import Theme",
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
"settingsImportThemeTitle": "Import Theme",
"settingsThemeErrorInvalid": "Error: Could not import $themeName, theme.yml missing, not a theme directory",
"settingThemeOverwriteQuestion": "Theme $themeName already exists, confirm overwrite?",
"settingThemeOverwriteConfirm": "Confirm",
"settingsThemeImagesDescription": "Enable display of images from themes",
"settingsThemeImages": "Theme Images",
"settingsGroupAbout": "About", "settingsGroupAbout": "About",
"localeUzbek": "Uzbek \/ Oʻzbekcha", "localeUzbek": "Uzbek \/ Oʻzbekcha",
"profileOfflineAtStart": "Appear Offline at Startup", "profileOfflineAtStart": "Appear Offline at Startup",

View File

@ -1,16 +1,6 @@
{ {
"@@locale": "sv", "@@locale": "sv",
"@@last_modified": "2024-02-12T08:05:24+01:00", "@@last_modified": "2024-01-04T10:56:20+01:00",
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
"settingsImportThemeButton": "Import Theme",
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
"settingsImportThemeTitle": "Import Theme",
"settingsThemeErrorInvalid": "Error: Could not import $themeName, theme.yml missing, not a theme directory",
"settingThemeOverwriteQuestion": "Theme $themeName already exists, confirm overwrite?",
"settingThemeOverwriteConfirm": "Confirm",
"settingsThemeImagesDescription": "Enable display of images from themes",
"settingsThemeImages": "Theme Images",
"settingsGroupAbout": "About", "settingsGroupAbout": "About",
"localeUzbek": "Uzbek \/ Oʻzbekcha", "localeUzbek": "Uzbek \/ Oʻzbekcha",
"profileOfflineAtStart": "Appear Offline at Startup", "profileOfflineAtStart": "Appear Offline at Startup",

View File

@ -1,16 +1,6 @@
{ {
"@@locale": "sw", "@@locale": "sw",
"@@last_modified": "2024-02-12T08:05:24+01:00", "@@last_modified": "2024-01-04T10:56:20+01:00",
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
"settingsImportThemeButton": "Import Theme",
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
"settingsImportThemeTitle": "Import Theme",
"settingsThemeErrorInvalid": "Error: Could not import $themeName, theme.yml missing, not a theme directory",
"settingThemeOverwriteQuestion": "Theme $themeName already exists, confirm overwrite?",
"settingThemeOverwriteConfirm": "Confirm",
"settingsThemeImagesDescription": "Enable display of images from themes",
"settingsThemeImages": "Theme Images",
"settingsGroupAbout": "About", "settingsGroupAbout": "About",
"localeUzbek": "Uzbek \/ Oʻzbekcha", "localeUzbek": "Uzbek \/ Oʻzbekcha",
"profileOfflineAtStart": "Appear Offline at Startup", "profileOfflineAtStart": "Appear Offline at Startup",

View File

@ -1,16 +1,6 @@
{ {
"@@locale": "tr", "@@locale": "tr",
"@@last_modified": "2024-02-12T08:05:24+01:00", "@@last_modified": "2024-01-04T10:56:20+01:00",
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
"settingsImportThemeButton": "Import Theme",
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
"settingsImportThemeTitle": "Import Theme",
"settingsThemeErrorInvalid": "Error: Could not import $themeName, theme.yml missing, not a theme directory",
"settingThemeOverwriteQuestion": "Theme $themeName already exists, confirm overwrite?",
"settingThemeOverwriteConfirm": "Confirm",
"settingsThemeImagesDescription": "Enable display of images from themes",
"settingsThemeImages": "Theme Images",
"settingsGroupAbout": "About", "settingsGroupAbout": "About",
"localeUzbek": "Uzbek \/ Oʻzbekcha", "localeUzbek": "Uzbek \/ Oʻzbekcha",
"profileOfflineAtStart": "Appear Offline at Startup", "profileOfflineAtStart": "Appear Offline at Startup",

View File

@ -1,16 +1,6 @@
{ {
"@@locale": "uk", "@@locale": "uk",
"@@last_modified": "2024-02-12T08:05:24+01:00", "@@last_modified": "2024-01-04T10:56:20+01:00",
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
"settingsImportThemeButton": "Import Theme",
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
"settingsImportThemeTitle": "Import Theme",
"settingsThemeErrorInvalid": "Error: Could not import $themeName, theme.yml missing, not a theme directory",
"settingThemeOverwriteQuestion": "Theme $themeName already exists, confirm overwrite?",
"settingThemeOverwriteConfirm": "Confirm",
"settingsThemeImagesDescription": "Enable display of images from themes",
"settingsThemeImages": "Theme Images",
"settingsGroupAbout": "About", "settingsGroupAbout": "About",
"localeUzbek": "Uzbek \/ Oʻzbekcha", "localeUzbek": "Uzbek \/ Oʻzbekcha",
"profileOfflineAtStart": "Appear Offline at Startup", "profileOfflineAtStart": "Appear Offline at Startup",

View File

@ -1,16 +1,6 @@
{ {
"@@locale": "uz", "@@locale": "uz",
"@@last_modified": "2024-02-12T08:05:24+01:00", "@@last_modified": "2024-01-04T10:56:20+01:00",
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
"settingsImportThemeButton": "Import Theme",
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
"settingsImportThemeTitle": "Import Theme",
"settingsThemeErrorInvalid": "Error: Could not import $themeName, theme.yml missing, not a theme directory",
"settingThemeOverwriteQuestion": "Theme $themeName already exists, confirm overwrite?",
"settingThemeOverwriteConfirm": "Confirm",
"settingsThemeImagesDescription": "Enable display of images from themes",
"settingsThemeImages": "Theme Images",
"settingsGroupAbout": "About", "settingsGroupAbout": "About",
"localeUzbek": "Uzbek \/ Oʻzbekcha", "localeUzbek": "Uzbek \/ Oʻzbekcha",
"profileOfflineAtStart": "Appear Offline at Startup", "profileOfflineAtStart": "Appear Offline at Startup",

View File

@ -1,7 +1,9 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:isolate';
import 'package:cwtch/config.dart'; import 'package:cwtch/config.dart';
import 'package:cwtch/notification_manager.dart'; import 'package:cwtch/notification_manager.dart';
import 'package:cwtch/themes/cwtch.dart';
import 'package:cwtch/views/doublecolview.dart'; import 'package:cwtch/views/doublecolview.dart';
import 'package:cwtch/views/messageview.dart'; import 'package:cwtch/views/messageview.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
@ -31,7 +33,9 @@ import 'themes/opaque.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:connectivity_plus/connectivity_plus.dart';
var globalSettings = Settings(Locale("en", '')); import 'package:intl/intl.dart' as intl;
var globalSettings = Settings(Locale("en", ''), CwtchDark());
var globalErrorHandler = ErrorHandler(); var globalErrorHandler = ErrorHandler();
var globalTorStatus = TorStatus(); var globalTorStatus = TorStatus();
var globalAppState = AppState(); var globalAppState = AppState();
@ -76,7 +80,7 @@ class FlwtchState extends State<Flwtch> with WindowListener {
@override @override
initState() { initState() {
print("initState() started, setting up handlers"); print("initState() started, setting up handlers");
globalSettings = Settings(Locale("en", '')); globalSettings = Settings(Locale("en", ''), CwtchDark());
globalErrorHandler = ErrorHandler(); globalErrorHandler = ErrorHandler();
globalTorStatus = TorStatus(); globalTorStatus = TorStatus();
globalAppState = AppState(); globalAppState = AppState();
@ -103,14 +107,12 @@ class FlwtchState extends State<Flwtch> with WindowListener {
new CwtchNotifier(profs, globalSettings, globalErrorHandler, globalTorStatus, newDesktopNotificationsManager(_notificationSelectConvo), globalAppState, globalServersList, this); new CwtchNotifier(profs, globalSettings, globalErrorHandler, globalTorStatus, newDesktopNotificationsManager(_notificationSelectConvo), globalAppState, globalServersList, this);
cwtch = CwtchFfi(cwtchNotifier); cwtch = CwtchFfi(cwtchNotifier);
} }
print("initState: invoking cwtch.Start()");
// Cwtch.start can take time, we don't want it blocking first splash screen draw, so postpone a smidge to let splash render // Cwtch.start can take time, we don't want it blocking first splash screen draw, so postpone a smidge to let splash render
Future.delayed(const Duration(milliseconds: 100), () { Future.delayed(const Duration(milliseconds: 50), () {
print("initState delayed: invoking cwtch.Start()"); print("actually invoking cwtch.cwtch()!!!");
cwtch.Start().then((v) { cwtch.Start();
cwtch.getCwtchDir().then((dir) { LoadAssetThemes();
globalSettings.themeloader.LoadThemes(dir);
});
});
}); });
print("initState: starting connectivityListener"); print("initState: starting connectivityListener");
if (EnvironmentConfig.TEST_MODE == false) { if (EnvironmentConfig.TEST_MODE == false) {
@ -127,7 +129,7 @@ class FlwtchState extends State<Flwtch> with WindowListener {
// gracefully fails and NOPs, as it's not a required functionality // gracefully fails and NOPs, as it's not a required functionality
startConnectivityListener() async { startConnectivityListener() async {
try { try {
connectivityStream = Connectivity().onConnectivityChanged.listen((ConnectivityResult result) { connectivityStream = await Connectivity().onConnectivityChanged.listen((ConnectivityResult result) {
// Got a new connectivity status! // Got a new connectivity status!
if (result == ConnectivityResult.none) { if (result == ConnectivityResult.none) {
connectivityState = ConnectivityState.confirmed_offline; connectivityState = ConnectivityState.confirmed_offline;
@ -160,7 +162,6 @@ class FlwtchState extends State<Flwtch> with WindowListener {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
globalSettings.initPackageInfo(); globalSettings.initPackageInfo();
return MultiProvider( return MultiProvider(
providers: [ providers: [
getFlwtchStateProvider(), getFlwtchStateProvider(),
@ -172,6 +173,10 @@ class FlwtchState extends State<Flwtch> with WindowListener {
getServerListStateProvider(), getServerListStateProvider(),
], ],
builder: (context, widget) { builder: (context, widget) {
// in test mode...rebuild everything every second...if cwtch isn't loaded...
if (EnvironmentConfig.TEST_MODE && cwtch.IsLoaded() == false) {
Timer t = new Timer.periodic(Duration(seconds: 1), (Timer t) => setState(() {}));
}
return Consumer2<Settings, AppState>( return Consumer2<Settings, AppState>(
builder: (context, settings, appState, child) => MaterialApp( builder: (context, settings, appState, child) => MaterialApp(
key: Key('app'), key: Key('app'),
@ -189,7 +194,7 @@ class FlwtchState extends State<Flwtch> with WindowListener {
title: 'Cwtch', title: 'Cwtch',
showSemanticsDebugger: settings.useSemanticDebugger, showSemanticsDebugger: settings.useSemanticDebugger,
theme: mkThemeData(settings), theme: mkThemeData(settings),
home: (!appState.loaded) ? SplashView() : ProfileMgrView(), home: (!appState.cwtchInit || appState.modalState != ModalState.none) || !cwtch.IsLoaded() ? SplashView() : ProfileMgrView(),
), ),
); );
}, },
@ -252,6 +257,7 @@ class FlwtchState extends State<Flwtch> with WindowListener {
exit(0); exit(0);
} }
} }
;
} }
// Invoked via notificationClickChannel by MyBroadcastReceiver in MainActivity.kt // Invoked via notificationClickChannel by MyBroadcastReceiver in MainActivity.kt

View File

@ -1,3 +1,4 @@
import 'package:cwtch/themes/cwtch.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -7,14 +8,16 @@ import 'package:glob/list_local_fs.dart';
import 'config.dart'; import 'config.dart';
import 'licenses.dart'; import 'licenses.dart';
import 'main.dart'; import 'main.dart';
import 'themes/opaque.dart';
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'dart:typed_data';
import "package:flutter_driver/driver_extension.dart"; import "package:flutter_driver/driver_extension.dart";
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:glob/glob.dart'; import 'package:glob/glob.dart';
var globalSettings = Settings(Locale("en", '')); var globalSettings = Settings(Locale("en", ''), CwtchDark());
var globalErrorHandler = ErrorHandler(); var globalErrorHandler = ErrorHandler();
Future<void> main() async { Future<void> main() async {

View File

@ -1,7 +1,7 @@
import 'dart:async'; import 'dart:async';
import 'dart:io';
import 'package:cwtch/config.dart'; import 'package:cwtch/config.dart';
import 'package:cwtch/main.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
enum ModalState { none, storageMigration, shutdown } enum ModalState { none, storageMigration, shutdown }
@ -18,8 +18,6 @@ class AppState extends ChangeNotifier {
bool _unreadMessagesBelow = false; bool _unreadMessagesBelow = false;
bool _disableFilePicker = false; bool _disableFilePicker = false;
bool _focus = true; bool _focus = true;
bool _settingsLoaded = false;
bool _themesLoaded = false;
StreamController<bool> _profilesUnreadNotifyControler = StreamController<bool>(); StreamController<bool> _profilesUnreadNotifyControler = StreamController<bool>();
late Stream<bool> profilesUnreadNotify; late Stream<bool> profilesUnreadNotify;
@ -35,13 +33,13 @@ class AppState extends ChangeNotifier {
void SetAppError(String error) { void SetAppError(String error) {
appError = error; appError = error;
EnvironmentConfig.debugLog("App Error: $appError"); EnvironmentConfig.debugLog("App Error: ${appError}");
notifyListeners(); notifyListeners();
} }
void SetModalState(ModalState newState) { void SetModalState(ModalState newState) {
modalState = newState; modalState = newState;
EnvironmentConfig.debugLog("Modal State: $newState"); EnvironmentConfig.debugLog("Modal State: ${newState}");
notifyListeners(); notifyListeners();
} }
@ -88,18 +86,6 @@ class AppState extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
set settingsLoaded(bool newVal) {
_settingsLoaded = newVal;
notifyListeners();
}
set themesLoaded(bool newVal) {
_themesLoaded = newVal;
notifyListeners();
}
bool get loaded => cwtchInit && _settingsLoaded && globalSettings.themeloader.themes.length > 0 && modalState == ModalState.none;
bool isLandscape(BuildContext c) => MediaQuery.of(c).size.width > MediaQuery.of(c).size.height; bool isLandscape(BuildContext c) => MediaQuery.of(c).size.width > MediaQuery.of(c).size.height;
void notifyProfileUnread() { void notifyProfileUnread() {

View File

@ -1,3 +1,5 @@
import 'dart:ffi';
import 'package:cwtch/main.dart'; import 'package:cwtch/main.dart';
import 'package:cwtch/models/message_draft.dart'; import 'package:cwtch/models/message_draft.dart';
import 'package:cwtch/models/profile.dart'; import 'package:cwtch/models/profile.dart';
@ -11,6 +13,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart'; import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
import 'message.dart';
import 'messagecache.dart'; import 'messagecache.dart';
enum ConversationNotificationPolicy { enum ConversationNotificationPolicy {

View File

@ -54,7 +54,7 @@ class ContactListState extends ChangeNotifier {
if (otherGroups != null && otherGroups.isNotEmpty) { if (otherGroups != null && otherGroups.isNotEmpty) {
EnvironmentConfig.debugLog("sharing antispam tickets to new group. FIXME: in Cwtch 1.14"); EnvironmentConfig.debugLog("sharing antispam tickets to new group. FIXME: in Cwtch 1.14");
var antispamTickets = otherGroups[0].antispamTickets; var antispamTickets = otherGroups[0].antispamTickets;
_contacts.last.antispamTickets = antispamTickets; _contacts.last!.antispamTickets = antispamTickets;
} }
servers?.addGroup(newContact); servers?.addGroup(newContact);
} }

View File

@ -3,22 +3,12 @@ class FileDownloadProgress {
int chunksTotal = 1; int chunksTotal = 1;
bool complete = false; bool complete = false;
bool gotManifest = false; bool gotManifest = false;
bool _interrupted = false; bool interrupted = false;
// we keep track of both an explicit interrupt flag (for when a request fails or is explicitly cancelled)
set interrupted(isInterrupted) {
this._interrupted = isInterrupted;
}
// but we have a fuzzy get which depends on lastUpdate, if the file isn't complete, but the last update was more
// that 30 seconds ago, we consider this download as failed.
get interrupted => _interrupted || (DateTime.now().difference(lastUpdate).abs().inSeconds > 30 && !complete);
String? downloadedTo; String? downloadedTo;
DateTime? timeStart; DateTime? timeStart;
DateTime? timeEnd; DateTime? timeEnd;
DateTime? requested; DateTime? requested;
DateTime lastUpdate = DateTime.fromMillisecondsSinceEpoch(0); DateTime lastUpdate = DateTime.now();
FileDownloadProgress(this.chunksTotal, this.timeStart); FileDownloadProgress(this.chunksTotal, this.timeStart);

View File

@ -34,7 +34,7 @@ abstract class Message {
Widget getWidget(BuildContext context, Key key, int index); Widget getWidget(BuildContext context, Key key, int index);
Widget getPreviewWidget(BuildContext context, {BoxConstraints? constraints}); Widget getPreviewWidget(BuildContext context);
} }
Message compileOverlay(MessageInfo messageInfo) { Message compileOverlay(MessageInfo messageInfo) {
@ -64,7 +64,6 @@ Message compileOverlay(MessageInfo messageInfo) {
abstract class CacheHandler { abstract class CacheHandler {
Future<MessageInfo?> get(Cwtch cwtch, String profileOnion, int conversationIdentifier, MessageCache cache); Future<MessageInfo?> get(Cwtch cwtch, String profileOnion, int conversationIdentifier, MessageCache cache);
Future<MessageInfo?> sync(Cwtch cwtch, String profileOnion, int conversationIdentifier, MessageCache cache);
} }
class ByIndex implements CacheHandler { class ByIndex implements CacheHandler {
@ -129,8 +128,7 @@ class ByIndex implements CacheHandler {
List<dynamic> messagesWrapper = jsonDecode(msgs); List<dynamic> messagesWrapper = jsonDecode(msgs);
for (; i < messagesWrapper.length; i++) { for (; i < messagesWrapper.length; i++) {
var messageInfo = MessageWrapperToInfo(profileOnion, conversationIdentifier, messagesWrapper[i]); var messageInfo = messageWrapperToInfo(profileOnion, conversationIdentifier, messagesWrapper[i]);
messageInfo.metadata.lastChecked = DateTime.now();
cache.addIndexed(messageInfo, start + i); cache.addIndexed(messageInfo, start + i);
} }
} catch (e, stacktrace) { } catch (e, stacktrace) {
@ -145,13 +143,6 @@ class ByIndex implements CacheHandler {
void add(MessageCache cache, MessageInfo messageInfo) { void add(MessageCache cache, MessageInfo messageInfo) {
cache.addIndexed(messageInfo, index); cache.addIndexed(messageInfo, index);
} }
@override
Future<MessageInfo?> sync(Cwtch cwtch, String profileOnion, int conversationIdentifier, MessageCache cache) {
EnvironmentConfig.debugLog("performing a resync on message ${index}");
fetchAndProcess(index, 1, cwtch, profileOnion, conversationIdentifier, cache);
return get(cwtch, profileOnion, conversationIdentifier, cache);
}
} }
class ById implements CacheHandler { class ById implements CacheHandler {
@ -181,11 +172,6 @@ class ById implements CacheHandler {
} }
return fetch(cwtch, profileOnion, conversationIdentifier, cache); return fetch(cwtch, profileOnion, conversationIdentifier, cache);
} }
@override
Future<MessageInfo?> sync(Cwtch cwtch, String profileOnion, int conversationIdentifier, MessageCache cache) {
return get(cwtch, profileOnion, conversationIdentifier, cache);
}
} }
class ByContentHash implements CacheHandler { class ByContentHash implements CacheHandler {
@ -214,11 +200,6 @@ class ByContentHash implements CacheHandler {
} }
return fetch(cwtch, profileOnion, conversationIdentifier, cache); return fetch(cwtch, profileOnion, conversationIdentifier, cache);
} }
@override
Future<MessageInfo?> sync(Cwtch cwtch, String profileOnion, int conversationIdentifier, MessageCache cache) {
return get(cwtch, profileOnion, conversationIdentifier, cache);
}
} }
List<Message> getReplies(MessageCache cache, int messageIdentifier) { List<Message> getReplies(MessageCache cache, int messageIdentifier) {
@ -276,16 +257,6 @@ Future<Message> messageHandler(BuildContext context, String profileOnion, int co
MessageInfo? messageInfo = await cacheHandler.get(cwtch, profileOnion, conversationIdentifier, cache); MessageInfo? messageInfo = await cacheHandler.get(cwtch, profileOnion, conversationIdentifier, cache);
if (messageInfo != null) {
if (messageInfo.metadata.ackd == false) {
if (messageInfo.metadata.lastChecked == null || messageInfo.metadata.lastChecked!.difference(DateTime.now()).abs().inSeconds > 30) {
messageInfo.metadata.lastChecked = DateTime.now();
// NOTE: Only ByIndex lookups will trigger
messageInfo = await cacheHandler.sync(cwtch, profileOnion, conversationIdentifier, cache);
}
}
}
if (messageInfo != null) { if (messageInfo != null) {
return compileOverlay(messageInfo); return compileOverlay(messageInfo);
} else { } else {
@ -301,14 +272,14 @@ MessageInfo? messageJsonToInfo(String profileOnion, int conversationIdentifier,
return null; return null;
} }
return MessageWrapperToInfo(profileOnion, conversationIdentifier, messageWrapper); return messageWrapperToInfo(profileOnion, conversationIdentifier, messageWrapper);
} catch (e, stacktrace) { } catch (e, stacktrace) {
EnvironmentConfig.debugLog("message handler exception on parse message and cache: " + e.toString() + " " + stacktrace.toString()); EnvironmentConfig.debugLog("message handler exception on parse message and cache: " + e.toString() + " " + stacktrace.toString());
return null; return null;
} }
} }
MessageInfo MessageWrapperToInfo(String profileOnion, int conversationIdentifier, dynamic messageWrapper) { MessageInfo messageWrapperToInfo(String profileOnion, int conversationIdentifier, dynamic messageWrapper) {
// Construct the initial metadata // Construct the initial metadata
var messageID = messageWrapper['ID']; var messageID = messageWrapper['ID'];
var timestamp = DateTime.tryParse(messageWrapper['Timestamp'])!; var timestamp = DateTime.tryParse(messageWrapper['Timestamp'])!;
@ -341,7 +312,6 @@ class MessageMetadata extends ChangeNotifier {
final String? signature; final String? signature;
final String contenthash; final String contenthash;
DateTime? lastChecked;
dynamic get attributes => this._attributes; dynamic get attributes => this._attributes;

View File

@ -1,4 +1,5 @@
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
/// A "MessageDraft" structure that stores information about in-progress message drafts. /// A "MessageDraft" structure that stores information about in-progress message drafts.
/// MessageDraft stores text, quoted replies, and attached images. /// MessageDraft stores text, quoted replies, and attached images.
@ -49,8 +50,6 @@ class MessageDraft extends ChangeNotifier {
void clearDraft() { void clearDraft() {
this._quotedReference = null; this._quotedReference = null;
this.ctrlCompose.clear(); this.ctrlCompose.clear();
this.ctrlCompose.clearComposing();
this.ctrlCompose.text = "";
this._inviteHandle = null; this._inviteHandle = null;
notifyListeners(); notifyListeners();
} }

View File

@ -128,9 +128,8 @@ class MessageCache extends ChangeNotifier {
void addNew(String profileOnion, int conversation, int messageID, DateTime timestamp, String senderHandle, String senderImage, bool isAuto, String data, String contenthash) { void addNew(String profileOnion, int conversation, int messageID, DateTime timestamp, String senderHandle, String senderImage, bool isAuto, String data, String contenthash) {
this.cache[messageID] = MessageInfo(MessageMetadata(profileOnion, conversation, messageID, timestamp, senderHandle, senderImage, "", {}, false, false, isAuto, contenthash), data); this.cache[messageID] = MessageInfo(MessageMetadata(profileOnion, conversation, messageID, timestamp, senderHandle, senderImage, "", {}, false, false, isAuto, contenthash), data);
this.cache[messageID]?.metadata.lastChecked = DateTime.now(); // Don't check straight away...
this.cacheByIndex.insert(0, LocalIndexMessage(messageID)); this.cacheByIndex.insert(0, LocalIndexMessage(messageID));
if (contenthash != "") { if (contenthash != null && contenthash != "") {
this.cacheByHash[contenthash] = messageID; this.cacheByHash[contenthash] = messageID;
} }
} }

View File

@ -49,27 +49,24 @@ class FileMessage extends Message {
} }
@override @override
Widget getPreviewWidget(BuildContext context, {BoxConstraints? constraints}) { Widget getPreviewWidget(BuildContext context) {
return ChangeNotifierProvider.value( return ChangeNotifierProvider.value(
value: this.metadata, value: this.metadata,
builder: (bcontext, child) { builder: (bcontext, child) {
dynamic shareObj = jsonDecode(this.content); dynamic shareObj = jsonDecode(this.content);
if (shareObj == null) { if (shareObj == null) {
return MalformedBubble(); return MessageRow(MalformedBubble(), 0);
} }
String nameSuggestion = shareObj['f'] as String; String nameSuggestion = shareObj['f'] as String;
String rootHash = shareObj['h'] as String; String rootHash = shareObj['h'] as String;
String nonce = shareObj['n'] as String; String nonce = shareObj['n'] as String;
int fileSize = shareObj['s'] as int; int fileSize = shareObj['s'] as int;
if (!validHash(rootHash, nonce)) { if (!validHash(rootHash, nonce)) {
return MalformedBubble(); return MessageRow(MalformedBubble(), 0);
} }
return Container( return Container(
padding: EdgeInsets.all(1.0), alignment: Alignment.center,
decoration: BoxDecoration(), height: 100,
clipBehavior: Clip.antiAliasWithSaveLayer,
constraints: BoxConstraints(minHeight: 50, maxHeight: 50, minWidth: 50, maxWidth: 300),
alignment: Alignment.centerLeft,
child: FileBubble( child: FileBubble(
nameSuggestion, nameSuggestion,
rootHash, rootHash,

View File

@ -48,7 +48,7 @@ class InviteMessage extends Message {
} }
@override @override
Widget getPreviewWidget(BuildContext context, {BoxConstraints? constraints}) { Widget getPreviewWidget(BuildContext context) {
return ChangeNotifierProvider.value( return ChangeNotifierProvider.value(
value: this.metadata, value: this.metadata,
builder: (bcontext, child) { builder: (bcontext, child) {

View File

@ -18,7 +18,7 @@ class MalformedMessage extends Message {
} }
@override @override
Widget getPreviewWidget(BuildContext context, {BoxConstraints? constraints}) { Widget getPreviewWidget(BuildContext context) {
return ChangeNotifierProvider.value( return ChangeNotifierProvider.value(
value: this.metadata, value: this.metadata,
builder: (bcontext, child) { builder: (bcontext, child) {

View File

@ -1,5 +1,6 @@
import 'dart:convert'; import 'dart:convert';
import 'package:cwtch/config.dart';
import 'package:cwtch/models/message.dart'; import 'package:cwtch/models/message.dart';
import 'package:cwtch/models/messages/malformedmessage.dart'; import 'package:cwtch/models/messages/malformedmessage.dart';
import 'package:cwtch/widgets/malformedbubble.dart'; import 'package:cwtch/widgets/malformedbubble.dart';
@ -10,6 +11,7 @@ import 'package:flutter/widgets.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../settings.dart'; import '../../settings.dart';
import '../../third_party/linkify/flutter_linkify.dart';
class QuotedMessageStructure { class QuotedMessageStructure {
final String quotedHash; final String quotedHash;
@ -28,7 +30,7 @@ class QuotedMessage extends Message {
QuotedMessage(this.metadata, this.content); QuotedMessage(this.metadata, this.content);
@override @override
Widget getPreviewWidget(BuildContext context, {BoxConstraints? constraints}) { Widget getPreviewWidget(BuildContext context) {
return ChangeNotifierProvider.value( return ChangeNotifierProvider.value(
value: this.metadata, value: this.metadata,
builder: (bcontext, child) { builder: (bcontext, child) {
@ -38,7 +40,7 @@ class QuotedMessage extends Message {
); );
var content = message["body"]; var content = message["body"];
var formatMessages = Provider.of<Settings>(bcontext).isExperimentEnabled(FormattingExperiment); var formatMessages = Provider.of<Settings>(bcontext).isExperimentEnabled(FormattingExperiment);
return compileMessageContentWidget(context, constraints ?? BoxConstraints.loose(MediaQuery.sizeOf(context)), false, content, FocusNode(), formatMessages, false); return compileMessageContentWidget(context, false, content, FocusNode(), formatMessages, false);
} catch (e) { } catch (e) {
return MalformedBubble(); return MalformedBubble();
} }

View File

@ -1,11 +1,17 @@
import 'dart:math';
import 'package:cwtch/models/message.dart'; import 'package:cwtch/models/message.dart';
import 'package:cwtch/models/messages/malformedmessage.dart';
import 'package:cwtch/widgets/malformedbubble.dart';
import 'package:cwtch/widgets/messagebubble.dart'; import 'package:cwtch/widgets/messagebubble.dart';
import 'package:cwtch/widgets/messageloadingbubble.dart';
import 'package:cwtch/widgets/messagerow.dart'; import 'package:cwtch/widgets/messagerow.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../settings.dart'; import '../../settings.dart';
import '../../third_party/linkify/flutter_linkify.dart';
import '../../widgets/messageBubbleWidgetHelpers.dart'; import '../../widgets/messageBubbleWidgetHelpers.dart';
class TextMessage extends Message { class TextMessage extends Message {
@ -15,12 +21,13 @@ class TextMessage extends Message {
TextMessage(this.metadata, this.content); TextMessage(this.metadata, this.content);
@override @override
Widget getPreviewWidget(BuildContext context, {BoxConstraints? constraints}) { Widget getPreviewWidget(BuildContext context) {
return ChangeNotifierProvider.value( return ChangeNotifierProvider.value(
value: this.metadata, value: this.metadata,
builder: (bcontext, child) { builder: (bcontext, child) {
var formatMessages = Provider.of<Settings>(bcontext).isExperimentEnabled(FormattingExperiment); var formatMessages = Provider.of<Settings>(bcontext).isExperimentEnabled(FormattingExperiment);
return compileMessageContentWidget(context, constraints ?? BoxConstraints.loose(MediaQuery.sizeOf(context)), false, content, FocusNode(), formatMessages, false); return compileMessageContentWidget(context, false, content, FocusNode(), formatMessages, false);
;
}); });
} }

View File

@ -14,6 +14,8 @@ import '../views/contactsview.dart';
import 'contact.dart'; import 'contact.dart';
import 'contactlist.dart'; import 'contactlist.dart';
import 'filedownloadprogress.dart'; import 'filedownloadprogress.dart';
import 'message.dart';
import 'messagecache.dart';
import 'profileservers.dart'; import 'profileservers.dart';
class ProfileInfoState extends ChangeNotifier { class ProfileInfoState extends ChangeNotifier {
@ -239,7 +241,7 @@ class ProfileInfoState extends ChangeNotifier {
this._unreadMessages = 0; this._unreadMessages = 0;
this.replaceServers(serverJson); this.replaceServers(serverJson);
if (contactsJson != "" && contactsJson != "null") { if (contactsJson != null && contactsJson != "" && contactsJson != "null") {
List<dynamic> contacts = jsonDecode(contactsJson); List<dynamic> contacts = jsonDecode(contactsJson);
contacts.forEach((contact) { contacts.forEach((contact) {
var profileContact = this._contacts.getContact(contact["identifier"]); var profileContact = this._contacts.getContact(contact["identifier"]);
@ -381,6 +383,19 @@ class ProfileInfoState extends ChangeNotifier {
if (this._downloads[fileKey]!.interrupted) { if (this._downloads[fileKey]!.interrupted) {
return true; return true;
} }
if (this._downloads[fileKey]!.requested != null) {
if (DateTime.now().difference(this._downloads[fileKey]!.requested!) > Duration(minutes: 1)) {
this._downloads[fileKey]!.requested = null;
this._downloads[fileKey]!.interrupted = true;
return true;
}
if (DateTime.now().difference(this._downloads[fileKey]!.lastUpdate) > Duration(minutes: 1)) {
this._downloads[fileKey]!.requested = null;
this._downloads[fileKey]!.interrupted = true;
return true;
}
}
} }
return false; return false;
} }

View File

@ -1,3 +1,6 @@
import 'dart:ui';
import 'package:cwtch/config.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';

View File

@ -1,3 +1,5 @@
import 'dart:io';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
@ -37,7 +39,5 @@ String prettyDateString(BuildContext context, DateTime date) {
// } // }
return AppLocalizations.of(context)!.now; return AppLocalizations.of(context)!.now;
} }
// note: explicitly overriding the 'locale' here to force return DateFormat.yMd(Platform.localeName).add_jm().format(date.toLocal());
// a consistent YYYY-mm-dd HH::MM format.
return DateFormat.yMd('en_CA').add_jm().format(date.toLocal());
} }

View File

@ -1,3 +1,4 @@
import 'package:cwtch/config.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'contact.dart'; import 'contact.dart';

View File

@ -3,8 +3,13 @@ import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:cwtch/main.dart'; import 'package:cwtch/main.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:win_toast/win_toast.dart'; import 'package:win_toast/win_toast.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:flutter_local_notifications_linux/flutter_local_notifications_linux.dart';
import 'package:flutter_local_notifications_linux/src/model/hint.dart';
import 'package:flutter_local_notifications_linux/src/model/icon.dart';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;

View File

@ -1,6 +1,8 @@
import 'dart:collection'; import 'dart:collection';
import 'dart:ui';
import 'dart:core'; import 'dart:core';
import 'package:cwtch/themes/cwtch.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:package_info_plus/package_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart';
@ -40,7 +42,7 @@ enum NotificationContent {
class Settings extends ChangeNotifier { class Settings extends ChangeNotifier {
Locale locale; Locale locale;
late PackageInfo packageInfo; late PackageInfo packageInfo;
bool _themeImages = false; OpaqueThemeType theme;
// explicitly set experiments to false until told otherwise... // explicitly set experiments to false until told otherwise...
bool experimentsEnabled = false; bool experimentsEnabled = false;
@ -67,8 +69,6 @@ class Settings extends ChangeNotifier {
bool _useSemanticDebugger = false; bool _useSemanticDebugger = false;
double _fontScaling = 1.0; double _fontScaling = 1.0;
ThemeLoader themeloader = ThemeLoader();
String get torCacheDir => _torCacheDir; String get torCacheDir => _torCacheDir;
// Whether to show the profiling interface, not saved // Whether to show the profiling interface, not saved
@ -87,19 +87,8 @@ class Settings extends ChangeNotifier {
bool get useSemanticDebugger => _useSemanticDebugger; bool get useSemanticDebugger => _useSemanticDebugger;
String? _themeId;
String? get themeId => _themeId;
String? _mode;
OpaqueThemeType get theme => themeloader.getTheme(_themeId, _mode);
void setTheme(String themeId, String mode) { void setTheme(String themeId, String mode) {
_themeId = themeId; theme = getTheme(themeId, mode);
_mode = mode;
notifyListeners();
}
bool get themeImages => _themeImages;
set themeImages(bool newVal) {
_themeImages = newVal;
notifyListeners(); notifyListeners();
} }
@ -138,7 +127,6 @@ class Settings extends ChangeNotifier {
handleUpdate(dynamic settings) { handleUpdate(dynamic settings) {
// Set Theme and notify listeners // Set Theme and notify listeners
this.setTheme(settings["Theme"], settings["ThemeMode"] ?? mode_dark); this.setTheme(settings["Theme"], settings["ThemeMode"] ?? mode_dark);
_themeImages = settings["ThemeImages"] ?? false;
// Set Locale and notify listeners // Set Locale and notify listeners
switchLocaleByCode(settings["Locale"]); switchLocaleByCode(settings["Locale"]);
@ -408,12 +396,9 @@ class Settings extends ChangeNotifier {
// checks experiment settings and file extension for image previews // checks experiment settings and file extension for image previews
// (ignores file size; if the user manually accepts the file, assume it's okay to preview) // (ignores file size; if the user manually accepts the file, assume it's okay to preview)
bool shouldPreview(String path) { bool shouldPreview(String path) {
return isExperimentEnabled(ImagePreviewsExperiment) && isImage(path);
}
bool isImage(String path) {
var lpath = path.toLowerCase(); var lpath = path.toLowerCase();
return (lpath.endsWith(".jpg") || lpath.endsWith(".jpeg") || lpath.endsWith(".png") || lpath.endsWith(".gif") || lpath.endsWith(".webp") || lpath.endsWith(".bmp")); return isExperimentEnabled(ImagePreviewsExperiment) &&
(lpath.endsWith(".jpg") || lpath.endsWith(".jpeg") || lpath.endsWith(".png") || lpath.endsWith(".gif") || lpath.endsWith(".webp") || lpath.endsWith(".bmp"));
} }
String get downloadPath => _downloadPath; String get downloadPath => _downloadPath;
@ -468,7 +453,7 @@ class Settings extends ChangeNotifier {
} }
/// Construct a default settings object. /// Construct a default settings object.
Settings(this.locale); Settings(this.locale, this.theme);
String _blodeuweddPath = ""; String _blodeuweddPath = "";
String get blodeuweddPath => _blodeuweddPath; String get blodeuweddPath => _blodeuweddPath;
@ -482,9 +467,8 @@ class Settings extends ChangeNotifier {
dynamic asJson() { dynamic asJson() {
return { return {
"Locale": this.locale.toString(), "Locale": this.locale.toString(),
"Theme": _themeId, "Theme": theme.theme,
"ThemeMode": theme.mode, "ThemeMode": theme.mode,
"ThemeImages": _themeImages,
"PreviousPid": -1, "PreviousPid": -1,
"BlockUnknownConnections": blockUnknownConnections, "BlockUnknownConnections": blockUnknownConnections,
"NotificationPolicy": _notificationPolicy.toString(), "NotificationPolicy": _notificationPolicy.toString(),

Some files were not shown because too many files have changed in this diff Show More